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.15.tar.gz (50.6 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.15-pp37-pypy37_pp73-win_amd64.whl (107.9 kB view details)

Uploaded PyPyWindows x86-64

plum_dispatch-1.5.15-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (134.4 kB view details)

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

plum_dispatch-1.5.15-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (135.7 kB view details)

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

plum_dispatch-1.5.15-pp37-pypy37_pp73-macosx_10_9_x86_64.whl (120.5 kB view details)

Uploaded PyPymacOS 10.9+ x86-64

plum_dispatch-1.5.15-cp310-cp310-win_amd64.whl (124.2 kB view details)

Uploaded CPython 3.10Windows x86-64

plum_dispatch-1.5.15-cp310-cp310-win32.whl (114.3 kB view details)

Uploaded CPython 3.10Windows x86

plum_dispatch-1.5.15-cp310-cp310-musllinux_1_1_x86_64.whl (619.0 kB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.15-cp310-cp310-musllinux_1_1_i686.whl (591.9 kB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ i686

plum_dispatch-1.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (549.3 kB view details)

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

plum_dispatch-1.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (526.8 kB view details)

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

plum_dispatch-1.5.15-cp310-cp310-macosx_11_0_arm64.whl (143.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

plum_dispatch-1.5.15-cp310-cp310-macosx_10_9_x86_64.whl (158.3 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

plum_dispatch-1.5.15-cp39-cp39-win_amd64.whl (125.9 kB view details)

Uploaded CPython 3.9Windows x86-64

plum_dispatch-1.5.15-cp39-cp39-win32.whl (115.2 kB view details)

Uploaded CPython 3.9Windows x86

plum_dispatch-1.5.15-cp39-cp39-musllinux_1_1_x86_64.whl (618.7 kB view details)

Uploaded CPython 3.9musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.15-cp39-cp39-musllinux_1_1_i686.whl (595.0 kB view details)

Uploaded CPython 3.9musllinux: musl 1.1+ i686

plum_dispatch-1.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (558.2 kB view details)

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

plum_dispatch-1.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (535.3 kB view details)

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

plum_dispatch-1.5.15-cp39-cp39-macosx_11_0_arm64.whl (141.1 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

plum_dispatch-1.5.15-cp39-cp39-macosx_10_9_x86_64.whl (155.4 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

plum_dispatch-1.5.15-cp38-cp38-win_amd64.whl (126.2 kB view details)

Uploaded CPython 3.8Windows x86-64

plum_dispatch-1.5.15-cp38-cp38-win32.whl (115.3 kB view details)

Uploaded CPython 3.8Windows x86

plum_dispatch-1.5.15-cp38-cp38-musllinux_1_1_x86_64.whl (679.4 kB view details)

Uploaded CPython 3.8musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.15-cp38-cp38-musllinux_1_1_i686.whl (647.8 kB view details)

Uploaded CPython 3.8musllinux: musl 1.1+ i686

plum_dispatch-1.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (607.6 kB view details)

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

plum_dispatch-1.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (580.5 kB view details)

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

plum_dispatch-1.5.15-cp38-cp38-macosx_11_0_arm64.whl (141.3 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

plum_dispatch-1.5.15-cp38-cp38-macosx_10_9_x86_64.whl (154.0 kB view details)

Uploaded CPython 3.8macOS 10.9+ x86-64

plum_dispatch-1.5.15-cp37-cp37m-win_amd64.whl (123.0 kB view details)

Uploaded CPython 3.7mWindows x86-64

plum_dispatch-1.5.15-cp37-cp37m-win32.whl (112.8 kB view details)

Uploaded CPython 3.7mWindows x86

plum_dispatch-1.5.15-cp37-cp37m-musllinux_1_1_x86_64.whl (556.0 kB view details)

Uploaded CPython 3.7mmusllinux: musl 1.1+ x86-64

plum_dispatch-1.5.15-cp37-cp37m-musllinux_1_1_i686.whl (529.1 kB view details)

Uploaded CPython 3.7mmusllinux: musl 1.1+ i686

plum_dispatch-1.5.15-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (495.2 kB view details)

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

plum_dispatch-1.5.15-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (470.8 kB view details)

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

plum_dispatch-1.5.15-cp37-cp37m-macosx_10_9_x86_64.whl (151.9 kB view details)

Uploaded CPython 3.7mmacOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: plum-dispatch-1.5.15.tar.gz
  • Upload date:
  • Size: 50.6 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.15.tar.gz
Algorithm Hash digest
SHA256 9fb0f76acebf3ae905a112ab833993d4e8ab132271cd7531013ab373703e6a6f
MD5 8d5951372e95966850e75a3ffe8373ee
BLAKE2b-256 36194ba245c3c7b0297e208cab7847100b69d16ce87e1a008d8ba73b9b046770

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-pp37-pypy37_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 ca5e054ea628fe2a272f62b48ee796e9fdba6378791395cad618185e22ee5adf
MD5 2985a24a6611df60ae9c14d5e306620a
BLAKE2b-256 5fbcdbac744d60d3bb63c10eb0f316bbe2d52f349345db4b522e53adb507e1f5

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 e96ccfad262c4892340d9d109d02f83b2f8b6fef33ba712683fa63cb3830713e
MD5 9049f09d1f59fe96c2c8b6f9ff555312
BLAKE2b-256 e3667e3aca6a220bc64cb8c16f8a61624df2976218277749cd21e050e36bbb42

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 d985e67233d0ce834de6e24d626249b1b00eeb76215668632d3dfda3d57e7a70
MD5 4165c23fc293f1915c9b1a7ba718ed38
BLAKE2b-256 992751e0d9fdb94d214224f15805aa59cf7b21a87c1aa688cab2e7e458e5e15a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-pp37-pypy37_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 8fc03684fe70782c5471473d21cdb64536fba32126705ae0459ef45aa9bb3321
MD5 dbcedd314bfa7b4c263a5f3d29d7643b
BLAKE2b-256 fbeb8117759be5740351cf16fd7c976ed9e16be5260b335271552d9699067b61

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 9204a4e532a90c5d54820c79db3f689eb1aeaf9a9b9b09b3282159a82758c095
MD5 51fdbc31dd0d1b82ae69684ca889fb9c
BLAKE2b-256 7a0cfb6e8138cc4f3f294290909870a1a65152e9880e80d2e5fcc1f0318eed39

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 c13badea0b41c17583f4a56f0e01ccfa2e7d25bc55a2a0fb333154cb0fd5dc7a
MD5 a83cb6e8740dfa006e0e4bd09eec7e16
BLAKE2b-256 d76238963cac9ddee2cdfa6ddc4562e00765ffd812f390c8952b694b7f176338

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 4c9375e7142165d865a5e72f4901fc7f694c6fd85ff83acef7e483dc20bee366
MD5 75896a401134bcbd4ce792322c31a076
BLAKE2b-256 afe0cbbe02ef200cc4d05ef538c4547c4d32d324ca1bc4769c1d782b4fe7afe1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp310-cp310-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 250740a0a6d12d17f622e0d7a41cbc6e3b40d36ad4d4172755fc90c11c9eb678
MD5 4ef42ef37c1c57ebe07ee9d0c1372bb8
BLAKE2b-256 f9e4cedc269c55aa8a1bc35276b1c65bdca82df9dd9670902bcf849ec57d0640

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 19f567149f6b1fd3454ca4432ded8709907973c6469cc525b8e9dd92ea60e675
MD5 856b9ac2c83192d0c4ea7e5c8ec60c4a
BLAKE2b-256 55ca4275a5d947a4baf3b855f8bdfde9e6b2c1d4a0c1839d92c7b3bf57294c53

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 93da10e989555187e0451c824a8742980f5fc3cfc99a0fb9967f65c1c1674ee5
MD5 76a59cdb3cba990e21f9959935f9c624
BLAKE2b-256 e420d4f45ad890f3ef774bf7d0d21a9a324a8e1e5c7823d1c902b5fdc7f477a0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dab7aca956d335cedc7be91d60ce02ab78412d4a130a24cfd2832907c1982377
MD5 f36798602596f67acc6490939fc737fe
BLAKE2b-256 20ad02de2b209dd2550dc76f6bcb8ee05d032f76f801e4d90cbedb08d0ef8509

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 c541c9b39737b3e5fa2fead09368461944099c8639ed9a0f6ca4da9f21a3b13d
MD5 62aa43ff141b4488861cf44ff900dceb
BLAKE2b-256 7b0547d7ee8212db665007141c18b29bcc5f6988120ce207cea5dcad30a09bc9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 54dab8d39d92c7412e3bfeb9e8193c891d1af9aa666f2577640e30268441476f
MD5 b24f2b0b33d27313a3b12688f86d9f15
BLAKE2b-256 1b56272a1d3b315e72e8951f813ecf8d659fa7514ab5fd5e84f68068057b0130

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plum_dispatch-1.5.15-cp39-cp39-win32.whl
  • Upload date:
  • Size: 115.2 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.15-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 5d9f7ae805dfaa1120546a8d4d1a95a77491d4e8080ea0b769c8ecf59e857393
MD5 52c249d9d0f126e27bd3a84d97677862
BLAKE2b-256 10d32689f3bbca9f06989d9348c77dabcb03224af40c7c47b2a65eb5f6e58168

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 b6bb9c58ae3a9c14150b28a411f31ff40f01d46beb0127a6429fe802a7f9dd6c
MD5 076982786053d0dced525d159baf3446
BLAKE2b-256 ef0777d9ceece464ef857fa956c3e716a4f47efa0cf7ff5a8a4ff81fa2c62a69

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp39-cp39-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 292fe21121980dc4b320e3a2098b0a60a5e7e48cec0c5b4e8910b152aa0a089e
MD5 f8df8de30dcebda0b3b38e45d4a2277f
BLAKE2b-256 57dfe5d06049ccf0f962c0fb6cce31d41f4d2c5bfe69873b61f0200da4013367

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 a64ee89372f42e4741d8793229f0277f9481e80a91a4bb71ebb038006b002f58
MD5 351611332a06b3a96d22f024a12b1af7
BLAKE2b-256 6979c5f42bf79f20c14a84021bc90af95b8b6a52313f42c756ede741b3837b6b

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 88a58746cf124086b51a2704a32e4423f54ce623117f0867206b864a084931f9
MD5 198c25f7c87a22b71cd2b2d1b2dd8ae7
BLAKE2b-256 26180897d46f7d8f0283dee3fd2ec994387a77fba180a8afdeff7b207ad60c2c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 19f20b99517923ea386470e6eae49fb3a5c52063fffc3f874963c0d71f47f3fa
MD5 fb021dd5feddd8cfa7db7c017f622fc3
BLAKE2b-256 d60d905daf1d1cf92ef6b3a6a5289f6551c63618616875f5359813eaa63e355e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 e98ec67e50ead1834f35175f38b368f54359c0723d98b8e6a2fb0d67a1f94a04
MD5 4a9e0bc7e1dadd2d070ff55f0747c3da
BLAKE2b-256 09f39c56e584594c64141feee9d4a8dabc843794980346a59102578d404c5b19

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 d70981d4a6cf5e567a7731b6e4c2e381c29825bd220d127791e3eaf49ec0d79c
MD5 a9e69418c697bf20ee97a25c93d0811b
BLAKE2b-256 42b1cee7799bc71c3f6d23177240d730c92df1c15967e12972e9886c4abbf1d5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plum_dispatch-1.5.15-cp38-cp38-win32.whl
  • Upload date:
  • Size: 115.3 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.15-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 7e2fc33a220ed3a07e08a5cf7f922ebf6975087a52e1b1c8781fc4f988828cd9
MD5 69bd46c4fe8cc9c4d7f4d8f42151632e
BLAKE2b-256 0d272b3004adaabe9a9cd267a2f1e22c0735d73c7f96d412dfed2f1fbf067fb4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 980bc8220ecec1c1f650f95f26c11738e92a9f526ad6403598f7f62305ea0e5a
MD5 ed0ff065ad4926960065ce906308142e
BLAKE2b-256 bc9bc210a04901a6e2536d226dba5fdbffdac4c20c8e61d43a48b01618b1cd4c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp38-cp38-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 f597960ec7cb83f7fa162eb829c6573dd4bcf3d4108ac32602719296080465f6
MD5 d44c2f9a596a2c7471dbad244c6410c8
BLAKE2b-256 c92a5a387c83b28ab603916f284af90468db570385dafce5eb5da86aadbf494b

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 c3f846c24be462922678ce0758ba3118d18de6359d0c9f316db7792064b94af4
MD5 63aaea20b620514d935f5446cc6d026c
BLAKE2b-256 75d246483b9f0b386d405aa6e13af1c9404da96b4dd9e99c29d4c17e29bada1b

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 de3f817b3e139326c602adf26ef46766d1283e61e6bc820c9fc0dcc01733dc57
MD5 778e52fec576774bfa4876e1c4c46839
BLAKE2b-256 b14eb64418d955764ea6555db7902a3ac4e2889895b118f7ebe2e12406a11150

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 faf087b7f2f83a79bb9bb618dae1869e6aa4c743ac7d2d71e4be36dee1fe03eb
MD5 36dd53d459adaeae9e6446abbe716d59
BLAKE2b-256 63ed884e4b9c40d038fbaf4a6f5a188c78f222a47c2096a137a32aada348b60b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 73c52ebb5e81ca5f3c7957e7daa847e40622539bca2fc41247f10f5257442d69
MD5 8cb0c3efbf351bec49404f70b25650b4
BLAKE2b-256 d43e6f4541d31865c84f99dce26dad32ec1723dfac12420c60235a528d07be90

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 2c7c2cd0cb6e22fbe9e28c5d2abd9e74031e1ed48af71a7ab8ee2d51ffadcd17
MD5 13e7407cf142279612b14fb7a86d061d
BLAKE2b-256 5811bc115d7f09c05e07960ae5f0ddc60bb409e56bde7bb4d3455a411d54444a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plum_dispatch-1.5.15-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 112.8 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.15-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 ee7d9741df5c12d5c05d541b1b2076f6303f95f3fc2883294bf08457db888315
MD5 b929e2e1d814dbc430502bf7c0b6841c
BLAKE2b-256 05cf8f9843c05c4b4639c1076abe7dba222cd5fb63aa915b18cb3baf96e53176

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 966098825b8f65fa62bd12100bd9f079ec55d440bbe6f6344becbad0bc90e4ac
MD5 7562a7c68ab77f834b6e2bb52bbfbd0d
BLAKE2b-256 e38a5d9b104a122ae43768ed5728ec8f30f524474f5b2649e767f91a79179787

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp37-cp37m-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 141587734f10807dc43ad9965b9bc132245cfccb764b255b46660c7e17ecb251
MD5 0df0bc1a8c628cf38b6102fe276d6b4c
BLAKE2b-256 f57f2f82571e0902a59a0803985973b3a6417044b121eeb684289ce7b816ee61

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 fcdf5c2a701da8ed25efc181348106894e105d8f2d1f9e9da552565562305f23
MD5 3ade6e2830f0e8817266588af68a1bd0
BLAKE2b-256 9b171bd6000e8bb371c38319566715d87cc2110cc59b170123d3786afef1b2ec

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.15-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.15-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 79b0f3320cc143974e8f55f185ffdd57f9a08a1f98527b39dbdb2aa46f33e52e
MD5 cde0982abad98c45519b34e1bb777362
BLAKE2b-256 fe604fa90fef91c59f142bc52d5c5636a037dcefac1a7bf3804ce1cdee14cac8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.15-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a2530182fbef4e6911b79ed4cf2549d491b40785e93225457c1c2f6d45ca19fb
MD5 ef967c10cac60096a2bcf2ec9792a173
BLAKE2b-256 465c21d70da4b80e445622e5637e8838fee14c40fb2b08840e88674ed96546c5

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