Repository: marshmallow-code/marshmallow-oneofschema (language: python)

Issue:
Enable typing so that mypy with "disallow subclassing any" option passes
Consider the following code:

`example.py`:

```python
from typing import Dict
from marshmallow_oneofschema import OneOfSchema


class ExampleSchema(OneOfSchema):
    type_schemas: Dict = {}
```

I would like to type check my code as strictly as possible.
A minimal version of this is:

```
$ mypy example.py --disallow-subclassing-any
```

This generates the error:

```
example.py:5: error: Class cannot subclass 'OneOfSchema' (has type 'Any')
```


Discussion / hints:
I think this issue is related to the #157 .

Fix patch:
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..96d1cfd
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+open_collective: "marshmallow"
+tidelift: "pypi/marshmallow"
diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
new file mode 100644
index 0000000..f5cf612
--- /dev/null
+++ b/.github/workflows/build-release.yml
@@ -0,0 +1,56 @@
+name: build
+on:
+  push:
+    branches: ["main", "*.x-line"]
+    tags: ["*"]
+  pull_request:
+
+jobs:
+  tests:
+    name: ${{ matrix.name }}
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - { name: "3.8", python: "3.8", tox: py38 }
+          - { name: "3.12", python: "3.12", tox: py312 }
+    steps:
+      - uses: actions/checkout@v4.0.0
+      - uses: actions/setup-python@v4.7.0
+        with:
+          python-version: ${{ matrix.python }}
+          allow-prereleases: true
+      - run: python -m pip install --upgrade pip
+      - run: python -m pip install tox
+      - run: python -m tox -e ${{ matrix.tox }}
+  # this duplicates pre-commit.ci, so only run it on tags
+  # it guarantees that linting is passing prior to a release
+  lint-pre-release:
+    name: lint
+    if: startsWith(github.ref, 'refs/tags')
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4.0.0
+      - uses: actions/setup-python@v4.7.0
+        with:
+          python-version: "3.11"
+      - run: python -m pip install --upgrade pip
+      - run: python -m pip install tox
+      - run: python -m tox -e lint
+  release:
+    needs: [tests, lint-pre-release]
+    name: PyPI release
+    if: startsWith(github.ref, 'refs/tags')
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4.0.0
+      - uses: actions/setup-python@v4.7.0
+      - name: install requirements
+        run: python -m pip install build twine
+      - name: build dists
+        run: python -m build
+      - name: check package metadata
+        run: twine check dist/*
+      - name: publish
+        run: twine upload -u __token__ -p ${{ secrets.PYPI_API_TOKEN }} dist/*
diff --git a/.gitignore b/.gitignore
index 1f930e1..1395446 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,5 @@ nosetests.xml
 coverage.xml
 *,cover
 .pytest_cache/
+.mypy_cache
+.ruff_cache
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 2adc914..cc4687b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,21 +1,20 @@
 repos:
-- repo: https://github.com/asottile/pyupgrade
-  rev: v2.11.0
+- repo: https://github.com/astral-sh/ruff-pre-commit
+  rev: v0.1.13
   hooks:
-  - id: pyupgrade
-    args: [--py36-plus]
-- repo: https://github.com/python/black
-  rev: 20.8b1
+    - id: ruff
+    - id: ruff-format
+- repo: https://github.com/python-jsonschema/check-jsonschema
+  rev: 0.27.3
   hooks:
-  - id: black
-    language_version: python3
-- repo: https://gitlab.com/pycqa/flake8
-  rev: 3.9.0
-  hooks:
-  - id: flake8
-    additional_dependencies: [flake8-bugbear==21.4.3]
+    - id: check-github-workflows
 - repo: https://github.com/asottile/blacken-docs
-  rev: v1.10.0
+  rev: 1.16.0
   hooks:
   - id: blacken-docs
-    additional_dependencies: [black==20.8b1]
+    additional_dependencies: [black==23.12.1]
+- repo: https://github.com/pre-commit/mirrors-mypy
+  rev: v1.8.0
+  hooks:
+  - id: mypy
+    additional_dependencies: ["marshmallow>=3,<4"]
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index fa23096..49bcdd9 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,17 @@
 Changelog
 ---------
 
+3.1.0 (unreleased)
+++++++++++++++++++
+
+Features:
+
+- Publish type information.
+
+Support:
+
+- Support Python 3.8-3.12. Older versions are no longer supported.
+
 3.0.2 (2021-11-14)
 ++++++++++++++++++
 
diff --git a/LICENSE b/LICENSE
index 1c736ab..d0c0544 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,6 @@
 Copyright 2016-2017 Maxim Kulkin
 Copyright 2018 Alex Rothberg and contributors
+Copyright 2024 Steven Loria and contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index c74cefe..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,1 +0,0 @@
-include *.rst LICENSE
diff --git a/README.rst b/README.rst
index 8989368..6f4a46c 100644
--- a/README.rst
+++ b/README.rst
@@ -2,8 +2,8 @@
 marshmallow-oneofschema
 =======================
 
-.. image:: https://dev.azure.com/sloria/sloria/_apis/build/status/marshmallow-code.marshmallow-oneofschema?branchName=master
-    :target: https://dev.azure.com/sloria/sloria/_build/latest?definitionId=13&branchName=master
+.. image:: https://github.com/marshmallow-code/marshmallow-oneofschema/actions/workflows/build-release.yml/badge.svg
+    :target: https://github.com/marshmallow-code/flask-marshmallow/actions/workflows/build-release.yml
     :alt: Build Status
 
 .. image:: https://badgen.net/badge/marshmallow/3
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index 6f9a543..0000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-trigger:
-  branches:
-    include: [master, 1.x-line, test-me-*]
-  tags:
-    include: ['*']
-
-resources:
-  repositories:
-    - repository: sloria
-      type: github
-      endpoint: github
-      name: sloria/azure-pipeline-templates
-      ref: refs/heads/sloria
-
-jobs:
-- template: job--python-tox.yml@sloria
-  parameters:
-    toxenvs: [lint, py36, py37, py38, py39, check-build]
-    os: linux
-- template: job--pypi-release.yml@sloria
-  parameters:
-    python: "3.9"
-    distributions: "sdist bdist_wheel"
-    dependsOn:
-      - tox_linux
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..89ef0d4
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,52 @@
+[project]
+name = "marshmallow-oneofschema"
+version = "3.0.2"
+description = "marshmallow multiplexing schema"
+readme = "README.rst"
+license = { file = "LICENSE" }
+authors = [{ name = "Maxim Kulkin", email = "maxim.kulkin@gmail.com" }]
+maintainers = [{ name = "Steven Loria", email = "sloria1@gmail.com" }]
+classifiers = [
+  "Intended Audience :: Developers",
+  "License :: OSI Approved :: MIT License",
+  "Programming Language :: Python :: 3",
+  "Programming Language :: Python :: 3.8",
+  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.10",
+  "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
+]
+requires-python = ">=3.8"
+dependencies = ["marshmallow>=3.0.0,<4.0.0"]
+
+[project.urls]
+Issues = "https://github.com/marshmallow-code/marshmallow-oneofschema/issues"
+Funding = "https://opencollective.com/marshmallow"
+Source = "https://github.com/marshmallow-code/marshmallow-oneofschema"
+
+[project.optional-dependencies]
+tests = ["pytest"]
+dev = ["marshmallow-oneofschema[tests]", "tox", "pre-commit~=3.5"]
+
+[build-system]
+requires = ["flit_core<4"]
+build-backend = "flit_core.buildapi"
+
+[tool.flit.sdist]
+include = ["tests/", "CHANGELOG.rst", "SECURITY.md", "tox.ini"]
+
+[tool.ruff]
+src = ["src"]
+fix = true
+show-fixes = true
+show-source = true
+
+[tool.ruff.lint]
+select = [
+  "B",  # flake8-bugbear
+  "E",  # pycodestyle error
+  "F",  # pyflakes
+  "I",  # isort
+  "UP", # pyupgrade
+  "W",  # pycodestyle warning
+]
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 1a2fd8f..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-[bdist_wheel]
-universal = 1
-
-[flake8]
-ignore = E203, E266, E501, W503
-max-line-length = 80
-max-complexity = 18
-select = B,C,E,F,W,T4,B9
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 7a74dc2..0000000
--- a/setup.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from setuptools import setup
-
-EXTRAS_REQUIRE = {
-    "tests": ["pytest", "mock"],
-    "lint": ["flake8==4.0.1", "flake8-bugbear==22.3.23", "pre-commit~=2.7"],
-}
-EXTRAS_REQUIRE["dev"] = EXTRAS_REQUIRE["tests"] + EXTRAS_REQUIRE["lint"] + ["tox"]
-
-
-def read(fname):
-    with open(fname) as fp:
-        content = fp.read()
-    return content
-
-
-setup(
-    name="marshmallow-oneofschema",
-    version="3.0.2",
-    description="marshmallow multiplexing schema",
-    long_description=read("README.rst"),
-    author="Maxim Kulkin",
-    author_email="maxim.kulkin@gmail.com",
-    maintainer="Steven Loria",
-    maintainer_email="sloria1@gmail.com",
-    url="https://github.com/marshmallow-code/marshmallow-oneofschema",
-    packages=["marshmallow_oneofschema"],
-    license="MIT",
-    keywords=[
-        "serialization",
-        "deserialization",
-        "json",
-        "marshal",
-        "marshalling",
-        "schema",
-        "validation",
-        "multiplexing",
-        "demultiplexing",
-        "polymorphic",
-    ],
-    python_requires=">=3.6",
-    install_requires=["marshmallow>=3.0.0,<4.0.0"],
-    extras_require=EXTRAS_REQUIRE,
-    classifiers=[
-        "Intended Audience :: Developers",
-        "License :: OSI Approved :: MIT License",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.6",
-        "Programming Language :: Python :: 3.7",
-        "Programming Language :: Python :: 3.8",
-        "Programming Language :: Python :: 3.9",
-    ],
-)
diff --git a/marshmallow_oneofschema/__init__.py b/src/marshmallow_oneofschema/__init__.py
similarity index 100%
rename from marshmallow_oneofschema/__init__.py
rename to src/marshmallow_oneofschema/__init__.py
diff --git a/marshmallow_oneofschema/one_of_schema.py b/src/marshmallow_oneofschema/one_of_schema.py
similarity index 96%
rename from marshmallow_oneofschema/one_of_schema.py
rename to src/marshmallow_oneofschema/one_of_schema.py
index 42d3270..7548c36 100644
--- a/marshmallow_oneofschema/one_of_schema.py
+++ b/src/marshmallow_oneofschema/one_of_schema.py
@@ -1,3 +1,5 @@
+import typing
+
 from marshmallow import Schema, ValidationError
 
 
@@ -57,7 +59,7 @@ def get_obj_type(self, obj):
 
     type_field = "type"
     type_field_remove = True
-    type_schemas = {}
+    type_schemas: typing.Dict[str, typing.Type[Schema]] = {}
 
     def get_obj_type(self, obj):
         """Returns name of the schema during dump() calls, given the object
@@ -167,9 +169,11 @@ def _load(self, data, *, partial=None, unknown=None, **kwargs):
 
         try:
             type_schema = self.type_schemas.get(data_type)
-        except TypeError:
+        except TypeError as error:
             # data_type could be unhashable
-            raise ValidationError({self.type_field: ["Invalid value: %s" % data_type]})
+            raise ValidationError(
+                {self.type_field: ["Invalid value: %s" % data_type]}
+            ) from error
         if not type_schema:
             raise ValidationError(
                 {self.type_field: ["Unsupported value: %s" % data_type]}
diff --git a/src/marshmallow_oneofschema/py.typed b/src/marshmallow_oneofschema/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/tox.ini b/tox.ini
index fa7f047..0e74a88 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,26 +1,16 @@
 [tox]
 envlist=
     lint
-    check-build
-    py{36,37,38,39}
+    py{38,39,310,311,312}
 
 [testenv]
 extras = tests
 commands = pytest {posargs}
 
 [testenv:lint]
-deps = pre-commit~=2.7
+deps = pre-commit~=3.5
 skip_install = true
-commands = pre-commit run --all-files --show-diff-on-failure
-
-[testenv:check-build]
-skip_install = true
-deps =
-    twine
-    pip >= 18.0.0
-commands =
-    pip wheel -w {envtmpdir}/build --no-deps .
-    twine check {envtmpdir}/build/*
+commands = pre-commit run --all-files
 
 ; Below tasks are for development only (not run in CI)
 


Test patch:
diff --git a/tests/test_one_of_schema.py b/tests/test_one_of_schema.py
index 0087aaa..e8d0528 100644
--- a/tests/test_one_of_schema.py
+++ b/tests/test_one_of_schema.py
@@ -1,8 +1,8 @@
 import marshmallow as m
 import marshmallow.fields as f
-from marshmallow_oneofschema import OneOfSchema
 import pytest
 
+from marshmallow_oneofschema import OneOfSchema
 
 REQUIRED_ERROR = "Missing data for required field."