"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "roundup/instance.py" between
roundup-1.6.1.tar.gz and roundup-2.0.0.tar.gz

About: Roundup is an highly customisable issue-tracking system with command-line, web and e-mail interfaces (written in Python).

instance.py  (roundup-1.6.1):instance.py  (roundup-2.0.0)
skipping to change at line 31 skipping to change at line 31
Open a tracker with: Open a tracker with:
>>> from roundup import instance >>> from roundup import instance
>>> db = instance.open('path to tracker home') >>> db = instance.open('path to tracker home')
The "db" handle you get back is the tracker's hyperdb which has the interface The "db" handle you get back is the tracker's hyperdb which has the interface
described in `roundup.hyperdb.Database`. described in `roundup.hyperdb.Database`.
""" """
__docformat__ = 'restructuredtext' __docformat__ = 'restructuredtext'
try:
import builtins
except ImportError:
import __builtin__ as builtins
try:
from collections.abc import Callable
except ImportError:
from collections import Callable
import os import os
import sys import sys
import warnings import warnings
from roundup import configuration, mailgw from roundup import configuration, mailgw
from roundup import hyperdb, backends, actions from roundup import hyperdb, backends, actions
from roundup.cgi import client, templating from roundup.cgi import client, templating
from roundup.cgi import actions as cgi_actions from roundup.cgi import actions as cgi_actions
from roundup.exceptions import RoundupException
class Tracker: class Tracker:
def __init__(self, tracker_home, optimize=0): def __init__(self, tracker_home, optimize=0):
"""New-style tracker instance constructor """New-style tracker instance constructor
Parameters: Parameters:
tracker_home: tracker_home:
tracker home directory tracker home directory
optimize: optimize:
if set, precompile html templates if set, precompile html templates
skipping to change at line 67 skipping to change at line 78
self.config = configuration.CoreConfig(tracker_home) self.config = configuration.CoreConfig(tracker_home)
self.actions = {} self.actions = {}
self.cgi_actions = {} self.cgi_actions = {}
self.templating_utils = {} self.templating_utils = {}
libdir = os.path.join(self.tracker_home, 'lib') libdir = os.path.join(self.tracker_home, 'lib')
self.libdir = os.path.isdir(libdir) and libdir or '' self.libdir = os.path.isdir(libdir) and libdir or ''
self.load_interfaces() self.load_interfaces()
self.templates = templating.get_loader(self.config["TEMPLATES"], self.templates = templating.get_loader(self.config["TEMPLATES"],
self.config["TEMPLATE_ENGINE"]) self.config["TEMPLATE_ENGINE"])
rdbms_backend = self.config.RDBMS_BACKEND rdbms_backend = self.config.RDBMS_BACKEND
# TODO: Remove in v1.7 # TODO: Remove in v1.7
# Provide some backwards compatability for existing Roundup instances # Provide some backwards compatability for existing Roundup instances
# that still define the backend type in 'db/backend_name' and warn the # that still define the backend type in 'db/backend_name' and warn the
# users they need to update their config.ini # users they need to update their config.ini
if rdbms_backend == '': if rdbms_backend == '':
filename = os.path.join(self.config.DATABASE, 'backend_name') filename = os.path.join(self.config.DATABASE, 'backend_name')
msg = """\n msg = """\n
The 'backend_name' file is no longer used to configure the database backend The 'backend_name' file is no longer used to configure the database backend
used for the tracker. Please read 'doc/upgrading.txt' to find out how to used for the tracker. Please read 'doc/upgrading.txt' to find out how to
update your config.ini update your config.ini
""" """
try: try:
with file(filename) as backend_file: with open(filename) as backend_file:
rdbms_backend = backend_file.readline().strip() rdbms_backend = backend_file.readline().strip()
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter("once", DeprecationWarning) warnings.simplefilter("once", DeprecationWarning)
warnings.warn(msg, DeprecationWarning, stacklevel=2) warnings.warn(msg, DeprecationWarning, stacklevel=2)
except IOError: except IOError:
pass pass
self.backend = backends.get_backend(rdbms_backend) self.backend = backends.get_backend(rdbms_backend)
skipping to change at line 131 skipping to change at line 142
'Interval': hyperdb.Interval, 'Interval': hyperdb.Interval,
'Boolean': hyperdb.Boolean, 'Boolean': hyperdb.Boolean,
'Number': hyperdb.Number, 'Number': hyperdb.Number,
'Integer': hyperdb.Integer, 'Integer': hyperdb.Integer,
'db': backend.Database(self.config, name) 'db': backend.Database(self.config, name)
} }
if self.optimize: if self.optimize:
# execute preloaded schema object # execute preloaded schema object
self._exec(self.schema, env) self._exec(self.schema, env)
if callable (self.schema_hook): if isinstance(self.schema_hook, Callable):
self.schema_hook(**env) self.schema_hook(**env)
# use preloaded detectors # use preloaded detectors
detectors = self.detectors detectors = self.detectors
else: else:
# execute the schema file # execute the schema file
self._execfile('schema.py', env) self._execfile('schema.py', env)
if callable (self.schema_hook): if isinstance(self.schema_hook, Callable):
self.schema_hook(**env) self.schema_hook(**env)
# reload extensions and detectors # reload extensions and detectors
for extension in self.get_extensions('extensions'): for extension in self.get_extensions('extensions'):
extension(self) extension(self)
detectors = self.get_extensions('detectors') detectors = self.get_extensions('detectors')
db = env['db'] db = env['db']
db.tx_Source = None db.tx_Source = None
# apply the detectors # apply the detectors
for detector in detectors: for detector in detectors:
skipping to change at line 165 skipping to change at line 176
# pointing at a defined class. Otherwise, the schema is # pointing at a defined class. Otherwise, the schema is
# internally inconsistent. This is an important safety # internally inconsistent. This is an important safety
# measure as it protects against an accidental schema change # measure as it protects against an accidental schema change
# dropping a table while there are still links to the table; # dropping a table while there are still links to the table;
# once the table has been dropped, there is no way to get it # once the table has been dropped, there is no way to get it
# back, so it is important to drop it only if we are as sure # back, so it is important to drop it only if we are as sure
# as possible that it is no longer needed. # as possible that it is no longer needed.
classes = db.getclasses() classes = db.getclasses()
for classname in classes: for classname in classes:
cl = db.getclass(classname) cl = db.getclass(classname)
for propname, prop in cl.getprops().iteritems(): for propname, prop in cl.getprops().items():
if not isinstance(prop, (hyperdb.Link, if not isinstance(prop, (hyperdb.Link,
hyperdb.Multilink)): hyperdb.Multilink)):
continue continue
linkto = prop.classname linkto = prop.classname
if linkto not in classes: if linkto not in classes:
raise ValueError, \ raise ValueError("property %s.%s links to "
("property %s.%s links to non-existent class %s" "non-existent class %s"
% (classname, propname, linkto)) % (classname, propname, linkto))
db.post_init() db.post_init()
self.db_open = 1 self.db_open = 1
return db return db
def load_interfaces(self): def load_interfaces(self):
"""load interfaces.py (if any), initialize Client and MailGW attrs""" """load interfaces.py (if any), initialize Client and MailGW attrs"""
env = {} env = {}
if os.path.isfile(os.path.join(self.tracker_home, 'interfaces.py')): if os.path.isfile(os.path.join(self.tracker_home, 'interfaces.py')):
self._execfile('interfaces.py', env) self._execfile('interfaces.py', env)
self.Client = env.get('Client', client.Client) self.Client = env.get('Client', client.Client)
self.MailGW = env.get('MailGW', mailgw.MailGW) self.MailGW = env.get('MailGW', mailgw.MailGW)
self.TemplatingUtils = env.get('TemplatingUtils', templating.TemplatingU self.TemplatingUtils = env.get('TemplatingUtils',
tils) templating.TemplatingUtils)
def get_extensions(self, dirname): def get_extensions(self, dirname):
"""Load python extensions """Load python extensions
Parameters: Parameters:
dirname: dirname:
extension directory name relative to tracker home extension directory name relative to tracker home
Return value: Return value:
list of init() functions for each extension list of init() functions for each extension
skipping to change at line 215 skipping to change at line 227
continue continue
env = {} env = {}
self._execfile(os.path.join(dirname, name), env) self._execfile(os.path.join(dirname, name), env)
extensions.append(env['init']) extensions.append(env['init'])
sys.path.remove(dirpath) sys.path.remove(dirpath)
return extensions return extensions
def init(self, adminpw, tx_Source=None): def init(self, adminpw, tx_Source=None):
db = self.open('admin') db = self.open('admin')
db.tx_Source = tx_Source db.tx_Source = tx_Source
self._execfile('initial_data.py', {'db': db, 'adminpw': adminpw, self._execfile('initial_data.py',
'admin_email': self.config['ADMIN_EMAIL']}) {'db': db, 'adminpw': adminpw,
'admin_email': self.config['ADMIN_EMAIL']})
db.commit() db.commit()
db.close() db.close()
def exists(self): def exists(self):
return self.backend.db_exists(self.config) return self.backend.db_exists(self.config)
def nuke(self): def nuke(self):
self.backend.db_nuke(self.config) self.backend.db_nuke(self.config)
def _compile(self, fname): def _compile(self, fname):
fname = os.path.join(self.tracker_home, fname) fname = os.path.join(self.tracker_home, fname)
return compile(file(fname).read(), fname, 'exec') return compile(builtins.open(fname).read(), fname, 'exec')
def _exec(self, obj, env): def _exec(self, obj, env):
if self.libdir: if self.libdir:
sys.path.insert(1, self.libdir) sys.path.insert(1, self.libdir)
exec(obj, env) exec(obj, env)
if self.libdir: if self.libdir:
sys.path.remove(self.libdir) sys.path.remove(self.libdir)
return env return env
def _execfile(self, fname, env): def _execfile(self, fname, env):
skipping to change at line 260 skipping to change at line 273
if issubclass(action, actions.Action): if issubclass(action, actions.Action):
self.actions[name] = action self.actions[name] = action
if issubclass(action, cgi_actions.Bridge): if issubclass(action, cgi_actions.Bridge):
self.cgi_actions[name] = action self.cgi_actions[name] = action
else: else:
self.cgi_actions[name] = action self.cgi_actions[name] = action
def registerUtil(self, name, function): def registerUtil(self, name, function):
self.templating_utils[name] = function self.templating_utils[name] = function
class TrackerError(BaseException): class TrackerError(RoundupException):
pass pass
class OldStyleTrackers: class OldStyleTrackers:
def __init__(self): def __init__(self):
self.number = 0 self.number = 0
self.trackers = {} self.trackers = {}
def open(self, tracker_home, optimize=0): def open(self, tracker_home, optimize=0):
"""Open the tracker. """Open the tracker.
skipping to change at line 283 skipping to change at line 296
tracker home directory tracker home directory
optimize: optimize:
if set, precompile html templates if set, precompile html templates
Raise ValueError if the tracker home doesn't exist. Raise ValueError if the tracker home doesn't exist.
""" """
import imp import imp
# sanity check existence of tracker home # sanity check existence of tracker home
if not os.path.exists(tracker_home): if not os.path.exists(tracker_home):
raise ValueError, 'no such directory: "%s"'%tracker_home raise ValueError('no such directory: "%s"' % tracker_home)
# sanity check tracker home contents # sanity check tracker home contents
for reqd in 'config dbinit select_db interfaces'.split(): for reqd in 'config dbinit select_db interfaces'.split():
if not os.path.exists(os.path.join(tracker_home, '%s.py'%reqd)): if not os.path.exists(os.path.join(tracker_home, '%s.py' % reqd)):
raise TrackerError, 'File "%s.py" missing from tracker '\ raise TrackerError('File "%s.py" missing from tracker '
'home "%s"'%(reqd, tracker_home) 'home "%s"' % (reqd, tracker_home))
if self.trackers.has_key(tracker_home): if tracker_home in self.trackers:
return imp.load_package(self.trackers[tracker_home], return imp.load_package(self.trackers[tracker_home],
tracker_home) tracker_home)
# register all available backend modules # register all available backend modules
backends.list_backends() backends.list_backends()
self.number = self.number + 1 self.number = self.number + 1
modname = '_roundup_tracker_%s'%self.number modname = '_roundup_tracker_%s' % self.number
self.trackers[tracker_home] = modname self.trackers[tracker_home] = modname
# load the tracker # load the tracker
tracker = imp.load_package(modname, tracker_home) tracker = imp.load_package(modname, tracker_home)
# ensure the tracker has all the required bits # ensure the tracker has all the required bits
for required in 'open init Client MailGW'.split(): for required in 'open init Client MailGW'.split():
if not hasattr(tracker, required): if not hasattr(tracker, required):
raise TrackerError, \ raise TrackerError('Required tracker attribute "%s" missing' %
'Required tracker attribute "%s" missing'%required required)
# load and apply the config # load and apply the config
tracker.config = configuration.CoreConfig(tracker_home) tracker.config = configuration.CoreConfig(tracker_home)
tracker.dbinit.config = tracker.config tracker.dbinit.config = tracker.config
tracker.optimize = optimize tracker.optimize = optimize
tracker.templates = templating.get_loader(tracker.config["TEMPLATES"]) tracker.templates = templating.get_loader(tracker.config["TEMPLATES"])
if optimize: if optimize:
tracker.templates.precompile() tracker.templates.precompile()
return tracker return tracker
OldStyleTrackers = OldStyleTrackers() OldStyleTrackers = OldStyleTrackers()
def open(tracker_home, optimize=0): def open(tracker_home, optimize=0):
if os.path.exists(os.path.join(tracker_home, 'dbinit.py')): if os.path.exists(os.path.join(tracker_home, 'dbinit.py')):
# user should upgrade... # user should upgrade...
return OldStyleTrackers.open(tracker_home, optimize=optimize) return OldStyleTrackers.open(tracker_home, optimize=optimize)
return Tracker(tracker_home, optimize=optimize) return Tracker(tracker_home, optimize=optimize)
# vim: set filetype=python sts=4 sw=4 et si : # vim: set filetype=python sts=4 sw=4 et si :
 End of changes. 19 change blocks. 
23 lines changed or deleted 36 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)