Skip to content

Commit d2f8e17

Browse files
committed
Initial Implementation
1 parent 36f294d commit d2f8e17

File tree

12 files changed

+886
-0
lines changed

12 files changed

+886
-0
lines changed

.editorconfig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
trim_trailing_whitespace = true
7+
8+
[*.yml]
9+
indent_size = 2
10+
11+
[*.rst]
12+
indent_size = 2
13+
ij_visual_guides = 78
14+
15+
[*.{py,pyi}]
16+
ij_visual_guides = 80,88
17+
18+
[*.c]
19+
indent_style = tab

.github/dependabot.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: "/"
5+
open-pull-requests-limit: 2
6+
schedule:
7+
interval: monthly

.github/workflows/publish.yml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Based on https://github.com/pypa/cibuildwheel/blob/main/examples/github-deploy.yml
2+
name: Build and upload to PyPI
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches:
8+
- master
9+
release:
10+
types:
11+
- published
12+
13+
jobs:
14+
build-sdist:
15+
name: Build source tarball
16+
runs-on: ubuntu-24.04
17+
steps:
18+
- uses: actions/checkout@v3
19+
- uses: actions/setup-python@v4
20+
- run: |
21+
python -m pip install --upgrade build
22+
python -m build --sdist
23+
- uses: actions/upload-artifact@v4
24+
with:
25+
if-no-files-found: error
26+
compression-level: 0
27+
name: cibw-sdist
28+
path: ./dist/*
29+
30+
build-wheels:
31+
name: Build Wheels
32+
runs-on: ${{ matrix.os }}
33+
strategy:
34+
matrix:
35+
os: [ubuntu-24.04, ubuntu-24.04-arm, macos-14]
36+
env:
37+
CIBW_SKIP: pp*
38+
CIBW_ENVIRONMENT: >-
39+
CIBW_ENABLE="cpython-freethreading"
40+
PIP_CONFIG_SETTINGS="build_ext=-j4"
41+
CFLAGS="-g0"
42+
steps:
43+
- uses: actions/checkout@v4
44+
- name: Build sdist
45+
run: pipx run build --sdist
46+
- name: Build wheels
47+
uses: pypa/cibuildwheel@v2.23.3
48+
- uses: actions/upload-artifact@v4
49+
with:
50+
if-no-files-found: error
51+
compression-level: 0
52+
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
53+
path: ./wheelhouse/*.whl
54+
55+
test-pypi-publish:
56+
name: Upload release to TestPyPI
57+
needs: [build-sdist, build-wheels]
58+
runs-on: ubuntu-latest
59+
environment: test-pypi
60+
permissions:
61+
id-token: write
62+
if: github.event_name == 'release' && github.event.action == 'published'
63+
steps:
64+
- uses: actions/download-artifact@v4
65+
with:
66+
pattern: cibw-*
67+
path: dist
68+
merge-multiple: true
69+
- name: Publish package distributions to PyPI
70+
uses: pypa/gh-action-pypi-publish@release/v1
71+
with:
72+
repository-url: https://test.pypi.org/legacy/
73+
74+
pypi-publish:
75+
name: Upload release to PyPI
76+
needs: [test-pypi-publish]
77+
runs-on: ubuntu-latest
78+
environment: pypi
79+
permissions:
80+
id-token: write
81+
if: github.event_name == 'release' && github.event.action == 'published'
82+
steps:
83+
- uses: actions/download-artifact@v4
84+
with:
85+
pattern: cibw-*
86+
path: dist
87+
merge-multiple: true
88+
- name: Publish package distributions to PyPI
89+
uses: pypa/gh-action-pypi-publish@release/v1

.gitignore

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
2+
# Created by https://www.gitignore.io/api/python
3+
# Edit at https://www.gitignore.io/?templates=python
4+
5+
### Python ###
6+
# Byte-compiled / optimized / DLL files
7+
__pycache__/
8+
*.py[cod]
9+
*$py.class
10+
11+
# C extensions
12+
*.so
13+
14+
# Distribution / packaging
15+
.Python
16+
build/
17+
develop-eggs/
18+
dist/
19+
downloads/
20+
eggs/
21+
.eggs/
22+
lib/
23+
lib64/
24+
parts/
25+
sdist/
26+
var/
27+
wheels/
28+
wheelhouse/
29+
pip-wheel-metadata/
30+
share/python-wheels/
31+
*.egg-info/
32+
.installed.cfg
33+
*.egg
34+
MANIFEST
35+
36+
# PyInstaller
37+
# Usually these files are written by a python script from a template
38+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
39+
*.manifest
40+
*.spec
41+
42+
# Installer logs
43+
pip-log.txt
44+
pip-delete-this-directory.txt
45+
46+
# Unit test / coverage reports
47+
htmlcov/
48+
.tox/
49+
.nox/
50+
.coverage
51+
.coverage.*
52+
.cache
53+
nosetests.xml
54+
coverage.xml
55+
*.cover
56+
.hypothesis/
57+
.pytest_cache/
58+
59+
# Translations
60+
*.mo
61+
*.pot
62+
63+
# Django stuff:
64+
*.log
65+
local_settings.py
66+
db.sqlite3
67+
db.sqlite3-journal
68+
69+
# Flask stuff:
70+
instance/
71+
.webassets-cache
72+
73+
# Scrapy stuff:
74+
.scrapy
75+
76+
# Sphinx documentation
77+
docs/_build/
78+
79+
# PyBuilder
80+
target/
81+
82+
# Jupyter Notebook
83+
.ipynb_checkpoints
84+
85+
# IPython
86+
profile_default/
87+
ipython_config.py
88+
89+
# pyenv
90+
.python-version
91+
92+
# pipenv
93+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
95+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
96+
# install all needed dependencies.
97+
#Pipfile.lock
98+
99+
# celery beat schedule file
100+
celerybeat-schedule
101+
102+
# SageMath parsed files
103+
*.sage.py
104+
105+
# Environments
106+
.env
107+
.venv
108+
env/
109+
venv/
110+
ENV/
111+
env.bak/
112+
venv.bak/
113+
114+
# Spyder project settings
115+
.spyderproject
116+
.spyproject
117+
118+
# Rope project settings
119+
.ropeproject
120+
121+
# mkdocs documentation
122+
/site
123+
124+
# mypy
125+
.mypy_cache/
126+
.dmypy.json
127+
dmypy.json
128+
129+
# Pyre type checker
130+
.pyre/
131+
132+
# End of https://www.gitignore.io/api/python
133+
134+
.idea/
135+

LICENSE

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
BSD 2-Clause License
2+
3+
Copyright (c) 2025, Anatolii Aniskovych
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.rst

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
========================
2+
Python SonyFlake (Turbo)
3+
========================
4+
5+
A `SonyFlake <https://github.com/sony/sonyflake>`_ ID generator tailored for
6+
high-volume ID generation.
7+
8+
Installation
9+
============
10+
11+
.. code-block:: sh
12+
13+
pip install sonyflake-turbo
14+
15+
Usage
16+
=====
17+
18+
Easy mode:
19+
20+
.. code-block:: python
21+
22+
from sonyflake_turbo import SonyFlake
23+
24+
sf = SonyFlake(0x1337, 0xCAFE)
25+
26+
for _, id_ in zip(range(10), sf):
27+
print(f"{id_:016x}")
28+
29+
Turbo mode:
30+
31+
.. code-block:: python
32+
33+
from datetime import datetime, timezone
34+
from random import sample
35+
from timeit import timeit
36+
37+
from sonyflake_turbo import SONYFLAKE_MACHINE_ID_MAX, SonyFlake
38+
39+
epoch = datetime(2025, 6, 5, tzinfo=timezone.utc)
40+
41+
for count in [32, 16, 8, 4, 2, 1]:
42+
machine_ids = sample(range(SONYFLAKE_MACHINE_ID_MAX + 1), count)
43+
sf = SonyFlake(*machine_ids, start_time=int(epoch.timestamp()))
44+
t = timeit(lambda: [next(sf) for _ in range(1000)], number=1000)
45+
print(f"Speed: 1M ids / {t:.2f}sec with {count} machine IDs")
46+
47+
Important Notes
48+
===============
49+
50+
SonyFlake algorithm produces IDs at rate 256 IDs per 10msec per 1 Machine ID.
51+
One obvious way to increase the throughput is to use multiple generators with
52+
different Machine IDs. This library provides a way to do exactly that by
53+
passing multiple Machine IDs to the constructor of the `SonyFlake` class.
54+
Generated IDs are non-repeating and are always increasing. But be careful! You
55+
should be conscious about assigning Machine IDs to different processes and/or
56+
machines to avoid collisions. This library does not come with any Machine ID
57+
management features, so it's up to you to figure this out.
58+
59+
This library has limited free-threaded mode support. It won't crash, but
60+
you won't get much performance gain from multithreaded usage. Consider
61+
creating generators per thread instead of sharing them across multiple
62+
threads.
63+
64+
Development
65+
===========
66+
67+
Install:
68+
69+
.. code-block:: sh
70+
71+
python3 -m venv env
72+
. env/bin/activate
73+
pip install -e .[test]
74+
75+
Run tests:
76+
77+
.. code-block:: sh
78+
79+
py.test
80+
81+
Building wheels:
82+
83+
.. code-block:: sh
84+
85+
pip install cibuildwheel
86+
cibuildwheel

py.typed

Whitespace-only changes.

0 commit comments

Comments
 (0)