Beispiel #1
0
def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None,
          pyversion: Tuple[int, int] = defaults.PYTHON3_VERSION,
          custom_typing_module: str = None, implicit_any: bool = False) -> MypyFile:
    """Parse a source file, without doing any semantic analysis.

    Return the parse tree. If errors is not provided, raise ParseError
    on failure. Otherwise, use the errors object to report parse errors.

    The pyversion (major, minor) argument determines the Python syntax variant.
    """
    is_stub_file = bool(fnam) and fnam.endswith('.pyi')
    try:
        ast = typed_ast.parse(source, fnam, 'exec')
    except SyntaxError as e:
        if errors:
            errors.set_file('<input>' if fnam is None else fnam)
            errors.report(e.lineno, e.msg)  # type: ignore
        else:
            raise
    else:
        tree = ASTConverter().visit(ast)
        tree.path = fnam
        tree.is_stub = is_stub_file
        return tree

    return MypyFile([],
                    [],
                    False,
                    set(),
                    weak_opts=set())
Beispiel #2
0
def parse(source: Union[str, bytes],
          fnam: str = None,
          errors: Errors = None,
          pyversion: Tuple[int, int] = defaults.PYTHON3_VERSION,
          custom_typing_module: str = None) -> MypyFile:
    """Parse a source file, without doing any semantic analysis.

    Return the parse tree. If errors is not provided, raise ParseError
    on failure. Otherwise, use the errors object to report parse errors.

    The pyversion (major, minor) argument determines the Python syntax variant.
    """
    is_stub_file = bool(fnam) and fnam.endswith('.pyi')
    try:
        assert pyversion[0] < 3 and not is_stub_file
        ast = ast27.parse(source, fnam, 'exec')
        tree = ASTConverter(
            pyversion=pyversion,
            is_stub=is_stub_file,
            custom_typing_module=custom_typing_module,
        ).visit(ast)
        assert isinstance(tree, MypyFile)
        tree.path = fnam
        tree.is_stub = is_stub_file
        return tree
    except (SyntaxError, TypeCommentParseError) as e:
        if errors:
            errors.set_file('<input>' if fnam is None else fnam)
            errors.report(e.lineno, e.offset, e.msg)
        else:
            raise

    return MypyFile([], [], False, set())
Beispiel #3
0
def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None,
          pyversion: Tuple[int, int] = defaults.PYTHON3_VERSION,
          custom_typing_module: str = None) -> MypyFile:
    """Parse a source file, without doing any semantic analysis.

    Return the parse tree. If errors is not provided, raise ParseError
    on failure. Otherwise, use the errors object to report parse errors.

    The pyversion (major, minor) argument determines the Python syntax variant.
    """
    is_stub_file = bool(fnam) and fnam.endswith('.pyi')
    try:
        assert pyversion[0] < 3 and not is_stub_file
        ast = ast27.parse(source, fnam, 'exec')
        tree = ASTConverter(pyversion=pyversion,
                            is_stub=is_stub_file,
                            custom_typing_module=custom_typing_module,
                            ).visit(ast)
        assert isinstance(tree, MypyFile)
        tree.path = fnam
        tree.is_stub = is_stub_file
        return tree
    except (SyntaxError, TypeCommentParseError) as e:
        if errors:
            errors.set_file('<input>' if fnam is None else fnam)
            errors.report(e.lineno, e.offset, e.msg)
        else:
            raise

    return MypyFile([], [], False, set())
Beispiel #4
0
def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None,
          options: Options = Options()) -> MypyFile:
    """Parse a source file, without doing any semantic analysis.

    Return the parse tree. If errors is not provided, raise ParseError
    on failure. Otherwise, use the errors object to report parse errors.
    """
    raise_on_error = False
    if errors is None:
        errors = Errors()
        raise_on_error = True
    errors.set_file('<input>' if fnam is None else fnam, None)
    is_stub_file = bool(fnam) and fnam.endswith('.pyi')
    try:
        assert options.python_version[0] < 3 and not is_stub_file
        ast = ast27.parse(source, fnam, 'exec')
        tree = ASTConverter(options=options,
                            is_stub=is_stub_file,
                            errors=errors,
                            ).visit(ast)
        assert isinstance(tree, MypyFile)
        tree.path = fnam
        tree.is_stub = is_stub_file
    except SyntaxError as e:
        errors.report(e.lineno, e.offset, e.msg)
        tree = MypyFile([], [], False, set())

    if raise_on_error and errors.is_errors():
        errors.raise_error()

    return tree
Beispiel #5
0
def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None,
          pyversion: Tuple[int, int] = defaults.PYTHON3_VERSION,
          custom_typing_module: str = None) -> MypyFile:
    """Parse a source file, without doing any semantic analysis.

    Return the parse tree. If errors is not provided, raise ParseError
    on failure. Otherwise, use the errors object to report parse errors.

    The pyversion (major, minor) argument determines the Python syntax variant.
    """
    raise_on_error = False
    if errors is None:
        errors = Errors()
        raise_on_error = True
    errors.set_file('<input>' if fnam is None else fnam)
    is_stub_file = bool(fnam) and fnam.endswith('.pyi')
    try:
        assert pyversion[0] >= 3 or is_stub_file
        ast = ast35.parse(source, fnam, 'exec')

        tree = ASTConverter(pyversion=pyversion,
                            is_stub=is_stub_file,
                            errors=errors,
                            custom_typing_module=custom_typing_module,
                            ).visit(ast)
        tree.path = fnam
        tree.is_stub = is_stub_file
    except SyntaxError as e:
        errors.report(e.lineno, e.offset, e.msg)
        tree = MypyFile([], [], False, set())

    if raise_on_error and errors.is_errors():
        errors.raise_error()

    return tree
Beispiel #6
0
def parse(source: Union[str, bytes],
          fnam: str = None,
          errors: Errors = None,
          pyversion: Tuple[int, int] = defaults.PYTHON3_VERSION,
          custom_typing_module: str = None,
          implicit_any: bool = False) -> MypyFile:
    """Parse a source file, without doing any semantic analysis.

    Return the parse tree. If errors is not provided, raise ParseError
    on failure. Otherwise, use the errors object to report parse errors.

    The pyversion (major, minor) argument determines the Python syntax variant.
    """
    is_stub_file = bool(fnam) and fnam.endswith('.pyi')
    try:
        ast = typed_ast.parse(source, fnam, 'exec')
    except SyntaxError as e:
        if errors:
            errors.set_file('<input>' if fnam is None else fnam)
            errors.report(e.lineno, e.msg)  # type: ignore
        else:
            raise
    else:
        tree = ASTConverter().visit(ast)
        tree.path = fnam
        tree.is_stub = is_stub_file
        return tree

    return MypyFile([], [], False, set(), weak_opts=set())
Beispiel #7
0
def parse_type_comment(type_comment: str, line: int, errors: Errors) -> Optional[Type]:
    try:
        typ = ast35.parse(type_comment, '<type_comment>', 'eval')
    except SyntaxError as e:
        errors.report(line, e.offset, TYPE_COMMENT_SYNTAX_ERROR)
        return None
    else:
        assert isinstance(typ, ast35.Expression)
        return TypeConverter(errors, line=line).visit(typ.body)
Beispiel #8
0
def parse_type_comment(type_comment: str, line: int,
                       errors: Errors) -> Optional[Type]:
    try:
        typ = ast3.parse(type_comment, '<type_comment>', 'eval')
    except SyntaxError as e:
        errors.report(line, e.offset, TYPE_COMMENT_SYNTAX_ERROR)
        return None
    else:
        assert isinstance(typ, ast3.Expression)
        return TypeConverter(errors, line=line).visit(typ.body)
Beispiel #9
0
def extract_django_settings_module(config_file_path: Optional[str]) -> str:
    errors = Errors()
    if config_file_path is None:
        errors.report(
            0, None,
            "'django_settings_module' is not set: no mypy config file specified"
        )
        errors.raise_error()

    parser = configparser.ConfigParser()
    parser.read(config_file_path)  # type: ignore

    if not parser.has_section('mypy.plugins.django-stubs'):
        errors.report(
            0,
            None,
            "'django_settings_module' is not set: no section [mypy.plugins.django-stubs]",
            file=config_file_path)
        errors.raise_error()
    if not parser.has_option('mypy.plugins.django-stubs',
                             'django_settings_module'):
        errors.report(
            0,
            None,
            "'django_settings_module' is not set: setting is not provided",
            file=config_file_path)
        errors.raise_error()

    django_settings_module = parser.get('mypy.plugins.django-stubs',
                                        'django_settings_module').strip('\'"')
    return django_settings_module
Beispiel #10
0
def parse(source: Union[str, bytes],
          fnam: str = None,
          errors: Errors = None,
          pyversion: Tuple[int, int] = defaults.PYTHON3_VERSION,
          custom_typing_module: str = None) -> MypyFile:
    """Parse a source file, without doing any semantic analysis.

    Return the parse tree. If errors is not provided, raise ParseError
    on failure. Otherwise, use the errors object to report parse errors.

    The pyversion (major, minor) argument determines the Python syntax variant.
    """
    raise_on_error = False
    if errors is None:
        errors = Errors()
        raise_on_error = True
    errors.set_file('<input>' if fnam is None else fnam)
    is_stub_file = bool(fnam) and fnam.endswith('.pyi')
    try:
        assert pyversion[0] >= 3 or is_stub_file
        feature_version = pyversion[
            1] if not is_stub_file else defaults.PYTHON3_VERSION[1]
        ast = ast3.parse(source, fnam, 'exec', feature_version=feature_version)

        tree = ASTConverter(
            pyversion=pyversion,
            is_stub=is_stub_file,
            errors=errors,
            custom_typing_module=custom_typing_module,
        ).visit(ast)
        tree.path = fnam
        tree.is_stub = is_stub_file
    except SyntaxError as e:
        errors.report(e.lineno, e.offset, e.msg)
        tree = MypyFile([], [], False, set())

    if raise_on_error and errors.is_errors():
        errors.raise_error()

    return tree
Beispiel #11
0
def calculate_class_abstract_status(typ: TypeInfo, is_stub_file: bool, errors: Errors) -> None:
    """Calculate abstract status of a class.

    Set is_abstract of the type to True if the type has an unimplemented
    abstract attribute.  Also compute a list of abstract attributes.
    Report error is required ABCMeta metaclass is missing.
    """
    if typ.typeddict_type:
        return  # TypedDict can't be abstract
    concrete: Set[str] = set()
    abstract: List[str] = []
    abstract_in_this_class: List[str] = []
    if typ.is_newtype:
        # Special case: NewTypes are considered as always non-abstract, so they can be used as:
        #     Config = NewType('Config', Mapping[str, str])
        #     default = Config({'cannot': 'modify'})  # OK
        typ.abstract_attributes = []
        return
    for base in typ.mro:
        for name, symnode in base.names.items():
            node = symnode.node
            if isinstance(node, OverloadedFuncDef):
                # Unwrap an overloaded function definition. We can just
                # check arbitrarily the first overload item. If the
                # different items have a different abstract status, there
                # should be an error reported elsewhere.
                if node.items:  # can be empty for invalid overloads
                    func: Optional[Node] = node.items[0]
                else:
                    func = None
            else:
                func = node
            if isinstance(func, Decorator):
                fdef = func.func
                if fdef.is_abstract and name not in concrete:
                    typ.is_abstract = True
                    abstract.append(name)
                    if base is typ:
                        abstract_in_this_class.append(name)
            elif isinstance(node, Var):
                if node.is_abstract_var and name not in concrete:
                    typ.is_abstract = True
                    abstract.append(name)
                    if base is typ:
                        abstract_in_this_class.append(name)
            concrete.add(name)
    # In stubs, abstract classes need to be explicitly marked because it is too
    # easy to accidentally leave a concrete class abstract by forgetting to
    # implement some methods.
    typ.abstract_attributes = sorted(abstract)
    if is_stub_file:
        if typ.declared_metaclass and typ.declared_metaclass.type.fullname == 'abc.ABCMeta':
            return
        if typ.is_protocol:
            return
        if abstract and not abstract_in_this_class:
            def report(message: str, severity: str) -> None:
                errors.report(typ.line, typ.column, message, severity=severity)

            attrs = ", ".join('"{}"'.format(attr) for attr in sorted(abstract))
            report("Class {} has abstract attributes {}".format(typ.fullname, attrs), 'error')
            report("If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metaclass",
                   'note')
    if typ.is_final and abstract:
        attrs = ", ".join('"{}"'.format(attr) for attr in sorted(abstract))
        errors.report(typ.line, typ.column,
                      "Final class {} has abstract attributes {}".format(typ.fullname, attrs))