Skip to main content

Python interface to PartMC

Project description

logo

PyPartMC

PyPartMC is a Python interface to PartMC, a particle-resolved Monte-Carlo code for atmospheric aerosol simulation. Development of PyPartMC has been intended to remove limitations to the use of Fortran-implemented PartMC. PyPartMC facilitates the dissemination of computational research results by streamlining independent execution of PartMC simulations (also during peer-review processes). Additionally, the ability to easily package examples, simple simulations, and results in a web-based notebook allows PyPartMC to support the efforts of many members of the scientific community, including researchers, instructors, and students, with nominal software and hardware requirements.

Documentation of PyPartMC is hosted at https://open-atmos.github.io/PyPartMC. PyPartMC is implemented in C++ and it also constitutes a C++ API to the PartMC Fortran internals (C++ example below). The Python API can facilitate using PartMC from other environments - see, e.g., Julia and Matlab examples below.

For an outline of the project, rationale, architecture, and features, refer to: D'Aquino et al., 2024 (SoftwareX) (please cite if PyPartMC is used in your research). For a list of talks and other relevant resources, please see project Wiki. If interested in contributing to PyPartMC, please have a look a the notes for developers.

US Funding PL Funding

License: GPL v3 Copyright tests+pypi API docs codecov DOI PyPI version Project Status: Active – The project has reached a stable, usable state and is being actively developed. pyOpenSci Peer-Reviewed

Python 3 Linux OK macOS OK Windows OK Jupyter

Installation

Using the command-line pip tool (also applies to conda environments)

pip install PyPartMC

Note that, depending on the environment (OS, hardware, Python version), the pip-install invocation may either trigger a download of a pre-compiled binary, or trigger compilation of PyPartMC. In the latter case, a Fortran compiler and some development tools includiong CMake, m4 and perl are required (while all non-Python dependencies are included in the PyPartMC source archive). In both cases, all Python dependencies will be resolved by pip.

In a Jupyter notebook cell (also on Colab or jupyter-hub instances)

! pip install PyPartMC
import PyPartMC

Jupyter notebooks with examples

Note: clicking the badges below redirects to cloud-computing platforms. The mybinder.org links allow anonymous execution, Google Colab requires logging in with a Google account, ARM JupyerHub requires logging in with an ARM account (and directing Jupyter to a particular notebook within the examples folder).

The example notebooks feature additional dependencies that can be installed with:

pip install PyPartMC[examples]
  • Urban plume scenario demo (as in PartMC):
    View notebook Open In Colab Binder ARM JupyterHub
  • Chamber simulation example from Barrel Study (Tian el al., 2017):
    View notebook Open In Colab Binder ARM JupyterHub
  • Dry-Wet Particle Size Equilibration with PartMC and PySDM:
    View notebook Open In Colab Binder ARM JupyterHub Voila
  • Simulation output processing example (loading from netCDF files using PyPartMC):
    View notebook Open In Colab Binder ARM JupyterHub
  • Optical properties calculation using external Python package (PyMieScatt):
    View notebook Open In Colab Binder ARM JupyterHub
  • Cloud parcel example featuring supersaturation-evolution-coupled CCN activation and drop growth:
    View notebook Open In Colab Binder ARM JupyterHub
  • Immersion freezing example:
    View notebook Open In Colab Binder ARM JupyterHub
  • Coagulation model intercomparison for additive (Golovin) kernel with: PyPartMC, PySDM, Droplets.jl and dustpy:
    View notebook Open In Colab Binder ARM JupyterHub
  • Particle simulation with multiphase chemistry handled using CAMP (without coagulation):
    View notebook Open In Colab Binder ARM JupyterHub

Features

  • works on Linux, macOS and Windows (compatibility assured with CI builds)
  • hassle-free installation using pip (prior PartMC installation not needed)
  • works out of the box on mybinder.org, Google Colab and alike
  • ships with a set of examples maintained in a form of Jupyter notebooks
  • Pythonic API (but retaining PartMC jargon) incl. Python GC deallocation of Fortran objects
  • specification of parameters using native Python datatypes (lists, dicts) in place of PartMC spec files
  • code snippets in README depicting how to use PyPartMC from Julia and Matlab (also executed on CI)
  • auto-generated API docs on the web
  • support for [de]serialization of selected wrapped structures using JSON
  • based on unmodified PartMC code
  • does not use or require shell or any pre-installed libraries
  • aiming at 100% unit test coverage

Usage examples

The listings below depict how the identical task of randomly sampling particles from an aerosol size distribution in PartMC can be done in different programming languages.

For a Fortran equivalent of the Python, Julia and Matlab programs below, see the readme_fortran folder.

Python

import numpy as np

import PyPartMC as ppmc
from PyPartMC import si

aero_data = ppmc.AeroData((
    #      [density, ions in solution, molecular weight, kappa, abifm_m, abifm_c]
    {"OC": [1000 *si.kg/si.m**3, 0, 1e-3 *si.kg/si.mol, 0.001, 0, 0]},
    {"BC": [1800 *si.kg/si.m**3, 0, 1e-3 *si.kg/si.mol, 0, 0 , 0]},
))

aero_dist = ppmc.AeroDist(
    aero_data,
    [{
        "cooking": {
            "mass_frac": [{"OC": [1]}],
            "diam_type": "geometric",
            "mode_type": "log_normal",
            "num_conc": 3200 / si.cm**3,
            "geom_mean_diam": 8.64 * si.nm,
            "log10_geom_std_dev": 0.28,
        },
        "diesel": {
            "mass_frac": [{"OC": [0.3]}, {"BC": [0.7]}],
            "diam_type": "geometric",
            "mode_type": "log_normal",
            "num_conc": 2900 / si.cm**3,
            "geom_mean_diam": 50 * si.nm,
            "log10_geom_std_dev": 0.24,
        }
    }],
)

n_part = 100
aero_state = ppmc.AeroState(aero_data, n_part, "nummass_source")
aero_state.dist_sample(aero_dist)
print(np.dot(aero_state.masses(), aero_state.num_concs), "# kg/m3")

C++

#include <iostream>
#include <memory>
#include <numeric>

#include "PyPartMC.hpp"
#include "PyPartMC/si.hpp"

int main() {
    auto aero_data = std::make_shared<AeroData>(nlohmann::json({
        { {"OC", {1000.0 * si::kg / (si::m * si::m * si::m), 0.0, 1e-3 * si::kg / si::mol, 0.001, 0.0, 0.0}} },
        { {"BC", {1800.0 * si::kg / (si::m * si::m * si::m), 0.0, 1e-3 * si::kg / si::mol, 0.0,   0.0, 0.0}} }
    }));

    auto aero_dist = AeroDist(
        aero_data, 
        nlohmann::ordered_json::array({
            nlohmann::ordered_json::object({
                {"cooking", {
                    {"mass_frac", nlohmann::ordered_json::array({ nlohmann::ordered_json::object({{"OC", {1.0}}}) }) }, 
                    {"diam_type", "geometric"},
                    {"mode_type", "log_normal"},
                    {"num_conc", 3200.0 / (si::cm * si::cm * si::cm)},
                    {"geom_mean_diam", 8.64 * si::nm},
                    {"log10_geom_std_dev", 0.28}
                }},
                {"diesel", {
                    {"mass_frac", nlohmann::ordered_json::array({ nlohmann::ordered_json::object({{"OC", {0.3}}}), nlohmann::ordered_json::object({{"BC", {0.7}}}) }) }, 
                    {"diam_type", "geometric"},
                    {"mode_type", "log_normal"},
                    {"num_conc", 2900.0 / (si::cm * si::cm * si::cm)},
                    {"geom_mean_diam", 50.0 * si::nm},
                    {"log10_geom_std_dev", 0.24}
                }}
            })
        })
    );

    int n_part = 100;
    auto aero_state = AeroState(aero_data, n_part, "nummass_source");
    
    AeroState::dist_sample(aero_state, aero_dist, 1.0, 0.0, true, true);

    auto masses = AeroState::masses(aero_state, {}, {});
    auto num_concs = AeroState::num_concs(aero_state);

    double total_mass = std::inner_product(
        std::begin(num_concs), std::end(num_concs), 
        std::begin(masses), 
        0.0
    );
    
    std::cout << std::scientific << total_mass << " # kg/m3\n";

    return 0;
}

What can be compiled using CMake with following CMakeLists.txt:

cmake_minimum_required(VERSION 3.22)
project(AeroSimulation LANGUAGES CXX)

enable_testing()
set(CMAKE_CXX_STANDARD 17)

find_package(Python 3.8 REQUIRED COMPONENTS Interpreter)
execute_process(
    COMMAND ${Python_EXECUTABLE} -c "import PyPartMC, pathlib; print(pathlib.Path(PyPartMC.cmake_dir()).as_posix())"
    OUTPUT_VARIABLE PYPARTMC_CMAKE_DIR
    OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(PyPartMC_DIR "${PYPARTMC_CMAKE_DIR}")

find_package(PyPartMC REQUIRED)

add_executable(my_test test.cpp)
target_link_libraries(my_test PRIVATE PyPartMC::PyPartMC)
pypartmc_setup_runtime(my_test)

add_test(NAME maketest COMMAND my_test)

Julia (using PyCall.jl)

using Pkg
Pkg.add("PyCall")

using PyCall
ppmc = pyimport("PyPartMC")
si = ppmc["si"]

aero_data = ppmc.AeroData((
  #       (density, ions in solution, molecular weight, kappa, abifm_m, abifm_c)
  Dict("OC"=>(1000 * si.kg/si.m^3, 0, 1e-3 * si.kg/si.mol, 0.001, 0, 0)),
  Dict("BC"=>(1800 * si.kg/si.m^3, 0, 1e-3 * si.kg/si.mol, 0, 0, 0))
))

aero_dist = ppmc.AeroDist(aero_data, (
  Dict( 
    "cooking" => Dict(
      "mass_frac" => (Dict("OC" => (1,)),),
      "diam_type" => "geometric",
      "mode_type" => "log_normal",
      "num_conc" => 3200 / si.cm^3,
      "geom_mean_diam" => 8.64 * si.nm,
      "log10_geom_std_dev" => .28,
    ),
    "diesel" => Dict(
      "mass_frac" => (Dict("OC" => (.3,)), Dict("BC" => (.7,))),
      "diam_type" => "geometric",
      "mode_type" => "log_normal",
      "num_conc" => 2900 / si.cm^3,
      "geom_mean_diam" => 50 * si.nm,
      "log10_geom_std_dev" => .24,
    )
  ),
))

n_part = 100
aero_state = ppmc.AeroState(aero_data, n_part, "nummass_source")
aero_state.dist_sample(aero_dist)
print(aero_state.masses()'aero_state.num_concs, "# kg/m3")

Matlab (using Matlab's built-in Python interface)

notes (see the PyPartMC Matlab CI workflow for an example on how to achieve it on Ubuntu 20):

  • Matlab ships with convenience copies of C, C++ and Fortran runtime libraries which are dlopened() by default; one way to make PyPartMC OK with it is to [pip-]install by compiling from source using the very same version of GCC that Matlab borrowed these libraries from (e.g., GCC 9 for Matlab R2022a, etc);
  • Matlab needs to use the same Python interpretter/venv as the pip invocation used to install PyPartMC;
ppmc = py.importlib.import_module('PyPartMC');
si = py.importlib.import_module('PyPartMC').si;

aero_data = ppmc.AeroData(py.tuple({ ...
  py.dict(pyargs("OC", py.tuple({1000 * si.kg/si.m^3, 0, 1e-3 * si.kg/si.mol, 0.001, 0, 0}))), ...
  py.dict(pyargs("BC", py.tuple({1800 * si.kg/si.m^3, 0, 1e-3 * si.kg/si.mol, 0, 0, 0}))) ...
}));

aero_dist = ppmc.AeroDist(aero_data, py.tuple({ ...
  py.dict(pyargs( ...
    "cooking", py.dict(pyargs( ...
      "mass_frac", py.tuple({py.dict(pyargs("OC", py.tuple({1})))}), ...
      "diam_type", "geometric", ...
      "mode_type", "log_normal", ...
      "num_conc", 3200 / si.cm^3, ...
      "geom_mean_diam", 8.64 * si.nm, ...
      "log10_geom_std_dev", .28 ...
    )), ...
    "diesel", py.dict(pyargs( ...
      "mass_frac", py.tuple({ ...
        py.dict(pyargs("OC", py.tuple({.3}))), ...
        py.dict(pyargs("BC", py.tuple({.7}))), ...
      }), ...
      "diam_type", "geometric", ...
      "mode_type", "log_normal", ...
      "num_conc", 2900 / si.cm^3, ...
      "geom_mean_diam", 50 * si.nm, ...
      "log10_geom_std_dev", .24 ...
    )) ...
  )) ...
}));

n_part = 100;
aero_state = ppmc.AeroState(aero_data, n_part, "nummass_source");
aero_state.dist_sample(aero_dist);
masses = cell(aero_state.masses());
num_concs = cell(aero_state.num_concs);
fprintf('%g # kg/m3\n', dot([masses{:}], [num_concs{:}]))

usage in other projects

PyPartMC is used within the test workflow of the PySDM project.

Other packages with relevant feature scope

  • aerosolGDEFoam: OpenFOAM CFD-coupled aerosol dynamics including nucleation, coagulation, and surface growth
  • AIOMFAC and AIOMFAC-web: Fortran-implemented aerosol thermodynamic model for calculation of activity coefficients in organic-inorganic mixtures – from simple binary solutions to complex multicomponent systems
  • DustPy: Python package for modelling dust evolution in protoplanetary disks (differences: focus on astrophysical applications vs. atmospheric aerosol)
  • multilayerpy: kinetic multi-layer model for aerosol particles and films
  • PyBox: aerosol simulation model featuring gas and particle chamistry (differences: PyBox focuses on chemical mechanisms; PyPartMC is an interface to PartMC which focuses on physics - e.g., collisions of aerosol particles - while chemical processes are handled with external software, e.g., CAMP or MOSAIC)
  • PyCHAM: CHemistry with Aerosol Microphysics in Python Box Model for modelling of indoor environments, including aerosol chambers
  • PySDM: particle-based Monte-Carlo aerosol-cloud simulation package (differences: PySDM focuses on growth and breakup processes relevant to cloud droplets; PyPartMC focuses on processes relevant to air pollutants and their chemical and physical transformations)
  • SSH-aerosol: C++/Fortran package for simulating evolution of primary and secondary atmospheric aerosols

FAQ

  • Q: How to install PyPartMC with MOSAIC enabled?
    A: Installation can be done using pip, however, pip needs to be instructed not to use binary packages available at pypi.org but rather to compile from source (pip will download the source from pip.org), and the path to compiled MOSAIC library needs to be provided at compile-time; the following command should convey it:
MOSAIC_HOME=<<PATH_TO_MOSAIC_LIB>> pip install --force-reinstall --no-binary=PyPartMC PyPartMC
  • Q: Why pip install PyPartMC triggers compilation on my brand new Apple machine, while it quickly downloads and installs binary packages when executed on older Macs, Windows or Linux?
    A: We are providing binary wheels on PyPI for Apple-silicon (arm64) machines for selected macOS version made available by Github. In case the macOS version you are using is newer, compilation from source is triggered.

  • Q: Why some of the constructors expect data to be passed as lists of single-entry dictionaries instead of multi-element dictionaries?
    A: This is intentional and related with PartMC relying on the order of elements within spec-file input; while Python dictionaries preserve ordering (insertion order), JSON format does not, and we intend to make these data structures safe to be [de]serialized using JSON.

  • Q: How to check the version of PartMC that PyPartMC was compiled against?
    A: Version numbers of compile-time dependencies of PyPartMC, including PartMC, can be accessed as follows:

import PyPartMC
PyPartMC.__versions_of_build_time_dependencies__['PartMC']
  • Q: Why m4 and perl are required at compile time?
    A: PyPartMC includes parts of netCDF and HDF5 codebases which depend on m4 and perl, respectively, for generating source files before compilation.

Troubleshooting

Common installation issues

error: [Errno 2] No such file or directory: 'cmake'

Try rerunning after installing CMake, e.g., using apt-get install cmake (Ubuntu/Debian), brew install cmake (homebrew on macOS) or using MSYS2 on Windows.

No CMAKE_Fortran_COMPILER could be found.

Try installing a Fortran compiler (e.g., brew reinstall gcc with Homebrew on macOS or using MSYS2 on Windows).

Could not find NC_M4 using the following names: m4, m4.exe

Try installing m4 (e.g., using MSYS2 on Windows).

Acknowledgement and citations

We would greatly appreciate citation of the PartMC model description paper (Riemer et al., 2009) and the PyPartMC description paper (D’Aquino et al., 2024) if PyPartMC was used in your study. The citations are:

  • Riemer, N., M. West, R. A. Zaveri, R. C. Easter: Simulating the evolution of soot mixing-state with a particle-resolved aerosol model
    J. Geophys. Res., 114, D09202, 2009, DOI: 10.1029/2008JD011073
  • D’Aquino, Z., S. Arabas, J. H. Curtis, A. Vaishnav, N. Riemer, M. West: PyPartMC: A pythonic interfact to a particle-resolved, Monte Carlo aerosol simulation framework
    SoftwareX, 25, 101613, 2024, DOI: 10.1016/j.softx.2023.101613

The following paragraph provides a more substantial description of PartMC (text released into the public domain and can be freely copied by anyone for any purpose):

PartMC is a stochastic, particle-resolved aerosol box model. It tracks the composition of many computational particles (104 to 106) within a well-mixed air volume, each represented by a composition vector that evolves based on physical and chemical processes. The physical processes—including Brownian coagulation, new particle formation, emissions, dilution, and deposition—are simulated using a stochastic Monte Carlo approach via a Poisson process while chemical processes are simulated deterministically for each computational particle. The weighted flow algorithm (DeVille, Riemer, and West, 2011, 2019) enhances efficiency and reduces ensemble variance. Detailed numerical methods are described in Riemer et al. (2009), DeVille et al. (2011, 2019), and Curtis et al. (2016). PartMC is open-source under the GNU GPL v2 and available at github.com/compdyn/partmc.

References:

  • Curtis, J. H., M. D. Michelotti, N. Riemer, M. T. Heath, M. West: Accelerated simulation of stochastic particle removal processes in particle-resolved aerosol models, J. Computational Phys., 322, 21-32, 2016, DOI: 10.1016/j.jcp.2016.06.029
  • DeVille, L., N. Riemer, M. West, Convergence of a generalized weighted flow algorithm for stochastic particle coagulation, J. Computational Dynamics, 6, 69-94, 2019, DOI: 10.3934/jcd.2019003
  • DeVille, R. E. L., N. Riemer, M. West, The Weighted Flow Algorithm (WFA) for stochastic particle coagulation, J. Computational Phys., 230, 8427-8451, 2011, DOI: 10.1016/j.jcp.2011.07.027
  • Riemer, N., M. West, R. A. Zaveri, R. C. Easter, Simulating the evolution of soot mixing-state with a particle-resolved aerosol model, J. Geophys. Res., 114, D09202, 2009., DOI: 10.1029/2008JD011073

Credits

PyPartMC:

authors: PyPartMC developers
funding: US Department of Energy Atmospheric System Research programme, Polish National Science Centre
copyright: University of Illinois at Urbana-Champaign
licence: GPL v3

PartMC:

authors: Nicole Riemer, Matthew West, Jeff Curtis et al.
licence: GPL v2 or later

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

pypartmc-2.1.0.tar.gz (6.9 MB view details)

Uploaded Source

Built Distributions

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

pypartmc-2.1.0-cp314-cp314-win_amd64.whl (4.5 MB view details)

Uploaded CPython 3.14Windows x86-64

pypartmc-2.1.0-cp314-cp314-manylinux_2_28_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

pypartmc-2.1.0-cp314-cp314-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ ARM64

pypartmc-2.1.0-cp314-cp314-macosx_15_0_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.14macOS 15.0+ x86-64

pypartmc-2.1.0-cp314-cp314-macosx_15_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.14macOS 15.0+ ARM64

pypartmc-2.1.0-cp314-cp314-macosx_14_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.14macOS 14.0+ ARM64

pypartmc-2.1.0-cp313-cp313-win_amd64.whl (4.3 MB view details)

Uploaded CPython 3.13Windows x86-64

pypartmc-2.1.0-cp313-cp313-manylinux_2_28_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

pypartmc-2.1.0-cp313-cp313-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ ARM64

pypartmc-2.1.0-cp313-cp313-macosx_15_0_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.13macOS 15.0+ x86-64

pypartmc-2.1.0-cp313-cp313-macosx_15_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.13macOS 15.0+ ARM64

pypartmc-2.1.0-cp313-cp313-macosx_14_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.13macOS 14.0+ ARM64

pypartmc-2.1.0-cp312-cp312-win_amd64.whl (4.3 MB view details)

Uploaded CPython 3.12Windows x86-64

pypartmc-2.1.0-cp312-cp312-manylinux_2_28_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

pypartmc-2.1.0-cp312-cp312-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ ARM64

pypartmc-2.1.0-cp312-cp312-macosx_15_0_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.12macOS 15.0+ x86-64

pypartmc-2.1.0-cp312-cp312-macosx_15_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.12macOS 15.0+ ARM64

pypartmc-2.1.0-cp312-cp312-macosx_14_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

pypartmc-2.1.0-cp311-cp311-win_amd64.whl (4.3 MB view details)

Uploaded CPython 3.11Windows x86-64

pypartmc-2.1.0-cp311-cp311-manylinux_2_28_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

pypartmc-2.1.0-cp311-cp311-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

pypartmc-2.1.0-cp311-cp311-macosx_15_0_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.11macOS 15.0+ x86-64

pypartmc-2.1.0-cp311-cp311-macosx_15_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.11macOS 15.0+ ARM64

pypartmc-2.1.0-cp311-cp311-macosx_14_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

pypartmc-2.1.0-cp310-cp310-win_amd64.whl (4.3 MB view details)

Uploaded CPython 3.10Windows x86-64

pypartmc-2.1.0-cp310-cp310-manylinux_2_28_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

pypartmc-2.1.0-cp310-cp310-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ ARM64

pypartmc-2.1.0-cp310-cp310-macosx_15_0_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.10macOS 15.0+ x86-64

pypartmc-2.1.0-cp310-cp310-macosx_15_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.10macOS 15.0+ ARM64

pypartmc-2.1.0-cp310-cp310-macosx_14_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.10macOS 14.0+ ARM64

pypartmc-2.1.0-cp39-cp39-win_amd64.whl (4.3 MB view details)

Uploaded CPython 3.9Windows x86-64

pypartmc-2.1.0-cp39-cp39-manylinux_2_28_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.28+ x86-64

pypartmc-2.1.0-cp39-cp39-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.28+ ARM64

pypartmc-2.1.0-cp39-cp39-macosx_15_0_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.9macOS 15.0+ x86-64

pypartmc-2.1.0-cp39-cp39-macosx_15_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.9macOS 15.0+ ARM64

pypartmc-2.1.0-cp39-cp39-macosx_14_0_arm64.whl (4.0 MB view details)

Uploaded CPython 3.9macOS 14.0+ ARM64

File details

Details for the file pypartmc-2.1.0.tar.gz.

File metadata

  • Download URL: pypartmc-2.1.0.tar.gz
  • Upload date:
  • Size: 6.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypartmc-2.1.0.tar.gz
Algorithm Hash digest
SHA256 2e4d50e1a2f0443820078a3e4b3f615a666fb54a373f426581d18766d0e2629e
MD5 7011dfe975cb41dce33b8382dd1a9535
BLAKE2b-256 4ecbcad58ad48a01f8b2747a32823f8e9138838c0ae5239d9f6997808deea785

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: pypartmc-2.1.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 4.5 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypartmc-2.1.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 e92c8ef8a48602c3353bac27a6266261d950aaaf4ca14fbdc1e4cf7b3ee05ddf
MD5 4513f18bdea88564e4bf6267cd491763
BLAKE2b-256 372f5b7021ee829b4564fbbb1fe2dcdc60415c1b079c245113b60e4cd23ff8c5

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp314-cp314-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 34721ef32796b520386313cac7f434915a40958a28ad7badef45a1890f9997a6
MD5 326ed5eb1b955c881fe5c41cb769cc58
BLAKE2b-256 e4e4a468989ac80f1270832a30e882e440700c8228f58ae64fbd279f922095f9

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp314-cp314-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp314-cp314-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a7cbbfdc779fb5aea92b0df284473afd92e4840da088e3d71b6687cec160b5f2
MD5 d292c604438bedeaceef4c99cd9abc56
BLAKE2b-256 2b77b7486b16c0c96ae37d409ede0211cc51188c3152d33badd4337e7c7e1599

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp314-cp314-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp314-cp314-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 ed7f64657d1024f78c7b47183fb1b8975507b72ab5ef87f0f2b7a45907a1449e
MD5 63c1b916b96a7a656c6958f46049ce8a
BLAKE2b-256 ec8c903886b18c107e9f7e383ab54cc6e6a53cc1a37d49b168cbe9929a49d59d

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp314-cp314-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp314-cp314-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 e81f7dcace03b4fbdec2e2420590f25cc54fb7ec3aed5af847987e7fa8deccaa
MD5 a2e4dcb259c5f7c56f9a5dfeeee36557
BLAKE2b-256 43e6c47a925fe0f45a6ae98c76093bc5450840e3c974d63f1ddd927ae1eb1d95

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp314-cp314-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 1613af1aae8293f282bd70fb287b09dffc87a129f591c0036973c1cf366d89c9
MD5 7f9b4ba53e0ed5ddf6cc5df9d75324e1
BLAKE2b-256 5455177a0a785099b1e699db6445f2ec6edc747bbc6ffef66a7467c3dc34839d

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: pypartmc-2.1.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 4.3 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypartmc-2.1.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 e8eca827f286bd6c31237a16ae20084193deb5d1b854f05462c84ced7089aa9f
MD5 2eadd386394af7808527d1a17118f932
BLAKE2b-256 e130fecff0fccf300a020f73de848359d02cc5983f66e1a9d23cced588b2f014

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3bea0591f74814058c519b31da1fc999475345f3bc91d191ea3e6cd2479e60b2
MD5 2a72b11e62bbc1ab6de8148fbd96369a
BLAKE2b-256 7dd354ad1ce0af26dfd1f1cda493c8c3b1c0b388dca4daa307803debdbaabece

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp313-cp313-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp313-cp313-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b5835185b5a145558bb3b915b3bb15ddff5a8ed4b8eb91c5ffbd334a4cb094c8
MD5 92ed4fea14f6eec491e3c4f67e169e7a
BLAKE2b-256 3055f68e1b8b113711a99027d137b27bc2ddab01144bbcd114ce236068d5adde

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp313-cp313-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp313-cp313-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 0f0d29e8892cd1be8e8459a49a9eb6fe9c8a2015e9a84268d5664ba5d1bd75f3
MD5 406e6cadc692246c164efd01202b49f0
BLAKE2b-256 d5aa0560d7f2b88eced3aa4f4eed19c61c68725837332dcbc0356ea48248c3a8

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp313-cp313-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp313-cp313-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 75570e9eb5f88089d9553e5c630823f9fa319fa58150e13eca6a2406eff09f18
MD5 9dcb4c7fd861b15d9190571a000ecde0
BLAKE2b-256 7d7f0cf3050669d0052ca2d317f2801aaa6c5f1b5c15cd432591ab1b43abdcf3

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp313-cp313-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 f413cf7baeead421ee13e7265e9d91f6fe4230b2b12b4545ad7a7c0e01df0bd6
MD5 dbccc52fb7485d5a65dfa8d49e83d791
BLAKE2b-256 fa1ac76977187c94f705b8617baf5ead92d7cc26f30f2392d406ba042572aa88

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: pypartmc-2.1.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 4.3 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypartmc-2.1.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 12e59fd7bc11e0ad5b5b25021b755ab1960fcc87e81d8dbd40add723e5780e46
MD5 339feed78279e474a9b2421e8c0fa3a6
BLAKE2b-256 c25d3fc85a92579ee605a493185352b20238a920979a75764694feb8de99836a

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4937f4f696e0445fff21024839b5a3e7f3e9e2d305ed49a72955fd5659632424
MD5 4a45cbfadf7798e7dc10be2e37b412ea
BLAKE2b-256 85468d55251ad7c7953cf9d8d3701ab58ca55029b37e9231d43b7d7d360daeac

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp312-cp312-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp312-cp312-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9b103731eb21044a9673cf5a35d3a4b17055e275f549f1decae4dfac48ae9838
MD5 3b105576345d32e5412f6048b5b5c939
BLAKE2b-256 340161cd5efe788930af661f82133add8cb817865eaf0cfc1f77c52061e7df14

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp312-cp312-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp312-cp312-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 fe4d1b99f5f1027381c4749413d03b01fcd48937d94d2c7c2f623be742462180
MD5 f2c5f4152b92b9933d6582a78b175bd3
BLAKE2b-256 69df6bfaa5650fce720aebde82414bff8f0918a90c591058faf350e9f51d18ed

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp312-cp312-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp312-cp312-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 bb65d860cd1bf3959bf62eb49e7308e7b0ba1443fc34eac3dd1c0ef971d06ccd
MD5 9ba494e0217bc6957587d0569083821c
BLAKE2b-256 7b2a3bd1aaa2d7a20d42e48c5d6e599bab93ee59dada5662301892025a15b386

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp312-cp312-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 568bdd8e1eafb546c50dc56cc15f0574a990245bcd89416d1ee4224ce725741e
MD5 9eb4fe96d23846c3df379cff0ef3482f
BLAKE2b-256 42b93f997b09ad076017f2d09f7524095f45191748e4a483acba0ad7e255a0f4

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: pypartmc-2.1.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 4.3 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypartmc-2.1.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 1c92100bec3643aa2d86ff392acb2af22bdff69b9d3ef05ad4463c346ea90a09
MD5 1ec1bd64a3596d99f9dfe746101c9261
BLAKE2b-256 37c62fc56d8de742758870deb0e3d441587bc7a399e3131e295ad1e922141580

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ceb0075e34da67c12c602ffb914c70c4c518d5565b6555398d1c0fd1b0403313
MD5 ea0f151459afb89fe633c8d7e2613e0b
BLAKE2b-256 ab6dafc8e1f65012099d7958bcd8adf6b1b2e40684cd7bd02615383238ae64bb

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 d69b0f19a883e8344a1c4ae59dd8bf03570630f6e45a1dc9ca0146c3c6b0f13f
MD5 1e9d09c0a3b5497f4c564ac38bbb82c7
BLAKE2b-256 71afe63a49b29e016eabe6a1c20f84debbef1a05e32a117fea0ae1c358e91c50

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp311-cp311-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp311-cp311-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 bbf539a04f75769c311f0ce349f603fb90c19d6671513c3da8bc770210172b3d
MD5 c45f7263daba96c8f276afa2076a38a6
BLAKE2b-256 6bb6ebd31f74373c97f4b274d7a7328c606e0c844907a3afa4ea4dbd3b35b17d

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp311-cp311-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp311-cp311-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 b47b720497af941ad0e2b47bd4066ae35f82a5ac022f4910ebe0de5010c71fc9
MD5 cfc616968054c7d7013e434642753f9b
BLAKE2b-256 6d264ba1a12036fbcc75beb127d94bbb9df1de86de7bf44cbe0c23eb34da44df

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp311-cp311-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 7bbd978dd5e26aea436d80f89fbbdb859a0800ee9c1aeb2bdbacd8458baca699
MD5 f55b449ffa93b566073cd0c67207e2cc
BLAKE2b-256 6d85099aa4fe06c13697cedce065e2b39be1301661493322cdac668bed54f959

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: pypartmc-2.1.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 4.3 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypartmc-2.1.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 d79e5690235230829d711ab5676db5b874d5fdbfa7d2ddf4587ada06a26590ff
MD5 076e7bbff1752cff0bf39621490ccce8
BLAKE2b-256 d504e4d78e6e441971957a5cfa3a7155a9254e6b6914aa83657e2055e8199087

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 404eb593b55b23b4f6a6268a1c6d74cf37f41ead169429222a19a661f8f51937
MD5 73d128df9f41b689de2eb0199c6b85c4
BLAKE2b-256 342edba3b414ab1bbea79f39cfce798064f6eed40546c0fa726c9831f9fb1d65

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp310-cp310-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 02cfe170e3b7506d7d5d5d91f03043b1e487b84d351354d96d2f5cf06c163365
MD5 e469eb4607a6709920e203865cd2bc3f
BLAKE2b-256 48b8f92ec338277db4d0ce0055675337f946a34c06ba0faac86405abad0eb679

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp310-cp310-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp310-cp310-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 161f2d489e0bb0cd5ce9adeca5a905db2d85899fe9d596f50c2d59307e861e9c
MD5 d2b4c2ec337aabe93f987e60b69f9319
BLAKE2b-256 dba6fb52cde8d71bfc24357c11de603b3c2e90b5c8984f50393619cadcce9e61

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp310-cp310-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp310-cp310-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 60c9548a4ee87206b5a90dc2662a567d1ddc2ffc6d1983c00bb1373e541bf057
MD5 fb5ad311e71e17c5af6750b9cf999a9c
BLAKE2b-256 9dbbbfe4bb3ca76e52bfa5479bbe4c74f67e554348b0231079083287fcaab675

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp310-cp310-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp310-cp310-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 d546e29ce6e817fd9f48075ae429a13074a6a61a3ea2766fce850a4a46323714
MD5 1af15f0ff0605f0ef1cf637cca08d24e
BLAKE2b-256 63dd242bb7990bd6568fe4183f29d38c763bb7a055954f670590e0696d8e3408

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: pypartmc-2.1.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 4.3 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypartmc-2.1.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 06fd89564a6f8cc31ea802428c6dd24b55c0df600408b03260069587d6070fd9
MD5 46d2d46cf2bb0b613593372b6de5603b
BLAKE2b-256 f4d498954f870b1a3eb2646759b5a43d2428060e9f93b90c53917104553d5175

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp39-cp39-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bf83f3c4a9a8c8eb8cac693325204a785ef05bcd659abbf25d48347cc657330f
MD5 089cb72812762bfcb803c689be2dadad
BLAKE2b-256 4deecc77b0d00504ebb5e6fded039fd73f5045f2f55370350dac0aba49c9483b

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp39-cp39-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp39-cp39-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 640113b04355a743ff9e2591225aa3279db97601673766e030d81b8d84232433
MD5 a554927af7c12deeb725b447a0d391b5
BLAKE2b-256 d898ffc747725b662b46b19b9abbb075ad102f9d364879158f9609ad5dd26920

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp39-cp39-macosx_15_0_x86_64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp39-cp39-macosx_15_0_x86_64.whl
Algorithm Hash digest
SHA256 4aa352633575514f1a031fd9b9faecc1c57226af8295ce17282d551ef48e138e
MD5 0485fc0a68f9b6829f9880cb8c2bcce7
BLAKE2b-256 6b616fb1bdc37d5e5392d559999c77302f237311e158500863900a4ae02f1691

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp39-cp39-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp39-cp39-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 bbd90b40cf3efe3b2ef522dc76df04c77c391291817e79c8874bb1a69adfcce8
MD5 3964122643becb9eb8c3b0124ca6e22e
BLAKE2b-256 5fc82fff41856f983d6f26c6ac293f2a486440aa2cf7b8cee8dcbd3978583e21

See more details on using hashes here.

File details

Details for the file pypartmc-2.1.0-cp39-cp39-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pypartmc-2.1.0-cp39-cp39-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 e2265b0c1c4c07d81f7b70ed5a8923c0d7e83eeb5f0ee6b7406b53fcec3f989d
MD5 cfa912c9aae0f1da9c4b054bfa36e078
BLAKE2b-256 886787f5281685ef76c01bafa79e74bca21ed49e5940b79ae07bb9cecaa35dcd

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