Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
597e1b1
python 3.13 support
altendky Jan 10, 2025
1f66b2f
some more
altendky Jan 13, 2025
6761551
Merge branch 'main' into fine_william___fine
altendky Jul 11, 2025
f1c6ee8
Merge branch 'main' into fine_william___fine
altendky Jul 16, 2025
7459a8b
3.13 for dep checks
altendky Jul 17, 2025
aa4fe30
more 3.13 *confused*
altendky Jul 17, 2025
3555b28
Merge branch 'main' into fine_william___fine
altendky Jul 30, 2025
3c335be
Merge branch 'main' into fine_william___fine
altendky Aug 5, 2025
e51c22a
Merge branch 'main' into fine_william___fine
altendky Aug 5, 2025
da74ac1
Merge branch 'main' into fine_william___fine
altendky Aug 18, 2025
ec0df86
Merge branch 'main' into fine_william___fine
altendky Sep 2, 2025
238ae01
fixup
altendky Sep 2, 2025
f8d4f7d
fixup
altendky Sep 2, 2025
828e413
update expected signature in 3.13
altendky Sep 2, 2025
fafd2a2
Merge branch 'main' into fine_william___fine
altendky Sep 11, 2025
f395ca9
fixup _attach/_detach hinting and testing
altendky Sep 11, 2025
d25d03c
Merge branch 'main' into fine_william___fine
altendky Sep 29, 2025
fd39d60
ban freethreading
altendky Oct 9, 2025
65b2671
Merge branch 'main' into fine_william___fine
altendky Oct 9, 2025
8805402
Merge remote-tracking branch 'origin/main' into fine_william___fine
emlowe Oct 14, 2025
ace36ba
Fix trailing comma in list
emlowe Oct 15, 2025
d91391b
Merge remote-tracking branch 'origin/main' into fine_william___fine
emlowe Oct 15, 2025
d8c9131
replace legacy kw_only_dataclass decorator
emlowe Oct 15, 2025
0c5d538
Adjust check for python version
emlowe Oct 15, 2025
e948c45
Remove debugging output
emlowe Oct 15, 2025
0c7bf69
Merge remote-tracking branch 'origin/main' into fine_william___fine
emlowe Oct 17, 2025
fcce75f
Use reruns for 3.13+Windows flakes only
emlowe Oct 21, 2025
a49bdf9
Merge remote-tracking branch 'origin/main' into fine_william___fine
emlowe Oct 22, 2025
c4348d9
Merge branch 'main' into fine_william___fine
Quexington Oct 23, 2025
7c60a5a
re-lock poetry
Quexington Oct 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check_wheel_availability.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
matrix: arm
- name: Intel
matrix: intel
python-version: ["3.10", "3.11", "3.12"]
python-version: ["3.10", "3.11", "3.12", "3.13"]
exclude:
- os:
matrix: windows
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ jobs:
- major_dot_minor: "3.10"
- major_dot_minor: "3.11"
- major_dot_minor: "3.12"
- major_dot_minor: "3.13"
exclude:
- os:
matrix: windows
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-install-scripts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ jobs:
# The behavior we follow in install.sh is unique with Arch in that
# we leave it to the user to install the appropriate version of python,
# so we need to install python here in order for the test to succeed.
pacman --noconfirm -U --needed https://archive.archlinux.org/packages/p/python/python-3.12.7-1-x86_64.pkg.tar.zst
pacman --noconfirm -U --needed https://archive.archlinux.org/packages/p/python/python-3.13.5-1-x86_64.pkg.tar.zst

- name: Prepare Debian
if: ${{ matrix.distribution.type == 'debian' }}
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/test-single.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ jobs:
apt: "3.12"
install_sh: "3.12"
matrix: "3.12"
- name: "3.13"
file_name: "3.13"
action: "3.13"
apt: "3.13"
install_sh: "3.13"
matrix: "3.13"
exclude_from:
limited: True
main: True
exclude:
- arch:
matrix: arm
Expand Down Expand Up @@ -244,7 +253,13 @@ jobs:
run: |
mv chia/ notchia/

- name: Test blockchain code with pytest with windows and 3.13 and reruns
if: matrix.os.name == 'windows' && matrix.python.name == '3.13'
run: |
pytest --reruns 1 --cov=chia --cov-config=.coveragerc --cov-report= -o 'junit_suite_name=${{ env.JOB_FILE_NAME }}' --junitxml='junit-data/junit.${{ env.JOB_FILE_NAME }}.xml' --durations=10 ${{ matrix.configuration.pytest_parallel_args[matrix.os.matrix] }} -m "not benchmark" ${{ env.ENABLE_PYTEST_MONITOR }} ${{ matrix.configuration.test_files }}

- name: Test blockchain code with pytest
if: ${{ !(matrix.os.name == 'windows' && matrix.python.name == '3.13') }}
env:
ENABLE_PYTEST_MONITOR: ${{ matrix.os.matrix == 'ubuntu' && matrix.configuration.enable_pytest_monitor || '' }}
run: |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/upload-pypi-source.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
- major_dot_minor: "3.10"
- major_dot_minor: "3.11"
- major_dot_minor: "3.12"
- major_dot_minor: "3.13"
check:
- name: mypy
command: |
Expand Down
2 changes: 1 addition & 1 deletion Install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ if ($null -eq (Get-Command py -ErrorAction SilentlyContinue))
Exit 1
}

$supportedPythonVersions = "3.12", "3.11", "3.10"
$supportedPythonVersions = "3.13", "3.12", "3.11", "3.10"
if ("$env:INSTALL_PYTHON_VERSION" -ne "")
{
$pythonVersion = $env:INSTALL_PYTHON_VERSION
Expand Down
4 changes: 4 additions & 0 deletions chia/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import importlib.metadata
import sys

__version__: str
try:
Expand All @@ -15,3 +16,6 @@
pass
else:
raise Exception("asserts are not working and _must_ be enabled, do not run with an optimized build of python")

if not getattr(sys, "_is_gil_enabled", lambda: True)():
raise Exception("freethreading is not supported, do not run with a freethreaded build of python")
14 changes: 11 additions & 3 deletions chia/_tests/core/server/test_event_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def test_base_event_loop_has_methods() -> None:
assert hasattr(base_selector_event_loop, "create_server")
method = getattr(base_selector_event_loop, "create_server")
assert inspect.ismethod(method)
if sys.version_info >= (3, 11):
if sys.version_info >= (3, 13):
expected_signature = "(protocol_factory, host=None, port=None, *, family=<AddressFamily.AF_UNSPEC: 0>, flags=<AddressInfo.AI_PASSIVE: 1>, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)" # noqa: E501
elif sys.version_info >= (3, 11):
expected_signature = "(protocol_factory, host=None, port=None, *, family=<AddressFamily.AF_UNSPEC: 0>, flags=<AddressInfo.AI_PASSIVE: 1>, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)" # noqa: E501
else:
expected_signature = "(protocol_factory, host=None, port=None, *, family=<AddressFamily.AF_UNSPEC: 0>, flags=<AddressInfo.AI_PASSIVE: 1>, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, ssl_handshake_timeout=None, start_serving=True)" # noqa: E501
Expand Down Expand Up @@ -103,7 +105,13 @@ async def main() -> None:

for func in ("_attach", "_detach"):
assert hasattr(base_server, func)
method = getattr(base_server, func)
assert str(inspect.signature(method)) == "()"
if sys.version_info >= (3, 13):
# https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Lib/asyncio/base_events.py#L296
method = getattr(base_server, func)
assert str(inspect.signature(method)) == "(transport)"
else:
method = getattr(base_server, func)
assert str(inspect.signature(method)) == "()"

finally:
selector_event_loop.close()
44 changes: 32 additions & 12 deletions chia/server/chia_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ssl
import struct
import sys
import weakref

if sys.platform == "win32":
import _overlapped # type: ignore[import-not-found]
Expand Down Expand Up @@ -57,15 +58,26 @@ class BaseEventsServer(asyncio.base_events.Server):
else:
_loop: EventsAbstractEventLoop
_sockets: Iterable[socket.socket]
_active_count: int
if sys.version_info >= (3, 13):
# https://github.com/python/cpython/blob/v3.13.7/Lib/asyncio/base_events.py#L283
_clients: weakref.WeakSet[object]
else:
_active_count: int
_protocol_factory: _ProtocolFactory
_backlog: int
_ssl_context: _SSLContext
_ssl_handshake_timeout: Optional[float]

def _attach(self) -> None: ...
if sys.version_info >= (3, 13):
# https://github.com/python/cpython/blob/bcee1c322115c581da27600f2ae55e5439c027eb/Lib/asyncio/base_events.py#L296
def _attach(self, transport: object) -> None: ...

def _detach(self, transport: object) -> None: ...
else:

def _attach(self) -> None: ...

def _detach(self) -> None: ...
def _detach(self) -> None: ...

def _start_serving(self) -> None: ...

Expand Down Expand Up @@ -132,20 +144,22 @@ def __init__(
max_concurrent_connections if max_concurrent_connections is not None else global_max_concurrent_connections
)

def _attach(self) -> None:
super()._attach()
logging.getLogger(__name__).debug(f"New connection. Total connections: {self._active_count}")
if not self._paused and self._active_count >= self.max_concurrent_connections:
def _attach(self, *args: object, **kwargs: object) -> None:
super()._attach(*args, **kwargs)
active_connections = self._chia_active_connections()
logging.getLogger(__name__).debug(f"New connection. Total connections: {active_connections}")
if not self._paused and active_connections >= self.max_concurrent_connections:
self._chia_pause()

def _detach(self) -> None:
super()._detach()
logging.getLogger(__name__).debug(f"Connection lost. Total connections: {self._active_count}")
def _detach(self, *args: object, **kwargs: object) -> None:
super()._detach(*args, **kwargs)
active_connections = self._chia_active_connections()
logging.getLogger(__name__).debug(f"Connection lost. Total connections: {active_connections}")
if (
self._active_count > 0
active_connections > 0
and self._sockets is not None
and self._paused
and self._active_count < self.max_concurrent_connections
and active_connections < self.max_concurrent_connections
):
self._chia_resume()

Expand Down Expand Up @@ -180,6 +194,12 @@ def _chia_resume(self) -> None:
)
logging.getLogger(__name__).debug("Resumed accepting connections.")

def _chia_active_connections(self) -> int:
if sys.version_info >= (3, 13):
return len(self._clients)
else:
return self._active_count


async def _chia_create_server(
cls: Any,
Expand Down
6 changes: 3 additions & 3 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ OPENSSL_VERSION_INT=
find_python() {
set +e
unset BEST_VERSION
for V in 312 3.12 311 3.11 310 3.10 3; do
for V in 313 3.13 312 3.12 311 3.11 310 3.10 3; do
if command -v python$V >/dev/null; then
if [ "$BEST_VERSION" = "" ]; then
BEST_VERSION=$V
Expand Down Expand Up @@ -134,8 +134,8 @@ if ! command -v "$INSTALL_PYTHON_PATH" >/dev/null; then
exit 1
fi

if [ "$PYTHON_MAJOR_VER" -ne "3" ] || [ "$PYTHON_MINOR_VER" -lt "7" ] || [ "$PYTHON_MINOR_VER" -ge "13" ]; then
echo "Chia requires Python version >= 3.10 and < 3.13.0" >&2
if [ "$PYTHON_MAJOR_VER" -ne "3" ] || [ "$PYTHON_MINOR_VER" -lt "10" ] || [ "$PYTHON_MINOR_VER" -ge "14" ]; then
echo "Chia requires Python version >= 3.10 and < 3.14.0" >&2
echo "Current Python version = $INSTALL_PYTHON_VERSION" >&2
# If Arch, direct to Arch Wiki
if type pacman >/dev/null 2>&1 && [ -f "/etc/arch-release" ]; then
Expand Down
35 changes: 26 additions & 9 deletions poetry.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand.
# This file is automatically @generated by Poetry 2.2.0 and should not be changed by hand.

[[package]]
name = "aiofiles"
Expand Down Expand Up @@ -225,7 +225,7 @@ description = "Python graph (network) package"
optional = true
python-versions = "*"
groups = ["main"]
markers = "extra == \"dev\" and python_version <= \"3.12\""
markers = "extra == \"dev\" and python_version < \"3.14\""
files = [
{file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"},
{file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"},
Expand Down Expand Up @@ -2059,7 +2059,7 @@ description = "Mach-O header analysis and editing"
optional = true
python-versions = "*"
groups = ["main"]
markers = "extra == \"dev\" and python_version <= \"3.12\" and sys_platform == \"darwin\""
markers = "extra == \"dev\" and python_version < \"3.14\" and sys_platform == \"darwin\""
files = [
{file = "macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c"},
{file = "macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30"},
Expand Down Expand Up @@ -2511,7 +2511,7 @@ description = "Python PE parsing module"
optional = true
python-versions = ">=3.6.0"
groups = ["main"]
markers = "extra == \"dev\" and python_version <= \"3.12\" and sys_platform == \"win32\""
markers = "extra == \"dev\" and python_version < \"3.14\" and sys_platform == \"win32\""
files = [
{file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"},
{file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"},
Expand Down Expand Up @@ -2848,7 +2848,7 @@ description = "PyInstaller bundles a Python application and all its dependencies
optional = true
python-versions = "<3.15,>=3.8"
groups = ["main"]
markers = "extra == \"dev\" and python_version <= \"3.12\""
markers = "extra == \"dev\" and python_version < \"3.14\""
files = [
{file = "pyinstaller-6.15.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:9f00c71c40148cd1e61695b2c6f1e086693d3bcf9bfa22ab513aa4254c3b966f"},
{file = "pyinstaller-6.15.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:cbcc8eb77320c60722030ac875883b564e00768fe3ff1721c7ba3ad0e0a277e9"},
Expand Down Expand Up @@ -2884,7 +2884,7 @@ description = "Community maintained hooks for PyInstaller"
optional = true
python-versions = ">=3.8"
groups = ["main"]
markers = "extra == \"dev\" and python_version <= \"3.12\""
markers = "extra == \"dev\" and python_version < \"3.14\""
files = [
{file = "pyinstaller_hooks_contrib-2025.8-py3-none-any.whl", hash = "sha256:8d0b8cfa0cb689a619294ae200497374234bd4e3994b3ace2a4442274c899064"},
{file = "pyinstaller_hooks_contrib-2025.8.tar.gz", hash = "sha256:3402ad41dfe9b5110af134422e37fc5d421ba342c6cb980bd67cb30b7415641c"},
Expand Down Expand Up @@ -3010,6 +3010,23 @@ pytest = "*"
requests = "*"
wheel = "*"

[[package]]
name = "pytest-rerunfailures"
version = "16.1"
description = "pytest plugin to re-run tests to eliminate flaky failures"
optional = true
python-versions = ">=3.10"
groups = ["main"]
markers = "extra == \"dev\""
files = [
{file = "pytest_rerunfailures-16.1-py3-none-any.whl", hash = "sha256:5d11b12c0ca9a1665b5054052fcc1084f8deadd9328962745ef6b04e26382e86"},
{file = "pytest_rerunfailures-16.1.tar.gz", hash = "sha256:c38b266db8a808953ebd71ac25c381cb1981a78ff9340a14bcb9f1b9bff1899e"},
]

[package.dependencies]
packaging = ">=17.1"
pytest = ">=7.4,<8.2.2 || >8.2.2"

[[package]]
name = "pytest-xdist"
version = "3.8.0"
Expand Down Expand Up @@ -3934,7 +3951,7 @@ description = "ZSTD Bindings for Python"
optional = false
python-versions = "*"
groups = ["main"]
markers = "python_version == \"3.12\""
markers = "python_version >= \"3.12\""
files = [
{file = "zstd-1.5.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b5cd20afab8d13c52d2b2219bf18cc765eae87b8219343bce20647007890adab"},
{file = "zstd-1.5.5.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:0f467ab9b57ab8b4b874e6974d38b802f20406803bb7ec9308df923553cd48f7"},
Expand Down Expand Up @@ -3969,11 +3986,11 @@ url = "https://pypi.chia.net/simple"
reference = "chia"

[extras]
dev = ["aiohttp_cors", "build", "coverage", "diff-cover", "lxml", "mypy", "pre-commit", "py3createtorrent", "pyinstaller", "pytest", "pytest-cov", "pytest-mock", "pytest-monitor", "pytest-xdist", "ruff", "tach", "types-aiofiles", "types-cryptography", "types-pyyaml", "types-setuptools"]
dev = ["aiohttp_cors", "build", "coverage", "diff-cover", "lxml", "mypy", "pre-commit", "py3createtorrent", "pyinstaller", "pytest", "pytest-cov", "pytest-mock", "pytest-monitor", "pytest-rerunfailures", "pytest-xdist", "ruff", "tach", "types-aiofiles", "types-cryptography", "types-pyyaml", "types-setuptools"]
legacy-keyring = ["keyrings.cryptfile"]
upnp = ["miniupnpc"]

[metadata]
lock-version = "2.1"
python-versions = ">=3.10, <4"
content-hash = "593d5a538eed9036f2a2a58bfbf9069cb973bb34a54eb13ef1382cf4c92a0a1b"
content-hash = "8174ff43e3ed9ac6cc494a6fcbabb8e9c6b0efd47cefb9f1270f074649033919"
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ typing-extensions = ">=4.12.2" # typing backports like Protocol and TypedDict
watchdog = ">=4.0.1" # Filesystem event watching - watches keyring.yaml
zstd = [
{version=">=1.5.5.1", python = "<3.12"},
{version=">=1.5.5.1", python = "3.12", source="chia"},
{version=">=1.5.5.1", python = ">=3.12", source="chia"},
]
importlib-resources = ">=6.4.5"
hsms = ">=0.3.1"
Expand All @@ -91,12 +91,13 @@ diff-cover = { version = ">=9.2.0", optional = true }
mypy = { version = ">=1.11.1", optional = true }
pre-commit = { version = ">=3.7.1", optional = true }
py3createtorrent = { version = ">=1.2.1", optional = true }
pyinstaller = { version = ">=6.9.0", python = "<3.13", optional = true }
pyinstaller = { version = ">=6.9.0", python = "<3.14", optional = true }
pytest = { version = ">=8.3.3", optional = true }
pytest-cov = { version = ">=5.0.0", optional = true }
pytest-mock = { version = ">=3.14.0", optional = true }
pytest-monitor = { version = ">=1.6.6", platform = "linux", optional = true }
pytest-xdist = { version = ">=3.6.1", optional = true }
pytest-rerunfailures = { version = ">=16.1, <17.0", optional = true }
tach = { version = ">=0.29.0", optional = true }
types-aiofiles = { version = ">=24.1.0.20240626", optional = true }
types-cryptography = { version = ">=3.3.23.2", optional = true }
Expand All @@ -111,7 +112,7 @@ miniupnpc = {version = ">=2.3.2, <3", source = "chia", optional = true}
ruff = { version = ">=0.8.1", optional = true }

[project.optional-dependencies]
dev = ["aiohttp_cors", "build", "coverage", "diff-cover", "mypy", "pre-commit", "py3createtorrent", "pyinstaller", "pytest", "pytest-cov", "pytest-mock", "pytest-monitor", "pytest-xdist", "ruff", "tach", "types-aiofiles", "types-cryptography", "types-pyyaml", "types-setuptools", "lxml"]
dev = ["aiohttp_cors", "build", "coverage", "diff-cover", "mypy", "pre-commit", "py3createtorrent", "pyinstaller", "pytest", "pytest-cov", "pytest-mock", "pytest-monitor", "pytest-xdist", "pytest-rerunfailures", "ruff", "tach", "types-aiofiles", "types-cryptography", "types-pyyaml", "types-setuptools", "lxml"]
upnp = ["miniupnpc"]
legacy_keyring = ["keyrings.cryptfile"]

Expand Down
Loading