Skip to main content

Mutable variant of collections.namedtuple -- recordclass.recordclass, which support assignments, and other memory saving variants.

Project description

Recordclass library

Recordclass is MIT Licensed python library. It was started as a "proof of concept" for the problem of fast "mutable" alternative of namedtuple (see question on stackoverflow). It implements a factory function recordclass (a variant of collection.namedtuple) in order to create record-like classes with the same API as collection.namedtuple. It was evolved further in order to provide more memory saving, fast and flexible types.

Recordclass library provide record-like classes that do not participate in cyclic garbage collection (CGC) mechanism, but support only reference counting mechanism for garbage collection. The instances of such classes havn't PyGC_Head prefix in the memory, which decrease their size. This may make sense in cases where it is necessary to limit the size of the objects as much as possible, provided that they will never be part of references cycles in the application. For example, when an object represents a record with fields that represent simple values by convention (int, float, str, date/time/datetime, timedelta, etc.).

In order to illustrate this, consider a simple class with type hints:

class Point:
    x: int
    y: int

By contract instances of the class Point have attributes x and y with values of int type. Assigning other types of values, which are not subclass of int, should be considered as a violation of the contract.

Another examples are non-recursive data structures in which all leaf elements represent a value of an atomic type. Of course, in python, nothing prevent you from “shooting yourself in the foot" by creating the reference cycle in the script or application code. But in many cases, this can still be avoided provided that the developer understands what he is doing and uses such classes in the code with care. Another option is to use static code analyzers along with type annotations to monitor compliance with typehints.

  1. The recodeclass library provide the base class dataobject. The type of dataobject is special metaclass datatype. It control creation of subclasses of dataobject, which will not participate in CGC by default. As the result the instance of such class need less memory. It's memory footprint is similar to memory footprint of instances of the classes with __slots__. The difference is equal to the size of PyGC_Head. It also tunes basicsize of the instances, creates descriptors for the fields and etc. All subclasses of dataobject created by class statement support attrs/dataclasses-like API. For example:

     from recordclass import dataobject, astuple, asdict
     class Point(dataobject):
         x:int
         y:int
    
     >>> p = Point(1, 2)
     >>> astuple(p)
     (1, 2)
     >>> asdict(p)
     {'x':1, 'y':2}
    
  2. The recordclass factory create dataobject-based subclass with specified fields and support namedtuple-like API. By default it will not participate in CGC too.

     >>> from recordclass import recordclass
     >>> Point = recordclass('Point', 'x y')
     >>> p = Point(1, 2)
     >>> p.y = -1
     >>> print(p._astuple)
     (1, -1)
    
  3. It provide a factory function make_dataclass for creation of subclasses of dataobject with the specified field names. These subclasses support attrs/dataclasses-like API. This is an equivalent to creation of subclasses of dataobject using class statement. For example:

     >>> Point = make_dataclass('Point', 'x y')
     >>> p = Point(1, 2)
     >>> p.y = -1
     >>> print(p.x, p.y)
     1 -1
    
  4. It provide a factory function make_arrayclass in order to create subclass of dataobject wich can consider as array of simple values. For example:

     >>> Pair = make_arrayclass(2)
     >>> p = Pair(2, 3)
     >>> p[1] = -1
     >>> print(p)
     Pair(2, -1)
    
  5. It provide classes lightlist and litetuple, which considers as list-like and tuple-like light containers in order to save memory. Mutable variant of litetuple is called by mutabletuple. The instances of both types don't participate in CGC. For example:

     >>> lt = litetuple(1, 2, 3)
     >>> mt = mutabletuple(1, 2, 3)
     >>> lt == mt
     True
     >>> mt[-1] = -3
     >>> lt == mt
     False
     >>> print(sys.getsizeof(litetuple(1,2,3)), sys.getsizeof((1,2,3)))
     64 48
    

Main repository for recordclassis on bitbucket.

Here is also a simple example.

Quick start

Installation

Installation from directory with sources

Install:

>>> python setup.py install

Run tests:

>>> python test_all.py

Installation from PyPI

Install:

>>> pip install recordclass

Run tests:

>>> python -c "from recordclass.test import *; test_all()"

Quick start with recordclass

The recordclass factory function is designed to create classes that support namedtuple's API, can be mutable and immutable, provide fast creation of the instances and have a minimum memory footprint.

First load inventory:

>>> from recordclass import recordclass

Example with recordclass:

>>> Point = recordclass('Point', 'x y')
>>> p = Point(1,2)
>>> print(p)
Point(1, 2)
>>> print(p.x, p.y)
1 2             
>>> p.x, p.y = 1, 2
>>> print(p)
Point(1, 2)
>>> sys.getsizeof(p) # the output below is for 64bit cpython3.8+
32

Example with class statement and typehints:

>>> from recordclass import RecordClass

class Point(RecordClass):
   x: int
   y: int

>>> print(Point.__annotations__)
{'x': <class 'int'>, 'y': <class 'int'>}
>>> p = Point(1, 2)
>>> print(p)
Point(1, 2)
>>> print(p.x, p.y)
1 2
>>> p.x, p.y = 1, 2
>>> print(p)
Point(1, 2)

By default recordclass-based class instances doesn't participate in CGC and therefore they are smaller than namedtuple-based ones. If one want to use it in scenarios with reference cycles then one have to use option gc=True (gc=False by default):

>>> Node = recordclass('Node', 'root children', gc=True)

or

@clsconfig(gc=True)
class Node(RecordClass):
     root: 'Node'
     chilren: list

Quick start with dataobject

Dataobject is the base class for creation of data classes with fast instance creation and small memory footprint. They don't provide namedtuple-like API.

First load inventory:

>>> from recordclass import dataobject, asdict, astuple

class Point(dataobject):
    x: int
    y: int

>>> print(Point.__annotations__)
{'x': <class 'int'>, 'y': <class 'int'>}

>>> p = Point(1,2)
>>> print(p)
Point(x=1, y=2)

>>> sys.getsizeof() # the output below for 64bit python 3.8+
32
>>> p.__sizeof__() == sys.getsizeof(p) # no additional space for CGC support
True    

>>> p.x, p.y = 10, 20
>>> print(p)
Point(x=10, y=20)
>>> asdict(p)
{'x':10, 'y':20}
>>> astuple(p)
(10, 20)

By default subclasses of dataobject are mutable. If one want make it immutable then there is the option readonly=True:

class Point(dataobject, readonly=True):
    x: int
    y: int

>>> p = Point(1,2)
>>> p.x = -1
TypeError: item is readonly

By default subclasses of dataobject are not iterable by default. If one want make it iterable then there is the option iterable=True:

class Point(dataobject, iterable=True):
    x: int
    y: int

>>> p = Point(1,2)
>>> for x in p: print(x)
1
2

Another way to create subclasses of dataobject – factory function make_dataclass:

>>> from recordclass import make_dataclass

>>> Point = make_dataclass("Point", [("x",int), ("y",int)])

or

>>> Point = make_dataclass("Point", {"x":int, "y":int})

Default values are also supported::

class CPoint(dataobject):
    x: int
    y: int
    color: str = 'white'

or

>>> CPoint = make_dataclass("CPoint", [("x",int), ("y",int), ("color",str)], defaults=("white",))

>>> p = CPoint(1,2)
>>> print(p)
Point(x=1, y=2, color='white')

But

class PointInvalidDefaults(dataobject):
    x:int = 0
    y:int

is not allowed. A fields without default value may not appear after a field with default value.

There is the options fast_new=True. It allows faster creation of the instances. Here is an example:

class FastPoint(dataobject, fast_new=True):
    x: int
    y: int

The followings timings explain (in jupyter notebook) boosting effect of fast_new option:

%timeit l1 = [Point(i,i) for i in range(100000)]
%timeit l2 = [FastPoint(i,i) for i in range(100000)]
# output with python 3.9 64bit
25.6 ms ± 2.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
10.4 ms ± 426 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Using dataobject-based classes for recursive data without reference cycles

There is the option deep_dealloc (default value is True) for deallocation of recursive datastructures. Let consider simple example:

class LinkedItem(dataobject, fast_new=True):
    val: object
    next: 'LinkedItem'

class LinkedList(dataobject, deep_dealloc=True):
    start: LinkedItem = None
    end: LinkedItem = None

    def append(self, val):
        link = LinkedItem(val, None)
        if self.start is None:
            self.start = link
        else:
            self.end.next = link
        self.end = link

Without deep_dealloc=True deallocation of the instance of LinkedList will be failed if the length of the linked list is too large. But it can be resolved with __del__ method for clearing the linked list:

def __del__(self):
    curr = self.start
    while curr is not None:
        next = curr.next
        curr.next = None
        curr = next

There is builtin more fast deallocation method using finalization mechanizm when deep_dealloc=True. In such case one don't need __del__ method for clearing tthe list.

Note that for classes with gc=True (cyclic GC is used) this method is disabled: the python's cyclic GC is used.

For more details see notebook example_datatypes.

Memory footprint

The following table explain memory footprints of recordclass-base and dataobject-base objects:

namedtuple class with __slots__ recordclass dataobject
$g+b+s+n*p$ $g+b+n*p$ $b+n*p$ $b+n*p$

where:

  • b = sizeof(PyObject)
  • s = sizeof(Py_ssize_t)
  • n = number of items
  • p = sizeof(PyObject*)
  • g = sizeof(PyGC_Head)

This is useful in that case when you absolutely sure that reference cycle isn't supposed. For example, when all field values are instances of atomic types. As a result the size of the instance is decreased by 24-32 bytes (for cpython 3.4-3.7) and by 16 bytes since cpython 3.8.

Performance counters

Here is the table with performance counters (python 3.9, debian linux, x86-64), which are mesured using utils/perfcount.py script:

id new getattr setattr size
namedtuple 2.643526 0.471421 56
class+slots 1.851441 0.536047 0.549807 48
dataobject 2.017816 0.466287 0.534306 32
dataobject+fast_new 0.927759 0.468668 0.523788 32
dataobject+gc 2.162687 0.463672 0.523189 48
dataobject+fast_new+gc 1.046897 0.468382 0.525876 48

Changes:

0.15.1

  • Options readonly and iterable now can be sspecified via keyword arguments in class statement. For example:

      class Point(dataobject, readonly=True, iterable=True):
           x:int
           y:int
    
  • Add update(cls, **kwargs) function to update attribute values.`

0.15

  • Now library supports only Python >= 3.6
  • 'gc' and 'fast_new' options now can be specified as kwargs in class statement.
  • Add a function astuple(ob) for transformation dataobject instance ob to a tuple.
  • Drop datatuple based classes.
  • Add function make(cls, args, **kwargs) to create instance of the class cls.
  • Add function clone(ob, **kwargs) to clone dataobject instance ob.
  • Make structclass as alias of make_dataclass.
  • Add option 'deep_dealloc' (@clsconfig(deep_dealloc=True)) for deallocation instances of dataobject-based recursive subclasses.

0.14.3:

  • Subclasses of dataobject now support iterable and hashable protocols by default.

0.14.2:

  • Fix compilation issue for python 3.9.

0.14.1:

  • Fix issue with hash when subclassing recordclass-based classes.

0.14:

  • Add doc to generated dataobject-based class in order to support inspect.signature.
  • Add fast_new argument/option for fast instance creation.
  • Fix refleak in litelist.
  • Fix sequence protocol ability for dataobject/datatuple.
  • Fix typed interface for StructClass.

0.13.2

  • Fix issue #14 with deepcopy of dataobjects.

0.13.1

  • Restore ``join_classesand add new functionjoin_dataclasses`.

0.13.0.1

  • Remove redundant debug code.

0.13

  • Make recordclass compiled and work with cpython 3.8.
  • Move repository to git instead of mercurial since bitbucket will drop support of mercurial repositories.
  • Fix some potential reference leaks.

0.12.0.1

  • Fix missing .h files.

0.12

  • clsconfig now become the main decorator for tuning dataobject-based classes.
  • Fix concatenation of mutabletuples (issue #10).

0.11.1:

  • dataobject instances may be deallocated faster now.

0.11:

  • Rename memoryslots to mutabletuple.
  • mutabletuple and immutabletuple dosn't participate in cyclic garbage collection.
  • Add litelist type for list-like objects, which doesn't participate in cyglic garbage collection.

0.10.3:

  • Introduce DataclassStorage and RecordclassStorage. They allow cache classes and used them without creation of new one.
  • Add iterable decorator and argument. Now dataobject with fields isn't iterable by default.
  • Move astuple to dataobject.c.

0.10.2

  • Fix error with dataobject's __copy__.
  • Fix error with pickling of recordclasses and structclasses, which was appeared since 0.8.5 (Thanks to Connor Wolf).

0.10.1

  • Now by default sequence protocol is not supported by default if dataobject has fields, but iteration is supported.
  • By default argsonly=False for usability reasons.

0.10

  • Invent new factory function make_class for creation of different kind of dataobject classes without GC support by default.
  • Invent new metaclass datatype and new base class dataobject for creation dataobject class using class statement. It have disabled GC support, but could be enabled by decorator dataobject.enable_gc. It support type hints (for python >= 3.6) and default values. It may not specify sequence of field names in __fields__ when type hints are applied to all data attributes (for python >= 3.6).
  • Now recordclass-based classes may not support cyclic garbage collection too. This reduces the memory footprint by the size of PyGC_Head. Now by default recordclass-based classes doesn't support cyclic garbage collection.

0.9

  • Change version to 0.9 to indicate a step forward.
  • Cleanup dataobject.__cinit__.

0.8.5

  • Make arrayclass-based objects support setitem/getitem and structclass-based objects able to not support them. By default, as before structclass-based objects support setitem/getitem protocol.
  • Now only instances of dataobject are comparable to 'arrayclass'-based and structclass-based instances.
  • Now generated classes can be hashable.

0.8.4

  • Improve support for readonly mode for structclass and arrayclass.
  • Add tests for arrayclass.

0.8.3

  • Add typehints support to structclass-based classes.

0.8.2

  • Remove usedict, gc, weaklist from the class __dict__.

0.8.1

  • Remove Cython dependence by default for building recordclass from the sources [Issue #7].

0.8

  • Add structclass factory function. It's analog of recordclass but with less memory footprint for it's instances (same as for instances of classes with __slots__) in the camparison with recordclass and namedtuple (it currently implemented with Cython).
  • Add arrayclass factory function which produce a class for creation fixed size array. The benefit of such approach is also less memory footprint (it currently currently implemented with Cython).
  • structclass factory has argument gc now. If gc=False (by default) support of cyclic garbage collection will switched off for instances of the created class.
  • Add function join(C1, C2) in order to join two structclass-based classes C1 and C2.
  • Add sequenceproxy function for creation of immutable and hashable proxy object from class instances, which implement access by index (it currently currently implemented with Cython).
  • Add support for access to recordclass object attributes by idiom: ob['attrname'] (Issue #5).
  • Add argument readonly to recordclass factory to produce immutable namedtuple. In contrast to collection.namedtuple it use same descriptors as for regular recordclasses for performance increasing.

0.7

  • Make mutabletuple objects creation faster. As a side effect: when number of fields >= 8 recordclass instance creation time is not biger than creation time of instaces of dataclasses with __slots__.
  • Recordclass factory function now create new recordclass classes in the same way as namedtuple in 3.7 (there is no compilation of generated python source of class).

0.6

  • Add support for default values in recordclass factory function in correspondence to same addition to namedtuple in python 3.7.

0.5

  • Change version to 0.5

0.4.4

  • Add support for default values in RecordClass (patches from Pedro von Hertwig)
  • Add tests for RecorClass (adopted from python tests for NamedTuple)

0.4.3

  • Add support for typing for python 3.6 (patches from Vladimir Bolshakov).
  • Resolve memory leak issue.

0.4.2

  • Fix memory leak in property getter/setter

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

recordclass-0.15.1.tar.gz (473.2 kB view details)

Uploaded Source

Built Distributions

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

recordclass-0.15.1-cp39-cp39-win_amd64.whl (118.2 kB view details)

Uploaded CPython 3.9Windows x86-64

recordclass-0.15.1-cp39-cp39-win32.whl (104.3 kB view details)

Uploaded CPython 3.9Windows x86

recordclass-0.15.1-cp38-cp38-win_amd64.whl (118.3 kB view details)

Uploaded CPython 3.8Windows x86-64

recordclass-0.15.1-cp38-cp38-win32.whl (105.0 kB view details)

Uploaded CPython 3.8Windows x86

recordclass-0.15.1-cp37-cp37m-win_amd64.whl (116.3 kB view details)

Uploaded CPython 3.7mWindows x86-64

recordclass-0.15.1-cp37-cp37m-win32.whl (103.9 kB view details)

Uploaded CPython 3.7mWindows x86

recordclass-0.15.1-cp36-cp36m-win_amd64.whl (116.4 kB view details)

Uploaded CPython 3.6mWindows x86-64

recordclass-0.15.1-cp36-cp36m-win32.whl (103.8 kB view details)

Uploaded CPython 3.6mWindows x86

File details

Details for the file recordclass-0.15.1.tar.gz.

File metadata

  • Download URL: recordclass-0.15.1.tar.gz
  • Upload date:
  • Size: 473.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1.tar.gz
Algorithm Hash digest
SHA256 168dca4613bf1a837b2013ea65d682f28b6290b13cbc5bed14225835a6143fdd
MD5 3631722071c8e89408f14bd923f0fe92
BLAKE2b-256 e00d4ac0472bbbad49cbc14e0f7bc9461e9d4aaaf9655365e8f46f9ebdb7bdcb

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 118.2 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 2839b81b52860306bba2fdb249b71d023d2fb2ffc9e70d7e8077b51625370d25
MD5 bd022e3474dc9ee5cd312713f41b27fb
BLAKE2b-256 f99319f76665f72cc6b6009d7b684b1e7da07a4f24da3a469df0da20d4a9aac3

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp39-cp39-win32.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp39-cp39-win32.whl
  • Upload date:
  • Size: 104.3 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 e3ad7fd4d38f895400fb36598289f792b5c9a976e05fcafcafaab0ed4c178d23
MD5 a8fcd840f9ecefe14c38c9da9a19ab74
BLAKE2b-256 46901df9f6d44f4393892e8e2451cae962da029c7ffaa510e623f848b1d3f595

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 118.3 kB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 a879f197aad2d60c1552c0895933057948fa85cd798933d1a9cef8755333f8a2
MD5 58325ead262c4bd9a06ee24e29e8bdc5
BLAKE2b-256 88ac7a197029a97002f4ec8035eb6ef9ba3d24e67c8537c3455b9a86b5d2eebf

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp38-cp38-win32.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp38-cp38-win32.whl
  • Upload date:
  • Size: 105.0 kB
  • Tags: CPython 3.8, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 568c172511f070d5443871762ddf2619ce2d0713650d68dce9df5d0a66357d86
MD5 0e09e1c38f018a509b1311e5b3097711
BLAKE2b-256 94574fb45dd9469f8ae98496a406312228dfb51b8934581d9e7b18e305ba7e94

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 116.3 kB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 8f6dec05a3167931ef4690e51551175a86d4726fc9efb417a8140e503aeb98fe
MD5 270d4e84ef00894e38ceb53d6356b756
BLAKE2b-256 83983b48479b4b92de140da91f0e90f3bd39a35b9b75e66216a5c410c1adc5b7

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp37-cp37m-win32.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 103.9 kB
  • Tags: CPython 3.7m, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 4abe2ed7a91c2229a3d5225f52eff5a4523f036a956f60e24eaf108972c910e7
MD5 82f8999f508cc9c8f095358777d1e9b8
BLAKE2b-256 8f61e9cac1e84ec299b307963b1c9fb44e2742f95a5b17df0c1ab1833ca20486

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp36-cp36m-win_amd64.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp36-cp36m-win_amd64.whl
  • Upload date:
  • Size: 116.4 kB
  • Tags: CPython 3.6m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 dee057663ba0793823b8ed9607568dc32e89983e2fac5db107ea07f7b541aab4
MD5 e804f780d49501c89fd1a4bc89af36db
BLAKE2b-256 ea9d08fe4088ea62f6b70569a824099625781eb0889925c8e1b8b079ea853342

See more details on using hashes here.

File details

Details for the file recordclass-0.15.1-cp36-cp36m-win32.whl.

File metadata

  • Download URL: recordclass-0.15.1-cp36-cp36m-win32.whl
  • Upload date:
  • Size: 103.8 kB
  • Tags: CPython 3.6m, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2

File hashes

Hashes for recordclass-0.15.1-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 f9f69f37c215d8c7d503b70bcd92637974e978731cddb5d739c5aa7e6e71f676
MD5 1866bd9e0882b236e33199b0da944d92
BLAKE2b-256 c3072b3b8b5a36107c6fe85912512f8c210dddd796bbabef7816cdaf2fa673d2

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