PyPI / sqlalchemy / 2.1.5

sqlalchemy 2.1.5

Source
https://github.com/sqlalchemy/sqlalchemy
Tag scanned
rel_2_1_5
Compared with
rel_2_1_4 (0 signals introduced since)
Files
879 scanned, 17 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 0 warn · 46 info
Scan time
40.3 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 42 of 42 warn and critical signals; 42 demoted to info.
Disclude version
4.1.0
Scanned (UTC)
2026-10-22 00:29

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. info critical → info by review dynamic-import examples/performance/__init__.py:335:21

    `__import__` called on a non-literal expression (ast pass, confidence 0.90)

                    try:
                        __import__(__name__ + "." + potential_name)
                    except ImportError:
                        pass
    likely benign LLM, confidence 0.85 Dynamically imports example profiler modules by name.
    Reasoning

    Imports a module named from a runtime string built from the package name and a discovered name, inside a try/except ImportError. This is the usual plugin-discovery pattern for example modules, with nothing fetched from outside or hidden.

  2. info critical → info by review dynamic-import examples/performance/__init__.py:394:13

    `__import__` called on a non-literal expression (ast pass, confidence 0.90)

            if cls.name is None:
                __import__(__name__ + "." + args.name)
    
            Profiler(args).run()
    likely benign LLM, confidence 0.85 Imports the selected example module from a CLI argument.
    Reasoning

    Same pattern as the sibling finding: it imports the module named by a command-line argument under the package. It is a developer-facing example runner with no obfuscation.

  3. info critical → info by review dynamic-import lib/sqlalchemy/dialects/__init__.py:48:22

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            else:
                module = __import__("sqlalchemy.dialects.%s" % (dialect,)).dialects
                module = getattr(module, dialect)
        except ImportError:
    likely benign LLM, confidence 0.92 Loads a SQLAlchemy dialect module by name.
    Reasoning

    Loads a dialect package by name from the sqlalchemy.dialects namespace, then falls back when ImportError occurs. This is the standard SQLAlchemy dialect plugin loader, restricted to its own package.

  4. info critical → info by review dynamic-import lib/sqlalchemy/dialects/mysql/mariadb.py:49:19

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

    def loader(driver: str) -> type[MariaDBDialect]:
        dialect_mod = __import__(
            "sqlalchemy.dialects.mysql.%s" % driver
        ).dialects.mysql
    likely benign LLM, confidence 0.92 Loads the MariaDB driver dialect module by driver name.
    Reasoning

    Imports a MySQL driver submodule under sqlalchemy.dialects.mysql using a driver string. It is a standard dialect loader inside the library's own namespace.

  5. info critical → info by review dynamic-import lib/sqlalchemy/dialects/mysql/mariadbconnector.py:210:32

    `__import__` called on a non-literal expression (ast pass, confidence 0.90)

                try:
                    CLIENT_FLAGS = __import__(
                        self.dbapi.__name__ + ".constants.CLIENT"
                    ).constants.CLIENT
    likely benign LLM, confidence 0.90 Reads CLIENT flag constants from the MariaDB connector module.
    Reasoning

    Imports the constants submodule of the DBAPI module the user already loaded, then reads CLIENT flags, inside a guarded try. This is routine compatibility code.

  6. info critical → info by review dynamic-import lib/sqlalchemy/dialects/mysql/mysqldb.py:260:32

    `__import__` called on a non-literal expression (ast pass, confidence 0.90)

                try:
                    CLIENT_FLAGS = __import__(
                        self.dbapi.__name__ + ".constants.CLIENT"
                    ).constants.CLIENT
    likely benign LLM, confidence 0.90 Reads CLIENT flag constants from the mysqlclient DBAPI module.
    Reasoning

    Same constants-import compatibility pattern as the mariadbconnector finding, derived from the loaded DBAPI module name, with no hidden behavior.

  7. info critical → info by review dynamic-import lib/sqlalchemy/engine/default.py:742:13

    `__import__` called on a non-literal expression (ast pass, confidence 0.90)

            try:
                __import__(package + ".provision")
            except ImportError:
                pass
    likely benign LLM, confidence 0.90 Optionally imports a package's provision submodule.
    Reasoning

    Imports an optional provision submodule of the given package and ignores ImportError. This is the optional test-provisioning hook pattern.

  8. info warn → info by review dynamic-attribute lib/sqlalchemy/event/base.py:335:9

    reach-by-name through `globals` (ast pass, confidence 0.60)

            # establish pickle capability by adding it to this module
            globals()[klass.__name__] = klass
    likely benign LLM, confidence 0.90 Registers a generated class in module globals for pickling.
    Reasoning

    Registers a class in module globals so pickle can find it, as the comment states. This is a common, documented technique for pickle support.

  9. info warn → info by review dynamic-execution lib/sqlalchemy/orm/clsregistry.py:592:21

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

                try:
                    x = eval(self.arg, globals(), self._dict)
    
                    if isinstance(x, _GetColumns):
    likely benign LLM, confidence 0.80 Evaluates developer-supplied declarative expression strings.
    Reasoning

    eval runs a string argument, such as a relationship expression supplied by the developer in model declarations, against restricted namespaces. It is an intentional, documented ORM feature, though eval on strings is a dynamic-execution pattern worth noting.

  10. info warn → info by review dynamic-attribute lib/sqlalchemy/sql/annotation.py:562:5

    reach-by-name through `globals` (ast pass, confidence 0.60)

        )
        globals()["Annotated%s" % cls.__name__] = anno_cls
    
        if "_traverse_internals" in cls.__dict__:
    likely benign LLM, confidence 0.90 Publishes a generated Annotated class into module globals.
    Reasoning

    Assigns a generated Annotated class into module globals by name, which is a standard way to make generated classes importable and picklable. Nothing suggests hiding.

  11. info warn → info by review dynamic-attribute lib/sqlalchemy/sql/coercions.py:1366:20

    reach-by-name through `globals` (ast pass, confidence 0.60)

            if name in globals():
                impl = globals()[name](cls)
                _impl_lookup[cls] = impl
    likely benign LLM, confidence 0.90 Dispatches coercion implementations via module-global lookup.
    Reasoning

    Looks up a class by name in module globals to build a coercion implementation. This is internal registry dispatch, not hidden behavior.

  12. info warn → info by review dynamic-execution lib/sqlalchemy/sql/lambdas.py:1264:9

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

            vars_ = {"o%d" % i: cell_values[i] for i in argrange}
            exec(code, vars_, vars_)
            closure = vars_["make_cells"]()
    likely benign LLM, confidence 0.80 Executes generated code to rebuild lambda closure cells.
    Reasoning

    exec runs code generated internally from lambda closure cell values to rebuild closures, a known performance technique. The code is produced by the library rather than taken from outside input.

  13. info critical → info by review dynamic-import lib/sqlalchemy/testing/engines.py:250:17

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                mod = getattr(
                    __import__("sqlalchemy.dialects.%s" % name).dialects, name
                )
            yield mod.dialect()
    likely benign LLM, confidence 0.90 Imports a dialect module for test engine setup.
    Reasoning

    Imports a dialect module by name inside the SQLAlchemy test engine helper, which is expected in test tooling.

  14. info warn → info by review frame-introspection lib/sqlalchemy/testing/fixtures/mypy.py:118:27

    `inspect.stack` — call-stack frame introspection (ast pass, confidence 0.70)

            else:
                caller_path = inspect.stack()[1].filename
                path = os.path.join(os.path.dirname(caller_path), dirname)
            files = list(Path(path).glob("**/*.py"))
    likely benign LLM, confidence 0.90 Finds the caller's directory to locate mypy test fixtures.
    Reasoning

    Uses inspect.stack to find the caller's file path so tests can locate fixture files. This is a common test-helper technique with no evasion.

  15. info critical → info by review dynamic-import lib/sqlalchemy/testing/plugin/plugin_base.py:487:11

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

        # late
        mod = __import__(modname)
        for component in modname.split(".")[1:]:
            mod = getattr(mod, component)
    likely benign LLM, confidence 0.90 Imports a test module by dotted name and walks its attributes.
    Reasoning

    Imports a module from a name in the testing plugin, then walks its attributes. This is standard test plugin loading.

  16. info warn → info by review dynamic-execution lib/sqlalchemy/testing/plugin/pytestplugin.py:671:9

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

            # in format_argpsec_plus()
            exec(code, env)
            return env[fn_name]
    likely benign LLM, confidence 0.80 Execs generated source to create a function with a matching signature.
    Reasoning

    exec builds a function from generated source for a signature-preserving wrapper, as the comment indicates. This is a common decorator-generation technique within the library.

  17. info warn → info by review frame-introspection lib/sqlalchemy/testing/schema.py:192:18

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

        try:
            module = sys._getframe(1).f_globals.get("__name__", "__main__")
        except (AttributeError, ValueError):
            pass
    likely benign LLM, confidence 0.90 Reads the caller's module name via sys._getframe in a testing helper.
    Reasoning

    sys._getframe(1) reads the caller's module name to set a default __module__ on a test schema object. It is a routine introspection idiom and the call is guarded by try/except. Nothing here is hidden or malicious.

  18. identifier `é試蛇ẟΩ` mixes scripts: Latin + Han + Greek (in string/comment) (raw pass, confidence 0.40)

                metadata,
                Column("unicode", Integer, comment="é試蛇ẟΩ"),
                Column("emoji", Integer, comment="☁⟨U+FE0F⟩✨"),
                comment="試蛇ẟΩ✨",
  19. identifier `試蛇ẟΩ` mixes scripts: Han + Latin + Greek (in string/comment) (raw pass, confidence 0.40)

                Column("emoji", Integer, comment="☁⟨U+FE0F⟩✨"),
                comment="試蛇ẟΩ✨",
            )
  20. identifier `試蛇ẟΩ` mixes scripts: Han + Latin + Greek (in string/comment) (raw pass, confidence 0.40)

            tc = insp.get_table_comment("unicode_comments")
            eq_(tc, {"text": "試蛇ẟΩ✨"})
    
            cols = insp.get_columns("unicode_comments")
  21. identifier `é試蛇ẟΩ` mixes scripts: Latin + Han + Greek (in string/comment) (raw pass, confidence 0.40)

            value = {c["name"]: c["comment"] for c in cols}
            exp = {"unicode": "é試蛇ẟΩ", "emoji": "☁⟨U+FE0F⟩✨"}
            eq_(value, exp)
  22. info warn → info by review dynamic-execution lib/sqlalchemy/util/langhelpers.py:453:16

    `compile` called on a non-literal expression (ast pass, confidence 0.70)

                linecache_cache[filename] = entry
            code = compile(code, filename, "exec")
    
        exec(code, env)
    likely benign LLM, confidence 0.85 Compiles generated wrapper source code for a decorator helper.
    Reasoning

    This is the standard decorator-generation pattern: source text for a wrapper function is built from a signature, compiled with a real filename, cached in linecache, and exec'd. SQLAlchemy uses it to produce signature-preserving wrappers. It is a legitimate code-generation idiom, not obfuscation.

  23. info warn → info by review dynamic-execution lib/sqlalchemy/util/langhelpers.py:455:5

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

    
        exec(code, env)
        fn = env[fn_name]
    likely benign LLM, confidence 0.85 Executes generated wrapper source to produce a function object.
    Reasoning

    This exec runs the code object compiled from generated wrapper source in a fresh namespace and then pulls out the named function. It is the second half of the same legitimate code-generation helper.

  24. info critical → info by review dynamic-import lib/sqlalchemy/util/langhelpers.py:507:19

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            def load():
                mod = __import__(modulepath)
                for token in modulepath.split(".")[1:]:
                    mod = getattr(mod, token)
    likely benign LLM, confidence 0.90 Lazily imports a module from a dotted path string.
    Reasoning

    This is a lazy dotted-path loader that imports a module named by a string and walks attributes to reach the target. It is a documented utility for deferred imports. The module path comes from library code, not from untrusted input.

  25. info critical → info by review frame-introspection lib/sqlalchemy/util/langhelpers.py:2060:17

    `sys._getframe` — call-stack frame introspection — file also calls `sys.exit`/`exec`/`eval` (anti-analysis shape) (ast pass, confidence 0.85)

        try:
            frame = sys._getframe(stacklevel)
        except ValueError:
            # being called from less than 3 (or given) stacklevels, weird,
    likely benign LLM, confidence 0.90 Inspects the caller stack frame to attribute a warning location.
    Reasoning

    sys._getframe(stacklevel) is used by the deprecation-warning helper to attribute warnings to the correct caller. The critical severity comes only from the file also containing sys.exit or exec, which is normal for a library this size. There is no anti-analysis behavior.

  26. info warn → info by review dynamic-execution lib/sqlalchemy/util/langhelpers.py:2163:5

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

        env = locals().copy()
        exec(code, env)
        return env["set"]
    likely benign LLM, confidence 0.85 Executes generated source to build a helper function.
    Reasoning

    This exec runs generated source text in a namespace built from locals and returns a set function from it. It is the same kind of compatibility or code-generation helper seen elsewhere in this file.

  27. info critical → info by review dynamic-import lib/sqlalchemy/util/preloaded.py:142:17

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

                ) and key not in self.__dict__:
                    __import__(module, globals(), locals())
                    self.__dict__[key] = globals()[key] = sys.modules[module]
    likely benign LLM, confidence 0.90 Lazily imports a named module on first attribute access.
    Reasoning

    This is a lazy module loader that imports a named module on first attribute access and caches it in the instance and globals. It is a standard deferred-import pattern for avoiding circular imports.

  28. info warn → info by review dynamic-attribute lib/sqlalchemy/util/preloaded.py:143:38

    reach-by-name through `globals` (ast pass, confidence 0.60)

                    __import__(module, globals(), locals())
                    self.__dict__[key] = globals()[key] = sys.modules[module]
    likely benign LLM, confidence 0.85 Caches a lazily imported module into globals and the instance dict.
    Reasoning

    The globals() lookup is the cache write-back that follows the lazy import on the line above. It stores the loaded module under its key. It is part of the same ordinary lazy-loading mechanism.

  29. info warn → info by review dynamic-execution lib/sqlalchemy/util/typing.py:265:26

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

    
                annotation = eval(expression, cls_namespace, locals_)
            else:
                annotation = eval(expression, base_globals, locals_)
    likely benign LLM, confidence 0.85 Evaluates a string type annotation within class namespaces.
    Reasoning

    eval resolves string type annotations (for example forward references) against the class and module namespaces. This is the expected behavior of typing-introspection code. The input is annotation text from source code, not attacker-controlled runtime data.

  30. info warn → info by review dynamic-execution lib/sqlalchemy/util/typing.py:267:26

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

            else:
                annotation = eval(expression, base_globals, locals_)
        except Exception as err:
            raise NameError(
    likely benign LLM, confidence 0.85 Evaluates a string annotation against base module globals as a fallback.
    Reasoning

    This is the fallback branch of the same annotation resolver, evaluating the string against the base module globals. It is ordinary typing-introspection code.

  31. info warn → info by review dynamic-execution test/base/test_typing_utils.py:243:5

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

        scope = {}
        exec(code, None, scope)
        if len(vars) == 1:
            return scope[vars[0]]
    likely benign LLM, confidence 0.80 Executes a test snippet in a scratch scope to obtain typed variables.
    Reasoning

    This test helper execs a snippet of source to define variables for typing tests. It is confined to the test suite and uses a local scope dict. Nothing suggests hidden or malicious behavior.

  32. info critical → info by review dynamic-execution test/conftest.py:56:12

    `compile` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

    with open(bootstrap_file) as f:
        code = compile(f.read(), "bootstrap.py", "exec")
        to_bootstrap = "pytest"
        exec(code, globals(), locals())
    likely benign LLM, confidence 0.80 Compiles the repo's own bootstrap.py file at conftest import time.
    Reasoning

    The conftest reads bootstrap.py from the repository's own test directory and compiles it. This is the usual bootstrap for the SQLAlchemy pytest plugin. The path comes from the repo, not from a remote or encoded source. The critical rating reflects the module-scope exec, not hidden content.

  33. info critical → info by review dynamic-execution test/conftest.py:58:5

    `exec` at module scope (runs on import) on a non-literal expression (ast pass, confidence 0.80)

        to_bootstrap = "pytest"
        exec(code, globals(), locals())
        from sqla_pytestplugin import *  # noqa
    likely benign LLM, confidence 0.80 Executes the local bootstrap code to set up the pytest plugin.
    Reasoning

    This exec runs the locally compiled bootstrap.py to load the pytest plugin. It is a known test-harness pattern in this project. The source is a local file in the repo, which is the main thing to check for supply-chain concerns, and it appears ordinary.

  34. info warn → info by review dynamic-execution test/dialect/mysql/test_types.py:202:29

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

            # test that repr() copies out all arguments
            self.assert_compile(eval("mysql.%r" % type_inst), res)
    
        @testing.combinations(
    likely benign LLM, confidence 0.90 Evaluates the repr of a MySQL type instance to check round-trip output.
    Reasoning

    eval is applied to a repr() of a type instance that is constructed in the test itself, so the input is trusted and controlled. It is a common round-trip test for repr output.

  35. info critical → info by review dynamic-import test/dialect/postgresql/test_dialect.py:1271:40

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            if psycopg.__version__.startswith("3"):
                TransactionRollbackError = __import__(
                    "%s.errors" % psycopg.__name__
                ).errors.TransactionRollback
    likely benign LLM, confidence 0.90 Dynamically imports the psycopg errors module for version compatibility.
    Reasoning

    This dynamically imports the psycopg errors submodule to pick the right exception class for the installed driver version. It is a standard compatibility shim, and the module name comes from the driver's own __name__.

  36. info critical → info by review dynamic-import test/dialect/postgresql/test_dialect.py:1275:40

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            else:
                TransactionRollbackError = __import__(
                    "%s.extensions" % psycopg.__name__
                ).extensions.TransactionRollbackError
    likely benign LLM, confidence 0.90 Dynamically imports the psycopg extensions module for version compatibility.
    Reasoning

    This is the psycopg2 branch of the same compatibility shim, importing the extensions submodule via the driver's __name__. It is benign driver-version handling.

  37. info critical → info by review dynamic-import test/dialect/test_all.py:9:21

    `__import__` called on a non-literal expression (ast pass, confidence 0.70)

            return [
                getattr(__import__("sqlalchemy.dialects.%s" % d).dialects, d)
                for d in dialects.__all__
                if not d.startswith("_")
    likely benign LLM, confidence 0.93 Dynamic import of SQLAlchemy dialect modules in a test helper.
    Reasoning

    The __import__ call builds a module name from a loop over the package's own dialects.__all__ list, filtered to skip names starting with an underscore. The input is a fixed internal list, not attacker-controlled data, which is a standard way to load dialect modules in a test suite.

  38. info warn → info by review dynamic-execution test/engine/test_parseconnect.py:541:13

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

            ):
                exec(
                    "from sqlalchemy.dialects import %s\ndialect = "
                    "%s.dialect()" % (name, name),
    likely benign LLM, confidence 0.90 exec of a templated dialect import inside a connection-parsing test.
    Reasoning

    The exec string is a fixed template that imports a dialect module by name and instantiates its dialect class. The name comes from the test's own parameter list, so this is test scaffolding for URL parsing and not a payload.

  39. info warn → info by review decoder-import-with-exec test/ext/test_associationproxy.py:918:21

    file imports decoder module(s) pickle and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)

    
                        exec("p.children %s other" % op)
                        exec("control %s other" % op)
    likely benign LLM, confidence 0.88 Test exec of operator expressions, flagged by the decoder-plus-exec heuristic.
    Reasoning

    The exec strings are built from a fixed set of comparison operators in a test that checks operator behaviour on association proxies. The pickle import co-occurs with this test scaffolding, not with any decode-then-run chain. The multi-stage flag is a heuristic false positive here.

  40. info warn → info by review dynamic-execution test/ext/test_associationproxy.py:918:21

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

    
                        exec("p.children %s other" % op)
                        exec("control %s other" % op)
    likely benign LLM, confidence 0.90 exec of a formatted operator expression in an association proxy test.
    Reasoning

    The same exec of an operator-template string, where op is drawn from a fixed test list. It is generated test code with no external input.

  41. info warn → info by review dynamic-execution test/ext/test_associationproxy.py:919:21

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

                        exec("p.children %s other" % op)
                        exec("control %s other" % op)
    
                        try:
    likely benign LLM, confidence 0.90 exec of a formatted comparison in an association proxy test.
    Reasoning

    This exec runs a formatted expression built from a fixed operator in a test loop. No untrusted input reaches it.

  42. info warn → info by review dynamic-execution test/orm/test_inspect.py:513:9

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

    
            exec(code, glbls)
            return names, glbls[clsname]
    likely benign LLM, confidence 0.90 exec of locally generated class source in an ORM inspection test.
    Reasoning

    The exec runs generated class-definition code inside a test helper that builds a mapped class with a given name and returns its names. The code is produced locally by the test, so this is dynamic class creation for testing.

  43. info critical → info by review dynamic-execution test/perf/orm2010.py:167:9

    `os.system` called on a non-literal command — runtime-determined shell invocation (ast pass, confidence 0.85)

        if runsnake:
            os.system("runsnake %s" % filename)
    likely benign LLM, confidence 0.85 os.system call to open a profiling output file with the runsnake viewer.
    Reasoning

    This is a performance script that optionally launches the local runsnake profile viewer on a file the script itself produced. Shell invocation with a formatted filename is ordinary for a developer benchmark tool and gated by a command-line flag, not a dropper.

  44. info warn → info by review dynamic-execution test/sql/test_lambdas.py:2220:9

    `exec` called on a non-literal expression (ast pass, confidence 0.70)

            d = {"A": A, "__name__": "lambda_fake"}
            exec(code, d)
            generate_lambda_stmt = d["generate_lambda_stmt"]
    likely benign LLM, confidence 0.90 exec of test-generated code to build a lambda statement generator.
    Reasoning

    The exec compiles a code string from the test into a dict namespace to produce a lambda statement generator. This is a typical way to test lambda SQL construction, and the source is test-controlled.

  45. info warn → info by review decoder-import-with-exec test/sql/test_metadata.py:7745:13

    file imports decoder module(s) pickle and calls `exec`/`eval`/`compile` — multi-stage payload shape (ast pass, confidence 0.80)

            # the repr round trips
            eq_(eval(repr(fk)).target_tokens, fk.target_tokens)
    
        def test_no_such_column_error_message(self):
    likely benign LLM, confidence 0.85 eval of a repr round trip in a metadata test, flagged by the decoder-plus-eval heuristic.
    Reasoning

    The pickle import sits in a file that also uses eval on repr(fk) to check a round trip for a ForeignKey object. The decoder-plus-eval heuristic fires on a repr round-trip test, which has no decoded or fetched payload.

  46. info warn → info by review dynamic-execution test/sql/test_metadata.py:7745:13

    `eval` called on a non-literal expression (ast pass, confidence 0.70)

            # the repr round trips
            eq_(eval(repr(fk)).target_tokens, fk.target_tokens)
    
        def test_no_such_column_error_message(self):
    likely benign LLM, confidence 0.90 eval of a ForeignKey repr in a metadata round-trip test.
    Reasoning

    eval(repr(fk)) is a deliberate round-trip assertion on a schema object within a unit test. The input is the object's own repr, not external data.

Reproduce This Scan

Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.1.0
git clone https://github.com/sqlalchemy/sqlalchemy sqlalchemy && cd sqlalchemy
git checkout rel_2_1_5
disclude scan --severity info --diff rel_2_1_4 .