Mercurial > p > roundup > code
view roundup/scripts/roundup_xmlrpc_server.py @ 7371:a210f4437b49
Incomplete work to generate config doc from config.ini
This is an incomplete attempt to allow generation of the config.ini
documentation in reference.txt. It reformats the output of
'roundup_admin.py genconfig'. So it now includes all of the
settings. Using a Makefile rule like:
tracker_config.txt: ../roundup/configuration.py
python3 ../roundup/scripts/roundup_admin.py \
genconfig _temp_config.txt
sed -e '1,8d' \
-e 's/^\[\([a-z]*\)\]/\n.. index:: config.ini; sections \1\n\n.. code:: ini\n\n [\1]/' \
-e 's/^\([^[]\)/ \1/' \
_temp_config.txt > tracker_config.txt
rm -f _temp_config.txt
results in the config.ini split by section and index links being put
in place. However some sections have a comment before the [section]
marker. This comment is orphaned at the end of the prior section
rather than starting the new section. A simple sed won't allow the
lookahead needed to target the [section] marker and include the prior
comment block. Also there are still have some long lines generated (>
65 characters). Maybe a python script can import configuration.py and
output proper restructured text output?
reference.txt:
add a commented out include:: tracker_config.txt directive
roundup/admin.py:
don't require a tracker home for genconfig. So user can generate a
clean config.ini on demand. Tracker home is still required for
updateconfig.
roundup/configuration.py:
wrap lines better. A number of them are generating comments > 65
characters which is the targeted line length. This cleans up
config.ini too, so is a good thing.
website/www/conf.py:
ignore doc/tracker_config.ini when processing.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Wed, 17 May 2023 13:34:36 -0400 |
| parents | bc2b00afa980 |
| children | 14c7c07b32d8 |
line wrap: on
line source
#! /usr/bin/env python # # Copyright (C) 2007 Stefan Seefeld # All rights reserved. # For license terms see the file COPYING.txt. # # --- patch sys.path to make sure 'import roundup' finds correct version from __future__ import print_function import sys import os.path as osp thisdir = osp.dirname(osp.abspath(__file__)) rootdir = osp.dirname(osp.dirname(thisdir)) if (osp.exists(thisdir + '/__init__.py') and osp.exists(rootdir + '/roundup/__init__.py')): # the script is located inside roundup source code sys.path.insert(0, rootdir) # --/ import base64, getopt, os, sys, socket from roundup.anypy import urllib_ from roundup.xmlrpc import translate from roundup.xmlrpc import RoundupInstance import roundup.instance from roundup.instance import TrackerError from roundup.cgi.exceptions import Unauthorised from roundup.anypy import xmlrpc_ SimpleXMLRPCServer = xmlrpc_.server.SimpleXMLRPCServer SimpleXMLRPCRequestHandler = xmlrpc_.server.SimpleXMLRPCRequestHandler class RequestHandler(SimpleXMLRPCRequestHandler): """A SimpleXMLRPCRequestHandler with support for basic HTTP Authentication.""" TRACKER_HOMES = {} TRACKERS = {} def is_rpc_path_valid(self): path = self.path.split('/') name = urllib_.unquote(path[1]).lower() return name in self.TRACKER_HOMES def get_tracker(self, name): """Return a tracker instance for given tracker name.""" if name in self.TRACKERS: return self.TRACKERS[name] if name not in self.TRACKER_HOMES: raise Exception('No such tracker "%s"' % name) tracker_home = self.TRACKER_HOMES[name] tracker = roundup.instance.open(tracker_home) self.TRACKERS[name] = tracker return tracker def authenticate(self, tracker): # Try to extract username and password from HTTP Authentication. username, password = None, None authorization = self.headers.get('authorization', ' ') scheme, challenge = authorization.split(' ', 1) if scheme.lower() == 'basic': decoded = base64.b64decode(challenge) if ':' in decoded: username, password = decoded.split(':') else: username = decoded if not username: username = 'anonymous' db = tracker.open('admin') try: userid = db.user.lookup(username) except KeyError: # No such user db.close() raise Unauthorised('Invalid user') stored = db.user.get(userid, 'password') if stored != password: # Wrong password db.close() raise Unauthorised('Invalid user') db.setCurrentUser(username) return db def do_POST(self): """Extract username and password from authorization header.""" db = None try: path = self.path.split('/') tracker_name = urllib_.unquote(path[1]).lower() tracker = self.get_tracker(tracker_name) db = self.authenticate(tracker) instance = RoundupInstance(db, tracker.actions, None) self.server.register_instance(instance) SimpleXMLRPCRequestHandler.do_POST(self) except Unauthorised as message: self.send_error(403, '%s (%s)' % (self.path, message)) except: if db: db.close() exc, val, tb = sys.exc_info() print(exc, val, tb) raise if db: db.close() class Server(SimpleXMLRPCServer): def _dispatch(self, method, params): retn = SimpleXMLRPCServer._dispatch(self, method, params) retn = translate(retn) return retn def usage(): print("""Usage: %s: [options] [name=tracker home]+ Options: -e, --encoding -- specify the encoding to use -V -- be verbose when importing -p, --port <port> -- port to listen on """ % sys.argv[0]) def run(): try: opts, args = getopt.getopt(sys.argv[1:], 'e:i:p:V', ['encoding=', 'port=']) except getopt.GetoptError: usage() return 1 verbose = False port = 8000 encoding = None for opt, arg in opts: if opt == '-V': verbose = True elif opt in ['-p', '--port']: port = int(arg) elif opt in ['-e', '--encoding']: encoding = encoding tracker_homes = {} for arg in args: try: name, home = arg.split('=', 1) # Validate the argument tracker = roundup.instance.open(home) except ValueError: print('Instances must be name=home') sys.exit(-1) except TrackerError: print('Tracker home does not exist.') sys.exit(-1) tracker_homes[name] = home RequestHandler.TRACKER_HOMES = tracker_homes if sys.version_info[0:2] < (2, 5): if encoding: print('encodings not supported with python < 2.5') sys.exit(-1) server = Server(('', port), RequestHandler) else: server = Server(('', port), RequestHandler, allow_none=True, encoding=encoding) # Go into the main listener loop print('Roundup XMLRPC server started on %s:%d' % (socket.gethostname(), port)) try: server.serve_forever() except KeyboardInterrupt: print('Keyboard Interrupt: exiting') if __name__ == '__main__': run()
