From 70c4c10ae48bae2b0c5a7b01e1753455a67c414d Mon Sep 17 00:00:00 2001 From: Jakob Date: Sun, 1 Dec 2019 16:12:40 -0600 Subject: [PATCH] Switch to hand-rolled logging --- api.py | 3 --- auth.py | 18 ++++++++---------- common.py | 25 +++++-------------------- main.py | 36 ++++++++++++++++++++++-------------- 4 files changed, 35 insertions(+), 47 deletions(-) diff --git a/api.py b/api.py index 13bc80c..fdee4c7 100644 --- a/api.py +++ b/api.py @@ -13,13 +13,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from collections import namedtuple import json from pathlib import PurePosixPath -from urllib.parse import urlencode as mk_qs import urllib.request -import auth import util def walk_pages(opener, url): diff --git a/auth.py b/auth.py index b91b09e..269991d 100644 --- a/auth.py +++ b/auth.py @@ -22,7 +22,7 @@ from pathlib import PurePosixPath import urllib.parse import urllib.request -import common +from common import log import util ADDRESS = 'localhost' @@ -31,8 +31,6 @@ ENDPOINT = '/redirection_endpoint' TIMEOUT = timedelta(minutes = 30) -LOGGER = common.LOGGER.getChild('auth') - class OauthCodeRequestHandler(http.server.BaseHTTPRequestHandler): LANDING_PATH = '/landing' @@ -124,7 +122,7 @@ class OauthHandler(urllib.request.BaseHandler): def _handle(self, request): token_doc = self.storage_mgr.get('authInfo') if not token_doc: - LOGGER.info("No stored access token. Requesting a new token.") + log('info', "No stored access token. Requesting a new token.") token_doc = get_access_token(self.storage_mgr, self.api_iface) self.storage_mgr['authInfo'] = token_doc self._set_auth_header(request, token_doc) @@ -134,7 +132,7 @@ class OauthHandler(urllib.request.BaseHandler): https_request = _handle def http_error_401(self, request, fp, code, msg, headers): - LOGGER.info("Access token expired or revoked. Requesting a new token.") + log('info', "Access token expired or revoked. Requesting a new token.") token_doc = get_access_token(self.storage_mgr, self.api_iface) self.storage_mgr['authInfo'] = token_doc self._set_auth_header(request, token_doc) @@ -177,7 +175,7 @@ def get_access_token(storage_mgr, api_iface): if resp.status == 200: token_doc = body else: - LOGGER.info("Stored refresh token rejected. Obtaining new authorization code.") + log('info', "Stored refresh token rejected. Obtaining new authorization code.") assert resp.status == 400 if token_doc is None: @@ -205,10 +203,10 @@ def get_access_token(storage_mgr, api_iface): ) Thread(target = server.serve_forever, daemon = True).start() - LOGGER.info("Attempting to launch a web browser to authorize the application…") + log('info', "Attempting to launch a web browser to authorize the application…") if not webbrowser.open(user_url): - LOGGER.info("Failed to launch a browser. Please visit this URL to authorize the application:") - LOGGER.info(" {}".format(user_url)) + log('info', "Failed to launch a browser. Please visit this URL to authorize the application:") + log('info', user_url, indent = 1) try: resp = channel.get(timeout = TIMEOUT.total_seconds()) @@ -315,6 +313,6 @@ class CookieAuthHandler(urllib.request.HTTPCookieProcessor): self.cookiejar.save() def http_error_401(self, request, fp, code, msg, headers): - LOGGER.info("Session cookies missing or expired. Logging in…") + log('info', "Session cookies missing or expired. Logging in…") self.log_in() return self.parent.open(request, timeout = request.timeout) diff --git a/common.py b/common.py index 3cc3ea7..b6346a6 100644 --- a/common.py +++ b/common.py @@ -13,11 +13,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from collections import deque, namedtuple +from collections import namedtuple import json -import logging from pathlib import PurePosixPath -import urllib.request + BlackboardRoot = namedtuple('BlackboardRoot', ['host', 'path']) BB_ROOT = BlackboardRoot( @@ -25,25 +24,11 @@ BB_ROOT = BlackboardRoot( path = PurePosixPath('/'), ) -LOGGER = logging.getLogger('bb-sync-api') -logging.basicConfig() -LOGGER.setLevel(logging.INFO) - -class Adapter(logging.LoggerAdapter): - def process(self, msg, kwargs): - return (' ' * kwargs['indent'] + msg, kwargs) - -''' -LOGGER = Adapter(LOGGER, {}) -LOGGER.debug('some message', indent = 1) -class IndentingFormatter(logging.Formatter): - def format(self, record): - prefix = ' ' * record.indent if hasattr(record, 'indent') else '' - return prefix + None +def log(level, message, indent = 0): + import sys + print(level.upper().rjust(7) + ': ' + indent * ' ' + message, file = sys.stderr) -LOGGER.setFormatter(logging.Formatter('', style = '{')) -''' class StorageManager(): def __init__(self, path): diff --git a/main.py b/main.py index c15e992..e35af39 100644 --- a/main.py +++ b/main.py @@ -20,10 +20,8 @@ import json from operator import attrgetter from pathlib import Path import shutil -import sys import tempfile import urllib.parse -import urllib.request from common import * import api @@ -93,26 +91,26 @@ with StorageManager(Path('auth_cache')) as storage_mgr: found_course_id = None if found_course_id: if found_course_id != course_id: - LOGGER.warning("Using a course root previously used for another course!") - LOGGER.warning("File versioning may misbehave.") + log('warning', "Using a course root previously used for another course!") + log('warning', "File versioning may misbehave.") else: with meta_path.open('x') as f: json.dump({'course_id': course_id}, f) content_path = api_iface.get_content_path(course_id, content_id) - LOGGER.info("Blackboard content path: {}".format('/'.join(seg['id'] for seg in content_path))) + log('info', "Blackboard content path: {}".format('/'.join(seg['id'] for seg in content_path))) local_content_root = functools.reduce(fs.join_content_path, content_path, local_course_root) - LOGGER.info("Local content path: {}".format(local_content_root)) + log('info', "Local content path: {}".format(local_content_root)) for child_doc in api_iface.get_children(course_id, content_id): - LOGGER.info("Processing content item {id}: \"{title}\"".format(**child_doc)) + log('info', "Processing content item {id}: \"{title}\"".format(**child_doc)) local_path = fs.join_content_path(local_content_root, child_doc) versions = fs.get_child_versions(local_path) for attachment_doc in api_iface.get_attachments(course_id, child_doc['id']): att_id = attachment_doc['id'] - LOGGER.info(" Checking attachment {id}: \"{fileName}\"".format(**attachment_doc)) + log('info', "Checking attachment {id}: \"{fileName}\"".format(**attachment_doc), indent = 1) class Result: NoVersions = namedtuple('NoVersions', []) @@ -146,19 +144,29 @@ with StorageManager(Path('auth_cache')) as storage_mgr: if Result.to_update(result): if isinstance(result, Result.SingleLatest): new_version = result.version.next() - LOGGER.info(" Found new revision ({})".format(new_version.version)) + log('info', "Found new revision ({})".format(new_version.version), indent = 2) else: new_version = fs.VersionInfo(att_id, 0) - LOGGER.info(" Storing initial revision") + log('info', "Storing initial revision", indent = 2) dest = fs.get_new_path(local_path, attachment_doc['fileName']) - LOGGER.info(" Destination: {}".format(dest)) + log('info', "Destination: {}".format(dest), indent = 2) tmp_path.replace(dest) fs.write_metadata(dest, new_version) elif isinstance(result, Result.SingleLatest): # versions match tmp_path.unlink() elif isinstance(result, Result.MultipleLatest): - LOGGER.error(" Identified multiple latest versions for {id}: {fileName}" - .format(**attachment_doc) + log( + 'error', + "Identified multiple latest versions for {id}: {fileName}".format(**attachment_doc), + indent = 2, ) - LOGGER.error(" Please delete ") + log( + 'error', + "To allow the program to check this attachment, delete all or all but one of these files:", + indent = 2, + ) + for path_str in sorted(map(str, result.paths)): + log('error', path_str, indent = 3) + else: + raise AssertionError() -- 2.30.2