Skip to main content

Multiple dispatch in Python

Project description

Plum: Multiple Dispatch in Python

DOI CI Coverage Status Latest Docs Code style: black

Everybody likes multiple dispatch, just like everybody likes plums.

Installation

Plum requires Python 3.7 or higher.

pip install plum-dispatch

Basic Usage

Multiple dispatch allows you to implement multiple methods for the same function, where the methods specify the types of their arguments:

from plum import dispatch

@dispatch
def f(x: str):
    return "This is a string!"
    

@dispatch
def f(x: int):
    return "This is an integer!"
>>> f("1")
'This is a string!'

>>> f(1)
'This is an integer!'

We haven't implemented a method for floats, so in that case an exception will be raised:

>>> f(1.0)
NotFoundLookupError: For function "f", signature Signature(builtins.float) could not be resolved.

Instead of implementing a method for floats, let's implement a method for all numbers:

from numbers import Number

@dispatch
def f(x: Number):
    return "This is a number!"

Since a float is a Number, f(1.0) will return "This is a number!". But an int is also a Number, so f(1) can either return "This is an integer!" or "This is a number!". The rule of multiple dispatch is that the most specific method is chosen:

>>> f(1)
'This is an integer!'

since an int is a Number, but a Number is not necessarily an int.

For a function f, all available methods can be obtained with f.methods:

>>> f.methods
{Signature(builtins.str): (<function __main__.f(x:str)>, builtins.object),
 Signature(builtins.int): (<function __main__.f(x:int)>, builtins.object),
 Signature(numbers.Number): (<function __main__.f(x:numbers.Number)>,
  builtins.object)}

In the values, the first element in the tuple is the implementation and the second element the return type.

For an excellent and way more detailed overview of multiple dispatch, see the manual of the Julia Language.

Scope of Functions

Consider the following package design.

package/__init__.py

import a
import b

package/a.py

from plum import dispatch

@dispatch
def f(x: int):
   return "int"

package/b.py

from plum import dispatch

@dispatch
def f(x: float):
   return "float"

In a design like this, the methods for f recorded by dispatch are global:

>>> from package.a import f

>>> f(1.0)
'float'

This could be what you want, but it can also be undesirable, because it means that someone could accidentally overwrite your methods. To keep your functions private, you can create new dispatchers:

package/__init__.py

import a
import b

package/a.py

from plum import Dispatcher

dispatch = Dispatcher()


@dispatch
def f(x: int):
   return "int"

package/b.py

from plum import Dispatcher

dispatch = Dispatcher()


@dispatch
def f(x: float):
   return "float"
>>> from package.a import f

>>> f(1)
'int'

>>> f(1.0)
NotFoundLookupError: For function "f", signature Signature(builtins.float) could not be resolved.

>>> from package.b import f

>>> f(1)
NotFoundLookupError: For function "f", signature Signature(builtins.int) could not be resolved.

>>> f(1.0)
'float'

Classes

You can use dispatch within classes:

from plum import dispatch

class Real:
   @dispatch
   def __add__(self, other: int):
      return "int added"
   
   @dispatch
   def __add__(self, other: float):
      return "float added"
>>> real = Real()

>>> real + 1
'int added'

>>> real + 1.0
'float added'

If you use other decorators, then dispatch must be the outermost decorator:

class Real:
   @dispatch
   @decorator
   def __add__(self, other: int):
      return "int added"

@staticmethod, @classmethod, and @property.setter

In the case of @staticmethod, @classmethod, or @property.setter, the rules are different:

  1. The @dispatch decorator must be applied before @staticmethod, @classmethod, and @property.setter. This means that @dispatch is then not the outermost decorator.
  2. The class must have at least one other method where @dispatch is the outermost decorator. If this is not the case, you will need to add a dummy method, as the following example illustrates.
from plum import dispatch

class MyClass:
    def __init__(self):
        self._name = None
       
    @property
    def property(self):
        return self._name

    @property.setter
    @dispatch
    def property(self, value: str):
        self._name = value
      
    @staticmethod
    @dispatch
    def f(x: int):
        return x

    @classmethod
    @dispatch
    def g(cls: type, x: float):
        return x

    @dispatch
    def _(self):
        # Dummy method that needs to be added whenever no method has
        # `@dispatch` as the outermost decorator.
        pass

If you don't add the dummy method whenever it is required, you will run into a ResolutionError:

from plum import dispatch

class MyClass:
    @staticmethod
    @dispatch
    def f(x: int):
        return x
>>> MyClass.f(1)
ResolutionError: Promise `Promise()` was not kept.

Forward References

Imagine the following design:

from plum import dispatch

class Real:
    @dispatch
    def __add__(self, other: Real):
        pass # Do something here. 

If we try to run this, we get the following error:

NameError                                 Traceback (most recent call last)
<ipython-input-1-2c6fe56c8a98> in <module>
      1 from plum import dispatch
      2
----> 3 class Real:
      4     @dispatch
      5     def __add__(self, other: Real):

<ipython-input-1-2c6fe56c8a98> in Real()
      3 class Real:
      4     @dispatch
----> 5     def __add__(self, other: Real):
      6         pass # Do something here.

NameError: name 'Real' is not defined

The problem is that name Real is not yet defined, when __add__ is defined and the type hint for other is set. To circumvent this issue, you can use a forward reference:

from plum import dispatch

class Real:
    @dispatch
    def __add__(self, other: "Real"):
        pass # Do something here. 

Note: A forward reference "A" will resolve to the next defined class A in which dispatch is used. This works fine for self references. In is recommended to only use forward references for self references. For more advanced use cases of forward references, you can use plum.type.PromisedType.

Keyword Arguments and Default Values

Default arguments can be used. The type annotation must match the default value otherwise an error is thrown. As the example below illustrates, different default values can be used for different methods:

from plum import dispatch

@dispatch
def f(x: int, y: int = 3):
    return y


@dispatch
def f(x: float, y: float = 3.0):
    return y
>>> f(1)
3

>>> f(1.0)
3.0

>>> f(1.0, 4.0)
4.0

>>> f(1.0, y=4.0)
4.0

Keyword-only arguments, separated by an asterisk from the other arguments, can also be used, but are not dispatched on.

Example:

from plum import dispatch

@dispatch
def f(x, *, option="a"):
    return option
>>> f(1)
'a'

>>> f(1, option="b")
'b'

>>> f(1, "b")  # This will not work, because `option` must be given as a keyword.
NotFoundLookupError: For function "f", signature Signature(builtins.int, builtins.str) could not be resolved.

Comparison with multipledispatch

As an alternative to Plum, there is multipledispatch, which also is a great solution. Plum was developed to provide a slightly more featureful implementation of multiple dispatch.

Like multipledispatch, Plum's caching mechanism is optimised to minimise overhead.

from multipledispatch import dispatch as dispatch_md
from plum import dispatch as dispatch_plum

@dispatch_md(int)
def f_md(x):
   return x


@dispatch_plum
def f_plum(x: int):
   return x


def f_native(x):
    return x
>>> f_md(1); f_plum(1);  # Run once to populate cache.

>>> %timeit f_native(1)
82.4 ns ± 0.162 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

>>> %timeit f_md(1)
845 ns ± 77.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

>>> %timeit f_plum(1)
404 ns ± 2.83 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Plum synergises with OOP.

Consider the following snippet:

from multipledispatch import dispatch

class A:
    def f(self, x):
        return "fallback"
        

class B:
    @dispatch(int)
    def f(self, x):
        return x
>>> b = B()

>>> b.f(1)
1

>>> b.f("1")
NotImplementedError: Could not find signature for f: <str>

This behaviour might be undesirable: since B.f isn't matched, we could want A.f to be tried next. Plum supports this:

from plum import dispatch

class A:
    def f(self, x):
        return "fallback"


class B(A):
    @dispatch
    def f(self, x: int):
        return x
>>> b = B()

>>> b.f(1)
1

>>> b.f("1")
'fallback'

Plum supports forward references.

Plum supports parametric types from typing.

Plum attempts to stay close to Julia's type system.

For example, multipledispatch's union type is not a true union type:

from multipledispatch import dispatch

@dispatch((object, int), int)
def f(x, y):
    return "first"
    

@dispatch(int, object)
def f(x, y):
    return "second"
>>> f(1, 1)
'first'

Because the union of object and int is object, f(1, 1) should raise an ambiguity error! For example, compare with Julia:

julia> f(x::Union{Any, Int}, y::Int) = "first"
f (generic function with 1 method)

julia> f(x::Int, y::Any) = "second"
f (generic function with 2 methods)

julia> f(3, 3)
ERROR: MethodError: f(::Int64, ::Int64) is ambiguous. Candidates:
  f(x, y::Int64) in Main at REPL[1]:1
  f(x::Int64, y) in Main at REPL[2]:1

Plum does provide a true union type:

from typing import Union

from plum import dispatch

@dispatch
def f(x: Union[object, int], y: int):
    return "first"


@dispatch
def f(x: int, y: object):
    return "second"
>>> f(1, 1)
AmbiguousLookupError: For function "f", signature Signature(builtins.int, builtins.int) is ambiguous among the following:
  Signature(builtins.object, builtins.int) (precedence: 0)
  Signature(builtins.int, builtins.object) (precedence: 0)

Just to sanity check that things are indeed working correctly:

>>> f(1.0, 1)
'first'

>>> f(1, 1.0)
'second'

Plum implements method precedence.

Method precedence can be a very powerful tool to simplify more complicated designs.

Plum provides generic convert and promote functions.

Type System

Union Types

typing.Union can be used to instantiate union types:

from typing import Union

from plum import dispatch

@dispatch
def f(x):
    return "fallback"


@dispatch
def f(x: Union[int, str]):
    return "int or str"
>>> f(1)
'int or str'

>>> f("1")
'int or str'

>>> f(1.0)
'fallback'

Parametric Types

The parametric types typing.Tuple, typing.List, typing.Dict, typing.Iterable, and typing.Sequence can be used to dispatch on respectively tuples, lists, dictionaries, iterables, and sequence with particular types of elements. Importantly, the type system is covariant, as opposed to Julia's type system, which is invariant.

Example involving some parametric types:

from typing import Union, Tuple, List, Dict

from plum import dispatch

@dispatch
def f(x: Union[tuple, list]):
    return "tuple or list"
    
    
@dispatch
def f(x: Tuple[int, int]):
    return "tuple of two ints"
    
    
@dispatch
def f(x: List[int]):
    return "list of int"


@dispatch
def f(x: Dict[int, str]):
   return "dict of int to str"
>>> f([1, 2])
'list of int'

>>> f([1, "2"])
'tuple or list'

>>> f((1, 2))
'tuple of two ints'

>>> f((1, 2, 3))
'tuple or list'

>>> f((1, "2"))
'tuple or list'

>>> f({1: "2"})
'dict of int to str'

Note: Although parametric types are supported, parametric types do incur a significant performance hit, because the type of every element in a list or tuple must be checked. It is recommended to use parametric types only where absolutely necessary.

Variable Arguments

A variable number of arguments can be used without any problem.

from plum import dispatch

@dispatch
def f(x: int):
    return "single argument"
    

@dispatch
def f(x: int, *xs: int):
    return "multiple arguments"
>>> f(1)
'single argument'

>>> f(1, 2)
'multiple arguments'

>>> f(1, 2, 3)
'multiple arguments'

Return Types

Return types can be used without any problem.

from typing import Union

from plum import dispatch, add_conversion_method

@dispatch
def f(x: Union[int, str]) -> int:
    return x
>>> f(1)
1

>>> f("1")
TypeError: Cannot convert a "builtins.str" to a "builtins.int".

>>> add_conversion_method(type_from=str, type_to=int, f=int)

>>> f("1")
1

Conversion and Promotion

Conversion

The function convert can be used to convert objects of one type to another:

from numbers import Number

from plum import convert


class Rational:
    def __init__(self, num, denom):
        self.num = num
        self.denom = denom
>>> convert(0.5, Number)
0.5

>>> convert(Rational(1, 2), Number)
TypeError: Cannot convert a "__main__.Rational" to a "numbers.Number".

The TypeError indicates that convert does not know how to convert a Rational to a Number. Let us implement that conversion:

from operator import truediv

from plum import conversion_method
        

@conversion_method(type_from=Rational, type_to=Number)
def rational_to_number(q):
    return truediv(q.num, q.denom)
>>> convert(Rational(1, 2), Number)
0.5

Instead of the decorator conversion_method, one can also use add_conversion_method:

from plum import add_conversion_method

add_conversion_method(type_from, type_to, conversion_function)

Promotion

The function promote can be used to promote objects to a common type:

from plum import dispatch, promote, add_promotion_rule, add_conversion_method

@dispatch
def add(x, y):
    return add(*promote(x, y))
    
    
@dispatch
def add(x: int, y: int):
    return x + y
    
    
@dispatch
def add(x: float, y: float):
    return x + y
>>> add(1, 2)
3

>>> add(1.0, 2.0)
3.0

>>> add(1, 2.0)
TypeError: No promotion rule for "builtins.int" and "builtins.float".

>>> add_promotion_rule(int, float, float)

>>> add(1, 2.0)
TypeError: Cannot convert a "builtins.int" to a "builtins.float".

>>> add_conversion_method(type_from=int, type_to=float, f=float)

>>> add(1, 2.0)
3.0

Advanced Features

Abstract Function Definitions

A function can be abstractly defined using dispatch.abstract. When a function is abstractly defined, the function is created, but no methods are defined.

from plum import dispatch

@dispatch.abstract
def f(x):
    pass
>>> f
<function <function f at 0x7f9f6820aea0> with 0 method(s)>

>>> @dispatch
... def f(x: int):
...     pass

>>> f
<function <function f at 0x7f9f6820aea0> with 1 method(s)>

Method Precedence

The keyword argument precedence can be set to an integer value to specify precedence levels of methods, which are used to break ambiguity:

from plum import dispatch

class Element:
    pass


class ZeroElement(Element):
    pass


class SpecialisedElement(Element):
    pass


@dispatch
def mul_no_precedence(a: ZeroElement, b: Element):
    return "zero"


@dispatch
def mul_no_precedence(a: Element, b: SpecialisedElement):
    return "specialised operation"
    

@dispatch(precedence=1)
def mul(a: ZeroElement, b: Element):
    return "zero"


@dispatch
def mul(a: Element, b: SpecialisedElement):
    return "specialised operation"
>>> zero = ZeroElement()

>>> specialised_element = SpecialisedElement()

>>> element = Element()

>>> mul(zero, element)
'zero'

>>> mul(element, specialised_element)
'specialised operation'

>>> mul_no_precedence(zero, specialised_element)
AmbiguousLookupError: For function "mul_no_precedence", signature Signature(__main__.ZeroElement, __main__.SpecialisedElement) is ambiguous among the following:
  Signature(__main__.ZeroElement, __main__.Element) (precedence: 0)
  Signature(__main__.Element, __main__.SpecialisedElement) (precedence: 0)

>>> mul(zero, specialised_element)
'zero'

The method precedences of all implementations of a function can be obtained with the attribute precedences:

>>> mul_no_precedence.precedences
{Signature(__main__.ZeroElement, __main__.Element): 0,
 Signature(__main__.Element, __main__.SpecialisedElement): 0}

>>> mul.precedences
{Signature(__main__.ZeroElement, __main__.Element): 1,
 Signature(__main__.Element, __main__.SpecialisedElement): 0}

Parametric Classes

The decorator @parametric can be used to create parametric classes:

from plum import dispatch, parametric

@parametric
class A:
    def __init__(self, x, *, y = 3):
        self.x = x
        self.y = y
    
    
@dispatch
def f(x: A):
    return "fallback: x={}".format(x.x)
    
    
@dispatch
def f(x: A[int]):
    return "int x={}".format(x.x)
    
    
@dispatch
def f(x: A[float]):
    return "float x={}".format(x.x)
>>> A
__main__.A

>>> A[int]
__main__.A[builtins.int]

>>> issubclass(A[int], A)
True

>>> type(A(1)) == A[int]
True

>>> A[int](1)
<__main__.A[builtins.int] at 0x10c2bab70>

>>> f(A[int](1))
'int x=1'

>>> f(A(1))
'int x=1'

>>> f(A(1.0))
'float x=1.0'

>>> f(A(1 + 1j))
'fallback: x=1+1j'

Note: Calling A[pars] on parametrized type A instantiates the concrete type with parameters pars. If A(args) is called directly, the concrete type is first instantiated by taking the type of all positional arguments, and then an instance of the type is created.

This behaviour can be customized by overriding the @classmethod __infer_type_parameter__ of the parametric class. This method must return the type parameter or a tuple of type parameters.

from plum import parametric

@parametric
class NTuple:
    @classmethod
    def __infer_type_parameter__(self, *args):
        # Mimicks the type parameters of an `NTuple`.
        T = type(args[0])
        N = len(args)
        return (N, T)

    def __init__(self, *args):
        # Check that the arguments satisfy the type specification.
        T = type(self)._type_parameter[1]
        assert all(isinstance(val, T) for val in args)
        self.args = args
>>> type(NTuple(1, 2, 3))
__main__.NTuple[3, <class 'int'>]

Hooking Into Type Inference

With parametric classes, you can hook into Plum's type inference system to do cool things! Here's an example which introduces types for NumPy arrays of particular ranks:

import numpy as np
from plum import dispatch, parametric, type_of


@parametric(runtime_type_of=True)
class NPArray(np.ndarray):
    """A type for NumPy arrays where the type parameter specifies the number of
    dimensions."""


@type_of.dispatch
def type_of(x: np.ndarray):
    # Hook into Plum's type inference system to produce an appropriate instance of
    # `NPArray` for NumPy arrays.
    return NPArray[x.ndim]


@dispatch
def f(x: NPArray[1]):
    return "vector"


@dispatch
def f(x: NPArray[2]):
    return "matrix"
>>> f(np.random.randn(10))
'vector'

>>> f(np.random.randn(10, 10))
'matrix'

>>> f(np.random.randn(10, 10, 10))
NotFoundLookupError: For function "f", signature Signature(__main__.NPArray[3]) could not be resolved.

Add Multiple Methods

Dispatcher.multi can be used to implement multiple methods at once:

from typing import Union

from plum import dispatch

@dispatch.multi((int, int), (float, float))
def add(x: Union[int, float], y: Union[int, float]):
    return x + y
>>> add(1, 1)
2

>>> add(1.0, 1.0)
2.0

>>> add(1, 1.0)
NotFoundLookupError: For function "add", signature Signature(builtins.int, builtins.float) could not be resolved.

Extend a Function From Another Package

Function.dispatch can be used to extend a particular function from an external package:

from package import f

@f.dispatch
def f(x: int):
    return "new behaviour"
>>> f(1.0)
'old behaviour'

>>> f(1)
'new behaviour'

Directly Invoke a Method

Function.invoke can be used to invoke a method given types of the arguments:

from plum import dispatch

@dispatch
def f(x: int):
    return "int"
    
    
@dispatch
def f(x: str):
    return "str"
>>> f(1)
'int'

>>> f("1")
'str'

>>> f.invoke(int)("1")
'int'

>>> f.invoke(str)(1)
'str'

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

plum-dispatch-1.5.12.tar.gz (50.2 kB view details)

Uploaded Source

Built Distributions

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

plum_dispatch-1.5.12-pp37-pypy37_pp73-win_amd64.whl (107.2 kB view details)

Uploaded PyPyWindows x86-64

plum_dispatch-1.5.12-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (133.7 kB view details)

Uploaded PyPymanylinux: glibc 2.12+ x86-64manylinux: glibc 2.5+ x86-64

plum_dispatch-1.5.12-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (135.2 kB view details)

Uploaded PyPymanylinux: glibc 2.12+ i686manylinux: glibc 2.5+ i686

plum_dispatch-1.5.12-pp37-pypy37_pp73-macosx_10_9_x86_64.whl (119.8 kB view details)

Uploaded PyPymacOS 10.9+ x86-64

plum_dispatch-1.5.12-cp310-cp310-win_amd64.whl (123.6 kB view details)

Uploaded CPython 3.10Windows x86-64

plum_dispatch-1.5.12-cp310-cp310-win32.whl (113.7 kB view details)

Uploaded CPython 3.10Windows x86

plum_dispatch-1.5.12-cp310-cp310-musllinux_1_1_x86_64.whl (617.8 kB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.12-cp310-cp310-musllinux_1_1_i686.whl (590.2 kB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ i686

plum_dispatch-1.5.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (547.8 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.12+ x86-64manylinux: glibc 2.5+ x86-64

plum_dispatch-1.5.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (524.4 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.12+ i686manylinux: glibc 2.5+ i686

plum_dispatch-1.5.12-cp310-cp310-macosx_11_0_arm64.whl (143.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

plum_dispatch-1.5.12-cp310-cp310-macosx_10_9_x86_64.whl (157.6 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

plum_dispatch-1.5.12-cp39-cp39-win_amd64.whl (125.1 kB view details)

Uploaded CPython 3.9Windows x86-64

plum_dispatch-1.5.12-cp39-cp39-win32.whl (114.5 kB view details)

Uploaded CPython 3.9Windows x86

plum_dispatch-1.5.12-cp39-cp39-musllinux_1_1_x86_64.whl (616.0 kB view details)

Uploaded CPython 3.9musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.12-cp39-cp39-musllinux_1_1_i686.whl (592.6 kB view details)

Uploaded CPython 3.9musllinux: musl 1.1+ i686

plum_dispatch-1.5.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (555.1 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.12+ x86-64manylinux: glibc 2.5+ x86-64

plum_dispatch-1.5.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (533.6 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.12+ i686manylinux: glibc 2.5+ i686

plum_dispatch-1.5.12-cp39-cp39-macosx_11_0_arm64.whl (140.4 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

plum_dispatch-1.5.12-cp39-cp39-macosx_10_9_x86_64.whl (154.8 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

plum_dispatch-1.5.12-cp38-cp38-win_amd64.whl (125.4 kB view details)

Uploaded CPython 3.8Windows x86-64

plum_dispatch-1.5.12-cp38-cp38-win32.whl (114.7 kB view details)

Uploaded CPython 3.8Windows x86

plum_dispatch-1.5.12-cp38-cp38-musllinux_1_1_x86_64.whl (677.5 kB view details)

Uploaded CPython 3.8musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.12-cp38-cp38-musllinux_1_1_i686.whl (646.4 kB view details)

Uploaded CPython 3.8musllinux: musl 1.1+ i686

plum_dispatch-1.5.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (605.8 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.12+ x86-64manylinux: glibc 2.5+ x86-64

plum_dispatch-1.5.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (578.4 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.12+ i686manylinux: glibc 2.5+ i686

plum_dispatch-1.5.12-cp38-cp38-macosx_11_0_arm64.whl (140.6 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

plum_dispatch-1.5.12-cp38-cp38-macosx_10_9_x86_64.whl (153.4 kB view details)

Uploaded CPython 3.8macOS 10.9+ x86-64

plum_dispatch-1.5.12-cp37-cp37m-win_amd64.whl (122.3 kB view details)

Uploaded CPython 3.7mWindows x86-64

plum_dispatch-1.5.12-cp37-cp37m-win32.whl (112.2 kB view details)

Uploaded CPython 3.7mWindows x86

plum_dispatch-1.5.12-cp37-cp37m-musllinux_1_1_x86_64.whl (554.4 kB view details)

Uploaded CPython 3.7mmusllinux: musl 1.1+ x86-64

plum_dispatch-1.5.12-cp37-cp37m-musllinux_1_1_i686.whl (528.1 kB view details)

Uploaded CPython 3.7mmusllinux: musl 1.1+ i686

plum_dispatch-1.5.12-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (493.2 kB view details)

Uploaded CPython 3.7mmanylinux: glibc 2.12+ x86-64manylinux: glibc 2.5+ x86-64

plum_dispatch-1.5.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (469.2 kB view details)

Uploaded CPython 3.7mmanylinux: glibc 2.12+ i686manylinux: glibc 2.5+ i686

plum_dispatch-1.5.12-cp37-cp37m-macosx_10_9_x86_64.whl (151.3 kB view details)

Uploaded CPython 3.7mmacOS 10.9+ x86-64

File details

Details for the file plum-dispatch-1.5.12.tar.gz.

File metadata

  • Download URL: plum-dispatch-1.5.12.tar.gz
  • Upload date:
  • Size: 50.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.10.4

File hashes

Hashes for plum-dispatch-1.5.12.tar.gz
Algorithm Hash digest
SHA256 d5ed261fd798e92963165ab19586aceff5ffb37ed8cdfe75bf29686d910bcc85
MD5 0526fd6341ae3254ee2e383f8a73ecf7
BLAKE2b-256 b87ae02fcd9c4a9f444362f6534d9a563f4ac4288504fcfb8d354e16e6f9b2d0

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-pp37-pypy37_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-pp37-pypy37_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 5c7e44d4fee69393ffaea0f568d84173763e5238b8ac5dfa87907f72bf441932
MD5 50b49c169a4f1d874b2f5cc1185a15c2
BLAKE2b-256 68ec50d4e6133f9f1e84a77dcb0b74116cd071d0aae9438b3bd0a3575d6b89a2

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 16b7f6a7e71f4f70748b361e7960fd78d4fb2d1897d548f18dd5fdf83a9fbb12
MD5 b6d5e420f9e03845d47cb13ba59b409a
BLAKE2b-256 9fc3cb58e016bb46e31a46328fbb3a5480717388cceda62ab5c9f16261369134

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 c6b97f5878f6566b36276e5e46430e02a913dfcc838fd674ec942b873b2e106e
MD5 0ce2987126ef8e5c9a8332b1fbec6682
BLAKE2b-256 91802599b79929c7fbc044f5e86b8c8146ef81ae5ef8c9eb793777e672418d0f

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-pp37-pypy37_pp73-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-pp37-pypy37_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4f28892cfa2c062af8d0bd3c92e3a14e82630dfce2f904ff5e01c63374b43b5b
MD5 58fd09fdff661a91d893030981c2f0d6
BLAKE2b-256 15067dda17831263831b9a6045b11dd4d526f8f9a1ee70162b891ed534e3bf14

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 ec12693d554165de8597cfda28b464c4d91e42005a55a3701b7104dc1e3c83ca
MD5 81305dea6e0eb4485b07150e01d52ff8
BLAKE2b-256 5e34b8d767913da3f742fcb1925cbfd5a05c9c2fd360d57e8263d6a1b3be3bb6

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-win32.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 e915f0899b4f6c8749afdf1917ba0fbe24798483afabebb7b3417dd4d29af98c
MD5 902354bf932739c764955165d80706d0
BLAKE2b-256 8a5da3f8ddaae63ff39c07d8b549b7ad1020dc0ca31623b0df53de6c95fca459

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 8c0f3edf223e9f8ece0145f0d9ffcad3bdbdf1423dcb0ddc7f0f2193a07603d6
MD5 f3ef83cf457e44800b3ceda805494c96
BLAKE2b-256 db20c566b281c835f16cc7555bea109113cc3ee9ee5e254e6766b08dd5c16a8e

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-musllinux_1_1_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 ce9fee7c581c5ef539b161d7812fd8a725374973be632f4e3db44bb61e1b892d
MD5 82420ba90325edd481df3697149e9898
BLAKE2b-256 2d768b7e643233a1a398c42d4d88c915ffbcbb279fae497bd523118d943070fb

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 243ab0d49cab6baf76c1266c97ed1448e13cb72db0e34be15666d59370b01040
MD5 d044edabd1405f7e04505b983415eb0b
BLAKE2b-256 68a70e5cb2138e6059e55d3a1f04a8a94b60c79054bf66aa21e0885cdcd852ba

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 e1bfdef0cce2462900c7c55eeafb8067b6c3617e4cc6769e461504371af2767d
MD5 fa3276dacbc983864c508b78a6188ba5
BLAKE2b-256 dff9c4d0811d2b5578d93296fe2edc5f5aa954a5f16930b12a150ff2dca9a68b

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6cc9238014ee8ff1ee0afbe9c1c3f220eb3798104dd1f4efc3657e9686c80493
MD5 1597559ca8091d1227198e04088a317b
BLAKE2b-256 15614d39b09d89a82b059116e76a99d3ff14cb5128ab5f0bb91726b7461f7e16

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 dbede237b1e3203ae937b04a485248bb296465eca5bb73c05c91ffb04cdb8449
MD5 48cd82a62af37fc0dae679b3eac2ff68
BLAKE2b-256 fa1fdbc5f4546bff6e9b425981ba5df6f447090d6168a96d2f13803d7295726b

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 ca5b67db1ea61a6eef5f2784fe2bec6630f731c330a5f26941c1242b3065f313
MD5 2248e8ffc7677a23fb7be861aa7ff7a2
BLAKE2b-256 267da0fe5723a4c635933ebc536e8115077008246f5c595e4875e4f68d993d9a

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-win32.whl.

File metadata

  • Download URL: plum_dispatch-1.5.12-cp39-cp39-win32.whl
  • Upload date:
  • Size: 114.5 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 8bef3137c4f1ce8b37d26f43882c0f26642fc2836f90007049aec6594f3d042b
MD5 73714d081cd93892ad45afd7af364a64
BLAKE2b-256 d7edbe07f643086caf267db3edbbb3a0fa15cb9a43992a44fc45a24c942c853e

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 5a7a28f507bb278593da93687e1e0daea1d02a728165e11981ef85dbb5bd5320
MD5 35728c6ef2c2f82b2d9449782cf25c56
BLAKE2b-256 cc58a49ab66fac219a5aa626c90979fe8846365abc3870dce3e2b493dbe5c1b4

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-musllinux_1_1_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 74fdcaf48acbe4723526e2aac1ac15b6512538ebd4c6026fefb113732a88ccee
MD5 bd83f7add2ad36d690be88475bd55363
BLAKE2b-256 f7589733a996d394460ac0f6087564748e28b736896b80c5fe79d764511d60df

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 0ac8eb1323552b81b0f9436e88c540a79ef9ca64f9aeb82555b8ae4676c8b59b
MD5 2e4970176a053a0eee96b3823b3439e5
BLAKE2b-256 369120768905777442f6580cacf2cd7f8c5e68fc498149eadbdcec7c89d63d26

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 ab7413e200f5b5620c249a0be529058a0d2c2cdc57ad2766e13a8639bc14461b
MD5 33fd9a7bc99132bcf3f5c6b6a249058a
BLAKE2b-256 390672b00e0bac64d7563e16373eadf4d49ab592a75724fbaf3f02eec3485dc9

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 17fb4205edd60c40ebad597040b0da190a9d71a121e7de459994487623291a79
MD5 0f76a74cebcb51662cc42030da1a950f
BLAKE2b-256 6bd0ff47443fd3f2cb6b857d1f6496d3b172bcd2a4ff90c9b0bd69829c04a470

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 e9061c1a497313a3bfcc8ce90c347c3deda59007ee7725fae3b0b62883946fa6
MD5 39a6519c3b50ace58c4bcd00d5563ff7
BLAKE2b-256 45677ad74e4a614443a373cdf87baf8d535e608b74831a0b339cc84680cbadba

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 b3e96d26a20b56215c5c4344be247581f8bfad2d5b699f5d8c0a2ff9bd9de44a
MD5 06fa8aedd90ba43be981d3e94ede6de8
BLAKE2b-256 225e8406d62e50fffdf098edc6b1830cfe9f144c7cbb865f5fbc7ff5d5470f26

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-win32.whl.

File metadata

  • Download URL: plum_dispatch-1.5.12-cp38-cp38-win32.whl
  • Upload date:
  • Size: 114.7 kB
  • Tags: CPython 3.8, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 78e822dc049d164cedfe5821e2ca7669689f1c081b53244fb2a25f98d6653c99
MD5 3192d0ee5d9959eec3798c86e45d0c29
BLAKE2b-256 bb341c4e75e63d18bb7bb05bb96ee975af53e94cd91beecfc11f09350b9cd8a3

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 7219a3dd2ae5e66a33cb7fa92493a6cd69df640a2f0df04643503a6b72ae2de4
MD5 d8343fca75f5c639bcabe00835779d30
BLAKE2b-256 0e9b2f689e4fac37da4c36362e9b2707e88ab572c40567d6c679116f5f8bf8bf

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-musllinux_1_1_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 f141828ece5e8395e77edf95f27c0ff3d5bf991540819f249f79633435a680dc
MD5 fd0fdc315a32d896581946b1a9fb4dae
BLAKE2b-256 9920d245b98c716b0b74240fb7dc1057067cc291b04fecd0adfba11347403e89

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 0aed62b87e6a5c3104868f3119d3f7b50963d2b2e48e91fb6f3043118ce5423b
MD5 1a5345265551c4c38a7733f8f173b530
BLAKE2b-256 74c7e32e8d0a7ae87ea2a250e44c32eede4e275583fb1c463342ced65c986c4b

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 eb334ab845de58d0d195f8a7b93fad2746021eb9da32ce7023095a39ac6d44a6
MD5 cc229288e63f5a8c9d1d6821690cb3f5
BLAKE2b-256 6dfb73d0aa3c0c938c328e68d3f5d5d05a2c2e10e796de9a93fb55182f86a55a

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3c71aa25869e96f944d573abd548438784fcbc515dd4c90a064d4cd5d68979e0
MD5 b32269d46d1a406cdd59cb7469a73037
BLAKE2b-256 930e808d3c0e68c70b433f54dbf791a49827b1f270f235f7c20231c6cab33d98

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 1208b1b42b457977dfd24743fcd9be7e6661c47ff2b2a843f6cf06bc2b46d3d6
MD5 3412427934f844554e6371d020dc743d
BLAKE2b-256 dd9d98b822de8032ebda671823e6334cdae1e8e673bac18f6bc3ec661e96c236

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 67aaa0d9a7c964004fa356f4b6ad4c1a86d8be33f2b0cc9bca0f7ed74eacac00
MD5 68a3f71a7779185b22191a9a6fb4e023
BLAKE2b-256 782c49a8f81eed19141584c74ed431cfadc5bbfa73eab850793acd0f7c4cd06d

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp37-cp37m-win32.whl.

File metadata

  • Download URL: plum_dispatch-1.5.12-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 112.2 kB
  • Tags: CPython 3.7m, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for plum_dispatch-1.5.12-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 afead064f8a7a1a4c1b9c10dcce310c9ee386a9ef21c8594197f0100e374df1a
MD5 2e89c5edab4c57f2f9bc2611a2ba0666
BLAKE2b-256 12f484c2ff9c14d247c85e1b0af648b29d9ce977cf40ca4a3bef3ae318b37d39

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp37-cp37m-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 f423c68c7f8d5cc45a187035b56b65e0fa61a0b109e60b2eb252171efcbd8ac8
MD5 1f11d0da5454b503b9da9aa561636647
BLAKE2b-256 750a3904ee3215d4dd12b2237772e8655b594760327daf11d2f4b5bb8fe81060

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp37-cp37m-musllinux_1_1_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp37-cp37m-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 dcd94da63e07945fc90312c0b7aa19d515fe41edaa044451f88d7a1d45c5710e
MD5 eac741831d5b0f1f1cb4b18bc69ce4a9
BLAKE2b-256 4f05804eff7179e7acd38cca3ce241d794c1c663ec754ec21922fac72f833b74

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 6144c808cedd2c51f12e5caed27f42ad5b6d661b8d9ce745c917f53207c75d10
MD5 da9d0dd439a6e5cf1fd50126b2189dd0
BLAKE2b-256 9bab7a7cfbb469f25f71c88f876769c6baae4557482f620930c1ef5ee92ca7fa

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 e03cb67883a7d14a3f14da922ae4051e36817c2815f8e8e4ad53380b9992bdb5
MD5 803e070798aa4100ee01a8bf091697b9
BLAKE2b-256 7ba7dbf4aeb379eb3d60bebdf8d11e5f79ad6aeda6207535fdfd4b3c60ad6721

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.12-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for plum_dispatch-1.5.12-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 659912be556899cf898f76ecbeb983fc83b3c63d466bcc765c7e709095f2b1e0
MD5 f0ec1717e19a36a11580649c3019c018
BLAKE2b-256 7b3ff13656af918e025945ddb347b1fbda5d17b6e1925fdee818f882e5602b2b

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