diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.expected b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.ql b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.ql new file mode 100644 index 000000000000..5bdb99415b2a --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModuleWithRef.ql @@ -0,0 +1,13 @@ +import python + +from ModuleValue mv, ControlFlowNode ref, string local_external +where + ref = mv.getAReference() and + exists(mv.getScope().getFile().getRelativePath()) and + ( + if exists(ref.getLocation().getFile().getRelativePath()) + then local_external = "local" + else local_external = "external" + ) +select "Local module", mv, "referenced in " + local_external + " file called", + ref.getLocation().getFile().getShortName() diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModules.expected b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModules.expected new file mode 100644 index 000000000000..7d18240655fa --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModules.expected @@ -0,0 +1,5 @@ +| code-invalid-package-name/cmd.py:0:0:0:0 | Script cmd.py | +| code-invalid-package-name/test_fail.py:0:0:0:0 | Script test_fail.py | +| code-invalid-package-name/test_ok.py:0:0:0:0 | Script test_ok.py | +| code-invalid-package-name/unique_name.py:0:0:0:0 | Script unique_name.py | +| code-invalid-package-name/unique_name_use.py:0:0:0:0 | Script unique_name_use.py | diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModules.ql b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModules.ql new file mode 100644 index 000000000000..faacf90522d8 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/LocalModules.ql @@ -0,0 +1,5 @@ +import python + +from Module m +where exists(m.getFile().getRelativePath()) +select m diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.expected b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.expected new file mode 100644 index 000000000000..2c66cfdbc993 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.expected @@ -0,0 +1,3 @@ +| Module 'cmd' (external, in stdlib, not missing) referenced in local file | code-invalid-package-name/test_ok.py:1 | +| Module 'pdb' (external, in stdlib, not missing) referenced in local file | code-invalid-package-name/test_fail.py:3 | +| Module 'unique_name' (external, not in stdlib, missing) referenced in local file | code-invalid-package-name/unique_name_use.py:1 | diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.ql b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.ql new file mode 100644 index 000000000000..030211ba0bf7 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/ModuleWithLocalRef.ql @@ -0,0 +1,19 @@ +import python + +from ModuleValue mv, ControlFlowNode ref, string in_stdlib, string local_external, string is_missing +where + ref = mv.getAReference() and + exists(ref.getLocation().getFile().getRelativePath()) and + ( + if mv.getScope().getFile().inStdlib() + then in_stdlib = "in stdlib" + else in_stdlib = "not in stdlib" + ) and + ( + if exists(mv.getScope().getFile().getRelativePath()) + then local_external = "local" + else local_external = "external" + ) and + (if mv.isAbsent() then is_missing = "missing" else is_missing = "not missing") +select "Module '" + mv.getName() + "' (" + local_external + ", " + in_stdlib + ", " + is_missing + + ") referenced in local file", ref.getLocation().toString() diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/README.md b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/README.md new file mode 100644 index 000000000000..666e3c4bd2a2 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/README.md @@ -0,0 +1,10 @@ +This test shows how we handle modules that shadow a module in the standard library. + +We manually replicate the behavior of `codeql database create --source-root `, which will use `-R `. By default, the way qltest invokes the extractor will cause different behavior. Therefore, we also need to move our code outside of the top-level folder, and it lives in `code-invalid-package-name/` -- notice that if we use `code` as the folder name, the extractor will treat it as if there is a package called `code` (note, `codeql database create` would not treat the folder `code` as a package when `code` is used as the `--source-root`). + +The results from `LocalModules.ql`, where everything is a script, matches with the extractor :+1: + +Because we have a `cmd.py` file, whenever the python interpreter sees `import cmd`, that is the file that will be used! + +* `python test_ok.py` works as intended, and prints `Foo` +* `python test_fail.py` raises an exception, since it imports `pdb.py` from the standard library, which (at least in Python 3.8) tries to import `cmd.py` from the standard library, but instead is served our `cmd.py` module. Therefore it fails with `AttributeError: module 'cmd' has no attribute 'Cmd'` diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/cmd.py b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/cmd.py new file mode 100644 index 000000000000..58bbb12f69c1 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/cmd.py @@ -0,0 +1,2 @@ +foo = "Foo" +print("my own cmd imported") diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/test_fail.py b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/test_fail.py new file mode 100644 index 000000000000..f9621b260937 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/test_fail.py @@ -0,0 +1,3 @@ +# we import `pdb` which import the `cmd` module from the standard library +# and allows us to set --max-import-depth=2, to make the test run fast +import pdb diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/test_ok.py b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/test_ok.py new file mode 100644 index 000000000000..6dcf8eb614eb --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/test_ok.py @@ -0,0 +1,2 @@ +from cmd import foo +print(foo) diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/unique_name.py b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/unique_name.py new file mode 100644 index 000000000000..191d0d6e4191 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/unique_name.py @@ -0,0 +1 @@ +foo = "Foo" diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/unique_name_use.py b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/unique_name_use.py new file mode 100644 index 000000000000..79d2ca3c3501 --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/code-invalid-package-name/unique_name_use.py @@ -0,0 +1,2 @@ +from unique_name import foo +print(foo) diff --git a/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/options b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/options new file mode 100644 index 000000000000..ee0f5414146c --- /dev/null +++ b/python/ql/test/library-tests/PointsTo/regressions/wrong/module-imports/conflict-stdlib/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=2 -R code-invalid-package-name/