summaryrefslogtreecommitdiff
path: root/pyreverse
diff options
context:
space:
mode:
authorEmile Anclin <emile.anclin@logilab.fr>2008-09-08 17:03:54 +0200
committerEmile Anclin <emile.anclin@logilab.fr>2008-09-08 17:03:54 +0200
commit78ad977bb7fdb6b77232e16a6f25b36ee35755e7 (patch)
treec82f02022506ff96d63cbda446468a802b1a55b1 /pyreverse
parenta47cc99e3f61f2cf7ec0ba7377ebf3a07cb3acef (diff)
downloadpylint-78ad977bb7fdb6b77232e16a6f25b36ee35755e7.tar.gz
adapt pyreverse for inclusion into pylint
Diffstat (limited to 'pyreverse')
-rw-r--r--pyreverse/diadefslib.py124
-rw-r--r--pyreverse/diagrams.py2
-rw-r--r--pyreverse/main.py120
-rw-r--r--pyreverse/utils.py33
-rw-r--r--pyreverse/writer.py2
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