Repository: zulip/zulip

Issue:
Add lint check for explicit python invocations
(Split from #2378.)

The following are some regexes to check for explicit `python` invocations and incorrect `python` shebang lines that may interfere with the Python 3 transition.

```python
def looks_like_python_args():
    yield '-'
    yield '/'
    yield r'\./'
    yield r'\.\./'
    for fpath in lister.list_files(ftypes=['py']):
        while True:
            yield re.escape(fpath)
            try:
                topdir, fpath = fpath.split(os.path.sep)
            except ValueError:
                break

bad_python_call_re = '''python[0-9.]*[ ,"']+(?:''' + '|'.join(set(looks_like_python_args())) + ')'
bad_python_shebang_re = '^#!(?!/usr/bin/env python$).*python'
```

We want to match the first one against all files (including random config files that don’t currently have a recognized file type), not just `py` files. Tim says we don't currently have a nice way to do that.


Discussion:
The closest we have to a mechanism for doing that is to add this to `whitespace_rules` (and then rename it).  Might make sense to just add it as a new list that is checked explicitly against all files; it would probably be a pretty small amount of code in `tools/lint-all`.
@timabbott I've just claimed the task from GCI, Could you explain me the issue please
> The basic idea is pretty simple--we want to remove uses of python2 and python3 in shebangs and in places where we call out to python programs, and then we want a lint rule to prevent future occurrences. I just think the implementation is kind of tricky.

Source: https://chat.zulip.org/#narrow/near/85427/stream/GCI.20help/topic/Issue.20.232435

Resolving patch:
diff --git a/zerver/lib/cache.py b/zerver/lib/cache.py
--- a/zerver/lib/cache.py
+++ b/zerver/lib/cache.py
@@ -312,7 +312,7 @@ def user_profile_by_id_cache_key(user_profile_id):
     return u"user_profile_by_id:%s" % (user_profile_id,)
 
 # TODO: Refactor these cache helpers into another file that can import
-# models.py so that python3-style type annotations can also work.
+# models.py so that python v3 style type annotations can also work.
 
 def cache_save_user_profile(user_profile):
     # type: (UserProfile) -> None


Test patch:
diff --git a/tools/tests/test_css_parser.py b/tools/tests/test_css_parser.py
--- a/tools/tests/test_css_parser.py
+++ b/tools/tests/test_css_parser.py
@@ -19,7 +19,7 @@
 class ParserTestHappyPath(unittest.TestCase):
     def __init__(self, *args, **kwargs):
         # type: (*Any, **Any) -> None
-        # This method should be remove when we quit from python2
+        # This method should be removed when we migrate to version 3 of Python
         import six
         if six.PY2:
             self.assertRaisesRegex = self.assertRaisesRegexp  # type: ignore
@@ -136,7 +136,7 @@ class ParserTestSadPath(unittest.TestCase):
     '''
     def __init__(self, *args, **kwargs):
         # type: (*Any, **Any) -> None
-        # This method should be remove when we quit from python2
+        # This method should be removed when we migrate to version 3 of Python
         import six
         if six.PY2:
             self.assertRaisesRegex = self.assertRaisesRegexp  # type: ignore
diff --git a/tools/tests/test_template_parser.py b/tools/tests/test_template_parser.py
--- a/tools/tests/test_template_parser.py
+++ b/tools/tests/test_template_parser.py
@@ -20,7 +20,7 @@
 class ParserTest(unittest.TestCase):
     def __init__(self, *args, **kwargs):
         # type: (*Any, **Any) -> None
-        # This method should be remove when we quit from python2
+        # This method should be removed when we migrate to version 3 of Python
         import six
         if six.PY2:
             self.assertRaisesRegex = self.assertRaisesRegexp  # type: ignore
diff --git a/zerver/lib/test_classes.py b/zerver/lib/test_classes.py
--- a/zerver/lib/test_classes.py
+++ b/zerver/lib/test_classes.py
@@ -80,7 +80,7 @@ class ZulipTestCase(TestCase):
     '''
     def __init__(self, *args, **kwargs):
         # type: (*Any, **Any) -> None
-        # This method should be remove when we quit from python2
+        # This method should be removed when we migrate to version 3 of Python
         import six
         if six.PY2:
             self.assertRaisesRegex = self.assertRaisesRegexp
diff --git a/zerver/tests/test_decorators.py b/zerver/tests/test_decorators.py
--- a/zerver/tests/test_decorators.py
+++ b/zerver/tests/test_decorators.py
@@ -40,7 +40,7 @@
 class DecoratorTestCase(TestCase):
     def __init__(self, *args, **kwargs):
         # type: (*Any, **Any) -> None
-        # This method should be remove when we quit from python2
+        # This method should be removed when we migrate to version 3 of Python
         import six
         if six.PY2:
             self.assertRaisesRegex = self.assertRaisesRegexp