Changeset 1140
- Timestamp:
- 02/28/07 06:09:17 (2 years ago)
- Files:
-
- gaphor/trunk/setup.py (modified) (5 diffs)
- gaphor/trunk/utils/command/__init__.py (added)
- gaphor/trunk/utils/command/build_mo.py (moved) (moved from gaphor/trunk/utils/build_mo.py)
- gaphor/trunk/utils/command/build_pot.py (moved) (moved from gaphor/trunk/utils/build_pot.py)
- gaphor/trunk/utils/command/build_uml.py (moved) (moved from gaphor/trunk/utils/genUML2.py) (1 diff)
- gaphor/trunk/utils/command/build_version.py (added)
- gaphor/trunk/utils/command/gen_uml.py (added)
- gaphor/trunk/utils/command/install_mo.py (moved) (moved from gaphor/trunk/utils/install_mo.py) (2 diffs)
- gaphor/trunk/utils/command/install_version.py (added)
- gaphor/trunk/utils/command/msgfmt.py (moved) (moved from gaphor/trunk/utils/msgfmt.py)
- gaphor/trunk/utils/command/override.py (moved) (moved from gaphor/trunk/utils/override.py) (1 diff)
- gaphor/trunk/utils/command/pygettext.py (moved) (moved from gaphor/trunk/utils/pygettext.py)
- gaphor/trunk/utils/command/run.py (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
gaphor/trunk/setup.py
r1139 r1140 47 47 AddPackagePath('gaphor.UML', 'build/lib/gaphor/UML') 48 48 49 49 50 from distutils.core import setup, Command 51 from distutils.command.build import build 52 from distutils.command.install import install 50 53 from distutils.command.build_py import build_py 51 54 from distutils.command.install_lib import install_lib … … 53 56 from distutils.util import byte_compile 54 57 from 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 58 from utils.command.build_mo import build_mo 59 from utils.command.build_pot import build_pot 60 from utils.command.install_mo import install_mo 61 from utils.command.build_uml import build_uml 62 from utils.command.build_version import build_version 63 from utils.command.install_version import install_version 64 from utils.command.run import run 58 65 59 66 str_version = sys.version[:3] … … 64 71 65 72 66 class config _Gaphor(Command):73 class config(Command): 67 74 description="Configure Gaphor" 68 75 … … 154 161 build.sub_commands.insert(0, ('config', None)) 155 162 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 164 class tests(Command): 391 165 392 166 description = 'Run the Gaphor test suite.' … … 469 243 scripts=['bin/gaphor', 'bin/gaphorconvert'], 470 244 471 cmdclass={'config': config _Gaphor,245 cmdclass={'config': config, 472 246 'build_uml': build_uml, 473 247 'build_version': build_version, 248 'install_version': install_version, 474 249 'build_mo': build_mo, 475 250 'build_pot': build_pot, 476 251 'install_mo': install_mo, 477 'run': run _Gaphor,478 'tests': tests _Gaphor252 'run': run, 253 'tests': tests 479 254 }, 480 255 # app=['gaphor-osx.py'], gaphor/trunk/utils/command/build_uml.py
r1139 r1140 1 1 #!/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 """ 3 This file provides the code generator which transforms gaphor/UML/uml2.gaphor 4 into gaphor/UML/uml2.py. 9 5 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 6 Also a distutils tool, build_uml, is provided. 20 7 """ 21 8 22 # Make getitem behave more politely 23 base.__real_getitem__ = base.__getitem__ 9 ## 10 ## The Command 11 ## 24 12 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" 13 import os.path 14 from distutils.core import Command 15 from distutils.command.build import build 16 from distutils.util import byte_compile 17 from distutils.dep_util import newer 36 18 37 19 38 import re 20 class build_uml(Command): 39 21 40 pattern = r'([A-Z])' 41 sub = r'_\1' 22 description = "Generate gaphor/UML/uml2.py." 42 23 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 ] 53 28 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 67 build.sub_commands.append(('build_uml', None)) 55 68 56 69 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 14 14 except ImportError: 15 15 from distutils.core import Command 16 from distutils.util import change_root16 #from distutils.util import change_root 17 17 import os.path 18 18 … … 37 37 if self.install_dir is None: 38 38 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') 41 41 42 42 self.name = self.distribution.get_name() gaphor/trunk/utils/command/override.py
r219 r1140 1 1 # vim:sw=4:et 2 """This file contains code for loading up an override file. The override file 2 """ 3 This file contains code for loading up an override file. The override file 3 4 provides implementations of functions where the code generator could not 4 5 do its job correctly.
