# Copyright 2002 by Jeffrey Chang, Andrew Dalke. All rights reserved. # This code is part of the Biopython distribution and governed by its # license. Please see the LICENSE file that should have been included # as part of this package. # This is based on some older code by Andrew Dalke. """This module implements some base classes used in the Registry system for Biopython. Classes: Registry Implements a Biopython Registry. RegisterableObject Base class for objects in the Registry. RegisterableGroup Base class for groups of objects in the Registry. """ class Registry: """This is a dictionary-like object for storing and retrieving objects in a registry. Methods: register Add a RegisterableObject into the Registry. Dictionary interface: __getitem__ get keys values items """ def __init__(self, name, load_path=None): """Registry(name[, load_path]) Create a new registry. name is the name of the registry. load_path is an optional path (e.g. Bio.config.dbdefs) that contains objects for the registry. """ self._name = name self._load_path = load_path self._name_table, self._abbrev_table = {}, {} self._autoloaded = self._autoloading = 0 def _autoload(self): if self._autoloaded or self._autoloading: return self._autoloading = 1 self._load(self._load_path) self._autoloading = 0 self._autoloaded = 1 def _load(self, path): if path is None: return import _support # Get a list of all the modules in that path. modulenames = _support.find_submodules(path) modulenames = filter(lambda x: not x.startswith("_"), modulenames) modulenames.sort() # Now load each one of the modules and look for # RegisterableObject objects in them. for name in modulenames: module = _support.load_module(name) for name, obj in module.__dict__.items(): if name.startswith("_") or \ not isinstance(obj, RegisterableObject): continue self.register(obj) def register(self, obj): """S.register(obj) Add an object to the registry. obj must be a RegisterableObject object. """ self._autoload() name, abbrev = obj.name, obj.abbrev abbrev = abbrev or name if self._name_table.has_key(name): raise ValueError("%r is a duplicate entry" % (name,)) if self._abbrev_table.has_key(abbrev): raise ValueError("%r is a duplicate entry" % (abbrev,)) self._name_table[name] = obj self._abbrev_table[abbrev] = obj def __getitem__(self, name): self._autoload() return self._name_table[name] # raises KeyError for unknown entries def get(self, name, default=None): self._autoload() return self._name_table.get(name, default) def keys(self): self._autoload() return self._name_table.keys() def values(self): self._autoload() return self._name_table.values() def items(self): self._autoload() return self._name_table.items() def __str__(self): objs = self.keys() objs.sort() if not objs: return self._name obj_str = ', '.join(map(repr, objs)) return "%s, exporting %s" % (self._name, obj_str) __repr__ = __str__ class RegisterableObject: """This is a base class for objects that can be added to a registry. Members: name The name of the object. abbrev An abbreviation for the name """ def __init__(self, name, abbrev, doc): """RegisterableObject(name, abbrev, doc)""" import re self.name = name self.abbrev = abbrev or name _legal_abbrev = re.compile(r"[a-zA-Z][a-zA-Z0-9_]*$") check_abbrev = _legal_abbrev.match if not check_abbrev(self.abbrev): raise ValueError, "abbrev name of %r is not allowed" % self.abbrev self.__doc__ = doc class RegisterableGroup(RegisterableObject): """This is a base class for a RegisterableObject that groups many objects together. Methods: add Add an object to the end of the group. add_after Add an object to the group after another object. add_before Add an object to the group before another object. """ def __init__(self, name, abbrev, doc): RegisterableObject.__init__(self, name, abbrev, doc) self.objs = [] def add(self, obj, index=None): if index is None: index = len(self.objs) self.objs.insert(index, obj) def add_after(self, obj, after): for i in range(len(self.objs)): if self.objs[i] == after: break else: raise ValueError, "I couldn't find the insertion point" self.add(obj, i+1) def add_before(self, obj, before): for i in range(len(self.objs)): if self.objs[i] == before: break else: raise ValueError, "I couldn't find the insertion point" self.add(obj, i)