Repository: google/pytype

Issue:
made `python_verision` in pytype.cfg same as its runtime python version
from #270

Now the field "python_version" in pytype.cfg is same as its runtime Python version.

Before this PR, always the filed equals "3.6" regardless of what version of Python you use: 
```pytype.cfg
python_version = 3.6
```

After this PR, the fileld equals the version of Python which you use:
```pytype.cfg
python_version = (the version of Python which you use)
```

This is done by using `sys.version_info`.



Discussion:

Resolving patch:
diff --git a/pytype/__version__.py b/pytype/__version__.py
--- a/pytype/__version__.py
+++ b/pytype/__version__.py
@@ -1,2 +1,2 @@
 # pylint: skip-file
-__version__ = '2019.03.21'
+__version__ = '2019.03.27'
diff --git a/pytype/imports_map_loader.py b/pytype/imports_map_loader.py
--- a/pytype/imports_map_loader.py
+++ b/pytype/imports_map_loader.py
@@ -30,8 +30,8 @@ def _validate_imports_map(imports_map):
 
   Args:
     imports_map: The map returned by _read_imports_map.
-  Raises:
-    AssertionError: If we found an error in the imports map.
+  Returns:
+    A list of invalid entries, in the form (short_path, long_path)
   """
   errors = []
   for short_path, paths in imports_map.items():
@@ -43,7 +43,7 @@ def _validate_imports_map(imports_map):
               os.path.abspath("."))
     for short_path, path in errors:
       log.error("  file does not exist: %r (mapped from %r)", path, short_path)
-    raise AssertionError("bad import map")
+  return errors
 
 
 def build_imports_map(options_info_path, output=None):
@@ -58,6 +58,8 @@ def build_imports_map(options_info_path, output=None):
              imports_info, this output should *not* exist.
   Returns:
     Dict of .py short_path to list of .pytd path or None if no options_info_path
+  Raises:
+    ValueError if the imports map is invalid
   """
   imports_multimap = _read_imports_map(options_info_path)
 
@@ -81,7 +83,11 @@ def build_imports_map(options_info_path, output=None):
         del imports_map[k]
         break
 
-  _validate_imports_map(imports_multimap)
+  errors = _validate_imports_map(imports_multimap)
+  if errors:
+    msg = "Invalid imports_map: %s\nBad entries:\n" % options_info_path
+    msg += "\n".join("  %s -> %s" % (k, v) for k, v in errors)
+    raise ValueError(msg)
 
   # Add the potential directory nodes for adding "__init__", because some build
   # systems automatically create __init__.py in empty directories. These are
diff --git a/pytype/tools/analyze_project/config.py b/pytype/tools/analyze_project/config.py
--- a/pytype/tools/analyze_project/config.py
+++ b/pytype/tools/analyze_project/config.py
@@ -52,7 +52,8 @@
         '', '.', None,
         'Paths to source code directories, separated by %r.' % os.pathsep),
     'python_version': Item(
-        '', '3.6', None, 'Python version (major.minor) of the target code.'),
+        '', '{}.{}'.format(*sys.version_info[:2]),
+        None, 'Python version (major.minor) of the target code.'),
 }
 
 


Test patch:
diff --git a/pytype/imports_map_loader_test.py b/pytype/imports_map_loader_test.py
--- a/pytype/imports_map_loader_test.py
+++ b/pytype/imports_map_loader_test.py
@@ -89,7 +89,7 @@ def testInvalidMapEntry(self):
       imports_info = "%s %s\n" % ("a/b/c.pyi", d["a/b/c.pyi"])
       d.create_file("imports_info", imports_info)
       output = os.path.join(d.path, "a/b.pyi")
-      with self.assertRaises(AssertionError):
+      with self.assertRaises(ValueError):
         imports_map_loader.build_imports_map(d["imports_info"], output)
 
 
diff --git a/pytype/pyi/parser_test.py b/pytype/pyi/parser_test.py
--- a/pytype/pyi/parser_test.py
+++ b/pytype/pyi/parser_test.py
@@ -1961,5 +1961,44 @@ def f(x: Alias[T, T]) -> T: ...
     """, 4, "List[List[T]] expected 1 parameters, got 2")
 
 
+class ImportTypeIgnoreTest(_ParserTestBase):
+
+  def test_import(self):
+    self.check("""
+      import mod  # type: ignore
+      def f(x: mod.attr) -> None: ...
+    """, """\
+      import mod
+
+      def f(x: mod.attr) -> None: ...""")
+
+  def test_from_import(self):
+    src = textwrap.dedent("""
+      from mod import attr  # type: ignore
+      def f(x: attr) -> None: ...
+    """)
+    ast = parser.parse_string(src, python_version=self.PYTHON_VERSION)
+    self.assertTrue(ast.Lookup("attr"))
+    self.assertTrue(ast.Lookup("f"))
+
+  def test_relative_import(self):
+    src = textwrap.dedent("""
+      from . import attr  # type: ignore
+      def f(x: attr) -> None: ...
+    """)
+    ast = parser.parse_string(src, python_version=self.PYTHON_VERSION)
+    self.assertTrue(ast.Lookup("attr"))
+    self.assertTrue(ast.Lookup("f"))
+
+  def test_relative_import_parent(self):
+    src = textwrap.dedent("""
+      from .. import attr  # type: ignore
+      def f(x: attr) -> None: ...
+    """)
+    ast = parser.parse_string(src, python_version=self.PYTHON_VERSION)
+    self.assertTrue(ast.Lookup("attr"))
+    self.assertTrue(ast.Lookup("f"))
+
+
 if __name__ == "__main__":
   unittest.main()
diff --git a/pytype/tools/analyze_project/config_test.py b/pytype/tools/analyze_project/config_test.py
--- a/pytype/tools/analyze_project/config_test.py
+++ b/pytype/tools/analyze_project/config_test.py
@@ -1,6 +1,7 @@
 """Tests for config.py."""
 
 import os
+import sys
 
 from pytype import datatypes
 from pytype import file_utils
@@ -113,6 +114,7 @@ class TestGenerateConfig(unittest.TestCase):
 
   @classmethod
   def setUpClass(cls):
+    super(TestGenerateConfig, cls).setUpClass()
     cls.parser = parse_args.make_parser()
 
   def test_bad_location(self):
@@ -141,6 +143,8 @@ def test_generate(self):
       expected_protocols = config._PYTYPE_SINGLE_ITEMS['protocols'].sample
       self.assertEqual(conf.pythonpath, expected_pythonpath)
       self.assertEqual(conf.protocols, expected_protocols)
+      self.assertEqual(conf.python_version,
+                       '{}.{}'.format(*sys.version_info[:2]))
 
   def test_read(self):
     with file_utils.Tempdir() as d: