diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca281b9..f8c56af 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,21 +19,18 @@ jobs: fail-fast: false matrix: python-version: - - '3.8' - - '3.9' - '3.10' - '3.11' - '3.12' - '3.13' - - 'pypy-3.8' - - 'pypy-3.9' + - '3.14' - 'pypy-3.10' - 'pypy-3.11' toxenv: [py] include: - - python-version: '3.8' + - python-version: '3.10' toxenv: lint - - python-version: '3.8' + - python-version: '3.10' toxenv: typing steps: - name: Check out repository diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ef61e2..716d6db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ v0.3.0 (in development) ----------------------- - Remove unused `typing_extensions` dependency +- Support Python 3.14 +- Drop support for Python 3.8 and 3.9 v0.2.2 (2024-12-01) ------------------- diff --git a/README.rst b/README.rst index 5fc898c..49ecfd2 100644 --- a/README.rst +++ b/README.rst @@ -35,7 +35,7 @@ recipients' raw e-mail addresses from an ``EmailMessage``. Installation ============ -``mailbits`` requires Python 3.8 or higher. Just use `pip +``mailbits`` requires Python 3.10 or higher. Just use `pip `_ for Python 3 (You have pip, right?) to install it:: python3 -m pip install mailbits @@ -78,11 +78,11 @@ b'text/plain; charset="utf-8"; name*=utf-8\'\'r%C3%A9sum%C3%A9.txt' .. code:: python class MessageDict(TypedDict): - unixfrom: Optional[str] - headers: Dict[str, Any] - preamble: Optional[str] + unixfrom: str | None + headers: dict[str, Any] + preamble: str | None content: Any - epilogue: Optional[str] + epilogue: str | None mailbits.email2dict(msg: email.message.Message, include_all: bool = False) -> MessageDict @@ -300,7 +300,7 @@ __ https://docs.python.org/3/library/email.examples.html .. code:: python - mailbits.format_addresses(addresses: Iterable[Union[str, Address, Group]], encode: bool = False) -> str + mailbits.format_addresses(addresses: Iterable[str | Address | Group], encode: bool = False) -> str Convert an iterable of e-mail address strings (of the form "``foo@example.com``", without angle brackets or a display name), @@ -341,8 +341,8 @@ into an ``Address`` object. .. code:: python - mailbits.parse_addresses(s: Union[str, email.headerregistry.AddressHeader]) \ - -> List[Union[email.headerregistry.Address, email.headerregistry.Group]] + mailbits.parse_addresses(s: str | email.headerregistry.AddressHeader) \ + -> list[email.headerregistry.Address | email.headerregistry.Group] Parse a formatted list of e-mail addresses or the contents of an ``EmailMessage``'s "To", "CC", "BCC", etc. header into a list of ``Address`` @@ -354,7 +354,7 @@ and/or ``Group`` objects. .. code:: python - mailbits.recipient_addresses(msg: email.message.EmailMessage) -> List[str] + mailbits.recipient_addresses(msg: email.message.EmailMessage) -> list[str] Return a sorted list of all of the distinct e-mail addresses (not including display names) in an ``EmailMessage``'s combined "To", "CC", and "BCC" headers. diff --git a/pyproject.toml b/pyproject.toml index 90597a2..5ea0d67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "mailbits" dynamic = ["version"] description = "Assorted e-mail utility functions" readme = "README.rst" -requires-python = ">=3.8" +requires-python = ">=3.10" license = "MIT" license-files = ["LICENSE"] authors = [ @@ -28,12 +28,11 @@ keywords = [ classifiers = [ "Programming Language :: Python :: 3 :: Only", "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", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Intended Audience :: Developers", diff --git a/src/mailbits/email2dict.py b/src/mailbits/email2dict.py index f1e3f76..a48ec73 100644 --- a/src/mailbits/email2dict.py +++ b/src/mailbits/email2dict.py @@ -4,16 +4,16 @@ from email import headerregistry as hr from email.message import Message import inspect -from typing import Any, Optional, TypedDict +from typing import Any, TypedDict from .misc import message2email, parse_addresses class MessageDict(TypedDict): - unixfrom: Optional[str] + unixfrom: str | None headers: dict[str, Any] - preamble: Optional[str] + preamble: str | None content: Any - epilogue: Optional[str] + epilogue: str | None def process_unique_string_header(ush: list[Any]) -> str: @@ -108,7 +108,7 @@ def process_cte_header(cteh: list[Any]) -> str: return cteh[0].cte # TODO: When is this different from `str(cteh[0])`? -def process_mime_version_header(mvh: list[Any]) -> Optional[str]: +def process_mime_version_header(mvh: list[Any]) -> str | None: assert len(mvh) == 1 assert isinstance(mvh[0], hr.MIMEVersionHeader) return mvh[0].version diff --git a/tox.ini b/tox.ini index 09baac6..8620e72 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = lint,typing,py38,py39,py310,py311,py312,py313,pypy3 +envlist = lint,typing,py310,py311,py312,py313,py314,pypy3 skip_missing_interpreters = True isolated_build = True minversion = 3.3.0