def test_universal_new_lines(self):
        test_file = os.path.join(TEST_DIR, 'dos-file')
        lines = pyficache.getlines(test_file)
        self.assertEqual(lines, ['Foo\n', 'bar\n', 'baz\n'])
        self.assertTrue(test_file in pyficache.file_cache)
        file_obj = pyficache.file_cache[test_file]
        self.assertEqual('\r\n', file_obj.eols)

        test_file = os.path.join(TEST_DIR, 'mixed-eol-file')
        lines = pyficache.getlines(test_file)
        self.assertEqual(lines, ['Unix\n', 'DOS\n', 'unix\n'])
        self.assertTrue(test_file in pyficache.file_cache)
        file_obj = pyficache.file_cache[test_file]
        self.assertEqual(('\n', '\r\n'), file_obj.eols)
Esempio n. 2
0
    def find_ref(self):
        """Get the external file reference and line number.

        :raises: :class:`~doorstop.common.DoorstopError` when no
            reference is found

        :return: relative path to file or None (when no reference
            set),
            line number (when found in file) or None (when found as
            filename) or None (when no reference set)

        """
        # Return immediately if no external reference
        if not self.ref:
            log.debug("no external reference to search for")
            return None, None
        # Update the cache
        if not settings.CACHE_PATHS:
            pyficache.clear_file_cache()
        # Search for the external reference
        log.debug("seraching for ref '{}'...".format(self.ref))
        pattern = r"(\b|\W){}(\b|\W)".format(re.escape(self.ref))
        log.trace("regex: {}".format(pattern))
        regex = re.compile(pattern)
        for path, filename, relpath in self.tree.vcs.paths:
            # Skip the item's file while searching
            if path == self.path:
                continue
            # Check for a matching filename
            if filename == self.ref:
                return relpath, None
            # Skip extensions that should not be considered text
            if os.path.splitext(filename)[-1] in settings.SKIP_EXTS:
                continue
            # Search for the reference in the file
            lines = pyficache.getlines(path)
            if lines is None:
                log.trace("unable to read lines from: {}".format(path))
                continue
            for lineno, line in enumerate(lines, start=1):
                if regex.search(line):
                    log.debug("found ref: {}".format(relpath))
                    return relpath, lineno

        msg = "external reference not found: {}".format(self.ref)
        raise DoorstopError(msg)
Esempio n. 3
0
    def find_ref(self):
        """Get the external file reference and line number.

        :raises: :class:`~doorstop.common.DoorstopError` when no
            reference is found

        :return: relative path to file or None (when no reference
            set),
            line number (when found in file) or None (when found as
            filename) or None (when no reference set)

        """
        # Return immediately if no external reference
        if not self.ref:
            log.debug("no external reference to search for")
            return None, None
        # Update the cache
        if not settings.CACHE_PATHS:
            pyficache.clear_file_cache()
        # Search for the external reference
        log.debug("seraching for ref '{}'...".format(self.ref))
        pattern = r"(\b|\W){}(\b|\W)".format(re.escape(self.ref))
        log.trace("regex: {}".format(pattern))
        regex = re.compile(pattern)
        for path, filename, relpath in self.tree.vcs.paths:
            # Skip the item's file while searching
            if path == self.path:
                continue
            # Check for a matching filename
            if filename == self.ref:
                return relpath, None
            # Skip extensions that should not be considered text
            if os.path.splitext(filename)[-1] in settings.SKIP_EXTS:
                continue
            # Search for the reference in the file
            lines = pyficache.getlines(path)
            if lines is None:
                log.trace("unable to read lines from: {}".format(path))
                continue
            for lineno, line in enumerate(lines, start=1):
                if regex.search(line):
                    log.debug("found ref: {}".format(relpath))
                    return relpath, lineno

        msg = "external reference not found: {}".format(self.ref)
        raise DoorstopError(msg)
Esempio n. 4
0
    def find_file_reference(ref_path, root, tree, item_path, keyword=None):
        """Find the external file reference.

        :raises: :class:`~doorstop.common.DoorstopError` when no
            reference is found

        :return: Tuple (ref_path, line) when reference is found

        """

        log.debug("searching for ref '{}'...".format(ref_path))
        ref_full_path = os.path.join(root, ref_path)

        for path, filename, relpath in tree.vcs.paths:
            # Skip the item's file while searching
            if path == item_path:
                continue
            if path == ref_full_path:
                if keyword is None:
                    return relpath, None

                # Search for the reference in the file
                lines = pyficache.getlines(path)
                if lines is None:
                    log.trace(  # type: ignore
                        "unable to read lines from: {}".format(
                            path))  # type: ignore
                    continue

                log.debug("searching for ref '{}'...".format(keyword))
                pattern = r"(\b|\W){}(\b|\W)".format(re.escape(keyword))
                log.trace("regex: {}".format(pattern))  # type: ignore
                regex = re.compile(pattern)
                for lineno, line in enumerate(lines, start=1):
                    if regex.search(line):
                        log.debug("found ref: {}".format(relpath))
                        return relpath, lineno

        msg = "external reference not found: {}".format(ref_path)
        raise DoorstopError(msg)
Esempio n. 5
0
    def run(self, args):
        co = self.proc.curframe.f_code
        name = co.co_name

        try:
            opts, args = getopt(args[1:], "hpPAto:O", [
                "help", "parent", "pretty", "AST", 'tree', "offset=", "offsets"
            ])
        except GetoptError as err:
            # print help information and exit:
            print(str(
                err))  # will print something like "option -a not recognized"
            return

        show_parent = False
        show_ast = False
        offset = None
        show_offsets = False
        for o, a in opts:
            if o in ("-h", "--help"):
                self.proc.commands['help'].run(['help', 'deparse'])
                return
            elif o in ("-O", "--offsets"):
                show_offsets = True
            elif o in ("-p", "--parent"):
                show_parent = True
            elif o in ("-A", "--tree", '--AST'):
                show_ast = True
            elif o in ("-o", '--offset'):
                offset = a
            else:
                self.errmsg("unhandled option '%s'" % o)
            pass
        pass
        nodeInfo = None

        try:
            float_version = sysinfo2float()
        except:
            self.errmsg(sys.exc_info()[1])
            return
        if len(args) >= 1 and args[0] == '.':
            temp_filename, name_for_code = deparse_and_cache(co, self.errmsg)
            if not temp_filename:
                return
            self.print_text(''.join(getlines(temp_filename)))
            return
        elif show_offsets:
            deparsed = deparse_code(float_version, co, is_pypy=IS_PYPY)
            self.section("Offsets known:")
            m = self.columnize_commands(
                list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0]))))
            self.msg_nocr(m)
            return
        elif offset is not None:
            mess = ("The 'deparse' command when given an argument requires an"
                    " instruction offset. Got: '%s'" % offset)
            last_i = self.proc.get_an_int(offset, mess)
            if last_i is None:
                return
        else:
            last_i = self.proc.curframe.f_lasti
            if last_i == -1: last_i = 0

        try:
            deparsed = deparse_code(float_version, co, is_pypy=IS_PYPY)
            nodeInfo = deparsed_find((name, last_i), deparsed, co)
            if not nodeInfo:
                self.errmsg(
                    "Can't find exact offset %d; giving inexact results" %
                    last_i)
                deparsed = deparse_code_around_offset(co.co_name,
                                                      last_i,
                                                      float_version,
                                                      co,
                                                      is_pypy=IS_PYPY)
        except:
            self.errmsg(sys.exc_info()[1])
            self.errmsg("error in deparsing code at offset %d" % last_i)
            return
        if not nodeInfo:
            nodeInfo = deparsed_find((name, last_i), deparsed, co)
        if nodeInfo:
            extractInfo = deparsed.extract_node_info(nodeInfo)
            parentInfo = None
            # print extractInfo
            if show_ast:
                p = deparsed.ast
                if show_parent:
                    parentInfo, p = deparsed.extract_parent_info(nodeInfo.node)
                self.msg(p)
            if extractInfo:
                self.rst_msg("*instruction:* %s" % (nodeInfo.node))
                self.print_text(extractInfo.selectedLine)
                self.msg(extractInfo.markerLine)
                if show_parent:
                    if not parentInfo:
                        parentInfo, p = deparsed.extract_parent_info(
                            nodeInfo.node)
                    if parentInfo:
                        self.section("Contained in...")
                        self.rst_msg("\t*Grammar Symbol:* %s" % p.kind)
                        self.print_text(parentInfo.selectedLine)
                        self.msg(parentInfo.markerLine)
                    pass
                pass
            pass
        elif last_i == -1:
            if name:
                self.msg("At beginning of %s " % name)
            elif self.core.filename(None):
                self.msg("At beginning of program %s" %
                         self.core.filename(None))
            else:
                self.msg("At beginning")
        else:
            self.errmsg(
                "haven't recorded info for offset %d. Offsets I know are:" %
                last_i)
            m = self.columnize_commands(
                list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0]))))
            self.msg_nocr(m)
        return
    def test_basic(self):
        filename = __file__
        if '.pyc' == filename[-4:]:
            filename = filename[:-1]
            pass

        fp = open(filename, 'r')
        compare_lines = fp.readlines()
        self.assertTrue(
            compare_lines,
            "Should have been able to read %s for comparing" % filename)
        fp.close()

        # Test getlines to read this file.
        lines = pyficache.getlines(__file__)
        self.assertEqual(
            compare_lines, lines, 'We should get exactly the same lines as '
            'reading this file.')

        # Test getline to read this file. The file should now be cached,
        # so internally a different set of routines are used.
        test_line = 2
        line = pyficache.getline(__file__, test_line, {'strip_nl': False})
        self.assertEqual(
            compare_lines[test_line - 1], line,
            'We should get exactly the same line as reading '
            'this file.')
        line = pyficache.getline(__file__, test_line, {'output': 'light'})
        self.assertTrue(
            line.index('Unit test for pyficache') > 0,
            'Terminal formatted line 2 should have '
            '"Unit test for pyficache"')

        # Test getting the line via a relative file name
        old_dir = os.getcwd()
        os.chdir(os.path.dirname(os.path.abspath((__file__))))
        short_file = os.path.basename(__file__)
        test_line = 10
        line = pyficache.getline(short_file, test_line, {'strip_nl': False})
        self.assertEqual(
            compare_lines[test_line - 1], line,
            'Short filename lookup on %s should work' % short_file)
        os.chdir(old_dir)

        # Write a temporary file; read contents, rewrite it and check that
        # we get a change when calling getline.
        (fd, path) = mkstemp(prefix="pyfcache", suffix='.txt')
        test_string = "Now is the time.\n"
        with open(path, 'w') as f:
            f.write(test_string)
            f.close()
            pass
        line = pyficache.getline(path, 1, {'strip_nl': False})
        self.assertEqual(
            test_string, line, "C'mon - a simple line test like this worked "
            "before.")
        with open(path, 'w') as f:
            test_string = "Now is another time."
            f.write(test_string)
            f.close()
            pass

        pyficache.checkcache()
        line = pyficache.getline(path, 1)
        self.assertEqual(test_string, line,
                         "checkcache should have reread the temporary file.")
        try:
            os.remove(path)
        except:
            pass
        return
Esempio n. 7
0
    def run(self, args):
        if sys.version_info[:2] > (3, 8):
            self.errmsg("Deparsing for Python greater than 3.8 not impemented")
            return
        co = self.proc.curframe.f_code
        name = co.co_name

        try:
            opts, args = getopt(
                args[1:],
                "hpPto:O",
                ["help", "parent", "pretty", "tree", "offset=", "offsets"],
            )
        except GetoptError as err:
            # print help information and exit:
            self.errmsg(str(
                err))  # will print something like "option -a not recognized"
            return

        show_parent = False
        show_tree = False
        offset = None
        show_offsets = False
        for o, a in opts:
            if o in ("-h", "--help"):
                self.proc.commands["help"].run(["help", "deparse"])
                return
            elif o in ("-O", "--offsets"):
                show_offsets = True
            elif o in ("-p", "--parent"):
                show_parent = True
            elif o in (
                    "-t",
                    "--tree",
            ):
                show_tree = True
            elif o in ("-o", "--offset"):
                offset = a
            else:
                self.errmsg("unhandled option '%s'" % o)
            pass
        pass
        nodeInfo = None

        if len(args) >= 1 and args[0] == ".":
            temp_filename, name_for_code = deparse_and_cache(
                co, self.errmsg, tempdir=self.settings["tempdir"])
            if not temp_filename:
                return
            self.print_text("".join(getlines(temp_filename)))
            return
        elif show_offsets:
            deparsed = code_deparse(co)
            self.section("Offsets known:")
            m = self.columnize_commands(
                list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0]))))
            self.msg_nocr(m)
            return
        elif offset is not None:
            mess = ("The 'deparse' command when given an argument requires an"
                    " instruction offset. Got: '%s'" % offset)
            last_i = self.proc.get_an_int(offset, mess)
            if last_i is None:
                return
        else:
            last_i = self.proc.curframe.f_lasti
            if last_i == -1:
                last_i = 0

        deparsed, nodeInfo = deparse_offset(co, name, last_i, self.errmsg)
        if not deparsed:
            return

        if nodeInfo:
            extractInfo = deparsed.extract_node_info(nodeInfo)
            parentInfo = None
            # print extractInfo
            if show_tree:
                p = deparsed.ast
                if show_parent:
                    parentInfo, p = deparsed.extract_parent_info(nodeInfo.node)
                self.msg(p)
            if extractInfo:
                self.rst_msg("*instruction:* %s" % (nodeInfo.node))
                self.print_text(extractInfo.selectedLine)
                self.msg(extractInfo.markerLine)
                if show_parent:
                    if not parentInfo:
                        parentInfo, p = deparsed.extract_parent_info(
                            nodeInfo.node)
                    if parentInfo:
                        self.section("Contained in...")
                        self.rst_msg("\t*Grammar Symbol:* %s" % p.kind)
                        self.print_text(parentInfo.selectedLine)
                        self.msg(parentInfo.markerLine)
                    pass
                pass
            pass
        elif last_i == -1:
            if name:
                self.msg("At beginning of %s " % name)
            elif self.core.filename(None):
                self.msg("At beginning of program %s" %
                         self.core.filename(None))
            else:
                self.msg("At beginning")
        else:
            self.errmsg(
                "haven't recorded info for offset %d. Offsets I know are:" %
                last_i)
            offsets = [
                key[1] for key in deparsed.offsets.keys()
                if isinstance(key[1], int)
            ]
            m = self.columnize_commands(list(sorted(offsets)))
            self.msg_nocr(m)
        return