Skip to main content

Python wrapper for the Helios Software SOF (SQL on FHIR) toolkit.

Project description

pysof - SQL on FHIR for Python

PyPI version Python versions License: MIT Downloads

High-performance FHIR data transformation for Python. Transform FHIR resources into tabular formats (CSV, JSON, Parquet) using declarative ViewDefinitions from the SQL on FHIR specification.

Built in Rust for speed, exposed to Python with a simple, Pythonic API. Part of the Helios FHIR Server project.

✨ Key Features

  • 🚀 High Performance: Native Rust implementation with minimal Python overhead
  • 📊 Multiple Output Formats: CSV, JSON, NDJSON, and Parquet
  • 🔄 Parallel Processing: Automatic multithreading with 5-7x speedup on multi-core systems
  • 📦 Streaming Support: Memory-efficient chunked processing for large NDJSON files
  • 🌐 Multi-Version FHIR: Supports R4, R4B, R5, and R6 (based on build features)
  • 🎯 Type-Safe: Leverages Rust's type safety with a Pythonic interface
  • GIL-Free: Python GIL released during processing for true parallelism

🎯 Why pysof?

Working with FHIR data in Python just got faster. pysof lets you:

  • Transform complex FHIR resources into clean, analyzable tables without writing custom parsers
  • Process large datasets efficiently with automatic parallel processing and Rust-level performance
  • Use standard SQL on FHIR ViewDefinitions for portable, maintainable data transformations
  • Export to multiple formats (CSV, JSON, NDJSON, Parquet) for analytics, ML, or reporting workflows

Perfect for healthcare data engineers, researchers, and developers building FHIR-based analytics pipelines.

🔗 Quick Links

📥 Installation

From PyPI (Recommended)

pip install pysof

Supported Platforms:

  • Linux: x86_64 (glibc and musl)
  • Windows: x86_64 (MSVC)
  • macOS: AArch64 (Apple Silicon)
  • Python: 3.10, 3.11, 3.12, 3.13, 3.14

From GitHub Releases

Download pre-built wheels from the releases page:

pip install pysof-*.whl

🚀 Quick Start

Transform FHIR patient data to CSV in just a few lines:

import pysof

# Define what data to extract
view_definition = {
    "resourceType": "ViewDefinition",
    "id": "patient-demographics",
    "name": "PatientDemographics",
    "status": "active",
    "resource": "Patient",
    "select": [{
        "column": [
            {"name": "id", "path": "id"},
            {"name": "family_name", "path": "name.family"},
            {"name": "given_name", "path": "name.given.first()"},
            {"name": "gender", "path": "gender"},
            {"name": "birth_date", "path": "birthDate"}
        ]
    }]
}

# Sample FHIR Bundle
bundle = {
    "resourceType": "Bundle",
    "type": "collection",
    "entry": [{
        "resource": {
            "resourceType": "Patient",
            "id": "patient-1",
            "name": [{"family": "Doe", "given": ["John"]}],
            "gender": "male",
            "birthDate": "1990-01-01"
        }
    }]
}

# Transform to CSV
csv_output = pysof.run_view_definition(view_definition, bundle, "csv")
print(csv_output.decode('utf-8'))
# Output:
# id,family_name,given_name,gender,birth_date
# patient-1,Doe,John,male,1990-01-01

📖 Usage

Multiple Output Formats

import pysof
import json

# Transform to different formats
csv_result = pysof.run_view_definition(view_definition, bundle, "csv")
json_result = pysof.run_view_definition(view_definition, bundle, "json")
ndjson_result = pysof.run_view_definition(view_definition, bundle, "ndjson")
parquet_result = pysof.run_view_definition(view_definition, bundle, "parquet")

print("CSV Output:")
print(csv_result.decode('utf-8'))

print("\nJSON Output:")
data = json.loads(json_result.decode('utf-8'))
print(json.dumps(data, indent=2))

Advanced Options

import pysof

# Transform with pagination and filtering
result = pysof.run_view_definition_with_options(
    view_definition,
    bundle,
    "json",
    limit=10,                          # Limit results
    page=1,                            # Page number
    since="2023-01-01T00:00:00Z",     # Filter by modification date
    fhir_version="R4"                  # Specify FHIR version
)

Remote resolve() (Trusted Servers)

resolve() dereferences references against the input bundle by default. You can optionally let it fetch references that point at explicitly trusted FHIR servers and fold them into the resolution pool before rows are generated. This is off by default and gated by a strict allowlist (matching scheme + host + port

  • path-prefix; private/loopback addresses are blocked unless opted in).
import pysof

config = pysof.RemoteResolveConfig(
    ["https://fhir.example.org/r4"],   # trusted base URLs (allowlist)
    max_fetches=256,                    # per-run/-stream fetch cap
    max_depth=1,                        # chained-reference rounds
    allow_private_addresses=False,      # allow internal LBs (e.g. Traefik) by hostname
    bearer_tokens={"fhir.example.org": "TOKEN"},  # optional per-host auth
)

# Or build it from SOF_RESOLVE_* environment variables:
# config = pysof.RemoteResolveConfig.from_env()

result = pysof.run_view_definition_remote(
    view_definition, bundle, "json", config, fhir_version="R4"
)

# Streaming NDJSON with remote resolve() (one shared cache across chunks):
stats = pysof.process_ndjson_to_file_remote(
    view_definition, "input.ndjson", "output.json", "ndjson", config, chunk_size=1000
)

When config.is_active() is False (disabled or empty allowlist) these behave exactly like their non-remote counterparts. Enabling remote resolution makes output depend on remote server state at run time. See the SQL-on-FHIR guide for the full security model and configuration reference.

Utility Functions

import pysof

# Validate structures
is_valid_view = pysof.validate_view_definition(view_definition)
is_valid_bundle = pysof.validate_bundle(bundle)

# Parse content types
format_str = pysof.parse_content_type("text/csv")  # Returns "csv_with_header"

# Check supported FHIR versions
versions = pysof.get_supported_fhir_versions()  # Returns ["R4"] or more
print(f"Supported FHIR versions: {versions}")

# Package info
print(f"Version: {pysof.get_version()}")
print(pysof.get_status())

Streaming Large NDJSON Files

For memory-efficient processing of large NDJSON files, use the ChunkedProcessor iterator or process_ndjson_to_file function:

import pysof

view_definition = {
    "resourceType": "ViewDefinition",
    "status": "active",
    "resource": "Patient",
    "select": [{"column": [
        {"name": "id", "path": "id"},
        {"name": "gender", "path": "gender"}
    ]}]
}

# Iterator approach - process chunks incrementally
for chunk in pysof.ChunkedProcessor(view_definition, "patients.ndjson", chunk_size=500):
    print(f"Chunk {chunk['chunk_index']}: {len(chunk['rows'])} rows")
    for row in chunk["rows"]:
        process_row(row)
    if chunk["is_last"]:
        print("Processing complete!")

# Access column names before iterating
processor = pysof.ChunkedProcessor(view_definition, "patients.ndjson")
print(f"Columns: {processor.columns}")
for chunk in processor:
    # Process chunks...
    pass

# File-to-file approach - most memory efficient
stats = pysof.process_ndjson_to_file(
    view_definition,
    "input.ndjson",
    "output.csv",
    "csv",  # or "csv_with_header", "ndjson"
    chunk_size=1000,
    skip_invalid=True,  # Continue past invalid JSON lines
    fhir_version="R4"
)
print(f"Processed {stats['resources_processed']} resources")
print(f"Output {stats['output_rows']} rows in {stats['chunks_processed']} chunks")
print(f"Skipped {stats['skipped_lines']} invalid lines")

When to use streaming:

  • Processing NDJSON files larger than available memory
  • Working with datasets of 100K+ resources
  • Building ETL pipelines that process data incrementally
  • When you need fault-tolerant processing (skip invalid lines)

Error Handling

import pysof

try:
    result = pysof.run_view_definition(view_definition, bundle, "json")
except pysof.InvalidViewDefinitionError as e:
    print(f"ViewDefinition validation error: {e}")
except pysof.SerializationError as e:
    print(f"JSON parsing error: {e}")
except pysof.UnsupportedContentTypeError as e:
    print(f"Unsupported format: {e}")
except pysof.SofError as e:
    print(f"General SOF error: {e}")

⚡ Performance

Automatic Parallel Processing

pysof automatically processes FHIR resources in parallel using rayon:

  • 5-7x speedup on typical batch workloads with multi-core CPUs
  • Streaming benefits: ChunkedProcessor and process_ndjson_to_file also use parallel processing
  • Zero configuration - parallelization is always enabled
  • Python GIL released during processing for true parallel execution

Performance Benchmarks

Mode Dataset Time Memory Notes
Batch 10k Patients ~2.7s 1.6 GB All resources in memory
Streaming 10k Patients ~0.9s 45 MB 35x less memory, 2.9x faster
Batch 93k Encounters ~4s 3.9 GB All resources in memory
Streaming 93k Encounters ~2.8s 25 MB 155x less memory, 1.4x faster

Streaming mode (ChunkedProcessor, process_ndjson_to_file) is recommended for large NDJSON files.

Controlling Thread Count (RAYON_NUM_THREADS)

Set the RAYON_NUM_THREADS environment variable to control parallel processing:

import os
os.environ['RAYON_NUM_THREADS'] = '4'  # Must be set before first import

import pysof
result = pysof.run_view_definition(view_definition, bundle, "json")

Or from the command line:

# Linux/Mac
RAYON_NUM_THREADS=4 python my_script.py

# Windows PowerShell
$env:RAYON_NUM_THREADS=4
python my_script.py

When to adjust thread count:

  • Reduce threads (RAYON_NUM_THREADS=2-4): On shared systems, containers with CPU limits, or when running multiple instances
  • Increase threads: Rarely needed; rayon auto-detects available cores
  • Single thread (RAYON_NUM_THREADS=1): For debugging or deterministic output ordering

Performance Tips:

  • Use all available cores for large datasets (default behavior)
  • Limit threads on shared systems to avoid resource contention
  • Prefer streaming mode (ChunkedProcessor) for NDJSON files > 100MB

📋 Supported Features

Output Formats

Format Description Output
csv CSV with headers Comma-separated values with header row
json JSON array Array of objects, one per result row
ndjson Newline-delimited JSON One JSON object per line
parquet Parquet format Columnar binary format for analytics

FHIR Versions

  • R4 (default, always available)
  • R4B (if compiled with R4B feature)
  • R5 (if compiled with R5 feature)
  • R6 (if compiled with R6 feature)

Use pysof.get_supported_fhir_versions() to check available versions in your build.


🔧 Development

Requirements

  • Python 3.10 or later (3.10, 3.11, 3.12, 3.13, 3.14 supported)
  • uv (package and environment manager)
  • Rust toolchain (for building from source)

Note: This crate is excluded from the default workspace build. When running cargo build from the repository root, pysof will not be built automatically.

Building from Source

Building with Cargo

This crate is excluded from the default workspace build to allow building the core Rust components without Python. To build it explicitly:

# Your current directory MUST be the pysof crate:
cd crates/pysof

# From the pysof folder
cargo build

# Or build with specific FHIR version features
cargo build -p pysof --features R4,R5

Building with Maturin (Recommended)

For Python development, it's recommended to use maturin via uv:

# From repo root
cd crates/pysof

# Create a venv with your preferred Python version (3.10+)
uv venv --python 3.11  # or 3.10, 3.12, 3.13, 3.14

# Install the project dev dependencies
uv sync --group dev

# Build and install the Rust extension into the venv
uv run maturin develop --release

# Build distributable artifacts
uv run maturin build --release -o dist     # wheels
uv run maturin sdist -o dist               # source distribution

# Sanity checks
uv run python -c "import pysof; print(pysof.__version__); print(pysof.get_status()); print(pysof.get_supported_fhir_versions())"

Installing from Source

Requires Rust toolchain:

# Install directly
pip install -e .

# Or build wheel locally
maturin build --release --out dist
pip install dist/*.whl

Testing

The project has separate test suites for Python and Rust components:

Python Tests

Run the comprehensive Python test suite:

# Run all Python tests
uv run pytest python-tests/

# Run specific test files
uv run pytest python-tests/test_core_functions.py -v
uv run pytest python-tests/test_content_types.py -v
uv run pytest python-tests/test_import.py -v

# Run with coverage
uv run pytest python-tests/ --cov=pysof --cov-report=html

# Run tests with detailed output
uv run pytest python-tests/ -v --tb=short

Rust Tests

Run the Rust unit and integration tests:

# Run all Rust tests
cargo test

# Run unit tests only
cargo test --test lib_tests

# Run integration tests only
cargo test --test integration

# Run with verbose output
cargo test -- --nocapture

Configuring FHIR Version Support

By default, pysof is compiled with R4 support only. You can configure which FHIR versions are available by modifying the feature compilation settings.

Change Default FHIR Version

To change from R4 to another version (e.g., R5):

  1. Edit crates/pysof/Cargo.toml:

    [features]
    default = ["R5"]  # Changed from ["R4"]
    R4 = ["helios-sof/R4", "helios-fhir/R4"]
    R4B = ["helios-sof/R4B", "helios-fhir/R4B"]
    R5 = ["helios-sof/R5", "helios-fhir/R5"]
    R6 = ["helios-sof/R6", "helios-fhir/R6"]
    
  2. Rebuild the extension:

    cd crates/pysof
    uv run maturin develop --release
    
  3. Verify the change:

    uv run python -c "
    import pysof
    versions = pysof.get_supported_fhir_versions()
    print('Supported FHIR versions:', versions)
    "
    

    This should now show ['R5'] instead of ['R4'].

Enable Multiple FHIR Versions

To support multiple FHIR versions simultaneously:

  1. Edit crates/pysof/Cargo.toml:

    [features]
    default = ["R4", "R5"]  # Enable both R4 and R5
    # Or enable all versions:
    # default = ["R4", "R4B", "R5", "R6"]
    
  2. Rebuild and verify:

    uv run maturin develop --release
    uv run python -c "import pysof; print(pysof.get_supported_fhir_versions())"
    

    This should show ['R4', 'R5'] (or all enabled versions).

  3. Use specific versions in code:

    import pysof
    
    # Use R4 explicitly
    result_r4 = pysof.run_view_definition(view, bundle, "json", fhir_version="R4")
    
    # Use R5 explicitly  
    result_r5 = pysof.run_view_definition(view, bundle, "json", fhir_version="R5")
    

Build with Specific Features (Without Changing Default)

To temporarily build with different features without modifying Cargo.toml:

# Build with only R5
cargo build --features R5 --no-default-features

# Build with R4 and R6
cargo build --features R4,R6 --no-default-features

# With maturin
uv run --with maturin -- maturin develop --release --cargo-extra-args="--features R5 --no-default-features"

Testing After Version Changes

After changing FHIR version support, run the test suite to ensure compatibility:

# Run all tests
uv run pytest

# Run FHIR version-specific tests
uv run pytest tests/test_fhir_versions.py -v

# Test with your new default version
uv run python -c "
import pysof

# Test with default version (should be your new default)
view = {'resourceType': 'ViewDefinition', 'id': 'test', 'name': 'Test', 'status': 'active', 'resource': 'Patient', 'select': [{'column': [{'name': 'id', 'path': 'id'}]}]}
bundle = {'resourceType': 'Bundle', 'type': 'collection', 'entry': [{'resource': {'resourceType': 'Patient', 'id': 'test'}}]}

result = pysof.run_view_definition(view, bundle, 'json')
print('Default version test successful:', len(result), 'bytes')
"

Project layout

crates/pysof/
├─ pyproject.toml          # PEP 621 metadata, Python >=3.8, uv-compatible
├─ README.md
├─ src/
│  ├─ pysof/
│  │  └─ __init__.py       # Python package root
│  └─ lib.rs               # Rust PyO3 bindings
├─ tests/                  # Rust tests (17 tests)
│  ├─ lib_tests.rs         # Unit tests for core library functions
│  ├─ integration.rs       # Integration tests for component interactions
│  └─ integration/         # Organized integration test modules
│     ├─ mod.rs
│     ├─ content_types.rs
│     ├─ error_handling.rs
│     └─ fhir_versions.rs
├─ python-tests/           # Python test suite (58 tests)
│  ├─ __init__.py
│  ├─ test_core_functions.py
│  ├─ test_content_types.py
│  ├─ test_fhir_versions.py
│  ├─ test_import.py
│  └─ test_package_metadata.py
└─ Cargo.toml              # Rust crate metadata

📄 License

MIT License - See LICENSE.md for details.

Copyright (c) 2025 Helios Software

🤝 Contributing

Contributions are welcome! Please see our Contributing Guidelines for details.

Reporting Issues

Development Setup

See the Development section above for instructions on setting up your development environment.

🙏 Acknowledgments

Built with:

  • PyO3 - Rust bindings for Python
  • maturin - Build system for Rust Python extensions
  • helios-sof - Core SQL-on-FHIR implementation in Rust

Part of the Helios FHIR Server project.


Made with ❤️ by Helios Software

Project details


Download files

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

Source Distribution

pysof-0.2.1.tar.gz (25.4 MB view details)

Uploaded Source

Built Distributions

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

pysof-0.2.1-cp314-cp314-win_amd64.whl (40.8 MB view details)

Uploaded CPython 3.14Windows x86-64

pysof-0.2.1-cp314-cp314-manylinux_2_34_x86_64.whl (36.9 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

pysof-0.2.1-cp314-cp314-manylinux_2_28_aarch64.whl (35.6 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ ARM64

pysof-0.2.1-cp314-cp314-macosx_11_0_arm64.whl (30.4 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

pysof-0.2.1-cp313-cp313-win_amd64.whl (40.8 MB view details)

Uploaded CPython 3.13Windows x86-64

pysof-0.2.1-cp313-cp313-manylinux_2_34_x86_64.whl (36.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

pysof-0.2.1-cp313-cp313-manylinux_2_28_aarch64.whl (35.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ ARM64

pysof-0.2.1-cp313-cp313-macosx_11_0_arm64.whl (30.4 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pysof-0.2.1-cp312-cp312-win_amd64.whl (40.8 MB view details)

Uploaded CPython 3.12Windows x86-64

pysof-0.2.1-cp312-cp312-manylinux_2_34_x86_64.whl (36.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

pysof-0.2.1-cp312-cp312-manylinux_2_28_aarch64.whl (35.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ ARM64

pysof-0.2.1-cp312-cp312-macosx_11_0_arm64.whl (30.4 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pysof-0.2.1-cp311-cp311-win_amd64.whl (40.8 MB view details)

Uploaded CPython 3.11Windows x86-64

pysof-0.2.1-cp311-cp311-manylinux_2_34_x86_64.whl (36.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.34+ x86-64

pysof-0.2.1-cp311-cp311-manylinux_2_28_aarch64.whl (35.6 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

pysof-0.2.1-cp311-cp311-macosx_11_0_arm64.whl (30.4 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pysof-0.2.1-cp310-cp310-win_amd64.whl (40.8 MB view details)

Uploaded CPython 3.10Windows x86-64

pysof-0.2.1-cp310-cp310-manylinux_2_34_x86_64.whl (36.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.34+ x86-64

pysof-0.2.1-cp310-cp310-manylinux_2_28_aarch64.whl (35.6 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ ARM64

pysof-0.2.1-cp310-cp310-macosx_11_0_arm64.whl (30.4 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file pysof-0.2.1.tar.gz.

File metadata

  • Download URL: pysof-0.2.1.tar.gz
  • Upload date:
  • Size: 25.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for pysof-0.2.1.tar.gz
Algorithm Hash digest
SHA256 9bb1b22aba296fbe9e1d6a04aa0da46f5a4d6267841b96a4a029f229b136bb84
MD5 8839c4a8f65e09f1bb32a06686c801db
BLAKE2b-256 64853906522680c95366ce2c01a573912441267dbbca78a5a6023a010eb072e5

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: pysof-0.2.1-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 40.8 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for pysof-0.2.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 45e4fba603f78b38ba40e9957dff69f4b74f809767d96f9426ae00e78b7fcb71
MD5 1f47cc261056953a2552f592fbc4f4da
BLAKE2b-256 19bcc5b398cc4386ec2612a0aab4b73214acff65105d2b9a2cd23b118a9bdc87

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp314-cp314-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 e90c4ac2362cc7db73beb0aa40bdbab311334dc547f10be2623b5e04e37ec433
MD5 2193953718ad07535049d1f1d08c1bab
BLAKE2b-256 b91a95af0a87fba5f76995fadfd411214683ad4e39efff7b3f9da8425ac9feae

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp314-cp314-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp314-cp314-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b65f5f0e916290e6c701b391a17c14c894b3a273a36e7d0519d5e6d31ee9f0c3
MD5 4e4762c90caecfc0a931d8ffac9440cc
BLAKE2b-256 b8d2250fd569c663aebdcdc5604a05c73a34538541449ea13385cb9769899516

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f494d0177a939e955dedbad3a58554e6c10aab8179b90a3030bd664b847d63a0
MD5 8d9918b3bda3a5641d928ada13d6fa67
BLAKE2b-256 f66c4dbe88d23c38e6b4877551656b42ffc3f9dec5a5c21b9d4e836fc9840e31

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: pysof-0.2.1-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 40.8 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for pysof-0.2.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 5e586101aa7ad269f4b9d184aa19808baa7492ae7fd1eaf439f51ea1a023ab19
MD5 3a1c98a962723a647dd0a06285173dce
BLAKE2b-256 3b68abb3c49899a43b2558238fb2ab2a9c418e4c095fae426afe8667cb024a50

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 ea552d54adbea5bbf27cd67dedc3ac53f5d68425e2075d55016b8b36dbe65e81
MD5 46c6a1bcfd2681ab2373f13770472b0b
BLAKE2b-256 5f714d0602c581def0f3a8155e1458907387ce3bda69bcc0133ca72c7e5053db

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp313-cp313-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp313-cp313-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0b48b68aa1d22245e85bf9c81ed39617a3d7c06ac7994da490a2509dff1791c0
MD5 084a7ee71ba1fe10d025061a60b439d7
BLAKE2b-256 388df4af505e493018d2c60be4fd3c7912f1985a15da3f34f09cbcfb1fb6d5f3

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6123cc9efc7dca7205c0818100316c09ff79249e2666ad3e5b7f437094e5f9bb
MD5 5044628097115ef7809c8910289f3e66
BLAKE2b-256 23b897baa77ebfd0d61dcd2dd315a11f65cabdd094d0f5ce854de9fb879ea253

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: pysof-0.2.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 40.8 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for pysof-0.2.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 79a6b1648cd7f2b3b82f6fb725aa5ef121450383c3176bbde1095acfbf498431
MD5 a6bbf03ad8dd14fa9e31433b1a1a50f5
BLAKE2b-256 f3439bb2b6115924103119e0aa2067e38e01128b01a55787cd2095340857c212

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 c367725b001c887f83c93eb6098858a773bcd777fc0ce1208a6337f76bf37582
MD5 faa6fe2b7609bfe35fda817a27d5e944
BLAKE2b-256 5de52c1950aabb512857a8068b7af9afe1afe53c962a393a037ffceb672bc300

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp312-cp312-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp312-cp312-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 fd4dc24842614f5546232586948b55f6840a5370d7df5aaee2b9cadb726d1b5e
MD5 ab0c0802f57911137f6912aad0caa858
BLAKE2b-256 04f8ba3b0653699156a40e1437362db0a271f78b4c8ca71b4b88726f61620a1e

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a7e92f084fe3d440e7e2fd690094a94ba5150a81f0f3d1f33d8486a0da4aa627
MD5 561e4ce98355959d8702f574f3fb14ce
BLAKE2b-256 967712dee9b5554916bbddaca64496a084081fa98df55c2efe363cd059aa7059

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: pysof-0.2.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 40.8 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for pysof-0.2.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 2d36ce52857961c23ac95bbffc4c920c2a30b121791c7e2af57d231fe9447bd4
MD5 d1acc8a3985d7d09e323a4de4a33dc23
BLAKE2b-256 ce73b0f68a3cb39f6cd96b5d711282b5d579f49f32b440ff2ecc268cfa11c731

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp311-cp311-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp311-cp311-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 fafbea5780d546be8663593567315b134d7a1bf26ac4ae11cb56e44783790567
MD5 81b3d0fa7126f18ece423530ee4f8f19
BLAKE2b-256 ca2542d078b66b1a4e14fe699e60bcc00df5815561d3145d4c05ab8af9b8b35b

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9157ec10da6e1021df1dc1966cd35581826baa91e0b8cf6f8f187ba3aefdb65f
MD5 7056c0356407df1aff624e876ebc2ec6
BLAKE2b-256 43f98eb77951819755ee1334e39f2eac0764a0d42e36a3cd65a3d96389767ad5

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 090d15a5e16b76c5403edaef4df0f8a7406352934ebef63e8f15a4800bebc5d2
MD5 7dded436e22b45f13dd33794e323100b
BLAKE2b-256 fca7c9d6de50dbd47a2c763e74fe2099463722de05dfa5ae06664fda59c0bb30

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: pysof-0.2.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 40.8 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for pysof-0.2.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 1a2a12b7690f7fa9da72761e9eb95b405732f87eee111913e1240050e88d55bd
MD5 6c4b2828053862ee9db0daabdab26852
BLAKE2b-256 5009ee96f5f3213c51dad07b66f4fbfaa68c8ab72047f8dd3f7ddd6e5da83416

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp310-cp310-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp310-cp310-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 59fee56a0bd26e850ecc581d8cd62ebf8bf66b41a9e80b103af1ece5d9665049
MD5 80ec7950298679b4f2f50efe420b9d22
BLAKE2b-256 8fcf91a612023cc133d8f5d2e1d45c84cc9b1ca843afc1b34d5cff3fc05b26c7

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp310-cp310-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 979b18b83cd5e5ceba6b40e445c006a694c3c5c0af81a96a88b562e8ba67b0a8
MD5 f665fa76952166635a271c50ad08bae5
BLAKE2b-256 efaf49fac25ee09e7a4b82ea03d39b43ea87c6ba653ee9e0b51aeb490d19c0a7

See more details on using hashes here.

File details

Details for the file pysof-0.2.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pysof-0.2.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ce89460ad326e6787c76f65e0da776b9ca1851fa9a9c51846c17a616e26631ff
MD5 409c077d1c3522774b237026ad3a35b0
BLAKE2b-256 eea621458793c72d9adbe7bbf1cfb6e6858abc66bdd5cb02b7a2acad0a83d12e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page