Skip to content

Commit

Permalink
Drop 3.6 & move to Hatch + static metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
hynek committed Dec 30, 2022
1 parent 88d2a37 commit 79ffc48
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 52 deletions.
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Expand Up @@ -28,7 +28,6 @@ jobs:
fail-fast: false
matrix:
python-version:
- "3.6"
- "3.7"
- "3.8"
- "3.9"
Expand Down
114 changes: 112 additions & 2 deletions pyproject.toml
@@ -1,8 +1,118 @@
# SPDX-License-Identifier: MIT

[build-system]
requires = ["setuptools>=40.6.0", "wheel"]
build-backend = "setuptools.build_meta"
requires = ["hatchling", "hatch-fancy-pypi-readme"]
build-backend = "hatchling.build"


[project]
name = "attrs"
version = "23.1.0.dev0"
authors = [{ name = "Hynek Schlawack", email = "hs@ox.cx" }]
license = { file = "LICENSE" }
requires-python = ">=3.7"
description = "Classes Without Boilerplate"
keywords = ["class", "attribute", "boilerplate"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Natural Language :: English",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = ["importlib_metadata;python_version<'3.8'"]
dynamic = ["readme"]

[project.optional-dependencies]
tests-no-zope = [
# For regression test to ensure cloudpickle compat doesn't break.
'cloudpickle; python_implementation == "CPython"',
"hypothesis",
"pympler",
# 4.3.0 dropped last use of `convert`
"pytest>=4.3.0",
"pytest-xdist",
# Since the mypy error messages keep changing, we have to keep updating this
# pin.
'mypy>=0.971,<0.990; python_implementation == "CPython"',
'pytest-mypy-plugins; python_implementation == "CPython" and python_version<"3.11"',
]
tests = ["attrs[tests-no-zope]", "zope.interface"]
cov = [
"attrs[tests]",
# Makes coverage work with pytest-xdist.
"coverage-enable-subprocess",
# Ensure coverage is new enough for `source_pkgs`.
"coverage>=5.3",
]
docs = [
"furo",
"myst-parser",
"sphinx",
"zope.interface",
"sphinx-notfound-page",
"sphinxcontrib-towncrier",
"towncrier",
]
dev = ["attrs[tests,docs]", "pre-commit"]

[project.urls]
Documentation = "https://www.attrs.org/"
Changelog = "https://www.attrs.org/en/stable/changelog.html"
"Bug Tracker" = "https://github.com/python-attrs/attrs/issues"
"Source Code" = "https://github.com/python-attrs/attrs"
Funding = "https://github.com/sponsors/hynek"
Tidelift = "https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi"
Ko-fi = "https://ko-fi.com/the_hynek"


[tool.hatch.build.targets.wheel]
packages = ["src/attr", "src/attrs"]

[tool.hatch.metadata.hooks.fancy-pypi-readme]
content-type = "text/markdown"

# PyPI doesn't support the <picture> tag.
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
text = """<p align="center">
<a href="https://www.attrs.org/">
<img src="https://raw.githubusercontent.com/python-attrs/attrs/main/docs/_static/attrs_logo.svg" width="35%" alt="attrs" />
</a>
</p>
"""

[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
path = "README.md"
start-after = "<!-- logo-end -->"

[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
text = """
## Release Information
"""

[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
path = "CHANGELOG.md"
pattern = "\n(###.+?\n)## "

[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
text = """
---
[Full changelog](https://www.structlog.org/en/stable/changelog.html)
"""


[tool.pytest.ini_options]
Expand Down
91 changes: 65 additions & 26 deletions src/attr/__init__.py
@@ -1,9 +1,11 @@
# SPDX-License-Identifier: MIT

import sys
import warnings
"""
Classes Without Boilerplate
"""

from functools import partial
from typing import Callable

from . import converters, exceptions, filters, setters, validators
from ._cmp import cmp_using
Expand All @@ -24,30 +26,6 @@
from ._version_info import VersionInfo


if sys.version_info < (3, 7): # pragma: no cover
warnings.warn(
"Running attrs on Python 3.6 is deprecated & we intend to drop "
"support soon. If that's a problem for you, please let us know why & "
"we MAY re-evaluate: <https://github.com/python-attrs/attrs/pull/993>",
DeprecationWarning,
)

__version__ = "22.3.0.dev0"
__version_info__ = VersionInfo._from_version_string(__version__)

__title__ = "attrs"
__description__ = "Classes Without Boilerplate"
__url__ = "https://www.attrs.org/"
__uri__ = __url__
__doc__ = __description__ + " <" + __uri__ + ">"

__author__ = "Hynek Schlawack"
__email__ = "hs@ox.cx"

__license__ = "MIT"
__copyright__ = "Copyright (c) 2015 Hynek Schlawack"


s = attributes = attrs
ib = attr = attrib
dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)
Expand Down Expand Up @@ -91,3 +69,64 @@ class AttrsInstance:
"validate",
"validators",
]


def _make_getattr(mod_name: str) -> Callable:
"""
Create a metadata proxy for packaging information that uses *mod_name* in
its warnings and errors.
"""

def __getattr__(name: str) -> str:
dunder_to_metadata = {
"__title__": "Name",
"__copyright__": "",
"__version__": "version",
"__version_info__": "version",
"__description__": "summary",
"__uri__": "",
"__url__": "",
"__author__": "",
"__email__": "",
"__license__": "license",
}
if name not in dunder_to_metadata.keys():
raise AttributeError(f"module {mod_name} has no attribute {name}")

import sys
import warnings

if sys.version_info < (3, 8):
from importlib_metadata import metadata
else:
from importlib.metadata import metadata

if name != "__version_info__":
warnings.warn(
f"Accessing {mod_name}.{name} is deprecated and will be "
"removed in a future release. Use importlib.metadata directly "
"to query for attrs's packaging metadata.",
DeprecationWarning,
stacklevel=2,
)

meta = metadata("attrs")
if name == "__license__":
return "MIT"
elif name == "__copyright__":
return "Copyright (c) 2015 Hynek Schlawack"
elif name in ("__uri__", "__url__"):
return meta["Project-URL"].split(" ", 1)[-1]
elif name == "__version_info__":
return VersionInfo._from_version_string(meta["version"])
elif name == "__author__":
return meta["Author-email"].rsplit(" ", 1)[0]
elif name == "__email__":
return meta["Author-email"].rsplit("<", 1)[1][:-1]

return meta[dunder_to_metadata[name]]

return __getattr__


__getattr__ = _make_getattr(__name__)
7 changes: 1 addition & 6 deletions src/attr/validators.py
Expand Up @@ -9,19 +9,14 @@
import re

from contextlib import contextmanager
from re import Pattern

from ._config import get_run_validators, set_run_validators
from ._make import _AndValidator, and_, attrib, attrs
from .converters import default_if_none
from .exceptions import NotCallableError


try:
Pattern = re.Pattern
except AttributeError: # Python <3.7 lacks a Pattern type.
Pattern = type(re.compile(""))


__all__ = [
"and_",
"deep_iterable",
Expand Down
13 changes: 3 additions & 10 deletions src/attrs/__init__.py
Expand Up @@ -5,16 +5,7 @@
Attribute,
AttrsInstance,
Factory,
__author__,
__copyright__,
__description__,
__doc__,
__email__,
__license__,
__title__,
__url__,
__version__,
__version_info__,
_make_getattr,
assoc,
cmp_using,
define,
Expand Down Expand Up @@ -70,3 +61,5 @@
"validate",
"validators",
]

__getattr__ = _make_getattr(__name__)

0 comments on commit 79ffc48

Please sign in to comment.