Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

quapp-common

Quapp common library supporting Quapp Platform for Quantum Computing.

Overview

quapp-common is a Python library designed to support the Quapp Platform for Quantum Computing by providing common utilities, configurations, and abstractions for working with quantum providers and devices. Recent improvements add first-class asynchronous job processing with a cross-process JobManager, background task execution, and standardized result models for immediate client responses while work continues in the background.

Features

  • Provider and device factory for quantum computing platforms.
  • Logging and configuration utilities with improved and detailed log messages.
  • Support for AWS Braket, OQC Cloud, Qiskit, PennyLane, DWave Ocean, and Quapp quantum simulators.
  • Refactored classes and utilities to remove tenant-specific request, response, and promise classes.
  • Standardized naming by renaming ProjectHeader to CustomHeader.
  • Enhanced error handling and job metadata update mechanisms.
  • Simplified and cleaner HTTP request/response logging and URL parsing utilities.
  • Asynchronous job processing:
    • AsyncInvocationTask to run handlers in a background thread pool and return immediate responses.
    • JobManager for cross-process job registry with atomic add/update/get and pub-sub updates.
    • Standard Event/Result (Success, Error) models for consistent async responses.
    • Scheduler integration via callback URL; local updates are patched to the scheduler.
    • Safety: updates to jobs already DONE/FAILED are ignored to prevent post-completion mutations.
  • Multi-language SDK support:
    • Language enum for validating and resolving Python, JavaScript, and Q# runtimes.
    • Standalone dispatch() function (formerly SubprocessDispatcher class) to delegate tasks to non-Python runtimes via subprocess with timeout management and JSON payload processing; supports Node.js and precompiled Q# binary (./handler_runner_bin/Function[.exe]) runners.
    • Working directory configurable via QUAPP_WORKING_DIR environment variable; falls back to os.getcwd() when unset.
    • SubprocessBridge class integrating standalone dispatcher, circuit adapter, and result serializer for seamless JS/Q#-Python handler interaction.
    • Standalone adapt() function (formerly CircuitAdapter class) for converting subprocess circuit outputs into native SDK formats (OpenQASM, QUBO, JSON) across Qiskit, Braket, PennyLane, PyQuil, Qibo, Qulacs, and CUDA Quantum.
    • Standalone serialize() function (formerly ResultSerializer class) for converting complex job results into JSON-serializable dictionaries for subprocess communication.

Installation

Install via pip:

pip install quapp-common

Notes:

  • From version 0.0.11.dev7, starlette is a direct dependency to support background execution helpers.
  • From version 0.0.12.dev1, qibo and dimod are added as dependencies to support Qibo and D-Wave Ocean SDK integrations.

Recently Changes Highlights

v0.0.14.dev2 — Fix: log lỗi bị nhân đôi

  • Fix: mỗi lần lỗi phát hai dòng ERROR cùng event=job_failed, mỗi dòng kèm một traceback riêng. Nguyên nhân: build_error_job_response() (thêm ở 0.0.13.dev9) tự phát một dòng log tập trung, nhưng 10 call-site vẫn giữ self.logger.exception(...) của chúng.

    Ngoài việc làm ồn Function Log và nhân đôi lượng traceback, nó làm sai metric nếu backend đếm event=job_failed để tính tỉ lệ job thất bại.

    Đã gỡ log ở 10 call-site trong device.py, custom_device.py, invocation.py (×3), job_fetcher.py (×2), job_fetching.py (×2), post_processing_task.py. Dòng log tập trung mang nhiều thông tin hơn bản bị gỡ: event / category / error_code / phase + full traceback.

    phase_failed (WARNING, mốc timeline) là event khác, không bị tính là trùng.

  • Fix (security): credential lọt vào log text qua hai đườngredact() không chặn được:

    1. loguru diagnose=True (default) in giá trị biến cục bộ trong traceback dưới dạng └ 'value'. Không có tên key nên redact() — vốn match key: value — không mask. Token provider nằm trong biến cục bộ lọt nguyên. Đã set diagnose=False cho sink text (backtrace=True vẫn giữ: nó mở rộng call chain nhưng không in giá trị).
    2. Placeholder {exception} được loguru render trực tiếp từ exception object, không đi qua filter. Secret nằm trong str(exception) — ví dụ response body của provider bị nhét vào ValueError — lọt nguyên. Sink text nay append traceback đã redact ở extra[_exc_text] thay cho placeholder đó.

    Sink JSON không bị ảnh hưởng: nó đã dùng _exc_textdiagnose=False.

  • Docs: ghi rõ trong docstring nên chọn QUAPP_LOG_FORMAT nào. Với Grafana/Loki phải dùng json: ở chế độ text, traceback là các dòng riêng không có prefix [ConsoleJobLog][<job_id>], nên filter theo job_id sẽ mất toàn bộ stack. both ghi mỗi record hai lần — chỉ dùng khi debug.

  • Test: thêm tests/test_log_secret_leak.py — 5 case, test qua sink THẬT do configure_logging() tạo (không introspect internals). Có một case khoá lại hành vi diagnose=True của loguru, để nếu upstream đổi thì ta biết.

  • Test: thêm tests/test_error_log_dedupe.py — khoá hồi quy ở hai mức: đếm số dòng job_failed khi chạy thật, quét source để bắt trường hợp ai đó thêm lại logger.exception() ngay trước build_error_job_response().

    Kèm test cho trường hợp nhiều job đồng thời: 4 job qua run_in_threadpool + circuit_running_pool phải có số dòng log đều nhau, không job nào nhận log của job khác, và phase giữ được khi đi vào thread pool.

v0.0.14.dev1 — Error taxonomy & error envelope (Phase 1)

Tiếp nối Phase 0. Bổ sung phân loại lỗi có ngữ nghĩa và envelope dùng chung cho Function Log lẫn Job Log. Additive: job_result chỉ thêm field error, messageexception giữ nguyên; contract callback URL không đổi.

Taxonomy — hai chiều phân loại độc lập

  • enum/error_category.py: ErrorCategory 13 giá trị, nhóm theo ai xử lý được (owner_of() → USER / WORKSPACE_ADMIN / PROVIDER / PLATFORM).
  • enum/runtime_phase.py: RuntimePhase 9 giá trị. Tách được PROVIDER_INVOCATION / COMPILATION / EXECUTION — trước đây auth sai, transpile fail và provider từ chối job đều ra chung nhãn EXECUTION. PHASE_TO_STEP giữ nguyên contract InvocationStep của callback URL.

Classifier (util/error_classifier.py) — tổ hợp 5 tín hiệu theo độ tin cậy:

  1. phase — biết chắc từ context manager, không suy đoán;
  2. frame_owner() — code của ai, dựa vào đường dẫn frame sâu nhất (function/ = user, quapp_* = platform, site-packages/ = SDK);
  3. tên class exception, đi hết cause chain qua cả __cause__ __context__ — cần thiết vì nhiều provider lib bọc lỗi bằng raise ValueError(...) trong khối except mà không có from;
  4. attribute đọc được: HTTP status, AWS error code, exit code, signal;
  5. message pattern (dùng cuối cùng).

register_rules() cho phép lib provider đăng ký rule đặc thù SDK khi import, nên qapp-common không phải import qiskit/braket. Batch đăng ký sau được xét trước; trong cùng batch giữ nguyên thứ tự. Rule ném lỗi bị bỏ qua chứ không làm hỏng đường báo lỗi. 20 rule generic sẵn có.

Fallback nhiều tầng nên không bao giờ trả UNKNOWN một cách mù: không rule nào khớp thì suy từ frame ownership, rồi tới phase.

Envelope (data/response/error_report.py)job_result['error'] gồm code, category, phase, owner, retryable, rootCause (type + detail + file:line), causeChain, stackTrace (full, đã redact), handlerStackTrace (stack JS/.NET cho handler không phải Python), context, resolution (summary + steps + docUrl), retry, traceId. log_fields() bind cùng vocabulary vào Function Log.

Timeline (config/log_context.py) — context manager phase() phát phase_start / phase_end / phase_failed kèm duration_ms. Đây là dữ liệu để UI vẽ timeline và chỉ ra job chết ở bước nào. phase_failed ở mức WARNING để thấy được khi chạy LOG_LEVEL=INFO.

_FAILED_PHASE ghi lại phase mà exception thoát ra: khối except xử lý lỗi gần như luôn nằm ngoài with phase(...), lúc đó phase đang mở đã bị reset trong finally. Không có nó thì mọi ErrorReport đều phase=None và fallback theo phase không bao giờ chạy. Dùng effective_phase() ở đường báo lỗi.

config/thread_config.pyContextAwareThreadPoolExecutor copy contextvars khi submit. ThreadPoolExecutor thuần không làm việc này (khác asyncio.to_thread), nên analysis + finalization chạy trong circuit_running_pool sẽ mất job_id / trace_id / phase.

Call-sitephase() bọc PREPROCESSING / DEVICE_SELECTION / PROVIDER_INVOCATION / COMPILATION / EXECUTION / ANALYSIS; toàn bộ 13 call-site của build_error_job_response() truyền phase=.

Testtests/test_error_classifier.py (52 case: cause chain, HTTP/AWS code, frame ownership, phase fallback, rule ordering) và tests/test_error_report.py (44 case: envelope, timeline, thread pool).

v0.0.13.dev9 — Error logging & observability (Phase 0)

Mục tiêu: Function Log và Job Log phải chỉ ra được nguyên nhân lỗi. Toàn bộ thay đổi trong bản này là additive hoặc bug fix — không đổi contract callback, không đổi schema job_result, không cần frontend/backend sửa gì.

Logging (config/)

  • Thêm config/log_context.py: bind_job() / enrich_job_context() đặt job_id, trace_id, sdk, provider, device vào contextvars. Mọi log sau đó tự có đủ field, kể cả log của Provider / DeviceSelection / *Factory — những chỗ trước đây rơi vào context "QuappLibs" nên không gắn được vào job nào.
  • configure_logging() idempotent. Trước đây AsyncInvocationTask.do() gọi logger.add(sink=sys.stderr, ...) cho mỗi request, nên sau N job có N+1 sink và mỗi dòng log in N+1 lần.
  • Thêm InterceptHandler + install_stdlib_intercept(): đẩy mọi record của stdlib logging sang loguru. Cần thiết vì 24/34 template trong quapp-sdk-templates dùng logging.getLogger('index') mà không cấu hình handler — debug/info của chúng bị drop im lặng và exception in ra không có prefix [ConsoleJobLog] lẫn job_id. Log của uvicorn/qiskit/botocore cũng về cùng một format.
  • Thêm JSON sink cho structured logging, bật bằng QUAPP_LOG_FORMAT=json|both (default text, giữ nguyên hành vi cũ). Field: jobId, traceId, phase, category, errorCode, sdk, provider, device, event, durationMs.
  • Thêm redaction filter: mask token / apiKey / authentication / clientSecret / … trước khi ghi log, áp dụng cả cho stack trace.
  • Fix: text formatter thiếu {exception}. Với formatter dạng callable, loguru không tự append traceback — nên trước đây mọi logger.exception() trong codebase không in ra stack trace nào.
  • Fix: depth trong intercept khiến mọi record hiện là logging:callHandlers:<line> thay vì file:line của nơi gọi log.
  • Fix: với enqueue=True, traceback object không picklable nên bị thay bằng None sau khi qua queue. Traceback nay được format sẵn ở filter.

Error từ runner không phải Python (component/dispatcher.py, bridge.py)

  • Bỏ subprocess.run(..., check=True). Nó raise CalledProcessError trước khi đọc được output, làm nhánh _extract_error_message() thành dead code và user chỉ thấy Command '[...]' returned non-zero exit status 1.
  • Thêm HandlerRuntimeError mang language, action, error_type, stack (stack của runtime gốc — JS/.NET), exit_code, signal_name. Sáu tình huống được phân biệt: runner không có trong image, timeout, bị signal (handler.c segfault → returncode âm, stdout rỗng), structured error trên stdout, exit code khác 0, và output không phải JSON hợp lệ.
  • Đọc được cả contract cũ (error dạng string, stack trên stderr) nên không cần deploy đồng thời với template.
  • _format_exception() đưa handlerStackTrace / language / action / exitCode / signal lên job_result cho lỗi handler JS/Q#/C.

Đường lỗi (model/device/device.py, util/response_utils.py, …)

  • Device._on_execution dùng build_error_job_response() thay cho job_result = {"error": str(exception)} và log ở ERROR thay vì DEBUG. Đây là đường lỗi quan trọng nhất (submit circuit lên device) và trước đây là đường mất thông tin nhiều nhất.
  • build_error_job_response() nay tự phát một log ERROR duy nhất cho mọi lỗi, nên Job Log và Function Log không còn lệch nhau.
  • Truyền stage cho 8 call-site còn thiếu (trước đây 10/13 call-site rơi vào default 'while running your job').
  • Fix generate_response(): nhánh else truy cập job_response.status_code khi job_response là falsy → AttributeError, thay lỗi gốc bằng lỗi khác.
  • Fix job_fetching.py: __produce_histogram_data / __get_execution_time khai báo @staticmethod nhưng dùng self.loggerNameError khi được gọi.
  • DeviceSelection: không log nguyên response (chứa token provider) và không nhét response.content thô vào exception (nội dung này chảy vào job_result rồi hiện lên UI).
  • PostProcessingTask: bỏ print() ghi thẳng ra stdout (không qua sink nên không được redact và không có job_id).

Test

  • tests/test_logging_config.py — redaction, idempotent sink, job context, intercept stdlib, exception payload.
  • tests/test_dispatcher_runner_error.py — 6 nhánh phân loại lỗi runner.

v0.0.13.dev2

  • Fix: _openqasm_to_braket in circuit_adapter.py now injects a default Probability result type when the Braket circuit produced by tk_to_braket has no result types. OpenQASM circuits submitted from non-Python runtimes (e.g. Q#) do not carry explicit measurement annotations, so the converted Braket circuit would have an empty result_types list and fail at execution time. The fix adds circuit.probability(target=list(range(circuit.qubit_count))) before returning, ensuring every Braket job has at least one result type.

v0.0.13.dev1

  • Refactor: Replace class-based subprocess components with standalone module-level functions for simpler imports and testability:
    • SubprocessDispatcher class → dispatch() and is_subprocess_language() in dispatcher.py.
    • CircuitAdapter class → adapt() and private helper functions in circuit_adapter.py.
    • ResultSerializer class → serialize() in result_serializer.py.
    • SubprocessBridge retains its class form but delegates internally to the new standalone functions.
  • Refactor dispatcher.py: WORKING_DIR is now read from the QUAPP_WORKING_DIR environment variable (previously hardcoded None); falls back to os.getcwd() when the variable is unset.
  • Refactor dispatcher.py: Q# runner command changed from dotnet run --project HandlerRunner.csproj to a precompiled platform-specific binary — ./handler_runner_bin/Function.exe on Windows and ./handler_runner_bin/Function on other platforms — eliminating the dotnet toolchain requirement at runtime.
  • Refactor circuit_adapter.py: Extract _load_qasm_circuit(qasm_str) private utility that centralises OpenQASM 2.0 string parsing with Qiskit version compatibility — uses qiskit.qasm2.loads (Qiskit >= 1.0) and falls back to QiskitCircuit.from_qasm_str (Qiskit < 1.0).
  • Fix: subprocess.run now passes check=True so a non-zero exit code raises CalledProcessError before the manual return-code branch is reached.
  • Add unit tests: tests/test_circuit_adapter.py, tests/test_json_parser_utils.py, tests/test_result_serializer.py.

v0.0.12.dev15

  • Extend multi-language SDK support with Q# (QSharp) runtime:
    • Add QSHARP to Language enum.
    • Add Q# runner configuration to SubprocessDispatcher (dotnet run --project ., 300 s timeout).

v0.0.12.dev14

  • Fix: CircuitAdapter._adapt_openqasm for Sdk.PENNYLANE now catches the "Failed to load the qasm plugin" error raised by qml.from_qasm on PennyLane versions that route QASM parsing through the IO plugin registry and require pennylane-qiskit to be installed (affects both older releases and the current latest). When the error is detected, it falls back to parsing the QASM string via Qiskit (a hard dependency) and emitting native PennyLane operations gate-by-gate through the new CircuitAdapter._qiskit_to_pennylane helper. Supported gates: H, X, Y, Z, S, Sdg (→ PhaseShift −π/2), T, Tdg (→ PhaseShift −π/4), CX, CZ, SWAP, RX, RY, RZ, P/U1 (→ PhaseShift), U2, U3/U; unrecognized gates are logged as a warning and skipped.

v0.0.12.dev13

  • Fix: CircuitAdapter._adapt_openqasm for Sdk.PENNYLANE now injects string sentinels ("Expectation", "Variance", "Sample", "Probability", "State", "MidMeasure") back into pennylane.measurements when they are absent. PennyLane 0.37 removed ObservableReturnTypes from that module, but legacy plugins such as pennylane-rigetti import these names at module level and crash with ImportError before the device is created. The shim is injected inside __pre_execute, before PennylaneInvocation creates the device, so the plugin import succeeds and the removed code paths are bypassed at runtime.

v0.0.12.dev12

  • Feat: add QUAPP_HPC to ProviderTag enum to support the Slurm HPC integration. Required by quapp-hpc so its SlurmProvider can register itself in the shared ProviderTag namespace; without this, importing quapp-hpc fails at SlurmProvider.__init__ with AttributeError on the enum lookup.

v0.0.12.dev11

  • Enhance: CircuitAdapter now emits structured debug logs at each routing decision — SDK selected, QASM string length, qubit count, per-SDK adapter chosen, tk_to_braket return type (tuple vs bare Circuit), DenseMatrix fallback for unrecognized/parametric gates in _qiskit_to_qulacs, and QUBO entry counts before and after parsing.
  • Enhance: SubprocessBridge now emits debug logs on initialisation (language, sdk), processing() (input keys, JS status, adapted circuit type), and post_processing() (job-result type, serialised keys, JS status, result type); subprocess failures are additionally promoted to logger.error before the RuntimeError is raised.

v0.0.12.dev10

  • Fix: CircuitAdapter._adapt_openqasm for Sdk.BRAKET now handles the breaking API change in pytket-braket >= 0.35, where tk_to_braket returns a (Circuit, n_shots) tuple instead of a bare Circuit — the method unpacks the first element when a tuple is returned and passes through the value unchanged for older versions.

v0.0.12.dev9

  • Fix: QulacsInvocation._get_qubit_amount now handles OpenQASM string input — when a JS job submits an OpenQASM 2.0 string circuit, the method parses the qreg declaration to extract the qubit count instead of raising "Invalid circuit type!".

v0.0.12.dev8

  • Add Sdk.QULACS support in CircuitAdapter._adapt_openqasm with a two-stage fallback strategy:
    1. Qiskit bridge (preferred): parse OpenQASM with QiskitCircuit.from_qasm_str, then convert gate-by-gate to a qulacs.QuantumCircuit via the new CircuitAdapter._qiskit_to_qulacs helper. Fixed gates (H, X, Y, Z, S, Sdg, T, Tdg, CX, CZ, SWAP) use named qulacs methods; parametric and unrecognized gates fall back to qulacs.gate.DenseMatrix with gate.to_matrix().
    2. Raw pass-through (fallback): if qiskit is not installed or conversion raises any exception, the raw OpenQASM string is returned as-is (same approach as Sdk.CUDA_QUANTUM) and a warning is logged.
  • Add qulacs as a direct dependency in pyproject.toml.

v0.0.12.dev7

  • Fix: remove Sdk.CU_QUANTUM from the CUDA-Q branch in CircuitAdapter._adapt_openqasmCU_QUANTUM is not a member of the Sdk enum; the only valid CUDA-Q value is Sdk.CUDA_QUANTUM, so the compound sdk in (Sdk.CUDA_QUANTUM, Sdk.CU_QUANTUM) check is replaced with a plain sdk == Sdk.CUDA_QUANTUM.

v0.0.12.dev6

  • Fix: replace direct from pytket.extensions.braket import ... and from pytket.extensions.pyquil import ... with importlib.import_module() in CircuitAdapter — avoids IDE static-analysis false positives caused by pytket.extensions being a namespace package populated at runtime by separately installed pytket-braket / pytket-pyquil packages.

v0.0.12.dev5

  • Version bump to 0.0.12.dev5.
  • Refactor: update logger imports in SubprocessBridge, CircuitAdapter, and SubprocessDispatcher to use relative paths (from ..config.logging_config import logger) for consistency across modules.

v0.0.12.dev4

  • Version bumps to 0.0.12.dev4.
  • Fix: AsyncInvocationTask._on_task_done now properly fires the step error callback when a background task raises an unhandled exception — reads onErrorCallbackUrl from the event's preparation step and calls update_job_metadata with a structured error response.
  • Fix: circuit preparation failure in Invocation.__pre_execute now returns None instead of raising ValueError, allowing the caller to handle the empty result gracefully without an unhandled exception propagating.
  • Refactor: replace stdlib logging with the project’s loguru-based logger (via config.logging_config) in SubprocessBridge, CircuitAdapter, and SubprocessDispatcher; all three now call logger.bind(context=__name__).
  • Style: reformat SubprocessBridge and SubprocessDispatcher from 2-space to 4-space indentation, consistent with the rest of the codebase.

v0.0.12.dev3

  • Version bumps to 0.0.12.dev3.
  • Add QUANTUM_HPC SDK enum value (display name "quantum hpc") to support the Quapp HPC backend.
  • Make circuitExportUrl optional in Invocation for SDKs that do not require a circuit-export step.

v0.0.12.dev2

  • Version bumps to 0.0.12.dev2.
  • Fix: correct JavaScript handler runner path in SubprocessDispatcher.RUNNER_MAP — removed the erroneous function/ directory prefix so the subprocess command resolves to handler_runner.js relative to the working directory.

v0.0.12.dev1

  • Version bump to 0.0.12.dev1 and dependency update (add qibo, dimod).
  • Introduce multi-language SDK support primitives:
    • Language enum for validating and resolving Python/JavaScript runtimes.
    • SubprocessDispatcher for delegating tasks to non-Python runtimes via subprocess with runner configuration and timeout management.
    • SubprocessBridge integrating dispatcher, circuit adapter, and result serializer for JS-Python handler interaction.
    • CircuitAdapter for converting JS subprocess circuit outputs into native SDK formats (OpenQASM, QUBO, JSON) across Qiskit, Braket, PennyLane, etc.
    • ResultSerializer for converting complex job results (numpy, complex numbers, Enums, datetime) into JSON-serializable dictionaries.

v0.0.11.dev7 – v0.0.11.dev10

  • Version bump to 0.0.11.dev7 and dependency update (add starlette).
  • Introduce asynchronous job processing primitives:
    • AsyncInvocationTask for background execution with immediate client response.
    • Event and standardized Result models (Success, Error).
  • Introduce JobManager for cross-process job management and update publication.
  • Integrate JobManager into Request to register jobs and carry scheduler callback URL.
  • Modularize update_job_metadata with clearer helpers; patch scheduler on local state changes.
  • Fix: ignore updates for jobs that are already DONE or FAILED.
  • Improve logging and error handling (use full tracebacks, cleaner logs).

For detailed usage and API references, please refer to the in-code documentation or contact the maintainers.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

quapp_common-0.0.14.dev2.tar.gz (100.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

quapp_common-0.0.14.dev2-py3-none-any.whl (99.1 kB view details)

Uploaded Python 3

File details

Details for the file quapp_common-0.0.14.dev2.tar.gz.

File metadata

  • Download URL: quapp_common-0.0.14.dev2.tar.gz
  • Upload date:
  • Size: 100.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.10.12

File hashes

Hashes for quapp_common-0.0.14.dev2.tar.gz
Algorithm Hash digest
SHA256 86adf40f49d81f8358750a174001a95a4a244b2f02b4dc464e3681526cc96e79
MD5 7c19592ff076f84e5beb7b3d2d4165fc
BLAKE2b-256 a77578cb1265d5c2bb27046da6c232ef2e81da6cced1666e54eba08ffee199a3

See more details on using hashes here.

File details

Details for the file quapp_common-0.0.14.dev2-py3-none-any.whl.

File metadata

File hashes

Hashes for quapp_common-0.0.14.dev2-py3-none-any.whl
Algorithm Hash digest
SHA256 b79e5195a663f87b1150b79f577db15e3cab20a076f933a0cbd2744229d5dd80
MD5 a585387b131b99b77bb5ce4a59871f81
BLAKE2b-256 6222d05ed5a41152491d3c457bebf9a7262ebb9633c72d7fb0791d45a36f211b

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.14

2 files

This release

0.0.14.dev2 This release

2 files

0.0.13

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page