|
@@ -24,7 +24,9 @@ |
|
|
EarwigBot's Wiki Toolset: Misc Functions |
|
|
EarwigBot's Wiki Toolset: Misc Functions |
|
|
|
|
|
|
|
|
This module, a component of the wiki package, contains miscellaneous functions |
|
|
This module, a component of the wiki package, contains miscellaneous functions |
|
|
that are not methods of any class, like get_site(). |
|
|
|
|
|
|
|
|
that are not methods of any class. Currently, it contains get_site(), |
|
|
|
|
|
add_site(), and remove_site(). These functions act as bridges between the bot's |
|
|
|
|
|
config files and Site objects. |
|
|
|
|
|
|
|
|
There's no need to import this module explicitly. All functions here are |
|
|
There's no need to import this module explicitly. All functions here are |
|
|
automatically available from earwigbot.wiki. |
|
|
automatically available from earwigbot.wiki. |
|
@@ -36,21 +38,25 @@ from getpass import getpass |
|
|
from os import chmod, path |
|
|
from os import chmod, path |
|
|
import platform |
|
|
import platform |
|
|
import stat |
|
|
import stat |
|
|
|
|
|
import sqlite3 as sqlite |
|
|
|
|
|
|
|
|
import earwigbot |
|
|
|
|
|
|
|
|
from earwigbot import __version__ |
|
|
from earwigbot.config import config |
|
|
from earwigbot.config import config |
|
|
from earwigbot.wiki.exceptions import SiteNotFoundError |
|
|
from earwigbot.wiki.exceptions import SiteNotFoundError |
|
|
from earwigbot.wiki.site import Site |
|
|
from earwigbot.wiki.site import Site |
|
|
|
|
|
|
|
|
__all__ = ["get_site", "add_site", "del_site"] |
|
|
|
|
|
|
|
|
__all__ = ["get_site", "add_site", "remove_site"] |
|
|
|
|
|
|
|
|
_cookiejar = None |
|
|
_cookiejar = None |
|
|
|
|
|
_sitesdb = "sites.db" |
|
|
|
|
|
|
|
|
def _load_config(): |
|
|
def _load_config(): |
|
|
"""Called by a config-requiring function, such as get_site(), when config |
|
|
|
|
|
|
|
|
"""Load the bot's config. |
|
|
|
|
|
|
|
|
|
|
|
Called by a config-requiring function, such as get_site(), when config |
|
|
has not been loaded. This will usually happen only if we're running code |
|
|
has not been loaded. This will usually happen only if we're running code |
|
|
directly from Python's interpreter and not the bot itself, because |
|
|
directly from Python's interpreter and not the bot itself, because |
|
|
earwigbot.py or core/main.py will already call these functions. |
|
|
|
|
|
|
|
|
bot.py and earwigbot.runner will already call these functions. |
|
|
""" |
|
|
""" |
|
|
is_encrypted = config.load() |
|
|
is_encrypted = config.load() |
|
|
if is_encrypted: # Passwords in the config file are encrypted |
|
|
if is_encrypted: # Passwords in the config file are encrypted |
|
@@ -59,21 +65,20 @@ def _load_config(): |
|
|
config.decrypt(config.wiki, "password") |
|
|
config.decrypt(config.wiki, "password") |
|
|
|
|
|
|
|
|
def _get_cookiejar(): |
|
|
def _get_cookiejar(): |
|
|
"""Returns a LWPCookieJar object loaded from our .cookies file. The same |
|
|
|
|
|
one is returned every time. |
|
|
|
|
|
|
|
|
"""Return a LWPCookieJar object loaded from our .cookies file. |
|
|
|
|
|
|
|
|
The .cookies file is located in the project root, same directory as |
|
|
|
|
|
config.yml and bot.py. If it doesn't exist, we will create the file and set |
|
|
|
|
|
it to be readable and writeable only by us. If it exists but the |
|
|
|
|
|
information inside is bogus, we will ignore it. |
|
|
|
|
|
|
|
|
The same .cookies file is returned every time, located in the project root, |
|
|
|
|
|
same directory as config.yml and bot.py. If it doesn't exist, we will |
|
|
|
|
|
create the file and set it to be readable and writeable only by us. If it |
|
|
|
|
|
exists but the information inside is bogus, we will ignore it. |
|
|
|
|
|
|
|
|
This is normally called by _get_site_object_from_dict() (in turn called by |
|
|
|
|
|
|
|
|
This is normally called by _make_site_object() (in turn called by |
|
|
get_site()), and the cookiejar is passed to our Site's constructor, used |
|
|
get_site()), and the cookiejar is passed to our Site's constructor, used |
|
|
when it makes API queries. This way, we can easily preserve cookies between |
|
|
when it makes API queries. This way, we can easily preserve cookies between |
|
|
sites (e.g., for CentralAuth), making logins easier. |
|
|
sites (e.g., for CentralAuth), making logins easier. |
|
|
""" |
|
|
""" |
|
|
global _cookiejar |
|
|
global _cookiejar |
|
|
if _cookiejar is not None: |
|
|
|
|
|
|
|
|
if _cookiejar: |
|
|
return _cookiejar |
|
|
return _cookiejar |
|
|
|
|
|
|
|
|
cookie_file = path.join(config.root_dir, ".cookies") |
|
|
cookie_file = path.join(config.root_dir, ".cookies") |
|
@@ -94,17 +99,63 @@ def _get_cookiejar(): |
|
|
|
|
|
|
|
|
return _cookiejar |
|
|
return _cookiejar |
|
|
|
|
|
|
|
|
def _get_site_object_from_dict(name, d): |
|
|
|
|
|
"""Return a Site object based on the contents of a dict, probably acquired |
|
|
|
|
|
through our config file, and a separate name. |
|
|
|
|
|
|
|
|
def _create_sitesdb(): |
|
|
|
|
|
"""Initialize the sitesdb file with its three necessary tables.""" |
|
|
|
|
|
script = """ |
|
|
|
|
|
CREATE TABLE sites (site_name, site_project, site_lang, site_base_url, |
|
|
|
|
|
site_article_path, site_script_path); |
|
|
|
|
|
CREATE TABLE sql_data (sql_site, sql_data_key, sql_data_value); |
|
|
|
|
|
CREATE TABLE namespaces (ns_site, ns_id, ns_name, ns_is_primary_name); |
|
|
|
|
|
""" |
|
|
|
|
|
with sqlite.connect(_sitesdb) as conn: |
|
|
|
|
|
conn.executescript(script) |
|
|
|
|
|
|
|
|
|
|
|
def _load_site_from_sitesdb(name): |
|
|
|
|
|
"""Return all information stored in the sitesdb relating to site 'name'. |
|
|
|
|
|
|
|
|
|
|
|
The information will be returned as a tuple, containing the site's project, |
|
|
|
|
|
language, base URL, article path, script path, SQL connection data, and |
|
|
|
|
|
namespaces, in that order. If the site is not found in the database, |
|
|
|
|
|
SiteNotFoundError will be raised. An empty database will be created before |
|
|
|
|
|
the exception is raised if none exists. |
|
|
""" |
|
|
""" |
|
|
project = d.get("project") |
|
|
|
|
|
lang = d.get("lang") |
|
|
|
|
|
base_url = d.get("baseURL") |
|
|
|
|
|
article_path = d.get("articlePath") |
|
|
|
|
|
script_path = d.get("scriptPath") |
|
|
|
|
|
sql = d.get("sql", {}) |
|
|
|
|
|
namespaces = d.get("namespaces", {}) |
|
|
|
|
|
|
|
|
query1 = "SELECT * FROM sites WHERE site_name = ?" |
|
|
|
|
|
query2 = "SELECT sql_data_key, sql_data_value FROM sql_data WHERE sql_site = ?" |
|
|
|
|
|
query3 = "SELECT ns_id, ns_name, ns_is_primary_name FROM namespaces WHERE ns_site = ?" |
|
|
|
|
|
error = "Site '{0}' not found in the sitesdb.".format(name) |
|
|
|
|
|
with sqlite.connect(_sitesdb) as conn: |
|
|
|
|
|
try: |
|
|
|
|
|
site_data = conn.execute(query1, (name,)).fetchone() |
|
|
|
|
|
except sqllite.OperationalError: |
|
|
|
|
|
_create_sitesdb() |
|
|
|
|
|
raise SiteNotFoundError(error) |
|
|
|
|
|
if not site_data: |
|
|
|
|
|
raise SiteNotFoundError(error) |
|
|
|
|
|
sql_data = conn.execute(query2, (name,)).fetchall() |
|
|
|
|
|
ns_data = conn.execute(query3, (name,)).fetchall() |
|
|
|
|
|
|
|
|
|
|
|
project, lang, base_url, article_path, script_path = site_data |
|
|
|
|
|
sql = dict(sql_data) |
|
|
|
|
|
namespaces = {} |
|
|
|
|
|
for ns_id, ns_name, ns_is_primary_name in ns_data: |
|
|
|
|
|
try: |
|
|
|
|
|
if ns_is_primary_name: # "Primary" name goes first in list |
|
|
|
|
|
namespaces[ns_id].insert(0, ns_name) |
|
|
|
|
|
else: # Ordering of the aliases doesn't matter |
|
|
|
|
|
namespaces[ns_id].append(ns_name) |
|
|
|
|
|
except KeyError: |
|
|
|
|
|
namespaces[ns_id] = [ns_name] |
|
|
|
|
|
|
|
|
|
|
|
return project, lang, base_url, article_path, script_path, sql, namespaces |
|
|
|
|
|
|
|
|
|
|
|
def _make_site_object(name): |
|
|
|
|
|
"""Return a Site object associated with the site 'name' in our sitesdb. |
|
|
|
|
|
|
|
|
|
|
|
This calls _load_site_from_sitesdb(), so SiteNotFoundError will be raised |
|
|
|
|
|
if the site is not in our sitesdb. |
|
|
|
|
|
""" |
|
|
|
|
|
(project, lang, base_url, article_path, script_path, sql, |
|
|
|
|
|
namespaces) = _load_site_from_sitesdb(name) |
|
|
login = (config.wiki.get("username"), config.wiki.get("password")) |
|
|
login = (config.wiki.get("username"), config.wiki.get("password")) |
|
|
cookiejar = _get_cookiejar() |
|
|
cookiejar = _get_cookiejar() |
|
|
user_agent = config.wiki.get("userAgent") |
|
|
user_agent = config.wiki.get("userAgent") |
|
@@ -113,7 +164,7 @@ def _get_site_object_from_dict(name, d): |
|
|
search_config = config.wiki.get("search") |
|
|
search_config = config.wiki.get("search") |
|
|
|
|
|
|
|
|
if user_agent: |
|
|
if user_agent: |
|
|
user_agent = user_agent.replace("$1", earwigbot.__version__) |
|
|
|
|
|
|
|
|
user_agent = user_agent.replace("$1", __version__) |
|
|
user_agent = user_agent.replace("$2", platform.python_version()) |
|
|
user_agent = user_agent.replace("$2", platform.python_version()) |
|
|
|
|
|
|
|
|
return Site(name=name, project=project, lang=lang, base_url=base_url, |
|
|
return Site(name=name, project=project, lang=lang, base_url=base_url, |
|
@@ -122,90 +173,196 @@ def _get_site_object_from_dict(name, d): |
|
|
user_agent=user_agent, assert_edit=assert_edit, maxlag=maxlag, |
|
|
user_agent=user_agent, assert_edit=assert_edit, maxlag=maxlag, |
|
|
search_config=search_config) |
|
|
search_config=search_config) |
|
|
|
|
|
|
|
|
|
|
|
def _get_site_name_from_sitesdb(project, lang): |
|
|
|
|
|
"""Return the name of the first site with the specified project and lang. |
|
|
|
|
|
|
|
|
|
|
|
If the site is not found, return None. An empty sitesdb will be created if |
|
|
|
|
|
none exists. |
|
|
|
|
|
""" |
|
|
|
|
|
query = "SELECT site_name FROM site WHERE site_project = ? and site_lang = ?" |
|
|
|
|
|
with sqlite.connect(_sitesdb) as conn: |
|
|
|
|
|
try: |
|
|
|
|
|
return conn.execute(query, (project, lang)).fetchone() |
|
|
|
|
|
except sqllite.OperationalError: |
|
|
|
|
|
_create_sitesdb() |
|
|
|
|
|
|
|
|
|
|
|
def _add_site_to_sitesdb(site): |
|
|
|
|
|
"""Extract relevant info from a Site object and add it to the sitesdb. |
|
|
|
|
|
|
|
|
|
|
|
Works like a reverse _load_site_from_sitesdb(); the site's project, |
|
|
|
|
|
language, base URL, article path, script path, SQL connection data, and |
|
|
|
|
|
namespaces are extracted from the site and inserted into the sites |
|
|
|
|
|
database. If the sitesdb doesn't exist, we'll create it first. |
|
|
|
|
|
""" |
|
|
|
|
|
name = site.name |
|
|
|
|
|
sites_data = (name, site.project, site.lang, site._base_url, |
|
|
|
|
|
site._article_path, site._script_path) |
|
|
|
|
|
sql_data = [(name, key, val) for key, val in site._sql_data.iteritems()] |
|
|
|
|
|
ns_data = [] |
|
|
|
|
|
for ns_id, ns_names in site._namespaces.iteritems(): |
|
|
|
|
|
ns_data.append((name, ns_id, ns_names.pop(0), True)) |
|
|
|
|
|
for ns_name in ns_names: |
|
|
|
|
|
ns_data.append((name, ns_id, ns_name, False)) |
|
|
|
|
|
|
|
|
|
|
|
with sqlite.connect(_sitesdb) as conn: |
|
|
|
|
|
check_exists = "SELECT 1 FROM sites WHERE site_name = ?" |
|
|
|
|
|
try: |
|
|
|
|
|
exists = conn.execute(check_exists, (name,)).fetchone() |
|
|
|
|
|
except sqlite.OperationalError: |
|
|
|
|
|
_create_sitesdb() |
|
|
|
|
|
else: |
|
|
|
|
|
if exists: |
|
|
|
|
|
conn.execute("DELETE FROM sites WHERE site_name = ?", (name,)) |
|
|
|
|
|
conn.execute("DELETE FROM sql_data WHERE sql_site = ?", (name,)) |
|
|
|
|
|
conn.execute("DELETE FROM namespaces WHERE ns_site = ?", (name,)) |
|
|
|
|
|
conn.execute("INSERT INTO sites VALUES (?, ?, ?, ?, ?, ?)", sites_data) |
|
|
|
|
|
conn.executemany("INSERT INTO sql_data VALUES (?, ?, ?)", sql_data) |
|
|
|
|
|
conn.executemany("INSERT INTO namespaces VALUES (?, ?, ?, ?)", ns_data) |
|
|
|
|
|
|
|
|
|
|
|
def _remove_site_from_sitesdb(name): |
|
|
|
|
|
"""Remove a site by name from the sitesdb.""" |
|
|
|
|
|
with sqlite.connect(_sitesdb) as conn: |
|
|
|
|
|
cursor = conn.execute("DELETE FROM sites WHERE site_name = ?", (name,)) |
|
|
|
|
|
if cursor.rowcount == 0: |
|
|
|
|
|
return False |
|
|
|
|
|
else: |
|
|
|
|
|
conn.execute("DELETE FROM sql_data WHERE sql_site = ?", (name,)) |
|
|
|
|
|
conn.execute("DELETE FROM namespaces WHERE ns_site = ?", (name,)) |
|
|
|
|
|
return True |
|
|
|
|
|
|
|
|
def get_site(name=None, project=None, lang=None): |
|
|
def get_site(name=None, project=None, lang=None): |
|
|
"""Returns a Site instance based on information from our config file. |
|
|
|
|
|
|
|
|
"""Return a Site instance based on information from the sitesdb. |
|
|
|
|
|
|
|
|
With no arguments, returns the default site as specified by our config |
|
|
|
|
|
file. This is default = config.wiki["defaultSite"]; |
|
|
|
|
|
config.wiki["sites"][default]. |
|
|
|
|
|
|
|
|
With no arguments, return the default site as specified by our config |
|
|
|
|
|
file. This is config.wiki["defaultSite"]. |
|
|
|
|
|
|
|
|
With `name` specified, returns the site specified by |
|
|
|
|
|
config.wiki["sites"][name]. |
|
|
|
|
|
|
|
|
With 'name' specified, return the site with that name. This is equivalent |
|
|
|
|
|
to the site's 'wikiid' in the API, like 'enwiki'. |
|
|
|
|
|
|
|
|
With `project` and `lang` specified, returns the site specified by the |
|
|
|
|
|
member of config.wiki["sites"], `s`, for which s["project"] == project and |
|
|
|
|
|
s["lang"] == lang. |
|
|
|
|
|
|
|
|
With 'project' and 'lang' specified, return the site whose project and |
|
|
|
|
|
language match these values. If there are multiple sites with the same |
|
|
|
|
|
values (unlikely), this is not a reliable way of loading a site. Call the |
|
|
|
|
|
function with an explicit 'name' in that case. |
|
|
|
|
|
|
|
|
We will attempt to login to the site automatically |
|
|
|
|
|
using config.wiki["username"] and config.wiki["password"] if both are |
|
|
|
|
|
defined. |
|
|
|
|
|
|
|
|
We will attempt to login to the site automatically using |
|
|
|
|
|
config.wiki["username"] and config.wiki["password"] if both are defined. |
|
|
|
|
|
|
|
|
Specifying a project without a lang or a lang without a project will raise |
|
|
Specifying a project without a lang or a lang without a project will raise |
|
|
TypeError. If all three args are specified, `name` will be first tried, |
|
|
|
|
|
then `project` and `lang`. If, with any number of args, a site cannot be |
|
|
|
|
|
found in the config, SiteNotFoundError is raised. |
|
|
|
|
|
|
|
|
TypeError. If all three args are specified, 'name' will be first tried, |
|
|
|
|
|
then 'project' and 'lang' if 'name' doesn't work. If a site cannot be found |
|
|
|
|
|
in the sitesdb, SiteNotFoundError will be raised. An empty sitesdb will be |
|
|
|
|
|
created if none is found. |
|
|
""" |
|
|
""" |
|
|
# Check if config has been loaded, and load it if it hasn't: |
|
|
|
|
|
if not config.is_loaded(): |
|
|
if not config.is_loaded(): |
|
|
_load_config() |
|
|
_load_config() |
|
|
|
|
|
|
|
|
# Someone specified a project without a lang (or a lang without a project)! |
|
|
# Someone specified a project without a lang (or a lang without a project)! |
|
|
if (project is None and lang is not None) or (project is not None and |
|
|
|
|
|
lang is None): |
|
|
|
|
|
|
|
|
if (project and not lang) or (not project and lang): |
|
|
e = "Keyword arguments 'lang' and 'project' must be specified together." |
|
|
e = "Keyword arguments 'lang' and 'project' must be specified together." |
|
|
raise TypeError(e) |
|
|
raise TypeError(e) |
|
|
|
|
|
|
|
|
# No args given, so return our default site (project is None implies lang |
|
|
|
|
|
# is None, so we don't need to add that in): |
|
|
|
|
|
if name is None and project is None: |
|
|
|
|
|
|
|
|
# No args given, so return our default site: |
|
|
|
|
|
if not name and not project and not lang: |
|
|
try: |
|
|
try: |
|
|
default = config.wiki["defaultSite"] |
|
|
default = config.wiki["defaultSite"] |
|
|
except KeyError: |
|
|
except KeyError: |
|
|
e = "Default site is not specified in config." |
|
|
e = "Default site is not specified in config." |
|
|
raise SiteNotFoundError(e) |
|
|
raise SiteNotFoundError(e) |
|
|
try: |
|
|
|
|
|
site = config.wiki["sites"][default] |
|
|
|
|
|
except KeyError: |
|
|
|
|
|
e = "Default site specified by config is not in the config's sites list." |
|
|
|
|
|
raise SiteNotFoundError(e) |
|
|
|
|
|
return _get_site_object_from_dict(default, site) |
|
|
|
|
|
|
|
|
return _make_site_object(default) |
|
|
|
|
|
|
|
|
# Name arg given, but don't look at others unless `name` isn't found: |
|
|
# Name arg given, but don't look at others unless `name` isn't found: |
|
|
if name is not None: |
|
|
|
|
|
|
|
|
if name: |
|
|
try: |
|
|
try: |
|
|
site = config.wiki["sites"][name] |
|
|
|
|
|
except KeyError: |
|
|
|
|
|
if project is None: # Implies lang is None, so only name was given |
|
|
|
|
|
e = "Site '{0}' not found in config.".format(name) |
|
|
|
|
|
raise SiteNotFoundError(e) |
|
|
|
|
|
for sitename, site in config.wiki["sites"].items(): |
|
|
|
|
|
if site["project"] == project and site["lang"] == lang: |
|
|
|
|
|
return _get_site_object_from_dict(sitename, site) |
|
|
|
|
|
e = "Neither site '{0}' nor site '{1}:{2}' found in config." |
|
|
|
|
|
e.format(name, project, lang) |
|
|
|
|
|
raise SiteNotFoundError(e) |
|
|
|
|
|
else: |
|
|
|
|
|
return _get_site_object_from_dict(name, site) |
|
|
|
|
|
|
|
|
return _make_site_object(name) |
|
|
|
|
|
except SiteNotFoundError: |
|
|
|
|
|
if project and lang: |
|
|
|
|
|
name = _get_site_name_from_sitesdb(project, lang) |
|
|
|
|
|
if name: |
|
|
|
|
|
return _make_site_object(name) |
|
|
|
|
|
raise |
|
|
|
|
|
|
|
|
# If we end up here, then project and lang are both not None: |
|
|
|
|
|
for sitename, site in config.wiki["sites"].items(): |
|
|
|
|
|
if site["project"] == project and site["lang"] == lang: |
|
|
|
|
|
return _get_site_object_from_dict(sitename, site) |
|
|
|
|
|
e = "Site '{0}:{1}' not found in config.".format(project, lang) |
|
|
|
|
|
|
|
|
# If we end up here, then project and lang are the only args given: |
|
|
|
|
|
name = _get_site_name_from_sitesdb(project, lang) |
|
|
|
|
|
if name: |
|
|
|
|
|
return _make_site_object(name) |
|
|
|
|
|
e = "Site '{0}:{1}' not found in the sitesdb.".format(project, lang) |
|
|
raise SiteNotFoundError(e) |
|
|
raise SiteNotFoundError(e) |
|
|
|
|
|
|
|
|
def add_site(): |
|
|
|
|
|
"""STUB: config editing is required first. |
|
|
|
|
|
|
|
|
def add_site(project=None, lang=None, base_url=None, script_path="/w", |
|
|
|
|
|
sql=None): |
|
|
|
|
|
"""Add a site to the sitesdb so it can be retrieved with get_site() later. |
|
|
|
|
|
|
|
|
|
|
|
If only a project and a lang are given, we'll guess the base_url as |
|
|
|
|
|
"http://{lang}.{project}.org". If this is wrong, provide the correct |
|
|
|
|
|
base_url as an argument (in which case project and lang are ignored). Most |
|
|
|
|
|
wikis use "/w" as the script path (meaning the API is located at |
|
|
|
|
|
"{base_url}{script_path}/api.php" -> "http://{lang}.{project}.org/w/api.php"), |
|
|
|
|
|
so this is the default. If your wiki is different, provide the script_path |
|
|
|
|
|
as an argument. The only other argument to Site() that we can't get from |
|
|
|
|
|
config files or by querying the wiki itself is SQL connection info, so |
|
|
|
|
|
provide a dict of kwargs as `sql` and Site will be pass it to |
|
|
|
|
|
oursql.connect(**sql), allowing you to make queries with site.sql_query(). |
|
|
|
|
|
|
|
|
|
|
|
Returns True if the site was added successfully or False if the site is |
|
|
|
|
|
already in our sitesdb (this can be done purposefully to update old site |
|
|
|
|
|
info). Raises SiteNotFoundError if not enough information has been provided |
|
|
|
|
|
to identify the site (e.g. a project but not a lang). |
|
|
|
|
|
""" |
|
|
|
|
|
if not config.is_loaded(): |
|
|
|
|
|
_load_config() |
|
|
|
|
|
|
|
|
|
|
|
if not base_url: |
|
|
|
|
|
if not project or not lang: |
|
|
|
|
|
e = "Without a base_url, both a project and a lang must be given." |
|
|
|
|
|
raise SiteNotFoundError(e) |
|
|
|
|
|
base_url = "http://{0}.{1}.org".format(lang, project) |
|
|
|
|
|
|
|
|
|
|
|
login = (config.wiki.get("username"), config.wiki.get("password")) |
|
|
|
|
|
cookiejar = _get_cookiejar() |
|
|
|
|
|
user_agent = config.wiki.get("userAgent") |
|
|
|
|
|
assert_edit = config.wiki.get("assert") |
|
|
|
|
|
maxlag = config.wiki.get("maxlag") |
|
|
|
|
|
search_config = config.wiki.get("search") |
|
|
|
|
|
|
|
|
|
|
|
# Create a temp Site object to log in and load the other attributes: |
|
|
|
|
|
site = Site(base_url=base_url, script_path=script_path, sql=sql, |
|
|
|
|
|
login=login, cookiejar=cookiejar, user_agent=user_agent, |
|
|
|
|
|
assert_edit=assert_edit, maxlag=maxlag, |
|
|
|
|
|
search_config=search_config) |
|
|
|
|
|
|
|
|
Returns True if the site was added successfully or False if the site was |
|
|
|
|
|
already in our config. Raises ConfigError if saving the updated file failed |
|
|
|
|
|
for some reason.""" |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
_add_site_to_sitesdb(site) |
|
|
|
|
|
return site |
|
|
|
|
|
|
|
|
def del_site(name): |
|
|
|
|
|
"""STUB: config editing is required first. |
|
|
|
|
|
|
|
|
def remove_site(name=None, project=None, lang=None): |
|
|
|
|
|
"""Remove a site from the sitesdb. |
|
|
|
|
|
|
|
|
Returns True if the site was removed successfully or False if the site was |
|
|
Returns True if the site was removed successfully or False if the site was |
|
|
not in our config originally. Raises ConfigError if saving the updated file |
|
|
|
|
|
failed for some reason.""" |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
not in our sitesdb originally. If all three args (name, project, and lang) |
|
|
|
|
|
are given, we'll first try 'name' and then try the latter two if 'name' |
|
|
|
|
|
wasn't found in the database. Raises TypeError if a project was given but |
|
|
|
|
|
not a language, or vice versa. Will create an empty sitesdb if none was |
|
|
|
|
|
found. |
|
|
|
|
|
""" |
|
|
|
|
|
if not config.is_loaded(): |
|
|
|
|
|
_load_config() |
|
|
|
|
|
|
|
|
|
|
|
# Someone specified a project without a lang (or a lang without a project)! |
|
|
|
|
|
if (project and not lang) or (not project and lang): |
|
|
|
|
|
e = "Keyword arguments 'lang' and 'project' must be specified together." |
|
|
|
|
|
raise TypeError(e) |
|
|
|
|
|
|
|
|
|
|
|
if name: |
|
|
|
|
|
was_removed = _remove_site_from_sitesdb(name) |
|
|
|
|
|
if not was_removed: |
|
|
|
|
|
if project and lang: |
|
|
|
|
|
name = _get_site_name_from_sitesdb(project, lang) |
|
|
|
|
|
if name: |
|
|
|
|
|
return _remove_site_from_sitesdb(name) |
|
|
|
|
|
return was_removed |
|
|
|
|
|
|
|
|
|
|
|
if project and lang: |
|
|
|
|
|
name = _get_site_name_from_sitesdb(project, lang) |
|
|
|
|
|
if name: |
|
|
|
|
|
return _remove_site_from_sitesdb(name) |
|
|
|
|
|
|
|
|
|
|
|
return False |