Skip to main content

Save and load Bioconductor objects in Python

Project description

Project generated with PyScaffold PyPI-Server Monthly Downloads Unit tests

Save and load Bioconductor objects in Python

The dolomite-base package is the Python counterpart to the alabaster.base R package for language-agnostic reading and writing of Bioconductor objects (see the BiocPy project). This is a more robust and portable alternative to the typical approach of pickling Python objects to save them to disk.

  • By separating the on-disk representation from the in-memory object structure, we can more easily adapt to changes in class definitions. This improves robustness to Python environment updates.
  • By using standard file formats like HDF5 and CSV, we ensure that the objects can be easily read from other languages like R and Javascript. This improves interoperability between application ecosystems.
  • By breaking up complex Bioconductor objects into their components, we enable modular reads and writes to the backing store. We can easily read or update part of an object without having to consider the other parts.

The dolomite-base package defines the base generics to read and write the file structures along with the associated metadata. Implementations of these methods for various Bioconductor classes can be found in the other dolomite packages like dolomite-ranges and dolomite-se.

Quick start

First, we'll install the dolomite-base package. This package is available from PyPI so we can use the standard installation process:

pip install dolomite-base

The simplest example involves saving a BiocFrame inside a staging directory. Let's mock one up:

import biocframe
df = biocframe.BiocFrame({
    "X": list(range(0, 10)),
    "Y": [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ]
})
print(df)
## BiocFrame with 10 rows and 2 columns
##           X      Y
##     <range> <list>
## [0]       0      a
## [1]       1      b
## [2]       2      c
## [3]       3      d
## [4]       4      e
## [5]       5      f
## [6]       6      g
## [7]       7      h
## [8]       8      i
## [9]       9      j

We save our BiocFrame to a user-specified directory with the save_object() function. This function saves its input object to file according to the relevant specification.

import tempfile
import os
tmp = tempfile.mkdtemp()

import dolomite_base
path = os.path.join(tmp, "my_df")
dolomite_base.save_object(df, path)

os.listdir(path)
## ['basic_columns.h5', 'OBJECT']

We load the contents of the directory back into a Python session by using the read_object() function. Note that the exact Python types for the BiocFrame columns may not be preserved by the round trip, though the contents of the columns will be unchanged.

out = dolomite_base.read_object(path)
print(out)
BiocFrame with 10 rows and 2 columns
##                    X            Y
##     <ndarray[int32]> <StringList>
## [0]                0            a
## [1]                1            b
## [2]                2            c
## [3]                3            d
## [4]                4            e
## [5]                5            f
## [6]                6            g
## [7]                7            h
## [8]                8            i
## [9]                9            j

Check out the API reference for more details.

Supported classes

The saving/reading process can be applied to a range of BiocPy data structures, provided the appropriate dolomite package is installed. Each package implements a saving and reading function for its associated classes, which are automatically used from dolomite-base's save_object() and read_object() functions, respectively. (That is, there is no need to explicitly import the package when calling save_object() or read_object() for its classes.)

Package Object types PyPI
dolomite-base BiocFrame, list, dict, NamedList
dolomite-matrix numpy.ndarray, scipy.sparse.spmatrix, DelayedArray
dolomite-ranges GenomicRanges, GenomicRangesList
dolomite-se SummarizedExperiment, RangedSummarizedExperiment
dolomite-sce SingleCellExperiment
dolomite-mae MultiAssayExperiment

Each class's on-disk representation is determined by the associated takane specification. For more complex objects, the on-disk representation may consist of multiple files, or even subdirectories containing "child" objects from internal save_object() calls. Each call to save_object() will automatically enforce the relevant specification by validating the directory contents with dolomite-base's validate_object() function. This provides some guarantees on the file structure within the directory, allowing developers to reliably implement readers in a variety of frameworks - for example, the alabaster will run the same validators on its directory contents to guarantee interoperability.

All of the listed packages are available from PyPI and can be installed with the usual pip install procedure. Alternatively, to install all packages in one go, users can install the dolomite umbrella package.

Operating on directories

Users can move freely rename or relocate directories and read_object() function will still work. For example, we can easily copy the entire directory to a new file system and everything will still be correctly referenced within the directory. The simplest way to share objects is to just zip or tar the staging directory for ad hoc distribution. For more serious applications, r self can be used in conjunction with storage systems like AWS S3 for easier distribution.

# Mocking up an object:
import biocframe
df = biocframe.BiocFrame({
    "X": list(range(0, 10)),
    "Y": [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ]
})

# Saving to one location:
import tempfile
import os
import dolomite_base
tmp = tempfile.mkdtemp()
path = os.path.join(tmp, "my_df")
dolomite_base.save_object(df, path)

# Reading from another location:
alt_path = os.path.join(tmp, "foobar")
os.rename(path, alt_path)
alt_out = dolomite_base.read_object(alt_path)

That said, it is unwise to manipulate the files inside the directory created by save_object(). Reading functions will usually depend on specific file names or subdirectory structures within the directory, and fiddling with them may cause unexpected results. Advanced users can exploit this by loading components from subdirectories if the full object is not required:

# Creating a nested DF:
nested = biocframe.BiocFrame({ "A": df })
nest_path = os.path.join(tmp, "nesting")
dolomite_base.save_object(nested, nest_path)

# Now reading in the nested DF:
redf = dolomite_base.read_object(os.path.join(nest_path, "other_columns", "0"))

Extending to new classes

The dolomite framework is easily extended to new classes by:

  1. Writing a method for save_object(). This should accept an instance of the object and a path to a directory, and save the contents of the object inside the directory. It should also produce an OBJECT file that specifies the type of the object, e.g., data_frame, hdf5_sparse_matrix.
  2. Writing a function for read_object() and registering it in the read_object_registry. This should accept a path to a directory and read its contents to reconstruct the object. The registered type should be the same as that used in the OBJECT file.
  3. Writing a function for validate_object() and registering it in the validate_object_registry. This should accept a path to a directory and read its contents to determine if it is a valid on-disk representation. The registered type should be the same as that used in the OBJECT file.
    • (optional) Devleopers can alternatively formalize the on-disk representation by adding a specification to the takane repository. This aims to provide C++-based validators for each representation, allowing us to enforce consistency across multiple languages (e.g., R). Any takane validator is automatically used by validate_object() so no registration is required.

To illustrate, let's extend dolomite to a new custom class:

class Coffee:
    def __init__(self, beans: str, milk: bool):
        self.beans = beans
        self.milk = milk

First we implement the saving method. Note that we add a @validate_saves decorator to instruct save_object() to automatically run validate_object() on the generated directory, to confirm that the output is valid.

import dolomite_base
import os
import json

@dolomite_base.save_object.register
@dolomite_base.validate_saves
def save_object_for_Coffee(x: Coffee, path: str, **kwargs):
    os.mkdir(path)
    with open(os.path.join(path, "bean_type"), "w") as handle:
        handle.write(x.beans)
    with open(os.path.join(path, "has_milk"), "w") as handle:
        handle.write("true" if x.milk else "false")
    with open(os.path.join(path, "OBJECT"), "w") as handle:
        json.dump({ "type": "coffee", "coffee": { "version": "0.1" } }, handle)

Then the reading method:

from typing import Dict

def read_Coffee(path: str, metadata: Dict, **kwargs) -> Coffee:
    metadata["coffee"]["version"] # possibly do something different based on version
    with open(os.path.join(path, "bean_type"), "r") as handle:
        beans = handle.read()
    with open(os.path.join(path, "has_milk"), "r") as handle:
        milk = (handle.read() == "true")
    return Coffee(beans, milk)

dolomite_base.read_object_registry["coffee"] = read_Coffee

And finally, the validation method:

def validate_Coffee(path: str, metadata: Dict):
    metadata["coffee"]["version"] # possibly do something different based on version
    with open(os.path.join(path, "bean_type"), "r") as handle:
        beans = handle.read()
        if not beans in [ "arabica", "robusta", "excelsa", "liberica" ]:
            raise ValueError("wrong bean type '" + beans + "'")
    with open(os.path.join(path, "has_milk"), "r") as handle:
        milk = handle.read()
        if not milk in [ "true", "false" ]:
            raise ValueError("invalid milk '" + milk + "'")

dolomite_base.validate_object_registry["coffee"] = validate_Coffee

Let's run them and see how it works:

cup = Coffee("arabica", milk=False)

import tempfile
tmp = tempfile.mkdtemp()
path = os.path.join(tmp, "stuff")
dolomite_base.save_object(cup, path)

cup2 = dolomite_base.read_object(path)
print(cup2.beans)
## arabica

For more complex objects that are composed of multiple smaller "child" objects, developers should consider saving each of their children in subdirectories of path. This can be achieved by calling alt_save_object() and alt_read_object() in the saving and loading functions, respectively. (We use the alt_* versions of these functions to respect application overrides, see below.)

Creating applications

Developers can also create applications that customize the machinery of the dolomite framework for specific needs. In most cases, this involves storing more metadata to describe the object in more detail. For example, we might want to remember the identity of the author for each object. This is achieved by creating an application-specific saving generic with the same signature as save_object():

from functools import singledispatch
from typing import Any, Dict, Optional
import dolomite_base
import json
import os
import getpass
import biocframe

def dump_extra_metadata(path: str, extra: Dict):
    user_id = getpass.getuser()
    # File names with leading underscores are reserved for application-specific
    # use, so they won't clash with anything produced by save_object().
    metapath = os.path.join(path, "_metadata.json")
    with open(metapath, "w") as handle:
        json.dump({ **extra, "author": user_id }, handle)

@singledispatch
def app_save_object(x: Any, path: str, **kwargs):
    dolomite_base.save_object(x, path, **kwargs) # does the real work
    dump_extra_metadata(path, {}) # adding some application-specific metadata

@app_save_object.register
def app_save_object_for_BiocFrame(x: biocframe.BiocFrame, path: str, **kwargs):
    dolomite_base.save_object(x, path, **kwargs) # does the real work
    # We can also override specific methods to add object+application-specific metadata:
    dump_extra_metadata(path, { "columns": x.get_column_names().as_list() })

Applications should call alt_save_object_function() to instruct alt_save_object() to use this new generic. This ensures that the customizations are applied to all child objects, such as the nested BiocFrame below.

# Create a friendly user-visible function to handle the generic override; this
# is reversed on function exit to avoid interfering with other applications.
def save_for_application(x, path: str, **kwargs):
    old = dolomite_base.alt_save_object_function(app_save_object)
    try:
        dolomite_base.alt_save_object(x, path, **kwargs)
    finally:
        dolomite_base.alt_save_object_function(old)

# Saving our nested BiocFrames with our overrides active.
import biocframe
df = biocframe.BiocFrame({
    "A": [1, 2, 3, 4],
    "B": biocframe.BiocFrame({
        "C": ["a", "b", "c", "d"]
    })
})

import tempfile
tmp = tempfile.mkdtemp()
path = os.path.join(tmp, "foobar")
save_for_application(df, path)

# Both the parent and child BiocFrames have new metadata.
with open(os.path.join(path, "_metadata.json"), "r") as handle:
    print(handle.read())
## {"columns": ["A", "B"], "author": "aaron"}

with open(os.path.join(path, "other_columns", "1", "_metadata.json"), "r") as handle:
    print(handle.read())
## {"columns": ["C"], "author": "aaron"}

The reading function can be similarly overridden by setting alt_read_object_function() to instruct all alt_read_object() calls to use the override. This allows applications to, e.g., do something with the metadata that we just added.

def app_read_object(path: str, metadata: Optional[Dict] = None, **kwargs):
    if metadata is None:
        with open(os.path.join(path, "OBJECT"), "r") as handle:
            metadata = json.load(handle)

    # Print custom message based on the type and application-specific metadata.
    with open(os.path.join(path, "_metadata.json"), "r") as handle:
        appmeta = json.load(handle)
        print("I am a " + metadata["type"] + " created by " + appmeta["author"])
        if metadata["type"] == "data_frame":
            print("I have the following columns: " + ", ".join(appmeta["columns"]))

    return dolomite_base.read_object(path, metadata=metadata, **kwargs)

# Creating a user-friendly function to set the override before the read.
def read_for_application(path: str, metadata: Optional[Dict] = None, **kwargs):
    old = dolomite_base.alt_read_object_function(app_read_object)
    try:
        return dolomite_base.alt_read_object(path, metadata=metadata, **kwargs)
    finally:
        dolomite_base.alt_read_object_function(old)

# This diverts to the override with printing of custom messages.
read_for_application(path)
## I am a data_frame created by aaron
## I have the following columns: A, B
## I am a data_frame created by aaron
## I have the following columns: C

By overriding the saving and reading process for one or more classes, each application can customize the behavior of dolomite to their own needs. In general, applications should avoid modifying the files created by save_object(), to avoid violating any takane format specifications (unless the application maintainer really knows what they're doing). Applications are free to write to any path starting with an underscore as this will not be used by any specification.

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

dolomite-base-0.2.1.tar.gz (56.1 kB view details)

Uploaded Source

Built Distributions

dolomite_base-0.2.1-cp312-cp312-musllinux_1_1_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.12 musllinux: musl 1.1+ x86-64

dolomite_base-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

dolomite_base-0.2.1-cp312-cp312-macosx_13_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.12 macOS 13.0+ ARM64

dolomite_base-0.2.1-cp312-cp312-macosx_11_0_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.12 macOS 11.0+ x86-64

dolomite_base-0.2.1-cp311-cp311-musllinux_1_1_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.11 musllinux: musl 1.1+ x86-64

dolomite_base-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

dolomite_base-0.2.1-cp311-cp311-macosx_13_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.11 macOS 13.0+ ARM64

dolomite_base-0.2.1-cp311-cp311-macosx_11_0_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.11 macOS 11.0+ x86-64

dolomite_base-0.2.1-cp310-cp310-musllinux_1_1_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.10 musllinux: musl 1.1+ x86-64

dolomite_base-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

dolomite_base-0.2.1-cp310-cp310-macosx_13_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.10 macOS 13.0+ ARM64

dolomite_base-0.2.1-cp310-cp310-macosx_11_0_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.10 macOS 11.0+ x86-64

dolomite_base-0.2.1-cp39-cp39-musllinux_1_1_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.9 musllinux: musl 1.1+ x86-64

dolomite_base-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

dolomite_base-0.2.1-cp39-cp39-macosx_13_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.9 macOS 13.0+ ARM64

dolomite_base-0.2.1-cp39-cp39-macosx_11_0_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.9 macOS 11.0+ x86-64

dolomite_base-0.2.1-cp38-cp38-musllinux_1_1_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.8 musllinux: musl 1.1+ x86-64

dolomite_base-0.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.6 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

dolomite_base-0.2.1-cp38-cp38-macosx_13_0_arm64.whl (1.7 MB view details)

Uploaded CPython 3.8 macOS 13.0+ ARM64

dolomite_base-0.2.1-cp38-cp38-macosx_11_0_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.8 macOS 11.0+ x86-64

File details

Details for the file dolomite-base-0.2.1.tar.gz.

File metadata

  • Download URL: dolomite-base-0.2.1.tar.gz
  • Upload date:
  • Size: 56.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.7

File hashes

Hashes for dolomite-base-0.2.1.tar.gz
Algorithm Hash digest
SHA256 337a1d49e6969cb459fedb08d9b4b37c8c7a0c5cd48907417f1438b6860012bb
MD5 65cb7c882614596c54581843ed2b002b
BLAKE2b-256 50309fa9879ec306c8109e52a47f47f8d4564056bc5a1c80707a605d822e5da9

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp312-cp312-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp312-cp312-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 3099c311039746a67f77d441c281071acba5fac22ad515dc36701e315e93d193
MD5 af6b41e1b2d7503e71957031ce1bc603
BLAKE2b-256 23b76d6375ae3ce1cc68a87e58433397e55e6a23fec71e8e78dc2c5881843c20

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5db05fe70bcacabd00a103247f178a7f049ac66e674ef7e4ea8e636645f116d6
MD5 e99ad694a5da3f2f1ff2e2d0047e724a
BLAKE2b-256 9b255030194a8bc57061f29bd2b1afec0b77c3c41c2240e4307bf30b4b08df1e

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp312-cp312-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp312-cp312-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 b6e099661bf31c1ee40abca94676abb77fd7f655da9dfd761a5ae634e6aea52d
MD5 80ae18677c5f02351fb497976cefaa37
BLAKE2b-256 4b507207a6ffec3cc1b0b9f66ddc5ed8f297513aa6ade675525e768a83f9594d

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp312-cp312-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp312-cp312-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 2861421ffc1bfdcfb523b46112b603e2e147bb27e130551c722b13560044d487
MD5 d47ea2b162f55b2b234600c0d788a12f
BLAKE2b-256 2aa9faa8ed051009e6adf26698c1f85d5092b4814bf7c6208435bed9b2614d62

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp311-cp311-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 48064e54acaa06020ea5fccc60186d2d5581e25cd154abbd7d4ddc005dad77d2
MD5 74aee526ce0a20ea40e76cb01b7a5983
BLAKE2b-256 98d25451723032b77fd0d3fc4e0d6fed537b02824c6a7d5a780d4036005ab1aa

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1dd34854aaeb6e6eec520ce3b163df56b959f77539af97b54f2776a303ea742c
MD5 0081234f8abfab1d08f3845ded40ed41
BLAKE2b-256 929b108b2a572f85cd8d2b6e40b74b892bd39dec83ce262baf9d03b145a1c437

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp311-cp311-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp311-cp311-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 9ec9ae6201f47e2ecd1b33cff8eb02e7e5065c7650a9de4a7cd85eede33eee0c
MD5 d6b1a92de6082def7d6837503aaf67c8
BLAKE2b-256 3d56aa8d970eb88f4508aed90757bd208d1583d6ba68c3564a7003c079b3e3e0

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp311-cp311-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 afff8bfe5b28f16cc50b8c54b9df9491c111f9cd5ab0808c3cdc5544dbab50e6
MD5 a000dedc0ce714fa066e39205a78d44a
BLAKE2b-256 216502cb1d8b908f16d6ad860526f98ce85b810d61ec7cd94204401ce268f386

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp310-cp310-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 83dba8859bd2a752e485b039f746522de3e8086380c71afce8fdb9c9d6b5ddeb
MD5 fd85c42ce96777cffce32f099a5cf1fd
BLAKE2b-256 73d1c697e96afa9fb447a61690c92152df8d75840cc3e429b3f9b3ae2d923293

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 76376286f3bdab974019727f0bb110cf16655e41aa4c322d87175bb64d52b5ad
MD5 842fe50a6396cddc51eba300eadac19f
BLAKE2b-256 17ff8f94338f54d6649ff7445738cbe25066ae75ec6de8d9a08a096d11088e26

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp310-cp310-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp310-cp310-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 cf58ec68c590b2a418113cb5e1931cfede1faf3a4292ee18faeb3d79be384ba3
MD5 9b20ee2f1630128b27ca871f15651a98
BLAKE2b-256 690443f18f06a39a585be82736057704329801b30273d3d4fccbe03e176d827e

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp310-cp310-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp310-cp310-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 1ca94ad67b9b139b9dab9311b6b7335a540206f4becae2b8614204cf82c20b76
MD5 ec8c01a89bbde1cb67ab94a0d266757c
BLAKE2b-256 0dd5d2e2e1ed7f42063edbcc327514cc45f51dcc2091d3143908867873a4b2d2

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp39-cp39-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 97befd562eeeb1c9337f7eda50a6c66b8b37ffcc57a861e14febb49dd7c14833
MD5 83995307af2419c1aa294effdeff8f90
BLAKE2b-256 e13d778b111f3b84292fbaa87b1fd7de35a527ec44228b828eb6726c8993f3cb

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 69bad03d82ad0d2c922da64327eeaefc07acb383fe7e1fc863dc83069b3c9478
MD5 1150e476f7fdce6cc8d67a26ce040c56
BLAKE2b-256 831398043103b0b6a6f0171f8774a0569b4928619d4e00d209669d61e424fd4e

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp39-cp39-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp39-cp39-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 94bee5403abbf6ae2de520e6fc21efcf509ba37976300cf6a83bbd2a407f9f0f
MD5 655af3307c8831f758c7ca05af655d21
BLAKE2b-256 dbab467c38976c99d582621ed38afd8378bd5ba43f5af6de4104ca7085b1a191

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp39-cp39-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp39-cp39-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 48ce428e75745b73f0ea0ce2ff97202848a88154ce47a90c330989ced18357d5
MD5 c97842645cb82be82d423844727e642d
BLAKE2b-256 16124da102ecd254a3504625a2d17ad2a2e901b0d97b9138088f2b069d4ae67d

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp38-cp38-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 e3ebd57cab05e80e2a093c2d871ff79fca0c37bf7b09b78b0c612590e3f2a484
MD5 b5faa458b3e8dfa52e1031018d329f60
BLAKE2b-256 7ad366ae8985c58339a3dd885753d52643ed3e0ead587cf9e38ab24bbff4a32b

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fd0449a098a027aeb4795da2b87d4373836a848947a65c25d9ebfa329f5c1888
MD5 7320433ee21ff62d41523a7d2f4c8de4
BLAKE2b-256 93a1a1dbe6f6d0027e68de7dcbed3f50fb9a76e194e4161c189165be37709f97

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp38-cp38-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp38-cp38-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 90bbccde62567f6b245d83042574ed58bfdfd6b13eb27056fda6b9d2eb948068
MD5 e84bdb08384b103954c0137a9b7ca555
BLAKE2b-256 e086ec8aa704ce53393bec74cede8238233f583a793171b8577d48c3b1540cb6

See more details on using hashes here.

File details

Details for the file dolomite_base-0.2.1-cp38-cp38-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for dolomite_base-0.2.1-cp38-cp38-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 926688016d299af0de61cc51450878df3aeb81116e2761d72ad4758a6613eff9
MD5 9f65deb0e6826c7e9837b200fb890178
BLAKE2b-256 acdad8566f4fd1d5c9d867b3a2f61f61fc6dc23fceb41c3aebe1873ca9ad752f

See more details on using hashes here.

Supported by

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