lovasoa / marshmallow_dataclass

Automatic generation of marshmallow schemas from dataclasses.
https://lovasoa.github.io/marshmallow_dataclass/html/marshmallow_dataclass.html
MIT License
456 stars 78 forks source link

Latest version of typing inspect breaks (related to issue #51?) #206

Closed winddon closed 1 year ago

winddon commented 2 years ago

Dependency of typing-inspect>=0.7.1 is breaking this package. the latest release typing-inspect==0.8.0 gives the issue,

class_or_instance = <function NewType.<locals>.new_type at 0x0000027F368C62F0>
      def fields(class_or_instance):
          """Return a tuple describing the fields of this dataclass.

          Accepts a dataclass or an instance of one. Tuple elements are of
          type Field.
          """

          # Might it be worth caching this, per class?
          try:
              fields = getattr(class_or_instance, _FIELDS)
          except AttributeError:
  >           raise TypeError('must be called with a dataclass type or instance')
  E           TypeError: must be called with a dataclass type or instance

  .tox\py36-win\lib\site-packages\dataclasses.py:972: TypeError

  During handling of the above exception, another exception occurred:

  clazz = <function NewType.<locals>.new_type at 0x0000027F368C62F0>
  base_schema = <class 'blue_steel_splice_tables.utils.marshmallow.BaseSchema'>
  clazz_frame = <frame object at 0x0000027F3521DC28>

      @lru_cache(maxsize=MAX_CLASS_SCHEMA_CACHE_SIZE)
      def _internal_class_schema(
          clazz: type,
          base_schema: Optional[Type[marshmallow.Schema]] = None,
          clazz_frame: types.FrameType = None,
      ) -> Type[marshmallow.Schema]:
          _RECURSION_GUARD.seen_classes[clazz] = clazz.__name__
          try:
              # noinspection PyDataclass
              fields: Tuple[dataclasses.Field, ...] = dataclasses.fields(clazz)
          except TypeError:  # Not a dataclass
              try:
                  warnings.warn(
                      "****** WARNING ****** "
                      f"marshmallow_dataclass was called on the class {clazz}, which is not a dataclass. "
                      "It is going to try and convert the class into a dataclass, which may have "
                      "undesirable side effects. To avoid this message, make sure all your classes and "
                      "all the classes of their fields are either explicitly supported by "
                      "marshmallow_dataclass, or define the schema explicitly using "
                      "field(metadata=dict(marshmallow_field=...)). For more information, see "
                      "https://github.com/lovasoa/marshmallow_dataclass/issues/51 "
                      "****** WARNING ******"
                  )
  >               created_dataclass: type = dataclasses.dataclass(clazz)

  .tox\py36-win\lib\site-packages\marshmallow_dataclass\__init__.py:384: 
elzzz commented 2 years ago

Encountered with the same issue and may confirm that the latest release of typing-inspect (0.8.0) is breaking it because with 0.7.1 it worked like a charm.

vit-zikmund commented 2 years ago

The problem is with custom types created with NewType. For those field_for_schema calls typing_inspect.is_new_type(typ), but this function has been "made more robust" for v0.8.0. Since then the function returns False while previously it returned True.

All the new checks there work, except the one for module, that requires it to be in ('typing', 'typing_extensions'), while ours is from marshmallow_dataclass.

I successfully worked this around by adding

    # hack alert :P
    new_type.__module__ = 'typing'

into local NewType, but that's hardly a nice solution :frowning_face:

Maybe this might be a better fix (that also works for me, btw): https://github.com/lovasoa/marshmallow_dataclass/pull/207

dairiki commented 1 year ago

Fixed in marshmallow-dataclass==8.5.9 via #207, #211.