From 091d8d9f99556267f90ed57625d0328d45283e6e Mon Sep 17 00:00:00 2001 From: Benedikt Bartscher Date: Sat, 7 Feb 2026 00:56:04 +0100 Subject: [PATCH 1/3] try orjson --- pyproject.toml | 1 + reflex/app.py | 10 ++-- reflex/compiler/templates.py | 9 ++-- reflex/plugins/shared_tailwind.py | 27 +++++----- reflex/utils/exec.py | 8 +-- reflex/utils/format.py | 58 ++++++++++++++++++++- reflex/utils/frontend_skeleton.py | 4 +- reflex/utils/path_ops.py | 9 ++-- reflex/utils/prerequisites.py | 8 +-- reflex/utils/pyi_generator.py | 8 +-- reflex/utils/serializers.py | 11 ++-- reflex/utils/telemetry.py | 8 +-- reflex/vars/base.py | 5 +- reflex/vars/number.py | 6 +-- reflex/vars/sequence.py | 8 +-- tests/units/test_prerequisites.py | 8 +-- uv.lock | 87 ++++++++++++++++++++++++++++++- 17 files changed, 210 insertions(+), 65 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e56b97ceccd..58f1ed4a173 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,6 +57,7 @@ db = [ "sqlmodel >=0.0.24,<0.1", ] monitoring = ["pyleak >=0.1.14,<1.0"] +orjson = ["orjson >=3.10,<4.0"] [project.urls] homepage = "https://reflex.dev" diff --git a/reflex/app.py b/reflex/app.py index 4ff412ef863..f0ff5f8120f 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -546,7 +546,7 @@ def _setup_state(self) -> None: ping_timeout=environment.REFLEX_SOCKET_TIMEOUT.get(), json=SimpleNamespace( dumps=staticmethod(format.json_dumps), - loads=staticmethod(json.loads), + loads=staticmethod(format.orjson_loads), ), allow_upgrades=False, transports=[config.transport], @@ -1170,8 +1170,8 @@ def get_compilation_time() -> str: if not dry_run and not should_compile and backend_dir.exists(): stateful_pages_marker = backend_dir / constants.Dirs.STATEFUL_PAGES if stateful_pages_marker.exists(): - with stateful_pages_marker.open("r") as f: - stateful_pages = json.load(f) + with stateful_pages_marker.open("rb") as f: + stateful_pages = format.orjson_loads(f.read()) for route in stateful_pages: console.debug(f"BE Evaluating stateful page: {route}") self._compile_page(route, save_page=False) @@ -1546,7 +1546,7 @@ def _write_stateful_pages_marker(self): ) stateful_pages_marker.parent.mkdir(parents=True, exist_ok=True) with stateful_pages_marker.open("w") as f: - json.dump(list(self._stateful_pages), f) + f.write(format.orjson_dumps(list(self._stateful_pages))) def add_all_routes_endpoint(self): """Add an endpoint to the app that returns all the routes.""" @@ -2172,7 +2172,7 @@ async def on_event(self, sid: str, data: Any): f" Event data: {fields}" ) try: - fields = json.loads(fields) + fields = format.orjson_loads(fields) except json.JSONDecodeError as ex: msg = f"Failed to deserialize event data: {fields}." raise exceptions.EventDeserializationError(msg) from ex diff --git a/reflex/compiler/templates.py b/reflex/compiler/templates.py index 2abcb6dd533..e751094ee48 100644 --- a/reflex/compiler/templates.py +++ b/reflex/compiler/templates.py @@ -2,14 +2,13 @@ from __future__ import annotations -import json from collections.abc import Iterable, Mapping from typing import TYPE_CHECKING, Any, Literal from reflex import constants from reflex.constants import Hooks from reflex.constants.state import CAMEL_CASE_MEMO_MARKER -from reflex.utils.format import format_state_name, json_dumps +from reflex.utils.format import format_state_name, json_dumps, orjson_dumps from reflex.vars.base import VarData if TYPE_CHECKING: @@ -354,11 +353,11 @@ def context_template( export const DispatchContext = createContext(null); export const StateContexts = {{{state_contexts_str}}}; export const EventLoopContext = createContext(null); -export const clientStorage = {"{}" if client_storage is None else json.dumps(client_storage)} +export const clientStorage = {"{}" if client_storage is None else orjson_dumps(client_storage)} {state_str} -export const isDevMode = {json.dumps(is_dev_mode)}; +export const isDevMode = {orjson_dumps(is_dev_mode)}; export function UploadFilesProvider({{ children }}) {{ const [filesById, setFilesById] = useState({{}}) @@ -486,7 +485,7 @@ def package_json_template( Returns: Rendered package.json content as string. """ - return json.dumps({ + return orjson_dumps({ "name": "reflex", "type": "module", "scripts": scripts, diff --git a/reflex/plugins/shared_tailwind.py b/reflex/plugins/shared_tailwind.py index 0ea8a6d394a..a3fe0ebc78d 100644 --- a/reflex/plugins/shared_tailwind.py +++ b/reflex/plugins/shared_tailwind.py @@ -91,7 +91,7 @@ def tailwind_config_js_template( Returns: The Tailwind config template. """ - import json + from reflex.utils.format import orjson_dumps # Extract parameters plugins = kwargs.get("plugins", []) @@ -113,7 +113,8 @@ def tailwind_config_js_template( # Generate import statements for destructured imports import_lines = "\n".join([ - f"import {{ {imp['name']} }} from {json.dumps(imp['from'])};" for imp in imports + f"import {{ {imp['name']} }} from {orjson_dumps(imp['from'])};" + for imp in imports ]) # Generate plugin imports @@ -121,15 +122,15 @@ def tailwind_config_js_template( for i, plugin in enumerate(plugins, 1): if isinstance(plugin, Mapping) and "call" not in plugin: plugin_imports.append( - f"import plugin{i} from {json.dumps(plugin['name'])};" + f"import plugin{i} from {orjson_dumps(plugin['name'])};" ) elif not isinstance(plugin, Mapping): - plugin_imports.append(f"import plugin{i} from {json.dumps(plugin)};") + plugin_imports.append(f"import plugin{i} from {orjson_dumps(plugin)};") plugin_imports_lines = "\n".join(plugin_imports) presets_imports_lines = "\n".join([ - f"import preset{i} from {json.dumps(preset)};" + f"import preset{i} from {orjson_dumps(preset)};" for i, preset in enumerate(presets, 1) ]) @@ -139,7 +140,7 @@ def tailwind_config_js_template( if isinstance(plugin, Mapping) and "call" in plugin: args_part = "" if "args" in plugin: - args_part = json.dumps(plugin["args"]) + args_part = orjson_dumps(plugin["args"]) plugin_list.append(f"{plugin['call']}({args_part})") else: plugin_list.append(f"plugin{i}") @@ -154,13 +155,13 @@ def tailwind_config_js_template( {presets_imports_lines} export default {{ - content: {json.dumps(content or default_content)}, - theme: {json.dumps(theme or {})}, - {f"darkMode: {json.dumps(dark_mode)}," if dark_mode is not None else ""} - {f"corePlugins: {json.dumps(core_plugins)}," if core_plugins is not None else ""} - {f"importants: {json.dumps(important)}," if important is not None else ""} - {f"prefix: {json.dumps(prefix)}," if prefix is not None else ""} - {f"separator: {json.dumps(separator)}," if separator is not None else ""} + content: {orjson_dumps(content or default_content)}, + theme: {orjson_dumps(theme or {})}, + {f"darkMode: {orjson_dumps(dark_mode)}," if dark_mode is not None else ""} + {f"corePlugins: {orjson_dumps(core_plugins)}," if core_plugins is not None else ""} + {f"importants: {orjson_dumps(important)}," if important is not None else ""} + {f"prefix: {orjson_dumps(prefix)}," if prefix is not None else ""} + {f"separator: {orjson_dumps(separator)}," if separator is not None else ""} {f"presets: [{', '.join(f'preset{i}' for i in range(1, len(presets) + 1))}]," if presets else ""} plugins: [{plugin_use_str}] }}; diff --git a/reflex/utils/exec.py b/reflex/utils/exec.py index ac6f720cda8..4a3ca6be7be 100644 --- a/reflex/utils/exec.py +++ b/reflex/utils/exec.py @@ -4,7 +4,6 @@ import hashlib import importlib.util -import json import os import platform import re @@ -21,6 +20,7 @@ from reflex.environment import environment from reflex.utils import console, path_ops from reflex.utils.decorator import once +from reflex.utils.format import orjson_dumps, orjson_loads from reflex.utils.misc import get_module_path from reflex.utils.prerequisites import get_web_dir @@ -37,11 +37,11 @@ def get_package_json_and_hash(package_json_path: Path) -> tuple[PackageJson, str Returns: A tuple containing the content of package.json as a dictionary and its SHA-256 hash. """ - with package_json_path.open("r") as file: - json_data = json.load(file) + with package_json_path.open("rb") as file: + json_data = orjson_loads(file.read()) # Calculate the hash - json_string = json.dumps(json_data, sort_keys=True) + json_string = orjson_dumps(json_data, sort_keys=True) hash_object = hashlib.sha256(json_string.encode()) return (json_data, hash_object.hexdigest()) diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 3093e455d55..08c59031f52 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -498,7 +498,7 @@ def format_event(event_spec: EventSpec) -> str: name._js_expr, ( wrap( - json.dumps(val._js_expr).strip('"').replace("`", "\\`"), + orjson_dumps(val._js_expr).strip('"').replace("`", "\\`"), "`", ) if val._var_is_string @@ -686,6 +686,62 @@ def json_dumps(obj: Any, **kwargs) -> str: return json.dumps(obj, **kwargs) +def orjson_dumps(obj: Any, **kwargs) -> str: + """Serialize obj to a JSON string, using orjson when available. + + Translates common json.dumps kwargs (indent, sort_keys) into orjson + option flags. Falls back to stdlib json if orjson is not installed, + an unsupported kwarg is passed, or orjson raises TypeError. + + Args: + obj: The object to serialize. + kwargs: Optional keyword arguments (indent, sort_keys). + + Returns: + A JSON string. + """ + try: + import orjson + except ImportError: + return json.dumps(obj, **kwargs) + + option = 0 + if kwargs.pop("indent", None): + option |= orjson.OPT_INDENT_2 + if kwargs.pop("sort_keys", False): + option |= orjson.OPT_SORT_KEYS + kwargs.pop("ensure_ascii", None) # orjson always produces UTF-8 + + if kwargs: + # Fall back to stdlib json for unsupported kwargs. + return json.dumps(obj, **kwargs) + + try: + return orjson.dumps(obj, option=option or None).decode() + except TypeError: + # Fallback for types orjson can't handle (e.g. int > 64-bit). + return json.dumps(obj) + + +def orjson_loads(data: str | bytes) -> Any: + """Deserialize a JSON string or bytes, using orjson when available. + + Falls back to stdlib json.loads if orjson is not installed. + + Args: + data: JSON string or bytes to deserialize. + + Returns: + The deserialized Python object. + """ + try: + import orjson + except ImportError: + return json.loads(data) + + return orjson.loads(data) + + def collect_form_dict_names(form_dict: dict[str, Any]) -> dict[str, Any]: """Collapse keys with consecutive suffixes into a single list value. diff --git a/reflex/utils/frontend_skeleton.py b/reflex/utils/frontend_skeleton.py index 96ced280fe2..0d12a6553df 100644 --- a/reflex/utils/frontend_skeleton.py +++ b/reflex/utils/frontend_skeleton.py @@ -1,6 +1,5 @@ """This module provides utility functions to initialize the frontend skeleton.""" -import json import random import re from pathlib import Path @@ -10,6 +9,7 @@ from reflex.config import Config, get_config from reflex.environment import environment from reflex.utils import console, path_ops +from reflex.utils.format import orjson_dumps from reflex.utils.prerequisites import get_project_hash, get_web_dir from reflex.utils.registry import get_npm_registry @@ -164,7 +164,7 @@ def _update_react_router_config(config: Config, prerender_routes: bool = False): react_router_config["prerender"] = True react_router_config["build"] = constants.Dirs.BUILD_DIR - return f"export default {json.dumps(react_router_config)};" + return f"export default {orjson_dumps(react_router_config)};" def _compile_package_json(): diff --git a/reflex/utils/path_ops.py b/reflex/utils/path_ops.py index 152fac596fa..c17dd7ca075 100644 --- a/reflex/utils/path_ops.py +++ b/reflex/utils/path_ops.py @@ -2,7 +2,6 @@ from __future__ import annotations -import json import os import re import shutil @@ -11,6 +10,7 @@ from reflex.config import get_config from reflex.environment import environment +from reflex.utils.format import orjson_dumps, orjson_loads # Shorthand for join. join = os.linesep.join @@ -245,15 +245,14 @@ def update_json_file(file_path: str | Path, update_dict: dict[str, int | str]): # Read the existing json object from the file. json_object = {} if fp.stat().st_size: - with fp.open() as f: - json_object = json.load(f) + with fp.open("rb") as f: + json_object = orjson_loads(f.read()) # Update the json object with the new data. json_object.update(update_dict) # Write the updated json object to the file - with fp.open("w") as f: - json.dump(json_object, f, ensure_ascii=False) + fp.write_text(orjson_dumps(json_object)) def find_replace(directory: str | Path, find: str, replace: str): diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index 886d1dead96..5f754686741 100644 --- a/reflex/utils/prerequisites.py +++ b/reflex/utils/prerequisites.py @@ -6,7 +6,6 @@ import importlib import importlib.metadata import inspect -import json import random import re import sys @@ -24,6 +23,7 @@ from reflex.environment import environment from reflex.utils import console, net, path_ops from reflex.utils.decorator import once +from reflex.utils.format import orjson_loads from reflex.utils.misc import get_module_path if typing.TYPE_CHECKING: @@ -111,7 +111,7 @@ def get_or_set_last_reflex_version_check_datetime(): if not reflex_json_file.exists(): return None # Open and read the file - data = json.loads(reflex_json_file.read_text()) + data = orjson_loads(reflex_json_file.read_text()) last_version_check_datetime = data.get("last_version_check_datetime") if not last_version_check_datetime: data.update({"last_version_check_datetime": str(datetime.now())}) @@ -492,7 +492,7 @@ def get_project_hash(raise_on_fail: bool = False) -> int | None: json_file = get_web_dir() / constants.Reflex.JSON if not json_file.exists() and not raise_on_fail: return None - data = json.loads(json_file.read_text()) + data = orjson_loads(json_file.read_text()) return data.get("project_hash") @@ -558,7 +558,7 @@ def _is_app_compiled_with_same_reflex_version() -> bool: json_file = get_web_dir() / constants.Reflex.JSON if not json_file.exists(): return False - app_version = json.loads(json_file.read_text()).get("version") + app_version = orjson_loads(json_file.read_text()).get("version") return app_version == constants.Reflex.VERSION diff --git a/reflex/utils/pyi_generator.py b/reflex/utils/pyi_generator.py index 2c2f2eff822..c8e17d4c331 100644 --- a/reflex/utils/pyi_generator.py +++ b/reflex/utils/pyi_generator.py @@ -6,7 +6,6 @@ import contextlib import importlib import inspect -import json import logging import re import subprocess @@ -23,6 +22,7 @@ from reflex.components.component import Component from reflex.utils import types as rx_types +from reflex.utils.format import orjson_dumps, orjson_loads from reflex.vars.base import Var logger = logging.getLogger("pyi_generator") @@ -1301,7 +1301,7 @@ def scan_all( if pyi_hashes_file.exists(): pyi_hashes_file.write_text( - json.dumps( + orjson_dumps( dict( zip( [ @@ -1328,7 +1328,7 @@ def scan_all( pyi_hashes_file = pyi_hashes_parent / PYI_HASHES if pyi_hashes_file.exists(): - pyi_hashes = json.loads(pyi_hashes_file.read_text()) + pyi_hashes = orjson_loads(pyi_hashes_file.read_text()) for file_path, hashed_content in zip( file_paths, hashes, strict=False ): @@ -1338,7 +1338,7 @@ def scan_all( pyi_hashes[formatted_path] = hashed_content pyi_hashes_file.write_text( - json.dumps(pyi_hashes, indent=2, sort_keys=True) + "\n" + orjson_dumps(pyi_hashes, indent=2, sort_keys=True) + "\n" ) diff --git a/reflex/utils/serializers.py b/reflex/utils/serializers.py index 9693601ec5d..fe77fbac5d0 100644 --- a/reflex/utils/serializers.py +++ b/reflex/utils/serializers.py @@ -7,7 +7,6 @@ import decimal import functools import inspect -import json import warnings from collections.abc import Callable, Mapping, Sequence from datetime import date, datetime, time, timedelta @@ -474,7 +473,9 @@ def serialize_figure(figure: Figure) -> dict: Returns: The serialized figure. """ - return json.loads(str(to_json(figure))) + from reflex.utils.format import orjson_loads + + return orjson_loads(str(to_json(figure))) @serializer def serialize_template(template: layout.Template) -> dict: @@ -486,9 +487,11 @@ def serialize_template(template: layout.Template) -> dict: Returns: The serialized template. """ + from reflex.utils.format import orjson_loads + return { - "data": json.loads(str(to_json(template.data))), - "layout": json.loads(str(to_json(template.layout))), + "data": orjson_loads(str(to_json(template.data))), + "layout": orjson_loads(str(to_json(template.layout))), } diff --git a/reflex/utils/telemetry.py b/reflex/utils/telemetry.py index 87202215268..2b031aadf82 100644 --- a/reflex/utils/telemetry.py +++ b/reflex/utils/telemetry.py @@ -3,7 +3,6 @@ import asyncio import dataclasses import importlib.metadata -import json import multiprocessing import platform import warnings @@ -16,6 +15,7 @@ from reflex.utils import console, processes from reflex.utils.decorator import once, once_unless_none from reflex.utils.exceptions import ReflexError +from reflex.utils.format import orjson_dumps, orjson_loads from reflex.utils.js_runtimes import get_bun_version, get_node_version from reflex.utils.prerequisites import ensure_reflex_installation_id, get_project_hash @@ -60,7 +60,7 @@ def _retrieve_cpu_info() -> CpuInfo | None: cmd = 'powershell -Command "Get-CimInstance Win32_Processor | Select-Object -First 1 | Select-Object AddressWidth,Manufacturer,Name | ConvertTo-Json"' output = processes.execute_command_and_return_output(cmd) if output: - cpu_data = json.loads(output) + cpu_data = orjson_loads(output) cpuinfo["address_width"] = cpu_data["AddressWidth"] cpuinfo["manufacturer_id"] = cpu_data["Manufacturer"] cpuinfo["model_name"] = cpu_data["Name"] @@ -110,12 +110,12 @@ def get_cpu_info() -> CpuInfo | None: The CPU info. """ cpu_info_file = environment.REFLEX_DIR.get() / "cpu_info.json" - if cpu_info_file.exists() and (cpu_info := json.loads(cpu_info_file.read_text())): + if cpu_info_file.exists() and (cpu_info := orjson_loads(cpu_info_file.read_text())): return CpuInfo(**cpu_info) cpu_info = _retrieve_cpu_info() if cpu_info: cpu_info_file.parent.mkdir(parents=True, exist_ok=True) - cpu_info_file.write_text(json.dumps(dataclasses.asdict(cpu_info))) + cpu_info_file.write_text(orjson_dumps(dataclasses.asdict(cpu_info))) return cpu_info diff --git a/reflex/vars/base.py b/reflex/vars/base.py index 8a8f0e754d1..b47c14c9bcf 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -8,7 +8,6 @@ import datetime import functools import inspect -import json import re import string import uuid @@ -1179,7 +1178,9 @@ def _decode(self) -> Any: if isinstance(self, LiteralVar): return self._var_value try: - return json.loads(str(self)) + from reflex.utils.format import orjson_loads + + return orjson_loads(str(self)) except ValueError: return str(self) diff --git a/reflex/vars/number.py b/reflex/vars/number.py index 4f639c799d0..3a9aedcf724 100644 --- a/reflex/vars/number.py +++ b/reflex/vars/number.py @@ -4,7 +4,6 @@ import dataclasses import decimal -import json import math from collections.abc import Callable from typing import TYPE_CHECKING, Any, NoReturn, TypeVar, overload @@ -17,6 +16,7 @@ VarTypeError, VarValueError, ) +from reflex.utils.format import orjson_dumps from reflex.utils.imports import ImportDict, ImportVar from reflex.utils.types import safe_issubclass @@ -959,11 +959,11 @@ def json(self) -> str: PrimitiveUnserializableToJSONError: If the var is unserializable to JSON. """ if isinstance(self._var_value, decimal.Decimal): - return json.dumps(float(self._var_value)) + return orjson_dumps(float(self._var_value)) if math.isinf(self._var_value) or math.isnan(self._var_value): msg = f"No valid JSON representation for {self}" raise PrimitiveUnserializableToJSONError(msg) - return json.dumps(self._var_value) + return orjson_dumps(self._var_value) def __hash__(self) -> int: """Calculate the hash value of the object. diff --git a/reflex/vars/sequence.py b/reflex/vars/sequence.py index 3824ba8760b..9319ee1dff2 100644 --- a/reflex/vars/sequence.py +++ b/reflex/vars/sequence.py @@ -6,7 +6,6 @@ import dataclasses import decimal import inspect -import json import re from collections.abc import Iterable, Mapping, Sequence from typing import TYPE_CHECKING, Any, Literal, TypeVar, get_args, overload @@ -17,6 +16,7 @@ from reflex.constants.base import REFLEX_VAR_OPENING_TAG from reflex.utils import types from reflex.utils.exceptions import VarTypeError +from reflex.utils.format import orjson_dumps from reflex.utils.types import GenericType, get_origin from .base import ( @@ -1264,7 +1264,7 @@ def create( ) return LiteralStringVar( - _js_expr=json.dumps(value), + _js_expr=orjson_dumps(value), _var_type=_var_type, _var_data=_var_data, _var_value=value, @@ -1284,7 +1284,7 @@ def json(self) -> str: Returns: The JSON representation of the var. """ - return json.dumps(self._var_value) + return orjson_dumps(self._var_value) @dataclasses.dataclass( @@ -1842,6 +1842,6 @@ def json(self) -> str: Returns: The JSON representation of the var. """ - return json.dumps( + return orjson_dumps( list(self._var_value), ) diff --git a/tests/units/test_prerequisites.py b/tests/units/test_prerequisites.py index 131904e964c..f0c7556af8c 100644 --- a/tests/units/test_prerequisites.py +++ b/tests/units/test_prerequisites.py @@ -27,7 +27,7 @@ app_name="test", ), False, - 'export default {"basename": "/", "future": {"unstable_optimizeDeps": true}, "ssr": false};', + 'export default {"basename":"/","future":{"unstable_optimizeDeps":true},"ssr":false};', ), ( Config( @@ -35,7 +35,7 @@ static_page_generation_timeout=30, ), False, - 'export default {"basename": "/", "future": {"unstable_optimizeDeps": true}, "ssr": false};', + 'export default {"basename":"/","future":{"unstable_optimizeDeps":true},"ssr":false};', ), ( Config( @@ -43,14 +43,14 @@ frontend_path="/test", ), False, - 'export default {"basename": "/test/", "future": {"unstable_optimizeDeps": true}, "ssr": false};', + 'export default {"basename":"/test/","future":{"unstable_optimizeDeps":true},"ssr":false};', ), ( Config( app_name="test", ), True, - 'export default {"basename": "/", "future": {"unstable_optimizeDeps": true}, "ssr": false, "prerender": true, "build": "build"};', + 'export default {"basename":"/","future":{"unstable_optimizeDeps":true},"ssr":false,"prerender":true,"build":"build"};', ), ], ) diff --git a/uv.lock b/uv.lock index 04c0eb503e6..456df9e58ac 100644 --- a/uv.lock +++ b/uv.lock @@ -1057,6 +1057,87 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/c7/b801bf98514b6ae6475e941ac05c58e6411dd863ea92916bfd6d510b08c1/numpy-2.4.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:4f1b68ff47680c2925f8063402a693ede215f0257f02596b1318ecdfb1d79e33", size = 12492579, upload-time = "2026-01-10T06:44:57.094Z" }, ] +[[package]] +name = "orjson" +version = "3.11.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/1a/a373746fa6d0e116dd9e54371a7b54622c44d12296d5d0f3ad5e3ff33490/orjson-3.11.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174", size = 229140, upload-time = "2026-02-02T15:37:06.082Z" }, + { url = "https://files.pythonhosted.org/packages/52/a2/fa129e749d500f9b183e8a3446a193818a25f60261e9ce143ad61e975208/orjson-3.11.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67", size = 128670, upload-time = "2026-02-02T15:37:08.002Z" }, + { url = "https://files.pythonhosted.org/packages/08/93/1e82011cd1e0bd051ef9d35bed1aa7fb4ea1f0a055dc2c841b46b43a9ebd/orjson-3.11.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11", size = 123832, upload-time = "2026-02-02T15:37:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d8/a26b431ef962c7d55736674dddade876822f3e33223c1f47a36879350d04/orjson-3.11.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc", size = 129171, upload-time = "2026-02-02T15:37:11.112Z" }, + { url = "https://files.pythonhosted.org/packages/a7/19/f47819b84a580f490da260c3ee9ade214cf4cf78ac9ce8c1c758f80fdfc9/orjson-3.11.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16", size = 141967, upload-time = "2026-02-02T15:37:12.282Z" }, + { url = "https://files.pythonhosted.org/packages/5b/cd/37ece39a0777ba077fdcdbe4cccae3be8ed00290c14bf8afdc548befc260/orjson-3.11.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222", size = 130991, upload-time = "2026-02-02T15:37:13.465Z" }, + { url = "https://files.pythonhosted.org/packages/8f/ed/f2b5d66aa9b6b5c02ff5f120efc7b38c7c4962b21e6be0f00fd99a5c348e/orjson-3.11.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa", size = 133674, upload-time = "2026-02-02T15:37:14.694Z" }, + { url = "https://files.pythonhosted.org/packages/c4/6e/baa83e68d1aa09fa8c3e5b2c087d01d0a0bd45256de719ed7bc22c07052d/orjson-3.11.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e", size = 138722, upload-time = "2026-02-02T15:37:16.501Z" }, + { url = "https://files.pythonhosted.org/packages/0c/47/7f8ef4963b772cd56999b535e553f7eb5cd27e9dd6c049baee6f18bfa05d/orjson-3.11.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2", size = 409056, upload-time = "2026-02-02T15:37:17.895Z" }, + { url = "https://files.pythonhosted.org/packages/38/eb/2df104dd2244b3618f25325a656f85cc3277f74bbd91224752410a78f3c7/orjson-3.11.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c", size = 144196, upload-time = "2026-02-02T15:37:19.349Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2a/ee41de0aa3a6686598661eae2b4ebdff1340c65bfb17fcff8b87138aab21/orjson-3.11.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f", size = 134979, upload-time = "2026-02-02T15:37:20.906Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fa/92fc5d3d402b87a8b28277a9ed35386218a6a5287c7fe5ee9b9f02c53fb2/orjson-3.11.7-cp310-cp310-win32.whl", hash = "sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de", size = 127968, upload-time = "2026-02-02T15:37:23.178Z" }, + { url = "https://files.pythonhosted.org/packages/07/29/a576bf36d73d60df06904d3844a9df08e25d59eba64363aaf8ec2f9bff41/orjson-3.11.7-cp310-cp310-win_amd64.whl", hash = "sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993", size = 125128, upload-time = "2026-02-02T15:37:24.329Z" }, + { url = "https://files.pythonhosted.org/packages/37/02/da6cb01fc6087048d7f61522c327edf4250f1683a58a839fdcc435746dd5/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c", size = 228664, upload-time = "2026-02-02T15:37:25.542Z" }, + { url = "https://files.pythonhosted.org/packages/c1/c2/5885e7a5881dba9a9af51bc564e8967225a642b3e03d089289a35054e749/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b", size = 125344, upload-time = "2026-02-02T15:37:26.92Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1d/4e7688de0a92d1caf600dfd5fb70b4c5bfff51dfa61ac555072ef2d0d32a/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e", size = 128404, upload-time = "2026-02-02T15:37:28.108Z" }, + { url = "https://files.pythonhosted.org/packages/2f/b2/ec04b74ae03a125db7bd69cffd014b227b7f341e3261bf75b5eb88a1aa92/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5", size = 123677, upload-time = "2026-02-02T15:37:30.287Z" }, + { url = "https://files.pythonhosted.org/packages/4c/69/f95bdf960605f08f827f6e3291fe243d8aa9c5c9ff017a8d7232209184c3/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62", size = 128950, upload-time = "2026-02-02T15:37:31.595Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1b/de59c57bae1d148ef298852abd31909ac3089cff370dfd4cd84cc99cbc42/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910", size = 141756, upload-time = "2026-02-02T15:37:32.985Z" }, + { url = "https://files.pythonhosted.org/packages/ee/9e/9decc59f4499f695f65c650f6cfa6cd4c37a3fbe8fa235a0a3614cb54386/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b", size = 130812, upload-time = "2026-02-02T15:37:34.204Z" }, + { url = "https://files.pythonhosted.org/packages/28/e6/59f932bcabd1eac44e334fe8e3281a92eacfcb450586e1f4bde0423728d8/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960", size = 133444, upload-time = "2026-02-02T15:37:35.446Z" }, + { url = "https://files.pythonhosted.org/packages/f1/36/b0f05c0eaa7ca30bc965e37e6a2956b0d67adb87a9872942d3568da846ae/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8", size = 138609, upload-time = "2026-02-02T15:37:36.657Z" }, + { url = "https://files.pythonhosted.org/packages/b8/03/58ec7d302b8d86944c60c7b4b82975d5161fcce4c9bc8c6cb1d6741b6115/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504", size = 408918, upload-time = "2026-02-02T15:37:38.076Z" }, + { url = "https://files.pythonhosted.org/packages/06/3a/868d65ef9a8b99be723bd510de491349618abd9f62c826cf206d962db295/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e", size = 143998, upload-time = "2026-02-02T15:37:39.706Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c7/1e18e1c83afe3349f4f6dc9e14910f0ae5f82eac756d1412ea4018938535/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561", size = 134802, upload-time = "2026-02-02T15:37:41.002Z" }, + { url = "https://files.pythonhosted.org/packages/d4/0b/ccb7ee1a65b37e8eeb8b267dc953561d72370e85185e459616d4345bab34/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d", size = 127828, upload-time = "2026-02-02T15:37:42.241Z" }, + { url = "https://files.pythonhosted.org/packages/af/9e/55c776dffda3f381e0f07d010a4f5f3902bf48eaba1bb7684d301acd4924/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471", size = 124941, upload-time = "2026-02-02T15:37:43.444Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8e/424a620fa7d263b880162505fb107ef5e0afaa765b5b06a88312ac291560/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d", size = 126245, upload-time = "2026-02-02T15:37:45.18Z" }, + { url = "https://files.pythonhosted.org/packages/80/bf/76f4f1665f6983385938f0e2a5d7efa12a58171b8456c252f3bae8a4cf75/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f", size = 228545, upload-time = "2026-02-02T15:37:46.376Z" }, + { url = "https://files.pythonhosted.org/packages/79/53/6c72c002cb13b5a978a068add59b25a8bdf2800ac1c9c8ecdb26d6d97064/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b", size = 125224, upload-time = "2026-02-02T15:37:47.697Z" }, + { url = "https://files.pythonhosted.org/packages/2c/83/10e48852865e5dd151bdfe652c06f7da484578ed02c5fca938e3632cb0b8/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a", size = 128154, upload-time = "2026-02-02T15:37:48.954Z" }, + { url = "https://files.pythonhosted.org/packages/6e/52/a66e22a2b9abaa374b4a081d410edab6d1e30024707b87eab7c734afe28d/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10", size = 123548, upload-time = "2026-02-02T15:37:50.187Z" }, + { url = "https://files.pythonhosted.org/packages/de/38/605d371417021359f4910c496f764c48ceb8997605f8c25bf1dfe58c0ebe/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa", size = 129000, upload-time = "2026-02-02T15:37:51.426Z" }, + { url = "https://files.pythonhosted.org/packages/44/98/af32e842b0ffd2335c89714d48ca4e3917b42f5d6ee5537832e069a4b3ac/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8", size = 141686, upload-time = "2026-02-02T15:37:52.607Z" }, + { url = "https://files.pythonhosted.org/packages/96/0b/fc793858dfa54be6feee940c1463370ece34b3c39c1ca0aa3845f5ba9892/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f", size = 130812, upload-time = "2026-02-02T15:37:53.944Z" }, + { url = "https://files.pythonhosted.org/packages/dc/91/98a52415059db3f374757d0b7f0f16e3b5cd5976c90d1c2b56acaea039e6/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad", size = 133440, upload-time = "2026-02-02T15:37:55.615Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/cb540117bda61791f46381f8c26c8f93e802892830a6055748d3bb1925ab/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867", size = 138386, upload-time = "2026-02-02T15:37:56.814Z" }, + { url = "https://files.pythonhosted.org/packages/63/1a/50a3201c334a7f17c231eee5f841342190723794e3b06293f26e7cf87d31/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d", size = 408853, upload-time = "2026-02-02T15:37:58.291Z" }, + { url = "https://files.pythonhosted.org/packages/87/cd/8de1c67d0be44fdc22701e5989c0d015a2adf391498ad42c4dc589cd3013/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab", size = 144130, upload-time = "2026-02-02T15:38:00.163Z" }, + { url = "https://files.pythonhosted.org/packages/0f/fe/d605d700c35dd55f51710d159fc54516a280923cd1b7e47508982fbb387d/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2", size = 134818, upload-time = "2026-02-02T15:38:01.507Z" }, + { url = "https://files.pythonhosted.org/packages/e4/e4/15ecc67edb3ddb3e2f46ae04475f2d294e8b60c1825fbe28a428b93b3fbd/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f", size = 127923, upload-time = "2026-02-02T15:38:02.75Z" }, + { url = "https://files.pythonhosted.org/packages/34/70/2e0855361f76198a3965273048c8e50a9695d88cd75811a5b46444895845/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74", size = 125007, upload-time = "2026-02-02T15:38:04.032Z" }, + { url = "https://files.pythonhosted.org/packages/68/40/c2051bd19fc467610fed469dc29e43ac65891571138f476834ca192bc290/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5", size = 126089, upload-time = "2026-02-02T15:38:05.297Z" }, + { url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z" }, + { url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z" }, + { url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z" }, + { url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z" }, + { url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z" }, + { url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z" }, + { url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z" }, + { url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z" }, + { url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z" }, + { url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z" }, + { url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z" }, + { url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" }, + { url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" }, + { url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" }, + { url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" }, + { url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" }, + { url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" }, + { url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" }, + { url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" }, + { url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" }, + { url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" }, + { url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" }, + { url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" }, + { url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" }, + { url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" }, +] + [[package]] name = "outcome" version = "1.3.0.post0" @@ -2032,6 +2113,9 @@ db = [ monitoring = [ { name = "pyleak" }, ] +orjson = [ + { name = "orjson" }, +] [package.dev-dependencies] dev = [ @@ -2077,6 +2161,7 @@ requires-dist = [ { name = "click", specifier = ">=8.2" }, { name = "granian", extras = ["reload"], specifier = ">=2.5.5" }, { name = "httpx", specifier = ">=0.23.3,<1.0" }, + { name = "orjson", marker = "extra == 'orjson'", specifier = ">=3.10,<4.0" }, { name = "packaging", specifier = ">=24.2,<27" }, { name = "platformdirs", specifier = ">=4.3.7,<5.0" }, { name = "psutil", marker = "sys_platform == 'win32'", specifier = ">=7.0.0,<8.0" }, @@ -2094,7 +2179,7 @@ requires-dist = [ { name = "typing-extensions", specifier = ">=4.13.0" }, { name = "wrapt", specifier = ">=1.17.0,<3.0" }, ] -provides-extras = ["db", "monitoring"] +provides-extras = ["db", "monitoring", "orjson"] [package.metadata.requires-dev] dev = [ From 56462f8e94d028c7ccfd9bdae84435d19666c587 Mon Sep 17 00:00:00 2001 From: Benedikt Bartscher Date: Sat, 7 Feb 2026 00:58:09 +0100 Subject: [PATCH 2/3] better pathlib api --- reflex/app.py | 3 +-- reflex/utils/exec.py | 3 +-- reflex/utils/path_ops.py | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/reflex/app.py b/reflex/app.py index f0ff5f8120f..51b2840b75e 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -1170,8 +1170,7 @@ def get_compilation_time() -> str: if not dry_run and not should_compile and backend_dir.exists(): stateful_pages_marker = backend_dir / constants.Dirs.STATEFUL_PAGES if stateful_pages_marker.exists(): - with stateful_pages_marker.open("rb") as f: - stateful_pages = format.orjson_loads(f.read()) + stateful_pages = format.orjson_loads(stateful_pages_marker.read_bytes()) for route in stateful_pages: console.debug(f"BE Evaluating stateful page: {route}") self._compile_page(route, save_page=False) diff --git a/reflex/utils/exec.py b/reflex/utils/exec.py index 4a3ca6be7be..25da507baeb 100644 --- a/reflex/utils/exec.py +++ b/reflex/utils/exec.py @@ -37,8 +37,7 @@ def get_package_json_and_hash(package_json_path: Path) -> tuple[PackageJson, str Returns: A tuple containing the content of package.json as a dictionary and its SHA-256 hash. """ - with package_json_path.open("rb") as file: - json_data = orjson_loads(file.read()) + json_data = orjson_loads(package_json_path.read_bytes()) # Calculate the hash json_string = orjson_dumps(json_data, sort_keys=True) diff --git a/reflex/utils/path_ops.py b/reflex/utils/path_ops.py index c17dd7ca075..d21787bc37a 100644 --- a/reflex/utils/path_ops.py +++ b/reflex/utils/path_ops.py @@ -245,8 +245,7 @@ def update_json_file(file_path: str | Path, update_dict: dict[str, int | str]): # Read the existing json object from the file. json_object = {} if fp.stat().st_size: - with fp.open("rb") as f: - json_object = orjson_loads(f.read()) + json_object = orjson_loads(fp.read_bytes()) # Update the json object with the new data. json_object.update(update_dict) From 1d44fd4c40a5d05f261d02e438ada901525b40cf Mon Sep 17 00:00:00 2001 From: Benedikt Bartscher Date: Sat, 7 Feb 2026 01:03:49 +0100 Subject: [PATCH 3/3] fix pyright --- pyproject.toml | 1 + reflex/utils/format.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 58f1ed4a173..12971ceed3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -100,6 +100,7 @@ dev = [ "starlette-admin", "toml", "uvicorn", + "orjson >=3.10,<4.0", ] diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 08c59031f52..689a816dc05 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -701,7 +701,7 @@ def orjson_dumps(obj: Any, **kwargs) -> str: A JSON string. """ try: - import orjson + import orjson # pyright: ignore[reportMissingImports] except ImportError: return json.dumps(obj, **kwargs) @@ -735,7 +735,7 @@ def orjson_loads(data: str | bytes) -> Any: The deserialized Python object. """ try: - import orjson + import orjson # pyright: ignore[reportMissingImports] except ImportError: return json.loads(data)