Skip to content

Commit c853d7f

Browse files
authored
feat: drop support for python 3.9 (#377)
EOL is approaching BREAKING CHANGE:
1 parent 5353293 commit c853d7f

File tree

8 files changed

+96
-128
lines changed

8 files changed

+96
-128
lines changed

.github/workflows/python-tests.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ jobs:
2525
fail-fast: false
2626
matrix:
2727
python-version:
28-
- '3.9'
2928
- '3.10'
3029
- '3.11'
3130
- '3.12'

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ repos:
5858
hooks:
5959
- id: pyupgrade
6060
args:
61-
- --py39-plus
61+
- --py310-plus
6262
- repo: https://github.com/MarcoGorelli/auto-walrus
6363
rev: ba0661836089a532a710f68713a3e3e53f7f0113 # frozen: 0.3.4
6464
hooks:

irclib/parser.py

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import warnings
99
from abc import ABCMeta, abstractmethod
1010
from collections.abc import Iterable, Iterator, Sequence
11-
from typing import Final, Literal, Optional, Union, cast
11+
from typing import Final, Literal, Optional, TypeAlias, cast
1212

13-
from typing_extensions import Self, TypeAlias
13+
from typing_extensions import Self
1414

1515
from irclib.errors import ParseError
1616

@@ -59,7 +59,7 @@
5959

6060

6161
def parse_server_time(
62-
value: Optional[str], default: datetime.datetime
62+
value: str | None, default: datetime.datetime
6363
) -> datetime.datetime:
6464
if value:
6565
return datetime.datetime.strptime(
@@ -86,7 +86,7 @@ def __str__(self) -> str:
8686
class Cap(Parseable):
8787
"""Represents a CAP entity as defined in IRCv3.2."""
8888

89-
def __init__(self, name: str, value: Optional[str] = None) -> None:
89+
def __init__(self, name: str, value: str | None = None) -> None:
9090
"""Construct Cap object.
9191
9292
Args:
@@ -102,11 +102,11 @@ def name(self) -> str:
102102
return self._name
103103

104104
@property
105-
def value(self) -> Optional[str]:
105+
def value(self) -> str | None:
106106
"""CAP value."""
107107
return self._value
108108

109-
def as_tuple(self) -> tuple[str, Optional[str]]:
109+
def as_tuple(self) -> tuple[str, str | None]:
110110
"""Get data as a tuple of values."""
111111
return self.name, self.value
112112

@@ -307,9 +307,10 @@ def __init__(self, tags: Iterable[MessageTag] = ()) -> None:
307307
@staticmethod
308308
def _cmp_type_map(
309309
obj: object,
310-
) -> Union[
311-
tuple[dict[str, MessageTag], Literal[True]], tuple[None, Literal[False]]
312-
]:
310+
) -> (
311+
tuple[dict[str, MessageTag], Literal[True]]
312+
| tuple[None, Literal[False]]
313+
):
313314
if isinstance(obj, str):
314315
return TagList.parse(obj), True
315316

@@ -367,9 +368,9 @@ class Prefix(Parseable):
367368

368369
def __init__(
369370
self,
370-
nick: Optional[str] = None,
371-
user: Optional[str] = None,
372-
host: Optional[str] = None,
371+
nick: str | None = None,
372+
user: str | None = None,
373+
host: str | None = None,
373374
) -> None:
374375
"""Construct a prefix."""
375376
self._nick = nick or ""
@@ -558,7 +559,7 @@ def __str__(self) -> str:
558559

559560

560561
def _parse_tags(
561-
tags: Union[TagList, dict[str, str], str, None, list[str]],
562+
tags: TagList | dict[str, str] | str | None | list[str],
562563
) -> MsgTagList:
563564
if isinstance(tags, TagList):
564565
return tags
@@ -575,7 +576,7 @@ def _parse_tags(
575576
return TagList(MessageTag.parse(str(tag)) for tag in tags)
576577

577578

578-
def _parse_prefix(prefix: Union[Prefix, str, None, Iterable[str]]) -> MsgPrefix:
579+
def _parse_prefix(prefix: Prefix | str | None | Iterable[str]) -> MsgPrefix:
579580
if isinstance(prefix, Prefix):
580581
return prefix
581582

@@ -589,7 +590,7 @@ def _parse_prefix(prefix: Union[Prefix, str, None, Iterable[str]]) -> MsgPrefix:
589590

590591

591592
def _parse_params(
592-
parameters: tuple[Union[str, list[str], ParamList], ...],
593+
parameters: tuple[str | list[str] | ParamList, ...],
593594
) -> ParamList:
594595
if len(parameters) == 1 and not isinstance(parameters[0], str):
595596
# This seems to be a list
@@ -606,11 +607,11 @@ class Message(Parseable):
606607

607608
def __init__(
608609
self,
609-
tags: Union[TagList, dict[str, str], str, None, list[str]],
610-
prefix: Union[str, Prefix, None, Iterable[str]],
610+
tags: TagList | dict[str, str] | str | None | list[str],
611+
prefix: str | Prefix | None | Iterable[str],
611612
command: str,
612-
*parameters: Union[str, list[str], ParamList],
613-
time: Optional[datetime.datetime] = None,
613+
*parameters: str | list[str] | ParamList,
614+
time: datetime.datetime | None = None,
614615
) -> None:
615616
"""Construct message object."""
616617
self._tags = _parse_tags(tags)
@@ -638,7 +639,7 @@ def has_tag(self, name: str) -> bool:
638639

639640
return name in self.tags
640641

641-
def get_tag_value(self, name: str) -> Optional[str]:
642+
def get_tag_value(self, name: str) -> str | None:
642643
"""Get value for a message tag, or None if not set."""
643644
if self.tags and name in self.tags:
644645
return self.tags[name].value
@@ -654,12 +655,12 @@ def time(self) -> datetime.datetime:
654655
return parse_server_time(self.get_tag_value("time"), self._time)
655656

656657
@property
657-
def message_id(self) -> Optional[str]:
658+
def message_id(self) -> str | None:
658659
"""Unique message ID provided by server."""
659660
return self.get_tag_value("msgid")
660661

661662
@property
662-
def batch_id(self) -> Optional[str]:
663+
def batch_id(self) -> str | None:
663664
"""Batch ID provided by server."""
664665
return self.get_tag_value("batch")
665666

@@ -689,16 +690,13 @@ def as_tuple(self) -> MessageTuple:
689690

690691
@classmethod
691692
def parse(
692-
cls,
693-
text: Union[str, bytes],
694-
*,
695-
time: Optional[datetime.datetime] = None,
693+
cls, text: str | bytes, *, time: datetime.datetime | None = None
696694
) -> Self:
697695
"""Parse an IRC message in to objects."""
698696
if isinstance(text, memoryview):
699697
text = text.tobytes().decode(errors="ignore")
700698

701-
if isinstance(text, (bytes, bytearray)):
699+
if isinstance(text, bytes | bytearray):
702700
text = text.decode(errors="ignore")
703701

704702
tags = ""
@@ -720,7 +718,7 @@ def parse(
720718

721719
def __eq__(self, other: object) -> bool:
722720
"""Compare to another message which can be str, bytes, or a Message object."""
723-
if isinstance(other, (str, bytes)):
721+
if isinstance(other, str | bytes):
724722
return self == Message.parse(other)
725723

726724
if isinstance(other, Message):
@@ -730,7 +728,7 @@ def __eq__(self, other: object) -> bool:
730728

731729
def __ne__(self, other: object) -> bool:
732730
"""Compare to another message which can be str, bytes, or a Message object."""
733-
if isinstance(other, (str, bytes)):
731+
if isinstance(other, str | bytes):
734732
return self != Message.parse(other)
735733

736734
if isinstance(other, Message):

irclib/util/commands.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""IRC command data and utilities."""
22

33
from collections.abc import Iterator, Mapping
4-
from typing import Optional, cast
4+
from typing import cast
55

66
import attr
77

@@ -13,7 +13,7 @@ class CommandArgument:
1313
"""A single IRC command argument."""
1414

1515
name: str
16-
required: Optional[bool] = True
16+
required: bool | None = True
1717

1818
@classmethod
1919
def parse(cls, s: str) -> "CommandArgument":
@@ -47,7 +47,7 @@ class Command:
4747
name: str
4848
args: list[CommandArgument]
4949
min_args: int = 0
50-
max_args: Optional[int] = None
50+
max_args: int | None = None
5151

5252

5353
class LookupDict(Mapping[str, Command]):

irclib/util/frozendict.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Frozen Dict."""
22

33
from collections.abc import Iterable, Iterator, Mapping
4-
from typing import Optional, TypeVar, Union
4+
from typing import TypeVar
55

66
from typing_extensions import Self
77

@@ -20,14 +20,14 @@ class FrozenDict(Mapping[str, _V]):
2020

2121
def __init__(
2222
self,
23-
seq: Union[Mapping[str, _V], Iterable[tuple[str, _V]], None] = None,
23+
seq: Mapping[str, _V] | Iterable[tuple[str, _V]] | None = None,
2424
**kwargs: _V,
2525
) -> None:
2626
"""Construct a FrozenDict."""
2727
d = dict(seq, **kwargs) if seq is not None else dict(**kwargs)
2828

2929
self.__data: dict[str, _V] = d
30-
self.__hash: Optional[int] = None
30+
self.__hash: int | None = None
3131

3232
def copy(self, **kwargs: _V) -> Self:
3333
"""Copy dict, replacing values according to kwargs.

0 commit comments

Comments
 (0)