Skip to content

Commit df983f9

Browse files
authored
Support free-threaded Python 3.13 (#925)
* Support free-threaded Python 3.13 * fix issues with tox.ini * add multithreading test * fix pep8 * fix ruff format * name linux CI run based on python VERSION * clarify use of pytest-run-parallel marks * refactor test_multithreading * simplify test_multithreading * remove pytest-run-parallel use
1 parent 1de1cad commit df983f9

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
PYTHON:
1717
- {VERSION: "3.8", TOXENV: "py38"}
1818
- {VERSION: "3.13", TOXENV: "py313"}
19+
- {VERSION: "3.13t", TOXENV: "py313"}
1920
MACOS:
2021
- macos-13
2122
- macos-latest
@@ -24,7 +25,7 @@ jobs:
2425
- uses: actions/[email protected]
2526
- name: Setup python
2627
id: setup-python
27-
uses: actions/[email protected].0
28+
uses: quansight-labs/[email protected].1
2829
with:
2930
python-version: ${{ matrix.PYTHON.VERSION }}
3031
- uses: actions/[email protected]
@@ -53,12 +54,13 @@ jobs:
5354
PYTHON:
5455
- {VERSION: "3.8", TOXENV: "py38"}
5556
- {VERSION: "3.13", TOXENV: "py313"}
57+
- {VERSION: "3.13t", TOXENV: "py313"}
5658
name: "Python ${{ matrix.PYTHON.VERSION }} on ${{ matrix.WINDOWS.WINDOWS }}"
5759
steps:
5860
- uses: actions/[email protected]
5961
- name: Setup python
6062
id: setup-python
61-
uses: actions/[email protected].0
63+
uses: quansight-labs/[email protected].1
6264
with:
6365
python-version: ${{ matrix.PYTHON.VERSION }}
6466
architecture: ${{ matrix.WINDOWS.ARCH }}
@@ -92,19 +94,20 @@ jobs:
9294
- {VERSION: "3.11", TOXENV: "py311"}
9395
- {VERSION: "3.12", TOXENV: "py312"}
9496
- {VERSION: "3.13", TOXENV: "py313"}
97+
- {VERSION: "3.13t", TOXENV: "py313"}
9598
- {VERSION: "pypy-3.9", TOXENV: "pypy3"}
9699
- {VERSION: "pypy-3.10", TOXENV: "pypy3"}
97100

98101
# MSRV
99102
- {VERSION: "3.13", TOXENV: "py313", RUST_VERSION: "1.64.0"}
100103
- {VERSION: "3.13", TOXENV: "py313", RUST_VERSION: "beta"}
101104
- {VERSION: "3.13", TOXENV: "py313", RUST_VERSION: "nightly"}
102-
name: "${{ matrix.PYTHON.TOXENV }} on linux, Rust ${{ matrix.PYTHON.RUST_VERSION || 'stable' }}"
105+
name: "${{ matrix.PYTHON.VERSION }} on linux, Rust ${{ matrix.PYTHON.RUST_VERSION || 'stable' }}"
103106
steps:
104107
- uses: actions/[email protected]
105108
- name: Setup python
106109
id: setup-python
107-
uses: actions/[email protected].0
110+
uses: quansight-labs/[email protected].1
108111
with:
109112
python-version: ${{ matrix.PYTHON.VERSION }}
110113
- uses: actions/[email protected]

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ Compatibility
285285
-------------
286286

287287
This library should be compatible with py-bcrypt and it will run on Python
288-
3.6+, and PyPy 3.
288+
3.8+ (including free-threaded builds), and PyPy 3.
289289

290290
Security
291291
--------

src/_bcrypt/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ fn kdf<'p>(
182182
})
183183
}
184184

185-
#[pyo3::pymodule]
185+
#[pyo3::pymodule(gil_used = false)]
186186
mod _bcrypt {
187187
use pyo3::types::PyModuleMethods;
188188

tests/test_bcrypt.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import uuid
2+
from concurrent.futures import ThreadPoolExecutor
3+
14
import pytest
25

36
import bcrypt
@@ -171,7 +174,7 @@
171174
]
172175

173176

174-
def test_gensalt_basic(monkeypatch):
177+
def test_gensalt_basic():
175178
salt = bcrypt.gensalt()
176179
assert salt.startswith(b"$2b$12$")
177180

@@ -219,7 +222,7 @@ def test_gensalt_bad_prefix():
219222
bcrypt.gensalt(prefix=b"bad")
220223

221224

222-
def test_gensalt_2a_prefix(monkeypatch):
225+
def test_gensalt_2a_prefix():
223226
salt = bcrypt.gensalt(prefix=b"2a")
224227
assert salt.startswith(b"$2a$12$")
225228

@@ -494,3 +497,24 @@ def test_2a_wraparound_bug():
494497
)
495498
== b"$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi"
496499
)
500+
501+
502+
def test_multithreading():
503+
def create_user(pw):
504+
salt = bcrypt.gensalt(4)
505+
hash_ = bcrypt.hashpw(pw, salt)
506+
key = bcrypt.kdf(pw, salt, 32, 50)
507+
assert bcrypt.checkpw(pw, hash_)
508+
return (salt, hash_, key)
509+
510+
user_creator = ThreadPoolExecutor(max_workers=4)
511+
pws = [uuid.uuid4().bytes for _ in range(50)]
512+
513+
futures = [user_creator.submit(create_user, pw) for pw in pws]
514+
515+
users = [future.result() for future in futures]
516+
517+
for pw, (salt, hash_, key) in zip(pws, users):
518+
assert bcrypt.hashpw(pw, salt) == hash_
519+
assert bcrypt.checkpw(pw, hash_)
520+
assert bcrypt.kdf(pw, salt, 32, 50) == key

0 commit comments

Comments
 (0)