ソースを参照

Fix all references to earwigbot.config.config; update SitesDBManager

tags/v0.1^2
Ben Kurtovic 12年前
コミット
8a7eb798a3
14個のファイルの変更48行の追加76行の削除
  1. +11
    -7
      earwigbot/bot.py
  2. +3
    -2
      earwigbot/commands/__init__.py
  3. +1
    -2
      earwigbot/commands/afc_status.py
  4. +1
    -2
      earwigbot/commands/chanops.py
  5. +1
    -2
      earwigbot/commands/ctcp.py
  6. +1
    -2
      earwigbot/commands/git.py
  7. +1
    -2
      earwigbot/commands/restart.py
  8. +2
    -3
      earwigbot/commands/threads.py
  9. +1
    -0
      earwigbot/tasks/__init__.py
  10. +1
    -2
      earwigbot/tasks/afc_copyvios.py
  11. +1
    -2
      earwigbot/tasks/afc_history.py
  12. +1
    -2
      earwigbot/tasks/afc_statistics.py
  13. +6
    -2
      earwigbot/wiki/__init__.py
  14. +17
    -46
      earwigbot/wiki/sitesdb.py

+ 11
- 7
earwigbot/bot.py ファイルの表示

@@ -27,6 +27,7 @@ from earwigbot.commands import CommandManager
from earwigbot.config import BotConfig
from earwigbot.irc import Frontend, Watcher
from earwigbot.tasks import TaskManager
from earwigbot.wiki import SitesDBManager

__all__ = ["Bot"]

@@ -51,6 +52,7 @@ class Bot(object):
self.logger = logging.getLogger("earwigbot")
self.commands = CommandManager(self)
self.tasks = TaskManager(self)
self.wiki = SitesDBManager(self.config)
self.frontend = None
self.watcher = None

@@ -100,12 +102,13 @@ class Bot(object):
sleep(5)

def run(self):
self.config.load()
self.config.decrypt(config.wiki, "password")
self.config.decrypt(config.wiki, "search", "credentials", "key")
self.config.decrypt(config.wiki, "search", "credentials", "secret")
self.config.decrypt(config.irc, "frontend", "nickservPassword")
self.config.decrypt(config.irc, "watcher", "nickservPassword")
config = self.config
config.load()
config.decrypt(config.wiki, "password")
config.decrypt(config.wiki, "search", "credentials", "key")
config.decrypt(config.wiki, "search", "credentials", "secret")
config.decrypt(config.irc, "frontend", "nickservPassword")
config.decrypt(config.irc, "watcher", "nickservPassword")
self.commands.load()
self.tasks.load()
self._start_irc_components()
@@ -121,6 +124,7 @@ class Bot(object):
self._start_irc_components()

def stop(self):
self._stop_irc_components()
with self.component_lock:
self._stop_irc_components()
self._keep_looping = False
sleep(3) # Give a few seconds to finish closing IRC connections

+ 3
- 2
earwigbot/commands/__init__.py ファイルの表示

@@ -58,9 +58,10 @@ class BaseCommand(object):
super(Command, self).__init__() first.
"""
self.bot = bot
self.config = bot.config
self.logger = bot.commands.getLogger(self.name)

def _execute(self, data):
def _wrap_process(self, data):
"""Make a quick connection alias and then process() the message."""
self.connection = self.bot.frontend
self.process(data)
@@ -158,7 +159,7 @@ class CommandManager(object):
if hook in command.hooks:
if command.check(data):
try:
command._execute(data)
command._wrap_process(data)
except Exception:
e = "Error executing command '{0}':"
self.logger.exception(e.format(data.command))


+ 1
- 2
earwigbot/commands/afc_status.py ファイルの表示

@@ -24,7 +24,6 @@ import re

from earwigbot import wiki
from earwigbot.commands import BaseCommand
from earwigbot.config import config

class Command(BaseCommand):
"""Get the number of pending AfC submissions, open redirect requests, and
@@ -39,7 +38,7 @@ class Command(BaseCommand):

try:
if data.line[1] == "JOIN" and data.chan == "#wikipedia-en-afc":
if data.nick != config.irc["frontend"]["nick"]:
if data.nick != self.config.irc["frontend"]["nick"]:
return True
except IndexError:
pass


+ 1
- 2
earwigbot/commands/chanops.py ファイルの表示

@@ -21,7 +21,6 @@
# SOFTWARE.

from earwigbot.commands import BaseCommand
from earwigbot.config import config

class Command(BaseCommand):
"""Voice, devoice, op, or deop users in the channel."""
@@ -39,7 +38,7 @@ class Command(BaseCommand):
self.connection.reply(data, msg)
return

if data.host not in config.irc["permissions"]["admins"]:
if data.host not in self.config.irc["permissions"]["admins"]:
msg = "you must be a bot admin to use this command."
self.connection.reply(data, msg)
return


+ 1
- 2
earwigbot/commands/ctcp.py ファイルの表示

@@ -25,7 +25,6 @@ import time

from earwigbot import __version__
from earwigbot.commands import BaseCommand
from earwigbot.config import config

class Command(BaseCommand):
"""Not an actual command, this module is used to respond to the CTCP
@@ -63,7 +62,7 @@ class Command(BaseCommand):

elif command == "VERSION":
default = "EarwigBot - $1 - Python/$2 https://github.com/earwig/earwigbot"
vers = config.irc.get("version", default)
vers = self.config.irc.get("version", default)
vers = vers.replace("$1", __version__)
vers = vers.replace("$2", platform.python_version())
self.connection.notice(target, "\x01VERSION {0}\x01".format(vers))

+ 1
- 2
earwigbot/commands/git.py ファイルの表示

@@ -25,7 +25,6 @@ import subprocess
import re

from earwigbot.commands import BaseCommand
from earwigbot.config import config

class Command(BaseCommand):
"""Commands to interface with the bot's git repository; use '!git' for a
@@ -34,7 +33,7 @@ class Command(BaseCommand):

def process(self, data):
self.data = data
if data.host not in config.irc["permissions"]["owners"]:
if data.host not in self.config.irc["permissions"]["owners"]:
msg = "you must be a bot owner to use this command."
self.connection.reply(data, msg)
return


+ 1
- 2
earwigbot/commands/restart.py ファイルの表示

@@ -21,7 +21,6 @@
# SOFTWARE.

from earwigbot.commands import BaseCommand
from earwigbot.config import config

class Command(BaseCommand):
"""Restart the bot. Only the owner can do this."""
@@ -32,7 +31,7 @@ class Command(BaseCommand):
return data.is_command and data.command in commands

def process(self, data):
if data.host not in config.irc["permissions"]["owners"]:
if data.host not in self.config.irc["permissions"]["owners"]:
msg = "you must be a bot owner to use this command."
self.connection.reply(data, msg)
return


+ 2
- 3
earwigbot/commands/threads.py ファイルの表示

@@ -24,7 +24,6 @@ import threading
import re

from earwigbot.commands import BaseCommand
from earwigbot.config import config
from earwigbot.irc import KwargParseException
from earwigbot.tasks import task_manager

@@ -40,7 +39,7 @@ class Command(BaseCommand):

def process(self, data):
self.data = data
if data.host not in config.irc["permissions"]["owners"]:
if data.host not in self.config.irc["permissions"]["owners"]:
msg = "you must be a bot owner to use this command."
self.connection.reply(data, msg)
return
@@ -80,7 +79,7 @@ class Command(BaseCommand):
if tname == "MainThread":
t = "\x0302MainThread\x0301 (id {1})"
normal_threads.append(t.format(thread.ident))
elif tname in config.components:
elif tname in self.config.components:
t = "\x0302{0}\x0301 (id {1})"
normal_threads.append(t.format(tname, thread.ident))
elif tname.startswith("reminder"):


+ 1
- 0
earwigbot/tasks/__init__.py ファイルの表示

@@ -50,6 +50,7 @@ class BaseTask(object):
(or if you do, remember super(Task, self).__init()) - use setup().
"""
self.bot = bot
self.config = bot.config
self.logger = bot.tasks.logger.getLogger(self.name)
self.setup()



+ 1
- 2
earwigbot/tasks/afc_copyvios.py ファイルの表示

@@ -27,7 +27,6 @@ from threading import Lock
import oursql

from earwigbot import wiki
from earwigbot.config import config
from earwigbot.tasks import BaseTask

class Task(BaseTask):
@@ -37,7 +36,7 @@ class Task(BaseTask):
number = 1

def setup(self):
cfg = config.tasks.get(self.name, {})
cfg = self.config.tasks.get(self.name, {})
self.template = cfg.get("template", "AfC suspected copyvio")
self.ignore_list = cfg.get("ignoreList", [])
self.min_confidence = cfg.get("minConfidence", 0.5)


+ 1
- 2
earwigbot/tasks/afc_history.py ファイルの表示

@@ -32,7 +32,6 @@ from numpy import arange
import oursql

from earwigbot import wiki
from earwigbot.config import config
from earwigbot.tasks import BaseTask

# Valid submission statuses:
@@ -58,7 +57,7 @@ class Task(BaseTask):
name = "afc_history"

def setup(self):
cfg = config.tasks.get(self.name, {})
cfg = self.config.tasks.get(self.name, {})
self.num_days = cfg.get("days", 90)
self.categories = cfg.get("categories", {})



+ 1
- 2
earwigbot/tasks/afc_statistics.py ファイルの表示

@@ -30,7 +30,6 @@ from time import sleep
import oursql

from earwigbot import wiki
from earwigbot.config import config
from earwigbot.tasks import BaseTask

# Chart status number constants:
@@ -54,7 +53,7 @@ class Task(BaseTask):
number = 2

def setup(self):
self.cfg = cfg = config.tasks.get(self.name, {})
self.cfg = cfg = self.config.tasks.get(self.name, {})

# Set some wiki-related attributes:
self.pagename = cfg.get("page", "Template:AFC statistics")


+ 6
- 2
earwigbot/wiki/__init__.py ファイルの表示

@@ -27,7 +27,11 @@ This is a collection of classes and functions to read from and write to
Wikipedia and other wiki sites. No connection whatsoever to python-wikitools
written by Mr.Z-man, other than a similar purpose. We share no code.

Import the toolset with `from earwigbot import wiki`.
Import the toolset directly with `from earwigbot import wiki`. If using the
built-in integration with the rest of the bot, that's usually not necessary:
Bot() objects contain a `wiki` attribute containing a SitesDBManager object
tied to the sites.db file located in the same directory as config.yml. That
object has the principal methods get_site, add_site, and remove_site.
"""

import logging as _log
@@ -40,5 +44,5 @@ from earwigbot.wiki.exceptions import *
from earwigbot.wiki.category import Category
from earwigbot.wiki.page import Page
from earwigbot.wiki.site import Site
from earwigbot.wiki.sitesdb import get_site, add_site, remove_site
from earwigbot.wiki.sitesdb import SitesDBManager
from earwigbot.wiki.user import User

+ 17
- 46
earwigbot/wiki/sitesdb.py ファイルの表示

@@ -29,11 +29,10 @@ import stat
import sqlite3 as sqlite

from earwigbot import __version__
from earwigbot.config import config
from earwigbot.wiki.exceptions import SiteNotFoundError
from earwigbot.wiki.site import Site

__all__ = ["SitesDBManager", "get_site", "add_site", "remove_site"]
__all__ = ["SitesDBManager"]

class SitesDBManager(object):
"""
@@ -47,31 +46,19 @@ class SitesDBManager(object):
remove_site -- removes a site from the database, given its name

There's usually no need to use this class directly. All public methods
here are available as earwigbot.wiki.get_site(), earwigbot.wiki.add_site(),
and earwigbot.wiki.remove_site(), which use a sites.db file located in the
same directory as our config.yml file. Lower-level access can be achieved
here are available as bot.wiki.get_site(), bot.wiki.add_site(), and
bot.wiki.remove_site(), which use a sites.db file located in the same
directory as our config.yml file. Lower-level access can be achieved
by importing the manager class
(`from earwigbot.wiki.sitesdb import SitesDBManager`).
(`from earwigbot.wiki import SitesDBManager`).
"""

def __init__(self, db_file):
"""Set up the manager with an attribute for the sitesdb filename."""
def __init__(self, config):
"""Set up the manager with an attribute for the BotConfig object."""
self.config = config
self._sitesdb = path.join(config.root_dir, "sitesdb")
self._cookie_file = path.join(config.root_dir, ".cookies")
self._cookiejar = None
self._sitesdb = db_file

def _load_config(self):
"""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 directly from Python's interpreter and not the bot itself, because
bot.py and earwigbot.runner will already call these functions.
"""
is_encrypted = config.load()
if is_encrypted: # Passwords in the config file are encrypted
key = getpass("Enter key to unencrypt bot passwords: ")
config._decryption_key = key
config.decrypt(config.wiki, "password")

def _get_cookiejar(self):
"""Return a LWPCookieJar object loaded from our .cookies file.
@@ -89,8 +76,7 @@ class SitesDBManager(object):
if self._cookiejar:
return self._cookiejar

cookie_file = path.join(config.root_dir, ".cookies")
self._cookiejar = LWPCookieJar(cookie_file)
self._cookiejar = LWPCookieJar(self._cookie_file)

try:
self._cookiejar.load()
@@ -163,10 +149,12 @@ class SitesDBManager(object):
This calls _load_site_from_sitesdb(), so SiteNotFoundError will be
raised if the site is not in our sitesdb.
"""
cookiejar = self._get_cookiejar()
(name, project, lang, base_url, article_path, script_path, sql,
namespaces) = self._load_site_from_sitesdb(name)

config = self.config
login = (config.wiki.get("username"), config.wiki.get("password"))
cookiejar = self._get_cookiejar()
user_agent = config.wiki.get("userAgent")
use_https = config.wiki.get("useHTTPS", False)
assert_edit = config.wiki.get("assert")
@@ -265,9 +253,6 @@ class SitesDBManager(object):
cannot be found in the sitesdb, SiteNotFoundError will be raised. An
empty sitesdb will be created if none is found.
"""
if not config.is_loaded():
self._load_config()

# Someone specified a project without a lang, or vice versa:
if (project and not lang) or (not project and lang):
e = "Keyword arguments 'lang' and 'project' must be specified together."
@@ -276,7 +261,7 @@ class SitesDBManager(object):
# No args given, so return our default site:
if not name and not project and not lang:
try:
default = config.wiki["defaultSite"]
default = self.config.wiki["defaultSite"]
except KeyError:
e = "Default site is not specified in config."
raise SiteNotFoundError(e)
@@ -322,17 +307,15 @@ class SitesDBManager(object):
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():
self._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 = "//{0}.{1}.org".format(lang, project)
cookiejar = self._get_cookiejar()

config = self.config
login = (config.wiki.get("username"), config.wiki.get("password"))
cookiejar = self._get_cookiejar()
user_agent = config.wiki.get("userAgent")
use_https = config.wiki.get("useHTTPS", False)
assert_edit = config.wiki.get("assert")
@@ -358,9 +341,6 @@ class SitesDBManager(object):
was given but not a language, or vice versa. Will create an empty
sitesdb if none was found.
"""
if not config.is_loaded():
self._load_config()

# Someone specified a project without a lang, or vice versa:
if (project and not lang) or (not project and lang):
e = "Keyword arguments 'lang' and 'project' must be specified together."
@@ -381,12 +361,3 @@ class SitesDBManager(object):
return self._remove_site_from_sitesdb(name)

return False

_root = path.split(path.split(path.dirname(path.abspath(__file__)))[0])[0]
_dbfile = path.join(_root, "sites.db")
_manager = SitesDBManager(_dbfile)
del _root, _dbfile

get_site = _manager.get_site
add_site = _manager.add_site
remove_site = _manager.remove_site

読み込み中…
キャンセル
保存