示例#1
0
    def test_validate_bad_field(self):
        badch = tuple(c for c in string.punctuation + string.digits)
        notnames = (
                '1a',
                'a.b',
                'a-b',
                '&a',
                'a++',
                ) + badch
        tests = [
            ('filename', ()),  # Any non-empty str is okay.
            ('funcname', notnames),
            ('name', notnames),
            ]
        seen = set()
        for field, invalid in tests:
            for value in invalid:
                seen.add(value)
                with self.subTest(f'{field}={value!r}'):
                    id = ID(**self.VALID_KWARGS)
                    id = id._replace(**{field: value})

                    with self.assertRaises(ValueError):
                        id.validate()

        for field, invalid in tests:
            valid = seen - set(invalid)
            for value in valid:
                with self.subTest(f'{field}={value!r}'):
                    id = ID(**self.VALID_KWARGS)
                    id = id._replace(**{field: value})

                    id.validate()  # This does not fail.
示例#2
0
    def test_typical(self):
        lines = textwrap.dedent('''
            filename    funcname        name    kind    declaration
            file1.c     -       var1    variable        static int
            file1.c     func1   local1  variable        static int
            file1.c     -       var2    variable        int
            file1.c     func2   local2  variable        char *
            file2.c     -       var1    variable        char *
            ''').strip().splitlines()
        lines = [re.sub(r'\s+', '\t', line, 4) for line in lines]
        self._return_read_tsv = [
            tuple(v.strip() for v in line.split('\t')) for line in lines[1:]
        ]

        known = list(read_file('known.tsv', _read_tsv=self._read_tsv))

        self.assertEqual(known, [
            ('variable', ID('file1.c', '', 'var1'), 'static int'),
            ('variable', ID('file1.c', 'func1', 'local1'), 'static int'),
            ('variable', ID('file1.c', '', 'var2'), 'int'),
            ('variable', ID('file1.c', 'func2', 'local2'), 'char *'),
            ('variable', ID('file2.c', '', 'var1'), 'char *'),
        ])
        self.assertEqual(self.calls, [
            ('_read_tsv',
             ('known.tsv', 'filename\tfuncname\tname\tkind\tdeclaration')),
        ])
示例#3
0
    def test_typical(self):
        lines = textwrap.dedent('''
            filename    funcname        name    kind    reason
            file1.c     -       var1    variable        ...
            file1.c     func1   local1  variable        |
            file1.c     -       var2    variable        ???
            file1.c     func2   local2  variable           |
            file2.c     -       var1    variable        reasons
            ''').strip().splitlines()
        lines = [
            re.sub(r'\s{1,8}', '\t', line, 4).replace('|', '')
            for line in lines
        ]
        self._return_read_tsv = [
            tuple(v.strip() for v in line.split('\t')) for line in lines[1:]
        ]

        ignored = ignored_from_file('spam.c', _read_tsv=self._read_tsv)

        self.assertEqual(
            ignored, {
                'variables': {
                    ID('file1.c', '', 'var1'): '...',
                    ID('file1.c', 'func1', 'local1'): '',
                    ID('file1.c', '', 'var2'): '???',
                    ID('file1.c', 'func2', 'local2'): '',
                    ID('file2.c', '', 'var1'): 'reasons',
                },
            })
        self.assertEqual(self.calls, [
            ('_read_tsv',
             ('spam.c', 'filename\tfuncname\tname\tkind\treason')),
        ])
示例#4
0
    def test_validate_typical(self):
        id = ID(
                filename='x/y/z/spam.c',
                funcname='func',
                name='eggs',
                )

        id.validate()  # This does not fail.
示例#5
0
    def test_init_coercion(self):
        tests = [
            ('str subclass',
             dict(
                 id=PseudoStr('eggs'),
                 kind=PseudoStr('variable'),
                 external=0,
             ), (
                 ID(None, None, 'eggs'),
                 Symbol.KIND.VARIABLE,
                 False,
             )),
            ('with filename',
             dict(
                 id=('x/y/z/spam.c', 'eggs'),
                 kind=PseudoStr('variable'),
                 external=0,
             ), (
                 ID('x/y/z/spam.c', None, 'eggs'),
                 Symbol.KIND.VARIABLE,
                 False,
             )),
            ('non-str 1',
             dict(
                 id=('a', 'b', 'c'),
                 kind=StrProxy('variable'),
                 external=0,
             ), (
                 ID('a', 'b', 'c'),
                 Symbol.KIND.VARIABLE,
                 False,
             )),
            ('non-str 2', dict(
                id=('a', 'b', 'c'),
                kind=Object(),
                external=0,
            ), (
                ID('a', 'b', 'c'),
                '<object>',
                False,
            )),
        ]
        for summary, kwargs, expected in tests:
            with self.subTest(summary):
                symbol = Symbol(**kwargs)

                for field in Symbol._fields:
                    value = getattr(symbol, field)
                    if field == 'external':
                        self.assertIs(type(value), bool)
                    elif field == 'id':
                        self.assertIs(type(value), ID)
                    else:
                        self.assertIs(type(value), str)
                self.assertEqual(tuple(symbol), expected)
示例#6
0
    def test_validate_missing_field(self):
        for field in ID._fields:
            with self.subTest(field):
                id = ID(**self.VALID_KWARGS)
                id = id._replace(**{field: None})

                if field == 'funcname':
                    id.validate()  # The field can be missing (not set).
                    id = id._replace(filename=None)
                    id.validate()  # Both fields can be missing (not set).
                    continue

                with self.assertRaises(TypeError):
                    id.validate()
示例#7
0
    def test_init_all_coerced(self):
        tests = [
            ('str subclass',
             dict(
                 filename=PseudoStr('x/y/z/spam.c'),
                 funcname=PseudoStr('func'),
                 name=PseudoStr('eggs'),
                 ),
             ('x/y/z/spam.c',
              'func',
              'eggs',
              )),
            ('non-str',
             dict(
                 filename=StrProxy('x/y/z/spam.c'),
                 funcname=Object(),
                 name=('a', 'b', 'c'),
                 ),
             ('x/y/z/spam.c',
              '<object>',
              "('a', 'b', 'c')",
              )),
            ]
        for summary, kwargs, expected in tests:
            with self.subTest(summary):
                id = ID(**kwargs)

                for field in ID._fields:
                    value = getattr(id, field)
                    self.assertIs(type(value), str)
                self.assertEqual(tuple(id), expected)
示例#8
0
    def test_iterable(self):
        id = ID(**self.VALID_KWARGS)

        filename, funcname, name = id

        values = (filename, funcname, name)
        for value, expected in zip(values, self.VALID_EXPECTED):
            self.assertEqual(value, expected)
示例#9
0
    def test_fields(self):
        id = ID('z', 'x', 'a')

        symbol = Symbol(id, 'b', False)

        self.assertEqual(symbol.id, id)
        self.assertEqual(symbol.kind, 'b')
        self.assertIs(symbol.external, False)
示例#10
0
 def __new__(cls, id, kind=KIND.VARIABLE, external=None):
     self = super().__new__(
         cls,
         id=ID.from_raw(id),
         kind=str(kind) if kind else None,
         external=bool(external) if external is not None else None,
     )
     return self
示例#11
0
    def test_init_all_coerced(self):
        id = ID('x/y/z/spam.c', 'func', 'spam')
        tests = [
            ('str subclass',
             dict(
                 id=(
                     PseudoStr('x/y/z/spam.c'),
                     PseudoStr('func'),
                     PseudoStr('spam'),
                 ),
                 storage=PseudoStr('static'),
                 vartype=PseudoStr('int'),
             ), (
                 id,
                 'static',
                 'int',
             )),
            ('non-str 1', dict(
                id=id,
                storage=Object(),
                vartype=Object(),
            ), (
                id,
                '<object>',
                '<object>',
            )),
            ('non-str 2',
             dict(
                 id=id,
                 storage=StrProxy('static'),
                 vartype=StrProxy('variable'),
             ), (
                 id,
                 'static',
                 'variable',
             )),
            ('non-str',
             dict(
                 id=id,
                 storage=('a', 'b', 'c'),
                 vartype=('x', 'y', 'z'),
             ), (
                 id,
                 "('a', 'b', 'c')",
                 "('x', 'y', 'z')",
             )),
        ]
        for summary, kwargs, expected in tests:
            with self.subTest(summary):
                static = Variable(**kwargs)

                for field in Variable._fields:
                    value = getattr(static, field)
                    if field == 'id':
                        self.assertIs(type(value), ID)
                    else:
                        self.assertIs(type(value), str)
                self.assertEqual(tuple(static), expected)
示例#12
0
    def test_init_all_missing(self):
        id = ID(None, None, 'spam')

        symbol = Symbol(id)

        self.assertEqual(symbol, (
            id,
            Symbol.KIND.VARIABLE,
            None,
        ))
示例#13
0
    def test_validate_typical(self):
        id = ID('z', 'x', 'a')

        symbol = Symbol(
            id=id,
            kind=Symbol.KIND.VARIABLE,
            external=False,
        )

        symbol.validate()  # This does not fail.
示例#14
0
    def test___getattr__(self):
        id = ID('z', 'x', 'a')
        symbol = Symbol(id, 'b', False)

        filename = symbol.filename
        funcname = symbol.funcname
        name = symbol.name

        self.assertEqual(filename, 'z')
        self.assertEqual(funcname, 'x')
        self.assertEqual(name, 'a')
示例#15
0
    def test_init_typical_global(self):
        id = ID(
                filename='x/y/z/spam.c',
                funcname=None,
                name='eggs',
                )

        self.assertEqual(id, (
                'x/y/z/spam.c',
                None,
                'eggs',
                ))
示例#16
0
    def test_init_typical_local(self):
        id = ID(
                filename='x/y/z/spam.c',
                funcname='func',
                name='eggs',
                )

        self.assertEqual(id, (
                'x/y/z/spam.c',
                'func',
                'eggs',
                ))
示例#17
0
    def test_minimal(self):
        id = ID(
                filename=None,
                funcname=None,
                name='eggs',
                )

        self.assertEqual(id, (
                None,
                None,
                'eggs',
                ))
示例#18
0
    def test_init_typical_binary_global(self):
        id = ID('Python/ceval.c', None, 'spam')
        symbol = Symbol(
            id=id,
            kind=Symbol.KIND.VARIABLE,
            external=False,
        )

        self.assertEqual(symbol, (
            id,
            Symbol.KIND.VARIABLE,
            False,
        ))
示例#19
0
    def test_init_all_missing(self):
        for value in ('', None):
            with self.subTest(repr(value)):
                id = ID(
                        filename=value,
                        funcname=value,
                        name=value,
                        )

                self.assertEqual(id, (
                        None,
                        None,
                        None,
                        ))
示例#20
0
    def test_from_raw(self):
        tests = [
            ('', None),
            (None, None),
            ('spam', (None, None, 'spam')),
            (('spam',), (None, None, 'spam')),
            (('x/y/z/spam.c', 'spam'), ('x/y/z/spam.c', None, 'spam')),
            (self.VALID_ARGS, self.VALID_EXPECTED),
            (self.VALID_KWARGS, self.VALID_EXPECTED),
            ]
        for raw, expected in tests:
            with self.subTest(raw):
                id = ID.from_raw(raw)

                self.assertEqual(id, expected)
示例#21
0
    def test_validate_typical(self):
        validstorage = ('static', 'extern', 'implicit', 'local')
        self.assertEqual(set(validstorage), set(Variable.STORAGE))

        for storage in validstorage:
            with self.subTest(storage):
                static = Variable(
                    id=ID(
                        filename='x/y/z/spam.c',
                        funcname='func',
                        name='eggs',
                    ),
                    storage=storage,
                    vartype='int',
                )

                static.validate()  # This does not fail.
示例#22
0
    def test_init_typical_global(self):
        for storage in ('static', 'extern', 'implicit'):
            with self.subTest(storage):
                static = Variable(
                    id=ID(
                        filename='x/y/z/spam.c',
                        funcname=None,
                        name='eggs',
                    ),
                    storage=storage,
                    vartype='int',
                )

                self.assertEqual(static, (
                    ('x/y/z/spam.c', None, 'eggs'),
                    storage,
                    'int',
                ))
示例#23
0
    def test_init_typical_local(self):
        for storage in ('static', 'local'):
            with self.subTest(storage):
                static = Variable(
                    id=ID(
                        filename='x/y/z/spam.c',
                        funcname='func',
                        name='eggs',
                    ),
                    storage=storage,
                    vartype='int',
                )

        self.assertEqual(static, (
            ('x/y/z/spam.c', 'func', 'eggs'),
            storage,
            'int',
        ))
示例#24
0
def ignored_from_file(
    infile,
    *,
    _read_tsv=read_tsv,
):
    """Yield a Variable for each ignored var in the file."""
    ignored = {
        'variables': {},
        #'types': {},
        #'constants': {},
        #'macros': {},
    }
    for row in _read_tsv(infile, IGNORED_HEADER):
        filename, funcname, name, kind, reason = row
        if not funcname or funcname == '-':
            funcname = None
        id = ID(filename, funcname, name)
        if kind == 'variable':
            values = ignored['variables']
        else:
            raise ValueError(f'unsupported kind in row {row}')
        values[id] = reason
    return ignored
示例#25
0
def _known(symbol):
    if symbol.funcname:
        if symbol.funcname != UNKNOWN or symbol.filename != UNKNOWN:
            raise KeyError(symbol.name)
        filename, funcname, decl = LOCALS[symbol.name]
        varid = ID(filename, funcname, symbol.name)
    elif not symbol.filename or symbol.filename == UNKNOWN:
        raise KeyError(symbol.name)
    else:
        varid = symbol.id
        try:
            decl = GLOBALS[symbol.name]
        except KeyError:

            if symbol.name.endswith('_methods'):
                decl = 'static PyMethodDef '
            elif symbol.filename == 'Objects/exceptions.c' and symbol.name.startswith(
                ('PyExc_', '_PyExc_')):
                decl = 'static PyTypeObject '
            else:
                raise
    if symbol.name not in decl:
        decl = decl + symbol.name
    return Variable(varid, 'static', decl)
示例#26
0
class SymbolTests(unittest.TestCase):

    VALID_ARGS = (
        ID('x/y/z/spam.c', 'func', 'eggs'),
        Symbol.KIND.VARIABLE,
        False,
    )
    VALID_KWARGS = dict(zip(Symbol._fields, VALID_ARGS))
    VALID_EXPECTED = VALID_ARGS

    def test_init_typical_binary_local(self):
        id = ID(None, None, 'spam')
        symbol = Symbol(
            id=id,
            kind=Symbol.KIND.VARIABLE,
            external=False,
        )

        self.assertEqual(symbol, (
            id,
            Symbol.KIND.VARIABLE,
            False,
        ))

    def test_init_typical_binary_global(self):
        id = ID('Python/ceval.c', None, 'spam')
        symbol = Symbol(
            id=id,
            kind=Symbol.KIND.VARIABLE,
            external=False,
        )

        self.assertEqual(symbol, (
            id,
            Symbol.KIND.VARIABLE,
            False,
        ))

    def test_init_coercion(self):
        tests = [
            ('str subclass',
             dict(
                 id=PseudoStr('eggs'),
                 kind=PseudoStr('variable'),
                 external=0,
             ), (
                 ID(None, None, 'eggs'),
                 Symbol.KIND.VARIABLE,
                 False,
             )),
            ('with filename',
             dict(
                 id=('x/y/z/spam.c', 'eggs'),
                 kind=PseudoStr('variable'),
                 external=0,
             ), (
                 ID('x/y/z/spam.c', None, 'eggs'),
                 Symbol.KIND.VARIABLE,
                 False,
             )),
            ('non-str 1',
             dict(
                 id=('a', 'b', 'c'),
                 kind=StrProxy('variable'),
                 external=0,
             ), (
                 ID('a', 'b', 'c'),
                 Symbol.KIND.VARIABLE,
                 False,
             )),
            ('non-str 2', dict(
                id=('a', 'b', 'c'),
                kind=Object(),
                external=0,
            ), (
                ID('a', 'b', 'c'),
                '<object>',
                False,
            )),
        ]
        for summary, kwargs, expected in tests:
            with self.subTest(summary):
                symbol = Symbol(**kwargs)

                for field in Symbol._fields:
                    value = getattr(symbol, field)
                    if field == 'external':
                        self.assertIs(type(value), bool)
                    elif field == 'id':
                        self.assertIs(type(value), ID)
                    else:
                        self.assertIs(type(value), str)
                self.assertEqual(tuple(symbol), expected)

    def test_init_all_missing(self):
        id = ID(None, None, 'spam')

        symbol = Symbol(id)

        self.assertEqual(symbol, (
            id,
            Symbol.KIND.VARIABLE,
            None,
        ))

    def test_fields(self):
        id = ID('z', 'x', 'a')

        symbol = Symbol(id, 'b', False)

        self.assertEqual(symbol.id, id)
        self.assertEqual(symbol.kind, 'b')
        self.assertIs(symbol.external, False)

    def test___getattr__(self):
        id = ID('z', 'x', 'a')
        symbol = Symbol(id, 'b', False)

        filename = symbol.filename
        funcname = symbol.funcname
        name = symbol.name

        self.assertEqual(filename, 'z')
        self.assertEqual(funcname, 'x')
        self.assertEqual(name, 'a')

    def test_validate_typical(self):
        id = ID('z', 'x', 'a')

        symbol = Symbol(
            id=id,
            kind=Symbol.KIND.VARIABLE,
            external=False,
        )

        symbol.validate()  # This does not fail.

    def test_validate_missing_field(self):
        for field in Symbol._fields:
            with self.subTest(field):
                symbol = Symbol(**self.VALID_KWARGS)
                symbol = symbol._replace(**{field: None})

                with self.assertRaises(TypeError):
                    symbol.validate()

    def test_validate_bad_field(self):
        badch = tuple(c for c in string.punctuation + string.digits)
        notnames = (
            '1a',
            'a.b',
            'a-b',
            '&a',
            'a++',
        ) + badch
        tests = [
            ('id', notnames),
            ('kind', ('bogus', )),
        ]
        seen = set()
        for field, invalid in tests:
            for value in invalid:
                if field != 'kind':
                    seen.add(value)
                with self.subTest(f'{field}={value!r}'):
                    symbol = Symbol(**self.VALID_KWARGS)
                    symbol = symbol._replace(**{field: value})

                    with self.assertRaises(ValueError):
                        symbol.validate()

        for field, invalid in tests:
            if field == 'kind':
                continue
            valid = seen - set(invalid)
            for value in valid:
                with self.subTest(f'{field}={value!r}'):
                    symbol = Symbol(**self.VALID_KWARGS)
                    symbol = symbol._replace(**{field: value})

                    symbol.validate()  # This does not fail.
示例#27
0
def _handle_id(filename, funcname, name, *,
               _relpath=os.path.relpath,
               ):
    filename = _relpath(filename, REPO_ROOT)
    return ID(filename, funcname, name)
示例#28
0
 def from_name(cls, name, filename=None, kind=KIND.VARIABLE, external=None):
     """Return a new symbol based on the given name."""
     id = ID(filename, None, name)
     return cls(id, kind, external)
示例#29
0
    def test_fields(self):
        id = ID('a', 'b', 'z')

        self.assertEqual(id.filename, 'a')
        self.assertEqual(id.funcname, 'b')
        self.assertEqual(id.name, 'z')