[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