Get mypy running on lint
diff --git a/tools/lint/lint.py b/tools/lint/lint.py
index 19d0c11..dd06e0a 100644
--- a/tools/lint/lint.py
+++ b/tools/lint/lint.py
@@ -4,6 +4,7 @@
import argparse
import ast
import json
+import logging
import os
import re
import subprocess
@@ -19,12 +20,15 @@
from ..wpt import testfiles
from ..manifest.vcs import walk
-from manifest.sourcefile import SourceFile, js_meta_re, python_meta_re, space_chars, get_any_variants, get_default_any_variants
-from six import binary_type, iteritems, itervalues
+from ..manifest.sourcefile import SourceFile, js_meta_re, python_meta_re, space_chars, get_any_variants, get_default_any_variants
+from six import binary_type, iteritems, itervalues, with_metaclass
from six.moves import range
from six.moves.urllib.parse import urlsplit, urljoin
-import logging
+MYPY = False
+if MYPY:
+ # MYPY is set to True when run under Mypy.
+ from typing import Type
logger = None
@@ -330,7 +334,7 @@
return [item for i, item in enumerate(errors) if not whitelisted[i]]
-regexps = [item() for item in
+regexps = [item() for item in # type: ignore
[rules.TrailingWhitespaceRegexp,
rules.TabsRegexp,
rules.CRRegexp,
@@ -503,9 +507,11 @@
return errors
-class ASTCheck(object):
- __metaclass__ = abc.ABCMeta
- rule = None
+class ASTCheck(with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def rule(self):
+ # type: () -> Type[rules.Rule]
+ pass
@abc.abstractmethod
def check(self, root):
diff --git a/tools/lint/rules.py b/tools/lint/rules.py
index 78f9d07..76d5d3e 100644
--- a/tools/lint/rules.py
+++ b/tools/lint/rules.py
@@ -1,11 +1,29 @@
from __future__ import unicode_literals
+
+import abc
import os
import re
-class Rule(object):
- name = None
- description = None
- to_fix = None
+import six
+
+MYPY = False
+if MYPY:
+ # MYPY is set to True when run under Mypy.
+ from typing import List, Optional, Pattern, Text, Match
+
+
+class Rule(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def name(self):
+ # type: () -> Text
+ pass
+
+ @abc.abstractproperty
+ def description(self):
+ # type: () -> Text
+ pass
+
+ to_fix = None # type: Optional[Text]
@classmethod
def error(cls, path, context=(), line_no=None):
@@ -232,19 +250,30 @@
description = "Metadata comment is not formatted correctly"
-class Regexp(Rule):
- pattern = None
- file_extensions = None
- _re = None
+class Regexp(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def pattern(self):
+ # type: () -> bytes
+ pass
+
+ @abc.abstractproperty
+ def description(self):
+ # type: () -> Text
+ pass
+
+ file_extensions = None # type: Optional[List[Text]]
def __init__(self):
- self._re = re.compile(self.pattern)
+ # type: () -> None
+ self._re = re.compile(self.pattern) # type: Pattern
def applies(self, path):
+ # type: (str) -> bool
return (self.file_extensions is None or
os.path.splitext(path)[1] in self.file_extensions)
def search(self, line):
+ # type: (bytes) -> Optional[Match[bytes]]
return self._re.search(line)
diff --git a/tools/manifest/update.py b/tools/manifest/update.py
index f1a7093..013ec21 100755
--- a/tools/manifest/update.py
+++ b/tools/manifest/update.py
@@ -2,7 +2,7 @@
import argparse
import os
-import manifest
+from . import manifest
from . import vcs
from .log import get_logger
from .download import download_from_github
diff --git a/tools/manifest/vcs.py b/tools/manifest/vcs.py
index 9a6726c..d900012 100644
--- a/tools/manifest/vcs.py
+++ b/tools/manifest/vcs.py
@@ -78,7 +78,7 @@
class FileSystem(object):
def __init__(self, root, url_base, cache_path, manifest_path=None, rebuild=False):
- from gitignore import gitignore
+ from gitignore import gitignore # type: ignore
self.root = os.path.abspath(root)
self.url_base = url_base
self.ignore_cache = None
diff --git a/tools/mypy.ini b/tools/mypy.ini
index 6a0fdce..710df96 100644
--- a/tools/mypy.ini
+++ b/tools/mypy.ini
@@ -23,7 +23,3 @@
[mypy-zstandard.*]
ignore_missing_imports = True
-
-[mypy-.lint.*]
-# this is weird
-ignore_missing_imports = True
diff --git a/tools/tox.ini b/tools/tox.ini
index 5706440..d0b1864 100644
--- a/tools/tox.ini
+++ b/tools/tox.ini
@@ -24,6 +24,7 @@
[testenv:py36-mypy]
deps = -rrequirements_mypy.txt
+changedir = {toxinidir}/..
commands =
- mypy --config-file={toxinidir}/mypy.ini --no-incremental --py2 -p manifest
- mypy --config-file={toxinidir}/mypy.ini --no-incremental -p manifest
+ mypy --config-file={toxinidir}/mypy.ini --no-incremental --py2 -p tools.manifest -p tools.lint -p tools.gitignore
+ mypy --config-file={toxinidir}/mypy.ini --no-incremental -p tools.manifest -p tools.lint -p tools.gitignore
diff --git a/tools/wpt/testfiles.py b/tools/wpt/testfiles.py
index 7f0f221..09dd45b 100644
--- a/tools/wpt/testfiles.py
+++ b/tools/wpt/testfiles.py
@@ -185,7 +185,7 @@
# Delay import after localpaths sets up sys.path, because otherwise the
# import path will be "..manifest" and Python will treat it as a different
# manifest module.
- from manifest import manifest
+ from manifest import manifest # type: ignore
if manifest_path is None:
manifest_path = os.path.join(wpt_root, "MANIFEST.json")
return manifest.load_and_update(wpt_root, manifest_path, "/",