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.16.tar.gz (51.0 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.16-pp37-pypy37_pp73-win_amd64.whl (109.8 kB view details)

Uploaded PyPyWindows x86-64

plum_dispatch-1.5.16-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (136.5 kB view details)

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

plum_dispatch-1.5.16-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (138.2 kB view details)

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

plum_dispatch-1.5.16-pp37-pypy37_pp73-macosx_10_9_x86_64.whl (122.7 kB view details)

Uploaded PyPymacOS 10.9+ x86-64

plum_dispatch-1.5.16-cp310-cp310-win_amd64.whl (126.3 kB view details)

Uploaded CPython 3.10Windows x86-64

plum_dispatch-1.5.16-cp310-cp310-win32.whl (116.1 kB view details)

Uploaded CPython 3.10Windows x86

plum_dispatch-1.5.16-cp310-cp310-musllinux_1_1_x86_64.whl (634.5 kB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.16-cp310-cp310-musllinux_1_1_i686.whl (606.9 kB view details)

Uploaded CPython 3.10musllinux: musl 1.1+ i686

plum_dispatch-1.5.16-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (560.8 kB view details)

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

plum_dispatch-1.5.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (539.4 kB view details)

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

plum_dispatch-1.5.16-cp310-cp310-macosx_11_0_arm64.whl (146.8 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

plum_dispatch-1.5.16-cp310-cp310-macosx_10_9_x86_64.whl (165.1 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

plum_dispatch-1.5.16-cp39-cp39-win_amd64.whl (127.9 kB view details)

Uploaded CPython 3.9Windows x86-64

plum_dispatch-1.5.16-cp39-cp39-win32.whl (117.0 kB view details)

Uploaded CPython 3.9Windows x86

plum_dispatch-1.5.16-cp39-cp39-musllinux_1_1_x86_64.whl (632.6 kB view details)

Uploaded CPython 3.9musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.16-cp39-cp39-musllinux_1_1_i686.whl (605.4 kB view details)

Uploaded CPython 3.9musllinux: musl 1.1+ i686

plum_dispatch-1.5.16-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (570.8 kB view details)

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

plum_dispatch-1.5.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (546.0 kB view details)

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

plum_dispatch-1.5.16-cp39-cp39-macosx_11_0_arm64.whl (143.4 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

plum_dispatch-1.5.16-cp39-cp39-macosx_10_9_x86_64.whl (162.1 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

plum_dispatch-1.5.16-cp38-cp38-win_amd64.whl (128.0 kB view details)

Uploaded CPython 3.8Windows x86-64

plum_dispatch-1.5.16-cp38-cp38-win32.whl (117.2 kB view details)

Uploaded CPython 3.8Windows x86

plum_dispatch-1.5.16-cp38-cp38-musllinux_1_1_x86_64.whl (694.1 kB view details)

Uploaded CPython 3.8musllinux: musl 1.1+ x86-64

plum_dispatch-1.5.16-cp38-cp38-musllinux_1_1_i686.whl (661.6 kB view details)

Uploaded CPython 3.8musllinux: musl 1.1+ i686

plum_dispatch-1.5.16-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (622.4 kB view details)

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

plum_dispatch-1.5.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (593.7 kB view details)

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

plum_dispatch-1.5.16-cp38-cp38-macosx_11_0_arm64.whl (143.6 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

plum_dispatch-1.5.16-cp38-cp38-macosx_10_9_x86_64.whl (160.7 kB view details)

Uploaded CPython 3.8macOS 10.9+ x86-64

plum_dispatch-1.5.16-cp37-cp37m-win_amd64.whl (124.8 kB view details)

Uploaded CPython 3.7mWindows x86-64

plum_dispatch-1.5.16-cp37-cp37m-win32.whl (114.5 kB view details)

Uploaded CPython 3.7mWindows x86

plum_dispatch-1.5.16-cp37-cp37m-musllinux_1_1_x86_64.whl (570.4 kB view details)

Uploaded CPython 3.7mmusllinux: musl 1.1+ x86-64

plum_dispatch-1.5.16-cp37-cp37m-musllinux_1_1_i686.whl (539.6 kB view details)

Uploaded CPython 3.7mmusllinux: musl 1.1+ i686

plum_dispatch-1.5.16-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (506.2 kB view details)

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

plum_dispatch-1.5.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl (479.8 kB view details)

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

plum_dispatch-1.5.16-cp37-cp37m-macosx_10_9_x86_64.whl (158.5 kB view details)

Uploaded CPython 3.7mmacOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: plum-dispatch-1.5.16.tar.gz
  • Upload date:
  • Size: 51.0 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.16.tar.gz
Algorithm Hash digest
SHA256 ec52f17bc8756b70ffb0fcc06838f90f6a82c2490c4ef7d73bccc68e80864f48
MD5 28b1aceab15e64169b465d3582c22f43
BLAKE2b-256 9516e5a466729e7c9eb53450f200b58c4507136327eee6dcb6f57ba4347cb9aa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-pp37-pypy37_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 b0d3c7461e2e8ad1ace10de5b1f01d8885e79017f3c81450010ca5f9236fa733
MD5 dbad18c8882fbaf92cbd2039e91967c0
BLAKE2b-256 db16adb74e8cdd74dbe8dcfede1f190857f468d1acee5abff6fdd78425c20b10

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 e6f137b793026797e213d74ab63b8edd15931cf8cc46387644538cbde1c79021
MD5 7eded8afc32354caac2c2ee9de74f2f5
BLAKE2b-256 8e2fb8802e55244066f6b94fb8db80c18b27714579d9e5c55543b4d793f991f8

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 ecdd686106bae542afa9d7282cca2d8d2885749446b1868e06d75be9faa6b21a
MD5 0aa718db6c5e980528b088d72a874be7
BLAKE2b-256 559276dad7cdb5b9c7304eb78e0e7e2b1efc35d3b32924839e15b1bac6a7e60f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-pp37-pypy37_pp73-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 13ed2ed354c59819ba9d67620e789421802797be4f5bce49f763f9b5b0a21a8a
MD5 b0139e2e36ef437685cdb5d5e6c71ed1
BLAKE2b-256 9e357d831ee8d1113ac171a7aec4f2dce4ecaf790a099e4ef06541bc87189d93

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 6dd4e7ec070402582567eab60c2f6603b7a6c0b5ddc184f0f50c1520c819bede
MD5 1d62a5897ae9a9a63f305ec310e15411
BLAKE2b-256 535f7444ead2a44bc8e61c098335f4ccff87c9f24e061ab7ff1856465c4fc5c2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 d820be58ef2d446d891e41315fda2e1c300015c66ddfefa08fdcd79b5534d288
MD5 7d8a9a46603f844e39a1d7f3ed2829bd
BLAKE2b-256 b11f8748d846cd3d48239ce7d0ec629c2303a28c75f812103f0343d064b5440d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 396481b93a4f01c4d3c4a61dc5b3a68e0e68f8c9973a26bdc336aca634079cab
MD5 6cc8ac60542aada13a0c67c70867bb87
BLAKE2b-256 7688098083847a7cc4b1ab4e0fd989574386e9541981a3efd6796cdcb1803367

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp310-cp310-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 dbc8c549e629c668e24efd8291227b3e7cfe465e35c980159815e68aa5d9d122
MD5 c80fdb1ae3a751926e0efb5ddd87a237
BLAKE2b-256 e5ce0e7841385e3351d76921fba73b7c637377ff13ea409a4090c930c60b832b

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 97e35f2ed5091648042cc5d7b918007c2889beb3056a7ad82ac4c5e7d7159942
MD5 e7fc83d90319700787587de67f0dddea
BLAKE2b-256 39cc74c3444d26cb70365984b22a0c04a0613c07184111cb15633e8e90305c1f

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 e651a11a61f6233c741705ed95e9387542ad614525afe614224399c72ad463a7
MD5 754614e8e34de11a8b669e535c2276c5
BLAKE2b-256 f2763db63aef40f6f8b2822e2dcac6d694de489424553e3d6a52b867bc11d2ac

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 92891b52e393a5cba0c5ca4a2c84a59a26cca78c190fdf2c186ac04b88013f96
MD5 dcb9c903f704b1040f8e101800b4af35
BLAKE2b-256 3da4ad498fa08beffbcb6dd7f2481552fbbd48075dba3f2d0f9574b4de398d5e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 0c2ce2866f6a34f0ad0e4ce064de674cd119b7ca3e2e9cb4760d8db5143fd180
MD5 3d7d491503fe04788d38e0b1eca17c89
BLAKE2b-256 e73fe1efb0b75708dc6bf4e0ddeae1c14f915175de4cd6ee3f0a8e2ac59ec3bd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 abaea0b4ee1fa04d0b8f1a40210b06903c26feafac0d5d4e81acdcb357b80739
MD5 ca955a75fbc9cafd966db90ddba1f286
BLAKE2b-256 3b56b296b3ea42b22ed06cc3c3fe57717107095f2e43c2b689bf46e4637fae64

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plum_dispatch-1.5.16-cp39-cp39-win32.whl
  • Upload date:
  • Size: 117.0 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.16-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 bdc78f0e0ec882fc970962775afc1d4a07c0c4d6dc56a1ffdd81cb1a00568a4f
MD5 c548d0315dd26e3e82ea7e9d6b5153b4
BLAKE2b-256 ad4a3a50b790ff073b2d302a460b1694fb2a7819e470ded778725c5877027be2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 7b1646e1e3d86a004d38208bfb1605b79d306e36a3a925f4aa9009f4ba0608e0
MD5 18f6974a5497cfbfde37db19c52a7ef6
BLAKE2b-256 6bf077644bfeb1bddbc68d4c3613938cd9fe4a53fd7ea4747575934912991b41

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp39-cp39-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 81680e29d21db56fda1feaf8d77370ed46b3b65c23ec4609b34e68d1da20e68c
MD5 83dba00a8e99a83147780480a4445993
BLAKE2b-256 88884c8746a980d1100e6fd656e5e59a953586e4e0bcf132f88c5943a961e55c

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 2d06b3fcec9117033f63a0c1229fc29318b834b89b6adafd65edc726273a71ce
MD5 fb8790a4b5af31450556b82d0128c723
BLAKE2b-256 78ba52838eddea96f0de8416fdfdd5985e335b2dfc8ec3ad638efc4c6784bb7d

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 b2ecbd15916a7e61db7aff49b63fc3df1761260a4e6d8eea1382c0b51a0a36cd
MD5 0a7f3d689cc7f1c2cbeef3ac819b3d9b
BLAKE2b-256 3687fec9c95c5c80dabfce281ee3a409b7bdc251134715d96c529bfd3b993fe7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2955e466cf144f080de6472d0fa48ab00f78a919c34f2bb5941e0b8228e92c9a
MD5 8e20d663629dd990eaaeb52d122370d9
BLAKE2b-256 d4300851a6959a06e25d15a098969570ede14e119212e68440f370b324daacb0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 f4c6f7859de7a093e9db5036ca5de952a33f51b654a47c753ec443b59e554786
MD5 3311c318e9b3fe68a492f1f473e90808
BLAKE2b-256 47e5c6fe6c85caf10a449b6801174fa58895d8d6ee8f6868d3408d7daca1f67e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 188894bf2a4c7da4c57b70fac44cd49afed0c2ed43c054fa67a58349334a2811
MD5 2a383172c481f910eae312d370fcff98
BLAKE2b-256 287ab55a4ff45f0a8e54a69d41248aa927e7a03a152a8e3b82d72127f0fe4531

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plum_dispatch-1.5.16-cp38-cp38-win32.whl
  • Upload date:
  • Size: 117.2 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.16-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 bd49b71792af2fd1c7137ea56c193f98c6dacb15810403a808ff6ea0de2a84ff
MD5 ca77997cc012de1084272e4d5ee42241
BLAKE2b-256 aa886b3423a51018e5437a8b5899ba3decb95bb6aa0e6fd465026f41a0b0da9f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 a586ae204826e907ad4cbbb5b4e921f3950c57a18ecda3ae14ce9249c9354212
MD5 f65ee74a59b2c7844fbe6a67096635fd
BLAKE2b-256 cad79147ef92864e2ec886d7947c997ef8e6ceab4e5785c341b7a7595120d6f1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp38-cp38-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 bceb80a11112235ceed24eb11a3baab3c10587536259bc983ee7989449b8c14a
MD5 ffbd854e27e4a102171d6afc744d48f0
BLAKE2b-256 e3f3dc0056ab116bfcd8fe96b6045467d8d7b9d3b62b97c5006c8a86a1d646d0

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 584a4dff3073d8389b0d5909bd5f0a8a3ef17f5fb646f5d84a48ae10b6fe3a40
MD5 f9d838bbc0f9356985d03cb783bdd9ad
BLAKE2b-256 ec5aa91469afc08fa0d5f0bb543e98215071a6dafe4911d7ff3f6d8bb075171e

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 880237874524b74fa5c5961110f5f7aa4b2e5d05ed154a3780cb1208f177bf4b
MD5 c4d592823f6f2b0e0747b671614de031
BLAKE2b-256 ded8600624d5802e30154ffbfb9bc06fcc0c3065b12c9f5e270a9c0b3ebdd1c9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 850fe704446dac53d2279c8dd4ac273e262f541b69823db5f4d896985de06bcd
MD5 79427f4e63c51dc5330e0fbe1bce87ec
BLAKE2b-256 7f32f36f0abb263d760bd76b0c14a2dd74a7b6dec66b0e01ae69fe4ed343f921

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 0255ecfb4628154a33d77bea3484f83f91fd952122784d6c8324c00d660c9d06
MD5 5e6a1ab44a07717828abf0963d79f7fe
BLAKE2b-256 cd1dadf55afe38e861ed4956a0ed94f69841dfa44110ded400649756a7c17c7a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 8c18ebf356906db3ab7c8a46b490a6175070e2ef07d9faddf5002d27d8a0bee3
MD5 e3456a8aaf148f3a0a739748c5199e3d
BLAKE2b-256 97d5fd94dfe4ad8b3ad9f3881f9235b001a24058ede90b66c3786cd03b41b7ec

See more details on using hashes here.

File details

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

File metadata

  • Download URL: plum_dispatch-1.5.16-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 114.5 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.16-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 9f2fc90de973545a06afe117376e3f89c0f78bca1cda89d26b9e43c9f5691e8b
MD5 4b662b445efeb3834ea94abecc89c268
BLAKE2b-256 86b683b48ff106c9b29d80f59d88d5992bb311f073594bf0f8b081a52bac2312

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 fd0d6d3ec102abb1ddd9269e6562afc947e3e4c3d9c457e83d056f545a5d8c1f
MD5 7bbe4eca5953070e34164276627064a8
BLAKE2b-256 896f1a0ec73805054947babeb50af2af00a53658f43af3955a8ed28d612746ec

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp37-cp37m-musllinux_1_1_i686.whl
Algorithm Hash digest
SHA256 5770911b29cc2bef49f98a19fe30fb3da5c76b56a785b4b602193fdb0f2525eb
MD5 c9fa6d4c0cd2fdf92e768504acadda2c
BLAKE2b-256 51aa43127cdb260aaef3d28a56e972801b37dc53e43a075900c4270b5776af98

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 d6efc125236cde4cece0208e349fac4b4ad8f5021e28b821769da6597798c201
MD5 0408529d03cc27e1ac4ba4c13898e3a0
BLAKE2b-256 5dc5773c4e6b8ad3a1e5637b675e9d5bcc2b477b9a14bf884c61bc720dfc7719

See more details on using hashes here.

File details

Details for the file plum_dispatch-1.5.16-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.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 8302c81b5070d94d48c2a13abe28a14a92eff41b75f682a38ed24c98e59875db
MD5 d03ac219fccba7423fa2ec8c343f812c
BLAKE2b-256 718243a79d9888c4ac203d0eb82326500b11e76e4a9a54ec10a557afc72436f3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for plum_dispatch-1.5.16-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 6ba90bb9cced6a7c09ccad7f40da25fca378a0c14474e215459ada93c1b09946
MD5 f17ac989610322d99aac600752a380be
BLAKE2b-256 463b120d6ce38b5767f5c9dbf082872e6573780e7d5bdcfd84c11583de4668d9

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