Adamw has submitted this change and it was merged. Change subject: python libraries are available in common ......................................................................
python libraries are available in common Deprecate virtualenv jail, it had no walls. Other than refactoring, the config semantics changed slightly. I'm unhappy with the import-by-value issue, "from process.globals import config" will not update config during initialization, so you need to call load_config before importing any other tools/ files. TODO: * moar docs Change-Id: I5bc6741852b95b67c6354c4634369ab7c7423fd8 --- M .gitignore D audit/globalcollect/db.py M audit/globalcollect/history.py M audit/paypal/history.py D banner_screenshot/mediawiki/__init__.py D banner_screenshot/mediawiki/centralnotice.py D banner_screenshot/mediawiki/time_util.py M banner_screenshot/shoot_banners A civicrm/__init__.py R civicrm/civicrm.py A database/__init__.py R database/db.py R fundraising_ab_tests/__init__.py R fundraising_ab_tests/campaign_log.py R fundraising_ab_tests/confidence.py R fundraising_ab_tests/results.py R fundraising_ab_tests/results_gdoc.py R fundraising_ab_tests/spec.py R fundraising_ab_tests/spec_gdoc.py A google/__init__.py R google/gdocs.py D junkyard/.gitignore M live_analysis/README M live_analysis/dump_tests.py D live_analysis/jail.py M live_analysis/publish_results M live_analysis/update_spec_sheet A mediawiki/__init__.py R mediawiki/api.py R mediawiki/centralnotice/__init__.py R mediawiki/centralnotice/api.py R mediawiki/centralnotice/contributions.py R mediawiki/centralnotice/impressions.py R mediawiki/centralnotice/time_util.py R mediawiki/centralnotice/top_ten.py A process/__init__.py A process/globals.py R process/lock.py A stats/__init__.py R stats/stats_abba.py 40 files changed, 104 insertions(+), 224 deletions(-) Approvals: Adamw: Verified; Looks good to me, approved diff --git a/.gitignore b/.gitignore index d4a8918..8711254 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.pyc + # IDE Files .idea diff --git a/audit/globalcollect/db.py b/audit/globalcollect/db.py deleted file mode 100644 index 30a2e6c..0000000 --- a/audit/globalcollect/db.py +++ /dev/null @@ -1,17 +0,0 @@ -import MySQLdb as Dbi - -class Connection(object): - def __init__(self, host=None, user=None, passwd=None, db=None, debug=False, **ignore): - self.db_conn = Dbi.connect(host=host, user=user, passwd=passwd, db=db) - self.debug = debug - - def close(self): - self.db_conn.commit() - pass - - def execute(self, sql, params=()): - cursor = self.db_conn.cursor(cursorclass=Dbi.cursors.DictCursor) - if self.debug: - print(sql % params) - cursor.execute(sql, params) - cursor.close() diff --git a/audit/globalcollect/history.py b/audit/globalcollect/history.py index 38b5a08..b4f53fe 100755 --- a/audit/globalcollect/history.py +++ b/audit/globalcollect/history.py @@ -11,7 +11,7 @@ import csv import atexit -from db import Connection as DbConnection +from database.db import Connection as DbConnection def main(): global config, options, db diff --git a/audit/paypal/history.py b/audit/paypal/history.py index 93d1802..061e72e 100755 --- a/audit/paypal/history.py +++ b/audit/paypal/history.py @@ -11,7 +11,7 @@ import gzip import locale import dateutil.parser -import civicrm +from civicrm.civicrm import Civicrm def main(): global config, messaging, options, civi @@ -36,7 +36,7 @@ log("*** Dummy mode! Not injecting stomp messages ***") messaging = Stomp(config) - civi = civicrm.Civicrm(config) + civi = Civicrm(config) locale.setlocale(locale.LC_NUMERIC, "") diff --git a/banner_screenshot/mediawiki/__init__.py b/banner_screenshot/mediawiki/__init__.py deleted file mode 100644 index 247139a..0000000 --- a/banner_screenshot/mediawiki/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -''' -Dumb interface to the MediaWiki api. -''' - -import config - -import json - -def mw_call( args ): - import simplemediawiki - - wiki = simplemediawiki.MediaWiki( - config.centralnotice_mw_api, - user_agent='bot: fr-screenshots' - ) - result = wiki.call( args ) - if 'error' in result: - raise RuntimeError(json.dumps(result, indent=4).replace('\\n', '\n')) - val = result[ args['action'] ] - if 'list' in args: - val = val[ args['list'] ] - return val diff --git a/banner_screenshot/mediawiki/centralnotice.py b/banner_screenshot/mediawiki/centralnotice.py deleted file mode 100644 index 4133d29..0000000 --- a/banner_screenshot/mediawiki/centralnotice.py +++ /dev/null @@ -1,56 +0,0 @@ -''' -Interface to the MediaWiki CentralNotice api -''' - -from mediawiki import mw_call - -cached_campaigns = {} - -def get_banners( **kw ): - if 'campaign' in kw: - campaign = get_campaign( kw['campaign'] ) - return campaign['banners'].keys() - return get_allocations( **kw ) - -def get_campaign( campaign ): - #TODO: push caching down into mediawiki.mw_call, with optional invalidation - global cached_campaigns - if campaign in cached_campaigns: - return cached_campaigns[campaign] - - #if '__iter__' in campaign: return get_campaigns - result = mw_call( { - 'action': 'centralnoticequerycampaign', - 'campaign': campaign, - } ) - - if campaign in result: - cached_campaigns[campaign] = result[campaign] - return cached_campaigns[campaign] - -def get_campaigns( campaigns ): - #FIXME cache - return mw_call( { - 'action': 'centralnoticequerycampaign', - 'campaign': '|'.join( campaigns ), - } ) - -def get_allocations( project=None, language=None, country=None, anonymous=True, bucket='0' ): - result = mw_call( { - 'action': 'centralnoticeallocations', - 'project': project, - 'language': language, - 'country': country, - 'anonymous': anonymous, - 'bucket': bucket, - 'minimal': 'false' - } ) - return result['banners'] - -def get_campaign_logs( since=None ): - result = mw_call( { - 'action': 'query', - 'list': 'centralnoticelogs', - 'start': since, - } ) - return result['logs'] diff --git a/banner_screenshot/mediawiki/time_util.py b/banner_screenshot/mediawiki/time_util.py deleted file mode 100644 index b02c2a6..0000000 --- a/banner_screenshot/mediawiki/time_util.py +++ /dev/null @@ -1,17 +0,0 @@ -from datetime import datetime, timedelta - -def str_time_offset(str_time=None, **delta_args): - if not str_time: - str_time = str_now() - time_time = datetime.strptime( str_time, '%Y%m%d%H%M%S' ) - str_time = ( time_time + timedelta( **delta_args )).strftime( '%Y%m%d%H%M%S' ) - return(str_time) - -def str_now(): - return( datetime.utcnow().strftime('%Y%m%d%H%M%S') ) - -def datetimefunix( unix_timestamp ): - return datetime.fromtimestamp(unix_timestamp) - -def strfunix( unix_timestamp ): - return datetime.fromtimestamp(unix_timestamp).strftime('%Y-%m-%d %H:%M') diff --git a/banner_screenshot/shoot_banners b/banner_screenshot/shoot_banners index 17c78c4..a700e6c 100755 --- a/banner_screenshot/shoot_banners +++ b/banner_screenshot/shoot_banners @@ -6,11 +6,13 @@ import re import sys -import config -from mediawiki.centralnotice import get_campaign_logs -from mediawiki.time_util import str_time_offset +from process.globals import load_config +load_config("config.py") -JS_RENDER_SCRIPT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "rasterize.js") +from process.globals import config +from mediawiki.centralnotice.api import get_campaign_logs +from mediawiki.centralnotice.time_util import str_time_offset +from process.lock import begin, end def reduce_banners(campaign_logs): '''Return a map from banner names to most recent campaign settings.''' @@ -47,6 +49,8 @@ return os.path.exists(get_screenshot_path(name, lang)) def render(name, lang, country): + global JS_RENDER_SCRIPT + url = config.article_url % { "banner": name, "lang": lang, "country": country } path = get_screenshot_path(name, lang) dir = os.path.dirname(path) @@ -75,8 +79,15 @@ if __name__ == "__main__": - if len(sys.argv) > 1: - for name in sys.argv[1:]: - screenshot_banner(name) - else: - process_banners() + try: + begin() + + JS_RENDER_SCRIPT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "rasterize.js") + + if len(sys.argv) > 1: + for name in sys.argv[1:]: + screenshot_banner(name) + else: + process_banners() + finally: + end() diff --git a/civicrm/__init__.py b/civicrm/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/civicrm/__init__.py diff --git a/audit/paypal/civicrm.py b/civicrm/civicrm.py similarity index 100% rename from audit/paypal/civicrm.py rename to civicrm/civicrm.py diff --git a/database/__init__.py b/database/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/database/__init__.py diff --git a/live_analysis/db.py b/database/db.py similarity index 97% rename from live_analysis/db.py rename to database/db.py index d454465..3ea43cd 100644 --- a/live_analysis/db.py +++ b/database/db.py @@ -3,6 +3,8 @@ ''' import MySQLdb as Dbi +from process.globals import config + class Connection(object): def __init__(self, host=None, user=None, passwd=None, db=None, debug=False): self.db_conn = Dbi.connect(host=host, user=user, passwd=passwd, db=db) @@ -56,8 +58,8 @@ def get_db(): '''Convienience''' - import config global db_conn + if not db_conn: db_conn = Connection(**config.db_params) return db_conn diff --git a/live_analysis/fr/tests/__init__.py b/fundraising_ab_tests/__init__.py similarity index 94% rename from live_analysis/fr/tests/__init__.py rename to fundraising_ab_tests/__init__.py index f0e5cc3..01a2efe 100644 --- a/live_analysis/fr/tests/__init__.py +++ b/fundraising_ab_tests/__init__.py @@ -4,14 +4,14 @@ These are not unit tests ;) they are WMF Fundraising A/B tests. ''' -from fr.centralnotice import get_campaign -from fr.tests.results import get_banner_results +import mediawiki.centralnotice.api +from results import get_banner_results class FrTest(object): def __init__(self, label=None, type="", campaign=None, banners=None, start=None, end=None, disabled=False, **ignore): print "Warning: ignoring columns: %s" % (", ".join(ignore.keys()), ) - self.campaign = get_campaign(campaign) + self.campaign = mediawiki.centralnotice.api.get_campaign(campaign) if not self.campaign: print "Warning: no such campaign '%s'" % campaign diff --git a/live_analysis/fr/tests/campaign_log.py b/fundraising_ab_tests/campaign_log.py similarity index 86% rename from live_analysis/fr/tests/campaign_log.py rename to fundraising_ab_tests/campaign_log.py index 2b0dc50..e1a7bca 100644 --- a/live_analysis/fr/tests/campaign_log.py +++ b/fundraising_ab_tests/campaign_log.py @@ -1,7 +1,4 @@ -''' -''' - -from fr.tests import FrTest +from fundraising_ab_tests import FrTest def tests_from_entry(entry): ''' @@ -40,8 +37,8 @@ return (test_from_entry('begin'), test_from_entry('end'), ) def get_relevant_events(): - from fr.centralnotice import get_campaign_logs - import fr.time_util + from mediawiki.centralnotice.api import get_campaign_logs + from mediawiki.centralnotice import time_util def is_relevant(entry): ''' @@ -50,5 +47,5 @@ if 'enabled' in entry['added'] or entry['begin']['enabled'] is 1: return True - logs = get_campaign_logs(since=fr.time_util.str_time_offset(days=-1)) + logs = get_campaign_logs(since=time_util.str_time_offset(days=-1)) return [ tests_from_entry(e) for e in reversed(logs) if is_relevant(e) ] diff --git a/live_analysis/fr/tests/confidence.py b/fundraising_ab_tests/confidence.py similarity index 96% rename from live_analysis/fr/tests/confidence.py rename to fundraising_ab_tests/confidence.py index 2c02f31..69e2771 100644 --- a/live_analysis/fr/tests/confidence.py +++ b/fundraising_ab_tests/confidence.py @@ -1,5 +1,5 @@ -import config -from stats_abba import Experiment +from process.globals import config +from stats.stats_abba import Experiment def add_confidence(results, name_column, successes_column): confidence = get_confidence(results, name_column, successes_column) diff --git a/live_analysis/fr/tests/results.py b/fundraising_ab_tests/results.py similarity index 87% rename from live_analysis/fr/tests/results.py rename to fundraising_ab_tests/results.py index 8179732..d9704da 100644 --- a/live_analysis/fr/tests/results.py +++ b/fundraising_ab_tests/results.py @@ -1,10 +1,10 @@ import re import json -import config -from fr.contributions import get_totals -from fr.impressions import get_impressions -from fr.tests.confidence import add_confidence +from process.globals import config +from mediawiki.centralnotice.contributions import get_totals +from mediawiki.centralnotice.impressions import get_impressions +from fundraising_ab_tests.confidence import add_confidence class TestResult(object): def __init__(self, criteria=None, results={}): diff --git a/live_analysis/fr/tests/results_gdoc.py b/fundraising_ab_tests/results_gdoc.py similarity index 97% rename from live_analysis/fr/tests/results_gdoc.py rename to fundraising_ab_tests/results_gdoc.py index 64bf0a6..c52b7d7 100644 --- a/live_analysis/fr/tests/results_gdoc.py +++ b/fundraising_ab_tests/results_gdoc.py @@ -1,4 +1,4 @@ -from gdocs import Spreadsheet +from google.gdocs import Spreadsheet def write_gdoc_results(doc=None, results=[]): print "Writing test results to %s" % doc diff --git a/live_analysis/fr/tests/spec.py b/fundraising_ab_tests/spec.py similarity index 96% rename from live_analysis/fr/tests/spec.py rename to fundraising_ab_tests/spec.py index e121617..099ec3d 100644 --- a/live_analysis/fr/tests/spec.py +++ b/fundraising_ab_tests/spec.py @@ -5,7 +5,7 @@ import re -from fr.tests import FrTest +from fundraising_ab_tests import FrTest import campaign_log def parse_spec(spec): diff --git a/live_analysis/fr/tests/spec_gdoc.py b/fundraising_ab_tests/spec_gdoc.py similarity index 96% rename from live_analysis/fr/tests/spec_gdoc.py rename to fundraising_ab_tests/spec_gdoc.py index 6d130da..3c56201 100644 --- a/live_analysis/fr/tests/spec_gdoc.py +++ b/fundraising_ab_tests/spec_gdoc.py @@ -1,6 +1,5 @@ -#import jail from spec import FrTestSpec, parse_spec -from gdocs import Spreadsheet +from google.gdocs import Spreadsheet def read_gdoc_spec(doc=None): return FrTestSpec(spec=list(parse_spec(Spreadsheet(doc=doc).get_all_rows()))) diff --git a/google/__init__.py b/google/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/google/__init__.py diff --git a/live_analysis/gdocs.py b/google/gdocs.py similarity index 98% rename from live_analysis/gdocs.py rename to google/gdocs.py index abaa31d..edad349 100644 --- a/live_analysis/gdocs.py +++ b/google/gdocs.py @@ -6,7 +6,7 @@ import gdata.docs.data import gdata.spreadsheet.service -import config +from process.globals import config # TODO: ExecuteBatch; 2-leg oauth # TODO: cache rows locally, operate and then flush diff --git a/junkyard/.gitignore b/junkyard/.gitignore deleted file mode 100644 index 72e8ffc..0000000 --- a/junkyard/.gitignore +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/live_analysis/README b/live_analysis/README index 13d7df1..dea3ecb 100644 --- a/live_analysis/README +++ b/live_analysis/README @@ -42,11 +42,8 @@ As root: - pip install virtualenv MySQL-python + pip install MySQL-python simplemediawiki kitchen gdata In this directory: - - virtualenv jailenv - PATH=jailenv/bin pip install simplemediawiki kitchen gdata cp config.py.example config.py # and edit diff --git a/live_analysis/dump_tests.py b/live_analysis/dump_tests.py index 3a905cd..e18eede 100755 --- a/live_analysis/dump_tests.py +++ b/live_analysis/dump_tests.py @@ -5,8 +5,9 @@ import csv import sys -from fr.tests.spec import FrTestSpec, parse_spec -from fr.centralnotice import get_campaign_logs +import mediawiki.centralnotice.api + +import process.globals def is_relevant(entry): ''' @@ -33,7 +34,7 @@ pagesize = 500 while True: - logs = get_campaign_logs(limit=pagesize, offset=cur) + logs = mediawiki.centralnotice.api.get_campaign_logs(limit=pagesize, offset=cur) for test in logs: if is_relevant(test): @@ -50,4 +51,6 @@ cur = cur + pagesize -fetch() +if __name__ == "__main__": + process.globals.load_config("config.py") + fetch() diff --git a/live_analysis/jail.py b/live_analysis/jail.py deleted file mode 100644 index f665022..0000000 --- a/live_analysis/jail.py +++ /dev/null @@ -1,14 +0,0 @@ -''' -Phony "jail" provides inline "virtualenv" execution -''' -import os -import subprocess - -jail_path = os.path.dirname(os.path.abspath(__file__)) + "/jailenv" - -def run(source): - env = os.environ - env['PATH'] = jail_path + "/bin:" + env['PATH'] - ret = subprocess.call( [ "python", "-c", source ], env=env ) - if ret is not 0: - raise Exception("Failed to run jail command, result=%d" % ret) diff --git a/live_analysis/publish_results b/live_analysis/publish_results index 159a4b4..c24457e 100755 --- a/live_analysis/publish_results +++ b/live_analysis/publish_results @@ -1,32 +1,18 @@ #!/usr/bin/env python -import json -import cPickle as pickle -import os +from process.globals import load_config +load_config("config.py") -import config -import jail -import lock +from process.lock import begin, end +from fundraising_ab_tests.spec_gdoc import read_gdoc_spec +from fundraising_ab_tests.results_gdoc import update_gdoc_results -unique = os.environ['LOGNAME'] -spec_tmp = "/tmp/%s-tests.pickle" % unique -results_tmp = "/tmp/%s-test_results.json" % unique -lockfile = "/tmp/%s-franal-publish-proc.lock" % unique +from process.globals import config -lock.begin(filename=lockfile) +begin() -# do gdocs and simplemediawiki queries in an insolated environment -#FIXME: security is illusory -jail.run(""" -from cPickle import dump -from fr.tests.spec_gdoc import read_gdoc_spec - -print "Reading test specifications from %(url)s" -tests = read_gdoc_spec(doc="%(url)s") -dump(tests, open("%(out)s", "w")) -""" % {'url': config.test_spec_url, 'out': spec_tmp}) - -tests = pickle.load(open(spec_tmp, "r")) +print "Reading test specifications from %s" % (config.test_spec_url, ) +tests = read_gdoc_spec(doc=config.test_spec_url) # Compile statistics from the database results = [] @@ -39,15 +25,7 @@ results.extend([r.__dict__ for r in test.results]) #results.extend(test.results) -open(results_tmp, "w").write(json.dumps(results, indent=4)) - # store in gdocs spreadsheet -jail.run(""" -from json import loads -from fr.tests.results_gdoc import update_gdoc_results +update_gdoc_results(doc=config.test_results_url, results=results) -results = loads(open("%(results)s", "r").read()) -update_gdoc_results(doc="%(url)s", results=results) -""" % {'results': results_tmp, 'url': config.test_results_url}) - -lock.end() +end() diff --git a/live_analysis/update_spec_sheet b/live_analysis/update_spec_sheet index 453ba38..d114378 100755 --- a/live_analysis/update_spec_sheet +++ b/live_analysis/update_spec_sheet @@ -1,21 +1,15 @@ #!/usr/bin/env python -import os +from process.globals import load_config +load_config("config.py") -import config -import jail -import lock +from process.lock import begin, end +from fundraising_ab_tests.spec_gdoc import update_gdoc_spec -unique = os.environ['LOGNAME'] -lockfile = "/tmp/%s-franal-update-proc.lock" % unique +from process.globals import config -lock.begin(filename=lockfile) +begin() -# do gdocs and simplemediawiki queries in an insolated environment -#FIXME: security is illusory -jail.run(""" -from fr.tests.spec_gdoc import update_gdoc_spec -update_gdoc_spec(doc="%(url)s") -""" % {'url': config.test_spec_url}) +update_gdoc_spec(doc=config.test_spec_url) -lock.end() +end() diff --git a/mediawiki/__init__.py b/mediawiki/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/mediawiki/__init__.py diff --git a/live_analysis/fr/mediawiki.py b/mediawiki/api.py similarity index 92% rename from live_analysis/fr/mediawiki.py rename to mediawiki/api.py index ed7f0b5..8c6bd87 100644 --- a/live_analysis/fr/mediawiki.py +++ b/mediawiki/api.py @@ -2,7 +2,7 @@ Dumb interface to the MediaWiki api. ''' -import config +from process.globals import config import json diff --git a/live_analysis/fr/__init__.py b/mediawiki/centralnotice/__init__.py similarity index 100% rename from live_analysis/fr/__init__.py rename to mediawiki/centralnotice/__init__.py diff --git a/live_analysis/fr/centralnotice.py b/mediawiki/centralnotice/api.py similarity index 97% rename from live_analysis/fr/centralnotice.py rename to mediawiki/centralnotice/api.py index b661cf5..9589a4a 100644 --- a/live_analysis/fr/centralnotice.py +++ b/mediawiki/centralnotice/api.py @@ -2,7 +2,7 @@ Interface to the MediaWiki CentralNotice api ''' -from mediawiki import mw_call +from mediawiki.api import mw_call cached_campaigns = {} diff --git a/live_analysis/fr/contributions.py b/mediawiki/centralnotice/contributions.py similarity index 97% rename from live_analysis/fr/contributions.py rename to mediawiki/centralnotice/contributions.py index 6f8d141..1c8e47d 100644 --- a/live_analysis/fr/contributions.py +++ b/mediawiki/centralnotice/contributions.py @@ -7,9 +7,11 @@ import os import decimal +from process.globals import config +from database import db + import time_util import top_ten -import config ct_banner_clause = "LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(utm_source, '.', 2),'.',1), LENGTH(SUBSTRING_INDEX(SUBSTRING_INDEX(utm_source, '.', 2),'.',1)))" @@ -36,8 +38,6 @@ ''' Note that the column names must match a heading in the results spreadsheet. ''' - import db - if not query: query = db.Query() query.columns.append('SUM(total_amount) AS total') diff --git a/live_analysis/fr/impressions.py b/mediawiki/centralnotice/impressions.py similarity index 94% rename from live_analysis/fr/impressions.py rename to mediawiki/centralnotice/impressions.py index 232df64..3d54392 100644 --- a/live_analysis/fr/impressions.py +++ b/mediawiki/centralnotice/impressions.py @@ -1,6 +1,6 @@ -def get_impressions(campaign=None, banner=None, **ignore): - import db +from database import db +def get_impressions(campaign=None, banner=None, **ignore): query = db.Query() query.columns.append("SUM(count) AS count") query.tables.append("pgehres.bannerimpressions") diff --git a/live_analysis/fr/time_util.py b/mediawiki/centralnotice/time_util.py similarity index 100% rename from live_analysis/fr/time_util.py rename to mediawiki/centralnotice/time_util.py diff --git a/live_analysis/fr/top_ten.py b/mediawiki/centralnotice/top_ten.py similarity index 100% rename from live_analysis/fr/top_ten.py rename to mediawiki/centralnotice/top_ten.py diff --git a/process/__init__.py b/process/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/process/__init__.py diff --git a/process/globals.py b/process/globals.py new file mode 100644 index 0000000..060fbb6 --- /dev/null +++ b/process/globals.py @@ -0,0 +1,16 @@ +import re +from importlib import import_module +from yaml import safe_load as load_yaml + +# n.b. Careful not to import `config` by value +config = dict() + +def load_config(filename): + global config + + if re.search(r'[.]py$', filename): + config = import_module(filename[:-3]) + elif re.search(r'[.]ya?ml$', filename): + config = load_yaml(file(filename, 'r')) + else: + raise Exception("No config found.") diff --git a/live_analysis/lock.py b/process/lock.py similarity index 81% rename from live_analysis/lock.py rename to process/lock.py index d7528f4..1e69ead 100644 --- a/live_analysis/lock.py +++ b/process/lock.py @@ -9,6 +9,11 @@ lockfile = None def begin(filename=None, failopen=False): + if not filename: + unique = os.environ['LOGNAME'] + cmd = os.path.basename(sys.argv[0]) + filename = "/tmp/%s-%s.lock" % (unique, cmd) + if os.path.exists(filename): print "Lockfile found!" f = open(filename, "r") @@ -42,4 +47,7 @@ def end(): global lockfile - os.unlink(lockfile) + if lockfile: + os.unlink(lockfile) + else: + raise RuntimeError("Already unlocked!") diff --git a/stats/__init__.py b/stats/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/stats/__init__.py diff --git a/live_analysis/stats_abba.py b/stats/stats_abba.py similarity index 100% rename from live_analysis/stats_abba.py rename to stats/stats_abba.py -- To view, visit https://gerrit.wikimedia.org/r/81436 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I5bc6741852b95b67c6354c4634369ab7c7423fd8 Gerrit-PatchSet: 5 Gerrit-Project: wikimedia/fundraising/tools Gerrit-Branch: master Gerrit-Owner: Adamw <awi...@wikimedia.org> Gerrit-Reviewer: Adamw <awi...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits