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

Error when running on python 3.10.2 & 3.9.10 - TypeError: ForwardRef('...') is not a class #501

Closed
cheginit opened this issue Jan 15, 2022 · 9 comments · Fixed by #503
Closed
Labels
Milestone

Comments

@cheginit
Copy link

The problem

It seems that requests-cache is not compatible with Python 3.10.2 (it works with 3.10.1).

$ python -c "from requests_cache import CachedSession"             
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/requests_cache/__init__.py", line 11, in <module>
    from .backends import *
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/requests_cache/backends/__init__.py", line 7, in <module>
    from .base import BaseCache, BaseStorage, DictStorage
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/requests_cache/backends/base.py", line 18, in <module>
    from ..serializers import init_serializer
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/requests_cache/serializers/__init__.py", line 6, in <module>
    from .preconf import (
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/requests_cache/serializers/preconf.py", line 27, in <module>
    CattrStage()
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/requests_cache/serializers/cattrs.py", line 32, in __init__
    self.converter = init_converter(factory)
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/requests_cache/serializers/cattrs.py", line 69, in init_converter
    converter.register_structure_hook(
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/cattr/converters.py", line 269, in register_structure_hook
    self._structure_func.register_cls_list([(cl, func)])
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/site-packages/cattr/dispatch.py", line 57, in register_cls_list
    self._single_dispatch.register(cls, handler)
  File "/Users/tchegini/.local/apps/mambaforge/envs/ts/lib/python3.10/functools.py", line 856, in register
    raise TypeError(
TypeError: Invalid first argument to `register()`. ForwardRef('CachedResponse') is not a class.

Expected behavior

Since Python 3.10.2 is a patch release requests-cache should work.

Steps to reproduce the behavior

Create an environment with python 3.10.2 and then just try importing CachedResponse:

python -c "from requests_cache import CachedSession"

Workarounds

Not that I know of.

Environment

  • requests-cache version: Tried with both the stable release, 0.9.0 and master from Github
  • Python version: 3.10.2
  • Platform: MacOSX 12.1
@cheginit cheginit added the bug label Jan 15, 2022
@JWCook
Copy link
Member

JWCook commented Jan 15, 2022

Thanks for reporting this. This might be a difficult one to figure out.

I don't see anything in the python 3.10.2 changelog that indicates different behavior with ForwardRef. This may be something that would require changes in the cattrs library, but I'm not 100% sure yet.

I should have some time to look into this next week. If I can't figure out the root cause, I can at least make an ugly temporary workaround.

@cheginit
Copy link
Author

I don't see anything in the python 3.10.2 changelog that indicates different behavior with ForwardRef.

Right, I was kinda surprised too.

I should have some time to look into this next week. If I can't figure out the root cause, I can at least make an ugly temporary workaround.

Thanks, that would be great.

@JWCook
Copy link
Member

JWCook commented Jan 15, 2022

While writing up python-attrs/cattrs#206, I found a fix for this in python-attrs/cattrs#201 (comment).

Brief explanation for anyone else who encounters a similar problem: In python 3.10.2, some behavior unexpectedly changed regarding ForwardRef and register() with functools single-dispatch generic functions.

This caused the following method of structuring ForwardRef (using cattrs) to fail:

from attr import define, field
from cattr import GenConverter
from typing import ForwardRef, List

@define()
class MyClass:
    history: List['MyClass'] = field(factory=list)

converter = GenConverter()

# Resolve MyClass forward reference during deserialization
converter.register_structure_hook(
    ForwardRef('MyClass'),
    lambda obj, _: converter.structure(obj, MyClass)
)

A solution for this is to register a function that tests whether a type is a ForwardRef, rather than registering a ForwardRef instance:

# Resolve any forward references during deserialization
converter.register_structure_hook_func(
    lambda cls: cls.__class__ is typing.ForwardRef,
    lambda obj, cls: converter .structure(obj, cls.__forward_value__),
)

This is also an all-around better solution since it generically resolves any forward references instead of a specific one, and avoids potential naming conflicts in forward references across different modules.

@JWCook JWCook changed the title Issue with Python 3.10.2 Error when running on python 3.10.2 - TypeError: ForwardRef('...') is not a class Jan 15, 2022
@dargor
Copy link

dargor commented Jan 15, 2022

I encountered the same problem with python 3.9.10, too. I patched with #503, now it works fine. Thanks !

@JWCook
Copy link
Member

JWCook commented Jan 15, 2022

This fix is now in the latest stable version (requests-cache 0.9.1).

@cheginit
Copy link
Author

@JWCook Will you be releasing 0.9.1 in conda-forge as well? The conda-forge build of my package (conda-forge/pygeoogc-feedstock#25) is failing due to requests-cache.

@JWCook
Copy link
Member

JWCook commented Jan 15, 2022

That is automated, it just takes some time to pick up a new release from PyPI sometimes. Looks like it just finished a few minutes ago:
conda-forge/requests-cache-feedstock#31
https://anaconda.org/conda-forge/requests-cache

@cheginit
Copy link
Author

Great! Thanks.

@JWCook JWCook changed the title Error when running on python 3.10.2 - TypeError: ForwardRef('...') is not a class Error when running on python 3.10.2 & 3.9.10 - TypeError: ForwardRef('...') is not a class Jan 19, 2022
probberechts pushed a commit to ML-KULeuven/socceraction that referenced this issue Jan 20, 2022
@Tinche
Copy link

Tinche commented Jan 26, 2022

FWIW I think they broke it with changes to singledispatch. (https://bugs.python.org/issue46032)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants