{ "info": { "author": "Covera Health", "author_email": "engineering@coverahealth.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Libraries" ], "description": "\nData Spec\n=========\n\n.. image:: https://img.shields.io/pypi/v/dataspec.svg?style=flat-square\n :target: https://pypi.org/project/dataspec/\n :alt: Package (on PyPI)\n\n.. image:: https://img.shields.io/pypi/pyversions/dataspec.svg?style=flat-square\n :target: https://pypi.org/project/dataspec/\n :alt: Supported Python Versions\n\n.. image:: https://img.shields.io/pypi/implementation/dataspec.svg?style=flat-square\n :target: https://pypi.org/project/dataspec/\n :alt: Supported Python Implementations\n\n.. image:: https://img.shields.io/circleci/project/github/coverahealth/dataspec/master.svg?style=flat-square\n :target: https://circleci.com/gh/coverahealth/dataspec\n :alt: Build Status (on CircleCI)\n\n.. image:: https://img.shields.io/readthedocs/dataspec?style=flat-square\n :target: https://dataspec.readthedocs.io/\n :alt: Documentation (on ReadTheDocs)\n\n.. image:: https://img.shields.io/github/license/coverahealth/dataspec.svg?style=flat-square\n :target: https://github.com/coverahealth/dataspec/blob/master/LICENSE\n :alt: MIT License\n\nDataspec is a data specification and normalization toolkit written in pure Python.\nWith Dataspec, you can create Specs to validate and normalize data of almost any\nshape. Dataspec is inspired by Clojure's `spec `_\nlibrary.\n\nWhat are Specs?\n---------------\n\nSpecs are declarative data specifications written in pure Python code. Specs can be\ncreated using the generic Spec constructor function ``s``. Specs provide two useful and\nrelated functions. The first is to evaluate whether an arbitrary data structure\nsatisfies the specification. The second function is to conform (or normalize) valid\ndata structures into a canonical format.\n\nThe simplest Specs are based on common predicate functions, such as\n``lambda x: isinstance(x, str)`` which asks \"Is the object x an instance of ``str``?\".\nFortunately, Specs are not limited to being created from single predicates. Specs can\nalso be created from groups of predicates, composed in a variety of useful ways, and\neven defined for complex data structures. Because Specs are ultimately backed by\npure Python code, any question that you can answer about your data in code can be\nencoded in a Spec.\n\nFeatures\n--------\n\n* Simple API using primarily native Python types and data structures\n\n* Stateless, immutable Spec objects are designed to be created once, reused, and composed\n\n* Rich error objects point to the exact location of the error in the input value\n\n* Builtin factories for many common validations\n\nInstallation\n------------\n\nDataspec is developed on `GitHub `_ and hosted\non `PyPI `_. You can fetch Dataspec using ``pip``:\n\n.. code-block:: bash\n\n pip install dataspec\n\nTo enable support for phone number specs or arbitrary date strings, you can choose the\nextras when you install:\n\n.. code-block:: bash\n\n pip install dataspec[dates]\n pip install dataspec[phonenumbers]\n\nGetting Started\n---------------\n\nTo begin using the ``dataspec`` library, you can simply import the ``s`` object:\n\n.. code-block:: python\n\n from dataspec import s\n\n``s`` is a generic constructor for creating new Specs. Many useful Specs can be\ncomposed from basic Python objects like types, functions, and data structures. The\n\"Hello, world!\" equivalent for creating new Specs might be a simple Spec that validates\nthat an input is a string (a Python ``str`` ). We can do this by simply passing the\nPython ``str`` type directly to ``s``. When ``s`` receives an instance of a ``type``\nobject, it assumes you want to create a Spec that validates input values are of that\ntype:\n\n.. code-block:: python\n\n spec = s(str)\n spec.is_valid(\"a string\") # True\n spec.is_valid(3) # False\n\nOften you want to assert more than one condition on an input value. After all, it's\nfairly trivial to assert type checks on a value. In fact, this may even be done by\na deserialization library on your behalf. Perhaps you're interested in checking that\nyour input is a string and that it contains only numbers and hyphens. ``dataspec`` lets\nyou define Specs with boolean logic, which can be useful for asserting multiple\nconditions on your input:\n\n.. code-block:: python\n\n spec = s.all(str, lambda s: all(c.isdecimal() or c == \"-\" for c in s))\n spec.is_valid(\"212-867-5309\") # True\n spec.is_valid(\"Philip Jennings\") # False\n\nComposition is at the heart of ``dataspec`` 's design. In the previous example, we\nlearned a few useful things. First, ``s`` is actually a callable object with static\nmethods which help produce other sorts of Specs. Second, we can see that when we\npass objects understood to ``s`` into various Spec constructors, they are automatically\ncoerced into the appropriate Spec type. Here, we passed a ``type``, which we used\npreviously. We also passed in a function of one argument returning a boolean; in\n``dataspec``, these are called predicates and they are turned into Specs which validate\ninput values if the function returns ``True`` and fail otherwise. Finally, we learned\nthat ``s.all`` can be used to produce ``and`` -type boolean logic between different\nSpecs. (You can produce ``or`` Specs using ``s.any``).\n\nIn the previous example, we used the ``and`` logic to check for our conditions to show\nvarious different features of ``dataspec``. However, in real code you'd likely take\nadvantage of ``dataspec`` 's builtin ``s.str`` factory, which can assert several useful\nproperties of strings (in addition to the basic ``isinstance`` check). In the case\nabove, perhaps we really wanted to check for a US ZIP code (with the trailing 4 digits).\nWe can perform that check using a simple regex string validator:\n\n.. code-block:: python\n\n spec = s.str(\"us_zip_plus_4\", regex=r\"\\d{5}\\-\\d{4}\")\n spec.is_valid(\"10001-3093\") # True\n spec.is_valid(\"10001\") # False\n spec.is_valid(\"N0L 1E0\") # False\n\nScalar Specs like the one above are trivially different from the same checks you could\nwrite in raw Python. The real power of ``dataspec`` comes from its ability to compose\nSpecs for larger, nested data structures. Suppose you were accepting a physician\nprofile object via a JSON API and you wanted to validate that the physician licenses\nwere valid in all of the states you operate in:\n\n.. code-block:: python\n\n operating_states = s(\"operating_states\", {\"CA\", \"GA\", \"NY\"})\n license_states = s(\"license_states\", [operating_states, {\"kind\": list}])\n license_states.is_valid([\"CA\", \"NY\"]) # True\n license_states.is_valid([\"SD\", \"GA\"]) # False, you do not operate in South Dakota\n license_states.is_valid({\"CA\"}) # False, as the input collection is a set\n\nIn the previous example, we learned a bit more about ``dataspec``. First, we can see\nthat Spec objects are designed to be reused. We declared ``operating_states`` as a\nseparate Spec from ``license_states`` with the intent that we could use it as a\ncomponent of other Specs. Specs are immutable and stateless, so they can be reused in\nother Specs without issue. Next, we can see that we're expecting a collection, indicated\nby the Python ``list`` wrapping ``operating_states`` in the ``license_states`` Spec.\nIn particular, we are expecting exactly a ``list``, not a ``set`` or ``tuple``.\nThird, we are expecting a limited set of enumerated values, indicated by\n``operating_states`` being a ``set``. Values not in the set are rejected. ``dataspec``\nalso supports using Python's ``Enum`` objects for defining enumerated types.\n\nWe did declare two separate Specs and pass both to ``s`` directly. However, we could\nhave declared the entire Spec inline and ``s`` would have converted each child value\ninto a Spec automatically: ``s([{\"CA\", \"GA\", \"NY\"}, {\"kind\": list}])`` .\n\nBuilding on the previous example, let's suppose we want to validate a simplified\nversion of that physician profile object. Spec is great for validating data at your\napplication boundaries. You can pass it your deserialized input values and it will\nhelp you ensure that you're receiving data in the shape your internal services\nexpect:\n\n.. code-block:: python\n\n spec = s(\n \"user-profile\",\n {\n \"id\": s.str(\"id\", format_=\"uuid\"),\n \"first_name\": s.str(\"first_name\"),\n \"last_name\": s.str(\"last_name\"),\n \"date_of_birth\": s.str(\"date_of_birth\", format_=\"iso-date\"),\n s.opt(\"gender\"): s(\"gender\", {\"M\", \"F\"}),\n \"license_states\": license_states, # using the previously defined Spec\n }\n )\n spec.is_valid( # True\n {\n \"id\": \"e1bc9fb2-a4d3-4683-bfef-3acc61b0edcc\",\n \"first_name\": \"Carl\",\n \"last_name\": \"Sagan\",\n \"date_of_birth\": \"1996-12-20\",\n \"license_states\": [\"CA\"],\n }\n )\n spec.is_valid( # False; the optional \"gender\" key included an invalid value\n {\n \"id\": \"e1bc9fb2-a4d3-4683-bfef-3acc61b0edcc\",\n \"first_name\": \"Carl\",\n \"last_name\": \"Sagan\",\n \"date_of_birth\": \"1996-12-20\",\n \"gender\": \"O\",\n \"license_states\": [\"CA\"],\n }\n )\n spec.is_valid( # True; note that extra keys _are ignored_\n {\n \"id\": \"958e2f55-5fdf-4b84-a522-a0765299ba4b\",\n \"first_name\": \"Marie\",\n \"last_name\": \"Curie\",\n \"date_of_birth\": \"1867-11-07\",\n \"gender\": \"F\",\n \"license_states\": [\"NY\", \"GA\"],\n \"occupation\": \"Chemist\",\n }\n )\n spec.is_valid( # False; the \"license_states\" includes the invalid value \"TX\"\n {\n \"id\": \"958e2f55-5fdf-4b84-a522-a0765299ba4b\",\n \"first_name\": \"Marie\",\n \"last_name\": \"Curie\",\n \"date_of_birth\": \"1867-11-07\",\n \"license_states\": [\"TX\"],\n }\n )\n\n``dataspec`` includes plenty of additional functionality which is not discussed above.\nRead more at `Read the Docs `_.\n\nWhy not X?\n----------\n\nPython's ecosystem features a rich collection of data validation and normalization\ntools, so a new entrant in the space naturally begs the question \"why didn't you just\nuse X instead?\". Before creating Dataspec, we surveyed a wide variety of different\ntools and had even used one or two in our production service. All of these tools are\ngenerally successful at validating data, but each had some issue that caused us to\npass.\n\n* Many of the libraries in this space primarily help validate data, but do not always\n help you normalize or conform that data after it has been validated. Dataspec\n provides validation and conformation out of the box.\n\n* Libraries which do feature validation and normalization often complect these two\n steps. Dataspec validation is a discrete step that occurs before conformation, so\n it is easy to reason about failures in validation.\n\n* Some of the libraries we tried were stateful or leaned too heavily on mutability.\n We tend to prefer immutable and stateless objects where mutability and state is not\n required. Specs in Dataspec are completely stateless and conformation always produces\n a new value. This is certainly more costly than mutating inputs, but mutating code\n is harder to reason about and is a major source of bugs, so we prefer to avoid it.\n\n* Many libraries we surveyed focused on defining validations from the top-down, rather\n than encouraging composition. Specs in Dataspec are designed to be created once,\n reused, and composed, rather than requiring a separate definition for each usage.\n\nLicense\n-------\n\nMIT License\n\n\n", "description_content_type": "text/x-rst", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/coverahealth/dataspec", "keywords": "", "license": "MIT License", "maintainer": "", "maintainer_email": "", "name": "dataspec", "package_url": "https://pypi.org/project/dataspec/", "platform": "", "project_url": "https://pypi.org/project/dataspec/", "project_urls": { "Homepage": "http://github.com/coverahealth/dataspec" }, "release_url": "https://pypi.org/project/dataspec/0.3.2/", "requires_dist": [ "attrs", "python-dateutil ; extra == 'dates'", "phonenumbers ; extra == 'phonenumbers'" ], "requires_python": ">=3.6.0", "summary": "Data specification and normalization toolkit", "version": "0.3.2", "yanked": false, "yanked_reason": null }, "last_serial": 7216183, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "aed289706ca5b7ce827cc7b2b62fea0f", "sha256": "897c2974ca2146690160ee51bff7f08c57630fec4820e9ead0c295889fe33705" }, "downloads": -1, "filename": "dataspec-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "aed289706ca5b7ce827cc7b2b62fea0f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 16850, "upload_time": "2019-10-21T20:56:59", "upload_time_iso_8601": "2019-10-21T20:56:59.154221Z", "url": "https://files.pythonhosted.org/packages/52/88/96787535011b8375ecdf5f00e231bdaf01b4407ba17abdd5890f8901300f/dataspec-0.1.0-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "68cd874ec64c7a743bd404f88c839891", "sha256": "83c1535e4f720928b068fe9a5446a53a508f54ab8a54d517dfb9a2e97e0e9368" }, "downloads": -1, "filename": "dataspec-0.1.0.tar.gz", "has_sig": false, "md5_digest": "68cd874ec64c7a743bd404f88c839891", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 19615, "upload_time": "2019-10-21T20:57:02", "upload_time_iso_8601": "2019-10-21T20:57:02.326783Z", "url": "https://files.pythonhosted.org/packages/25/36/818634897a44ddcc4696391bb1441615bbe8c684bbcffb70d938a87b56b6/dataspec-0.1.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.1.post0": [ { "comment_text": "", "digests": { "md5": "ace3fa2826154d0d36d14a106e3de329", "sha256": "4e2994a471d9cd2f9f081a9c95e09928430adec36318b90857f0c3f611b1dbde" }, "downloads": -1, "filename": "dataspec-0.1.post0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ace3fa2826154d0d36d14a106e3de329", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 17086, "upload_time": "2019-10-21T21:04:17", "upload_time_iso_8601": "2019-10-21T21:04:17.966099Z", "url": "https://files.pythonhosted.org/packages/f0/95/bbcd9aecaa0f20762c1c8045f65d488c6aa39d9a3bf40cee92affbe9a226/dataspec-0.1.post0-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "e7f4ecbec6578294cb6c374bc72b844a", "sha256": "88cd61d51d39b744082603af6407c5de434eebc51eff15f414894b27f2b4ea24" }, "downloads": -1, "filename": "dataspec-0.1.post0.tar.gz", "has_sig": false, "md5_digest": "e7f4ecbec6578294cb6c374bc72b844a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 19810, "upload_time": "2019-10-21T21:04:19", "upload_time_iso_8601": "2019-10-21T21:04:19.776681Z", "url": "https://files.pythonhosted.org/packages/27/bf/f1e759414953a11e59d9f1adaa1fe7a2ea7d5ec249277b32976cd8928657/dataspec-0.1.post0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "4aa9cb746f4aace7215291200803a64b", "sha256": "e5c7391a2aa5996ea39bbefb4c510011accadd5ac4a6c2e5f5fe434870c17aec" }, "downloads": -1, "filename": "dataspec-0.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4aa9cb746f4aace7215291200803a64b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 49547, "upload_time": "2019-10-28T17:12:50", "upload_time_iso_8601": "2019-10-28T17:12:50.242545Z", "url": "https://files.pythonhosted.org/packages/46/a7/f9bb85234008eeb827c66f2f4dbbd300cfecefdc7d040088aa82f7f14aee/dataspec-0.2.0-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "85bdc19d723b0f214aa84618833e8154", "sha256": "27002d482c25e077ba6c34e4025ecd679c20c06ddc450403212c593281b53ddb" }, "downloads": -1, "filename": "dataspec-0.2.0.tar.gz", "has_sig": false, "md5_digest": "85bdc19d723b0f214aa84618833e8154", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 49312, "upload_time": "2019-10-28T17:12:51", "upload_time_iso_8601": "2019-10-28T17:12:51.754777Z", "url": "https://files.pythonhosted.org/packages/bf/2a/81bc52ff269a0d48a4a68981ca2a9df38bb341ad50645762a7bc3b46d2bc/dataspec-0.2.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "c87902cdffadb91376042d55008d4928", "sha256": "9e49778b9e0e2f38c9890c4331f7a6d431223f5766e51cc090db05b0404c1e94" }, "downloads": -1, "filename": "dataspec-0.2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c87902cdffadb91376042d55008d4928", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 114835, "upload_time": "2019-11-15T14:12:05", "upload_time_iso_8601": "2019-11-15T14:12:05.987248Z", "url": "https://files.pythonhosted.org/packages/b7/bd/38de386d938918e347060bacb5d4c9107117a72de2d3df71e52a4aadf0b7/dataspec-0.2.1-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "aeb70a3b8ce2c2071ee7399c75a02417", "sha256": "0730fc1bce4bdc3cb234ef9b6c6ae03d369728ebb34e5e0faddde1b5951fea14" }, "downloads": -1, "filename": "dataspec-0.2.1.tar.gz", "has_sig": false, "md5_digest": "aeb70a3b8ce2c2071ee7399c75a02417", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 95792, "upload_time": "2019-11-15T14:12:07", "upload_time_iso_8601": "2019-11-15T14:12:07.802120Z", "url": "https://files.pythonhosted.org/packages/74/94/8c212ae0d18152374a9d44456e8bc4f086bc91fa976b51786ed53dd4084d/dataspec-0.2.1.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "fe70f0464dc18cdc1f7d80e0b1c4be9e", "sha256": "c616c131457e8fad2057f390e45d0432447bcfbccd5fdeea914e3884d31babf2" }, "downloads": -1, "filename": "dataspec-0.2.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "fe70f0464dc18cdc1f7d80e0b1c4be9e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 115706, "upload_time": "2019-11-27T20:48:34", "upload_time_iso_8601": "2019-11-27T20:48:34.019981Z", "url": "https://files.pythonhosted.org/packages/89/df/626f15e5d6c6b89b0ddddac3c8a2d6dc2bd6c8464f769d76a179b9d4854b/dataspec-0.2.2-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "a1666276772e495dab9813f069e244cb", "sha256": "8ccf4bdce979d9892b7e1a2243e16ee9eba7b5d7ed1dd40beb5c04791b628f97" }, "downloads": -1, "filename": "dataspec-0.2.2.tar.gz", "has_sig": false, "md5_digest": "a1666276772e495dab9813f069e244cb", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 96923, "upload_time": "2019-11-27T20:48:35", "upload_time_iso_8601": "2019-11-27T20:48:35.542396Z", "url": "https://files.pythonhosted.org/packages/36/a7/c2a81e10b3ecac033b831848689678695e7f6361b1f207bf875cedbb3817/dataspec-0.2.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.3": [ { "comment_text": "", "digests": { "md5": "f2aa05252715d91abf79fccbdfa0c941", "sha256": "3b084b8d04ff7364531c442244f385a00e6cde89e698b8d301d2a54faf88677b" }, "downloads": -1, "filename": "dataspec-0.2.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f2aa05252715d91abf79fccbdfa0c941", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 115824, "upload_time": "2019-11-27T21:56:36", "upload_time_iso_8601": "2019-11-27T21:56:36.302849Z", "url": "https://files.pythonhosted.org/packages/65/94/e389bc83e1e57dd433556bc95028137581c69c2642f5053f53ff91ad1d80/dataspec-0.2.3-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "f08086fca0796cc1230701d99d25d8b4", "sha256": "97660bbfac7823cf08896c7dac1dc6c6aacbf18329d5f0ab514cac7be0eb1d85" }, "downloads": -1, "filename": "dataspec-0.2.3.tar.gz", "has_sig": false, "md5_digest": "f08086fca0796cc1230701d99d25d8b4", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 97023, "upload_time": "2019-11-27T21:56:37", "upload_time_iso_8601": "2019-11-27T21:56:37.878904Z", "url": "https://files.pythonhosted.org/packages/9e/ee/efb573020a93ef1d8773cc9ec95ce7f63a16ee03abecd63f26fd1528054d/dataspec-0.2.3.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.4": [ { "comment_text": "", "digests": { "md5": "687026a2a0262b34c01065d3d8b50c9f", "sha256": "02d0b779116baf98d6e084d89e343c9ed87c3b45b2144071e4567980ef9812d7" }, "downloads": -1, "filename": "dataspec-0.2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "687026a2a0262b34c01065d3d8b50c9f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 116126, "upload_time": "2019-12-19T20:55:35", "upload_time_iso_8601": "2019-12-19T20:55:35.072644Z", "url": "https://files.pythonhosted.org/packages/67/8b/8bd3f2aa4a0c7a277179ad1558df595b5ef25a56ccf41b82b17e8968ebf2/dataspec-0.2.4-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "76b96d7967946da05a4d15e963cfbf69", "sha256": "cd71a862007c45636efff09503dfd437ea087fc52d7f6f49668f8b64c2960d99" }, "downloads": -1, "filename": "dataspec-0.2.4.tar.gz", "has_sig": false, "md5_digest": "76b96d7967946da05a4d15e963cfbf69", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 97301, "upload_time": "2019-12-19T20:55:36", "upload_time_iso_8601": "2019-12-19T20:55:36.993433Z", "url": "https://files.pythonhosted.org/packages/d3/e7/275069dd584fa7dd6db0e450558ad2812667670fe8844176fdac615888d6/dataspec-0.2.4.tar.gz", "yanked": false, "yanked_reason": null } ], "0.2.5": [ { "comment_text": "", "digests": { "md5": "a599f8671477d6d57c340ae3ef051be4", "sha256": "33e2d1efba0ed06dc8a338864346f54bea81dcd147b0847d17a3627f311abe73" }, "downloads": -1, "filename": "dataspec-0.2.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a599f8671477d6d57c340ae3ef051be4", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 59940, "upload_time": "2020-04-10T19:54:21", "upload_time_iso_8601": "2020-04-10T19:54:21.147235Z", "url": "https://files.pythonhosted.org/packages/f3/32/07a961747dd1373b3c7aa3085bb5ac13d96a683169401f6cd14dddcf21e9/dataspec-0.2.5-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "710da877af26013fdf95937af5adfead", "sha256": "7109a39df67425a939bbe0586190439fb0a2d960052b2966d74d1f86f4122a5d" }, "downloads": -1, "filename": "dataspec-0.2.5.tar.gz", "has_sig": false, "md5_digest": "710da877af26013fdf95937af5adfead", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 59985, "upload_time": "2020-04-10T19:54:25", "upload_time_iso_8601": "2020-04-10T19:54:25.797910Z", "url": "https://files.pythonhosted.org/packages/a3/f7/0a524579a1a97155b3f21f2ab97607d8a9577bbcc61194ff52ba7577b5fa/dataspec-0.2.5.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "40633f8e0fd70c59d0d13c8e69486961", "sha256": "b1694af98bf1c54ae44108dac10cf762e5c8d297c0d99cdae85f5cfee914b9d1" }, "downloads": -1, "filename": "dataspec-0.3.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "40633f8e0fd70c59d0d13c8e69486961", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 67326, "upload_time": "2020-05-07T14:33:12", "upload_time_iso_8601": "2020-05-07T14:33:12.129815Z", "url": "https://files.pythonhosted.org/packages/81/05/b97474e0e30fc1c0b1b6cf39212ca5615cf21633ac28a5983778d6ccaedb/dataspec-0.3.0-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "cfcbf30a8233bffd19ed67c93fba509a", "sha256": "b87e5b52689b8a08237a781b059927ad1f3577114cee1eb9fa04740100fae7c7" }, "downloads": -1, "filename": "dataspec-0.3.0.tar.gz", "has_sig": false, "md5_digest": "cfcbf30a8233bffd19ed67c93fba509a", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 68393, "upload_time": "2020-05-07T14:33:13", "upload_time_iso_8601": "2020-05-07T14:33:13.427522Z", "url": "https://files.pythonhosted.org/packages/07/8c/a5290d61674571544ce25151d57ede5b722c36247ed894e6d8bfe23e0a81/dataspec-0.3.0.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "7f0db8f33893aa1fb5df6c3d124dd419", "sha256": "914a7d209f7182bd5cc7bf40c6760e75d6b591da117876e2608443fa2ad159c3" }, "downloads": -1, "filename": "dataspec-0.3.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7f0db8f33893aa1fb5df6c3d124dd419", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 71482, "upload_time": "2020-05-07T16:32:09", "upload_time_iso_8601": "2020-05-07T16:32:09.840059Z", "url": "https://files.pythonhosted.org/packages/6a/3b/1e6670e9fe3a38e16a7974d04826e7c0d2cd4f2e3cadf409a970f90b75b0/dataspec-0.3.1-py2.py3-none-any.whl", "yanked": true, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "c08b9e984095d6f5179f9a5445aff63f", "sha256": "9be39f67ab6da46b92e2ddf16218897d201a78bbc78a22729386c3bc2a4a9b2c" }, "downloads": -1, "filename": "dataspec-0.3.1.tar.gz", "has_sig": false, "md5_digest": "c08b9e984095d6f5179f9a5445aff63f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 70369, "upload_time": "2020-05-07T16:32:10", "upload_time_iso_8601": "2020-05-07T16:32:10.942785Z", "url": "https://files.pythonhosted.org/packages/20/ed/f78516337d3ce1b2713391954287d0fde8ac3c309c644f72440ab9adc28f/dataspec-0.3.1.tar.gz", "yanked": true, "yanked_reason": null } ], "0.3.2": [ { "comment_text": "", "digests": { "md5": "b5ea01f31d596cdc68ecf66e61b45deb", "sha256": "653b82d52df681a8264ea3f33235b2448d1cdb3d6b25386862b54c9ab3010f15" }, "downloads": -1, "filename": "dataspec-0.3.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b5ea01f31d596cdc68ecf66e61b45deb", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 71716, "upload_time": "2020-05-11T15:34:26", "upload_time_iso_8601": "2020-05-11T15:34:26.183596Z", "url": "https://files.pythonhosted.org/packages/fb/7a/2664c4aed9056b976bd59b92dab6e6f1bce4d77a12c831531f1409be0d57/dataspec-0.3.2-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "a618e024abf350b4a58c52450641ae65", "sha256": "af12c4cc109d9bb5da83c37c2ae2cdf44f8022779ee3b808b592cc17524d3424" }, "downloads": -1, "filename": "dataspec-0.3.2.tar.gz", "has_sig": false, "md5_digest": "a618e024abf350b4a58c52450641ae65", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 70626, "upload_time": "2020-05-11T15:34:27", "upload_time_iso_8601": "2020-05-11T15:34:27.755315Z", "url": "https://files.pythonhosted.org/packages/7c/f7/0246a20601ac49858607e39f64ef799b2550ce6b6cbea7b0b01f91c6f65b/dataspec-0.3.2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.dev2": [ { "comment_text": "", "digests": { "md5": "7a5d092006f47a6a612a595441dcc938", "sha256": "f9adb3e6c1d9685124137ad19290733a6953f6b76ab3c9fdc2012835042ca17e" }, "downloads": -1, "filename": "dataspec-0.3.dev2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7a5d092006f47a6a612a595441dcc938", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 71758, "upload_time": "2020-05-11T14:57:22", "upload_time_iso_8601": "2020-05-11T14:57:22.182591Z", "url": "https://files.pythonhosted.org/packages/35/cc/e64104a05790635102a164826de56c843efca2d791e469df06d0010616b4/dataspec-0.3.dev2-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "a889de7449dd9096b38c82a40c988100", "sha256": "b25537219fa4c54af4a4a1b6e5bd8fb8f9d919c54fd6bb10de87faa36cd6b1fd" }, "downloads": -1, "filename": "dataspec-0.3.dev2.tar.gz", "has_sig": false, "md5_digest": "a889de7449dd9096b38c82a40c988100", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 70628, "upload_time": "2020-05-11T14:57:23", "upload_time_iso_8601": "2020-05-11T14:57:23.454358Z", "url": "https://files.pythonhosted.org/packages/8d/04/47b15b82de0ffa04c7c4d2c600108c4f3f6b7266cb25f23258ccaf9d400e/dataspec-0.3.dev2.tar.gz", "yanked": false, "yanked_reason": null } ], "0.3.post1": [ { "comment_text": "", "digests": { "md5": "52e771a39def8ff9807bc3a2dc9624d9", "sha256": "845b236a98bacb67001b4819b8ae2a72be26fb6bd44e3efb5d28791c441c5620" }, "downloads": -1, "filename": "dataspec-0.3.post1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "52e771a39def8ff9807bc3a2dc9624d9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 71537, "upload_time": "2020-05-07T16:39:54", "upload_time_iso_8601": "2020-05-07T16:39:54.679243Z", "url": "https://files.pythonhosted.org/packages/fb/f4/22aae82306e595aad5926a5a70a9a0829d5768264852094a37e08e85b77b/dataspec-0.3.post1-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "5ffa22986cd4ea61ea21038961851ebb", "sha256": "0680b542c49a7d0e423c81d44776e06aa975410e63ef6525afb7f0517bd85051" }, "downloads": -1, "filename": "dataspec-0.3.post1.tar.gz", "has_sig": false, "md5_digest": "5ffa22986cd4ea61ea21038961851ebb", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 70388, "upload_time": "2020-05-07T16:39:56", "upload_time_iso_8601": "2020-05-07T16:39:56.275494Z", "url": "https://files.pythonhosted.org/packages/3c/16/73941ed604d9d7433907f1bf3378f207cd927d2ec9940aacc3c37d214826/dataspec-0.3.post1.tar.gz", "yanked": false, "yanked_reason": null } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "b5ea01f31d596cdc68ecf66e61b45deb", "sha256": "653b82d52df681a8264ea3f33235b2448d1cdb3d6b25386862b54c9ab3010f15" }, "downloads": -1, "filename": "dataspec-0.3.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b5ea01f31d596cdc68ecf66e61b45deb", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 71716, "upload_time": "2020-05-11T15:34:26", "upload_time_iso_8601": "2020-05-11T15:34:26.183596Z", "url": "https://files.pythonhosted.org/packages/fb/7a/2664c4aed9056b976bd59b92dab6e6f1bce4d77a12c831531f1409be0d57/dataspec-0.3.2-py2.py3-none-any.whl", "yanked": false, "yanked_reason": null }, { "comment_text": "", "digests": { "md5": "a618e024abf350b4a58c52450641ae65", "sha256": "af12c4cc109d9bb5da83c37c2ae2cdf44f8022779ee3b808b592cc17524d3424" }, "downloads": -1, "filename": "dataspec-0.3.2.tar.gz", "has_sig": false, "md5_digest": "a618e024abf350b4a58c52450641ae65", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 70626, "upload_time": "2020-05-11T15:34:27", "upload_time_iso_8601": "2020-05-11T15:34:27.755315Z", "url": "https://files.pythonhosted.org/packages/7c/f7/0246a20601ac49858607e39f64ef799b2550ce6b6cbea7b0b01f91c6f65b/dataspec-0.3.2.tar.gz", "yanked": false, "yanked_reason": null } ], "vulnerabilities": [] }