Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Union[Literal["foo"], ...] evaluates foo in global context #372

Closed
2 tasks done
benclifford opened this issue Jul 28, 2023 · 1 comment
Closed
2 tasks done

Union[Literal["foo"], ...] evaluates foo in global context #372

benclifford opened this issue Jul 28, 2023 · 1 comment
Labels

Comments

@benclifford
Copy link

Things to check first

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

Typeguard version

4.0.1

Python version

3.11.2

What happened?

The behaviour of Literal inside a Union seems to have changed from typeguard 4.0.0 to 4.0.1

In typeguard 4.0.1, this code:

import typeguard

from typing import Union
from typing import Literal

class Config:
    @typeguard.typechecked
    def __init__(self,

                 p: Union[
                          Literal['foo'],
                         ]):
        pass

c = Config(p = "foo")

raises this error:

$ python x.py 
Traceback (most recent call last):
  File "/home/benc/parsl/src/parsl/x.py", line 15, in <module>
    c = Config(p = "foo")
        ^^^^^^^^^^^^^^^^^
  File "/home/benc/parsl/src/parsl/x.py", line 11, in __init__
    Literal['foo'],
            ^^^^^
NameError: name 'foo' is not defined

With typeguard 4.0.0, this code successfully runs.

If I assign a literal to global variable foo, then it looks as if the global variable is dereferenced to provide the literal value here:

$ cat x.py 
import typeguard

from typing import Union
from typing import Literal

foo = "HELLO"

class Config:
    @typeguard.typechecked
    def __init__(self,

                 p: Union[
                          Literal['foo'],
                         ]):
        pass

c = Config(p = "foo")

gives

Traceback (most recent call last):
  File "/home/benc/parsl/src/parsl/x.py", line 17, in <module>
    c = Config(p = "foo")
        ^^^^^^^^^^^^^^^^^
  File "/home/benc/parsl/src/parsl/x.py", line 10, in __init__
    def __init__(self,
  File "/home/benc/parsl/virtualenv-3.11/lib/python3.11/site-packages/typeguard/_functions.py", line 135, in check_argument_types
    check_type_internal(value, annotation, memo)
  File "/home/benc/parsl/virtualenv-3.11/lib/python3.11/site-packages/typeguard/_checkers.py", line 774, in check_type_internal
    checker(value, origin_type, args, memo)
  File "/home/benc/parsl/virtualenv-3.11/lib/python3.11/site-packages/typeguard/_checkers.py", line 582, in check_literal
    raise TypeCheckError(f"is not any of ({formatted_args})") from None
typeguard.TypeCheckError: argument "p" (str) is not any of ('HELLO')

I think this is incorrect behaviour.

If I remove the Union wrapping, then the code behaves as I would expect, executing without error.

$ cat x.py 
import typeguard

from typing import Union
from typing import Literal

class Config:
    @typeguard.typechecked
    def __init__(self,
                 p: Literal['foo'],
                         ):
        pass

c = Config(p = "foo")

(the broader context is this checkpoint_mode parameter: https://github.com/Parsl/parsl/blob/70b9a2cd663087bc2197f633681a0e5f23ad68e1/parsl/config.py#L79)

How can we reproduce the bug?

The above examples should be pretty minimal. Here's my installed package list:

$ pip list
Package                       Version                        Editable project location
----------------------------- ------------------------------ --------------------------
aiohttp                       3.8.2
aiosignal                     1.3.1
alabaster                     0.7.13
asttokens                     2.2.1
async-timeout                 4.0.2
atomicwrites                  1.4.1
attrs                         22.2.0
autopep8                      2.0.2
Babel                         2.12.1
backcall                      0.2.0
bcrypt                        4.0.1
beautifulsoup4                4.11.2
bleach                        6.0.0
boto3                         1.26.158
botocore                      1.29.158
certifi                       2023.5.7
cffi                          1.15.1
charset-normalizer            2.1.1
click                         8.1.3
cloudpickle                   2.2.1
comm                          0.1.2
conda-pack                    0.6.0
contourpy                     1.0.7
coverage                      7.2.1
cryptography                  41.0.1
cycler                        0.11.0
debugpy                       1.6.6
decorator                     4.4.2
defusedxml                    0.7.1
dill                          0.3.6
dnpcsql                       0                              /home/benc/parsl/src/dnpc
docutils                      0.17.1
entrypoints                   0.4
execnet                       1.9.0
executing                     1.2.0
fastjsonschema                2.16.3
flake8                        6.0.0
Flask                         2.2.3
Flask-SQLAlchemy              2.5.1
fonttools                     4.39.0
frozenlist                    1.3.3
globus-compute-common         0.2.0
globus-compute-sdk            2.2.1
globus-sdk                    3.22.0
greenlet                      2.0.3.dev0
idna                          3.4
imagesize                     1.4.1
importlib-metadata            4.13.0
iniconfig                     2.0.0
ipykernel                     6.21.3
ipyparallel                   8.4.1
ipython                       8.6.0
itsdangerous                  2.1.2
jaraco.classes                3.2.3
jedi                          0.18.2
jeepney                       0.8.0
Jinja2                        3.1.2
jmespath                      1.0.1
jsonschema                    4.17.3
jupyter_client                8.0.3
jupyter_core                  5.2.0
jupyterlab-pygments           0.2.2
keyring                       23.13.1
kiwisolver                    1.4.4
lazy-object-proxy             1.9.0
lockfile                      0.12.2
markdown-it-py                2.2.0
MarkupSafe                    2.1.2
matplotlib                    3.7.1
matplotlib-inline             0.1.6
mccabe                        0.7.0
mdurl                         0.1.2
mistune                       2.0.5
mock                          5.0.1
more-itertools                9.1.0
multidict                     5.2.0
mypy                          1.1.1
mypy-extensions               1.0.0
nbclient                      0.7.2
nbconvert                     7.2.9
nbformat                      5.7.3
nbsphinx                      0.8.12
nest-asyncio                  1.5.6
networkx                      2.5.1
numpy                         1.24.2
packaging                     23.0
pandas                        1.3.5
pandas-stubs                  1.5.3.230304
pandocfilters                 1.5.0
paramiko                      3.2.0
parsl                         2023.7.24.dev0+desc.2023.7.26a /home/benc/parsl/src/parsl
parso                         0.8.3
pexpect                       4.8.0
pickleshare                   0.7.5
pika                          1.3.1
Pillow                        9.4.0
pip                           23.0.1
pkginfo                       1.9.6
platformdirs                  3.1.0
plotly                        5.13.1
pluggy                        0.13.1
prompt-toolkit                3.0.38
psutil                        5.9.5
psycopg2                      2.9.6
ptyprocess                    0.7.0
pure-eval                     0.2.2
py                            1.11.0
pycodestyle                   2.10.0
pycparser                     2.21
pydantic                      1.10.7
pydot                         1.4.2
pyflakes                      3.0.1
Pygments                      2.14.0
PyJWT                         2.7.0
PyNaCl                        1.5.0
pyparsing                     3.0.9
pyrsistent                    0.19.3
pytest                        7.4.0
pytest-cov                    4.0.0
pytest-forked                 1.6.0
pytest-random-order           1.1.0
pytest-xdist                  1.26.1
python-daemon                 2.3.2
python-dateutil               2.8.2
pytz                          2022.7.1
pyzmq                         25.1.0
readme-renderer               37.3
requests                      2.31.0
requests-toolbelt             0.10.1
rfc3986                       2.0.0
rich                          13.3.2
s3transfer                    0.6.1
scipy                         1.10.1
SecretStorage                 3.3.3
serpent                       1.41
setproctitle                  1.3.2
setuptools                    67.4.0
six                           1.16.0
snowballstemmer               2.2.0
soupsieve                     2.4
Sphinx                        4.5.0
sphinx-rtd-theme              1.2.0
sphinxcontrib-applehelp       1.0.4
sphinxcontrib-devhelp         1.0.2
sphinxcontrib-htmlhelp        2.0.1
sphinxcontrib-jquery          2.0.0
sphinxcontrib-jsmath          1.0.1
sphinxcontrib-qthelp          1.0.3
sphinxcontrib-serializinghtml 1.1.5
SQLAlchemy                    1.4.48
sqlalchemy2-stubs             0.0.2a34
stack-data                    0.6.2
tblib                         1.7.0
tenacity                      8.2.2
texttable                     1.6.7
tinycss2                      1.2.1
toml                          0.10.2
tornado                       6.2
tqdm                          4.65.0
traitlets                     5.9.0
twine                         4.0.2
typeguard                     4.0.1
types-paramiko                3.2.0.0
types-python-dateutil         2.8.19.10
types-pytz                    2022.7.1.2
types-requests                2.31.0.1
types-six                     1.16.21.8
types-urllib3                 1.26.25.13
typing_extensions             4.7.1
urllib3                       1.26.16
wcwidth                       0.2.6
webencodings                  0.5.1
websockets                    10.3
Werkzeug                      2.2.3
wheel                         0.38.4
yarl                          1.9.2
zipp                          3.15.0

[notice] A new release of pip is available: 23.0.1 -> 23.2.1
[notice] To update, run: pip install --upgrade pip
@benclifford
Copy link
Author

more info:

Union[Literal['foo']] successfully accepts the literal string foo

adding a comma  `,`    @typeguard.typechecked
    def __init__(self,
                 p: Union[
                          Literal['foo']
                          ],
                         ):
        pass

but adding more to the union, even a , seems to break it: I've tried with a , on its own, , None and , Literal["another"]:

$ cat x.py 
import typeguard

from typing import Union
from typing import Literal

class Config:
    @typeguard.typechecked
    def __init__(self,
                 p: Union[
                          Literal['foo'], Literal['another']
                          ],
                         ):
        pass

c = Config(p = "foo")
python x.py 
Traceback (most recent call last):
  File "/home/benc/parsl/src/parsl/x.py", line 15, in <module>
    c = Config(p = "foo")
        ^^^^^^^^^^^^^^^^^
  File "/home/benc/parsl/src/parsl/x.py", line 10, in __init__
    Literal['foo'], Literal['another']
            ^^^^^
NameError: name 'foo' is not defined

@benclifford benclifford changed the title Union[Literal["foo"]] evaluates foo in global context Union[Literal["foo"], ...] evaluates foo in global context Jul 28, 2023
zanieb pushed a commit to astral-sh/ruff-lsp that referenced this issue Aug 18, 2023
Bumps [typeguard](https://github.com/agronholm/typeguard) from 4.1.1 to
4.1.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/agronholm/typeguard/blob/master/docs/versionhistory.rst">typeguard's
changelog</a>.</em></p>
<blockquote>
<h1>Version history</h1>
<p>This library adheres to <code>Semantic Versioning 2.0
&lt;https://semver.org/#semantic-versioning-200&gt;</code>_.</p>
<p><strong>UNRELEASED</strong></p>
<ul>
<li>Dropped Python 3.7 support</li>
</ul>
<p><strong>4.1.2</strong> (2023-08-18)</p>
<ul>
<li>Fixed <code>Any</code> being removed from a subscript that still
contains other elements
(<code>[#373](agronholm/typeguard#373)
&lt;https://github.com/agronholm/typeguard/issues/373&gt;</code>_</li>
</ul>
<p><strong>4.1.1</strong> (2023-08-16)</p>
<ul>
<li>Fixed <code>suppress_type_checks()</code> causing annotated variable
assignments to always
assign <code>None</code>
(<code>[#380](agronholm/typeguard#380)
&lt;https://github.com/agronholm/typeguard/issues/380&gt;</code>_)</li>
</ul>
<p><strong>4.1.0</strong> (2023-07-30)</p>
<ul>
<li>Added support for passing a tuple as <code>expected_type</code> to
<code>check_type()</code>, making it
more of a drop-in replacement for <code>isinstance()</code>
(<code>[#371](agronholm/typeguard#371)
&lt;https://github.com/agronholm/typeguard/issues/371&gt;</code>_</li>
<li>Fixed regression where <code>Literal</code> inside a
<code>Union</code> had quotes stripped from its
contents, thus typically causing <code>NameError</code> to be raised
when run
(<code>[#372](agronholm/typeguard#372)
&lt;https://github.com/agronholm/typeguard/issues/372&gt;</code>_)</li>
</ul>
<p><strong>4.0.1</strong> (2023-07-27)</p>
<ul>
<li>Fixed handling of <code>typing_extensions.Literal</code> on Python
3.8 and 3.9 when
<code>typing_extensions&gt;=4.6.0</code> is installed
(<code>[#363](agronholm/typeguard#363)
&lt;https://github.com/agronholm/typeguard/issues/363&gt;</code>_; PR by
Alex Waygood)</li>
<li>Fixed <code>NameError</code> when generated type checking code
references an imported name from
a method
(<code>[#362](agronholm/typeguard#362)
&lt;https://github.com/agronholm/typeguard/issues/362&gt;</code>_)</li>
<li>Fixed docstrings disappearing from instrumented functions
(<code>[#359](agronholm/typeguard#359)
&lt;https://github.com/agronholm/typeguard/issues/359&gt;</code>_)</li>
<li>Fixed <code>@TypeChecked</code> failing to instrument functions when
there are more than one
function within the same scope
(<code>[#355](agronholm/typeguard#355)
&lt;https://github.com/agronholm/typeguard/issues/355&gt;</code>_)</li>
<li>Fixed <code>frozenset</code> not being checked
(<code>[#367](agronholm/typeguard#367)
&lt;https://github.com/agronholm/typeguard/issues/367&gt;</code>_)</li>
</ul>
<p><strong>4.0.0</strong> (2023-05-12)</p>
<ul>
<li>No changes</li>
</ul>
<p><strong>4.0.0rc6</strong> (2023-05-07)</p>
<ul>
<li>Fixed <code>@TypeChecked</code> optimization causing compilation of
instrumented code to fail</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/agronholm/typeguard/commit/d7a705e329529456898265d94adbdafed0c4c22c"><code>d7a705e</code></a>
Added release date</li>
<li><a
href="https://github.com/agronholm/typeguard/commit/d07fbb4fd49e716c4db12a6fca3dcfa8a58fd6d2"><code>d07fbb4</code></a>
Fixed Any being removed from a subscript that still contains other
elements</li>
<li>See full diff in <a
href="https://github.com/agronholm/typeguard/compare/4.1.1...4.1.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typeguard&package-manager=pip&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
azurelotus0926 added a commit to azurelotus0926/ruff-lsp that referenced this issue Jun 27, 2024
Bumps [typeguard](https://github.com/agronholm/typeguard) from 4.1.1 to
4.1.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/agronholm/typeguard/blob/master/docs/versionhistory.rst">typeguard's
changelog</a>.</em></p>
<blockquote>
<h1>Version history</h1>
<p>This library adheres to <code>Semantic Versioning 2.0
&lt;https://semver.org/#semantic-versioning-200&gt;</code>_.</p>
<p><strong>UNRELEASED</strong></p>
<ul>
<li>Dropped Python 3.7 support</li>
</ul>
<p><strong>4.1.2</strong> (2023-08-18)</p>
<ul>
<li>Fixed <code>Any</code> being removed from a subscript that still
contains other elements
(<code>[#373](agronholm/typeguard#373)
&lt;https://github.com/agronholm/typeguard/issues/373&gt;</code>_</li>
</ul>
<p><strong>4.1.1</strong> (2023-08-16)</p>
<ul>
<li>Fixed <code>suppress_type_checks()</code> causing annotated variable
assignments to always
assign <code>None</code>
(<code>[#380](agronholm/typeguard#380)
&lt;https://github.com/agronholm/typeguard/issues/380&gt;</code>_)</li>
</ul>
<p><strong>4.1.0</strong> (2023-07-30)</p>
<ul>
<li>Added support for passing a tuple as <code>expected_type</code> to
<code>check_type()</code>, making it
more of a drop-in replacement for <code>isinstance()</code>
(<code>[#371](agronholm/typeguard#371)
&lt;https://github.com/agronholm/typeguard/issues/371&gt;</code>_</li>
<li>Fixed regression where <code>Literal</code> inside a
<code>Union</code> had quotes stripped from its
contents, thus typically causing <code>NameError</code> to be raised
when run
(<code>[#372](agronholm/typeguard#372)
&lt;https://github.com/agronholm/typeguard/issues/372&gt;</code>_)</li>
</ul>
<p><strong>4.0.1</strong> (2023-07-27)</p>
<ul>
<li>Fixed handling of <code>typing_extensions.Literal</code> on Python
3.8 and 3.9 when
<code>typing_extensions&gt;=4.6.0</code> is installed
(<code>[#363](agronholm/typeguard#363)
&lt;https://github.com/agronholm/typeguard/issues/363&gt;</code>_; PR by
Alex Waygood)</li>
<li>Fixed <code>NameError</code> when generated type checking code
references an imported name from
a method
(<code>[#362](agronholm/typeguard#362)
&lt;https://github.com/agronholm/typeguard/issues/362&gt;</code>_)</li>
<li>Fixed docstrings disappearing from instrumented functions
(<code>[#359](agronholm/typeguard#359)
&lt;https://github.com/agronholm/typeguard/issues/359&gt;</code>_)</li>
<li>Fixed <code>@TypeChecked</code> failing to instrument functions when
there are more than one
function within the same scope
(<code>[#355](agronholm/typeguard#355)
&lt;https://github.com/agronholm/typeguard/issues/355&gt;</code>_)</li>
<li>Fixed <code>frozenset</code> not being checked
(<code>[#367](agronholm/typeguard#367)
&lt;https://github.com/agronholm/typeguard/issues/367&gt;</code>_)</li>
</ul>
<p><strong>4.0.0</strong> (2023-05-12)</p>
<ul>
<li>No changes</li>
</ul>
<p><strong>4.0.0rc6</strong> (2023-05-07)</p>
<ul>
<li>Fixed <code>@TypeChecked</code> optimization causing compilation of
instrumented code to fail</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/agronholm/typeguard/commit/d7a705e329529456898265d94adbdafed0c4c22c"><code>d7a705e</code></a>
Added release date</li>
<li><a
href="https://github.com/agronholm/typeguard/commit/d07fbb4fd49e716c4db12a6fca3dcfa8a58fd6d2"><code>d07fbb4</code></a>
Fixed Any being removed from a subscript that still contains other
elements</li>
<li>See full diff in <a
href="https://github.com/agronholm/typeguard/compare/4.1.1...4.1.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=typeguard&package-manager=pip&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant