Beispiel #1
0
    def test01(self):
        """
        """
        FILE = 'python-in/testmodule08_multiple_inheritance.py'

        #self.p, debuginfo = old_parser(FILE)
        self.p, debuginfo = new_parser(FILE)

        #print self.p

        # -------------------------------------------------------

        gotevent1 = 0
        gotevent2 = 0
        gotevent3 = 0
        gotevent4 = 0
        gotevent5 = 0
        gotevent6 = 0
        gotevent7 = 0

        for classname, classentry in self.p.classlist.items():
            if classname == 'Fred':
                gotevent1 = 1
                assert classentry.classesinheritsfrom == ['Mary', 'Sam'], classentry.classesinheritsfrom

            if classname == 'MarySam':
                gotevent3 = False  # should not get this


        assert gotevent1
        assert not gotevent3
Beispiel #2
0
def parse_source(source_code, options):
    with tempfile.NamedTemporaryFile(
            mode="wt") as temp:  # TODO use streams not temporary files
        temp.write(source_code)
        temp.flush()
        pmodel, debuginfo = new_parser(temp.name, options)
    return pmodel, debuginfo
Beispiel #3
0
    def test01(self):
        """
        """
        FILE = PYTHON_CODE_EXAMPLES_TO_PARSE + "testmodule_bug_pyplecs.py"

        # Can also run using
        # python3 pynsource-cli.py --mode 3 --graph tests/python-in/testmodule_bug_pyplecs.py

        # create a html log file to contain html info
        log = LogWriter(FILE, print_to_console=False)
        log.out_html_header()

        # Normally debug info is false for performance reasons, so turn it on temporarily and restore it later
        old_debug_info_value = DEBUGINFO()
        set_DEBUGINFO(True)
        try:
            self.p, debuginfo = new_parser(FILE, log, options={"mode": 3})
        finally:
            set_DEBUGINFO(old_debug_info_value)

        log.out("<hr><h1>Errors:</h1>")
        log.out_wrap_in_html(self.p.errors)
        log.out("<hr><h1>debuginfo:</h1>")

        log.out(debuginfo)
        log.out_html_footer()
        log.finish()

        self.assertEqual(self.p.errors, "")
        print(self.p)
Beispiel #4
0
    def execute(self):
        workspace_was_empty: bool = len(self.context.displaymodel.graph.nodes) == 0
        if self.files:
            for f in self.files:
                # pmodel, debuginfo = old_parser(f)
                # pmodel, debuginfo = new_parser(f)
                mode = getattr(self, "mode", 2)
                # print(f"Importing Python in syntax mode {mode}")
                pmodel, debuginfo = new_parser(f, options={"mode": mode})
                if pmodel.errors:
                    # print(pmodel.errors)
                    self.context.wxapp.MessageBox(pmodel.errors)

                # from parsing.dump_pmodel import dump_old_structure
                # print(dump_old_structure(pmodel))

                self.context.displaymodel.build_graphmodel(pmodel)
                # self.context.displaymodel.Dump(msg="import, after build_graphmodel")

            # translatecoords being True is the culprit which keeps resetting the node positions
            self.context.umlcanvas.displaymodel.build_view(translatecoords=False)
            # self.context.displaymodel.Dump(msg="import, after build_view")

            self.context.umlcanvas.GetDiagram().ShowAll(1)  # need this, yes

            if workspace_was_empty:  # don't layout if importing into canvas with existing shapes
                self.context.umlcanvas.layout_and_position_shapes()
            else:
                # At least remove overlaps
                self.context.overlap_remover.RemoveOverlaps(watch_removals=True)

            self.context.umlcanvas.mega_refresh()

            # self.context.wxapp.refresh_plantuml_view()
            wx.PostEvent(self.context.frame, RefreshPlantUmlEvent())
Beispiel #5
0
def parse_source(source_code, options, html_debug_root_name=""):
    old_debug_info_value = DEBUGINFO()

    with tempfile.NamedTemporaryFile(
            mode="wt") as temp:  # TODO use streams not temporary files
        temp.write(source_code)
        temp.flush()

        if html_debug_root_name:
            # Normally debug info is false for performance reasons, so turn it on temporarily and restore it later
            set_DEBUGINFO(True)

            # create a html log file to contain html info
            log = LogWriter(html_debug_root_name, print_to_console=False)
            log.out_html_header()
        else:
            log = None

        try:
            pmodel, debuginfo = new_parser(temp.name, log=log, options=options)
        finally:
            set_DEBUGINFO(old_debug_info_value)

        if html_debug_root_name:
            log.out("<hr><h1>Errors:</h1>")
            log.out_wrap_in_html(pmodel.errors)
            log.out("<hr><h1>debuginfo:</h1>")
            log.out(debuginfo)
            log.out_html_footer()
            log.finish()
            print(f"html debug info is in '{log.out_filename}'")

    return pmodel, debuginfo
Beispiel #6
0
    def test01(self):
        """
        """
        FILE = 'python-in/testmodule08_multiple_inheritance.py'

        #self.p, debuginfo = old_parser(FILE)
        self.p, debuginfo = new_parser(FILE)

        #print self.p

        # -------------------------------------------------------

        gotevent1 = 0
        gotevent2 = 0
        gotevent3 = 0
        gotevent4 = 0
        gotevent5 = 0
        gotevent6 = 0
        gotevent7 = 0

        for classname, classentry in self.p.classlist.items():
            if classname == 'Fred':
                gotevent1 = 1
                assert classentry.classesinheritsfrom == [
                    'Mary', 'Sam'
                ], classentry.classesinheritsfrom

            if classname == 'MarySam':
                gotevent3 = False  # should not get this

        assert gotevent1
        assert not gotevent3
Beispiel #7
0
    def test01(self):
        """
        """
        FILE = PYTHON_CODE_EXAMPLES_TO_PARSE + "testmodule08_multiple_inheritance.py"

        # self.p, debuginfo = old_parser(FILE)
        self.p, debuginfo = new_parser(FILE)

        # print self.p

        # -------------------------------------------------------

        gotevent1 = 0
        gotevent2 = 0
        gotevent3 = 0
        gotevent4 = 0
        gotevent5 = 0
        gotevent6 = 0
        gotevent7 = 0

        for classname, classentry in list(self.p.classlist.items()):
            if classname == "Fred":
                gotevent1 = 1
                assert classentry.classesinheritsfrom == [
                    "Mary",
                    "Sam",
                ], classentry.classesinheritsfrom

            if classname == "MarySam":
                gotevent3 = False  # should not get this

        assert gotevent1
        assert not gotevent3
Beispiel #8
0
    def execute(self):
        assert self.files

        # these are tuples between class names.
        self.context.model.ClearAssociations(
        )  # WHY DO WE WANT TO DESTROY THIS VALUABLE INFO?

        if self.files:
            for f in self.files:
                #pmodel, debuginfo = old_parser(f)
                pmodel, debuginfo = new_parser(f)

                #from parsing.dump_pmodel import dump_old_structure
                #print dump_old_structure(pmodel)

                self.context.model.ConvertParseModelToUmlModel(pmodel)

                #p = PySourceAsJava()
                #p.optionModuleAsClass = 0
                #p.verbose = 0
                #p.Parse(f)
                #self.context.model.ConvertParseModelToUmlModel(p)

        self.context.umlwin.build_view()

        # Layout
        self.context.umlwin.layout_and_position_shapes()
    def test_bug_pyplecs(self):
        """
        """
        # breakpoint()
        FILE = PYTHON_CODE_EXAMPLES_TO_PARSE + "testmodule_bug_pyplecs.py"

        # Can also run using
        # python3 pynsource-cli.py --mode 3 --graph tests/python-in/testmodule_bug_pyplecs.py

        # create a html log file to contain html info
        log = LogWriter(FILE, print_to_console=False)
        log.out_html_header()

        # Normally debug info is false for performance reasons, so turn it on temporarily and restore it later
        old_debug_info_value = DEBUGINFO()
        set_DEBUGINFO(True)
        try:
            pmodel, debuginfo = new_parser(FILE, log, options={"mode": 3})
        finally:
            set_DEBUGINFO(old_debug_info_value)

        # this log finishing is all written out automatically in new_parser / parse / _convert_ast_to_old_parser
        # if there is an error- otherwise we have to do it ourselves.
        #
        if not pmodel.errors:
            # log.out("<hr><h1>Errors (shouldn't be any):</h1>")
            # log.out_wrap_in_html(pmodel.errors)
            log.out("<hr><h1>debuginfo:</h1>")
            log.out(debuginfo)
            log.out_html_footer()
            log.finish()

        self.assertEqual(pmodel.errors, "")
Beispiel #10
0
    def execute(self):
        assert self.files
        
        # these are tuples between class names.
        self.context.model.ClearAssociations()       # WHY DO WE WANT TO DESTROY THIS VALUABLE INFO?

        if self.files:
            for f in self.files:
                #pmodel, debuginfo = old_parser(f)
                pmodel, debuginfo = new_parser(f)
                
                #from parsing.dump_pmodel import dump_old_structure
                #print dump_old_structure(pmodel)
                
                self.context.model.ConvertParseModelToUmlModel(pmodel)

                #p = PySourceAsJava()
                #p.optionModuleAsClass = 0
                #p.verbose = 0
                #p.Parse(f)
                #self.context.model.ConvertParseModelToUmlModel(p)

        self.context.umlwin.build_view()

        # Layout
        self.context.umlwin.layout_and_position_shapes()
Beispiel #11
0
def reverse_engineer(files, mode, graph, methods_list, prop_decorator,
                     version):
    """Pynsource CLI - Reverse engineer python source code into UML

    This command line tool doesn't actualy generate diagrams, but it does parse Python code into the 
    underlying 'pmodel' (parse model) that the Pynsource GUI graphic diagrammer uses.  Used for debugging.
    
    Examples of use:

        python3 ./src/pynsource-cli.py a.py b.py

        python3 ./src/pynsource-cli.py --graph src/common/command_pattern.py

        python3 ./src/pynsource-cli.py --methods-list src/common/*.py

    """

    if version:
        click.echo(f"Pynsource CLI version {APP_VERSION}")

    click.echo(f"Files to parse: {files}")
    # click.echo(graph)

    # Expansion of files seems to happen magically via bash - need to check with windows
    # But if running via pycharm wildcards are not expanded, so play it safe and glob
    globbed = []
    for param in files:
        files = glob.glob(param)
        globbed += files
    click.echo(globbed)

    if graph:
        displaymodel = DisplayModel(canvas=None)

    for f in globbed:
        pmodel, debuginfo = new_parser(f,
                                       options={
                                           "mode":
                                           mode,
                                           "TREAT_PROPERTY_DECORATOR_AS_PROP":
                                           prop_decorator
                                       })
        if pmodel.errors:
            print(pmodel.errors)

        if methods_list:  # Dump simple list of methods
            click.echo(dump_pmodel_methods(pmodel))

        else:  # Dump table of underlying pmodel
            assert f == pmodel.filename
            click.echo(f"Parse model for '{pmodel.filename}':")
            click.echo(dump_pmodel(pmodel))

            if graph:  # Dump table of display model
                displaymodel.build_graphmodel(pmodel)  # will append

    if graph:
        displaymodel.Dump(
            msg="Final display model Graph containing all parse models:")
Beispiel #12
0
    def Parse(self, file):
        if self.ast_parsing:
            pmodel, debuginfo = new_parser(file)
        else:
            options = {"optionModuleAsClass": self.optionModuleAsClass}
            pmodel, debuginfo = old_parser(file, options)

        self.pmodel = pmodel  # remember the parse model

        # break apart pmodel so that its attributes are on the report generator itself (legacy yukiness)
        self.classlist = pmodel.classlist
        self.modulemethods = pmodel.modulemethods
Beispiel #13
0
    def execute(self):
        workspace_was_empty: bool = len(
            self.context.displaymodel.graph.nodes) == 0
        pmodels = []
        msgs = ""
        if self.files:
            for f in self.files:
                # pmodel, debuginfo = old_parser(f)
                # pmodel, debuginfo = new_parser(f)
                mode = getattr(self, "mode", 2)
                # print(f"Importing Python in syntax mode {mode}")
                pmodel, debuginfo = new_parser(f, options={"mode": mode})
                if pmodel.errors:
                    # print(pmodel.errors)
                    msgs += pmodel.errors + "\n"
                else:
                    pmodels.append(pmodel)

                # from parsing.dump_pmodel import dump_old_structure
                # print(dump_old_structure(pmodel))

                self.context.displaymodel.build_graphmodel(pmodel)
                # self.context.displaymodel.Dump(msg="import, after build_graphmodel")

            msgs += "\n"
            for pmodel in pmodels:
                msgs += f"{os.path.basename(pmodel.filename)} detected {len(pmodel.classlist)} classes.\n"

            if msgs:
                dlg = wx.MessageDialog(self.context.frame, msgs,
                                       "Import Notes", wx.ICON_WARNING)
                dlg.ShowModal()

            # translatecoords being True is the culprit which keeps resetting the node positions
            self.context.umlcanvas.displaymodel.build_view(
                translatecoords=False)
            # self.context.displaymodel.Dump(msg="import, after build_view")

            self.context.umlcanvas.GetDiagram().ShowAll(1)  # need this, yes

            if workspace_was_empty:  # don't layout if importing into canvas with existing shapes
                self.context.umlcanvas.layout_and_position_shapes()
            else:
                # At least remove overlaps
                self.context.overlap_remover.RemoveOverlaps(
                    watch_removals=True)

            self.context.umlcanvas.mega_refresh()

            # self.context.wxapp.refresh_plantuml_view()
            wx.PostEvent(self.context.frame, RefreshPlantUmlEvent())
Beispiel #14
0
def test():
    # FILE = "tests/python-in/testmodule01.py"
    FILE = "tests/python-in/testmodule66.py"

    strategy = "ast_via_api"  # 'old' or 'old_via_api'
    if strategy == "old":
        p = PynsourcePythonParser()
        # p.optionModuleAsClass = True
        p.Parse(FILE)
        pmodel = p.pmodel
    elif strategy == "old_via_api":
        pmodel, debuginfo = old_parser(FILE)
    elif strategy == "ast_via_api":
        pmodel, debuginfo = new_parser(FILE)

    print((dump_old_structure(pmodel)))  # TODO this could be another generate code reporter plugin
Beispiel #15
0
    def test_parse_power_operator(self):
        """
        """
        FILE = 'python-in/testmodule11_incoming_bugs.py'

        #self.p, debuginfo = old_parser(FILE)
        self.p, debuginfo = new_parser(FILE)

        #print self.p

        # -------------------------------------------------------

        gotevent1 = 0
        gotevent2 = 0

        for classname, classentry in self.p.classlist.items():
            if classname == 'Incoming1':
                gotevent1 = 1

        assert gotevent1
Beispiel #16
0
    def test_parse_power_operator(self):
        """
        """
        FILE = PYTHON_CODE_EXAMPLES_TO_PARSE + "testmodule11_incoming_bugs.py"

        # self.p, debuginfo = old_parser(FILE)
        self.p, debuginfo = new_parser(FILE)

        # print self.p

        # -------------------------------------------------------

        gotevent1 = 0
        gotevent2 = 0

        for classname, classentry in list(self.p.classlist.items()):
            if classname == "Incoming1":
                gotevent1 = 1

        assert gotevent1
Beispiel #17
0
    def test_parse_power_operator(self):
        """
        """
        FILE = 'python-in/testmodule11_incoming_bugs.py'

        #self.p, debuginfo = old_parser(FILE)
        self.p, debuginfo = new_parser(FILE)

        #print self.p

        # -------------------------------------------------------

        gotevent1 = 0
        gotevent2 = 0

        for classname, classentry in self.p.classlist.items():
            if classname == 'Incoming1':
                gotevent1 = 1


        assert gotevent1
Beispiel #18
0
def parse_source(source_code, options, html_debug_root_name=""):
    old_debug_info_value = DEBUGINFO()

    # Re temporary files, win10 needs delete=False otherwise other routines cannot access.
    # Need to pass "wt" since we're writing text, not bytes - helps python3 compatibility.
    with tempfile.NamedTemporaryFile(
            mode="wt",
            delete=False) as temp:  # TODO use streams not temporary files
        temp.write(source_code)
        temp.flush()

        if html_debug_root_name:
            # Normally debug info is false for performance reasons, so turn it on temporarily and restore it later
            set_DEBUGINFO(True)

            # create a html log file to contain html info
            log = LogWriter(html_debug_root_name, print_to_console=False)
            log.out_html_header()
        else:
            log = None

        try:
            pmodel, debuginfo = new_parser(temp.name, log=log, options=options)
        finally:
            set_DEBUGINFO(old_debug_info_value)

        if html_debug_root_name:
            log.ensure_is_open()  # file is sometimes closed, so reopen it
            log.out("<hr><h1>Errors:</h1>")
            log.out_wrap_in_html(pmodel.errors)
            log.out("<hr><h1>debuginfo:</h1>")
            log.out(debuginfo)
            log.out_html_footer()
            log.finish()
            print(
                f"\nHTML LOG parsing debug info is in {os.path.abspath(log.out_filename)}"
            )

    return pmodel, debuginfo
Beispiel #19
0
def reverse_engineer(files, mode, graph, prop_decorator, version):
    """reverse engineer python source code"""

    if version:
        click.echo(f"Pynsource CLI version {APP_VERSION}")

    click.echo(f"Files to parse: {files}")
    # click.echo(graph)

    # Expansion of files seems to happen magically via bash - need to check with windows
    # But if running via pycharm wildcards are not expanded, so play it safe and glob
    globbed = []
    for param in files:
        files = glob.glob(param)
        globbed += files
    click.echo(globbed)

    if graph:
        displaymodel = DisplayModel(canvas=None)

    for f in globbed:
        pmodel, debuginfo = new_parser(f,
                                       options={
                                           "mode":
                                           mode,
                                           "TREAT_PROPERTY_DECORATOR_AS_PROP":
                                           prop_decorator
                                       })
        if pmodel.errors:
            print(pmodel.errors)
        click.echo(f"Parse model for '{f}':")
        click.echo(dump_pmodel(pmodel))

        if graph:
            displaymodel.build_graphmodel(pmodel)  # will append

    if graph:
        displaymodel.Dump(
            msg="Final display model Graph containing all parse models:")
Beispiel #20
0
    def test_1(self):
        in_filename = 'tests/testing-generate-java/python-in/utilcc.py'

        p, debuginfo = old_parser(in_filename)
        pmodel_old = p.pmodel

        pmodel_new, debuginfo = new_parser(in_filename)

        # print pmodel_old.modulemethods
        # print pmodel_new.modulemethods

        old = set(pmodel_old.modulemethods)
        new = set(pmodel_new.modulemethods)

        any_changes = old ^ new

        differences_expected = set(['safeconvert', 'PopFoldersTillFind'])

        # no_changes = set()
        # self.assertSetEqual(any_changes, no_changes, any_changes)

        # Nested methods are not picked up by the new ast parser
        self.assertSetEqual(any_changes, differences_expected, any_changes)
Beispiel #21
0
def ParseArgsAndRun():
    import sys, glob
    import getopt  # good doco http://www.doughellmann.com/PyMOTW/getopt/
    # should possibly upgrade to using http://docs.python.org/library/argparse.html#module-argparse
    SIMPLE = 0
    globbed = []

    optionVerbose = 0
    optionModuleAsClass = 0
    optionExportToJava = 0
    optionExportToDelphi = 0
    optionExportToYuml = False
    option_export_to_plant_uml = False
    option_run_experiment = False
    option_show_parse_model = False
    optionExportTo_outdir = ''

    if SIMPLE:
        params = sys.argv[1]
        globbed = glob.glob(params)
    else:
        listofoptionvaluepairs, params = getopt.getopt(sys.argv[1:],
                                                       "amvy:j:d:xp:l:")

        #print listofoptionvaluepairs, params
        #print dict(listofoptionvaluepairs) # turn e.g. [('-v', ''), ('-y', 'fred.png')] into nicer? dict e.g. {'-v': '', '-y': 'fred.png'}

        def EnsurePathExists(outdir, outlanguagemsg):
            assert outdir, 'Need to specify output folder for %s output - got %s.' % (
                outlanguagemsg, outdir)
            if not os.path.exists(outdir):
                raise RuntimeError, (
                    'Output directory %s for %s file output does not exist.' %
                    (outdir, outlanguagemsg))

        for optionvaluepair in listofoptionvaluepairs:
            if '-x' == optionvaluepair[0]:
                option_run_experiment = True
            if '-p' == optionvaluepair[0]:
                # print "picked up -p parameter, globbed is", globbed, 'params', params
                option_show_parse_model = True

            if '-a' == optionvaluepair[0]:
                pass  # default is asciart, so don't need to specify
            if '-m' == optionvaluepair[0]:
                optionModuleAsClass = 1
            if '-v' == optionvaluepair[0]:
                optionVerbose = 1
            if optionvaluepair[0] in ('-j', '-d'):
                if optionvaluepair[0] == '-j':
                    optionExportToJava = 1
                    language = 'Java'
                else:
                    optionExportToDelphi = 1
                    language = 'Delphi'
                optionExportTo_outdir = optionvaluepair[1]
                EnsurePathExists(optionExportTo_outdir, language)
            if optionvaluepair[0] in ('-y'):
                optionExportToYuml = True
                optionExportTo_outpng = optionvaluepair[1]
            if optionvaluepair[0] in ('-l'):
                option_export_to_plant_uml = True
                optionExportTo_outpng = optionvaluepair[1]
        for param in params:
            files = glob.glob(param)
            globbed += files

    if globbed:
        if optionExportToJava or optionExportToDelphi:
            if optionExportToJava:
                u = CmdLinePythonToJava(globbed,
                                        treatmoduleasclass=optionModuleAsClass,
                                        verbose=optionVerbose)
            else:
                u = CmdLinePythonToDelphi(
                    globbed,
                    treatmoduleasclass=optionModuleAsClass,
                    verbose=optionVerbose)
            u.ExportTo(optionExportTo_outdir)
        elif optionExportToYuml:
            u = CmdLinePythonToYuml(globbed,
                                    treatmoduleasclass=optionModuleAsClass,
                                    verbose=optionVerbose)
            u.ExportTo(optionExportTo_outpng)
        elif option_export_to_plant_uml:
            u = CmdLinePythonToPlantUml(globbed,
                                        treatmoduleasclass=optionModuleAsClass,
                                        verbose=optionVerbose)
            u.ExportTo(optionExportTo_outpng)
        elif option_show_parse_model:
            for f in globbed:
                pmodel, debuginfo = new_parser(f)
                print(dump_old_structure(pmodel))
        else:
            u = CmdLinePythonToAsciiArt(globbed,
                                        treatmoduleasclass=optionModuleAsClass,
                                        verbose=optionVerbose)
            u.ExportTo(None)
    else:
        if option_run_experiment:
            test()
        else:
            print common.messages.HELP_COMMAND_LINE_USAGE
 def newparse():
     model, debuginfo = new_parser(in_filename, log)
     d2 = dump_old_structure(model)
     log.out_wrap_in_html(d2, style_class='dump1')
     return d2, debuginfo
Beispiel #23
0
 def newparse(options):
     model, debuginfo = new_parser(in_filename, log, options)
     d2 = dump_old_structure(model)
     log.out_wrap_in_html(d2, style_class='dump1')
     return d2, debuginfo