[cig-commits] r5058 - in cs/merlin/trunk: . merlin merlin/archimedes

leif at geodynamics.org leif at geodynamics.org
Tue Oct 17 02:11:51 PDT 2006


Author: leif
Date: 2006-10-17 02:11:50 -0700 (Tue, 17 Oct 2006)
New Revision: 5058

Added:
   cs/merlin/trunk/merlin/
   cs/merlin/trunk/merlin/__init__.py
   cs/merlin/trunk/merlin/archimedes/
   cs/merlin/trunk/merlin/archimedes/__init__.py
Modified:
   cs/merlin/trunk/setup.py
Log:
Initial check-in of my wizard.  (Still under construction.)


Added: cs/merlin/trunk/merlin/__init__.py
===================================================================
--- cs/merlin/trunk/merlin/__init__.py	2006-10-16 22:38:03 UTC (rev 5057)
+++ cs/merlin/trunk/merlin/__init__.py	2006-10-17 09:11:50 UTC (rev 5058)
@@ -0,0 +1,420 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                               merlin
+#
+# Copyright (c) 2006, California Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#
+#    * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+#    * Redistributions in binary form must reproduce the above
+#    copyright notice, this list of conditions and the following
+#    disclaimer in the documentation and/or other materials provided
+#    with the distribution.
+#
+#    * Neither the name of the California Institute of Technology nor
+#    the names of its contributors may be used to endorse or promote
+#    products derived from this software without specific prior
+#    written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+### don't forget, .svn metadata gone in tarball; need gen manifest/sources
+### imports.people?  Requires decoration
+### how to tie to filesystem?  svn:metadata?
+### implicit roots for traits
+####### style:  requires-imports?
+### exports, (freeze-and-?)include in project
+
+### food for thought:
+###### projects have implicit "root = ${thisfile}.${directory}"
+###### "mounting" stuff... almost nothing has to be hard-coded in merlin itself
+
+
+__inUserSpace__ = False
+
+
+class Node(object):
+
+    class UserAttributes(object):
+        
+        def __init__(self):
+            self._factory = None
+            self._frozen = False
+
+        def __getattribute__(self, attr):
+            xgetattr = super(Node.UserAttributes, self).__getattribute__
+            if (attr.startswith('_') or
+                self._frozen or
+                self._factory is None):
+                value = xgetattr(attr)
+            else:
+                try:
+                    value = xgetattr(attr)
+                except AttributeError:
+                    value = self._createNewAttribute(attr)
+            return value
+
+        def _createNewAttribute(self, attr):
+            value = self._factory(attr)
+            setattr(self, attr, value)
+            value._name = attr
+            return value
+
+    isContextual = False
+
+    def __init__(self, name):
+        super(Node, self).__init__()
+        self.name = name
+        self.attrs = Node.UserAttributes()
+        self.attrs._factory = Node
+
+    def __getattribute__(self, attr):
+        global __inUserSpace__, __lookups__
+        if __inUserSpace__:
+            __lookups__.append(attr)
+            return self.getUserAttribute(attr)
+        return super(Node, self).__getattribute__(attr)
+
+    def getFactory(self): return self.attrs._factory
+    def setFactory(self, value): self.attrs._factory = value
+    factory = property(getFactory, setFactory)
+
+    def __repr__(self):
+        return self.__class__.__name__
+
+    def getUserAttribute(self, attr): return getattr(self.attrs, attr)
+
+    def setUserAttribute(self, attr, value): setattr(self.attrs, attr, value)
+
+    def freeze(self):
+        self.attrs._frozen = True
+        for name, child in self.children():
+            child.freeze()
+        return
+
+    def resolveAll(self, context):
+        context.push(self)
+        self.resolve(context)
+        context.pop()
+
+    def resolve(self, context):
+        for name, child in self.children():
+            child.resolveAll(context)
+        return
+
+    def populateNamespace(self, namespace):
+        for name, child in self.children():
+            namespace[name] = child
+        return namespace
+
+    def dump(self, indent = 0):
+        i = indent * "    "
+        print "%s%s(%r):" % (i, self.name, self)
+        for name, child in self.children():
+            child.dump(indent + 1)
+        return
+
+    def children(self):
+        for k,v in self.attrs.__dict__.iteritems():
+            if k.startswith('_'):
+                continue
+            yield k,v
+        return
+
+    def find(self, name):
+        return self.follow(name.split('.'))
+
+    def follow(self, path):
+        node = self
+        for attr in path:
+            node = node.getUserAttribute(attr)
+        return node
+
+
+class LeafNode(Node):
+    def dump(self, indent = 0):
+        i = indent * "    "
+        print "%s%s = %r" % (i, self.name, self)
+
+
+class Literal(LeafNode):
+    
+    def __init__(self, name, value):
+        super(Literal, self).__init__(name)
+        self._value = value
+        
+    def __repr__(self):
+        return repr(self._value)
+
+
+class SymbolicExpr(LeafNode):
+    
+    def __init__(self, name, expr):
+        super(SymbolicExpr, self).__init__(name)
+        self._expr = expr
+        self._value = None
+        
+    def __repr__(self):
+        return repr(self._expr)
+    
+    def resolve(self, context):
+        self._value = context.resolve(self)
+
+
+class ErrorNode(LeafNode):
+    
+    def __init__(self, name, exception):
+        super(ErrorNode, self).__init__(name)
+        self._exception = exception
+        
+    def __repr__(self):
+        return repr(self._exception)
+
+
+class Object(Node): pass
+
+
+class Action(Object): pass
+class Component(Object): pass
+class Program(Object): pass
+class Library(Object): pass
+
+class Person(Object): pass
+
+
+class Project(Object):
+
+    isContextual = True
+
+    def __init__(self, name):
+        super(Project, self).__init__(name)
+        self.attrs.actions.factory = Action
+        self.attrs.components.factory = Component
+        self.attrs.programs.factory = Program
+        self.attrs.libraries.factory = Library
+
+
+class Root(Object):
+    isContextual = True
+    def __init__(self, name="root"):
+        super(Root, self).__init__(name)
+
+
+class Context(object):
+
+    def __init__(self, root):
+        super(Context, self).__init__()
+        self.path = []
+        self.root = root
+        self.errors = False
+        self.namespaceStack = [dict()] # pre-root namespace
+
+    def push(self, node):
+        self.path.append(node)
+        if node.isContextual:
+            new = dict(self.currentNamespace())
+            node.populateNamespace(new)
+            self.namespaceStack.append(new)
+        return
+
+    def pop(self):
+        node = self.path.pop()
+        if node.isContextual:
+            self.namespaceStack.pop()
+        return node
+
+    def currentPathName(self): return '.'.join([node.name for node in self.path[1:]])
+
+    def resolveAll(self):
+        self.root.resolveAll(self)
+
+    def resolve(self, symbol):
+        value, exception = self.lookup(symbol._expr)
+        if exception:
+            value = [ErrorNode(symbol.name, exception)]
+            self.unresolvedSymbol(symbol, exception)
+        return value
+
+    def lookup(self, identifier):
+        value = None
+        exception = None
+        userSpace = dict(globals())
+        userSpace['__inUserSpace__'] = True
+        userSpace['__lookups__'] = []
+        try:
+            value = eval(identifier, self.currentNamespace(), userSpace)
+        except Exception, e:
+            exception = e
+        print '@@@@', userSpace['__lookups__']
+        return value, exception
+
+    def currentNamespace(self): return self.namespaceStack[-1]
+    
+    def unresolvedSymbol(self, symbol, exception):
+        import sys
+        
+        self.errors = True
+        name = self.currentPathName()
+        
+        print >> sys.stderr, name
+        print >> sys.stderr,  "    error: cannot resolve '%s':" % symbol._expr
+        print >> sys.stderr,  "        %s" % exception
+        return
+
+
+def parseSpell(filename = 'project.cfg'):
+    
+    from os.path import expanduser, join
+    from ConfigParser import ConfigParser
+
+    # initialize
+    spell = ConfigParser()
+    #spell.readfp(open('defaults.cfg')) # pkg
+    spell.read(expanduser(join('~', '.merlin', 'etc', 'merlin', 'preferences.cfg')))
+
+    # parse the spell file
+    spell.readfp(open(filename))
+    
+    return spell
+
+
+def parseSpellSyntaxTree(spell):
+    """Return an abstract syntax tree for the raw syntax tree <spell>.
+
+    """
+
+    # This function is, in essence, a "tree parser" in the ANTLR
+    # sense.
+
+    from curses.ascii import isalpha
+    
+    ast = Root()
+    ast.attrs.projects.factory = Project
+    ast.attrs.people.factory = Person
+
+    for section in spell.sections():
+
+        # Walk the path given by the section name, starting at the
+        # root.
+        current = ast.find(section)
+        
+        # Walk the path given by each item name, starting at the
+        # current node.
+        items = spell.items(section)
+        for name, value in items:
+            path = name.split('.')
+            node = current.follow(path[:-1])
+            attr = path[-1]
+            
+            if len(value) and (isalpha(value[0]) or value[0] == '['):
+                # These will be evaluated later.
+                value = SymbolicExpr(attr, value)
+            else:
+                value = eval(value)
+                if isinstance(value, basestring):
+                    value = ' '.join(value.splitlines())
+                    value = value.strip()
+                value = Literal(attr, value)
+            node.setUserAttribute(attr, value)
+
+    return ast
+
+
+def setup():
+    from setuptools import setup, find_packages, Extension
+
+    spell = parseSpell()
+
+    ast = parseSpellSyntaxTree(spell)
+    
+    ast.dump()
+
+    # The spell has been cast; no magic node creation beyond this
+    # point.  Perhaps we need some Latin here or something, instead of
+    # 'freeze'.
+    ast.freeze()
+
+    # Fix-up symbolic references.
+    context = Context(ast)
+    context.resolveAll()
+    if context.errors:
+        import sys
+        sys.exit("merlin: error(s) loading project")
+    
+    return
+
+    name = config.get('project', 'name')
+    version = config.get('project', 'version')
+    extensions = config.get('project', 'extensions')
+
+    ext_modules = []
+
+    for extName in extensions:
+
+        section = 'extensions.%s' % extName
+        
+        extType = config.get(section, 'type')
+        assert extType == 'python/extension' # currently, the only supported option
+
+        sources = config.get(section, 'sources')
+        sources = sources.split()
+        
+        cSources = []
+        for s in sources:
+            if s.endswith('.c'):
+                cSources.append(s)
+
+        extension = Extension(extName, sources) # extra_compile_args=args
+        ext_modules.append(extension)
+
+    # find primary author
+    et_al = ", et al."
+
+    #  >= 0.8.1.0b2, < 0.8.2a
+    #  >= 1.0, < 2a
+
+    setup(
+        name = name, 
+        version = version,
+
+        # build/install any packages we can find
+        packages = find_packages(),
+            
+        # include in the distribution everything under version control
+        include_package_data = True,
+            
+        ext_modules = ext_modules,
+
+        # this is only here temporarily, for debugging
+        download_url = 'http://crust.geodynamics.org/~leif/shipping/',
+        
+        )
+    
+    return
+
+
+# end of file


Property changes on: cs/merlin/trunk/merlin/archimedes
___________________________________________________________________
Name: svn:externals
   + ez_setup    http://geodynamics.org/svn/cig/cs/ez_setup


Added: cs/merlin/trunk/merlin/archimedes/__init__.py
===================================================================
--- cs/merlin/trunk/merlin/archimedes/__init__.py	2006-10-16 22:38:03 UTC (rev 5057)
+++ cs/merlin/trunk/merlin/archimedes/__init__.py	2006-10-17 09:11:50 UTC (rev 5058)
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#                         merlin.archimedes
+#
+# Copyright (c) 2006, California Institute of Technology
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#
+#    * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+#    * Redistributions in binary form must reproduce the above
+#    copyright notice, this list of conditions and the following
+#    disclaimer in the documentation and/or other materials provided
+#    with the distribution.
+#
+#    * Neither the name of the California Institute of Technology nor
+#    the names of its contributors may be used to endorse or promote
+#    products derived from this software without specific prior
+#    written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+# Adjust the following numbers when creating a branch.  Branch numbers
+# follow the CVS convention (but with no even/odd rules).
+
+# Maybe I could extract this from .svn?
+
+def currentBranchNumber(): return '1'
+def endOfCurrentBranch(): return '2a'
+
+
+def currentVersion():
+    # Increment this before making a release.
+    return currentBranchNumber() + '.0'
+
+
+version = currentVersion()
+
+
+def currentVersionSpec():
+    """Return the global requirement specifier for all projects using
+    merlin.
+    
+    """
+    
+    return ">= %s, < %s" % (currentVersion(), endOfCurrentBranch())
+
+
+def use_merlin():
+    
+    from ez_setup import use_setuptools
+    use_setuptools()
+    
+    merlinRequirementSpec = 'merlin %s' % currentVersionSpec()
+    
+    # Call setup() with 'setup_requires' set to download merlin (and
+    # pythia... and setuptools, if it isn't already installed).  N.B.:
+    # The code below not mean that 'archimedes' would ever be
+    # distributed as a separate package!
+    
+    from setuptools import setup
+    setup(
+        script_args=['--version'],
+        
+        name = 'archimedes', 
+        version = version,
+        setup_requires = [merlinRequirementSpec],
+
+        author = 'Leif Strand',
+        author_email = 'leif at geodynamics.org',
+        description = """Merlin's owl.""",
+        license = 'BSD',
+        url = 'http://www.geodynamics.org/cig/software/packages/pythia/',
+
+        )
+
+    return
+
+
+# end of file

Modified: cs/merlin/trunk/setup.py
===================================================================
--- cs/merlin/trunk/setup.py	2006-10-16 22:38:03 UTC (rev 5057)
+++ cs/merlin/trunk/setup.py	2006-10-17 09:11:50 UTC (rev 5058)
@@ -3,20 +3,17 @@
 use_setuptools()
 
 from setuptools import setup
+from merlin.archimedes import version
 
 setup(
     
     name = 'merlin', 
-    version = '0.8.1.0',
+    version = version,
 
     zip_safe = True,
     
-    install_requires = [
-    'pythia[merlin] >= 0.8.1.0a, < 0.8.2.0a',
-    ],
-    
-    author = 'Michael A.G. Aivazis',
-    author_email = 'aivazis at caltech.edu',
+    author = 'Leif Strand',
+    author_email = 'leif at geodynamics.org',
     description = 'A wizard.',
     license = 'BSD',
     url = 'http://www.geodynamics.org/cig/software/packages/pythia/',



More information about the cig-commits mailing list