Merge branch 'master' into spec-resync-12-01-2025
This commit is contained in:
commit
b28f3c307f
@ -239,6 +239,19 @@ functions:
|
||||
working_dir: src
|
||||
type: test
|
||||
|
||||
# Test numpy
|
||||
test numpy:
|
||||
- command: subprocess.exec
|
||||
params:
|
||||
binary: bash
|
||||
args:
|
||||
- .evergreen/just.sh
|
||||
- test-numpy
|
||||
working_dir: src
|
||||
include_expansions_in_env:
|
||||
- TOOLCHAIN_VERSION
|
||||
type: test
|
||||
|
||||
# Upload coverage
|
||||
upload coverage:
|
||||
- command: ec2.assume_role
|
||||
|
||||
@ -4768,6 +4768,28 @@ tasks:
|
||||
- noauth
|
||||
- pypy
|
||||
|
||||
# Test numpy tests
|
||||
- name: test-numpy-python3.10
|
||||
commands:
|
||||
- func: test numpy
|
||||
vars:
|
||||
TOOLCHAIN_VERSION: "3.10"
|
||||
tags:
|
||||
- binary
|
||||
- vector
|
||||
- python-3.10
|
||||
- test-numpy
|
||||
- name: test-numpy-python3.14
|
||||
commands:
|
||||
- func: test numpy
|
||||
vars:
|
||||
TOOLCHAIN_VERSION: "3.14"
|
||||
tags:
|
||||
- binary
|
||||
- vector
|
||||
- python-3.14
|
||||
- test-numpy
|
||||
|
||||
# Test standard auth tests
|
||||
- name: test-standard-auth-v4.2-python3.10-auth-ssl-sharded-cluster
|
||||
commands:
|
||||
|
||||
@ -621,3 +621,42 @@ buildvariants:
|
||||
- rhel87-small
|
||||
expansions:
|
||||
STORAGE_ENGINE: inmemory
|
||||
|
||||
# Test numpy tests
|
||||
- name: test-numpy-rhel8
|
||||
tasks:
|
||||
- name: .test-numpy
|
||||
display_name: Test Numpy RHEL8
|
||||
run_on:
|
||||
- rhel87-small
|
||||
tags: [binary, vector, pr]
|
||||
- name: test-numpy-macos
|
||||
tasks:
|
||||
- name: .test-numpy
|
||||
display_name: Test Numpy macOS
|
||||
run_on:
|
||||
- macos-14
|
||||
tags: [binary, vector]
|
||||
- name: test-numpy-macos-arm64
|
||||
tasks:
|
||||
- name: .test-numpy
|
||||
display_name: Test Numpy macOS Arm64
|
||||
run_on:
|
||||
- macos-14-arm64
|
||||
tags: [binary, vector]
|
||||
- name: test-numpy-win64
|
||||
tasks:
|
||||
- name: .test-numpy
|
||||
display_name: Test Numpy Win64
|
||||
run_on:
|
||||
- windows-64-vsMulti-small
|
||||
tags: [binary, vector]
|
||||
- name: test-numpy-win32
|
||||
tasks:
|
||||
- name: .test-numpy
|
||||
display_name: Test Numpy Win32
|
||||
run_on:
|
||||
- windows-64-vsMulti-small
|
||||
expansions:
|
||||
IS_WIN32: "1"
|
||||
tags: [binary, vector]
|
||||
|
||||
@ -339,6 +339,37 @@ def create_disable_test_commands_variants():
|
||||
return [create_variant(tasks, display_name, host=host, expansions=expansions)]
|
||||
|
||||
|
||||
def create_test_numpy_tasks():
|
||||
tasks = []
|
||||
for python in MIN_MAX_PYTHON:
|
||||
tags = ["binary", "vector", f"python-{python}", "test-numpy"]
|
||||
task_name = get_task_name("test-numpy", python=python)
|
||||
test_func = FunctionCall(func="test numpy", vars=dict(TOOLCHAIN_VERSION=python))
|
||||
tasks.append(EvgTask(name=task_name, tags=tags, commands=[test_func]))
|
||||
return tasks
|
||||
|
||||
|
||||
def create_test_numpy_variants() -> list[BuildVariant]:
|
||||
variants = []
|
||||
base_display_name = "Test Numpy"
|
||||
|
||||
# Test a subset on each of the other platforms.
|
||||
for host_name in ("rhel8", "macos", "macos-arm64", "win64", "win32"):
|
||||
tasks = [".test-numpy"]
|
||||
host = HOSTS[host_name]
|
||||
tags = ["binary", "vector"]
|
||||
if host_name == "rhel8":
|
||||
tags.append("pr")
|
||||
expansions = dict()
|
||||
if host_name == "win32":
|
||||
expansions["IS_WIN32"] = "1"
|
||||
display_name = get_variant_name(base_display_name, host)
|
||||
variant = create_variant(tasks, display_name, host=host, tags=tags, expansions=expansions)
|
||||
variants.append(variant)
|
||||
|
||||
return variants
|
||||
|
||||
|
||||
def create_oidc_auth_variants():
|
||||
variants = []
|
||||
for host_name in ["ubuntu22", "macos", "win64"]:
|
||||
@ -1140,6 +1171,14 @@ def create_run_tests_func():
|
||||
return "run tests", [setup_cmd, test_cmd]
|
||||
|
||||
|
||||
def create_test_numpy_func():
|
||||
includes = ["TOOLCHAIN_VERSION"]
|
||||
test_cmd = get_subprocess_exec(
|
||||
include_expansions_in_env=includes, args=[".evergreen/just.sh", "test-numpy"]
|
||||
)
|
||||
return "test numpy", [test_cmd]
|
||||
|
||||
|
||||
def create_cleanup_func():
|
||||
cmd = get_subprocess_exec(args=[".evergreen/scripts/cleanup.sh"])
|
||||
return "cleanup", [cmd]
|
||||
|
||||
@ -63,7 +63,6 @@ HOSTS["macos"] = Host("macos", "macos-14", "macOS", dict())
|
||||
HOSTS["macos-arm64"] = Host("macos-arm64", "macos-14-arm64", "macOS Arm64", dict())
|
||||
HOSTS["ubuntu20"] = Host("ubuntu20", "ubuntu2004-small", "Ubuntu-20", dict())
|
||||
HOSTS["ubuntu22"] = Host("ubuntu22", "ubuntu2204-small", "Ubuntu-22", dict())
|
||||
HOSTS["rhel7"] = Host("rhel7", "rhel79-small", "RHEL7", dict())
|
||||
HOSTS["perf"] = Host("perf", "rhel90-dbx-perf-large", "", dict())
|
||||
HOSTS["debian11"] = Host("debian11", "debian11-small", "Debian11", dict())
|
||||
DEFAULT_HOST = HOSTS["rhel8"]
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import stat
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
from urllib import request
|
||||
|
||||
@ -117,9 +115,10 @@ def setup_libmongocrypt():
|
||||
LOGGER.info(f"Fetching {url}...")
|
||||
with request.urlopen(request.Request(url), timeout=15.0) as response: # noqa: S310
|
||||
if response.status == 200:
|
||||
fileobj = io.BytesIO(response.read())
|
||||
with tarfile.open("libmongocrypt.tar.gz", fileobj=fileobj) as fid:
|
||||
fid.extractall(Path.cwd() / "libmongocrypt")
|
||||
with Path("libmongocrypt.tar.gz").open("wb") as f:
|
||||
f.write(response.read())
|
||||
Path("libmongocrypt").mkdir()
|
||||
run_command("tar -xzf libmongocrypt.tar.gz -C libmongocrypt")
|
||||
LOGGER.info(f"Fetching {url}... done.")
|
||||
|
||||
run_command("ls -la libmongocrypt")
|
||||
|
||||
27
.github/pull_request_template.md
vendored
27
.github/pull_request_template.md
vendored
@ -1,38 +1,33 @@
|
||||
<!-- Thanks for contributing! -->
|
||||
<!-- Please ensure that the title of the PR is in the following form:
|
||||
[Issue Type]-[Issue Key]: Issue Title
|
||||
[JIRA TICKET]: Issue Title
|
||||
|
||||
If you are an external contributor and there is no JIRA ticket associated with your change, then use your best judgement
|
||||
for the PR title. A MongoDB employee will create a JIRA ticket and edit the name and links as appropriate.
|
||||
|
||||
Note on AI Contributions:
|
||||
We do not accept pull requests that are primarily or substantially generated by AI tools (ChatGPT, Copilot, etc.).
|
||||
All contributions must be written and understood by human contributors.
|
||||
-->
|
||||
[Issue Key](https://jira.mongodb.org/browse/%7BISSUE_KEY%7D)
|
||||
## Summary
|
||||
<!-- What conceptually is this PR introducing? If context is already provided from the JIRA ticket, still place it in the
|
||||
Pull Request as you should not make the reviewer do digging for a basic summary. -->
|
||||
[JIRA TICKET]
|
||||
|
||||
## Changes in this PR
|
||||
<!-- What changes did you make to the code? What new APIs (public or private) were added, removed, or edited to generate
|
||||
the desired outcome explained in the above summary? -->
|
||||
|
||||
## Testing Plan
|
||||
## Test Plan
|
||||
<!-- How did you test the code? If you added unit tests, you can say that. If you didn’t introduce unit tests, explain why.
|
||||
All code should be tested in some way – so please list what your validation strategy was. -->
|
||||
|
||||
### Screenshots (optional)
|
||||
<!-- Usually a great supplement to a test plan, especially if this requires local testing. -->
|
||||
|
||||
## Checklist
|
||||
<!-- Do not delete the items provided on this checklist. -->
|
||||
|
||||
### Checklist for Author
|
||||
- [ ] Did you update the changelog (if necessary)?
|
||||
- [ ] Is the intention of the code captured in relevant tests?
|
||||
- [ ] If there are new TODOs, has a related JIRA ticket been created?
|
||||
- [ ] Is there test coverage?
|
||||
- [ ] Is any followup work tracked in a JIRA ticket? If so, add link(s).
|
||||
|
||||
### Checklist for Reviewer {@primary_reviewer}
|
||||
### Checklist for Reviewer
|
||||
- [ ] Does the title of the PR reference a JIRA Ticket?
|
||||
- [ ] Do you fully understand the implementation? (Would you be comfortable explaining how this code works to someone else?)
|
||||
- [ ] Have you checked for spelling & grammar errors?
|
||||
- [ ] Is all relevant documentation (README or docstring) updated?
|
||||
|
||||
## Focus Areas for Reviewer (optional)
|
||||
<!-- List any complex portion of code you believe needs additional scrutiny and explain why. -->
|
||||
|
||||
2
.github/workflows/zizmor.yml
vendored
2
.github/workflows/zizmor.yml
vendored
@ -18,4 +18,4 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run zizmor 🌈
|
||||
uses: zizmorcore/zizmor-action@b0e5c0b2b3785bc67b9b6c743fdbd495cda1b4c4
|
||||
uses: zizmorcore/zizmor-action@c0e2b1c877e25a91d1d747c438d49199cad29698
|
||||
|
||||
@ -387,6 +387,11 @@ If you are running one of the `no-responder` tests, omit the `run-server` step.
|
||||
To run any of the test suites with minimum supported dependencies, pass `--test-min-deps` to
|
||||
`just setup-tests`.
|
||||
|
||||
## Testing time-dependent operations
|
||||
|
||||
- `test.utils_shared.delay` - One can trigger an arbitrarily long-running operation on the server using this delay utility
|
||||
in combination with a `$where` operation. Use this to test behaviors around timeouts or signals.
|
||||
|
||||
## Adding a new test suite
|
||||
|
||||
- If adding new tests files that should only be run for that test suite, add a pytest marker to the file and add
|
||||
|
||||
208
bson/binary.py
208
bson/binary.py
@ -65,6 +65,9 @@ if TYPE_CHECKING:
|
||||
from array import array as _array
|
||||
from mmap import mmap as _mmap
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
|
||||
class UuidRepresentation:
|
||||
UNSPECIFIED = 0
|
||||
@ -234,13 +237,20 @@ class BinaryVector:
|
||||
|
||||
__slots__ = ("data", "dtype", "padding")
|
||||
|
||||
def __init__(self, data: Sequence[float | int], dtype: BinaryVectorDtype, padding: int = 0):
|
||||
def __init__(
|
||||
self,
|
||||
data: Union[Sequence[float | int], npt.NDArray[np.number]],
|
||||
dtype: BinaryVectorDtype,
|
||||
padding: int = 0,
|
||||
):
|
||||
"""
|
||||
:param data: Sequence of numbers representing the mathematical vector.
|
||||
:param dtype: The data type stored in binary
|
||||
:param padding: The number of bits in the final byte that are to be ignored
|
||||
when a vector element's size is less than a byte
|
||||
and the length of the vector is not a multiple of 8.
|
||||
(Padding is equivalent to a negative value of `count` in
|
||||
`numpy.unpackbits <https://numpy.org/doc/stable/reference/generated/numpy.unpackbits.html>`_)
|
||||
"""
|
||||
self.data = data
|
||||
self.dtype = dtype
|
||||
@ -425,9 +435,19 @@ class Binary(bytes):
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@overload
|
||||
def from_vector(
|
||||
cls: Type[Binary],
|
||||
vector: Union[BinaryVector, list[int], list[float]],
|
||||
vector: npt.NDArray[np.number],
|
||||
dtype: BinaryVectorDtype,
|
||||
padding: int = 0,
|
||||
) -> Binary:
|
||||
...
|
||||
|
||||
@classmethod
|
||||
def from_vector(
|
||||
cls: Type[Binary],
|
||||
vector: Union[BinaryVector, list[int], list[float], npt.NDArray[np.number]],
|
||||
dtype: Optional[BinaryVectorDtype] = None,
|
||||
padding: Optional[int] = None,
|
||||
) -> Binary:
|
||||
@ -459,34 +479,72 @@ class Binary(bytes):
|
||||
vector = vector.data # type: ignore
|
||||
|
||||
padding = 0 if padding is None else padding
|
||||
if dtype == BinaryVectorDtype.INT8: # pack ints in [-128, 127] as signed int8
|
||||
format_str = "b"
|
||||
if padding:
|
||||
raise ValueError(f"padding does not apply to {dtype=}")
|
||||
elif dtype == BinaryVectorDtype.PACKED_BIT: # pack ints in [0, 255] as unsigned uint8
|
||||
format_str = "B"
|
||||
if 0 <= padding > 7:
|
||||
raise ValueError(f"{padding=}. It must be in [0,1, ..7].")
|
||||
if padding and not vector:
|
||||
raise ValueError("Empty vector with non-zero padding.")
|
||||
elif dtype == BinaryVectorDtype.FLOAT32: # pack floats as float32
|
||||
format_str = "f"
|
||||
if padding:
|
||||
raise ValueError(f"padding does not apply to {dtype=}")
|
||||
else:
|
||||
raise NotImplementedError("%s not yet supported" % dtype)
|
||||
|
||||
if not isinstance(dtype, BinaryVectorDtype):
|
||||
raise TypeError(
|
||||
"dtype must be a bson.BinaryVectorDtype of BinaryVectorDType.INT8, PACKED_BIT, FLOAT32"
|
||||
)
|
||||
metadata = struct.pack("<sB", dtype.value, padding)
|
||||
data = struct.pack(f"<{len(vector)}{format_str}", *vector) # type: ignore
|
||||
|
||||
if isinstance(vector, list):
|
||||
if dtype == BinaryVectorDtype.INT8: # pack ints in [-128, 127] as signed int8
|
||||
format_str = "b"
|
||||
if padding:
|
||||
raise ValueError(f"padding does not apply to {dtype=}")
|
||||
elif dtype == BinaryVectorDtype.PACKED_BIT: # pack ints in [0, 255] as unsigned uint8
|
||||
format_str = "B"
|
||||
if 0 <= padding > 7:
|
||||
raise ValueError(f"{padding=}. It must be in [0,1, ..7].")
|
||||
if padding and not vector:
|
||||
raise ValueError("Empty vector with non-zero padding.")
|
||||
elif dtype == BinaryVectorDtype.FLOAT32: # pack floats as float32
|
||||
format_str = "f"
|
||||
if padding:
|
||||
raise ValueError(f"padding does not apply to {dtype=}")
|
||||
else:
|
||||
raise NotImplementedError("%s not yet supported" % dtype)
|
||||
data = struct.pack(f"<{len(vector)}{format_str}", *vector)
|
||||
else: # vector is numpy array or incorrect type.
|
||||
try:
|
||||
import numpy as np
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Failed to create binary from vector. Check type. If numpy array, numpy must be installed."
|
||||
) from exc
|
||||
if not isinstance(vector, np.ndarray):
|
||||
raise TypeError(
|
||||
"Could not create Binary. Vector must be a BinaryVector, list[int], list[float] or numpy ndarray."
|
||||
)
|
||||
if vector.ndim != 1:
|
||||
raise ValueError(
|
||||
"from_numpy_vector only supports 1D arrays as it creates a single vector."
|
||||
)
|
||||
|
||||
if dtype == BinaryVectorDtype.FLOAT32:
|
||||
vector = vector.astype(np.dtype("float32"), copy=False)
|
||||
elif dtype == BinaryVectorDtype.INT8:
|
||||
if vector.min() >= -128 and vector.max() <= 127:
|
||||
vector = vector.astype(np.dtype("int8"), copy=False)
|
||||
else:
|
||||
raise ValueError("Values found outside INT8 range.")
|
||||
elif dtype == BinaryVectorDtype.PACKED_BIT:
|
||||
if vector.min() >= 0 and vector.max() <= 127:
|
||||
vector = vector.astype(np.dtype("uint8"), copy=False)
|
||||
else:
|
||||
raise ValueError("Values found outside UINT8 range.")
|
||||
else:
|
||||
raise NotImplementedError("%s not yet supported" % dtype)
|
||||
data = vector.tobytes()
|
||||
|
||||
if padding and len(vector) and not (data[-1] & ((1 << padding) - 1)) == 0:
|
||||
raise ValueError(
|
||||
"Vector has a padding P, but bits in the final byte lower than P are non-zero. They must be zero."
|
||||
)
|
||||
return cls(metadata + data, subtype=VECTOR_SUBTYPE)
|
||||
|
||||
def as_vector(self) -> BinaryVector:
|
||||
"""From the Binary, create a list of numbers, along with dtype and padding.
|
||||
def as_vector(self, return_numpy: bool = False) -> BinaryVector:
|
||||
"""From the Binary, create a list or 1-d numpy array of numbers, along with dtype and padding.
|
||||
|
||||
:param return_numpy: If True, BinaryVector.data will be a one-dimensional numpy array. By default, it is a list.
|
||||
:return: BinaryVector
|
||||
|
||||
.. versionadded:: 4.10
|
||||
@ -495,54 +553,84 @@ class Binary(bytes):
|
||||
if self.subtype != VECTOR_SUBTYPE:
|
||||
raise ValueError(f"Cannot decode subtype {self.subtype} as a vector")
|
||||
|
||||
position = 0
|
||||
dtype, padding = struct.unpack_from("<sB", self, position)
|
||||
position += 2
|
||||
dtype, padding = struct.unpack_from("<sB", self)
|
||||
dtype = BinaryVectorDtype(dtype)
|
||||
n_values = len(self) - position
|
||||
offset = 2
|
||||
n_bytes = len(self) - offset
|
||||
|
||||
if padding and dtype != BinaryVectorDtype.PACKED_BIT:
|
||||
raise ValueError(
|
||||
f"Corrupt data. Padding ({padding}) must be 0 for all but PACKED_BIT dtypes. ({dtype=})"
|
||||
)
|
||||
|
||||
if dtype == BinaryVectorDtype.INT8:
|
||||
dtype_format = "b"
|
||||
format_string = f"<{n_values}{dtype_format}"
|
||||
vector = list(struct.unpack_from(format_string, self, position))
|
||||
return BinaryVector(vector, dtype, padding)
|
||||
if not return_numpy:
|
||||
if dtype == BinaryVectorDtype.INT8:
|
||||
dtype_format = "b"
|
||||
format_string = f"<{n_bytes}{dtype_format}"
|
||||
vector = list(struct.unpack_from(format_string, self, offset))
|
||||
return BinaryVector(vector, dtype, padding)
|
||||
|
||||
elif dtype == BinaryVectorDtype.FLOAT32:
|
||||
n_bytes = len(self) - position
|
||||
n_values = n_bytes // 4
|
||||
if n_bytes % 4:
|
||||
raise ValueError(
|
||||
"Corrupt data. N bytes for a float32 vector must be a multiple of 4."
|
||||
)
|
||||
dtype_format = "f"
|
||||
format_string = f"<{n_values}{dtype_format}"
|
||||
vector = list(struct.unpack_from(format_string, self, position))
|
||||
return BinaryVector(vector, dtype, padding)
|
||||
elif dtype == BinaryVectorDtype.FLOAT32:
|
||||
n_values = n_bytes // 4
|
||||
if n_bytes % 4:
|
||||
raise ValueError(
|
||||
"Corrupt data. N bytes for a float32 vector must be a multiple of 4."
|
||||
)
|
||||
dtype_format = "f"
|
||||
format_string = f"<{n_values}{dtype_format}"
|
||||
vector = list(struct.unpack_from(format_string, self, offset))
|
||||
return BinaryVector(vector, dtype, padding)
|
||||
|
||||
elif dtype == BinaryVectorDtype.PACKED_BIT:
|
||||
# data packed as uint8
|
||||
if padding and not n_values:
|
||||
raise ValueError("Corrupt data. Vector has a padding P, but no data.")
|
||||
if padding > 7 or padding < 0:
|
||||
raise ValueError(f"Corrupt data. Padding ({padding}) must be between 0 and 7.")
|
||||
dtype_format = "B"
|
||||
format_string = f"<{n_values}{dtype_format}"
|
||||
unpacked_uint8s = list(struct.unpack_from(format_string, self, position))
|
||||
if padding and n_values and unpacked_uint8s[-1] & (1 << padding) - 1 != 0:
|
||||
warnings.warn(
|
||||
"Vector has a padding P, but bits in the final byte lower than P are non-zero. For pymongo>=5.0, they must be zero.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return BinaryVector(unpacked_uint8s, dtype, padding)
|
||||
elif dtype == BinaryVectorDtype.PACKED_BIT:
|
||||
# data packed as uint8
|
||||
if padding and not n_bytes:
|
||||
raise ValueError("Corrupt data. Vector has a padding P, but no data.")
|
||||
if padding > 7 or padding < 0:
|
||||
raise ValueError(f"Corrupt data. Padding ({padding}) must be between 0 and 7.")
|
||||
dtype_format = "B"
|
||||
format_string = f"<{n_bytes}{dtype_format}"
|
||||
unpacked_uint8s = list(struct.unpack_from(format_string, self, offset))
|
||||
if padding and n_bytes and unpacked_uint8s[-1] & (1 << padding) - 1 != 0:
|
||||
warnings.warn(
|
||||
"Vector has a padding P, but bits in the final byte lower than P are non-zero. For pymongo>=5.0, they must be zero.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return BinaryVector(unpacked_uint8s, dtype, padding)
|
||||
|
||||
else:
|
||||
raise NotImplementedError("Binary Vector dtype %s not yet supported" % dtype.name)
|
||||
else:
|
||||
raise NotImplementedError("Binary Vector dtype %s not yet supported" % dtype.name)
|
||||
else: # create a numpy array
|
||||
try:
|
||||
import numpy as np
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Converting binary to numpy.ndarray requires numpy to be installed."
|
||||
) from exc
|
||||
if dtype == BinaryVectorDtype.INT8:
|
||||
data = np.frombuffer(self[offset:], dtype="int8")
|
||||
elif dtype == BinaryVectorDtype.FLOAT32:
|
||||
if n_bytes % 4:
|
||||
raise ValueError(
|
||||
"Corrupt data. N bytes for a float32 vector must be a multiple of 4."
|
||||
)
|
||||
data = np.frombuffer(self[offset:], dtype="float32")
|
||||
elif dtype == BinaryVectorDtype.PACKED_BIT:
|
||||
# data packed as uint8
|
||||
if padding and not n_bytes:
|
||||
raise ValueError("Corrupt data. Vector has a padding P, but no data.")
|
||||
if padding > 7 or padding < 0:
|
||||
raise ValueError(f"Corrupt data. Padding ({padding}) must be between 0 and 7.")
|
||||
data = np.frombuffer(self[offset:], dtype="uint8")
|
||||
if padding and np.unpackbits(data[-1])[-padding:].sum() > 0:
|
||||
warnings.warn(
|
||||
"Vector has a padding P, but bits in the final byte lower than P are non-zero. For pymongo>=5.0, they must be zero.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError("Binary Vector dtype %s not yet supported" % dtype.name)
|
||||
return BinaryVector(data, dtype, padding)
|
||||
|
||||
@property
|
||||
def subtype(self) -> int:
|
||||
|
||||
@ -19,6 +19,7 @@ PyMongo 4.16 brings a number of changes including:
|
||||
- Use Zstandard support from the standard library for Python 3.14+, and use ``backports.zstd`` for older versions.
|
||||
- Fixed return type annotation for ``find_one_and_*`` methods on :class:`~pymongo.asynchronous.collection.AsyncCollection`
|
||||
and :class:`~pymongo.synchronous.collection.Collection` to include ``None``.
|
||||
- Added support for NumPy 1D-arrays in :class:`bson.binary.BinaryVector`.
|
||||
|
||||
Changes in Version 4.15.5 (2025/XX/XX)
|
||||
--------------------------------------
|
||||
|
||||
18
justfile
18
justfile
@ -2,7 +2,7 @@
|
||||
set shell := ["bash", "-c"]
|
||||
|
||||
# Commonly used command segments.
|
||||
typing_run := "uv run --group typing --extra aws --extra encryption --extra ocsp --extra snappy --extra test --extra zstd"
|
||||
typing_run := "uv run --group typing --extra aws --extra encryption --with numpy --extra ocsp --extra snappy --extra test --extra zstd"
|
||||
docs_run := "uv run --extra docs"
|
||||
doc_build := "./doc/_build"
|
||||
mypy_args := "--install-types --non-interactive"
|
||||
@ -38,14 +38,14 @@ typing: && resync
|
||||
|
||||
[group('typing')]
|
||||
typing-mypy: && resync
|
||||
{{typing_run}} mypy {{mypy_args}} bson gridfs tools pymongo
|
||||
{{typing_run}} mypy {{mypy_args}} --config-file mypy_test.ini test
|
||||
{{typing_run}} mypy {{mypy_args}} test/test_typing.py test/test_typing_strict.py
|
||||
{{typing_run}} python -m mypy {{mypy_args}} bson gridfs tools pymongo
|
||||
{{typing_run}} python -m mypy {{mypy_args}} --config-file mypy_test.ini test
|
||||
{{typing_run}} python -m mypy {{mypy_args}} test/test_typing.py test/test_typing_strict.py
|
||||
|
||||
[group('typing')]
|
||||
typing-pyright: && resync
|
||||
{{typing_run}} pyright test/test_typing.py test/test_typing_strict.py
|
||||
{{typing_run}} pyright -p strict_pyrightconfig.json test/test_typing_strict.py
|
||||
{{typing_run}} python -m pyright test/test_typing.py test/test_typing_strict.py
|
||||
{{typing_run}} python -m pyright -p strict_pyrightconfig.json test/test_typing_strict.py
|
||||
|
||||
[group('lint')]
|
||||
lint *args="": && resync
|
||||
@ -57,7 +57,11 @@ lint-manual *args="": && resync
|
||||
|
||||
[group('test')]
|
||||
test *args="-v --durations=5 --maxfail=10": && resync
|
||||
uv run --extra test pytest {{args}}
|
||||
uv run --extra test python -m pytest {{args}}
|
||||
|
||||
[group('test')]
|
||||
test-numpy: && resync
|
||||
uv run --extra test --with numpy python -m pytest test/test_bson.py
|
||||
|
||||
[group('test')]
|
||||
run-tests *args: && resync
|
||||
|
||||
@ -698,7 +698,7 @@ class AsyncDatabase(common.BaseObject, Generic[_DocumentType]):
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. _aggregation pipeline:
|
||||
https://mongodb.com/docs/manual/reference/operator/aggregation-pipeline
|
||||
https://www.mongodb.com/docs/manual/core/aggregation-pipeline/
|
||||
|
||||
.. _aggregate command:
|
||||
https://mongodb.com/docs/manual/reference/command/aggregate
|
||||
|
||||
@ -111,7 +111,7 @@ class Topology:
|
||||
self._publish_tp = self._listeners is not None and self._listeners.enabled_for_topology
|
||||
|
||||
# Create events queue if there are publishers.
|
||||
self._events = None
|
||||
self._events: queue.Queue[Any] | None = None
|
||||
self.__events_executor: Any = None
|
||||
|
||||
if self._publish_server or self._publish_tp:
|
||||
@ -126,6 +126,7 @@ class Topology:
|
||||
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put((self._listeners.publish_topology_opened, (self._topology_id,)))
|
||||
self._settings = topology_settings
|
||||
topology_description = TopologyDescription(
|
||||
@ -143,6 +144,7 @@ class Topology:
|
||||
)
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_topology_description_changed,
|
||||
@ -161,6 +163,7 @@ class Topology:
|
||||
for seed in topology_settings.seeds:
|
||||
if self._publish_server:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put((self._listeners.publish_server_opened, (seed, self._topology_id)))
|
||||
if _SDAM_LOGGER.isEnabledFor(logging.DEBUG):
|
||||
_debug_log(
|
||||
@ -491,6 +494,7 @@ class Topology:
|
||||
suppress_event = sd_old == server_description
|
||||
if self._publish_server and not suppress_event:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_server_description_changed,
|
||||
@ -503,6 +507,7 @@ class Topology:
|
||||
|
||||
if self._publish_tp and not suppress_event:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_topology_description_changed,
|
||||
@ -570,6 +575,7 @@ class Topology:
|
||||
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_topology_description_changed,
|
||||
@ -723,6 +729,7 @@ class Topology:
|
||||
# Publish only after releasing the lock.
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._description = TopologyDescription(
|
||||
TOPOLOGY_TYPE.Unknown,
|
||||
{},
|
||||
|
||||
@ -698,7 +698,7 @@ class Database(common.BaseObject, Generic[_DocumentType]):
|
||||
.. versionadded:: 3.9
|
||||
|
||||
.. _aggregation pipeline:
|
||||
https://mongodb.com/docs/manual/reference/operator/aggregation-pipeline
|
||||
https://www.mongodb.com/docs/manual/core/aggregation-pipeline/
|
||||
|
||||
.. _aggregate command:
|
||||
https://mongodb.com/docs/manual/reference/command/aggregate
|
||||
|
||||
@ -111,7 +111,7 @@ class Topology:
|
||||
self._publish_tp = self._listeners is not None and self._listeners.enabled_for_topology
|
||||
|
||||
# Create events queue if there are publishers.
|
||||
self._events = None
|
||||
self._events: queue.Queue[Any] | None = None
|
||||
self.__events_executor: Any = None
|
||||
|
||||
if self._publish_server or self._publish_tp:
|
||||
@ -126,6 +126,7 @@ class Topology:
|
||||
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put((self._listeners.publish_topology_opened, (self._topology_id,)))
|
||||
self._settings = topology_settings
|
||||
topology_description = TopologyDescription(
|
||||
@ -143,6 +144,7 @@ class Topology:
|
||||
)
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_topology_description_changed,
|
||||
@ -161,6 +163,7 @@ class Topology:
|
||||
for seed in topology_settings.seeds:
|
||||
if self._publish_server:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put((self._listeners.publish_server_opened, (seed, self._topology_id)))
|
||||
if _SDAM_LOGGER.isEnabledFor(logging.DEBUG):
|
||||
_debug_log(
|
||||
@ -491,6 +494,7 @@ class Topology:
|
||||
suppress_event = sd_old == server_description
|
||||
if self._publish_server and not suppress_event:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_server_description_changed,
|
||||
@ -503,6 +507,7 @@ class Topology:
|
||||
|
||||
if self._publish_tp and not suppress_event:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_topology_description_changed,
|
||||
@ -570,6 +575,7 @@ class Topology:
|
||||
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._events.put(
|
||||
(
|
||||
self._listeners.publish_topology_description_changed,
|
||||
@ -721,6 +727,7 @@ class Topology:
|
||||
# Publish only after releasing the lock.
|
||||
if self._publish_tp:
|
||||
assert self._events is not None
|
||||
assert self._listeners is not None
|
||||
self._description = TopologyDescription(
|
||||
TOPOLOGY_TYPE.Unknown,
|
||||
{},
|
||||
|
||||
@ -59,7 +59,7 @@ mockupdb = [
|
||||
]
|
||||
perf = ["simplejson>=3.17.0"]
|
||||
typing = [
|
||||
"mypy==1.18.2",
|
||||
"mypy==1.19.0",
|
||||
"pyright==1.1.407",
|
||||
"typing_extensions",
|
||||
"pip"
|
||||
|
||||
@ -482,7 +482,7 @@ class ClientContext:
|
||||
def drop_user(self, dbname, user):
|
||||
self.client[dbname].command("dropUser", user, writeConcern={"w": self.w})
|
||||
|
||||
def require_connection(self, func):
|
||||
def require_connection(self, func: Any) -> Any:
|
||||
"""Run a test only if we can connect to MongoDB."""
|
||||
return self._require(
|
||||
lambda: True, # _require checks if we're connected
|
||||
@ -552,7 +552,7 @@ class ClientContext:
|
||||
lambda: not self.fips_enabled, "Test cannot run on a FIPS-enabled host", func=func
|
||||
)
|
||||
|
||||
def require_replica_set(self, func):
|
||||
def require_replica_set(self, func: Any) -> Any:
|
||||
"""Run a test only if the client is connected to a replica set."""
|
||||
return self._require(lambda: self.is_rs, "Not connected to a replica set", func=func)
|
||||
|
||||
@ -638,7 +638,7 @@ class ClientContext:
|
||||
lambda: self.load_balancer, "Must be connected to a load balancer", func=func
|
||||
)
|
||||
|
||||
def require_no_load_balancer(self, func):
|
||||
def require_no_load_balancer(self, func: Any) -> Any:
|
||||
"""Run a test only if the client is not connected to a load balancer."""
|
||||
return self._require(
|
||||
lambda: not self.load_balancer, "Must not be connected to a load balancer", func=func
|
||||
@ -687,7 +687,7 @@ class ClientContext:
|
||||
lambda: self.test_commands_enabled, "Test commands must be enabled", func=func
|
||||
)
|
||||
|
||||
def require_failCommand_fail_point(self, func):
|
||||
def require_failCommand_fail_point(self, func: Any) -> Any:
|
||||
"""Run a test only if the server supports the failCommand fail
|
||||
point.
|
||||
"""
|
||||
|
||||
@ -482,7 +482,7 @@ class AsyncClientContext:
|
||||
async def drop_user(self, dbname, user):
|
||||
await self.client[dbname].command("dropUser", user, writeConcern={"w": self.w})
|
||||
|
||||
def require_connection(self, func):
|
||||
def require_connection(self, func: Any) -> Any:
|
||||
"""Run a test only if we can connect to MongoDB."""
|
||||
return self._require(
|
||||
lambda: True, # _require checks if we're connected
|
||||
@ -552,7 +552,7 @@ class AsyncClientContext:
|
||||
lambda: not self.fips_enabled, "Test cannot run on a FIPS-enabled host", func=func
|
||||
)
|
||||
|
||||
def require_replica_set(self, func):
|
||||
def require_replica_set(self, func: Any) -> Any:
|
||||
"""Run a test only if the client is connected to a replica set."""
|
||||
return self._require(lambda: self.is_rs, "Not connected to a replica set", func=func)
|
||||
|
||||
@ -638,7 +638,7 @@ class AsyncClientContext:
|
||||
lambda: self.load_balancer, "Must be connected to a load balancer", func=func
|
||||
)
|
||||
|
||||
def require_no_load_balancer(self, func):
|
||||
def require_no_load_balancer(self, func: Any) -> Any:
|
||||
"""Run a test only if the client is not connected to a load balancer."""
|
||||
return self._require(
|
||||
lambda: not self.load_balancer, "Must not be connected to a load balancer", func=func
|
||||
@ -687,7 +687,7 @@ class AsyncClientContext:
|
||||
lambda: self.test_commands_enabled, "Test commands must be enabled", func=func
|
||||
)
|
||||
|
||||
def require_failCommand_fail_point(self, func):
|
||||
def require_failCommand_fail_point(self, func: Any) -> Any:
|
||||
"""Run a test only if the server supports the failCommand fail
|
||||
point.
|
||||
"""
|
||||
|
||||
@ -771,8 +771,8 @@ class ProseSpecTestsMixin:
|
||||
class TestClusterAsyncChangeStream(TestAsyncChangeStreamBase, APITestsMixin):
|
||||
dbs: list
|
||||
|
||||
@async_client_context.require_version_min(4, 2, 0)
|
||||
@async_client_context.require_change_streams
|
||||
@async_client_context.require_version_min(4, 2, 0) # type:ignore[untyped-decorator]
|
||||
@async_client_context.require_change_streams # type:ignore[untyped-decorator]
|
||||
async def asyncSetUp(self) -> None:
|
||||
await super().asyncSetUp()
|
||||
self.dbs = [self.db, self.client.pymongo_test_2]
|
||||
@ -831,8 +831,8 @@ class TestClusterAsyncChangeStream(TestAsyncChangeStreamBase, APITestsMixin):
|
||||
|
||||
|
||||
class TestAsyncDatabaseAsyncChangeStream(TestAsyncChangeStreamBase, APITestsMixin):
|
||||
@async_client_context.require_version_min(4, 2, 0)
|
||||
@async_client_context.require_change_streams
|
||||
@async_client_context.require_version_min(4, 2, 0) # type:ignore[untyped-decorator]
|
||||
@async_client_context.require_change_streams # type:ignore[untyped-decorator]
|
||||
async def asyncSetUp(self) -> None:
|
||||
await super().asyncSetUp()
|
||||
|
||||
|
||||
@ -233,7 +233,7 @@ class AsyncEncryptionIntegrationTest(AsyncIntegrationTest):
|
||||
"""Base class for encryption integration tests."""
|
||||
|
||||
@unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
|
||||
@async_client_context.require_version_min(4, 2, -1)
|
||||
@async_client_context.require_version_min(4, 2, -1) # type:ignore[untyped-decorator]
|
||||
async def asyncSetUp(self) -> None:
|
||||
await super().asyncSetUp()
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ from __future__ import annotations
|
||||
import array
|
||||
import collections
|
||||
import datetime
|
||||
import importlib.util
|
||||
import mmap
|
||||
import os
|
||||
import pickle
|
||||
@ -71,6 +72,8 @@ from bson.son import SON
|
||||
from bson.timestamp import Timestamp
|
||||
from bson.tz_util import FixedOffset, utc
|
||||
|
||||
_NUMPY_AVAILABLE = importlib.util.find_spec("numpy") is not None
|
||||
|
||||
|
||||
class NotADict(abc.MutableMapping):
|
||||
"""Non-dict type that implements the mapping protocol."""
|
||||
@ -871,6 +874,65 @@ class TestBSON(unittest.TestCase):
|
||||
BinaryVector([1], BinaryVectorDtype.INT8), BinaryVector([2], BinaryVectorDtype.INT8)
|
||||
)
|
||||
|
||||
@unittest.skipIf(not _NUMPY_AVAILABLE, "numpy optional-dependency not installed.")
|
||||
def test_vector_from_numpy(self):
|
||||
"""Follows test_vector except for input type numpy.ndarray"""
|
||||
# Simple data values could be treated as any of our BinaryVectorDtypes
|
||||
import numpy as np
|
||||
|
||||
arr = np.array([2, 3])
|
||||
# INT8
|
||||
binary_vector_int8 = Binary.from_vector(arr, BinaryVectorDtype.INT8)
|
||||
# as_vector
|
||||
vector = binary_vector_int8.as_vector()
|
||||
assert isinstance(vector, BinaryVector)
|
||||
assert vector.data == arr.tolist()
|
||||
# as_numpy_vector
|
||||
vector_np = binary_vector_int8.as_vector(return_numpy=True)
|
||||
assert isinstance(vector_np, BinaryVector)
|
||||
assert isinstance(vector_np.data, np.ndarray)
|
||||
assert np.all(vector.data == arr)
|
||||
# PACKED_BIT
|
||||
binary_vector_uint8 = Binary.from_vector(arr, BinaryVectorDtype.PACKED_BIT)
|
||||
# as_vector
|
||||
vector = binary_vector_uint8.as_vector()
|
||||
assert isinstance(vector, BinaryVector)
|
||||
assert vector.data == arr.tolist()
|
||||
# as_numpy_vector
|
||||
vector_np = binary_vector_uint8.as_vector(return_numpy=True)
|
||||
assert isinstance(vector_np, BinaryVector)
|
||||
assert isinstance(vector_np.data, np.ndarray)
|
||||
assert np.all(vector_np.data == arr)
|
||||
# FLOAT32
|
||||
binary_vector_float32 = Binary.from_vector(arr, BinaryVectorDtype.FLOAT32)
|
||||
# as_vector
|
||||
vector = binary_vector_float32.as_vector()
|
||||
assert isinstance(vector, BinaryVector)
|
||||
assert vector.data == arr.tolist()
|
||||
# as_numpy_vector
|
||||
vector_np = binary_vector_float32.as_vector(return_numpy=True)
|
||||
assert isinstance(vector_np, BinaryVector)
|
||||
assert isinstance(vector_np.data, np.ndarray)
|
||||
assert np.all(vector_np.data == arr)
|
||||
|
||||
# Invalid cases
|
||||
with self.assertRaises(ValueError):
|
||||
Binary.from_vector(np.array([-1]), BinaryVectorDtype.PACKED_BIT)
|
||||
with self.assertRaises(ValueError):
|
||||
Binary.from_vector(np.array([128]), BinaryVectorDtype.PACKED_BIT)
|
||||
with self.assertRaises(ValueError):
|
||||
Binary.from_vector(np.array([-198]), BinaryVectorDtype.INT8)
|
||||
|
||||
# Unexpected cases
|
||||
# Creating a vector of INT8 from a list of doubles will be caught by struct.pack
|
||||
# Numpy's default behavior is to cast to the type requested.
|
||||
list_floats = [-1.1, 1.1]
|
||||
cast_bin = Binary.from_vector(np.array(list_floats), BinaryVectorDtype.INT8)
|
||||
vector = cast_bin.as_vector()
|
||||
vector_np = cast_bin.as_vector(return_numpy=True)
|
||||
assert vector.data != list_floats
|
||||
assert vector.data == vector_np.data.tolist() == [-1, 1]
|
||||
|
||||
def test_unicode_regex(self):
|
||||
"""Tests we do not get a segfault for C extension on unicode RegExs.
|
||||
This had been happening.
|
||||
|
||||
@ -757,8 +757,8 @@ class ProseSpecTestsMixin:
|
||||
class TestClusterChangeStream(TestChangeStreamBase, APITestsMixin):
|
||||
dbs: list
|
||||
|
||||
@client_context.require_version_min(4, 2, 0)
|
||||
@client_context.require_change_streams
|
||||
@client_context.require_version_min(4, 2, 0) # type:ignore[untyped-decorator]
|
||||
@client_context.require_change_streams # type:ignore[untyped-decorator]
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
self.dbs = [self.db, self.client.pymongo_test_2]
|
||||
@ -817,8 +817,8 @@ class TestClusterChangeStream(TestChangeStreamBase, APITestsMixin):
|
||||
|
||||
|
||||
class TestDatabaseChangeStream(TestChangeStreamBase, APITestsMixin):
|
||||
@client_context.require_version_min(4, 2, 0)
|
||||
@client_context.require_change_streams
|
||||
@client_context.require_version_min(4, 2, 0) # type:ignore[untyped-decorator]
|
||||
@client_context.require_change_streams # type:ignore[untyped-decorator]
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
|
||||
|
||||
@ -233,7 +233,7 @@ class EncryptionIntegrationTest(IntegrationTest):
|
||||
"""Base class for encryption integration tests."""
|
||||
|
||||
@unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
|
||||
@client_context.require_version_min(4, 2, -1)
|
||||
@client_context.require_version_min(4, 2, -1) # type:ignore[untyped-decorator]
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
|
||||
|
||||
@ -377,7 +377,50 @@ def oid_generated_on_process(oid):
|
||||
|
||||
|
||||
def delay(sec):
|
||||
return """function() { sleep(%f * 1000); return true; }""" % sec
|
||||
"""Along with a ``$where`` operator, this triggers an arbitrarily long-running
|
||||
operation on the server.
|
||||
|
||||
This can be useful in time-sensitive tests (e.g., timeouts, signals).
|
||||
Note that you must have at least one document in the collection or the
|
||||
server may decide not to sleep at all.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
db.coll.insert_one({"x": 1})
|
||||
db.test.find_one({"x": 1})
|
||||
# {'x': 1, '_id': ObjectId('54f4e12bfba5220aa4d6dee8')}
|
||||
|
||||
# The following will wait 2.5 seconds before returning.
|
||||
db.test.find_one({"$where": delay(2.5)})
|
||||
# {'x': 1, '_id': ObjectId('54f4e12bfba5220aa4d6dee8')}
|
||||
|
||||
Using ``delay`` to provoke a KeyboardInterrupt
|
||||
----------------------------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import signal
|
||||
|
||||
# Raise KeyboardInterrupt in 1 second
|
||||
def sigalarm(num, frame):
|
||||
raise KeyboardInterrupt
|
||||
|
||||
|
||||
signal.signal(signal.SIGALRM, sigalarm)
|
||||
signal.alarm(1)
|
||||
|
||||
raised = False
|
||||
try:
|
||||
clxn.find_one({"$where": delay(1.5)})
|
||||
except KeyboardInterrupt:
|
||||
raised = True
|
||||
|
||||
assert raised
|
||||
"""
|
||||
return "function() { sleep(%f * 1000); return true; }" % sec
|
||||
|
||||
|
||||
def camel_to_snake(camel):
|
||||
|
||||
164
uv.lock
generated
164
uv.lock
generated
@ -969,6 +969,89 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "librt"
|
||||
version = "0.7.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/d9/6f3d3fcf5e5543ed8a60cc70fa7d50508ed60b8a10e9af6d2058159ab54e/librt-0.7.3.tar.gz", hash = "sha256:3ec50cf65235ff5c02c5b747748d9222e564ad48597122a361269dd3aa808798", size = 144549, upload-time = "2025-12-06T19:04:45.553Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/66/79a14e672256ef58144a24eb49adb338ec02de67ff4b45320af6504682ab/librt-0.7.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2682162855a708e3270eba4b92026b93f8257c3e65278b456c77631faf0f4f7a", size = 54707, upload-time = "2025-12-06T19:03:10.881Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/fa/b709c65a9d5eab85f7bcfe0414504d9775aaad6e78727a0327e175474caa/librt-0.7.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:440c788f707c061d237c1e83edf6164ff19f5c0f823a3bf054e88804ebf971ec", size = 56670, upload-time = "2025-12-06T19:03:12.107Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/56/0685a0772ec89ddad4c00e6b584603274c3d818f9a68e2c43c4eb7b39ee9/librt-0.7.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399938edbd3d78339f797d685142dd8a623dfaded023cf451033c85955e4838a", size = 161045, upload-time = "2025-12-06T19:03:13.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/d9/863ada0c5ce48aefb89df1555e392b2209fcb6daee4c153c031339b9a89b/librt-0.7.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1975eda520957c6e0eb52d12968dd3609ffb7eef05d4223d097893d6daf1d8a7", size = 169532, upload-time = "2025-12-06T19:03:14.699Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/a0/71da6c8724fd16c31749905ef1c9e11de206d9301b5be984bf2682b4efb3/librt-0.7.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9da128d0edf990cf0d2ca011b02cd6f639e79286774bd5b0351245cbb5a6e51", size = 183277, upload-time = "2025-12-06T19:03:16.446Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/bf/9c97bf2f8338ba1914de233ea312bba2bbd7c59f43f807b3e119796bab18/librt-0.7.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e19acfde38cb532a560b98f473adc741c941b7a9bc90f7294bc273d08becb58b", size = 179045, upload-time = "2025-12-06T19:03:17.838Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/b1/ceea067f489e904cb4ddcca3c9b06ba20229bc3fa7458711e24a5811f162/librt-0.7.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:7b4f57f7a0c65821c5441d98c47ff7c01d359b1e12328219709bdd97fdd37f90", size = 173521, upload-time = "2025-12-06T19:03:19.17Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/41/6cb18f5da9c89ed087417abb0127a445a50ad4eaf1282ba5b52588187f47/librt-0.7.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:256793988bff98040de23c57cf36e1f4c2f2dc3dcd17537cdac031d3b681db71", size = 193592, upload-time = "2025-12-06T19:03:20.637Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/3c/fcef208746584e7c78584b7aedc617130c4a4742cb8273361bbda8b183b5/librt-0.7.3-cp310-cp310-win32.whl", hash = "sha256:fcb72249ac4ea81a7baefcbff74df7029c3cb1cf01a711113fa052d563639c9c", size = 47201, upload-time = "2025-12-06T19:03:21.764Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/bf/d8a6c35d1b2b789a4df9b3ddb1c8f535ea373fde2089698965a8f0d62138/librt-0.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:4887c29cadbdc50640179e3861c276325ff2986791e6044f73136e6e798ff806", size = 54371, upload-time = "2025-12-06T19:03:23.231Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/e6/f6391f5c6f158d31ed9af6bd1b1bcd3ffafdea1d816bc4219d0d90175a7f/librt-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:687403cced6a29590e6be6964463835315905221d797bc5c934a98750fe1a9af", size = 54711, upload-time = "2025-12-06T19:03:24.6Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/1b/53c208188c178987c081560a0fcf36f5ca500d5e21769596c845ef2f40d4/librt-0.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24d70810f6e2ea853ff79338001533716b373cc0f63e2a0be5bc96129edb5fb5", size = 56664, upload-time = "2025-12-06T19:03:25.969Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/5c/d9da832b9a1e5f8366e8a044ec80217945385b26cb89fd6f94bfdc7d80b0/librt-0.7.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bf8c7735fbfc0754111f00edda35cf9e98a8d478de6c47b04eaa9cef4300eaa7", size = 161701, upload-time = "2025-12-06T19:03:27.035Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/aa/1e0a7aba15e78529dd21f233076b876ee58c8b8711b1793315bdd3b263b0/librt-0.7.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32d43610dff472eab939f4d7fbdd240d1667794192690433672ae22d7af8445", size = 171040, upload-time = "2025-12-06T19:03:28.482Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/46/3cfa325c1c2bc25775ec6ec1718cfbec9cff4ac767d37d2d3a2d1cc6f02c/librt-0.7.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:adeaa886d607fb02563c1f625cf2ee58778a2567c0c109378da8f17ec3076ad7", size = 184720, upload-time = "2025-12-06T19:03:29.599Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/bb/e4553433d7ac47f4c75d0a7e59b13aee0e08e88ceadbee356527a9629b0a/librt-0.7.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:572a24fc5958c61431da456a0ef1eeea6b4989d81eeb18b8e5f1f3077592200b", size = 180731, upload-time = "2025-12-06T19:03:31.201Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/89/51cd73006232981a3106d4081fbaa584ac4e27b49bc02266468d3919db03/librt-0.7.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6488e69d408b492e08bfb68f20c4a899a354b4386a446ecd490baff8d0862720", size = 174565, upload-time = "2025-12-06T19:03:32.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/54/0578a78b587e5aa22486af34239a052c6366835b55fc307bc64380229e3f/librt-0.7.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed028fc3d41adda916320712838aec289956c89b4f0a361ceadf83a53b4c047a", size = 195247, upload-time = "2025-12-06T19:03:34.434Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/0a/ee747cd999753dd9447e50b98fc36ee433b6c841a42dbf6d47b64b32a56e/librt-0.7.3-cp311-cp311-win32.whl", hash = "sha256:2cf9d73499486ce39eebbff5f42452518cc1f88d8b7ea4a711ab32962b176ee2", size = 47514, upload-time = "2025-12-06T19:03:35.959Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/af/8b13845178dec488e752878f8e290f8f89e7e34ae1528b70277aa1a6dd1e/librt-0.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:35f1609e3484a649bb80431310ddbec81114cd86648f1d9482bc72a3b86ded2e", size = 54695, upload-time = "2025-12-06T19:03:36.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/7a/ae59578501b1a25850266778f59279f4f3e726acc5c44255bfcb07b4bc57/librt-0.7.3-cp311-cp311-win_arm64.whl", hash = "sha256:550fdbfbf5bba6a2960b27376ca76d6aaa2bd4b1a06c4255edd8520c306fcfc0", size = 48142, upload-time = "2025-12-06T19:03:38.263Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/90/ed8595fa4e35b6020317b5ea8d226a782dcbac7a997c19ae89fb07a41c66/librt-0.7.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fa9ac2e49a6bee56e47573a6786cb635e128a7b12a0dc7851090037c0d397a3", size = 55687, upload-time = "2025-12-06T19:03:39.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/f6/6a20702a07b41006cb001a759440cb6b5362530920978f64a2b2ae2bf729/librt-0.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e980cf1ed1a2420a6424e2ed884629cdead291686f1048810a817de07b5eb18", size = 57127, upload-time = "2025-12-06T19:03:40.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/f3/b0c4703d5ffe9359b67bb2ccb86c42d4e930a363cfc72262ac3ba53cff3e/librt-0.7.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e094e445c37c57e9ec612847812c301840239d34ccc5d153a982fa9814478c60", size = 165336, upload-time = "2025-12-06T19:03:41.369Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/69/3ba05b73ab29ccbe003856232cea4049769be5942d799e628d1470ed1694/librt-0.7.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aca73d70c3f553552ba9133d4a09e767dcfeee352d8d8d3eb3f77e38a3beb3ed", size = 174237, upload-time = "2025-12-06T19:03:42.44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/ad/d7c2671e7bf6c285ef408aa435e9cd3fdc06fd994601e1f2b242df12034f/librt-0.7.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c634a0a6db395fdaba0361aa78395597ee72c3aad651b9a307a3a7eaf5efd67e", size = 189017, upload-time = "2025-12-06T19:03:44.01Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/94/d13f57193148004592b618555f296b41d2d79b1dc814ff8b3273a0bf1546/librt-0.7.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a59a69deeb458c858b8fea6acf9e2acd5d755d76cd81a655256bc65c20dfff5b", size = 183983, upload-time = "2025-12-06T19:03:45.834Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/10/b612a9944ebd39fa143c7e2e2d33f2cb790205e025ddd903fb509a3a3bb3/librt-0.7.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d91e60ac44bbe3a77a67af4a4c13114cbe9f6d540337ce22f2c9eaf7454ca71f", size = 177602, upload-time = "2025-12-06T19:03:46.944Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/48/77bc05c4cc232efae6c5592c0095034390992edbd5bae8d6cf1263bb7157/librt-0.7.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:703456146dc2bf430f7832fd1341adac5c893ec3c1430194fdcefba00012555c", size = 199282, upload-time = "2025-12-06T19:03:48.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/aa/05916ccd864227db1ffec2a303ae34f385c6b22d4e7ce9f07054dbcf083c/librt-0.7.3-cp312-cp312-win32.whl", hash = "sha256:b7c1239b64b70be7759554ad1a86288220bbb04d68518b527783c4ad3fb4f80b", size = 47879, upload-time = "2025-12-06T19:03:49.289Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/92/7f41c42d31ea818b3c4b9cc1562e9714bac3c676dd18f6d5dd3d0f2aa179/librt-0.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef59c938f72bdbc6ab52dc50f81d0637fde0f194b02d636987cea2ab30f8f55a", size = 54972, upload-time = "2025-12-06T19:03:50.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/dc/53582bbfb422311afcbc92adb75711f04e989cec052f08ec0152fbc36c9c/librt-0.7.3-cp312-cp312-win_arm64.whl", hash = "sha256:ff21c554304e8226bf80c3a7754be27c6c3549a9fec563a03c06ee8f494da8fc", size = 48338, upload-time = "2025-12-06T19:03:51.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/7d/e0ce1837dfb452427db556e6d4c5301ba3b22fe8de318379fbd0593759b9/librt-0.7.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56f2a47beda8409061bc1c865bef2d4bd9ff9255219402c0817e68ab5ad89aed", size = 55742, upload-time = "2025-12-06T19:03:52.459Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/c0/3564262301e507e1d5cf31c7d84cb12addf0d35e05ba53312494a2eba9a4/librt-0.7.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:14569ac5dd38cfccf0a14597a88038fb16811a6fede25c67b79c6d50fc2c8fdc", size = 57163, upload-time = "2025-12-06T19:03:53.516Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/ac/245e72b7e443d24a562f6047563c7f59833384053073ef9410476f68505b/librt-0.7.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6038ccbd5968325a5d6fd393cf6e00b622a8de545f0994b89dd0f748dcf3e19e", size = 165840, upload-time = "2025-12-06T19:03:54.918Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/af/587e4491f40adba066ba39a450c66bad794c8d92094f936a201bfc7c2b5f/librt-0.7.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d39079379a9a28e74f4d57dc6357fa310a1977b51ff12239d7271ec7e71d67f5", size = 174827, upload-time = "2025-12-06T19:03:56.082Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/21/5b8c60ea208bc83dd00421022a3874330685d7e856404128dc3728d5d1af/librt-0.7.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8837d5a52a2d7aa9f4c3220a8484013aed1d8ad75240d9a75ede63709ef89055", size = 189612, upload-time = "2025-12-06T19:03:57.507Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/2f/8b819169ef696421fb81cd04c6cdf225f6e96f197366001e9d45180d7e9e/librt-0.7.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:399bbd7bcc1633c3e356ae274a1deb8781c7bf84d9c7962cc1ae0c6e87837292", size = 184584, upload-time = "2025-12-06T19:03:58.686Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/fc/af9d225a9395b77bd7678362cb055d0b8139c2018c37665de110ca388022/librt-0.7.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8d8cf653e798ee4c4e654062b633db36984a1572f68c3aa25e364a0ddfbbb910", size = 178269, upload-time = "2025-12-06T19:03:59.769Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/d8/7b4fa1683b772966749d5683aa3fd605813defffe157833a8fa69cc89207/librt-0.7.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2f03484b54bf4ae80ab2e504a8d99d20d551bfe64a7ec91e218010b467d77093", size = 199852, upload-time = "2025-12-06T19:04:00.901Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/e8/4598413aece46ca38d9260ef6c51534bd5f34b5c21474fcf210ce3a02123/librt-0.7.3-cp313-cp313-win32.whl", hash = "sha256:44b3689b040df57f492e02cd4f0bacd1b42c5400e4b8048160c9d5e866de8abe", size = 47936, upload-time = "2025-12-06T19:04:02.054Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/80/ac0e92d5ef8c6791b3e2c62373863827a279265e0935acdf807901353b0e/librt-0.7.3-cp313-cp313-win_amd64.whl", hash = "sha256:6b407c23f16ccc36614c136251d6b32bf30de7a57f8e782378f1107be008ddb0", size = 54965, upload-time = "2025-12-06T19:04:03.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/fd/042f823fcbff25c1449bb4203a29919891ca74141b68d3a5f6612c4ce283/librt-0.7.3-cp313-cp313-win_arm64.whl", hash = "sha256:abfc57cab3c53c4546aee31859ef06753bfc136c9d208129bad23e2eca39155a", size = 48350, upload-time = "2025-12-06T19:04:04.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/ae/c6ecc7bb97134a71b5241e8855d39964c0e5f4d96558f0d60593892806d2/librt-0.7.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:120dd21d46ff875e849f1aae19346223cf15656be489242fe884036b23d39e93", size = 55175, upload-time = "2025-12-06T19:04:05.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/bc/2cc0cb0ab787b39aa5c7645cd792433c875982bdf12dccca558b89624594/librt-0.7.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1617bea5ab31266e152871208502ee943cb349c224846928a1173c864261375e", size = 56881, upload-time = "2025-12-06T19:04:06.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/87/397417a386190b70f5bf26fcedbaa1515f19dce33366e2684c6b7ee83086/librt-0.7.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93b2a1f325fefa1482516ced160c8c7b4b8d53226763fa6c93d151fa25164207", size = 163710, upload-time = "2025-12-06T19:04:08.437Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/37/7338f85b80e8a17525d941211451199845093ca242b32efbf01df8531e72/librt-0.7.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d4801db8354436fd3936531e7f0e4feb411f62433a6b6cb32bb416e20b529f", size = 172471, upload-time = "2025-12-06T19:04:10.124Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/e0/741704edabbfae2c852fedc1b40d9ed5a783c70ed3ed8e4fe98f84b25d13/librt-0.7.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11ad45122bbed42cfc8b0597450660126ef28fd2d9ae1a219bc5af8406f95678", size = 186804, upload-time = "2025-12-06T19:04:11.586Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/d1/0a82129d6ba242f3be9af34815be089f35051bc79619f5c27d2c449ecef6/librt-0.7.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6b4e7bff1d76dd2b46443078519dc75df1b5e01562345f0bb740cea5266d8218", size = 181817, upload-time = "2025-12-06T19:04:12.802Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/32/704f80bcf9979c68d4357c46f2af788fbf9d5edda9e7de5786ed2255e911/librt-0.7.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:d86f94743a11873317094326456b23f8a5788bad9161fd2f0e52088c33564620", size = 175602, upload-time = "2025-12-06T19:04:14.004Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/6d/4355cfa0fae0c062ba72f541d13db5bc575770125a7ad3d4f46f4109d305/librt-0.7.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:754a0d09997095ad764ccef050dd5bf26cbf457aab9effcba5890dad081d879e", size = 196497, upload-time = "2025-12-06T19:04:15.487Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/eb/ac6d8517d44209e5a712fde46f26d0055e3e8969f24d715f70bd36056230/librt-0.7.3-cp314-cp314-win32.whl", hash = "sha256:fbd7351d43b80d9c64c3cfcb50008f786cc82cba0450e8599fdd64f264320bd3", size = 44678, upload-time = "2025-12-06T19:04:16.688Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/93/238f026d141faf9958da588c761a0812a1a21c98cc54a76f3608454e4e59/librt-0.7.3-cp314-cp314-win_amd64.whl", hash = "sha256:d376a35c6561e81d2590506804b428fc1075fcc6298fc5bb49b771534c0ba010", size = 51689, upload-time = "2025-12-06T19:04:17.726Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/44/43f462ad9dcf9ed7d3172fe2e30d77b980956250bd90e9889a9cca93df2a/librt-0.7.3-cp314-cp314-win_arm64.whl", hash = "sha256:cbdb3f337c88b43c3b49ca377731912c101178be91cb5071aac48faa898e6f8e", size = 44662, upload-time = "2025-12-06T19:04:18.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/35/fed6348915f96b7323241de97f26e2af481e95183b34991df12fd5ce31b1/librt-0.7.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9f0e0927efe87cd42ad600628e595a1a0aa1c64f6d0b55f7e6059079a428641a", size = 57347, upload-time = "2025-12-06T19:04:19.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/f2/045383ccc83e3fea4fba1b761796584bc26817b6b2efb6b8a6731431d16f/librt-0.7.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:020c6db391268bcc8ce75105cb572df8cb659a43fd347366aaa407c366e5117a", size = 59223, upload-time = "2025-12-06T19:04:20.862Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/3f/c081f8455ab1d7f4a10dbe58463ff97119272ff32494f21839c3b9029c2c/librt-0.7.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7af7785f5edd1f418da09a8cdb9ec84b0213e23d597413e06525340bcce1ea4f", size = 183861, upload-time = "2025-12-06T19:04:21.963Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/f5/73c5093c22c31fbeaebc25168837f05ebfd8bf26ce00855ef97a5308f36f/librt-0.7.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ccadf260bb46a61b9c7e89e2218f6efea9f3eeaaab4e3d1f58571890e54858e", size = 194594, upload-time = "2025-12-06T19:04:23.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b8/d5f17d4afe16612a4a94abfded94c16c5a033f183074fb130dfe56fc1a42/librt-0.7.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9883b2d819ce83f87ba82a746c81d14ada78784db431e57cc9719179847376e", size = 206759, upload-time = "2025-12-06T19:04:24.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/2e/021765c1be85ee23ffd5b5b968bb4cba7526a4db2a0fc27dcafbdfc32da7/librt-0.7.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:59cb0470612d21fa1efddfa0dd710756b50d9c7fb6c1236bbf8ef8529331dc70", size = 203210, upload-time = "2025-12-06T19:04:25.544Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/f0/9923656e42da4fd18c594bd08cf6d7e152d4158f8b808e210d967f0dcceb/librt-0.7.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1fe603877e1865b5fd047a5e40379509a4a60204aa7aa0f72b16f7a41c3f0712", size = 196708, upload-time = "2025-12-06T19:04:26.725Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/0b/0708b886ac760e64d6fbe7e16024e4be3ad1a3629d19489a97e9cf4c3431/librt-0.7.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5460d99ed30f043595bbdc888f542bad2caeb6226b01c33cda3ae444e8f82d42", size = 217212, upload-time = "2025-12-06T19:04:27.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/7f/12a73ff17bca4351e73d585dd9ebf46723c4a8622c4af7fe11a2e2d011ff/librt-0.7.3-cp314-cp314t-win32.whl", hash = "sha256:d09f677693328503c9e492e33e9601464297c01f9ebd966ea8fc5308f3069bfd", size = 45586, upload-time = "2025-12-06T19:04:29.116Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/df/8decd032ac9b995e4f5606cde783711a71094128d88d97a52e397daf2c89/librt-0.7.3-cp314-cp314t-win_amd64.whl", hash = "sha256:25711f364c64cab2c910a0247e90b51421e45dbc8910ceeb4eac97a9e132fc6f", size = 53002, upload-time = "2025-12-06T19:04:30.173Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/0c/6605b6199de8178afe7efc77ca1d8e6db00453bc1d3349d27605c0f42104/librt-0.7.3-cp314-cp314t-win_arm64.whl", hash = "sha256:a9f9b661f82693eb56beb0605156c7fca57f535704ab91837405913417d6990b", size = 45647, upload-time = "2025-12-06T19:04:31.302Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/70/b3f19e3bb34f44e218c8271dc0b2b14eb6b183fbccbececf94c71e2b5e69/librt-0.7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd8551aa21df6c60baa2624fd086ae7486bdde00c44097b32e1d1b1966e365e0", size = 54850, upload-time = "2025-12-06T19:04:32.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/97/6599ed7726aaa9b5bacea206d5861b94e76866240e2f394a59594bf3db46/librt-0.7.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6eb9295c730e26b849ed1f4022735f36863eb46b14b6e10604c1c39b8b5efaea", size = 56797, upload-time = "2025-12-06T19:04:34.193Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/83/216db13224a6f688787f456909bbc50f9d951c0f4bea8ba38a2eb931d581/librt-0.7.3-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3edbf257c40d21a42615e9e332a6b10a8bacaaf58250aed8552a14a70efd0d65", size = 159681, upload-time = "2025-12-06T19:04:35.554Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/23/0a490c8ba3bc90090647ac7b9b3c63c16af7378bcabe3ff4c7d7890d66e5/librt-0.7.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b29e97273bd6999e2bfe9fe3531b1f4f64effd28327bced048a33e49b99674a", size = 168505, upload-time = "2025-12-06T19:04:36.748Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/16/b47c60805285caa06728d61d933fdd6db5b7321f375ce496cb7fdbeb1a44/librt-0.7.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e40520c37926166c24d0c2e0f3bc3a5f46646c34bdf7b4ea9747c297d6ee809", size = 182234, upload-time = "2025-12-06T19:04:37.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/2f/bef211d7f0d55fa2484d2c644b2cdae8c9c5eec050754b0516e6582ad452/librt-0.7.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6bdd9adfca615903578d2060ee8a6eb1c24eaf54919ff0ddc820118e5718931b", size = 178276, upload-time = "2025-12-06T19:04:39.408Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/dd/5a3e7762b086b62fabb31fd4deaaf3ba888cfdd3b8f2e3247f076c18a6ff/librt-0.7.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f57aca20e637750a2c18d979f7096e2c2033cc40cf7ed201494318de1182f135", size = 172602, upload-time = "2025-12-06T19:04:40.619Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/d8/533d5bfd5b377eb03ed54101814b530fc1f9bbe0e79971c641a3f15bfb33/librt-0.7.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cad9971881e4fec00d96af7eaf4b63aa7a595696fc221808b0d3ce7ca9743258", size = 192741, upload-time = "2025-12-06T19:04:41.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/69/0b87ce8e95f65ebc864f390f1139b8fe9fac6fb64b797307447b1719610c/librt-0.7.3-cp39-cp39-win32.whl", hash = "sha256:170cdb8436188347af17bf9cccf3249ba581c933ed56d926497119d4cf730cec", size = 47154, upload-time = "2025-12-06T19:04:42.96Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/1c/070dee0add2d6e742be4d8b965d5a37c24562b43e8ef7deba8ed5b5d3c0f/librt-0.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:b278a9248a4e3260fee3db7613772ca9ab6763a129d6d6f29555e2f9b168216d", size = 54339, upload-time = "2025-12-06T19:04:44.415Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.2"
|
||||
@ -1047,53 +1130,54 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.18.2"
|
||||
version = "1.19.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "librt" },
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c0/77/8f0d0001ffad290cef2f7f216f96c814866248a0b92a722365ed54648e7e/mypy-1.18.2.tar.gz", hash = "sha256:06a398102a5f203d7477b2923dda3634c36727fa5c237d8f859ef90c42a9924b", size = 3448846, upload-time = "2025-09-19T00:11:10.519Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f9/b5/b58cdc25fadd424552804bf410855d52324183112aa004f0732c5f6324cf/mypy-1.19.0.tar.gz", hash = "sha256:f6b874ca77f733222641e5c46e4711648c4037ea13646fd0cdc814c2eaec2528", size = 3579025, upload-time = "2025-11-28T15:49:01.26Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/03/6f/657961a0743cff32e6c0611b63ff1c1970a0b482ace35b069203bf705187/mypy-1.18.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eab0cf6294dafe397c261a75f96dc2c31bffe3b944faa24db5def4e2b0f77c", size = 12807973, upload-time = "2025-09-19T00:10:35.282Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/e9/420822d4f661f13ca8900f5fa239b40ee3be8b62b32f3357df9a3045a08b/mypy-1.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a780ca61fc239e4865968ebc5240bb3bf610ef59ac398de9a7421b54e4a207e", size = 11896527, upload-time = "2025-09-19T00:10:55.791Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/73/a05b2bbaa7005f4642fcfe40fb73f2b4fb6bb44229bd585b5878e9a87ef8/mypy-1.18.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:448acd386266989ef11662ce3c8011fd2a7b632e0ec7d61a98edd8e27472225b", size = 12507004, upload-time = "2025-09-19T00:11:05.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/01/f6e4b9f0d031c11ccbd6f17da26564f3a0f3c4155af344006434b0a05a9d/mypy-1.18.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9e171c465ad3901dc652643ee4bffa8e9fef4d7d0eece23b428908c77a76a66", size = 13245947, upload-time = "2025-09-19T00:10:46.923Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/97/19727e7499bfa1ae0773d06afd30ac66a58ed7437d940c70548634b24185/mypy-1.18.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:592ec214750bc00741af1f80cbf96b5013d81486b7bb24cb052382c19e40b428", size = 13499217, upload-time = "2025-09-19T00:09:39.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/4f/90dc8c15c1441bf31cf0f9918bb077e452618708199e530f4cbd5cede6ff/mypy-1.18.2-cp310-cp310-win_amd64.whl", hash = "sha256:7fb95f97199ea11769ebe3638c29b550b5221e997c63b14ef93d2e971606ebed", size = 9766753, upload-time = "2025-09-19T00:10:49.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/87/cafd3ae563f88f94eec33f35ff722d043e09832ea8530ef149ec1efbaf08/mypy-1.18.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:807d9315ab9d464125aa9fcf6d84fde6e1dc67da0b6f80e7405506b8ac72bc7f", size = 12731198, upload-time = "2025-09-19T00:09:44.857Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/e0/1e96c3d4266a06d4b0197ace5356d67d937d8358e2ee3ffac71faa843724/mypy-1.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:776bb00de1778caf4db739c6e83919c1d85a448f71979b6a0edd774ea8399341", size = 11817879, upload-time = "2025-09-19T00:09:47.131Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/ef/0c9ba89eb03453e76bdac5a78b08260a848c7bfc5d6603634774d9cd9525/mypy-1.18.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1379451880512ffce14505493bd9fe469e0697543717298242574882cf8cdb8d", size = 12427292, upload-time = "2025-09-19T00:10:22.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/52/ec4a061dd599eb8179d5411d99775bec2a20542505988f40fc2fee781068/mypy-1.18.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1331eb7fd110d60c24999893320967594ff84c38ac6d19e0a76c5fd809a84c86", size = 13163750, upload-time = "2025-09-19T00:09:51.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/5f/2cf2ceb3b36372d51568f2208c021870fe7834cf3186b653ac6446511839/mypy-1.18.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ca30b50a51e7ba93b00422e486cbb124f1c56a535e20eff7b2d6ab72b3b2e37", size = 13351827, upload-time = "2025-09-19T00:09:58.311Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/7d/2697b930179e7277529eaaec1513f8de622818696857f689e4a5432e5e27/mypy-1.18.2-cp311-cp311-win_amd64.whl", hash = "sha256:664dc726e67fa54e14536f6e1224bcfce1d9e5ac02426d2326e2bb4e081d1ce8", size = 9757983, upload-time = "2025-09-19T00:10:09.071Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/06/dfdd2bc60c66611dd8335f463818514733bc763e4760dee289dcc33df709/mypy-1.18.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:33eca32dd124b29400c31d7cf784e795b050ace0e1f91b8dc035672725617e34", size = 12908273, upload-time = "2025-09-19T00:10:58.321Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/14/6a9de6d13a122d5608e1a04130724caf9170333ac5a924e10f670687d3eb/mypy-1.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3c47adf30d65e89b2dcd2fa32f3aeb5e94ca970d2c15fcb25e297871c8e4764", size = 11920910, upload-time = "2025-09-19T00:10:20.043Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/a9/b29de53e42f18e8cc547e38daa9dfa132ffdc64f7250e353f5c8cdd44bee/mypy-1.18.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d6c838e831a062f5f29d11c9057c6009f60cb294fea33a98422688181fe2893", size = 12465585, upload-time = "2025-09-19T00:10:33.005Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/ae/6c3d2c7c61ff21f2bee938c917616c92ebf852f015fb55917fd6e2811db2/mypy-1.18.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01199871b6110a2ce984bde85acd481232d17413868c9807e95c1b0739a58914", size = 13348562, upload-time = "2025-09-19T00:10:11.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/31/aec68ab3b4aebdf8f36d191b0685d99faa899ab990753ca0fee60fb99511/mypy-1.18.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a2afc0fa0b0e91b4599ddfe0f91e2c26c2b5a5ab263737e998d6817874c5f7c8", size = 13533296, upload-time = "2025-09-19T00:10:06.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/83/abcb3ad9478fca3ebeb6a5358bb0b22c95ea42b43b7789c7fb1297ca44f4/mypy-1.18.2-cp312-cp312-win_amd64.whl", hash = "sha256:d8068d0afe682c7c4897c0f7ce84ea77f6de953262b12d07038f4d296d547074", size = 9828828, upload-time = "2025-09-19T00:10:28.203Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/04/7f462e6fbba87a72bc8097b93f6842499c428a6ff0c81dd46948d175afe8/mypy-1.18.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:07b8b0f580ca6d289e69209ec9d3911b4a26e5abfde32228a288eb79df129fcc", size = 12898728, upload-time = "2025-09-19T00:10:01.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/5b/61ed4efb64f1871b41fd0b82d29a64640f3516078f6c7905b68ab1ad8b13/mypy-1.18.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ed4482847168439651d3feee5833ccedbf6657e964572706a2adb1f7fa4dfe2e", size = 11910758, upload-time = "2025-09-19T00:10:42.607Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/46/d297d4b683cc89a6e4108c4250a6a6b717f5fa96e1a30a7944a6da44da35/mypy-1.18.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3ad2afadd1e9fea5cf99a45a822346971ede8685cc581ed9cd4d42eaf940986", size = 12475342, upload-time = "2025-09-19T00:11:00.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/45/4798f4d00df13eae3bfdf726c9244bcb495ab5bd588c0eed93a2f2dd67f3/mypy-1.18.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a431a6f1ef14cf8c144c6b14793a23ec4eae3db28277c358136e79d7d062f62d", size = 13338709, upload-time = "2025-09-19T00:11:03.358Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/09/479f7358d9625172521a87a9271ddd2441e1dab16a09708f056e97007207/mypy-1.18.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7ab28cc197f1dd77a67e1c6f35cd1f8e8b73ed2217e4fc005f9e6a504e46e7ba", size = 13529806, upload-time = "2025-09-19T00:10:26.073Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/cf/ac0f2c7e9d0ea3c75cd99dff7aec1c9df4a1376537cb90e4c882267ee7e9/mypy-1.18.2-cp313-cp313-win_amd64.whl", hash = "sha256:0e2785a84b34a72ba55fb5daf079a1003a34c05b22238da94fcae2bbe46f3544", size = 9833262, upload-time = "2025-09-19T00:10:40.035Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/0c/7d5300883da16f0063ae53996358758b2a2df2a09c72a5061fa79a1f5006/mypy-1.18.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:62f0e1e988ad41c2a110edde6c398383a889d95b36b3e60bcf155f5164c4fdce", size = 12893775, upload-time = "2025-09-19T00:10:03.814Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/df/2cffbf25737bdb236f60c973edf62e3e7b4ee1c25b6878629e88e2cde967/mypy-1.18.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8795a039bab805ff0c1dfdb8cd3344642c2b99b8e439d057aba30850b8d3423d", size = 11936852, upload-time = "2025-09-19T00:10:51.631Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/50/34059de13dd269227fb4a03be1faee6e2a4b04a2051c82ac0a0b5a773c9a/mypy-1.18.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ca1e64b24a700ab5ce10133f7ccd956a04715463d30498e64ea8715236f9c9c", size = 12480242, upload-time = "2025-09-19T00:11:07.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/11/040983fad5132d85914c874a2836252bbc57832065548885b5bb5b0d4359/mypy-1.18.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d924eef3795cc89fecf6bedc6ed32b33ac13e8321344f6ddbf8ee89f706c05cb", size = 13326683, upload-time = "2025-09-19T00:09:55.572Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/ba/89b2901dd77414dd7a8c8729985832a5735053be15b744c18e4586e506ef/mypy-1.18.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20c02215a080e3a2be3aa50506c67242df1c151eaba0dcbc1e4e557922a26075", size = 13514749, upload-time = "2025-09-19T00:10:44.827Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/bc/cc98767cffd6b2928ba680f3e5bc969c4152bf7c2d83f92f5a504b92b0eb/mypy-1.18.2-cp314-cp314-win_amd64.whl", hash = "sha256:749b5f83198f1ca64345603118a6f01a4e99ad4bf9d103ddc5a3200cc4614adf", size = 9982959, upload-time = "2025-09-19T00:10:37.344Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/a6/490ff491d8ecddf8ab91762d4f67635040202f76a44171420bcbe38ceee5/mypy-1.18.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25a9c8fb67b00599f839cf472713f54249a62efd53a54b565eb61956a7e3296b", size = 12807230, upload-time = "2025-09-19T00:09:49.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/2e/60076fc829645d167ece9e80db9e8375648d210dab44cc98beb5b322a826/mypy-1.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2b9c7e284ee20e7598d6f42e13ca40b4928e6957ed6813d1ab6348aa3f47133", size = 11895666, upload-time = "2025-09-19T00:10:53.678Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/4a/1e2880a2a5dda4dc8d9ecd1a7e7606bc0b0e14813637eeda40c38624e037/mypy-1.18.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6985ed057513e344e43a26cc1cd815c7a94602fb6a3130a34798625bc2f07b6", size = 12499608, upload-time = "2025-09-19T00:09:36.204Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/81/a117f1b73a3015b076b20246b1f341c34a578ebd9662848c6b80ad5c4138/mypy-1.18.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f27105f1525ec024b5c630c0b9f36d5c1cc4d447d61fe51ff4bd60633f47ac", size = 13244551, upload-time = "2025-09-19T00:10:17.531Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/61/b9f48e1714ce87c7bf0358eb93f60663740ebb08f9ea886ffc670cea7933/mypy-1.18.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:030c52d0ea8144e721e49b1f68391e39553d7451f0c3f8a7565b59e19fcb608b", size = 13491552, upload-time = "2025-09-19T00:10:13.753Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/66/b2c0af3b684fa80d1b27501a8bdd3d2daa467ea3992a8aa612f5ca17c2db/mypy-1.18.2-cp39-cp39-win_amd64.whl", hash = "sha256:aa5e07ac1a60a253445797e42b8b2963c9675563a94f11291ab40718b016a7a0", size = 9765635, upload-time = "2025-09-19T00:10:30.993Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/e3/be76d87158ebafa0309946c4a73831974d4d6ab4f4ef40c3b53a385a66fd/mypy-1.18.2-py3-none-any.whl", hash = "sha256:22a1748707dd62b58d2ae53562ffc4d7f8bcc727e8ac7cbc69c053ddc874d47e", size = 2352367, upload-time = "2025-09-19T00:10:15.489Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/8f/55fb488c2b7dabd76e3f30c10f7ab0f6190c1fcbc3e97b1e588ec625bbe2/mypy-1.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6148ede033982a8c5ca1143de34c71836a09f105068aaa8b7d5edab2b053e6c8", size = 13093239, upload-time = "2025-11-28T15:45:11.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/1b/278beea978456c56b3262266274f335c3ba5ff2c8108b3b31bec1ffa4c1d/mypy-1.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a9ac09e52bb0f7fb912f5d2a783345c72441a08ef56ce3e17c1752af36340a39", size = 12156128, upload-time = "2025-11-28T15:46:02.566Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/f8/e06f951902e136ff74fd7a4dc4ef9d884faeb2f8eb9c49461235714f079f/mypy-1.19.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f7254c15ab3f8ed68f8e8f5cbe88757848df793e31c36aaa4d4f9783fd08ab", size = 12753508, upload-time = "2025-11-28T15:44:47.538Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/5a/d035c534ad86e09cee274d53cf0fd769c0b29ca6ed5b32e205be3c06878c/mypy-1.19.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318ba74f75899b0e78b847d8c50821e4c9637c79d9a59680fc1259f29338cb3e", size = 13507553, upload-time = "2025-11-28T15:44:39.26Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/17/c4a5498e00071ef29e483a01558b285d086825b61cf1fb2629fbdd019d94/mypy-1.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf7d84f497f78b682edd407f14a7b6e1a2212b433eedb054e2081380b7395aa3", size = 13792898, upload-time = "2025-11-28T15:44:31.102Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/f6/bb542422b3ee4399ae1cdc463300d2d91515ab834c6233f2fd1d52fa21e0/mypy-1.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:c3385246593ac2b97f155a0e9639be906e73534630f663747c71908dfbf26134", size = 10048835, upload-time = "2025-11-28T15:48:15.744Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/d2/010fb171ae5ac4a01cc34fbacd7544531e5ace95c35ca166dd8fd1b901d0/mypy-1.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a31e4c28e8ddb042c84c5e977e28a21195d086aaffaf08b016b78e19c9ef8106", size = 13010563, upload-time = "2025-11-28T15:48:23.975Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/6b/63f095c9f1ce584fdeb595d663d49e0980c735a1d2004720ccec252c5d47/mypy-1.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34ec1ac66d31644f194b7c163d7f8b8434f1b49719d403a5d26c87fff7e913f7", size = 12077037, upload-time = "2025-11-28T15:47:51.582Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/83/6cb93d289038d809023ec20eb0b48bbb1d80af40511fa077da78af6ff7c7/mypy-1.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb64b0ba5980466a0f3f9990d1c582bcab8db12e29815ecb57f1408d99b4bff7", size = 12680255, upload-time = "2025-11-28T15:46:57.628Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/db/d217815705987d2cbace2edd9100926196d6f85bcb9b5af05058d6e3c8ad/mypy-1.19.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:120cffe120cca5c23c03c77f84abc0c14c5d2e03736f6c312480020082f1994b", size = 13421472, upload-time = "2025-11-28T15:47:59.655Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/51/d2beaca7c497944b07594f3f8aad8d2f0e8fc53677059848ae5d6f4d193e/mypy-1.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a500ab5c444268a70565e374fc803972bfd1f09545b13418a5174e29883dab7", size = 13651823, upload-time = "2025-11-28T15:45:29.318Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/d1/7883dcf7644db3b69490f37b51029e0870aac4a7ad34d09ceae709a3df44/mypy-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:c14a98bc63fd867530e8ec82f217dae29d0550c86e70debc9667fff1ec83284e", size = 10049077, upload-time = "2025-11-28T15:45:39.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/7e/1afa8fb188b876abeaa14460dc4983f909aaacaa4bf5718c00b2c7e0b3d5/mypy-1.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fb3115cb8fa7c5f887c8a8d81ccdcb94cff334684980d847e5a62e926910e1d", size = 13207728, upload-time = "2025-11-28T15:46:26.463Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/13/f103d04962bcbefb1644f5ccb235998b32c337d6c13145ea390b9da47f3e/mypy-1.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3e19e3b897562276bb331074d64c076dbdd3e79213f36eed4e592272dabd760", size = 12202945, upload-time = "2025-11-28T15:48:49.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/93/a86a5608f74a22284a8ccea8592f6e270b61f95b8588951110ad797c2ddd/mypy-1.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9d491295825182fba01b6ffe2c6fe4e5a49dbf4e2bb4d1217b6ced3b4797bc6", size = 12718673, upload-time = "2025-11-28T15:47:37.193Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/58/cf08fff9ced0423b858f2a7495001fda28dc058136818ee9dffc31534ea9/mypy-1.19.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6016c52ab209919b46169651b362068f632efcd5eb8ef9d1735f6f86da7853b2", size = 13608336, upload-time = "2025-11-28T15:48:32.625Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/ed/9c509105c5a6d4b73bb08733102a3ea62c25bc02c51bca85e3134bf912d3/mypy-1.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f188dcf16483b3e59f9278c4ed939ec0254aa8a60e8fc100648d9ab5ee95a431", size = 13833174, upload-time = "2025-11-28T15:45:48.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/71/01939b66e35c6f8cb3e6fdf0b657f0fd24de2f8ba5e523625c8e72328208/mypy-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:0e3c3d1e1d62e678c339e7ade72746a9e0325de42cd2cccc51616c7b2ed1a018", size = 10112208, upload-time = "2025-11-28T15:46:41.702Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/0d/a1357e6bb49e37ce26fcf7e3cc55679ce9f4ebee0cd8b6ee3a0e301a9210/mypy-1.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7686ed65dbabd24d20066f3115018d2dce030d8fa9db01aa9f0a59b6813e9f9e", size = 13191993, upload-time = "2025-11-28T15:47:22.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/75/8e5d492a879ec4490e6ba664b5154e48c46c85b5ac9785792a5ec6a4d58f/mypy-1.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fd4a985b2e32f23bead72e2fb4bbe5d6aceee176be471243bd831d5b2644672d", size = 12174411, upload-time = "2025-11-28T15:44:55.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/31/ad5dcee9bfe226e8eaba777e9d9d251c292650130f0450a280aec3485370/mypy-1.19.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc51a5b864f73a3a182584b1ac75c404396a17eced54341629d8bdcb644a5bba", size = 12727751, upload-time = "2025-11-28T15:44:14.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/06/b6b8994ce07405f6039701f4b66e9d23f499d0b41c6dd46ec28f96d57ec3/mypy-1.19.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37af5166f9475872034b56c5efdcf65ee25394e9e1d172907b84577120714364", size = 13593323, upload-time = "2025-11-28T15:46:34.699Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/b1/126e274484cccdf099a8e328d4fda1c7bdb98a5e888fa6010b00e1bbf330/mypy-1.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:510c014b722308c9bd377993bcbf9a07d7e0692e5fa8fc70e639c1eb19fc6bee", size = 13818032, upload-time = "2025-11-28T15:46:18.286Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/56/53a8f70f562dfc466c766469133a8a4909f6c0012d83993143f2a9d48d2d/mypy-1.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:cabbee74f29aa9cd3b444ec2f1e4fa5a9d0d746ce7567a6a609e224429781f53", size = 10120644, upload-time = "2025-11-28T15:47:43.99Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/f4/7751f32f56916f7f8c229fe902cbdba3e4dd3f3ea9e8b872be97e7fc546d/mypy-1.19.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f2e36bed3c6d9b5f35d28b63ca4b727cb0228e480826ffc8953d1892ddc8999d", size = 13185236, upload-time = "2025-11-28T15:45:20.696Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/31/871a9531f09e78e8d145032355890384f8a5b38c95a2c7732d226b93242e/mypy-1.19.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a18d8abdda14035c5718acb748faec09571432811af129bf0d9e7b2d6699bf18", size = 12213902, upload-time = "2025-11-28T15:46:10.117Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/b8/af221910dd40eeefa2077a59107e611550167b9994693fc5926a0b0f87c0/mypy-1.19.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75e60aca3723a23511948539b0d7ed514dda194bc3755eae0bfc7a6b4887aa7", size = 12738600, upload-time = "2025-11-28T15:44:22.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/9f/c39e89a3e319c1d9c734dedec1183b2cc3aefbab066ec611619002abb932/mypy-1.19.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f44f2ae3c58421ee05fe609160343c25f70e3967f6e32792b5a78006a9d850f", size = 13592639, upload-time = "2025-11-28T15:48:08.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/6d/ffaf5f01f5e284d9033de1267e6c1b8f3783f2cf784465378a86122e884b/mypy-1.19.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:63ea6a00e4bd6822adbfc75b02ab3653a17c02c4347f5bb0cf1d5b9df3a05835", size = 13799132, upload-time = "2025-11-28T15:47:06.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/b0/c33921e73aaa0106224e5a34822411bea38046188eb781637f5a5b07e269/mypy-1.19.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ad925b14a0bb99821ff6f734553294aa6a3440a8cb082fe1f5b84dfb662afb1", size = 10269832, upload-time = "2025-11-28T15:47:29.392Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/59/a7748ef43446163a93159d82bb270c6c4f3d94c1fcbdd2a29a7e439e74d7/mypy-1.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0dde5cb375cb94deff0d4b548b993bec52859d1651e073d63a1386d392a95495", size = 13094255, upload-time = "2025-11-28T15:47:14.282Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/0b/92ebf5abc83f559a35dcba3bd9227726b04b04178f1e521f38e647b930eb/mypy-1.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1cf9c59398db1c68a134b0b5354a09a1e124523f00bacd68e553b8bd16ff3299", size = 12161414, upload-time = "2025-11-28T15:45:03.302Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/03/19412f0a786722055a52c01b4c5d71e5b5443a89f6bbcdd445408240e217/mypy-1.19.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3210d87b30e6af9c8faed61be2642fcbe60ef77cec64fa1ef810a630a4cf671c", size = 12756782, upload-time = "2025-11-28T15:46:49.522Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/85/395d53c9098b251414b0448cdadcd3277523ff36f5abda6d26ff945dbdb3/mypy-1.19.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2c1101ab41d01303103ab6ef82cbbfedb81c1a060c868fa7cc013d573d37ab5", size = 13503492, upload-time = "2025-11-28T15:48:57.339Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/33/1ab1113e3778617ae7aba66b4b537f90512bd279ff65b6c984fb91fbb2d3/mypy-1.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ea4fd21bb48f0da49e6d3b37ef6bd7e8228b9fe41bbf4d80d9364d11adbd43c", size = 13787703, upload-time = "2025-11-28T15:48:41.286Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/2d/8b0821b3e0d538de1ad96c86502256c7326274d5cb74e0b373efaada273f/mypy-1.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:16f76ff3f3fd8137aadf593cb4607d82634fca675e8211ad75c43d86033ee6c6", size = 10049225, upload-time = "2025-11-28T15:45:55.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/0e/fe228ed5aeab470c6f4eb82481837fadb642a5aa95cc8215fd2214822c10/mypy-1.19.0-py3-none-any.whl", hash = "sha256:0c01c99d626380752e527d5ce8e69ffbba2046eb8a060db0329690849cf9b6f9", size = 2469714, upload-time = "2025-11-28T15:45:33.22Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1307,7 +1391,7 @@ mockupdb = [{ name = "mockupdb", git = "https://github.com/mongodb-labs/mongo-mo
|
||||
perf = [{ name = "simplejson", specifier = ">=3.17.0" }]
|
||||
pip = [{ name = "pip" }]
|
||||
typing = [
|
||||
{ name = "mypy", specifier = "==1.18.2" },
|
||||
{ name = "mypy", specifier = "==1.19.0" },
|
||||
{ name = "pip" },
|
||||
{ name = "pyright", specifier = "==1.1.407" },
|
||||
{ name = "typing-extensions" },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user