All computer source code presented on this page, unless it includes attribution to another author, is provided by Ed Halley under the Artistic License. Use such code freely and without any expectation of support. I would like to know if you make anything cool with the code, or need questions answered.
# namespaces - a general unique-name-to-object-instance registry


A general unique-name-to-object-instance registry.


    A namespace registers arbitrary unique names and arbitrary data
    objects.  Once registered, hard references between objects is not
    necessary, and symbolic by-name references can be used instead.


    Ed Halley ( 5 January 2007



class Namespace (object):

    '''A Namespace is a registration mapping between arbitrary unique names
    and arbitrary (non-unique) data objects.  When registering a new object,
    if the desired name is already given, a new unique name is built by
    appending an incrementing number onto the desired name.  The name should
    be unregistered using the original data object before it is freed.'''

    import weakref

    # A Namespace may elect to use weak references to its associated data
    # objects at creation time.  This is experimental and may have issues
    # when an object disappears but is still registered under a name.

    def __init__(self, weak = False):
        self.names = {}
        self.roots = {}
        self.weak = weak

    def alloc(self, root):
        # Internal routine which finds and pins down a new unique name.
        count = 1
        if not isinstance(root, str): root = "Thing"
        if not root in self.roots:
            self.roots[root] = count
        name = root
        while name in self.names:
            count += 1
            name = "%s%s" % (root, count)
        self.names[name] = None
        return name

    def refer(self, thing):
        # Internal routine which makes the right sort of reference to data.
        if self.weak:
            return weakref.ref(thing)
            return thing

    def object(self, name):
        '''Looks up the object associated with a given name, if any.
        Returns None if there is no associated object by that name.
        if name in self.names:
            if self.weak and self.names[name]:
                return self.names[name]()
                return self.names[name]
        return None

    def register(self, thing, name=None):
        '''Associates a given data value to a new unique name.  The
        caller may suggest a name but if that suggestion is already
        registered, a numerical suffix is incremented and appended until
        the new name is unique.  The final actual name is returned, and
        the caller should not assume it matches the name they suggested.
        if thing is None:
            raise ValueError('Must register a non-None value to a name')
        name = self.alloc(name)
        self.names[name] = self.refer(thing)
        return name

    def unregister(self, thing, name):
        '''Removes any association between a given data value and a
        specific existing name.  The requirement to show the original
        data value is for safety, to ensure unrelated names are not
        if name in self.names:
            ours = self.object(name)
            if thing is not ours:
                msg = ('Must unregister name "%s" with same object' % name)
                if ours is None:
                    msg = (('Tried to unregister name "%s" with an object ' +
                            'but original object is None') % name)
                raise ValueError(msg)
            thing = ours
            del self.names[name]
        return thing


if __name__ == "__main__":

    # Unit tests are run by executing this module directly on command-line.
    # Tests are successful unless you see a python traceback in the output.

    raise Exception('No unit tests have been implemented for this module.')

Contact Ed Halley by email at
Text, code, layout and artwork are Copyright © 1996-2013 Ed Halley.
Copying in whole or in part, with author attribution, is expressly allowed.
Any references to trademarks are illustrative and are controlled by their respective owners.
Make donations with PayPal - it's fast, free and secure!