Changeset 1140

Show
Ignore:
Timestamp:
02/28/07 06:09:17 (2 years ago)
Author:
arjanmol
Message:

split setup.py in separate files for each command

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphor/trunk/setup.py

    r1139 r1140  
    4747    AddPackagePath('gaphor.UML', 'build/lib/gaphor/UML') 
    4848 
     49 
    4950from distutils.core import setup, Command 
     51from distutils.command.build import build 
     52from distutils.command.install import install 
    5053from distutils.command.build_py import build_py 
    5154from distutils.command.install_lib import install_lib 
     
    5356from distutils.util import byte_compile 
    5457from distutils.dir_util import mkpath 
    55 from utils.build_mo import build, build_mo 
    56 from utils.build_pot import build_pot 
    57 from utils.install_mo import install, install_mo 
     58from utils.command.build_mo import build_mo 
     59from utils.command.build_pot import build_pot 
     60from utils.command.install_mo import install_mo 
     61from utils.command.build_uml import build_uml 
     62from utils.command.build_version import build_version 
     63from utils.command.install_version import install_version 
     64from utils.command.run import run 
    5865 
    5966str_version = sys.version[:3] 
     
    6471 
    6572 
    66 class config_Gaphor(Command): 
     73class config(Command): 
    6774    description="Configure Gaphor" 
    6875 
     
    154161build.sub_commands.insert(0, ('config', None)) 
    155162 
    156 #class build_Gaphor(build): 
    157 
    158 #    def run(self): 
    159 #        self.run_command('config') 
    160 #        build.run(self) 
    161 
    162  
    163 def generate_version(dir, data_dir): 
    164     """ 
    165     Create a file gaphor/version.py which contains the current version. 
    166     """ 
    167     outfile = os.path.join(dir, 'gaphor', 'version.py') 
    168     print 'generating %s' % outfile, dir, data_dir 
    169     mkpath(os.path.dirname(outfile)) 
    170     f = open(outfile, 'w') 
    171     f.write('"""\nVersion information generated by setup.py. DO NOT EDIT.\n"""\n\n') 
    172     f.write('VERSION=\'%s\'\n' % VERSION) 
    173     # expand backspaces 
    174     f.write('DATA_DIR=\'%s\'\n' % data_dir.replace('\\', '\\\\')) 
    175     if os.name == 'nt': 
    176         home = 'USERPROFILE' 
    177     else: 
    178         home = 'HOME' 
    179     f.write('import os\n') 
    180     f.write('USER_DATA_DIR=os.path.join(os.getenv(\'%s\'), \'.gaphor\')\n' % home) 
    181     f.write('del os\n') 
    182     f.close() 
    183     byte_compile([outfile]) 
    184  
    185  
    186 class build_version(Command): 
    187  
    188     user_options = [ 
    189         ('build-lib=','b', "build directory (where to install from)"), 
    190         ('force', 'f', "force installation (overwrite existing files)"), 
    191         ('data-dir', None, "data directory (where images and plugins reside)"), 
    192         ] 
    193     boolean_options = [ 'force' ] 
    194  
    195     def initialize_options(self): 
    196         self.build_lib = None 
    197         self.force = 0 
    198         self.data_dir = None 
    199  
    200     def finalize_options(self): 
    201             self.set_undefined_options('build', 
    202                                        ('build_purelib', 'build_lib'), 
    203                                        ('force', 'force')) 
    204             self.data_dir = os.path.join(os.getcwd(), 'data') 
    205  
    206     def run(self): 
    207         generate_version(self.build_lib, self.data_dir) 
    208  
    209 build.sub_commands.insert(0, ('build_version', None)) 
    210  
    211 class build_uml(Command): 
    212  
    213     description = "Generate gaphor/UML/uml2.py." 
    214  
    215     user_options = [ 
    216         ('build-lib=','b', "build directory (where to install from)"), 
    217         ('force', 'f', "force installation (overwrite existing files)"), 
    218         ] 
    219  
    220     boolean_options = [ 'force' ] 
    221  
    222     def initialize_options(self): 
    223         self.build_lib = None 
    224         self.force = 0 
    225         self.data_dir = None 
    226  
    227     def finalize_options(self): 
    228             self.set_undefined_options('build', 
    229                                        ('build_lib', 'build_lib'), 
    230                                        ('force', 'force')) 
    231  
    232     def run(self): 
    233         sys.path.insert(0, self.build_lib) 
    234         self.generate_uml2() 
    235  
    236     def generate_uml2(self): 
    237         """ 
    238         Generate gaphor/UML/uml2.py in the build directory. 
    239         """ 
    240         import utils.genUML2 
    241         gen = os.path.join('utils', 'genUML2.py') 
    242         overrides = os.path.join('gaphor', 'UML', 'uml2.override') 
    243         model = os.path.join('gaphor', 'UML', 'uml2.gaphor') 
    244         py_model = os.path.join('gaphor', 'UML', 'uml2.py') 
    245         outfile = os.path.join(self.build_lib, py_model) 
    246         self.mkpath(os.path.dirname(outfile)) 
    247         if self.force or newer(model, outfile) \ 
    248                       or newer(overrides, outfile) \ 
    249                       or newer(gen, outfile): 
    250             print 'generating %s from %s...' % (py_model, model) 
    251             print '  (warnings can be ignored)' 
    252             utils.genUML2.generate(model, outfile, overrides) 
    253         else: 
    254             print 'not generating %s (up-to-date)' % py_model 
    255         byte_compile([outfile]) 
    256  
    257 build.sub_commands.append(('build_uml', None)) 
    258  
    259  
    260 class install_version(Command): 
    261  
    262     user_options = [ 
    263         ('install-dir=', 'd', "directory to install to"), 
    264         ('install-data=', 'd', "directory where data files are installed"), 
    265         ] 
    266  
    267  
    268     def initialize_options(self): 
    269         install_lib.initialize_options(self) 
    270         self.install_dir= None 
    271         self.install_data= None 
    272  
    273     def finalize_options(self): 
    274         install_lib.finalize_options(self) 
    275         self.set_undefined_options('install_lib', 
    276                                    ('install_dir', 'install_dir')) 
    277         self.set_undefined_options('install_data', 
    278                                    ('install_data', 'install_dir')) 
    279  
    280     def run(self): 
    281         # install a new version.py with install_data as data_dir; 
    282         # get rid of install root directory 
    283         print 'self', dir(self) 
    284         print 'self.get_finalized_command("install")', dir(self.get_finalized_command('install')) 
    285          
    286         skip = len(self.get_finalized_command('install').root or '') 
    287  
    288         generate_version(self.install_dir, self.install_data[skip:]) 
    289  
    290  
    291 class run_Gaphor(Command): 
    292  
    293     description = 'Launch Gaphor from the local directory' 
    294  
    295     user_options = [ 
    296         ('build-dir=', None, ''), 
    297         ('command=', 'c', 'execute command'), 
    298         ('file=', 'f', 'execute file'), 
    299         ('doctest=', 'd', 'execute doctests in module (e.g. gaphor.geometry)'), 
    300         ('unittest=', 'u', 'execute unittest file (e.g. tests/test-ns.py)'), 
    301         ('model=', 'm', 'load a model file'), 
    302         ('coverage', None, 'Calculate coverage (utils/coverage.py)'), 
    303     ] 
    304  
    305     def initialize_options(self): 
    306         self.build_lib = None 
    307         self.command = None 
    308         self.file = None 
    309         self.doctest = None 
    310         self.unittest = None 
    311         self.model = None 
    312         self.coverage = None 
    313         self.verbosity = 2 
    314  
    315     def finalize_options(self): 
    316         self.set_undefined_options('build', 
    317                                    ('build_lib', 'build_lib')) 
    318  
    319     def run(self): 
    320         print 'Starting Gaphor...' 
    321         print 'Starting with model file', self.model 
    322         for cmd_name in self.get_sub_commands(): 
    323             self.run_command(cmd_name) 
    324  
    325         import os.path 
    326         import gaphor 
    327         #os.environ['GAPHOR_DATADIR'] = os.path.abspath('data') 
    328         if self.coverage: 
    329             from utils import coverage 
    330             coverage.start() 
    331  
    332         if self.command: 
    333             print 'Executing command: %s...' % self.command 
    334             exec self.command 
    335  
    336         elif self.doctest: 
    337             print 'Running doctest cases in module: %s...' % self.doctest 
    338             import imp 
    339             # use zope's one since it handles coverage right 
    340             from zope.testing import doctest 
    341  
    342             # Figure out the file: 
    343             f = os.path.join(*self.doctest.split('.')) + '.py' 
    344             fp = open(f) 
    345             # Prepend module's package path to sys.path 
    346             pkg = os.path.join(self.build_lib, *self.doctest.split('.')[:-1]) 
    347             if pkg: 
    348                 sys.path.insert(0, pkg) 
    349                 print 'Added', pkg, 'to sys.path' 
    350             # Load the module as local module (without package) 
    351             test_module = imp.load_source(self.doctest.split('.')[-1], f, fp) 
    352             failure, tests = doctest.testmod(test_module, name=self.doctest, 
    353                  optionflags=doctest.ELLIPSIS + doctest.NORMALIZE_WHITESPACE) 
    354             if self.coverage: 
    355                 print 
    356                 print 'Coverage report:' 
    357                 coverage.report(f) 
    358             sys.exit(failure != 0) 
    359  
    360         elif self.unittest: 
    361             # Running a unit test is done by opening the unit test file 
    362             # as a module and running the tests within that module. 
    363             print 'Running test cases in unittest file: %s...' % self.unittest 
    364             import imp, unittest 
    365             fp = open(self.unittest) 
    366             test_module = imp.load_source('gaphor_test', self.unittest, fp) 
    367             test_suite = unittest.TestLoader().loadTestsFromModule(test_module) 
    368             #test_suite = unittest.TestLoader().loadTestsFromName(self.unittest) 
    369             test_runner = unittest.TextTestRunner(verbosity=self.verbosity) 
    370             result = test_runner.run(test_suite) 
    371             if self.coverage: 
    372                 print 
    373                 print 'Coverage report:' 
    374                 coverage.report(self.unittest) 
    375             sys.exit(not result.wasSuccessful()) 
    376  
    377         elif self.file: 
    378             print 'Executing file: %s...' % self.file 
    379             dir, f = os.path.split(self.file) 
    380             print 'Extending PYTHONPATH with %s' % dir 
    381             sys.path.append(dir) 
    382             execfile(self.file, {}) 
    383         else: 
    384             print 'Launching Gaphor...' 
    385             gaphor.main(self.model) 
    386  
    387     sub_commands = [('build', None)] 
    388  
    389  
    390 class tests_Gaphor(Command): 
     163 
     164class tests(Command): 
    391165 
    392166    description = 'Run the Gaphor test suite.' 
     
    469243      scripts=['bin/gaphor', 'bin/gaphorconvert'], 
    470244 
    471       cmdclass={'config': config_Gaphor
     245      cmdclass={'config': config
    472246                'build_uml': build_uml, 
    473247                'build_version': build_version, 
     248                'install_version': install_version, 
    474249                'build_mo': build_mo, 
    475250                'build_pot': build_pot, 
    476251                'install_mo': install_mo, 
    477                 'run': run_Gaphor
    478                 'tests': tests_Gaphor 
     252                'run': run
     253                'tests': tests 
    479254      }, 
    480255#      app=['gaphor-osx.py'], 
  • gaphor/trunk/utils/command/build_uml.py

    r1139 r1140  
    11#!/usr/bin/env python 
    2 # vim:sw=4:et 
    3 
    4 # Create a UML 2.0 datamodel from the Gaphor 0.2.0 model file. 
    5 
    6 # To do this we do the following: 
    7 # 1. read the model file with the gaphor parser 
    8 # 2. Create a object herarcy by ordering elements based on generalizations 
     2""" 
     3This file provides the code generator which transforms gaphor/UML/uml2.gaphor 
     4into gaphor/UML/uml2.py. 
    95 
    10 # Recreate the model using some very dynamic class, so we can set all 
    11 # attributes and traverse them to generate the data model. 
    12  
    13 from gaphor.parser import parse, base, element, canvas, canvasitem 
    14 import sys, string, operator 
    15 import override 
    16  
    17 header = """# This file is generated by genUML2.py. DO NOT EDIT! 
    18  
    19 from properties import association, attribute, enumeration, derivedunion, redefine 
     6Also a distutils tool, build_uml, is provided. 
    207""" 
    218 
    22 # Make getitem behave more politely 
    23 base.__real_getitem__ = base.__getitem__ 
     9## 
     10## The Command 
     11## 
    2412 
    25 def base__getitem__(self, key): 
    26     try: 
    27         return self.__real_getitem__(key) 
    28     except KeyError: 
    29         return None 
    30  
    31 base.__getitem__ = base__getitem__ 
    32  
    33 # redefine 'bool' for Python version < 2.3 
    34 if map(int, sys.version[:3].split('.')) < [2, 3]: 
    35     header = header + "bool = int\n" 
     13import os.path 
     14from distutils.core import Command 
     15from distutils.command.build import build 
     16from distutils.util import byte_compile 
     17from distutils.dep_util import newer 
    3618 
    3719 
    38 import re 
     20class build_uml(Command): 
    3921 
    40 pattern = r'([A-Z])' 
    41 sub = r'_\1' 
     22    description = "Generate gaphor/UML/uml2.py." 
    4223 
    43 def camelCase_to_underscore(str): 
    44     """ 
    45     >>> camelCase_to_underscore('camelcase') 
    46     'camelcase' 
    47     >>> camelCase_to_underscore('camelCase') 
    48     'camel_case' 
    49     >>> camelCase_to_underscore('camelCamelCase') 
    50     'camel_camel_case' 
    51     """ 
    52     return re.sub(pattern, sub, str).lower() 
     24    user_options = [ 
     25        ('build-lib=','b', "build directory (where to install from)"), 
     26        ('force', 'f', "force installation (overwrite existing files)"), 
     27        ] 
    5328 
    54 _ = camelCase_to_underscore 
     29    boolean_options = [ 'force' ] 
     30 
     31    def initialize_options(self): 
     32        self.build_lib = None 
     33        self.force = 0 
     34        self.data_dir = None 
     35 
     36    def finalize_options(self): 
     37            self.set_undefined_options('build', 
     38                                       ('build_lib', 'build_lib'), 
     39                                       ('force', 'force')) 
     40 
     41    def run(self): 
     42        import sys 
     43        sys.path.insert(0, self.build_lib) 
     44        self.generate_uml2() 
     45 
     46    def generate_uml2(self): 
     47        """ 
     48        Generate gaphor/UML/uml2.py in the build directory. 
     49        """ 
     50        gen = os.path.join('utils', 'command', 'gen_uml.py') 
     51        overrides = os.path.join('gaphor', 'UML', 'uml2.override') 
     52        model = os.path.join('gaphor', 'UML', 'uml2.gaphor') 
     53        py_model = os.path.join('gaphor', 'UML', 'uml2.py') 
     54        outfile = os.path.join(self.build_lib, py_model) 
     55        self.mkpath(os.path.dirname(outfile)) 
     56        if self.force or newer(model, outfile) \ 
     57                      or newer(overrides, outfile) \ 
     58                      or newer(gen, outfile): 
     59            print 'generating %s from %s...' % (py_model, model) 
     60            print '  (warnings can be ignored)' 
     61            import gen_uml 
     62            gen_uml.generate(model, outfile, overrides) 
     63        else: 
     64            print 'not generating %s (up-to-date)' % py_model 
     65        byte_compile([outfile]) 
     66 
     67build.sub_commands.append(('build_uml', None)) 
    5568 
    5669 
    57 def msg(s): 
    58     sys.stderr.write('  ') 
    59     sys.stderr.write(s) 
    60     sys.stderr.write('\n') 
    61     sys.stderr.flush() 
    62  
    63  
    64 class Writer: 
    65  
    66     def __init__(self, filename, overridesfile=None): 
    67         self.overrides = overridesfile and override.Overrides(overridesfile) or None 
    68         if filename: 
    69             self.out = open(filename, 'w') 
    70         else: 
    71             self.out = sys.stdout 
    72  
    73     def write(self, data): 
    74         self.out.write(data) 
    75  
    76     def close(self): 
    77         self.out.close() 
    78  
    79     def write_classdef(self, clazz): 
    80         """Write a class definition (class xx(x): pass). 
    81         First the parent classes are examined. After that its own definition 
    82         is written. It is ensured that class definitions are only written 
    83         once. 
    84         """ 
    85         if not clazz.written: 
    86             s = '' 
    87             for g in clazz.generalization: 
    88                 self.write_classdef(g) 
    89                 if s: s += ', ' 
    90                 s = s + g['name'] 
    91             if not s: s = 'object' 
    92             if not self.overrides.write_override(self, clazz['name']): 
    93                 self.write('class %s(%s): pass\n' % (clazz['name'], s)) 
    94         clazz.written = True 
    95  
    96     def write_property(self, full_name, value): 
    97         """Write a property to the file. If the property is overridden, use the 
    98         overridden value. full_name should be like Class.attribute. value is 
    99         free format text. 
    100         """ 
    101         if not self.overrides.write_override(self, full_name): 
    102             self.write('%s = %s\n' % (full_name, value)) 
    103  
    104     def write_attribute(self, a, enumerations={}): 
    105         """Write a definition for attribute a. Enumerations may be a dict 
    106         of enumerations, indexed by ID. These are used to identify enums. 
    107         """ 
    108         params = { } 
    109         type = a.typeValue and a.typeValue.get('value') 
    110         if type is None: 
    111             raise ValueError('ERROR! type is not specified for property %s.%s' % (a.class_name, a.name)) 
    112  
    113         if type.lower() == 'boolean': 
    114             # FixMe: Should this be a boolean or an integer? 
    115             # Integer is save and compattable with python2.2. 
    116             type = 'int' 
    117         elif type.lower() in ('integer', 'unlimitednatural'): 
    118             type = 'int' 
    119         elif type.lower() == 'string': 
    120             # Change to basestr for Python 2.3 
    121             type = 'str' 
    122             #type = '(str, unicode)' 
    123  
    124         default = a.defaultValue and a.defaultValue.value 
    125         # Make sure types are represented the Python way: 
    126         if default and default.lower() in ('true', 'false'): 
    127             default = default.title() # True or False... 
    128         if default is not None: 
    129             params['default'] = str(default) 
    130  
    131         lower = a.lowerValue and a.lowerValue.value 
    132         if lower and lower != '0': 
    133             params['lower'] = lower 
    134         upper = a.upperValue and a.upperValue.value 
    135         if upper and upper != '1': 
    136             params['upper'] = upper 
    137  
    138         #kind, derived, a.name, type, default, lower, upper = parse_attribute(a) 
    139  
    140         full_name = "%s.%s" % (a.class_name, a.name) 
    141         if self.overrides.has_override(full_name): 
    142             self.overrides.write_override(self, full_name) 
    143         elif eval(a.isDerived or '0'): 
    144             msg('ignoring derived attribute %s.%s: no definition' % (a.class_name, a.name)) 
    145         elif type.endswith('Kind') or type.endswith('Sort'): 
    146             e = filter(lambda e: e['name'] == type, enumerations.values())[0] 
    147             self.write_property("%s.%s" % (a.class_name, a.name), 
    148                                 "enumeration('%s', %s, '%s')" % (a.name, e.enumerates, default or e.enumerates[0])) 
    149         else: 
    150             if params: 
    151                 attribute = "attribute('%s', %s, %s)" % (a.name, type, ', '.join(map('='.join, params.items()))) 
    152             else: 
    153                 attribute = "attribute('%s', %s)" % (a.name, type) 
    154             self.write_property("%s.%s" % (a.class_name, a.name), attribute) 
    155  
    156     def write_operation(self, o): 
    157         full_name = "%s.%s" % (o.class_name, o.name) 
    158         if self.overrides.has_override(full_name): 
    159             self.overrides.write_override(self, full_name) 
    160         else: 
    161             msg("No override for operation %s" % full_name) 
    162  
    163     def write_association(self, head, tail): 
    164         """Write an association for head. False is returned if the association 
    165         is derived. 
    166         The head association end is enriched with the following attributes: 
    167             derived - association is a derived union or not 
    168             name - name of the association end (name of head is found on tail) 
    169             class_name - name of the class this association belongs to 
    170             opposite_class_name - name of the class at the other end of the assoc. 
    171             lower - lower multiplicity 
    172             upper - upper multiplicity 
    173             subsets - derived unions that use the association 
    174             redefines - redefines existing associations 
    175         Returns True if the association is written. False is returned if 
    176         the association should be handled by write_derivedunion() or 
    177         write_redefine(). 
    178         """ 
    179         navigable = head.get('class_') 
    180         if not navigable: 
    181             # from this side, the association is not navigable 
    182             return True 
    183  
    184         name = head.name 
    185         if name is None: 
    186             raise ValueError('ERROR! no name, but navigable: %s (%s.%s)' % (head.id, head.class_name, head.name)) 
    187  
    188         derived = int(head.isDerived or 0) 
    189  
    190         #print head.id, head.lowerValue 
    191         upper = head.upperValue and head.upperValue.value or '*' 
    192         lower = head.lowerValue and head.lowerValue.value or upper 
    193         if lower == '*': 
    194             lower = 0 
    195         subsets, redefines = parse_association_tags(head.taggedValue) 
    196  
    197         # Add the values found. These are used later to generate derived unions. 
    198         head.derived = derived 
    199         #head.name = name 
    200         head.class_name = head.class_['name'] 
    201         head.opposite_class_name = head.type['name'] 
    202         head.lower = lower 
    203         head.upper = upper 
    204         head.subsets = subsets 
    205         head.redefines = redefines 
    206  
    207         # Derived unions and redefines are handled separately 
    208         if derived or redefines: 
    209             return False 
    210  
    211         a = "association('%s', %s" % (name, head.opposite_class_name) 
    212         if lower not in ('0', 0): 
    213             a += ', lower=%s' % lower 
    214         if upper != '*': 
    215             a += ', upper=%s' % upper 
    216         if head.get('aggregation') == 'composite': 
    217             a += ', composite=True' 
    218  
    219         # Add the opposite property if the head itself is navigable: 
    220         navigable = tail.get('class_') 
    221         if navigable: 
    222             try: 
    223                 #o_derived, o_name = parse_association_name(tail['name']) 
    224                 o_name = tail.name 
    225                 o_derived = int(tail.isDerived or 0) 
    226             except KeyError: 
    227                 msg('ERROR! no name, but navigable: %s (%s.%s)' % 
    228                     (tail.id, tail.class_name, tail.name)) 
    229             else: 
    230                 assert not (derived and not o_derived), 'One end is derived, the other end not ???' 
    231                 a += ", opposite='%s'" % o_name 
    232  
    233         self.write_property("%s.%s" % (head.class_name, name), a + ')') 
    234         return True 
    235  
    236     def write_derivedunion(self, d): 
    237         """Write a derived union. If there are no subsets a warning 
    238         is issued. The derivedunion is still created though. 
    239         Derived unions may be created for associations that were returned 
    240         False by write_association().""" 
    241         subs = '' 
    242         for u in d.union: 
    243             if u.derived and not u.written: 
    244                 self.write_derivedunion(u) 
    245             if subs: subs += ', ' 
    246             subs += '%s.%s' % (u.class_name, u.name) 
    247         if subs: 
    248             self.write_property("%s.%s" % (d.class_name, d.name), 
    249                                 "derivedunion('%s', %s, %s, %s)" % (d.name, d.lower, d.upper == '*' and "'*'" or d.upper, subs)) 
    250         else: 
    251             if not self.overrides.has_override('%s.%s' % (d.class_name, d.name)): 
    252                 msg('no subsets for derived union: %s.%s[%s..%s]' % (d.class_name, d.name, d.lower, d.upper)) 
    253             self.write_property("%s.%s" % (d.class_name, d.name), 
    254                                 "derivedunion('%s', %s, %s)" % (d.name, d.lower, d.upper == '*' and "'*'" or d.upper)) 
    255         d.written = True 
    256  
    257     def write_redefine(self, r): 
    258         """Redefines may be created for associations that were returned 
    259         False by write_association().""" 
    260         self.write_property("%s.%s" % (r.class_name, r.name), 
    261                             "redefine('%s', %s, %s)" % (r.name, r.opposite_class_name, r.redefines)) 
    262  
    263  
    264 def parse_association_name(name): 
    265     # First remove spaces 
    266     name = name.replace(' ','') 
    267     derived = False 
    268     # Check if this is a derived union 
    269     while name and not name[0].isalpha(): 
    270         if name[0] == '/': 
    271             derived = True 
    272         name = name[1:] 
    273     return derived, name 
    274  
    275  
    276 def parse_association_tags(tag): 
    277     subsets = [] 
    278     redefines = None 
    279  
    280     # subsets has a comma separated syntax. Add all taggedValues together 
    281     if type(tag) is type([]): 
    282         tag = ', '.join(filter(None, map(getattr, tag, ['value'] * len(tag)))) 
    283     elif tag: 
    284         tag = tag.value 
    285  
    286     #print 'scanning tags: %s' % tag 
    287  
    288     if tag and tag.find('subsets') != -1: 
    289         # find the text after 'subsets': 
    290         subsets = tag[tag.find('subsets') + len('subsets'):] 
    291         # remove all whitespaces and stuff 
    292         subsets = subsets.replace(' ', '').replace('\n', '').replace('\r', '') 
    293         subsets = subsets.split(',') 
    294  
    295     if tag and tag.find('redefines') != -1: 
    296         # find the text after 'redefines': 
    297         redefines = tag[tag.find('redefines') + len('redefines'):] 
    298         # remove all whitespaces and stuff 
    299         redefines = redefines.replace(' ', '').replace('\n', '').replace('\r', '') 
    300         l = redefines.split(',') 
    301         assert len(l) == 1 
    302         redefines = l[0] 
    303  
    304     #print 'found', subsets, redefines 
    305     return subsets, redefines 
    306  
    307 def generate(filename, outfile=None, overridesfile=None): 
    308     # parse the file 
    309     all_elements = parse(filename) 
    310  
    311     def unref(val, attr): 
    312         """Resolve references. 
    313         """ 
    314         try: 
    315             refs = val.references[attr] 
    316         except KeyError: 
    317             val.references[attr] = None 
    318             return 
    319  
    320         if type(refs) is type([]): 
    321             unrefs = [] 
    322             for r in refs: 
    323                 unrefs.append(all_elements[r]) 
    324             val.references[attr] = unrefs 
    325         else: 
    326             val.references[attr] = all_elements[refs] 
    327  
    328     writer = Writer(outfile, overridesfile) 
    329  
    330     # extract usable elements from all_elements. Some elements are given 
    331     # some extra attributes. 
    332     classes = { } 
    333     enumerations = { } 
    334     generalizations = { } 
    335     associations = { } 
    336     properties = { } 
    337     operations = { } 
    338     for key, val in all_elements.items(): 
    339         # Find classes, *Kind (enumerations) are given special treatment 
    340         if isinstance(val, element): 
    341             if val.type == 'Class' and val.get('name'): 
    342                 if val['name'].endswith('Kind') or val['name'].endswith('Sort'): 
    343                     enumerations[key] = val 
    344                 else: 
    345                     classes[key] = val 
    346                     # Add extra properties for easy code generation: 
    347                     val.specialization = [] 
    348                     val.generalization = [] 
    349                     val.written = False 
    350             elif val.type == 'Generalization': 
    351                 generalizations[key] = val 
    352             elif val.type == 'Association': 
    353                 associations[key] = val 
    354             elif val.type == 'Property': 
    355                 properties[key] = val 
    356                 unref(val, 'typeValue') 
    357                 unref(val, 'defaultValue') 
    358                 unref(val, 'lowerValue') 
    359                 unref(val, 'upperValue') 
    360                 unref(val, 'taggedValue') 
    361             elif val.type == 'Operation': 
    362                 operations[key] = val 
    363  
    364     # find inheritance relationships 
    365     for g in generalizations.values(): 
    366         #assert g.specific and g.general 
    367         specific = g['specific'] 
    368         general = g['general'] 
    369         classes[specific].generalization.append(classes[general]) 
    370         classes[general].specialization.append(classes[specific]) 
    371  
    372     # add values to enumerations: 
    373     for e in enumerations.values(): 
    374         values = [] 
    375         for key in e['ownedAttribute']: 
    376             values.append(str(properties[key]['name'])) 
    377         e.enumerates = tuple(values) 
    378  
    379     # create file header 
    380     writer.write(header) 
    381  
    382     # create class definitions 
    383     for c in classes.values(): 
    384         writer.write_classdef(c) 
    385  
    386     # create attributes and enumerations 
    387     for c in classes.values(): 
    388         for p in c.get('ownedAttribute') or []: 
    389             a = properties.get(p) 
    390             # set class_name, since write_attribute depends on it 
    391             a.class_name = c['name'] 
    392             if not a.get('association'): 
    393                 writer.write_attribute(a, enumerations) 
    394  
    395     # create associations, derivedunions are held back 
    396     derivedunions = { } # indexed by name in stead of id 
    397     redefines = [ ] 
    398     for a in associations.values(): 
    399         ends = [] 
    400         for end in a['memberEnd']: 
    401             end = properties[end] 
    402             end.type = classes[end['type']] 
    403             end.class_ = end.get('class_') and classes[end['class_']] or None 
    404             #assert end.type is not end.class_ 
    405             #if not end.get('lowerValue'): 
    406                 #end.lowerValue = end.lowerValue.get('value') or '' 
    407             #else: 
    408                 #end.lowerValue = '' 
    409             ends.append(end) 
    410  
    411         for e1, e2 in ((ends[0], ends[1]), (ends[1], ends[0])): 
    412             if not writer.write_association(e1, e2): 
    413                 # At this point the association is parsed, but not written. 
    414                 # assure that derived unions do not get overwritten 
    415                 if e1.redefines: 
    416                     redefines.append(e1) 
    417                 else: 
    418                     assert not derivedunions.get(e1.name), "%s.%s is already in derived union set in class %s" % (e1.class_name, e1.name, derivedunions.get(e1.name).class_name) 
    419                     derivedunions[e1.name] = e1 
    420                     e1.union = [ ] 
    421                     e1.written = False 
    422  
    423  
    424     # create derived unions, first link the association ends to the d 
    425     for a in [v for v in properties.values() if v.subsets]: 
    426         for s in a.subsets or (): 
    427             try: 
    428                 derivedunions[s].union.append(a) 
    429             except KeyError: 
    430                 msg('not a derived union: %s.%s' % (a.class_name, s)) 
    431  
    432     for d in derivedunions.values(): 
    433         writer.write_derivedunion(d) 
    434  
    435     for r in redefines or (): 
    436         msg('redefining %s -> %s.%s' % (r.redefines, r.class_name, r.name)) 
    437         writer.write_redefine(r) 
    438  
    439     # create operations 
    440     for c in classes.values(): 
    441         for p in c.get('ownedOperation') or []: 
    442             o = operations.get(p) 
    443             o.class_name = c['name'] 
    444             writer.write_operation(o) 
    445  
    446     writer.close() 
    447  
    448 if __name__ == '__main__': 
    449     import doctest 
    450     doctest.testmod() 
    451     generate('uml2.gaphor') 
     70# vim:sw=4:et 
  • gaphor/trunk/utils/command/install_mo.py

    r1139 r1140  
    1414except ImportError: 
    1515    from distutils.core import Command 
    16 from distutils.util import change_root 
     16#from distutils.util import change_root 
    1717import os.path 
    1818 
     
    3737        if self.install_dir is None: 
    3838            self.set_undefined_options('install', 
    39                                        ('prefix', 'install_dir')) 
    40             self.install_dir = os.path.join(self.install_dir, 'share'
     39                                       ('install_base', 'install_dir')) 
     40            self.install_dir = os.path.join(self.install_dir, 'share', 'locale'
    4141 
    4242        self.name = self.distribution.get_name() 
  • gaphor/trunk/utils/command/override.py

    r219 r1140  
    11# vim:sw=4:et 
    2 """This file contains code for loading up an override file.  The override file 
     2""" 
     3This file contains code for loading up an override file.  The override file 
    34provides implementations of functions where the code generator could not 
    45do its job correctly.