uuid-utils 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of uuid-utils might be problematic. Click here for more details.

@@ -0,0 +1,276 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ tags:
8
+ - "*"
9
+ pull_request:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ env:
15
+ RUSTFLAGS: "--cfg uuid_unstable"
16
+
17
+ jobs:
18
+ lint:
19
+ name: Check code quality
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v3
23
+ - uses: actions/setup-python@v4
24
+ with:
25
+ python-version: "3.10"
26
+ - name: Install dependencies
27
+ run: pip install -r requirements.txt
28
+ - name: Check code
29
+ run: |
30
+ black --check .
31
+ isort --check --project=uuid_utils .
32
+ mypy .
33
+ ruff .
34
+
35
+ linux:
36
+ name: "Linux: ${{ matrix.target }}"
37
+ runs-on: ubuntu-latest
38
+ strategy:
39
+ matrix:
40
+ target: [x86_64, i686]
41
+ steps:
42
+ - uses: actions/checkout@v3
43
+ - uses: actions/setup-python@v4
44
+ with:
45
+ python-version: "3.11"
46
+ - name: Build wheels
47
+ uses: PyO3/maturin-action@v1
48
+ with:
49
+ target: ${{ matrix.target }}
50
+ args: --release --out dist -i 3.7 3.8 3.9 3.10 3.11 pypy3.8 pypy3.9
51
+ sccache: "true"
52
+ manylinux: auto
53
+ - name: Install and test
54
+ if: matrix.target == 'x86_64'
55
+ run: |
56
+ pip install uuid_utils --no-index --find-links dist --force-reinstall
57
+ pip install pytest
58
+ pytest -v .
59
+ - name: Upload wheels
60
+ uses: actions/upload-artifact@v3
61
+ with:
62
+ name: wheels
63
+ path: dist
64
+
65
+ linux-cross:
66
+ name: "Linux: ${{ matrix.target }}"
67
+ runs-on: ubuntu-latest
68
+ strategy:
69
+ matrix:
70
+ target: [aarch64, armv7, s390x, ppc64le]
71
+ steps:
72
+ - uses: actions/checkout@v3
73
+ - uses: actions/setup-python@v4
74
+ with:
75
+ python-version: '3.11'
76
+ - name: Build wheels
77
+ uses: PyO3/maturin-action@v1
78
+ with:
79
+ rust-toolchain: stable
80
+ target: ${{ matrix.target }}
81
+ manylinux: auto
82
+ args: --release --out dist -i 3.7 3.8 3.9 3.10 3.11 pypy3.8 pypy3.9
83
+ - uses: uraimo/run-on-arch-action@v2.3.0
84
+ if: matrix.target != 'ppc64'
85
+ name: Install built wheel
86
+ with:
87
+ arch: ${{ matrix.target }}
88
+ distro: ubuntu20.04
89
+ githubToken: ${{ github.token }}
90
+ install: |
91
+ apt-get update
92
+ apt-get install -y --no-install-recommends python3 python3-pip
93
+ pip3 install -U pip pytest
94
+ run: |
95
+ pip3 install uuid_utils --no-index --find-links dist/ --force-reinstall
96
+ pytest -v .
97
+ - name: Upload wheels
98
+ uses: actions/upload-artifact@v3
99
+ with:
100
+ name: wheels
101
+ path: dist
102
+
103
+ musllinux:
104
+ name: "Linux: ${{ matrix.target }}"
105
+ runs-on: ubuntu-latest
106
+ strategy:
107
+ matrix:
108
+ target:
109
+ - x86_64-unknown-linux-musl
110
+ - i686-unknown-linux-musl
111
+ steps:
112
+ - uses: actions/checkout@v3
113
+ - uses: actions/setup-python@v4
114
+ with:
115
+ python-version: '3.11'
116
+ architecture: x64
117
+ - name: Build wheels
118
+ uses: PyO3/maturin-action@v1
119
+ with:
120
+ rust-toolchain: stable
121
+ target: ${{ matrix.target }}
122
+ manylinux: musllinux_1_2
123
+ args: --release --out dist -i 3.7 3.8 3.9 3.10 3.11
124
+ - name: Install built wheel
125
+ if: matrix.target == 'x86_64-unknown-linux-musl'
126
+ uses: addnab/docker-run-action@v3
127
+ with:
128
+ image: alpine:latest
129
+ options: -v ${{ github.workspace }}:/io -w /io
130
+ run: |
131
+ apk add py3-pip
132
+ pip3 install -U pip pytest
133
+ pip3 install uuid_utils --no-index --find-links /io/dist/ --force-reinstall
134
+ python3 -m pytest -v
135
+ - name: Upload wheels
136
+ uses: actions/upload-artifact@v3
137
+ with:
138
+ name: wheels
139
+ path: dist
140
+
141
+ musllinux-cross:
142
+ name: "Linux: ${{ matrix.platform.target }}"
143
+ runs-on: ubuntu-latest
144
+ strategy:
145
+ matrix:
146
+ platform:
147
+ - target: aarch64-unknown-linux-musl
148
+ arch: aarch64
149
+ - target: armv7-unknown-linux-musleabihf
150
+ arch: armv7
151
+ steps:
152
+ - uses: actions/checkout@v3
153
+ - uses: actions/setup-python@v4
154
+ with:
155
+ python-version: '3.11'
156
+ - name: Build wheels
157
+ uses: PyO3/maturin-action@v1
158
+ with:
159
+ rust-toolchain: stable
160
+ target: ${{ matrix.platform.target }}
161
+ manylinux: musllinux_1_2
162
+ args: --release --out dist -i 3.7 3.8 3.9 3.10 3.11
163
+ - uses: uraimo/run-on-arch-action@v2.3.0
164
+ name: Install built wheel
165
+ with:
166
+ arch: ${{ matrix.platform.arch }}
167
+ distro: alpine_latest
168
+ githubToken: ${{ github.token }}
169
+ install: |
170
+ apk add py3-pip
171
+ pip3 install -U pip pytest
172
+ run: |
173
+ pip3 install uuid_utils --no-index --find-links dist/ --force-reinstall
174
+ python3 -m pytest -v .
175
+ - name: Upload wheels
176
+ uses: actions/upload-artifact@v3
177
+ with:
178
+ name: wheels
179
+ path: dist
180
+
181
+ windows:
182
+ name: "Windows: ${{ matrix.platform.target }}"
183
+ runs-on: windows-latest
184
+ strategy:
185
+ matrix:
186
+ platform:
187
+ - target: x64
188
+ interpreter: 3.7 3.8 3.9 3.10 3.11
189
+ - target: x86
190
+ interpreter: 3.7 3.8 3.9 3.10 3.11
191
+ steps:
192
+ - uses: actions/checkout@v3
193
+ - uses: actions/setup-python@v4
194
+ with:
195
+ python-version: "3.11"
196
+ architecture: ${{ matrix.platform.target }}
197
+ - uses: dtolnay/rust-toolchain@stable
198
+ - name: Build wheels
199
+ uses: PyO3/maturin-action@v1
200
+ with:
201
+ target: ${{ matrix.platform.target }}
202
+ args: --release --out dist -i ${{ matrix.platform.interpreter }}
203
+ sccache: "true"
204
+ - name: Install and test uuid_utils
205
+ run: |
206
+ pip install uuid_utils --no-index --find-links dist --force-reinstall
207
+ pip install pytest
208
+ pytest -v .
209
+ - name: Upload wheels
210
+ uses: actions/upload-artifact@v3
211
+ with:
212
+ name: wheels
213
+ path: dist
214
+
215
+ macos:
216
+ name: "MacOS"
217
+ runs-on: macos-latest
218
+ steps:
219
+ - uses: actions/checkout@v3
220
+ - uses: actions/setup-python@v4
221
+ with:
222
+ python-version: "3.11"
223
+ - uses: dtolnay/rust-toolchain@stable
224
+ - name: Build wheels - x86_64
225
+ uses: PyO3/maturin-action@v1
226
+ with:
227
+ target: x86_64
228
+ args: --release --out dist -i 3.7 3.8 3.9 3.10 3.11 pypy3.8 pypy3.9
229
+ sccache: "true"
230
+ - name: Build wheels - universal2
231
+ uses: PyO3/maturin-action@v1
232
+ with:
233
+ args: --release --out dist --universal2 -i 3.8 3.9 3.10 3.11 pypy3.8 pypy3.9
234
+ - name: Install and test uuid_utils
235
+ run: |
236
+ pip install uuid_utils --no-index --find-links dist --force-reinstall
237
+ pip install pytest
238
+ pytest -v .
239
+ - name: Upload wheels
240
+ uses: actions/upload-artifact@v3
241
+ with:
242
+ name: wheels
243
+ path: dist
244
+
245
+ sdist:
246
+ name: Source Distribution
247
+ runs-on: ubuntu-latest
248
+ steps:
249
+ - uses: actions/checkout@v3
250
+ - name: Build sdist
251
+ uses: PyO3/maturin-action@v1
252
+ with:
253
+ command: sdist
254
+ args: --out dist
255
+ - name: Upload sdist
256
+ uses: actions/upload-artifact@v3
257
+ with:
258
+ name: wheels
259
+ path: dist
260
+
261
+ release:
262
+ name: Release
263
+ runs-on: ubuntu-latest
264
+ if: "startsWith(github.ref, 'refs/tags/')"
265
+ needs: [lint, linux, windows, macos, sdist]
266
+ steps:
267
+ - uses: actions/download-artifact@v3
268
+ with:
269
+ name: wheels
270
+ - name: Publish to PyPI
271
+ uses: PyO3/maturin-action@v1
272
+ env:
273
+ MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
274
+ with:
275
+ command: upload
276
+ args: --skip-existing *
@@ -339,7 +339,7 @@ dependencies = [
339
339
 
340
340
  [[package]]
341
341
  name = "uuid-utils"
342
- version = "0.1.0"
342
+ version = "0.2.0"
343
343
  dependencies = [
344
344
  "pyo3",
345
345
  "uuid",
@@ -1,10 +1,10 @@
1
1
  [package]
2
2
  name = "uuid-utils"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  edition = "2021"
5
5
 
6
6
  [lib]
7
- name = "uuid_utils"
7
+ name = "_uuid_utils"
8
8
  crate-type = ["cdylib"]
9
9
 
10
10
  [dependencies]
@@ -0,0 +1,27 @@
1
+ Copyright © 2023, Amin Alaee.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of the copyright holder nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uuid_utils
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Programming Language :: Python
6
6
  Classifier: Programming Language :: Python :: 3
@@ -11,17 +11,32 @@ Classifier: Programming Language :: Python :: 3.9
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Rust
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Operating System :: OS Independent
17
+ License-File: LICENSE.md
14
18
  Summary: Drop-in replacement for Python UUID in Rust
15
19
  Keywords: rust,uuid
16
20
  Author-email: Amin Alaee <me@aminalaee.dev>
17
21
  Requires-Python: >=3.7
18
22
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
19
- Project-URL: Issues, https://github.com/aminalaee/uuid-utils/issues
20
23
  Project-URL: Documentation, https://github.com/aminalaee/uuid-utils
24
+ Project-URL: Issues, https://github.com/aminalaee/uuid-utils/issues
21
25
  Project-URL: Source, https://github.com/aminalaee/uuid-utils
22
26
 
23
27
  # Python UUID Utils
24
28
 
29
+ <p align="center">
30
+ <a href="https://pypi.org/project/uuid-utils/">
31
+ <img src="https://badge.fury.io/py/uuid-utils.svg" alt="Package version">
32
+ </a>
33
+ <a href="https://pypi.org/project/uuid-utils" target="_blank">
34
+ <img src="https://img.shields.io/pypi/pyversions/uuid-utils.svg?color=%2334D058" alt="Supported Python versions">
35
+ </a>
36
+ </p>
37
+
38
+ ---
39
+
25
40
  Python UUID implementation using Rust's UUID library.
26
41
  This will make `uuid4` function around 10x faster.
27
42
 
@@ -39,7 +54,13 @@ Avaialble UUID versions:
39
54
  - `uuid7` - Version 7 UUIDs using a Unix timestamp ordered by time.
40
55
  - `uuid8` - Version 8 UUIDs using user-defined data.
41
56
 
42
- **Please note that UUID versions 6, 7 and 8 are still in draft RFC.**
57
+ <sup>Please note that UUID versions 6, 7 and 8 are still in draft RFC.</sup><br>
58
+
59
+ ## Installation
60
+
61
+ ```shell
62
+ $ pip install uuid-utils
63
+ ```
43
64
 
44
65
  ## Example
45
66
 
@@ -77,5 +98,6 @@ UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
77
98
  ## Limitations
78
99
 
79
100
  - The `getnode` function is not available.
80
- - The `uuid1` and `uuid6` take `node` argument as mandatory.
101
+ - The `uuid1` and `uuid6` take `node` argument as mandatory.
102
+ - The `uuid3` function is not available.
81
103
 
@@ -1,5 +1,16 @@
1
1
  # Python UUID Utils
2
2
 
3
+ <p align="center">
4
+ <a href="https://pypi.org/project/uuid-utils/">
5
+ <img src="https://badge.fury.io/py/uuid-utils.svg" alt="Package version">
6
+ </a>
7
+ <a href="https://pypi.org/project/uuid-utils" target="_blank">
8
+ <img src="https://img.shields.io/pypi/pyversions/uuid-utils.svg?color=%2334D058" alt="Supported Python versions">
9
+ </a>
10
+ </p>
11
+
12
+ ---
13
+
3
14
  Python UUID implementation using Rust's UUID library.
4
15
  This will make `uuid4` function around 10x faster.
5
16
 
@@ -17,7 +28,13 @@ Avaialble UUID versions:
17
28
  - `uuid7` - Version 7 UUIDs using a Unix timestamp ordered by time.
18
29
  - `uuid8` - Version 8 UUIDs using user-defined data.
19
30
 
20
- **Please note that UUID versions 6, 7 and 8 are still in draft RFC.**
31
+ <sup>Please note that UUID versions 6, 7 and 8 are still in draft RFC.</sup><br>
32
+
33
+ ## Installation
34
+
35
+ ```shell
36
+ $ pip install uuid-utils
37
+ ```
21
38
 
22
39
  ## Example
23
40
 
@@ -55,4 +72,5 @@ UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
55
72
  ## Limitations
56
73
 
57
74
  - The `getnode` function is not available.
58
- - The `uuid1` and `uuid6` take `node` argument as mandatory.
75
+ - The `uuid1` and `uuid6` take `node` argument as mandatory.
76
+ - The `uuid3` function is not available.
@@ -0,0 +1,13 @@
1
+ ## Benchmarks
2
+
3
+ In order to run the benchmarks, install the `richbench` package first:
4
+
5
+ ```shell
6
+ $ pip install richbench
7
+ ```
8
+
9
+ Then you can run the benchmarks with:
10
+
11
+ ```shell
12
+ $ richbench benchmarks/
13
+ ```
@@ -0,0 +1,42 @@
1
+ import uuid
2
+
3
+ import uuid_utils
4
+
5
+ node = uuid.getnode()
6
+
7
+
8
+ def uuid_uuid1() -> None:
9
+ for _ in range(10_000):
10
+ uuid.uuid1(node)
11
+
12
+
13
+ def uuid_utils_uuid1() -> None:
14
+ for _ in range(10_000):
15
+ uuid_utils.uuid1(node)
16
+
17
+
18
+ def uuid_uuid4() -> None:
19
+ for _ in range(10_000):
20
+ uuid.uuid4()
21
+
22
+
23
+ def uuid_utils_uuid4() -> None:
24
+ for _ in range(10_000):
25
+ uuid_utils.uuid4()
26
+
27
+
28
+ def uuid_uuid5() -> None:
29
+ for _ in range(10_000):
30
+ uuid.uuid5(namespace=uuid.NAMESPACE_DNS, name="python.org")
31
+
32
+
33
+ def uuid_utils_uuid5() -> None:
34
+ for _ in range(10_000):
35
+ uuid_utils.uuid5(namespace=uuid_utils.NAMESPACE_DNS, name="python.org")
36
+
37
+
38
+ __benchmarks__ = [
39
+ (uuid_uuid1, uuid_utils_uuid1, "UUID V1"),
40
+ (uuid_uuid4, uuid_utils_uuid4, "UUID V4"),
41
+ (uuid_uuid5, uuid_utils_uuid5, "UUID V5"),
42
+ ]
@@ -0,0 +1,40 @@
1
+ import uuid
2
+
3
+ import uuid_utils
4
+
5
+
6
+ def uuid_from_hex() -> None:
7
+ for _ in range(10_000):
8
+ uuid.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
9
+
10
+
11
+ def uuid_utils_from_hex() -> None:
12
+ for _ in range(10_000):
13
+ uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
14
+
15
+
16
+ def uuid_from_bytes() -> None:
17
+ for _ in range(10_000):
18
+ uuid.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
19
+
20
+
21
+ def uuid_utils_from_bytes() -> None:
22
+ for _ in range(10_000):
23
+ uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
24
+
25
+
26
+ def uuid_from_int() -> None:
27
+ for _ in range(10_000):
28
+ uuid.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
29
+
30
+
31
+ def uuid_utils_from_int() -> None:
32
+ for _ in range(10_000):
33
+ uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
34
+
35
+
36
+ __benchmarks__ = [
37
+ (uuid_from_hex, uuid_utils_from_hex, "UUID from hex"),
38
+ (uuid_from_bytes, uuid_utils_from_bytes, "UUID from bytes"),
39
+ (uuid_from_int, uuid_utils_from_int, "UUID from int"),
40
+ ]
@@ -21,9 +21,12 @@ classifiers = [
21
21
  "Programming Language :: Python :: 3.10",
22
22
  "Programming Language :: Python :: 3.11",
23
23
  "Programming Language :: Rust",
24
+ "Intended Audience :: Developers",
25
+ "License :: OSI Approved :: BSD License",
26
+ "Operating System :: OS Independent",
24
27
  ]
25
28
 
26
- dynamic = ["version"]
29
+ dynamic = ["license", "version"]
27
30
 
28
31
  [project.urls]
29
32
  Documentation = "https://github.com/aminalaee/uuid-utils"
@@ -1,11 +1,20 @@
1
1
  use pyo3::{
2
2
  exceptions::{PyTypeError, PyValueError},
3
3
  prelude::*,
4
+ pyclass::CompareOp,
4
5
  types::{PyBytes, PyTuple},
5
6
  };
6
- use uuid::{Bytes, Context, Timestamp, Uuid};
7
+ use std::hash::Hasher;
8
+ use std::{collections::hash_map::DefaultHasher, hash::Hash};
9
+ use uuid::{Builder, Bytes, Context, Timestamp, Uuid, Variant, Version};
7
10
 
8
- #[pyclass(subclass)]
11
+ pub const RESERVED_NCS: &str = "reserved for NCS compatibility";
12
+ pub const RFC_4122: &str = "specified in RFC 4122";
13
+ pub const RESERVED_MICROSOFT: &str = "reserved for Microsoft compatibility";
14
+ pub const RESERVED_FUTURE: &str = "reserved for future definition";
15
+
16
+ #[pyclass(subclass, module="uuid_utils")]
17
+ #[derive(Clone, Debug)]
9
18
  struct UUID {
10
19
  uuid: Uuid,
11
20
  }
@@ -32,9 +41,9 @@ impl UUID {
32
41
  bytes_le: Option<&PyBytes>,
33
42
  fields: Option<&PyTuple>,
34
43
  int: Option<u128>,
35
- _version: Option<u8>,
44
+ version: Option<u8>,
36
45
  ) -> PyResult<Self> {
37
- match (hex, bytes, bytes_le, fields, int) {
46
+ let result = match (hex, bytes, bytes_le, fields, int) {
38
47
  (Some(hex), None, None, None, None) => Self::from_hex(hex),
39
48
  (None, Some(bytes), None, None, None) => Self::from_bytes(bytes),
40
49
  (None, None, Some(bytes_le), None, None) => Self::from_bytes_le(bytes_le),
@@ -43,20 +52,12 @@ impl UUID {
43
52
  _ => Err(PyTypeError::new_err(
44
53
  "one of the hex, bytes, bytes_le, fields, or int arguments must be given",
45
54
  )),
55
+ };
56
+
57
+ match version {
58
+ Some(v) => result.unwrap().set_version(v),
59
+ None => result,
46
60
  }
47
- // let version = match version {
48
- // Some(0) => Ok(Some(Version::Nil)),
49
- // Some(1) => Ok(Some(Version::Mac)),
50
- // Some(2) => Ok(Some(Version::Dce)),
51
- // Some(3) => Ok(Some(Version::Md5)),
52
- // Some(4) => Ok(Some(Version::Random)),
53
- // Some(5) => Ok(Some(Version::Sha1)),
54
- // Some(6) => Ok(Some(Version::SortMac)),
55
- // Some(7) => Ok(Some(Version::SortRand)),
56
- // Some(8) => Ok(Some(Version::Custom)),
57
- // None => Ok(None),
58
- // _ => Err(PyErr::new::<PyValueError, &str>("illegal version number.")),
59
- // }?;
60
61
  }
61
62
 
62
63
  fn __int__(&self) -> u128 {
@@ -71,6 +72,44 @@ impl UUID {
71
72
  format!("UUID('{}')", self.__str__())
72
73
  }
73
74
 
75
+ fn __richcmp__(&self, other: UUID, op: CompareOp) -> PyResult<bool> {
76
+ match op {
77
+ CompareOp::Lt => Ok(self.uuid < other.uuid),
78
+ CompareOp::Le => Ok(self.uuid <= other.uuid),
79
+ CompareOp::Eq => Ok(self.uuid == other.uuid),
80
+ CompareOp::Ne => Ok(self.uuid != other.uuid),
81
+ CompareOp::Gt => Ok(self.uuid > other.uuid),
82
+ CompareOp::Ge => Ok(self.uuid >= other.uuid),
83
+ }
84
+ }
85
+
86
+ fn __hash__(&self) -> PyResult<isize> {
87
+ let mut hasher = DefaultHasher::new();
88
+ self.uuid.hash(&mut hasher);
89
+ Ok(hasher.finish() as isize)
90
+ }
91
+
92
+ fn set_version(&self, version: u8) -> PyResult<UUID> {
93
+ let version = match version {
94
+ 1 => Version::Mac,
95
+ 2 => Version::Dce,
96
+ 3 => Version::Md5,
97
+ 4 => Version::Random,
98
+ 5 => Version::Sha1,
99
+ 6 => Version::SortMac,
100
+ 7 => Version::SortRand,
101
+ 8 => Version::Custom,
102
+ _ => return Err(PyErr::new::<PyValueError, &str>("illegal version number.")),
103
+ };
104
+
105
+ let mut builder = Builder::from_u128(self.uuid.as_u128());
106
+ builder.set_version(version);
107
+
108
+ Ok(UUID {
109
+ uuid: builder.into_uuid(),
110
+ })
111
+ }
112
+
74
113
  #[allow(unused_variables)]
75
114
  fn __setattr__(&self, name: &str, value: PyObject) -> PyResult<()> {
76
115
  Err(PyTypeError::new_err("UUID objects are immutable"))
@@ -101,6 +140,81 @@ impl UUID {
101
140
  self.uuid.as_u128()
102
141
  }
103
142
 
143
+ #[getter]
144
+ fn urn(&self) -> PyResult<String> {
145
+ Ok(self.uuid.urn().to_string())
146
+ }
147
+
148
+ #[getter]
149
+ fn version(&self) -> usize {
150
+ self.uuid.get_version_num()
151
+ }
152
+
153
+ #[getter]
154
+ fn variant(&self) -> &str {
155
+ match self.uuid.get_variant() {
156
+ Variant::NCS => RESERVED_NCS,
157
+ Variant::RFC4122 => RFC_4122,
158
+ Variant::Microsoft => RESERVED_MICROSOFT,
159
+ Variant::Future => RESERVED_FUTURE,
160
+ _ => RESERVED_FUTURE,
161
+ }
162
+ }
163
+
164
+ #[getter]
165
+ fn node(&self) -> u128 {
166
+ self.int() & 0xffffffffffff
167
+ }
168
+
169
+ #[getter]
170
+ fn time_low(&self) -> u128 {
171
+ self.int().wrapping_shr(96)
172
+ }
173
+
174
+ #[getter]
175
+ fn time_mid(&self) -> u128 {
176
+ (self.int().wrapping_shr(80)) & 0xffff
177
+ }
178
+
179
+ #[getter]
180
+ fn time_hi_version(&self) -> u128 {
181
+ (self.int().wrapping_shr(64)) & 0xffff
182
+ }
183
+
184
+ #[getter]
185
+ fn clock_seq_hi_variant(&self) -> u128 {
186
+ (self.int().wrapping_shr(56)) & 0xff
187
+ }
188
+
189
+ #[getter]
190
+ fn clock_seq_low(&self) -> u128 {
191
+ (self.int().wrapping_shr(48)) & 0xff
192
+ }
193
+
194
+ #[getter]
195
+ fn clock_seq(&self) -> u128 {
196
+ ((self.clock_seq_hi_variant() & 0x3f).wrapping_shl(8)) | self.clock_seq_low()
197
+ }
198
+
199
+ #[getter]
200
+ fn time(&self) -> u128 {
201
+ ((self.time_hi_version() & 0x0fff).wrapping_shl(48))
202
+ | (self.time_mid().wrapping_shl(32))
203
+ | self.time_low()
204
+ }
205
+
206
+ #[getter]
207
+ fn fields(&self) -> PyResult<(u128, u128, u128, u128, u128, u128)> {
208
+ Ok((
209
+ self.time_low(),
210
+ self.time_mid(),
211
+ self.time_hi_version(),
212
+ self.clock_seq_hi_variant(),
213
+ self.clock_seq_low(),
214
+ self.node(),
215
+ ))
216
+ }
217
+
104
218
  #[staticmethod]
105
219
  fn from_hex(hex: &str) -> PyResult<UUID> {
106
220
  match Uuid::parse_str(hex) {
@@ -210,19 +324,22 @@ fn uuid8(bytes: &PyBytes) -> PyResult<UUID> {
210
324
  }
211
325
 
212
326
  #[pymodule]
213
- fn uuid_utils(_py: Python, m: &PyModule) -> PyResult<()> {
327
+ fn _uuid_utils(_py: Python, m: &PyModule) -> PyResult<()> {
328
+ m.add("__version__", env!("CARGO_PKG_VERSION"))?;
214
329
  m.add_class::<UUID>()?;
215
-
216
330
  m.add_function(wrap_pyfunction!(uuid1, m)?)?;
217
331
  m.add_function(wrap_pyfunction!(uuid4, m)?)?;
218
332
  m.add_function(wrap_pyfunction!(uuid5, m)?)?;
219
333
  m.add_function(wrap_pyfunction!(uuid6, m)?)?;
220
334
  m.add_function(wrap_pyfunction!(uuid7, m)?)?;
221
335
  m.add_function(wrap_pyfunction!(uuid8, m)?)?;
222
-
223
336
  m.add("NAMESPACE_DNS", UUID::NAMESPACE_DNS)?;
224
337
  m.add("NAMESPACE_URL", UUID::NAMESPACE_URL)?;
225
338
  m.add("NAMESPACE_OID", UUID::NAMESPACE_OID)?;
226
339
  m.add("NAMESPACE_X500", UUID::NAMESPACE_X500)?;
340
+ m.add("RESERVED_NCS", RESERVED_NCS)?;
341
+ m.add("RFC_4122", RFC_4122)?;
342
+ m.add("RESERVED_MICROSOFT", RESERVED_MICROSOFT)?;
343
+ m.add("RESERVED_FUTURE", RESERVED_FUTURE)?;
227
344
  Ok(())
228
345
  }
@@ -1,4 +1,4 @@
1
- from uuid import getnode
1
+ from uuid import UUID, getnode
2
2
 
3
3
  import pytest
4
4
 
@@ -7,7 +7,7 @@ import uuid_utils
7
7
 
8
8
  def test_uuid_str() -> None:
9
9
  uuid = uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
10
- assert uuid.hex == "a8098c1af86e11dabd1a00112444be1e"
10
+ assert str(uuid) == "a8098c1a-f86e-11da-bd1a-00112444be1e"
11
11
 
12
12
 
13
13
  def test_uuid_repr() -> None:
@@ -15,6 +15,11 @@ def test_uuid_repr() -> None:
15
15
  assert repr(uuid) == "UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')"
16
16
 
17
17
 
18
+ def test_uuid_constructor() -> None:
19
+ with pytest.raises(TypeError):
20
+ uuid_utils.UUID()
21
+
22
+
18
23
  def test_uuid_from_hex() -> None:
19
24
  uuid = uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
20
25
  assert uuid.hex == "a8098c1af86e11dabd1a00112444be1e"
@@ -92,3 +97,58 @@ def test_uuid7() -> None:
92
97
  def test_uuid8() -> None:
93
98
  uuid = uuid_utils.uuid8(b"1234567812345678")
94
99
  assert isinstance(uuid, uuid_utils.UUID)
100
+
101
+
102
+ def test_uuid_comparisons() -> None:
103
+ uuid_1 = uuid_utils.uuid8(b"1234567812345678")
104
+ uuid_2 = uuid_utils.uuid8(b"1234567812345679")
105
+
106
+ assert uuid_1 < uuid_2
107
+ assert uuid_1 <= uuid_2
108
+
109
+ uuid_1 = uuid_utils.uuid8(b"1234567812345678")
110
+ uuid_2 = uuid_utils.uuid8(b"1234567812345678")
111
+
112
+ assert uuid_1 == uuid_2
113
+ assert hash(uuid_1) == hash(uuid_2)
114
+ assert not uuid_1 != uuid_2
115
+
116
+ uuid_1 = uuid_utils.uuid8(b"1234567812345678")
117
+ uuid_2 = uuid_utils.uuid8(b"1234567812345677")
118
+
119
+ assert uuid_1 > uuid_2
120
+ assert uuid_1 >= uuid_2
121
+
122
+
123
+ @pytest.mark.parametrize("version", [1, 2, 3, 4, 5, 7, 8])
124
+ def test_uuid_version(version: int) -> None:
125
+ uuid = uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e", version=version)
126
+ assert uuid.version == version
127
+
128
+
129
+ def test_uuid_illegal_version() -> None:
130
+ with pytest.raises(ValueError):
131
+ uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e", version=0)
132
+ uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e", version=9)
133
+
134
+
135
+ def test_uuid_properties() -> None:
136
+ uuid_1 = uuid_utils.UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
137
+ uuid_2 = UUID("a8098c1a-f86e-11da-bd1a-00112444be1e")
138
+
139
+ assert uuid_1.bytes == uuid_2.bytes
140
+ assert uuid_1.bytes_le == uuid_2.bytes_le
141
+ assert uuid_1.clock_seq_hi_variant == uuid_2.clock_seq_hi_variant
142
+ assert uuid_1.clock_seq_low == uuid_2.clock_seq_low
143
+ assert uuid_1.clock_seq == uuid_2.clock_seq
144
+ assert uuid_1.fields == uuid_2.fields
145
+ assert uuid_1.hex == uuid_2.hex
146
+ assert uuid_1.int == uuid_2.int
147
+ assert uuid_1.node == uuid_2.node
148
+ assert uuid_1.time == uuid_2.time
149
+ assert uuid_1.time_low == uuid_2.time_low
150
+ assert uuid_1.time_mid == uuid_2.time_mid
151
+ assert uuid_1.time_hi_version == uuid_2.time_hi_version
152
+ assert uuid_1.urn == uuid_2.urn
153
+ assert uuid_1.variant == uuid_2.variant
154
+ assert uuid_1.version == uuid_2.version
@@ -0,0 +1,5 @@
1
+ import uuid_utils
2
+
3
+
4
+ def test_version() -> None:
5
+ assert uuid_utils.__version__ == "0.2.0"
@@ -0,0 +1,37 @@
1
+ from _uuid_utils import (
2
+ NAMESPACE_DNS,
3
+ NAMESPACE_OID,
4
+ NAMESPACE_URL,
5
+ NAMESPACE_X500,
6
+ RESERVED_FUTURE,
7
+ RESERVED_MICROSOFT,
8
+ RESERVED_NCS,
9
+ RFC_4122,
10
+ UUID,
11
+ __version__,
12
+ uuid1,
13
+ uuid4,
14
+ uuid5,
15
+ uuid6,
16
+ uuid7,
17
+ uuid8,
18
+ )
19
+
20
+ __all__ = [
21
+ "NAMESPACE_DNS",
22
+ "NAMESPACE_OID",
23
+ "NAMESPACE_URL",
24
+ "NAMESPACE_X500",
25
+ "RESERVED_FUTURE",
26
+ "RESERVED_MICROSOFT",
27
+ "RESERVED_NCS",
28
+ "RFC_4122",
29
+ "UUID",
30
+ "__version__",
31
+ "uuid1",
32
+ "uuid4",
33
+ "uuid5",
34
+ "uuid6",
35
+ "uuid7",
36
+ "uuid8",
37
+ ]
@@ -9,12 +9,65 @@ _Int: TypeAlias = int
9
9
  _Bytes: TypeAlias = bytes
10
10
  _FieldsType: TypeAlias = tuple[int, int, int, int, int, int]
11
11
 
12
+ __version__: str
13
+
12
14
  class SafeUUID(Enum):
13
15
  safe: int
14
16
  unsafe: int
15
17
  unknown: None
16
18
 
17
19
  class UUID:
20
+ """Instances of the UUID class represent UUIDs as specified in RFC 4122.
21
+ UUID objects are immutable, hashable, and usable as dictionary keys.
22
+ Converting a UUID to a string with str() yields something in the form
23
+ '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
24
+ five possible forms: a similar string of hexadecimal digits, or a tuple
25
+ of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
26
+ 48-bit values respectively) as an argument named 'fields', or a string
27
+ of 16 bytes (with all the integer fields in big-endian order) as an
28
+ argument named 'bytes', or a string of 16 bytes (with the first three
29
+ fields in little-endian order) as an argument named 'bytes_le', or a
30
+ single 128-bit integer as an argument named 'int'.
31
+
32
+ UUIDs have these read-only attributes:
33
+
34
+ bytes the UUID as a 16-byte string (containing the six
35
+ integer fields in big-endian byte order)
36
+
37
+ bytes_le the UUID as a 16-byte string (with time_low, time_mid,
38
+ and time_hi_version in little-endian byte order)
39
+
40
+ fields a tuple of the six integer fields of the UUID,
41
+ which are also available as six individual attributes
42
+ and two derived attributes:
43
+
44
+ time_low the first 32 bits of the UUID
45
+ time_mid the next 16 bits of the UUID
46
+ time_hi_version the next 16 bits of the UUID
47
+ clock_seq_hi_variant the next 8 bits of the UUID
48
+ clock_seq_low the next 8 bits of the UUID
49
+ node the last 48 bits of the UUID
50
+
51
+ time the 60-bit timestamp
52
+ clock_seq the 14-bit sequence number
53
+
54
+ hex the UUID as a 32-character hexadecimal string
55
+
56
+ int the UUID as a 128-bit integer
57
+
58
+ urn the UUID as a URN as specified in RFC 4122
59
+
60
+ variant the UUID variant (one of the constants RESERVED_NCS,
61
+ RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
62
+
63
+ version the UUID version number (1 through 5, meaningful only
64
+ when the variant is RFC_4122)
65
+
66
+ is_safe An enum indicating whether the UUID has been generated in
67
+ a way that is safe for multiprocessing applications, via
68
+ uuid_generate_time_safe(3).
69
+ """
70
+
18
71
  def __init__(
19
72
  self,
20
73
  hex: str | None = None,
@@ -111,3 +164,7 @@ NAMESPACE_DNS: UUID
111
164
  NAMESPACE_URL: UUID
112
165
  NAMESPACE_OID: UUID
113
166
  NAMESPACE_X500: UUID
167
+ RESERVED_NCS: str
168
+ RFC_4122: str
169
+ RESERVED_MICROSOFT: str
170
+ RESERVED_FUTURE: str
@@ -1,158 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- tags:
8
- - "*"
9
- pull_request:
10
-
11
- permissions:
12
- contents: read
13
-
14
- env:
15
- RUSTFLAGS: "--cfg uuid_unstable"
16
-
17
- jobs:
18
- lint:
19
- name: Check code quality
20
- runs-on: ubuntu-latest
21
- steps:
22
- - uses: actions/checkout@v3
23
- - uses: actions/setup-python@v4
24
- with:
25
- python-version: "3.10"
26
- - name: Install dependencies
27
- run: pip install -r requirements.txt
28
- - name: Check code
29
- run: |
30
- black --check .
31
- isort --check --project=uuid_utils .
32
- mypy .
33
- ruff .
34
-
35
- linux:
36
- name: "Linux: ${{ matrix.target }}"
37
- runs-on: ubuntu-latest
38
- strategy:
39
- matrix:
40
- target: [x86_64, i686]
41
- steps:
42
- - uses: actions/checkout@v3
43
- - uses: actions/setup-python@v4
44
- with:
45
- python-version: "3.11"
46
- - name: Install dependencies
47
- run: pip install -r requirements.txt
48
- - name: Build wheels
49
- uses: PyO3/maturin-action@v1
50
- with:
51
- target: ${{ matrix.target }}
52
- args: --release --out dist --find-interpreter
53
- sccache: "true"
54
- manylinux: auto
55
- - name: Install and test
56
- if: matrix.target == 'x86_64'
57
- run: |
58
- pip install uuid_utils --no-index --find-links dist --force-reinstall
59
- pytest -v .
60
- - name: Upload wheels
61
- uses: actions/upload-artifact@v3
62
- with:
63
- name: wheels
64
- path: dist
65
-
66
- windows:
67
- name: "Windows: ${{ matrix.target }}"
68
- runs-on: windows-latest
69
- strategy:
70
- matrix:
71
- target: [x64, x86]
72
- steps:
73
- - uses: actions/checkout@v3
74
- - uses: actions/setup-python@v4
75
- with:
76
- python-version: "3.11"
77
- architecture: ${{ matrix.target }}
78
- - name: Install dependencies
79
- run: pip install -r requirements.txt
80
- - name: Build wheels
81
- uses: PyO3/maturin-action@v1
82
- with:
83
- target: ${{ matrix.target }}
84
- args: --release --out dist --find-interpreter
85
- sccache: "true"
86
- - name: Install and test uuid_utils
87
- run: |
88
- pip install uuid_utils --no-index --find-links dist --force-reinstall
89
- pytest -v .
90
- - name: Upload wheels
91
- uses: actions/upload-artifact@v3
92
- with:
93
- name: wheels
94
- path: dist
95
-
96
- macos:
97
- name: "MacOS"
98
- runs-on: macos-latest
99
- steps:
100
- - uses: actions/checkout@v3
101
- - uses: actions/setup-python@v4
102
- with:
103
- python-version: "3.11"
104
- - name: Install dependencies
105
- run: pip install -r requirements.txt
106
- - uses: dtolnay/rust-toolchain@stable
107
- - name: Build wheels - x86_64
108
- uses: PyO3/maturin-action@v1
109
- with:
110
- target: x86_64
111
- args: --release --out dist --find-interpreter
112
- sccache: "true"
113
- - name: Build wheels - universal2
114
- uses: PyO3/maturin-action@v1
115
- with:
116
- args: --release --out dist --find-interpreter --universal2
117
- - name: Install and test uuid_utils
118
- run: |
119
- pip install uuid_utils --no-index --find-links dist --force-reinstall
120
- pytest -v .
121
- - name: Upload wheels
122
- uses: actions/upload-artifact@v3
123
- with:
124
- name: wheels
125
- path: dist
126
-
127
- sdist:
128
- name: Source Distribution
129
- runs-on: ubuntu-latest
130
- steps:
131
- - uses: actions/checkout@v3
132
- - name: Build sdist
133
- uses: PyO3/maturin-action@v1
134
- with:
135
- command: sdist
136
- args: --out dist
137
- - name: Upload sdist
138
- uses: actions/upload-artifact@v3
139
- with:
140
- name: wheels
141
- path: dist
142
-
143
- release:
144
- name: Release
145
- runs-on: ubuntu-latest
146
- if: "startsWith(github.ref, 'refs/tags/')"
147
- needs: [lint, linux, windows, macos, sdist]
148
- steps:
149
- - uses: actions/download-artifact@v3
150
- with:
151
- name: wheels
152
- - name: Publish to PyPI
153
- uses: PyO3/maturin-action@v1
154
- env:
155
- MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
156
- with:
157
- command: upload
158
- args: --skip-existing *
File without changes
File without changes
File without changes