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

Add Annotated support #257

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

mvanderlee
Copy link
Contributor

Fixes #256

Moving away from NewType and instead add Annotated support.

@mivade
Copy link

mivade commented Mar 9, 2024

I would recommend importing Annotated from typing_extensions for Python 3.8 support (at least for as long as that continues receiving security updates).

@mvanderlee mvanderlee changed the title Add Annotated support and therefore set minimum python version as 3.9 Add Annotated support Mar 10, 2024
@lovasoa lovasoa requested a review from dairiki March 11, 2024 07:01
@dairiki dairiki mentioned this pull request Mar 11, 2024
@mvanderlee
Copy link
Contributor Author

Rebased, and retested.

@mvanderlee
Copy link
Contributor Author

@lovasoa @dairiki Any idea when you'll have time to review this? I'd like to see this merged so I can rebase and finalize the generic dataclass PR #259

Copy link
Collaborator

@dairiki dairiki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize for the delay. (Life has been crazy.)

The feature addition is a good one, I think. (Thank you!) And other than some style nits, I think it looks fine.

I think the addition of tox test configuration is long overdue. Ideally, it would be a separate PR, but since it's in here, already, I'm fine leaving it here. I do have a few comments about that.

or isinstance(arg, marshmallow.fields.Field)
]
if marshmallow_annotations:
field = marshmallow_annotations[-1]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the (admittedly esoteric case that) the annotations contain more than one marshmallow Field, here we use the last one and silently ignore the rest.
Is that the best (e.g. safest or most expected) behavior? Would it be better to raise an exception (e.g. a custom subclass of ValueError) in this case?

commands = pytest
extras = dev
set_env =
VIRTUALENV_DISCOVERY = pyenv
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unfamilar with virtualenv-pyenv before this.

My initial reaction (I could maybe be convinced otherwise) is that I don't like it as a requirement for the tox test flow. A major advantage of using tox, in my view, is that one can use a globally-installed tox to run the tests, and let tox deal with all the details of setting up venvs. Adding virtualenv-pyenv as a requirement to run tox means that either virtualenv-pyenv must be globally installed, or we need to set up a venv just to bootstrap the tox process.

My normal workflow here is to use a globally installed tox and manually adjust the set of available python interpreters — either globally or locally — by running pyenv global [...] or pyenv local [...].

Does the use of virtualenv-pyenv buy one much compared to the manual use of pyenv global|local?

Does use of virtualenv-pyenv force the user to use pyenv? (I don't know.) If so, that's bad. (E.g. It would be nice to move to using tox to run the tests, e.g., in the CI testing.)

If we do want to keep using it, it should be added to [tox] requires (probably instead of including it in the tests extra dependencies in setup.py). (This causes tox to provision a bootstrap venv if necessary.)

"docs": ["sphinx"],
"tests": [
"pytest>=5.4",
# re: pypy: typed-ast (a dependency of mypy) fails to install on pypy
# https://github.com/python/typed_ast/issues/111
"pytest-mypy-plugins>=1.2.0; implementation_name != 'pypy'",
"tox>=4",
"virtualenv-pyenv",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think either of these requirements belong here.

(I view tox as being in the same class as pip or virtualenv — it is a prerequisite of the package installation process. So — in the general case — it is installed before one can even start to install the package.)

(See note below on tox.ini.)

if origin:
# Override base_schema.TYPE_MAPPING to change the class used for generic types below
type_mapping = base_schema.TYPE_MAPPING if base_schema else {}

if origin is Annotated:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annotated is not a generic type (it is a special form). Handling it in a function named _field_for_generic_type could be confusing.

Admittedly, unions, which are also special forms, are already being handled in this function.

I'm not sure ... perhaps it would be better to handle Annotated (and union types) alongside where (the now-deprecated) NewType is handled in _field_for_schema. (New private functions, e.g., _field_for_annotated_type, _field_for_union_type could be introduced, if needed, to limit the complexity of _field_for_schema.)

@@ -0,0 +1,11 @@
[tox]
requires =
tox>=4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either add virtualenv-pyenv to requires, or remove usage of it. (See below.)

@@ -247,28 +247,25 @@ class Sample:

See [marshmallow's documentation about extending `Schema`](https://marshmallow.readthedocs.io/en/stable/extending.html).

### Custom NewType declarations
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably leave at least some documentation for NewType — with a notice that it is deprecated — so that people can still grok older code that uses it.

The README section on the mypy plugin (marshmallow_dataclass.mypy) belongs in the section about marshmallow_dataclass.NewType. The mypy plugin's only purpose is to deal with the custom NewType.

(If we do add a DeprecationWarning to the NewType constructor, we should probably add a similar deprecation warning to uses of the mypy plugin.)

@@ -247,28 +247,25 @@ class Sample:

See [marshmallow's documentation about extending `Schema`](https://marshmallow.readthedocs.io/en/stable/extending.html).

### Custom NewType declarations
### Custom type declarations
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This heading seems vague. Maybe "Custom type aliases using Annotated" or just "Custom type aliases"?

@@ -8,8 +8,6 @@
"Operating System :: OS Independent",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add classifier for Python 3.12.

commands = pytest
extras = dev
set_env =
VIRTUALENV_DISCOVERY = pyenv
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably better left for another PR, but since we're adding a tox.ini...

It would be nice to add combined coverage reporting for the tox run. Both to check general test coverage and to ferret out those version_info ImportError conditionals that are no longer necessary.

E.g. this works:

[tox]
requires =
    tox>=4
    virtualenv-pyenv
env_list =
    py{38,39,310,311,312}
    cover-report

[testenv]
deps =
    coverage
    pytest
commands = coverage run -p -m pytest tests
extras = dev
set_env =
  VIRTUALENV_DISCOVERY = pyenv
depends =
  cover-report: py{38,39,310,311,312}

[testenv:cover-report]
skip_install = true
deps = coverage
commands =
    coverage combine
    coverage html
    coverage report

If coverage reporting is added to tox.ini, adding the following to pyproject.toml is also appropriate:

[tool.coverage.report]
exclude_also = [
    '^\s*\.\.\.\s*$',
    '^\s*pass\s*$',
]

@@ -18,24 +16,20 @@
]

EXTRAS_REQUIRE = {
"enum": [
"marshmallow-enum; python_version < '3.7'",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove marshmallow-enum from the requirements for the mypy pre-commit hook, too.

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

Successfully merging this pull request may close these issues.

Refactor 'NewType' as it no longer conforms to the typing spec
3 participants