Repository: quora/pyanalyze
Pull request #392 (2022-01-10 18:52:03)

fix register_error_code


Patch:
diff --git a/docs/changelog.md b/docs/changelog.md
index 457b75d..1dec264 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -2,6 +2,8 @@
 
 ## Unreleased
 
+- Fix interaction of `register_error_code()` with new
+  configuration mechanism (#391)
 - Check against invalid `Signature` objects and prepare
   for refactoring `Signature` compatibility logic (#390)
 - Treat `int` and `float` as compatible with `complex`,
diff --git a/pyanalyze/error_code.py b/pyanalyze/error_code.py
index 943cf79..16dd723 100644
--- a/pyanalyze/error_code.py
+++ b/pyanalyze/error_code.py
@@ -6,6 +6,7 @@ Error codes used by test_scope.
 
 import enum
 from aenum import extend_enum
+import pyanalyze
 
 from .find_unused import used
 
@@ -218,4 +219,14 @@ def register_error_code(name: str, description: str) -> ErrorCode:
     extend_enum(ErrorCode, name, value)
     member = ErrorCode[name]
     ERROR_DESCRIPTION[member] = description
+    type(
+        name,
+        (pyanalyze.options.BooleanOption,),
+        {
+            "__doc__": description,
+            "name": name,
+            "default_value": True,
+            "should_create_command_line_option": False,
+        },
+    )
     return member


Test patch:
diff --git a/pyanalyze/test_config.py b/pyanalyze/test_config.py
index cb22514..602315c 100644
--- a/pyanalyze/test_config.py
+++ b/pyanalyze/test_config.py
@@ -18,6 +18,7 @@ from .signature import (
     ParameterKind,
 )
 from .config import Config
+from .error_code import ErrorCode, register_error_code
 from . import tests
 from . import value
 
@@ -27,6 +28,11 @@ def _failing_impl(ctx: CallContext) -> value.Value:
     return value.AnyValue(value.AnySource.error)
 
 
+def _custom_code_impl(ctx: CallContext) -> value.Value:
+    ctx.show_error("Always errors", ErrorCode.internal_test)
+    return value.AnyValue(value.AnySource.error)
+
+
 class TestConfig(Config):
     """Configuration to run in test_scope's unit tests."""
 
@@ -73,6 +79,10 @@ class TestConfig(Config):
         failing_impl_sig = arg_spec_cache.get_argspec(
             tests.FailingImpl, impl=_failing_impl
         )
+        custom_sig = arg_spec_cache.get_argspec(
+            tests.custom_code, impl=_custom_code_impl
+        )
+        assert isinstance(custom_sig, Signature), custom_sig
         assert isinstance(failing_impl_sig, Signature), failing_impl_sig
         return {
             tests.takes_kwonly_argument: Signature.make(
@@ -87,6 +97,7 @@ class TestConfig(Config):
                 callable=tests.takes_kwonly_argument,
             ),
             tests.FailingImpl: failing_impl_sig,
+            tests.custom_code: custom_sig,
             tests.overloaded: OverloadedSignature(
                 [
                     Signature.make(
@@ -120,3 +131,5 @@ class TestConfig(Config):
 
 TEST_INSTANCES = [StubPath([Path(__file__).parent / "stubs"])]
 TEST_OPTIONS = Options.from_option_list(TEST_INSTANCES, TestConfig())
+
+register_error_code("internal_test", "Used in an internal test")
diff --git a/pyanalyze/test_error_code.py b/pyanalyze/test_error_code.py
new file mode 100644
index 0000000..8baf9a4
--- /dev/null
+++ b/pyanalyze/test_error_code.py
@@ -0,0 +1,11 @@
+# static analysis: ignore
+from .test_node_visitor import assert_passes
+from .test_name_check_visitor import TestNameCheckVisitorBase
+
+
+class TestRegisterErrorCode(TestNameCheckVisitorBase):
+    @assert_passes()
+    def test(self) -> None:
+        from pyanalyze.tests import custom_code
+
+        custom_code()  # E: internal_test
diff --git a/pyanalyze/tests.py b/pyanalyze/tests.py
index 34a3433..072fe61 100644
--- a/pyanalyze/tests.py
+++ b/pyanalyze/tests.py
@@ -205,6 +205,10 @@ class FailingImpl:
         pass
 
 
+def custom_code() -> None:
+    pass
+
+
 @overload
 def overloaded() -> int:
     ...