Skip to main content

Acquisition is a mechanism that allows objects to obtain attributes from the containment hierarchy they're in.

Project description

Environmental Acquisiton

This package implements “environmental acquisiton” for Python, as proposed in the OOPSLA96 paper by Joseph Gil and David H. Lorenz:

We propose a new programming paradigm, environmental acquisition in the context of object aggregation, in which objects acquire behaviour from their current containers at runtime. The key idea is that the behaviour of a component may depend upon its enclosing composite(s). In particular, we propose a form of feature sharing in which an object “inherits” features from the classes of objects in its environment. By examining the declaration of classes, it is possible to determine which kinds of classes may contain a component, and which components must be contained in a given kind of composite. These relationships are the basis for language constructs that supports acquisition.

Introductory Example

Zope implements acquisition with “Extension Class” mix-in classes. To use acquisition your classes must inherit from an acquisition base class. For example:

>>> import ExtensionClass, Acquisition

>>> class C(ExtensionClass.Base):
...     color = 'red'

>>> class A(Acquisition.Implicit):
...     def report(self):
...         print(self.color)
...
>>> a = A()
>>> c = C()
>>> c.a = a

>>> c.a.report()
red

>>> d = C()
>>> d.color = 'green'
>>> d.a = a

>>> d.a.report()
green

>>> try:
...     a.report()
... except AttributeError:
...     pass
... else:
...     raise AssertionError('AttributeError not raised.')

The class A inherits acquisition behavior from Acquisition.Implicit. The object, a, “has” the color of objects c and d when it is accessed through them, but it has no color by itself. The object a obtains attributes from its environment, where its environment is defined by the access path used to reach a.

Acquisition Wrappers

When an object that supports acquisition is accessed through an extension class instance, a special object, called an acquisition wrapper, is returned. In the example above, the expression c.a returns an acquisition wrapper that contains references to both c and a. It is this wrapper that performs attribute lookup in c when an attribute cannot be found in a.

Acquisition wrappers provide access to the wrapped objects through the attributes aq_parent, aq_self, aq_base. Continue the example from above:

>>> c.a.aq_parent is c
True
>>> c.a.aq_self is a
True

Explicit and Implicit Acquisition

Two styles of acquisition are supported: implicit and explicit acquisition.

Implicit acquisition

Implicit acquisition is so named because it searches for attributes from the environment automatically whenever an attribute cannot be obtained directly from an object or through inheritance.

An attribute can be implicitly acquired if its name does not begin with an underscore.

To support implicit acquisition, your class should inherit from the mix-in class Acquisition.Implicit.

Explicit Acquisition

When explicit acquisition is used, attributes are not automatically obtained from the environment. Instead, the method aq_acquire must be used. For example:

>>> print(c.a.aq_acquire('color'))
red

To support explicit acquisition, your class should inherit from the mix-in class Acquisition.Explicit.

Controlling Acquisition

A class (or instance) can provide attribute by attribute control over acquisition. You should subclass from Acquisition.Explicit, and set all attributes that should be acquired to the special value Acquisition.Acquired. Setting an attribute to this value also allows inherited attributes to be overridden with acquired ones. For example:

>>> class C(Acquisition.Explicit):
...     id = 1
...     secret = 2
...     color = Acquisition.Acquired
...     __roles__ = Acquisition.Acquired

The only attributes that are automatically acquired from containing objects are color, and __roles__. Note that the __roles__ attribute is acquired even though its name begins with an underscore. In fact, the special Acquisition.Acquired value can be used in Acquisition.Implicit objects to implicitly acquire selected objects that smell like private objects.

Sometimes, you want to dynamically make an implicitly acquiring object acquire explicitly. You can do this by getting the object’s aq_explicit attribute. This attribute provides the object with an explicit wrapper that replaces the original implicit wrapper.

Filtered Acquisition

The acquisition method, aq_acquire, accepts two optional arguments. The first of the additional arguments is a “filtering” function that is used when considering whether to acquire an object. The second of the additional arguments is an object that is passed as extra data when calling the filtering function and which defaults to None. The filter function is called with five arguments:

  • The object that the aq_acquire method was called on,

  • The object where an object was found,

  • The name of the object, as passed to aq_acquire,

  • The object found, and

  • The extra data passed to aq_acquire.

If the filter returns a true object that the object found is returned, otherwise, the acquisition search continues.

Here’s an example:

>>> from Acquisition import Explicit

>>> class HandyForTesting(object):
...     def __init__(self, name):
...         self.name = name
...     def __str__(self):
...         return "%s(%s)" % (self.name, self.__class__.__name__)
...     __repr__=__str__
...
>>> class E(Explicit, HandyForTesting): pass
...
>>> class Nice(HandyForTesting):
...     isNice = 1
...     def __str__(self):
...         return HandyForTesting.__str__(self)+' and I am nice!'
...     __repr__ = __str__
...
>>> a = E('a')
>>> a.b = E('b')
>>> a.b.c = E('c')
>>> a.p = Nice('spam')
>>> a.b.p = E('p')

>>> def find_nice(self, ancestor, name, object, extra):
...     return hasattr(object,'isNice') and object.isNice

>>> print(a.b.c.aq_acquire('p', find_nice))
spam(Nice) and I am nice!

The filtered acquisition in the last line skips over the first attribute it finds with the name p, because the attribute doesn’t satisfy the condition given in the filter.

Filtered acquisition is rarely used in Zope.

Acquiring from Context

Normally acquisition allows objects to acquire data from their containers. However an object can acquire from objects that aren’t its containers.

Most of the examples we’ve seen so far show establishing of an acquisition context using getattr semantics. For example, a.b is a reference to b in the context of a.

You can also manually set acquisition context using the __of__ method. For example:

>>> from Acquisition import Implicit
>>> class C(Implicit): pass
...
>>> a = C()
>>> b = C()
>>> a.color = "red"
>>> print(b.__of__(a).color)
red

In this case, a does not contain b, but it is put in b’s context using the __of__ method.

Here’s another subtler example that shows how you can construct an acquisition context that includes non-container objects:

>>> from Acquisition import Implicit

>>> class C(Implicit):
...     def __init__(self, name):
...         self.name = name

>>> a = C("a")
>>> a.b = C("b")
>>> a.b.color = "red"
>>> a.x = C("x")

>>> print(a.b.x.color)
red

Even though b does not contain x, x can acquire the color attribute from b. This works because in this case, x is accessed in the context of b even though it is not contained by b.

Here acquisition context is defined by the objects used to access another object.

Containment Before Context

If in the example above suppose both a and b have an color attribute:

>>> a = C("a")
>>> a.color = "green"
>>> a.b = C("b")
>>> a.b.color = "red"
>>> a.x = C("x")

>>> print(a.b.x.color)
green

Why does a.b.x.color acquire color from a and not from b? The answer is that an object acquires from its containers before non-containers in its context.

To see why consider this example in terms of expressions using the __of__ method:

a.x -> x.__of__(a)

a.b -> b.__of__(a)

a.b.x -> x.__of__(a).__of__(b.__of__(a))

Keep in mind that attribute lookup in a wrapper is done by trying to look up the attribute in the wrapped object first and then in the parent object. So in the expressions above proceeds from left to right.

The upshot of these rules is that attributes are looked up by containment before context.

This rule holds true also for more complex examples. For example, a.b.c.d.e.f.g.attribute would search for attribute in g and all its containers first. (Containers are searched in order from the innermost parent to the outermost container.) If the attribute is not found in g or any of its containers, then the search moves to f and all its containers, and so on.

Additional Attributes and Methods

You can use the special method aq_inner to access an object wrapped only by containment. So in the example above, a.b.x.aq_inner is equivalent to a.x.

You can find out the acquisition context of an object using the aq_chain method like so:

>>> [obj.name for obj in a.b.x.aq_chain]
['x', 'b', 'a']

You can find out if an object is in the containment context of another object using the aq_inContextOf method. For example:

>>> a.b.aq_inContextOf(a)
True

Acquisition Module Functions

In addition to using acquisition attributes and methods directly on objects you can use similar functions defined in the Acquisition module. These functions have the advantage that you don’t need to check to make sure that the object has the method or attribute before calling it.

aq_acquire(object, name [, filter, extra, explicit, default, containment])

Acquires an object with the given name.

This function can be used to explictly acquire when using explicit acquisition and to acquire names that wouldn’t normally be acquired.

The function accepts a number of optional arguments:

filter

A callable filter object that is used to decide if an object should be acquired.

The filter is called with five arguments:

  • The object that the aq_acquire method was called on,

  • The object where an object was found,

  • The name of the object, as passed to aq_acquire,

  • The object found, and

  • The extra argument passed to aq_acquire.

If the filter returns a true object that the object found is returned, otherwise, the acquisition search continues.

extra

Extra data to be passed as the last argument to the filter.

explicit

A flag (boolean value) indicating whether explicit acquisition should be used. The default value is true. If the flag is true, then acquisition will proceed regardless of whether wrappers encountered in the search of the acquisition hierarchy are explicit or implicit wrappers. If the flag is false, then parents of explicit wrappers are not searched.

This argument is useful if you want to apply a filter without overriding explicit wrappers.

default

A default value to return if no value can be acquired.

containment

A flag indicating whether the search should be limited to the containment hierarchy.

In addition, arguments can be provided as keywords.

aq_base(object)

Return the object with all wrapping removed.

aq_chain(object [, containment])

Return a list containing the object and it’s acquisition parents. The optional argument, containment, controls whether the containment or access hierarchy is used.

aq_get(object, name [, default, containment])

Acquire an attribute, name. A default value can be provided, as can a flag that limits search to the containment hierarchy.

aq_inner(object)

Return the object with all but the innermost layer of wrapping removed.

aq_parent(object)

Return the acquisition parent of the object or None if the object is unwrapped.

aq_self(object)

Return the object with one layer of wrapping removed, unless the object is unwrapped, in which case the object is returned.

In most cases it is more convenient to use these module functions instead of the acquisition attributes and methods directly.

Acquisition and Methods

Python methods of objects that support acquisition can use acquired attributes. When a Python method is called on an object that is wrapped by an acquisition wrapper, the wrapper is passed to the method as the first argument. This rule also applies to user-defined method types and to C methods defined in pure mix-in classes.

Unfortunately, C methods defined in extension base classes that define their own data structures, cannot use aquired attributes at this time. This is because wrapper objects do not conform to the data structures expected by these methods. In practice, you will seldom find this a problem.

Conclusion

Acquisition provides a powerful way to dynamically share information between objects. Zope uses acquisition for a number of its key features including security, object publishing, and DTML variable lookup. Acquisition also provides an elegant solution to the problem of circular references for many classes of problems. While acquisition is powerful, you should take care when using acquisition in your applications. The details can get complex, especially with the differences between acquiring from context and acquiring from containment.

Changelog

6.1 (2024-09-16)

  • Add final support for Python 3.13.

6.0 (2024-05-30)

  • Drop support for Python 3.7.

  • Build Windows wheels on GHA.

5.2 (2024-02-13)

  • Add preliminary support for Python 3.13 as of 3.13a3.

5.1 (2023-10-05)

  • Add support for Python 3.12.

5.0 (2023-03-24)

  • Build Linux binary wheels for Python 3.11.

  • Drop support for Python 2.7, 3.5, 3.6.

  • Add preliminary support for Python 3.12a5.

4.13 (2022-11-17)

  • Add support for building arm64 wheels on macOS.

4.12 (2022-11-03)

  • Add support for final Python 3.11 release.

4.11 (2022-09-16)

  • Add support for Python 3.11 (as of 3.11.0rc1).

  • Switch from -Ofast to -O3 when compiling code for Linux wheels. (#64)

4.10 (2021-12-07)

  • Fix bug in the PURE_PYTHON version affecting aq_acquire applied to a class with a filter.

  • Improve interface documentation.

  • Add support for Python 3.10.

4.9 (2021-08-19)

  • On CPython no longer omit compiling the C code when PURE_PYTHON is required. Just evaluate it at runtime. (#53)

4.8 (2021-07-20)

  • Various fixes for the PURE_PYTHON version, e.g. make Acquired an str (as required by Zope), avoid infinite __cmp__ loop. (#51, #48)

  • Create aarch64 wheels.

4.7 (2020-10-07)

  • Add support for Python 3.8 and 3.9.

4.6 (2019-04-24)

  • Drop support for Python 3.4.

  • Add support for Python 3.8a3.

  • Add support to call bytes() on an object wrapped by an ImplicitAcquisitionWrapper. (#38)

4.5 (2018-10-05)

  • Avoid deprecation warnings by using current API.

  • Add support for Python 3.7.

4.4.4 (2017-11-24)

  • Add Appveyor configuration to automate building Windows eggs.

4.4.3 (2017-11-23)

  • Fix the extremely rare potential for a crash when the C extensions are in use. See issue 21.

4.4.2 (2017-05-12)

  • Fix C capsule name to fix import errors.

  • Ensure our dependencies match our expactations about C extensions.

4.4.1 (2017-05-04)

  • Fix C code under Python 3.4, with missing Py_XSETREF.

4.4.0 (2017-05-04)

  • Enable the C extension under Python 3.

  • Drop support for Python 3.3.

4.3.0 (2017-01-20)

  • Make tests compatible with ExtensionClass 4.2.0.

  • Drop support for Python 2.6 and 3.2.

  • Add support for Python 3.5 and 3.6.

4.2.2 (2015-05-19)

4.2.1 (2015-04-23)

4.2 (2015-04-04)

  • Add support for PyPy, PyPy3, and Python 3.2, 3.3, and 3.4.

4.1 (2014-12-18)

  • Bump dependency on ExtensionClass to match current release.

4.0.3 (2014-11-02)

  • Skip readme.rst tests when tests are run outside a source checkout.

4.0.2 (2014-11-02)

  • Include *.rst files in the release.

4.0.1 (2014-10-30)

  • Tolerate Unicode attribute names (ASCII only). LP #143358.

  • Make module-level aq_acquire API respect the default parameter. LP #1387363.

  • Don’t raise an attribute error for __iter__ if the fallback to __getitem__ succeeds. LP #1155760.

4.0 (2013-02-24)

  • Added trove classifiers to project metadata.

4.0a1 (2011-12-13)

  • Raise RuntimeError: Recursion detected in acquisition wrapper if an object with a __parent__ pointer points to a wrapper that in turn points to the original object.

  • Prevent wrappers to be created while accessing __parent__ on types derived from Explicit or Implicit base classes.

2.13.9 (2015-02-17)

  • Tolerate Unicode attribute names (ASCII only). LP #143358.

  • Make module-level aq_acquire API respect the default parameter. LP #1387363.

  • Don’t raise an attribute error for __iter__ if the fallback to __getitem__ succeeds. LP #1155760.

2.13.8 (2011-06-11)

  • Fixed a segfault on 64bit platforms when providing the explicit argument to the aq_acquire method of an Acquisition wrapper. Thx to LP #675064 for the hint to the solution. The code passed an int instead of a pointer into a function.

2.13.7 (2011-03-02)

  • Fixed bug: When an object did not implement __unicode__, calling unicode(wrapped) was calling __str__ with an unwrapped self.

2.13.6 (2011-02-19)

  • Add aq_explicit to IAcquisitionWrapper.

  • Fixed bug: unicode(wrapped) was not calling a __unicode__ method on wrapped objects.

2.13.5 (2010-09-29)

  • Fixed unit tests that failed on 64bit Python on Windows machines.

2.13.4 (2010-08-31)

  • LP 623665: Fixed typo in Acquisition.h.

2.13.3 (2010-04-19)

  • Use the doctest module from the standard library and no longer depend on zope.testing.

2.13.2 (2010-04-04)

  • Give both wrapper classes a __getnewargs__ method, which causes the ZODB optimization to fail and create persistent references using the _p_oid alone. This happens to be the persistent oid of the wrapped object. This lets these objects to be persisted correctly, even though they are passed to the ZODB in a wrapped state.

  • Added failing tests for http://dev.plone.org/plone/ticket/10318. This shows an edge-case where AQ wrappers can be pickled using the specific combination of cPickle, pickle protocol one and a custom Pickler class with an inst_persistent_id hook. Unfortunately this is the exact combination used by ZODB3.

2.13.1 (2010-02-23)

  • Update to include ExtensionClass 2.13.0.

  • Fix the tp_name of the ImplicitAcquisitionWrapper and ExplicitAcquisitionWrapper to match their Python visible names and thus have a correct __name__.

  • Expand the tp_name of our extension types to hold the fully qualified name. This ensures classes have their __module__ set correctly.

2.13.0 (2010-02-14)

2.12.4 (2009-10-29)

  • Fix iteration proxying to pass self acquisition-wrapped into both __iter__ as well as __getitem__ (this fixes https://bugs.launchpad.net/zope2/+bug/360761).

  • Add tests for the __getslice__ proxying, including open-ended slicing.

2.12.3 (2009-08-08)

  • More 64-bit fixes in Py_BuildValue calls.

  • More 64-bit issues fixed: Use correct integer size for slice operations.

2.12.2 (2009-08-02)

2.12.1 (2009-04-15)

  • Update for iteration proxying: The proxy for __iter__ must not rely on the object to have an __iter__ itself, but also support fall-back iteration via __getitem__ (this fixes https://bugs.launchpad.net/zope2/+bug/360761).

2.12 (2009-01-25)

  • Release as separate package.

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

acquisition-6.1.tar.gz (65.6 kB view details)

Uploaded Source

Built Distributions

Acquisition-6.1-cp313-cp313-win_amd64.whl (65.8 kB view details)

Uploaded CPython 3.13 Windows x86-64

Acquisition-6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (121.9 kB view details)

Uploaded CPython 3.13 manylinux: glibc 2.17+ ARM64

Acquisition-6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (122.1 kB view details)

Uploaded CPython 3.13 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.5+ x86-64

Acquisition-6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (114.2 kB view details)

Uploaded CPython 3.13 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

Acquisition-6.1-cp313-cp313-macosx_11_0_arm64.whl (64.4 kB view details)

Uploaded CPython 3.13 macOS 11.0+ ARM64

Acquisition-6.1-cp313-cp313-macosx_10_9_x86_64.whl (64.8 kB view details)

Uploaded CPython 3.13 macOS 10.9+ x86-64

Acquisition-6.1-cp312-cp312-win_amd64.whl (65.7 kB view details)

Uploaded CPython 3.12 Windows x86-64

Acquisition-6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (121.9 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64

Acquisition-6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (122.1 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.5+ x86-64

Acquisition-6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (114.2 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

Acquisition-6.1-cp312-cp312-macosx_11_0_arm64.whl (64.3 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

Acquisition-6.1-cp312-cp312-macosx_10_9_x86_64.whl (64.7 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

Acquisition-6.1-cp311-cp311-win_amd64.whl (65.6 kB view details)

Uploaded CPython 3.11 Windows x86-64

Acquisition-6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (122.2 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64

Acquisition-6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (122.7 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.5+ x86-64

Acquisition-6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (115.6 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

Acquisition-6.1-cp311-cp311-macosx_11_0_arm64.whl (64.4 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

Acquisition-6.1-cp311-cp311-macosx_10_9_x86_64.whl (64.6 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

Acquisition-6.1-cp310-cp310-win_amd64.whl (65.5 kB view details)

Uploaded CPython 3.10 Windows x86-64

Acquisition-6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (118.5 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64

Acquisition-6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (119.2 kB view details)

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

Acquisition-6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (112.2 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

Acquisition-6.1-cp310-cp310-macosx_11_0_arm64.whl (64.4 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

Acquisition-6.1-cp310-cp310-macosx_10_9_x86_64.whl (64.6 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

Acquisition-6.1-cp39-cp39-win_amd64.whl (65.6 kB view details)

Uploaded CPython 3.9 Windows x86-64

Acquisition-6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (117.9 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64

Acquisition-6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (118.6 kB view details)

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

Acquisition-6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (111.5 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

Acquisition-6.1-cp39-cp39-macosx_11_0_arm64.whl (64.4 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

Acquisition-6.1-cp39-cp39-macosx_10_9_x86_64.whl (64.6 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

Acquisition-6.1-cp38-cp38-win_amd64.whl (65.5 kB view details)

Uploaded CPython 3.8 Windows x86-64

Acquisition-6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (118.9 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64

Acquisition-6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (119.6 kB view details)

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

Acquisition-6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (112.6 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

Acquisition-6.1-cp38-cp38-macosx_11_0_arm64.whl (64.4 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

Acquisition-6.1-cp38-cp38-macosx_10_9_x86_64.whl (64.6 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

File details

Details for the file acquisition-6.1.tar.gz.

File metadata

  • Download URL: acquisition-6.1.tar.gz
  • Upload date:
  • Size: 65.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.9

File hashes

Hashes for acquisition-6.1.tar.gz
Algorithm Hash digest
SHA256 e88b296d6ec5fcb63194deb91d8c4df37150dcae149ede4e1aeb115d042e9378
MD5 dc2ee6e3db13c4f0eeec74da9078323a
BLAKE2b-256 679a3df1e83e6655ca6eee9920f746455b9865c7dff9ef5ca9dadb683fb38c02

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 35da0b71db5b02376a40d6f342776619979767f30d8dcd06cea45e0a8fb92e5d
MD5 6af3eab2cd7227c4f7bc19bda14bd54e
BLAKE2b-256 b09c2ed62813b108f090f9e8939aba4b281ebedb4fbf213b32e014eb81546358

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 da428b419eacd79930e8f27c0a2efbb32dc113402211696dfa6dc1627500148e
MD5 c8ad463ba731d69c0626cfd8b9821b99
BLAKE2b-256 5c11a857a37ee1f84bcff8c61de300b72fdfab3d7af739f36d9e0b9d99445005

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 127ee652eae6a0196443f69ccbd2362d9f5e28fd6eb6a178d3daa21276179355
MD5 d43e038dd6999afe6fa9db65962558f9
BLAKE2b-256 9e99ce406017db5f4698fce40b631682ffaf71ca878d1e8c9f715f0029b35163

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 05b93dbf29cbdb292557a6777aa0aab07acfa622764bc760facd1eab4b5415f9
MD5 4141cd69f1afe7c956a87ac7aa355ddb
BLAKE2b-256 7750ef82fd6bd6f9e3bd6f0e37361d61ef9f693e6490becac109b46461b45950

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 314cee791a819f5145dada1336682c6ba93ec33ccd6ee478fea69ce41c67cdbe
MD5 4c047a9743692aedc4c629120b710b12
BLAKE2b-256 f383761e8f0e01a36d848cc1c22d8dd2b59fda0fad3466df369fbfed40dafb28

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp313-cp313-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp313-cp313-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3e2115def6d944b054c57215b5acb8f1dec8ee3c2e80d4577dd5666dd3281217
MD5 9d688121f046d4caf9947ec37c52355a
BLAKE2b-256 982d85fb469da1cfd704a50b3d0ae367aba16013cb22ee526adec56c4415cef1

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 571c3ef9f5e90e3f5b70709bba4df2d4a66889334c9bc00be88fec4123279418
MD5 c5c31f75ea0127db3e97ac1ddd85b1a9
BLAKE2b-256 9f2b0f3a80bae17d9fcac17d1dbc0ab06f14a7751b9bf6b24b9b3114bee27de2

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 57efad980a9055485b6bddc785f1a13cae16606bf88e20e00b461d0cbdc4f7f9
MD5 b77651fa3b3f439c16470e1f9965a3cb
BLAKE2b-256 20592683ef5c750dfb1015857428bcb682f4334a045c5059f6c19c6c8a61adb6

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1f8b05bd67cf835f756a73cfb6f02eaf28bb0cad6f96097f479fdd7a17d5c444
MD5 6709f4d76deac5f19d9c3bb906bbb408
BLAKE2b-256 38a565c2841fd68caf8e62e554fb7fdb24b8706b396f0ae885507dd819bf98cb

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 d1bce20e2b285a675ffdc0c7587b530366dbec120c960da75db29dc9685431a2
MD5 6bee64318e050579ef58b4bbf71e76ff
BLAKE2b-256 d1d25d7fdad1e93e1773f9ef94c1ee8eb37f66d50770ff0a8397d844f3677b21

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 16e6ef44d626dfcfa69fa8481212db536be26fbd831f3810ad305d1514ee5f50
MD5 ca7c20eedf1eb5b4d99cc690c00e2cff
BLAKE2b-256 01ef491b2f66eefa8428562aa7a8065a0f809276f083ba6944c372a2bc737e59

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 0c82221d6563b1d4da15ee2d04d2e1e414beca07e419ca11d678fe2296445d22
MD5 939e1402085a09129ea327a9a4037bc8
BLAKE2b-256 7f0e054da462818895a0112b8c45164e123b2fd940459c4106f93afee2478e6e

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 3570958adf72db3a976d05cd2eaf241079b0ca65740e4f9e66c8a60646a60a79
MD5 9c2f6ed8bb6642eabbbb073d0400f9a8
BLAKE2b-256 116afec79a5e467fdbed6925a4177512845f47df5286511214e587100cc3f8f9

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 492b54abfade10420539bc599f2dcb6fd58187ca5231b9d2eedfb5be4a144ac3
MD5 ff8abb3bbd9eb9339fee890ee8bfcd79
BLAKE2b-256 eeacd069cab7ff6e4e9dfff085b10d269be8a57e87e177db9f363411a8f619f4

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3f7161d1bb950107efa2b887e43d9d259f8d2e562accfe7e4b28020bb3885012
MD5 32f43c4716e45be07f2609e7a74ac9f1
BLAKE2b-256 be78112f3ab456f40bb2cd3930140419b22ff60b02f0ec9eb5ca1cf8d97d2ea9

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 965098b74c055b23292c3f06b8399dd8b9b5b534a31fd4027952ee09f94168ae
MD5 32b612c99e09713a7cd830a02ea46d3b
BLAKE2b-256 f46f808efe4980aa10334df7a710b851de181411590cf472bc50d8dcdfad9806

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1de0b1204b02ae28cb095985327218417c3d7d832afd194124ebd5024e6a9bca
MD5 a372ebf15d0dedd20fefc7996dd11d3a
BLAKE2b-256 7a9de5c749721e1e3b2ff6b48c517706cc155675be96f56ce0841a37429f68f0

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 3f0f18441f04f6c0c401bfe44c989ca5f617f35742906862823c228bbd8fea36
MD5 1e3571e9bdfc7f832273aa64d1c8a25d
BLAKE2b-256 0ba9b3fcf2a807fc01bb72e5fb4717a6fe44b4d820f5f9585f8acc5adb34007e

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 dda39ac1ae2b8328e518b19b4aaf8a44cd1fdba765befac68533b081465b2965
MD5 8b9c34fcf364878981da3c974be0b02f
BLAKE2b-256 b5bc76f583cfd3eabcf68301d5ec3d8d3690891b825df80bc49a204499498a8d

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0b49c883d1fa865fd391dd55f480c69991876222eaa881eb2e9e42d8e0f6f1f4
MD5 e9b7fd1af2d131ccb254a9578a6b2393
BLAKE2b-256 fc43d6dcebc33782550d82c3858a8544b867333e3c3560d2c7d43ab0a52e2fb1

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 57d16b12829748f57668294108c5e92712373b5c06781a26e9925ba10eaff8c5
MD5 a4f7802e80e915234d2d121d7f784794
BLAKE2b-256 70cd73d4f59f3e03fbde8316b520b75a4f7f224221b55fce8f430ec04ec12b6f

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 ae613f0c54a77c54de83a66c44854919e9807be600f0fa4826af3969c1109619
MD5 0290da5d8090f7d5be4cf70d829c1bf3
BLAKE2b-256 275abf0eb042cf07ab29122ad66e3a84007eea511fd43bfb741c5468990a1348

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1489bd67b823fe847fd23c2281a419efa5d1fea52c690a6b4ecc6a387d7e4430
MD5 32858f65a00ae453dba1f53b344f7be3
BLAKE2b-256 fdecb80cf5bcada1e95f02e554e0ebf23d15fa65ef39a44e19144e22cd573a3b

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 2f2fab65f24e302da1ea1a957fc9506090bd4c27b5f1718c6fd0152e4d496386
MD5 37cd13c98b7bb8567eeb0db0d819982f
BLAKE2b-256 14464dc1080d8c83b6746b239180960ad26fd0bc6f1d9bda75f472f31a2d3604

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: Acquisition-6.1-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 65.6 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.9.13

File hashes

Hashes for Acquisition-6.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 4f18ec1f725479b736572d5a23a1577bb4d1b46bcc3dc2cda4cc4990f2f445a7
MD5 ca44d2b0d1a70270cbcc9d958c874623
BLAKE2b-256 776794b065708757e7b1dece6e82c86e2d59f429c83fa91a259f274f6821f5c9

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f3e4eb3538aabbe4e2085d51833f2e6603af915a861cab54816b37403566407d
MD5 af7b8e4ce4ff755173665cd25b15fe38
BLAKE2b-256 8f17f14631bd67eff020f3cc2d528eee8594d091271a38b477fef33db308e86f

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e9102c692d39256970b3f5f3587585daa7b15f37a715e18d841d6431e0ca041c
MD5 a7c0ddd57fda5d0d02f02c4a388d6751
BLAKE2b-256 7b0b7b51a2da3aae202f945b3c7577a11f65e6a1b9e98272d42b930434c3826f

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 79b65cd976c78f56f8eb95e9b1c44038d9a3b946bde6ab17ef721e11269e1c16
MD5 9add31c6d6fa2d6886712ac59e381c43
BLAKE2b-256 07d23c62a127d6d43317f7b1cfa57f4ff318e7d0d2771770fad11ab31c0b9185

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4b13e78503ac0f27ec22105648f2dd9f647518b3a108924f1f542bc8f76f28e2
MD5 72e0a93a50dbbd81ef1ccf612037131e
BLAKE2b-256 0913df3f3be68ccff3602b0026859ec30fe6ad7a57bc2cbb9e10c8563868df68

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 9cbcb0ab43f267a356715c5990513e886ef7992dbd9ee1465ec444a3b39e5477
MD5 f99ce57ac8fcadcd0d0f263a105c6d57
BLAKE2b-256 45ff8e2497087b60111110c57a55b5d1b7fe4411947daa7323947ee594304302

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: Acquisition-6.1-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 65.5 kB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.8.10

File hashes

Hashes for Acquisition-6.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 aefddf106cff40dda1c1e67dc958c2641449b75ebb047e0a3664b08e9b4e12a0
MD5 d003872a78c72fef4186afc1cd02e2cd
BLAKE2b-256 b950c973795b68dbbef68e6f678827530b10e85da5ca9d74d5e98ff7b490d991

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 31f9163c85abbe02fa472edb8c2a3de38c2370953f0bf2c5ed011f45cf2fde1d
MD5 b599c9083ee0bcc1086ead49d84a9214
BLAKE2b-256 d7ccdd053e46c3f48fa1c00063a2555437a09cc97ac55f2ea20be90f3e843d5e

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8703d1578d7108b0fe122050357752eebbcb44a63490f636563f882e69a74a00
MD5 215f3cc9e96b6c7930239d1825b1d320
BLAKE2b-256 5a41c34e4acf4d293f6d48e78d81288439693e8e9dc895eda0332b0dbde7c495

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 20ef445a2c26abd10233ed441f9c148a2084faa795056cfb2613aa6a53b51ad8
MD5 c45c6a7990e472a93db095a66c0cece8
BLAKE2b-256 1c0e4e7f8bc731808d1650400ebb29e8f1585cfb41986b89f84bad0df0a0e58c

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 081fbb606de2c3d87df6518e074bbfb2527b0abe95fe396685c0cbc5d1456cc8
MD5 4c03b0c19eae50319a5b7a627668627c
BLAKE2b-256 47f046874bfa76225f53b99ea841bde046bd91a5e338aef878d461bde328a54d

See more details on using hashes here.

File details

Details for the file Acquisition-6.1-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for Acquisition-6.1-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 69aee444760bc07b59abbd64db271b4fb4c2d51692fc2b738b0c4cf7529cf8b2
MD5 a2f64dccbbdb2b2979309ab81fcf5a7b
BLAKE2b-256 46f6e3d950390c117f675b6b3431426afb2cf47adda3a95d8f7fc7e139b5a4ef

See more details on using hashes here.

Supported by

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