diff options
| author | Emile Anclin <emile.anclin@logilab.fr> | 2008-09-08 17:03:54 +0200 |
|---|---|---|
| committer | Emile Anclin <emile.anclin@logilab.fr> | 2008-09-08 17:03:54 +0200 |
| commit | 78ad977bb7fdb6b77232e16a6f25b36ee35755e7 (patch) | |
| tree | c82f02022506ff96d63cbda446468a802b1a55b1 /pyreverse | |
| parent | a47cc99e3f61f2cf7ec0ba7377ebf3a07cb3acef (diff) | |
| download | pylint-78ad977bb7fdb6b77232e16a6f25b36ee35755e7.tar.gz | |
adapt pyreverse for inclusion into pylint
Diffstat (limited to 'pyreverse')
| -rw-r--r-- | pyreverse/diadefslib.py | 124 | ||||
| -rw-r--r-- | pyreverse/diagrams.py | 2 | ||||
| -rw-r--r-- | pyreverse/main.py | 120 | ||||
| -rw-r--r-- | pyreverse/utils.py | 33 | ||||
| -rw-r--r-- | pyreverse/writer.py | 2 |
5 files changed, 143 insertions, 138 deletions
diff --git a/pyreverse/diadefslib.py b/pyreverse/diadefslib.py index 8a98d68..263e2e8 100644 --- a/pyreverse/diadefslib.py +++ b/pyreverse/diadefslib.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""handle diagram generation options with diadefs or with default generator +"""handle diagram generation options for class diagram or default diagrams """ import sys @@ -21,117 +21,7 @@ import sys from logilab import astng from logilab.astng.utils import LocalsVisitor -from pyreverse.extensions.xmlconf import DictSaxHandlerMixIn, PrefReader -from pyreverse.extensions.diagrams import PackageDiagram, ClassDiagram - -# diadefs xml files utilities ################################################# - -class DiaDefsSaxHandler(DictSaxHandlerMixIn): - """ - definition of the structure of the diadef file, which will enable the MI - to fill the DiaDefs dictionary - """ - _MASTER = {} - _S_LIST = ('class-diagram', 'package-diagram', 'state-diagram', - 'class', 'package') - _LIST = () - _KEY = ('owner', 'name', 'include') - _CB = {} - - -def read_diadefs_file(filename): - """read a diadef file and return the DiaDef dictionnary""" - diadefs = {} - reader = PrefReader(DiaDefsSaxHandler, diadefs) - try: - reader.fromFile(filename) - except: - import traceback - traceback.print_exc() - print >> sys.stderr, 'error while reading file %s' % filename - return diadefs - - -class DiadefsResolverHelper: - """fetch objects in the project according to the diagram definition - from a XML file - """ - def __init__(self, project, linker, config): - self.mode = config.mode - self._p = project - self.linker = linker - - def resolve_packages(self, diadef, diagram=None): - """take a package diagram definition dictionnary and return matching - objects - """ - if diagram is None: - diagram = PackageDiagram(diadef.get('name', - 'No name packages diagram'), self.mode) - for package in diadef['package']: - name = package['name'] - module = self.get_module(name) - if module is None: - continue - self.linker.visit(module) - diagram.add_object(name, module) - if package.get('include', 'no') != 'no': - for node, title in self.get_classes(module): - self.linker.visit(node) - diagram.add_object(title, node) - self.resolve_classes(diadef, diagram) - return diagram - - def resolve_classes(self, diadef, diagram=None): - """take a class diagram definition dictionnary and return a Diagram - instance (given in paramaters or created) - """ - class_defs = diadef.get('class', []) - if diagram is None: - diagram = ClassDiagram(diadef.get('name', - 'No name classes diagram'), self.mode) - for klass in class_defs: - name, module = klass['name'], klass.get('owner', '') - c = self.get_class(module, name) - if c is None: - continue - self.linker.visit(c) - diagram.add_object(name, c) - return diagram - - - def get_classes(self, module): - """return all class defined in the given astng module - """ - classes = [] - for object in module.values(): - if isinstance(object, astng.Class): - classes.append((object, object.name)) - return classes - - def get_module(self, name): - """return the astng module corresponding to name if it exists in the - current project - """ - try: - return self._p.get_module(name) - except KeyError: - print >> sys.stderr, 'Warning: no module named %s' % name - - def get_class(self, module, name): - """return the astng class corresponding to module.name if it exists in - the current project - """ - try: - module = self._p.get_module(module) - except KeyError: - print >> sys.stderr, 'Warning: no module named %s' % module - else: - try: - return module[name] - except KeyError: - print >> sys.stderr, 'Warning: no module class %s in %s' % ( - name, module) +from pylint.pyreverse.diagrams import PackageDiagram, ClassDiagram # diagram generators ########################################################## @@ -315,21 +205,13 @@ class DiadefsHandler: self.config = config def get_diadefs(self, project, linker): - """get the diagrams configuration data, either from a specified file or - generated + """get the diagrams configuration data :param linker: astng.inspector.Linker(IdGeneratorMixIn, LocalsVisitor) :param project: astng.manager.Project """ # read and interpret diagram definitions (Diadefs) diagrams = [] - if self.config.diadefs_file is not None: - diadefs = read_diadefs_file(self.config.diadefs_file) - resolver = DiadefsResolverHelper(project, linker, self.config) - for class_diagram in diadefs.get('class-diagram', ()): - resolver.resolve_classes(class_diagram) - for package_diagram in diadefs.get('package-diagram', ()): - resolver.resolve_packages(package_diagram) generator = ClassDiadefGenerator(linker, self) for klass in self.config.classes: diagrams.append(generator.class_diagram(project, klass)) diff --git a/pyreverse/diagrams.py b/pyreverse/diagrams.py index 426d4e7..32a4640 100644 --- a/pyreverse/diagrams.py +++ b/pyreverse/diagrams.py @@ -17,7 +17,7 @@ """ from logilab import astng -from pyreverse.utils import is_interface, FilterMixIn +from pylint.pyreverse.utils import is_interface, FilterMixIn def set_counter(value): """Figure counter (re)set""" diff --git a/pyreverse/main.py b/pyreverse/main.py index e241f79..20b60b0 100644 --- a/pyreverse/main.py +++ b/pyreverse/main.py @@ -1,4 +1,4 @@ -# Copyright (c) 2008 LOGILAB S.A. (Paris, FRANCE). +# # Copyright (c) 2000-2008 LOGILAB S.A. (Paris, FRANCE). # http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This program is free software; you can redistribute it and/or modify it under @@ -14,14 +14,116 @@ # this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ -Pyreverse command line tool. + %prog [options] <packages> + + create UML diagrams for classes and modules in <packages> """ -def run(args): - from logilab.common.clcommands import main_run - from pyreverse import commands - main_run(args, __doc__) +import sys +from logilab.common.configuration import ConfigurationMixIn +from logilab.astng.manager import astng_wrapper, ASTNGManager +from logilab.astng.inspector import Linker + +from pylint.pyreverse.diadefslib import DiadefsHandler +from pylint.pyreverse import writer +from pylint.pyreverse.utils import insert_default_options + +OPTIONS = ( +("filter-mode", + dict(short='f', default='PUB_ONLY', dest='mode', type='string', + action='store', metavar='<mode>', + help="""filter attributes and functions according to + <mode>. Correct modes are : + 'PUB_ONLY' filter all non public attributes + [DEFAULT], equivalent to PRIVATE+SPECIAL_A + 'ALL' no filter + 'SPECIAL' filter Python special functions + except constructor + 'OTHER' filter protected and private + attributes""")), +#("diadefs-file", +#dict(short='d', metavar="<file>", action="store", + #help="create diagram according to the diagrams definitions in <file>")), +("class", +dict(short='c', action="append", metavar="<class>", dest="classes", default=[], + help="create a class diagram with all classes related to <class>;\ + this uses by default the options -ASmy")), + +("show-ancestors", +dict(short="a", action="store", metavar='<ancestor>', type='int', + help='show <ancestor> generations of ancestor classes not in <projects>')), +("all-ancestors", +dict(short="A", default=None, + help="show all ancestors off all classes in <projects>") ), +("show-associated", +dict(short='s', action="store", metavar='<ass_level>', type='int', + help='show <ass_level> levels of associated classes not in <projects>')), +("all-associated", +dict(short='S', default=None, + help='show recursively all associated off all associated classes')), + +("show-builtin", +dict(short="b", action="store_true", default=False, + help='include builtin objects in representation of classes')), + +("module-names", +dict(short="m", default=None, type='yn', metavar='[yn]', + help='include module name in representation of classes')), +# TODO : generate dependencies like in pylint +#("package-dependencies", +#dict(short="M", action="store", metavar='<package_depth>', type='int', + #help='show <package_depth> module dependencies beyond modules in \ +#<projects> (for the package diagram)')), +("only-classnames", +dict(short='k', action="store_true", default=False, + help="don't show attributes and methods in the class boxes; \ +this disables -f values")), +("output", dict(short="o", dest="output_format", action="store", + default="dot", metavar="<format>", + help="create a *.<format> output file if format available.")), +) +#( ('quiet', + #dict(help='run quietly', action='store_true', short='q')), ) + + +class PyreverseCommand(ConfigurationMixIn):# OptionsManagerMixIn + """base class providing common behaviour for pyreverse commands""" + + name = 'pyreverse' + + options = OPTIONS + priority = 0 + + def __init__(self, args): + ConfigurationMixIn.__init__(self, usage=__doc__) + insert_default_options() + self.manager = ASTNGManager() + self.register_options_provider(self.manager) + args = self.load_command_line_configuration() + self.run(args) + + def run(self, args): + """checking argmuents and run project""" + if not args: + print self.help() + return + self.project = self.manager.project_from_files(args, astng_wrapper) + self.linker = Linker(self.project, tag=True) + handler = DiadefsHandler(self.config) + diadefs = handler.get_diadefs(self.project, self.linker) + if self.config.output_format == "vcg": + writer.VCGWriter(self.config).write(diadefs) + else: + writer.DotWriter(self.config).write(diadefs) + + +#register_commands( (DiagramCommand,) ) + +class Run: + """pyreverse main class""" + def __init__(self, args): + """run pyreverse""" + pyreverse = PyreverseCommand(args) -if __name__ == "__main__": - import sys - run(sys.argv[1:]) +if __name__ == '__main__': + Run(sys.argv[1:]) diff --git a/pyreverse/utils.py b/pyreverse/utils.py index f3f2374..1dc7273 100644 --- a/pyreverse/utils.py +++ b/pyreverse/utils.py @@ -19,17 +19,38 @@ generic classes/functions for pyreverse core/extensions import sys import re +import os -from pyreverse.__pkginfo__ import version +########### pyreverse option utils ############################## -def time_tag(): + +RCFILE = '.pyreverserc' + +def get_default_options(): + """ + Read config file and return list of options """ - return a timestamp as string + options = [] + home = os.environ.get('HOME', '') + if home: + rcfile = os.path.join(home, RCFILE) + try: + options = open(rcfile).read().split() + except IOError: + pass # ignore if no config file found + return options + +def insert_default_options(): + """insert default options to sys.argv """ - from time import time, localtime, strftime - return strftime('%b %d at %T', localtime(time())) + options = get_default_options() + options.reverse() + for arg in options: + sys.argv.insert(1, arg) + + -# astng utilities ############################################################# +# astng utilities ########################################################### SPECIAL = re.compile('^__[A-Za-z0-9]+[A-Za-z0-9_]*__$') PRIVATE = re.compile('^__[_A-Za-z0-9]*[A-Za-z0-9]+_?$') diff --git a/pyreverse/writer.py b/pyreverse/writer.py index 7d56d4c..e18dd65 100644 --- a/pyreverse/writer.py +++ b/pyreverse/writer.py @@ -21,7 +21,7 @@ Utilities for creating VCG and Dot diagrams. from logilab.common.vcgutils import VCGPrinter from logilab.common.graph import DotBackend -from pyreverse.utils import is_exception +from pylint.pyreverse.utils import is_exception class DiagramWriter: """base class for writing project diagrams |
