Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,23 @@ Features detected include v2/v3 ``print expr`` and ``print(expr)``, ``long``, f-
asynchronous comprehensions, ``await`` in comprehensions, asynchronous ``for``-loops, boolean
constants, named expressions, keyword-only parameters, positional-only parameters, ``nonlocal``,
``yield from``, exception context cause (``raise .. from ..``), ``except*``, ``set`` literals,
``set`` comprehensions, ``dict`` comprehensions, infix matrix multiplication, ``"..".format(..)``,
imports (``import X``, ``from X import Y``, ``from X import *``), function calls wrt. name and
kwargs, ``strftime`` + ``strptime`` directives used, function and variable annotations (also
``Final`` and ``Literal``), ``continue`` in ``finally`` block, modular inverse ``pow()``, array
typecodes, codecs error handler names, encodings, ``%`` formatting and directives for bytes and
bytearray, ``with`` statement, asynchronous ``with`` statement, multiple context expressions in a
``with`` statement, multiple context expressions in a ``with`` statement grouped with parenthesis,
unpacking assignment, generalized unpacking, ellipsis literal (``...``) out of slices, dictionary
union (``{..} | {..}``), dictionary union merge (``a = {..}; a |= {..}``), builtin generic type
annotations (``list[str]``), function decorators, class decorators, relaxed decorators,
``metaclass`` class keyword, pattern matching with ``match``, union types written as ``X | Y``, type
alias statements (``type X = SomeType``), type alias statements with lambdas/comprehensions in class
scopes, generic classes (``class C[T]: ...``), and template string literals (``t'{var}'``). It tries
to detect and ignore user-defined functions, classes, arguments, and variables with names that clash
with library-defined symbols.
``set`` comprehensions, ``dict`` comprehensions, unpacking in comprehension value expressions (``[*x
for x in range(10)]``), infix matrix multiplication, ``"..".format(..)``, imports (``import X``,
``from X import Y``, ``from X import *``), function calls wrt. name and kwargs, ``strftime`` +
``strptime`` directives used, function and variable annotations (also ``Final`` and ``Literal``),
``continue`` in ``finally`` block, modular inverse ``pow()``, array typecodes, codecs error handler
names, encodings, ``%`` formatting and directives for bytes and bytearray, ``with`` statement,
asynchronous ``with`` statement, multiple context expressions in a ``with`` statement, multiple
context expressions in a ``with`` statement grouped with parenthesis, unpacking assignment,
generalized unpacking, ellipsis literal (``...``) out of slices, dictionary union (``{..} |
{..}``), dictionary union merge (``a = {..}; a |= {..}``), builtin generic type annotations
(``list[str]``), function decorators, class decorators, relaxed decorators, ``metaclass`` class
keyword, pattern matching with ``match``, union types written as ``X | Y``, type alias statements
(``type X = SomeType``), type alias statements with lambdas/comprehensions in class scopes, generic
classes (``class C[T]: ...``), template string literals (``t'{var}'``), lazy imports (``lazy
import``, ``lazy from ... import``), special module attributes like ``__lazy_modules__``, and slice
type subscription (``slice[1:2:3]``). It tries to detect and ignore user-defined functions, classes,
arguments, and variables with names that clash with library-defined symbols.

Caveats
=======
Expand Down
6 changes: 6 additions & 0 deletions tests/builtin_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ def test_ExceptionGroup(self):

def test_BaseExceptionGroup(self):
self.assertOnlyIn((3, 11), self.detect("BaseExceptionGroup()"))

def test_frozendict(self):
self.assertOnlyIn((3, 15), self.detect("frozendict()"))

def test_sentinel(self):
self.assertOnlyIn((3, 15), self.detect("sentinel()"))
24 changes: 24 additions & 0 deletions tests/class.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ def test_RawConfigParser_of_ConfigParser(self):
def test_SafeConfigParser_of_ConfigParser(self):
self.assertOnlyIn((2, 3), self.detect("from ConfigParser import SafeConfigParser"))

def test_ExtendedInterpolation_of_configparser(self):
self.assertOnlyIn((3, 2), self.detect("from configparser import ExtendedInterpolation"))

def test_LifoQueue_of_Queue(self):
self.assertOnlyIn((2, 6), self.detect("from Queue import LifoQueue"))

Expand All @@ -19,9 +22,15 @@ def test_PriorityQueue_of_Queue(self):
def test_ABC_of_abc(self):
self.assertOnlyIn((3, 4), self.detect("from abc import ABC"))

def test_Format_of_annotationlib(self):
self.assertOnlyIn((3, 14), self.detect("from annotationlib import Format"))

def test_BooleanOptionalAction_of_argparse(self):
self.assertOnlyIn((3, 9), self.detect("from argparse import BooleanOptionalAction"))

def test_Constant_of_ast(self):
self.assertOnlyIn((3, 6), self.detect("from ast import Constant"))

def test_Barrier_of_asyncio(self):
self.assertOnlyIn((3, 11), self.detect("from asyncio import Barrier"))

Expand Down Expand Up @@ -428,6 +437,12 @@ def test_Formatter_of_string(self):
def test_Template_of_string(self):
self.assertOnlyIn(((2, 4), (3, 0)), self.detect("from string import Template"))

def test_Interpolation_of_string_templatelib(self):
self.assertOnlyIn((3, 14), self.detect("from string.templatelib import Interpolation"))

def test_Template_of_string_templatelib(self):
self.assertOnlyIn((3, 14), self.detect("from string.templatelib import Template"))

def test_Struct_of_struct(self):
self.assertOnlyIn(((2, 5), (3, 0)), self.detect("from struct import Struct"))

Expand Down Expand Up @@ -461,6 +476,9 @@ def test_Barrier_of_threading(self):
def test_local_of_threading(self):
self.assertOnlyIn(((2, 4), (3, 0)), self.detect("from threading import local"))

def test_ttk_of_tkinter(self):
self.assertOnlyIn((3, 1), self.detect("from tkinter import ttk"))

def test_struct_time_of_time(self):
self.assertOnlyIn(((2, 2), (3, 0)), self.detect("from time import struct_time"))

Expand Down Expand Up @@ -539,6 +557,9 @@ def test_EnumCheck_of_enum(self):
def test_EnumDict_of_enum(self):
self.assertOnlyIn((3, 13), self.detect("from enum import EnumDict"))

def test_EnumType_of_enum(self):
self.assertOnlyIn((3, 11), self.detect("from enum import EnumType"))

def test_Flag_of_enum(self):
self.assertOnlyIn((3, 6), self.detect("from enum import Flag"))

Expand All @@ -548,6 +569,9 @@ def test_FlagBoundary_of_enum(self):
def test_IntFlag_of_enum(self):
self.assertOnlyIn((3, 6), self.detect("from enum import IntFlag"))

def test_ReprEnum_of_enum(self):
self.assertOnlyIn((3, 11), self.detect("from enum import ReprEnum"))

def test_StrEnum_of_enum(self):
self.assertOnlyIn((3, 11), self.detect("from enum import StrEnum"))

Expand Down
53 changes: 53 additions & 0 deletions tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ def test_line_number_of_dis_Instruction(self):
def test_cache_info_of_dis_Instruction(self):
self.assertOnlyIn((3, 13), self.detect("from dis import Instruction\nInstruction.cache_info"))

def test_hasarg_of_dis(self):
self.assertOnlyIn((3, 12), self.detect("from dis import hasarg"))

def test_hasexc_of_dis(self):
self.assertOnlyIn((3, 12), self.detect("from dis import hasexc"))

def test_skips_of_doctest_DocTestRunner(self):
self.assertOnlyIn((3, 13),
self.detect("from doctest import DocTestRunner\nDocTestRunner.skips"))
Expand All @@ -100,6 +106,24 @@ def test_verify_generated_headers_of_email_policy_Policy(self):
self.assertOnlyIn((3, 13), self.detect("""
from email.policy import Policy
Policy.verify_generated_headers
"""))

def test_FORWARDREF_of_annotationlib_Format(self):
self.assertOnlyIn((3, 14),
self.detect("from annotationlib import Format\nFormat.FORWARDREF"))

def test_STRING_of_annotationlib_Format(self):
self.assertOnlyIn((3, 14),
self.detect("from annotationlib import Format\nFormat.STRING"))

def test_VALUE_of_annotationlib_Format(self):
self.assertOnlyIn((3, 14),
self.detect("from annotationlib import Format\nFormat.VALUE"))

def test_VALUE_WITH_FAKE_GLOBALS_of_annotationlib_Format(self):
self.assertOnlyIn((3, 14), self.detect("""
from annotationlib import Format
Format.VALUE_WITH_FAKE_GLOBALS
"""))

def test_mode_of_lzma_LZMAFile(self):
Expand Down Expand Up @@ -1384,6 +1408,11 @@ def test_message_factory_from_email_policy_Policy(self):
self.detect("from email.policy import Policy\n"
"Policy().message_factory"))

def test_utf8_of_email_policy_EmailPolicy(self):
self.assertOnlyIn((3, 5),
self.detect("from email.policy import EmailPolicy\n"
"EmailPolicy.utf8"))

def test_EHWPOISON_of_errno(self):
self.assertOnlyIn((3, 14), self.detect("from errno import EHWPOISON"))

Expand Down Expand Up @@ -3387,6 +3416,9 @@ def test_minor_from_sys_version_info(self):
self.detect("from sys import version_info\n"
"version_info().minor"))

def test_monitoring_of_sys(self):
self.assertOnlyIn((3, 12), self.detect("from sys import monitoring"))

def test_releaselevel_from_sys_version_info(self):
self.assertOnlyIn(((2, 7), (3, 0)),
self.detect("from sys import version_info\n"
Expand Down Expand Up @@ -3520,6 +3552,9 @@ def test___spec___from_types_ModuleType(self):
self.detect("from types import ModuleType\n"
"ModuleType().__spec__"))

def test___name___of_property(self):
self.assertOnlyIn((3, 13), self.detect("property.__name__"))

def test_NoneType_of_types(self):
self.assertOnlyIn(((2, 0), (3, 10)), self.detect("from types import NoneType"))

Expand Down Expand Up @@ -3950,3 +3985,21 @@ def test_kwargs_of_unittest_mock_Mock_call_args(self):

def test_status_of_urllib_response_addinfourl(self):
self.assertOnlyIn((3, 9), self.detect("from urllib.response.addinfourl import status"))

def test_RLIMIT_NTHR_of_resource(self):
self.assertOnlyIn((3, 15), self.detect("from resource import RLIMIT_NTHR"))

def test_RLIMIT_THREADS_of_resource(self):
self.assertOnlyIn((3, 15), self.detect("from resource import RLIMIT_THREADS"))

def test_RLIMIT_UMTXP_of_resource(self):
self.assertOnlyIn((3, 15), self.detect("from resource import RLIMIT_UMTXP"))

def test_RLIM_SAVED_CUR_of_resource(self):
self.assertOnlyIn((3, 15), self.detect("from resource import RLIM_SAVED_CUR"))

def test_RLIM_SAVED_MAX_of_resource(self):
self.assertOnlyIn((3, 15), self.detect("from resource import RLIM_SAVED_MAX"))

def test_HAS_PSK_TLS13_of_ssl(self):
self.assertOnlyIn((3, 15), self.detect("from ssl import HAS_PSK_TLS13"))
3 changes: 3 additions & 0 deletions tests/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,6 @@ def foo(): pass""")

def test_deprecated_of_warnings(self):
self.assertOnlyIn((3, 13), self.detect("from warnings import deprecated"))

def test_disjoint_base_of_typing(self):
self.assertOnlyIn((3, 15), self.detect("from typing import disjoint_base"))
3 changes: 3 additions & 0 deletions tests/exception.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from .testutils import VerminTest

class VerminExceptionMemberTests(VerminTest):
def test_BrokenBarrierError_of_asyncio(self):
self.assertOnlyIn((3, 11), self.detect("from asyncio import BrokenBarrierError"))

def test_QueueShutDown_of_asyncio(self):
self.assertOnlyIn((3, 13), self.detect("from asyncio import QueueShutDown"))

Expand Down
Loading
Loading