Browse Source

push latest changes

pull/43/head
Alex Nørgaard 2 years ago
parent
commit
561ceaf845
No known key found for this signature in database GPG Key ID: 94D54F6A3604E97
  1. 9
      .github/workflows/coverage_and_lint.yml
  2. 3
      MANIFEST.in
  3. 24
      a2s/__init__.py
  4. 39
      a2s/a2s_async.py
  5. 24
      a2s/a2s_fragment.py
  6. 34
      a2s/a2s_sync.py
  7. 37
      a2s/byteio.py
  8. 24
      a2s/datacls.py
  9. 24
      a2s/defaults.py
  10. 25
      a2s/exceptions.py
  11. 59
      a2s/info.py
  12. 33
      a2s/players.py
  13. 36
      a2s/rules.py
  14. 2
      setup.py

9
.github/workflows/coverage_and_lint.yml

@ -32,8 +32,6 @@ jobs:
python-version: "${{ matrix.python-version }}" python-version: "${{ matrix.python-version }}"
- name: "Install Python deps @ ${{ matrix.python-version }}" - name: "Install Python deps @ ${{ matrix.python-version }}"
env:
PY_VER: "${{ matrix.python-version }}"
run: | run: |
pip install -U . pip install -U .
@ -42,10 +40,11 @@ jobs:
node-version: "17" node-version: "17"
- run: npm install --location=global pyright@latest - run: npm install --location=global pyright@latest
- name: "Type Sanity @ ${{ matrix.python-version }}"
run: pyright --pythonversion ${{ matrix.python-version }}
- name: "Type Coverage @ ${{ matrix.python-version }}" - name: "Type Coverage @ ${{ matrix.python-version }}"
run: | run: pyright --ignoreexternal --lib --verifytypes a2s --pythonversion ${{ matrix.python-version }}
pyright
pyright --ignoreexternal --lib --verifytypes a2s
- name: Lint - name: Lint
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}

3
MANIFEST.in

@ -0,0 +1,3 @@
include README.md
include LICENSE
include a2s/py.typed

24
a2s/__init__.py

@ -1,27 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from a2s.exceptions import BrokenMessageError as BrokenMessageError, BufferExhaustedError as BufferExhaustedError from a2s.exceptions import BrokenMessageError as BrokenMessageError, BufferExhaustedError as BufferExhaustedError
from a2s.info import GoldSrcInfo as GoldSrcInfo, SourceInfo as SourceInfo, ainfo as ainfo, info as info from a2s.info import GoldSrcInfo as GoldSrcInfo, SourceInfo as SourceInfo, ainfo as ainfo, info as info
from a2s.players import Player as Player, aplayers as aplayers, players as players from a2s.players import Player as Player, aplayers as aplayers, players as players

39
a2s/a2s_async.py

@ -1,26 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
@ -68,13 +45,13 @@ async def request_async(
@overload @overload
async def request_async( async def request_async(
address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[RulesProtocol] address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[RulesProtocol]
) -> Dict[str, str]: ) -> Dict[Union[str, bytes], Union[str, bytes]]:
... ...
async def request_async( async def request_async(
address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[T] address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[T]
) -> Union[SourceInfo, GoldSrcInfo, List[Player], Dict[str, str]]: ) -> Union[SourceInfo, GoldSrcInfo, List[Player], Dict[Union[str, bytes], Union[str, bytes]]]:
conn = await A2SStreamAsync.create(address, timeout) conn = await A2SStreamAsync.create(address, timeout)
response = await request_async_impl(conn, encoding, a2s_proto) response = await request_async_impl(conn, encoding, a2s_proto)
conn.close() conn.close()
@ -113,7 +90,7 @@ async def request_async_impl(
challenge: int = ..., challenge: int = ...,
retries: int = ..., retries: int = ...,
ping: Optional[float] = ..., ping: Optional[float] = ...,
) -> Dict[str, str]: ) -> Dict[Union[str, bytes], Union[str, bytes]]:
... ...
@ -124,7 +101,7 @@ async def request_async_impl(
challenge: int = 0, challenge: int = 0,
retries: int = 0, retries: int = 0,
ping: Optional[float] = None, ping: Optional[float] = None,
) -> Union[SourceInfo, GoldSrcInfo, Dict[str, str], List[Player]]: ) -> Union[SourceInfo, GoldSrcInfo, Dict[Union[str, bytes], Union[str, bytes]], List[Player]]:
send_time = time.monotonic() send_time = time.monotonic()
resp_data = await conn.request(a2s_proto.serialize_request(challenge)) resp_data = await conn.request(a2s_proto.serialize_request(challenge))
recv_time = time.monotonic() recv_time = time.monotonic()
@ -163,7 +140,7 @@ class A2SProtocol(asyncio.DatagramProtocol):
self.fragment_buf: List[A2SFragment] = [] self.fragment_buf: List[A2SFragment] = []
def connection_made(self, transport: asyncio.DatagramTransport) -> None: def connection_made(self, transport: asyncio.DatagramTransport) -> None:
self.transport = transport self.transport: asyncio.DatagramTransport = transport
def datagram_received(self, data: bytes, addr: Tuple[str, int]) -> None: def datagram_received(self, data: bytes, addr: Tuple[str, int]) -> None:
header = data[:4] header = data[:4]
@ -207,9 +184,9 @@ class A2SStreamAsync:
) )
def __init__(self, transport: asyncio.DatagramTransport, protocol: A2SProtocol, timeout: float) -> None: def __init__(self, transport: asyncio.DatagramTransport, protocol: A2SProtocol, timeout: float) -> None:
self.transport = transport self.transport: asyncio.DatagramTransport = transport
self.protocol = protocol self.protocol: A2SProtocol = protocol
self.timeout = timeout self.timeout: float = timeout
def __del__(self) -> None: def __del__(self) -> None:
self.close() self.close()

24
a2s/a2s_fragment.py

@ -1,27 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
import bz2 import bz2
import io import io

34
a2s/a2s_sync.py

@ -1,27 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from __future__ import annotations from __future__ import annotations
import io import io
@ -62,13 +38,15 @@ def request_sync(address: Tuple[str, int], timeout: float, encoding: str, a2s_pr
@overload @overload
def request_sync(address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[RulesProtocol]) -> Dict[str, str]: def request_sync(
address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[RulesProtocol]
) -> Dict[Union[str, bytes], Union[str, bytes]]:
... ...
def request_sync( def request_sync(
address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[T] address: Tuple[str, int], timeout: float, encoding: str, a2s_proto: Type[T]
) -> Union[List[Player], GoldSrcInfo, SourceInfo, Dict[str, str]]: ) -> Union[List[Player], GoldSrcInfo, SourceInfo, Dict[Union[str, bytes], Union[str, bytes]]]:
conn = A2SStream(address, timeout) conn = A2SStream(address, timeout)
response = request_sync_impl(conn, encoding, a2s_proto) response = request_sync_impl(conn, encoding, a2s_proto)
conn.close() conn.close()
@ -107,13 +85,13 @@ def request_sync_impl(
challenge: int = ..., challenge: int = ...,
retries: int = ..., retries: int = ...,
ping: Optional[float] = ..., ping: Optional[float] = ...,
) -> Dict[str, str]: ) -> Dict[Union[str, bytes], Union[str, bytes]]:
... ...
def request_sync_impl( def request_sync_impl(
conn: A2SStream, encoding: str, a2s_proto: Type[T], challenge: int = 0, retries: int = 0, ping: Optional[float] = None conn: A2SStream, encoding: str, a2s_proto: Type[T], challenge: int = 0, retries: int = 0, ping: Optional[float] = None
) -> Union[SourceInfo, GoldSrcInfo, Dict[str, str], List[Player]]: ) -> Union[SourceInfo, GoldSrcInfo, List[Player], Dict[Union[str, bytes], Union[str, bytes]]]:
send_time = time.monotonic() send_time = time.monotonic()
resp_data = conn.request(a2s_proto.serialize_request(challenge)) resp_data = conn.request(a2s_proto.serialize_request(challenge))
recv_time = time.monotonic() recv_time = time.monotonic()

37
a2s/byteio.py

@ -1,27 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from __future__ import annotations from __future__ import annotations
import io import io
@ -30,8 +6,6 @@ from typing import TYPE_CHECKING, Any, Optional, Tuple, Union
from a2s.exceptions import BufferExhaustedError from a2s.exceptions import BufferExhaustedError
from .defaults import DEFAULT_ENCODING
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import Literal from typing_extensions import Literal
@ -108,14 +82,14 @@ class ByteReader:
def read_bool(self) -> bool: def read_bool(self) -> bool:
return bool(self.unpack_one("b")) return bool(self.unpack_one("b"))
def read_char(self) -> str: def read_char(self) -> Union[str, bytes]:
char = self.unpack_one("c") char = self.unpack_one("c")
if self.encoding is not None: if self.encoding is not None:
return char.decode(self.encoding, errors="replace") return char.decode(self.encoding, errors="replace")
else: else:
return char.decode(DEFAULT_ENCODING, errors="replace") return char
def read_cstring(self, charsize: int = 1) -> str: def read_cstring(self, charsize: int = 1) -> Union[str, bytes]:
string = b"" string = b""
while True: while True:
c = self.read(charsize) c = self.read(charsize)
@ -127,7 +101,7 @@ class ByteReader:
if self.encoding is not None: if self.encoding is not None:
return string.decode(self.encoding, errors="replace") return string.decode(self.encoding, errors="replace")
else: else:
return string.decode(DEFAULT_ENCODING, errors="replace") return string
class ByteWriter: class ByteWriter:
@ -182,8 +156,9 @@ class ByteWriter:
def write_bool(self, val: bool) -> None: def write_bool(self, val: bool) -> None:
self.pack("b", val) self.pack("b", val)
def write_char(self, val: str) -> None: def write_char(self, val: Union[str, bytes]) -> None:
if self.encoding is not None: if self.encoding is not None:
assert isinstance(val, str)
self.pack("c", val.encode(self.encoding)) self.pack("c", val.encode(self.encoding))
else: else:
self.pack("c", val) self.pack("c", val)

24
a2s/datacls.py

@ -1,28 +1,4 @@
""" """
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-----
Cheap dataclasses module backport Cheap dataclasses module backport
Check out the official documentation to see what this is trying to Check out the official documentation to see what this is trying to

24
a2s/defaults.py

@ -1,27 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
DEFAULT_TIMEOUT = 3.0 DEFAULT_TIMEOUT = 3.0
DEFAULT_ENCODING = "utf-8" DEFAULT_ENCODING = "utf-8"
DEFAULT_RETRIES = 5 DEFAULT_RETRIES = 5

25
a2s/exceptions.py

@ -1,28 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
class BrokenMessageError(Exception): class BrokenMessageError(Exception):
pass pass

59
a2s/info.py

@ -1,26 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from __future__ import annotations from __future__ import annotations
from typing import Optional, Tuple, Union from typing import Optional, Tuple, Union
@ -42,16 +19,16 @@ class SourceInfo(metaclass=DataclsMeta):
protocol: int protocol: int
"""Protocol version used by the server""" """Protocol version used by the server"""
server_name: str server_name: Union[str, bytes]
"""Display name of the server""" """Display name of the server"""
map_name: str map_name: Union[str, bytes]
"""The currently loaded map""" """The currently loaded map"""
folder: str folder: Union[str, bytes]
"""Name of the game directory""" """Name of the game directory"""
game: str game: Union[str, bytes]
"""Name of the game""" """Name of the game"""
app_id: int app_id: int
@ -66,13 +43,13 @@ class SourceInfo(metaclass=DataclsMeta):
bot_count: int bot_count: int
"""Number of bots on the server""" """Number of bots on the server"""
server_type: str server_type: Union[str, bytes]
"""Type of the server: """Type of the server:
'd': Dedicated server 'd': Dedicated server
'l': Non-dedicated server 'l': Non-dedicated server
'p': SourceTV relay (proxy)""" 'p': SourceTV relay (proxy)"""
platform: str platform: Union[str, bytes]
"""Operating system of the server """Operating system of the server
'l', 'w', 'm' for Linux, Windows, macOS""" 'l', 'w', 'm' for Linux, Windows, macOS"""
@ -82,7 +59,7 @@ class SourceInfo(metaclass=DataclsMeta):
vac_enabled: bool vac_enabled: bool
"""Server has VAC enabled""" """Server has VAC enabled"""
version: str version: Union[str, bytes]
"""Version of the server software""" """Version of the server software"""
# Optional: # Optional:
@ -99,10 +76,10 @@ class SourceInfo(metaclass=DataclsMeta):
stv_port: int stv_port: int
"""Port of the SourceTV server""" """Port of the SourceTV server"""
stv_name: str stv_name: Union[str, bytes]
"""Name of the SourceTV server""" """Name of the SourceTV server"""
keywords: str keywords: Union[str, bytes]
"""Tags that describe the gamemode being played""" """Tags that describe the gamemode being played"""
game_id: int game_id: int
@ -134,19 +111,19 @@ class SourceInfo(metaclass=DataclsMeta):
class GoldSrcInfo(metaclass=DataclsMeta): class GoldSrcInfo(metaclass=DataclsMeta):
address: str address: Union[str, bytes]
"""IP Address and port of the server""" """IP Address and port of the server"""
server_name: str server_name: Union[str, bytes]
"""Display name of the server""" """Display name of the server"""
map_name: str map_name: Union[str, bytes]
"""The currently loaded map""" """The currently loaded map"""
folder: str folder: Union[str, bytes]
"""Name of the game directory""" """Name of the game directory"""
game: str game: Union[str, bytes]
"""Name of the game""" """Name of the game"""
player_count: int player_count: int
@ -158,13 +135,13 @@ class GoldSrcInfo(metaclass=DataclsMeta):
protocol: int protocol: int
"""Protocol version used by the server""" """Protocol version used by the server"""
server_type: str server_type: Union[str, bytes]
"""Type of the server: """Type of the server:
'd': Dedicated server 'd': Dedicated server
'l': Non-dedicated server 'l': Non-dedicated server
'p': SourceTV relay (proxy)""" 'p': SourceTV relay (proxy)"""
platform: str platform: Union[str, bytes]
"""Operating system of the server """Operating system of the server
'l', 'w' for Linux and Windows""" 'l', 'w' for Linux and Windows"""
@ -181,10 +158,10 @@ class GoldSrcInfo(metaclass=DataclsMeta):
"""Number of bots on the server""" """Number of bots on the server"""
# Optional: # Optional:
mod_website: str mod_website: Union[str, bytes]
"""URL to the mod website""" """URL to the mod website"""
mod_download: str mod_download: Union[str, bytes]
"""URL to download the mod""" """URL to download the mod"""
mod_version: int mod_version: int

33
a2s/players.py

@ -1,27 +1,3 @@
"""
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from a2s.a2s_async import request_async from a2s.a2s_async import request_async
@ -34,18 +10,17 @@ A2S_PLAYER_RESPONSE = 0x44
class Player(metaclass=DataclsMeta): class Player(metaclass=DataclsMeta):
"""Apparently an entry index, but seems to be always 0"""
index: int index: int
"""Apparently an entry index, but seems to be always 0"""
"""Name of the player"""
name: str name: str
"""Name of the player"""
"""Score of the player"""
score: int score: int
"""Score of the player"""
"""Time the player has been connected to the server"""
duration: float duration: float
"""Time the player has been connected to the server"""
def players(address: Tuple[str, int], timeout: float = DEFAULT_TIMEOUT, encoding: str = DEFAULT_ENCODING) -> List[Player]: def players(address: Tuple[str, int], timeout: float = DEFAULT_TIMEOUT, encoding: str = DEFAULT_ENCODING) -> List[Player]:

36
a2s/rules.py

@ -1,28 +1,4 @@
""" from typing import Dict, Optional, Tuple, Union
MIT License
Copyright (c) 2020 Gabriel Huber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from typing import Dict, Optional, Tuple
from a2s.a2s_async import request_async from a2s.a2s_async import request_async
from a2s.a2s_sync import request_sync from a2s.a2s_sync import request_sync
@ -32,13 +8,15 @@ from a2s.defaults import DEFAULT_ENCODING, DEFAULT_TIMEOUT
A2S_RULES_RESPONSE = 0x45 A2S_RULES_RESPONSE = 0x45
def rules(address: Tuple[str, int], timeout: float = DEFAULT_TIMEOUT, encoding: str = DEFAULT_ENCODING) -> Dict[str, str]: def rules(
address: Tuple[str, int], timeout: float = DEFAULT_TIMEOUT, encoding: str = DEFAULT_ENCODING
) -> Dict[Union[str, bytes], Union[str, bytes]]:
return request_sync(address, timeout, encoding, RulesProtocol) return request_sync(address, timeout, encoding, RulesProtocol)
async def arules( async def arules(
address: Tuple[str, int], timeout: float = DEFAULT_TIMEOUT, encoding: str = DEFAULT_ENCODING address: Tuple[str, int], timeout: float = DEFAULT_TIMEOUT, encoding: str = DEFAULT_ENCODING
) -> Dict[str, str]: ) -> Dict[Union[str, bytes], Union[str, bytes]]:
return await request_async(address, timeout, encoding, RulesProtocol) return await request_async(address, timeout, encoding, RulesProtocol)
@ -52,7 +30,9 @@ class RulesProtocol:
return b"\x56" + challenge.to_bytes(4, "little") return b"\x56" + challenge.to_bytes(4, "little")
@staticmethod @staticmethod
def deserialize_response(reader: ByteReader, response_type: int, ping: Optional[float]) -> Dict[str, str]: def deserialize_response(
reader: ByteReader, response_type: int, ping: Optional[float]
) -> Dict[Union[str, bytes], Union[str, bytes]]:
rule_count = reader.read_int16() rule_count = reader.read_int16()
# Have to use tuples to preserve evaluation order # Have to use tuples to preserve evaluation order
resp = dict((reader.read_cstring(), reader.read_cstring()) for _ in range(rule_count)) resp = dict((reader.read_cstring(), reader.read_cstring()) for _ in range(rule_count))

2
setup.py

@ -15,7 +15,7 @@ setuptools.setup(
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
url="https://github.com/Yepoleb/python-a2s", url="https://github.com/Yepoleb/python-a2s",
packages=["a2s"], packages=["a2s"],
package_data={"a2s": ["a2s/py.typed"]}, include_package_data=True,
license="MIT License", license="MIT License",
classifiers=[ classifiers=[
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",

Loading…
Cancel
Save