Skip to content

Commit

Permalink
Merge branch 'main' into add-codespell
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsDrike committed Dec 30, 2022
2 parents be2ede8 + 785b926 commit 1387dd3
Show file tree
Hide file tree
Showing 22 changed files with 128 additions and 68 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
install_args: "--without release"

- name: Run pre-commit hooks
run: SKIP=black,isort,flake8,pyright,codespell pre-commit run --all-files
run: SKIP=black,isort,flake8,slotscheck,codespell,pyright pre-commit run --all-files

- name: Run black formatter check
run: black --check --diff .
Expand All @@ -41,5 +41,8 @@ jobs:
- name: Run codespell linter
run: codespell .

- name: Run slotscheck
run: slotscheck -m mcproto

- name: Run pyright type checker
run: pyright .
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ repos:
language: system


- repo: local
hooks:
- id: slotscheck
name: Slotscheck
description: "Slotscheck: Ensure your __slots__ are working properly"
entry: poetry run slotscheck -v
language: python
require_serial: true
types: [python]

- repo: local
hooks:
- id: pyright
Expand Down
2 changes: 2 additions & 0 deletions changes/14.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add missing `__slots__` to `ServerBoundPacket` and `ClientBoundPacket` subclasses, which inherited from slotted
`Packet`, but didn't themselves define `__slots__`, causing `__dict__` to be needlessly created.
3 changes: 3 additions & 0 deletions changes/14.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Add `__slots__` to most classes in the project
- All connection classes are now slotted
- Classes in `mcproto.utils.abc` are now slotted
1 change: 1 addition & 0 deletions changes/14.internal.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add slotscheck, ensuring `__slots__` are defined properly everywhere.
1 change: 1 addition & 0 deletions changes/14.internal.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make `typing-extensions` a runtime dependency and use it directly, don't rely on `if typing.TYPE_CHECKING` blocks.
8 changes: 8 additions & 0 deletions changes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ the file with your `$EDITOR`.
If necessary, multiple fragment files can be created per pull-request, with different change types, if the PR covers
multiple areas (for example a PR that both introduces a feature, and changes the documentation).

Additionally, if a single PR is addressing multiple unrelated topics in the same category, and needs to make multiple
distinct changelog entries, you can do so by adding an optional counter value to the fragment file name, which needs to
be an integer, for example: `25.internal.1.md` and `25.internal.2.md`. This counter value will not be shown in the
final changelog and is merely here for separation of the individual fragments. That said, if you end up making multiple
distinct changelog fragments like this is a good sign that your PR is probably too big, and you should split it up into
multiple PRs. Making huge PRs that address several unrelated topics at once are generally a bad practice, and should be
avoided.

To preview the latest changelog, run `towncrier build --draft --version [version number]`. (For version number, you can
pretty much enter anything as this is just for a draft version. For true builds, this would be the next version number,
so for example, if the current version is 1.0.2, next one will be one either 1.0.3, or 1.1.0, or 2.0.0. But for drafts,
Expand Down
33 changes: 21 additions & 12 deletions mcproto/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,13 @@
import asyncio
import socket
from abc import ABC, abstractmethod
from typing import Generic, Optional, TYPE_CHECKING, TypeVar
from typing import Generic, Optional, TypeVar

import asyncio_dgram
from typing_extensions import ParamSpec, Self

from mcproto.protocol.base_io import BaseAsyncReader, BaseAsyncWriter, BaseSyncReader, BaseSyncWriter

if TYPE_CHECKING:
from typing_extensions import ParamSpec, Self

P = ParamSpec("P")

R = TypeVar("R")
T_SOCK = TypeVar("T_SOCK", bound=socket.socket)
T_STREAMREADER = TypeVar("T_STREAMREADER", bound=asyncio.StreamReader)
T_STREAMWRITER = TypeVar("T_STREAMWRITER", bound=asyncio.StreamWriter)
T_DATAGRAM_CLIENT = TypeVar("T_DATAGRAM_CLIENT", bound=asyncio_dgram.aio.DatagramClient)

__all__ = [
"AsyncConnection",
"SyncConnection",
Expand All @@ -29,8 +19,17 @@
"UDPSyncConnection",
]

P = ParamSpec("P")
R = TypeVar("R")
T_SOCK = TypeVar("T_SOCK", bound=socket.socket)
T_STREAMREADER = TypeVar("T_STREAMREADER", bound=asyncio.StreamReader)
T_STREAMWRITER = TypeVar("T_STREAMWRITER", bound=asyncio.StreamWriter)
T_DATAGRAM_CLIENT = TypeVar("T_DATAGRAM_CLIENT", bound=asyncio_dgram.aio.DatagramClient)


class SyncConnection(BaseSyncReader, BaseSyncWriter, ABC):
__slots__ = ("closed",)

def __init__(self):
self.closed = False

Expand Down Expand Up @@ -59,6 +58,8 @@ def __exit__(self, *a, **kw) -> None:


class AsyncConnection(BaseAsyncReader, BaseAsyncWriter, ABC):
__slots__ = ("closed",)

def __init__(self):
self.closed = False

Expand Down Expand Up @@ -87,6 +88,8 @@ async def __aexit__(self, *a, **kw) -> None:


class TCPSyncConnection(SyncConnection, Generic[T_SOCK]):
__slots__ = ("socket",)

def __init__(self, socket: T_SOCK):
super().__init__()
self.socket = socket
Expand Down Expand Up @@ -130,6 +133,8 @@ def _close(self) -> None:


class TCPAsyncConnection(AsyncConnection, Generic[T_STREAMREADER, T_STREAMWRITER]):
__slots__ = ("reader", "writer", "timeout")

def __init__(self, reader: T_STREAMREADER, writer: T_STREAMWRITER, timeout: float):
super().__init__()
self.reader = reader
Expand Down Expand Up @@ -180,6 +185,8 @@ def socket(self) -> socket.socket:


class UDPSyncConnection(SyncConnection, Generic[T_SOCK]):
__slots__ = ("socket", "address")

BUFFER_SIZE = 65535

def __init__(self, socket: T_SOCK, address: tuple[str, int]):
Expand Down Expand Up @@ -215,6 +222,8 @@ def _close(self) -> None:


class UDPAsyncConnection(AsyncConnection, Generic[T_DATAGRAM_CLIENT]):
__slots__ = ("stream", "timeout")

def __init__(self, stream: T_DATAGRAM_CLIENT, timeout: float):
super().__init__()
self.stream = stream
Expand Down
4 changes: 4 additions & 0 deletions mcproto/packets/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class Packet(Serializable, RequiredParamsABCMixin):
class ServerBoundPacket(Packet):
"""Packet bound to a server (Client -> Server)."""

__slots__ = ()


class ClientBoundPacket(Packet):
"""Packet bound to a client (Server -> Client)."""

__slots__ = ()
4 changes: 2 additions & 2 deletions mcproto/packets/interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
from mcproto.packets.map import PacketMap
from mcproto.protocol.base_io import BaseAsyncReader, BaseAsyncWriter, BaseSyncReader, BaseSyncWriter

T_Packet = TypeVar("T_Packet", bound=Packet)

__all__ = ["async_read_packet", "async_write_packet", "sync_read_packet", "sync_write_packet", "PACKET_MAP"]

T_Packet = TypeVar("T_Packet", bound=Packet)

# PACKET FORMAT:
# | Field name | Field type | Notes |
# |-------------|---------------|---------------------------------------|
Expand Down
7 changes: 3 additions & 4 deletions mcproto/packets/map.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from __future__ import annotations

from collections.abc import Mapping
from typing import Any, ClassVar, Literal, TYPE_CHECKING, overload
from typing import Any, ClassVar, Literal, overload

from typing_extensions import TypeGuard

from mcproto.packets.abc import ClientBoundPacket, GameState, Packet, PacketDirection, ServerBoundPacket
from mcproto.utils.version_map import VersionMap, WalkableModuleData

if TYPE_CHECKING:
from typing_extensions import TypeGuard

__all__ = ["PacketMap"]


Expand Down
8 changes: 3 additions & 5 deletions mcproto/packets/v757/handshaking/handshake.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
from __future__ import annotations

from enum import IntEnum
from typing import ClassVar, TYPE_CHECKING, Union
from typing import ClassVar, Union

from typing_extensions import Self

from mcproto.buffer import Buffer
from mcproto.packets.abc import GameState, ServerBoundPacket
from mcproto.protocol.base_io import StructFormat

if TYPE_CHECKING:
from typing_extensions import Self


__all__ = [
"NextState",
"Handshake",
Expand Down
8 changes: 3 additions & 5 deletions mcproto/packets/v757/status/ping.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
from __future__ import annotations

from typing import ClassVar, TYPE_CHECKING
from typing import ClassVar

from typing_extensions import Self

from mcproto.buffer import Buffer
from mcproto.packets.abc import ClientBoundPacket, GameState, ServerBoundPacket
from mcproto.protocol.base_io import StructFormat

if TYPE_CHECKING:
from typing_extensions import Self


__all__ = ["PingPong"]


Expand Down
7 changes: 3 additions & 4 deletions mcproto/packets/v757/status/status.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from __future__ import annotations

import json
from typing import Any, ClassVar, TYPE_CHECKING
from typing import Any, ClassVar

from typing_extensions import Self

from mcproto.buffer import Buffer
from mcproto.packets.abc import ClientBoundPacket, GameState, ServerBoundPacket

if TYPE_CHECKING:
from typing_extensions import Self

__all__ = ["StatusRequest", "StatusResponse"]


Expand Down
13 changes: 6 additions & 7 deletions mcproto/protocol/base_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
from collections.abc import Awaitable, Callable
from enum import Enum
from itertools import count
from typing import Literal, Optional, TYPE_CHECKING, TypeVar, Union, overload
from typing import Literal, Optional, TypeVar, Union, overload

from mcproto.protocol.utils import from_twos_complement, to_twos_complement

if TYPE_CHECKING:
from typing_extensions import TypeAlias
from typing_extensions import TypeAlias

T = TypeVar("T")
R = TypeVar("R")
from mcproto.protocol.utils import from_twos_complement, to_twos_complement

__all__ = [
"BaseAsyncReader",
Expand All @@ -25,6 +21,9 @@
"FLOAT_FORMATS_TYPE",
]

T = TypeVar("T")
R = TypeVar("R")


# region: Format types

Expand Down
11 changes: 7 additions & 4 deletions mcproto/utils/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

from abc import ABC, abstractmethod
from collections.abc import Sequence
from typing import ClassVar, TYPE_CHECKING
from typing import ClassVar

from mcproto.buffer import Buffer
from typing_extensions import Self

if TYPE_CHECKING:
from typing_extensions import Self
from mcproto.buffer import Buffer

__all__ = ["RequiredParamsABCMixin", "Serializable"]

Expand All @@ -32,6 +31,8 @@ class RequiredParamsABCMixin:
and if _REQUIRED_CLASS_VARS_NO_MRO isn't set, no such check will be performed.
"""

__slots__ = ()

_REQUIRRED_CLASS_VARS: ClassVar[Sequence[str]]
_REQUIRED_CLASS_VARS_NO_MRO: ClassVar[Sequence[str]]

Expand Down Expand Up @@ -64,6 +65,8 @@ def __new__(cls: type[Self], *a, **kw) -> Self:
class Serializable(ABC):
"""Base class for any type that should be (de)serializable into/from given buffer data."""

__slots__ = ()

@abstractmethod
def serialize(self) -> Buffer:
"""Represent the object as a transmittable sequence of bytes."""
Expand Down
14 changes: 5 additions & 9 deletions mcproto/utils/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@
import warnings
from collections.abc import Callable
from functools import wraps
from typing import Optional, TYPE_CHECKING, TypeVar, Union
from typing import Optional, TypeVar, Union

from mcproto.utils.version import SemanticVersion
from typing_extensions import ParamSpec, Protocol

if TYPE_CHECKING:
from typing_extensions import ParamSpec, Protocol
from mcproto.utils.version import SemanticVersion

P = ParamSpec("P")
else:
Protocol = object
__all__ = ["deprecated", "deprecation_warn"]

R = TypeVar("R")

__all__ = ["deprecated", "deprecation_warn"]
P = ParamSpec("P")


def deprecation_warn(
Expand Down
5 changes: 2 additions & 3 deletions mcproto/utils/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import re
from dataclasses import dataclass
from itertools import zip_longest
from typing import Any, Optional, TYPE_CHECKING
from typing import Any, Optional

if TYPE_CHECKING:
from typing_extensions import Self
from typing_extensions import Self

__all__ = ["SemanticVersion"]

Expand Down
9 changes: 4 additions & 5 deletions mcproto/utils/version_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@
from abc import ABC, abstractmethod
from collections.abc import Hashable, Iterator, Sequence
from types import ModuleType
from typing import Any, ClassVar, Generic, NamedTuple, NoReturn, TYPE_CHECKING, TypeVar
from typing import Any, ClassVar, Generic, NamedTuple, NoReturn, TypeVar

from typing_extensions import TypeGuard

from mcproto.utils.abc import RequiredParamsABCMixin

if TYPE_CHECKING:
from typing_extensions import TypeGuard
__all__ = ["VersionMap", "WalkableModuleData"]

K = TypeVar("K", bound=Hashable)
V = TypeVar("V")

__all__ = ["VersionMap", "WalkableModuleData"]


class WalkableModuleData(NamedTuple):
module: ModuleType
Expand Down
Loading

0 comments on commit 1387dd3

Please sign in to comment.