===============================================================================
parse_type
===============================================================================
.. |badge.CI_status| image:: https://github.com/jenisys/parse_type/actions/workflows/test.yml/badge.svg
:target: https://github.com/jenisys/parse_type/actions/workflows/test.yml
:alt: CI Build Status
.. |badge.latest_version| image:: https://img.shields.io/pypi/v/parse_type.svg
:target: https://pypi.python.org/pypi/parse_type
:alt: Latest Version
.. |badge.downloads| image:: https://img.shields.io/pypi/dm/parse_type.svg
:target: https://pypi.python.org/pypi/parse_type
:alt: Downloads
.. |badge.license| image:: https://img.shields.io/pypi/l/parse_type.svg
:target: https://pypi.python.org/pypi/parse_type/
:alt: License
|badge.CI_status| |badge.latest_version| |badge.license| |badge.downloads|
`parse_type`_ extends the `parse`_ module (opposite of `string.format()`_)
with the following features:
* build type converters for common use cases (enum/mapping, choice)
* build a type converter with a cardinality constraint (0..1, 0..*, 1..*)
from the type converter with cardinality=1.
* compose a type converter from other type converters
* an extended parser that supports the CardinalityField naming schema
and creates missing type variants (0..1, 0..*, 1..*) from the
primary type converter
.. _parse_type: http://pypi.python.org/pypi/parse_type
.. _parse: http://pypi.python.org/pypi/parse
.. _`string.format()`: http://docs.python.org/library/string.html#format-string-syntax
Definitions
-------------------------------------------------------------------------------
*type converter*
A type converter function that converts a textual representation
of a value type into instance of this value type.
In addition, a type converter function is often annotated with attributes
that allows the `parse`_ module to use it in a generic way.
A type converter is also called a *parse_type* (a definition used here).
*cardinality field*
A naming convention for related types that differ in cardinality.
A cardinality field is a type name suffix in the format of a field.
It allows parse format expression, ala::
"{person:Person}" #< Cardinality: 1 (one; the normal case)
"{person:Person?}" #< Cardinality: 0..1 (zero or one = optional)
"{persons:Person*}" #< Cardinality: 0..* (zero or more = many0)
"{persons:Person+}" #< Cardinality: 1..* (one or more = many)
This naming convention mimics the relationship descriptions in UML diagrams.
Basic Example
-------------------------------------------------------------------------------
Define an own type converter for numbers (integers):
.. code-block:: python
# -- USE CASE:
def parse_number(text):
return int(text)
parse_number.pattern = r"\d+" # -- REGULAR EXPRESSION pattern for type.
This is equivalent to:
.. code-block:: python
import parse
@parse.with_pattern(r"\d+")
def parse_number(text):
return int(text)
assert hasattr(parse_number, "pattern")
assert parse_number.pattern == r"\d+"
.. code-block:: python
# -- USE CASE: Use the type converter with the parse module.
schema = "Hello {number:Number}"
parser = parse.Parser(schema, dict(Number=parse_number))
result = parser.parse("Hello 42")
assert result is not None, "REQUIRE: text matches the schema."
assert result["number"] == 42
result = parser.parse("Hello XXX")
assert result is None, "MISMATCH: text does not match the schema."
.. hint::
The described functionality above is standard functionality
of the `parse`_ module. It serves as introduction for the remaining cases.
Cardinality
-------------------------------------------------------------------------------
Create an type converter for "ManyNumbers" (List, separated with commas)
with cardinality "1..* = 1+" (many) from the type converter for a "Number".
.. code-block:: python
# -- USE CASE: Create new type converter with a cardinality constraint.
# CARDINALITY: many := one or more (1..*)
from parse import Parser
from parse_type import TypeBuilder
parse_numbers = TypeBuilder.with_many(parse_number, listsep=",")
schema = "List: {numbers:ManyNumbers}"
parser = Parser(schema, dict(ManyNumbers=parse_numbers))
result = parser.parse("List: 1, 2, 3")
assert result["numbers"] == [1, 2, 3]
Create an type converter for an "OptionalNumbers" with cardinality "0..1 = ?"
(optional) from the type converter for a "Number".
.. code-block:: python
# -- USE CASE: Create new type converter with cardinality constraint.
# CARDINALITY: optional := zero or one (0..1)
from parse import Parser
from parse_type import TypeBuilder
parse_optional_number = TypeBuilder.with_optional(parse_number)
schema = "Optional: {number:OptionalNumber}"
parser = Parser(schema, dict(OptionalNumber=parse_optional_number))
result = parser.parse("Optional: 42")
assert result["number"] == 42
result = parser.parse("Optional: ")
assert result["number"] == None
Enumeration (Name-to-Value Mapping)
-------------------------------------------------------------------------------
Create an type converter for an "Enumeration" from the description of
the mapping as dictionary.
.. code-block:: python
# -- USE CASE: Create a type converter for an enumeration.
from parse import Parser
from parse_type import TypeBuilder
parse_enum_yesno = TypeBuilder.make_enum({"yes": True, "no": False})
parser = Parser("Answer: {answer:YesNo}", dict(YesNo=parse_enum_yesno))
result = parser.parse("Answer: yes")
assert result["answer"] == True
Create an type converter for an "Enumeration" from the description of
the mapping as an enumeration class (`Python 3.4 enum`_ or the `enum34`_
backport; see also: `PEP-0435`_).
.. code-block:: python
# -- USE CASE: Create a type converter for enum34 enumeration class.
# NOTE: Use Python 3.4 or enum34 backport.
from parse import Parser
from parse_type import TypeBuilder
from enum import Enum
class Color(Enum):
red = 1
green = 2
blue = 3
parse_enum_color = TypeBuilder.make_enum(Color)
parser = Parser("Select: {color:Color}", dict(Color=parse_enum_color))
result = parser.parse("Select: red")
assert result["color"] is Color.red
.. _`Python 3.4 enum`: http://docs.python.org/3.4/library/enum.html#module-enum
.. _enum34: http://pypi.python.org/pypi/enum34
.. _PEP-0435: http://www.python.org/dev/peps/pep-0435
Choice (Name Enumeration)
-------------------------------------------------------------------------------
A Choice data type allows to select one of several strings.
Create an type converter for an "Choice" list, a list of unique names
(as string).
.. code-block:: python
from parse import Parser
from parse_type import TypeBuilder
parse_choice_yesno = TypeBuilder.make_choice(["yes", "no"])
schema = "Answer: {answer:ChoiceYesNo}"
parser = Parser(schema, dict(ChoiceYesNo=parse_choice_yesno))
result = parser.parse("Answer: yes")
assert result["answer"] == "yes"
Variant (Type Alternatives)
-------------------------------------------------------------------------------
Sometimes you need a type converter that can accept text for multiple
type converter alternatives. This is normally called a "variant" (or: union).
Create an type converter for an "Variant" type that accepts:
* Numbers (positive numbers, as integer)
* Color enum values (by name)
.. code-block:: python
from parse import Parser, with_pattern
from parse_type import TypeBuilder
from enum import Enum
class Color(Enum):
red = 1
green = 2
blue = 3
@with_pattern(r"\d+")
def parse_number(text):
return int(text)
# -- MAKE VARIANT: Alternatives of different type converters.
parse_color = TypeBuilder.make_enum(Color)
parse_variant = TypeBuilder.make_variant([parse_number, parse_color])
schema = "Variant: {variant:Number_or_Color}"
parser = Parser(schema, dict(Number_or_Color=parse_variant))
# -- TEST VARIANT: With number, color and mismatch.
result = parser.parse("Variant: 42")
assert result["variant"] == 42
result = parser.parse("Variant: blue")
assert result["variant"] is Color.blue
result = parser.parse("Variant: __MISMATCH__")
assert not result
Extended Parser with CardinalityField support
-------------------------------------------------------------------------------
The parser extends the ``parse.Parser`` and adds the following functionality:
* supports the CardinalityField naming scheme
* automatically creates missing type variants for types with
a CardinalityField by using the primary type converter for cardinality=1
* extends the provide type converter dictionary with new type variants.
Example:
.. code-block:: python
# -- USE CASE: Parser with CardinalityField support.
# NOTE: Automatically adds missing type variants with CardinalityField part.
# USE: parse_number() type converter from above.
from parse_type.cfparse import Parser
# -- PREPARE: parser, adds missing type variant for cardinality 1..* (many)
type_dict = dict(Number=parse_number)
schema = "List: {numbers:Number+}"
parser = Parser(schema, type_dict)
assert "Number+" in type_dict, "Created missing type variant based on: Number"
# -- USE: parser.
result = parser.parse("List: 1, 2, 3")
assert result["numbers"] == [1, 2, 3]
Raw data
{
"_id": null,
"home_page": "https://github.com/jenisys/parse_type",
"name": "parse-type",
"maintainer": null,
"docs_url": null,
"requires_python": "!=3.0.*,!=3.1.*,>=2.7",
"maintainer_email": null,
"keywords": "parse, parsing",
"author": "Jens Engel",
"author_email": "Jens Engel <jenisys@noreply.github.com>",
"download_url": "https://files.pythonhosted.org/packages/17/e9/a3b2ae5f8a852542788ac1f1865dcea0c549cc40af243f42cabfa0acf24d/parse_type-0.6.4.tar.gz",
"platform": "any",
"description": "===============================================================================\nparse_type\n===============================================================================\n\n.. |badge.CI_status| image:: https://github.com/jenisys/parse_type/actions/workflows/test.yml/badge.svg\n :target: https://github.com/jenisys/parse_type/actions/workflows/test.yml\n :alt: CI Build Status\n\n.. |badge.latest_version| image:: https://img.shields.io/pypi/v/parse_type.svg\n :target: https://pypi.python.org/pypi/parse_type\n :alt: Latest Version\n\n.. |badge.downloads| image:: https://img.shields.io/pypi/dm/parse_type.svg\n :target: https://pypi.python.org/pypi/parse_type\n :alt: Downloads\n\n.. |badge.license| image:: https://img.shields.io/pypi/l/parse_type.svg\n :target: https://pypi.python.org/pypi/parse_type/\n :alt: License\n\n|badge.CI_status| |badge.latest_version| |badge.license| |badge.downloads|\n\n`parse_type`_ extends the `parse`_ module (opposite of `string.format()`_)\nwith the following features:\n\n* build type converters for common use cases (enum/mapping, choice)\n* build a type converter with a cardinality constraint (0..1, 0..*, 1..*)\n from the type converter with cardinality=1.\n* compose a type converter from other type converters\n* an extended parser that supports the CardinalityField naming schema\n and creates missing type variants (0..1, 0..*, 1..*) from the\n primary type converter\n\n.. _parse_type: http://pypi.python.org/pypi/parse_type\n.. _parse: http://pypi.python.org/pypi/parse\n.. _`string.format()`: http://docs.python.org/library/string.html#format-string-syntax\n\n\nDefinitions\n-------------------------------------------------------------------------------\n\n*type converter*\n A type converter function that converts a textual representation\n of a value type into instance of this value type.\n In addition, a type converter function is often annotated with attributes\n that allows the `parse`_ module to use it in a generic way.\n A type converter is also called a *parse_type* (a definition used here).\n\n*cardinality field*\n A naming convention for related types that differ in cardinality.\n A cardinality field is a type name suffix in the format of a field.\n It allows parse format expression, ala::\n\n \"{person:Person}\" #< Cardinality: 1 (one; the normal case)\n \"{person:Person?}\" #< Cardinality: 0..1 (zero or one = optional)\n \"{persons:Person*}\" #< Cardinality: 0..* (zero or more = many0)\n \"{persons:Person+}\" #< Cardinality: 1..* (one or more = many)\n\n This naming convention mimics the relationship descriptions in UML diagrams.\n\n\nBasic Example\n-------------------------------------------------------------------------------\n\nDefine an own type converter for numbers (integers):\n\n.. code-block:: python\n\n # -- USE CASE:\n def parse_number(text):\n return int(text)\n parse_number.pattern = r\"\\d+\" # -- REGULAR EXPRESSION pattern for type.\n\nThis is equivalent to:\n\n.. code-block:: python\n\n import parse\n\n @parse.with_pattern(r\"\\d+\")\n def parse_number(text):\n return int(text)\n assert hasattr(parse_number, \"pattern\")\n assert parse_number.pattern == r\"\\d+\"\n\n\n.. code-block:: python\n\n # -- USE CASE: Use the type converter with the parse module.\n schema = \"Hello {number:Number}\"\n parser = parse.Parser(schema, dict(Number=parse_number))\n result = parser.parse(\"Hello 42\")\n assert result is not None, \"REQUIRE: text matches the schema.\"\n assert result[\"number\"] == 42\n\n result = parser.parse(\"Hello XXX\")\n assert result is None, \"MISMATCH: text does not match the schema.\"\n\n.. hint::\n\n The described functionality above is standard functionality\n of the `parse`_ module. It serves as introduction for the remaining cases.\n\n\nCardinality\n-------------------------------------------------------------------------------\n\nCreate an type converter for \"ManyNumbers\" (List, separated with commas)\nwith cardinality \"1..* = 1+\" (many) from the type converter for a \"Number\".\n\n.. code-block:: python\n\n # -- USE CASE: Create new type converter with a cardinality constraint.\n # CARDINALITY: many := one or more (1..*)\n from parse import Parser\n from parse_type import TypeBuilder\n parse_numbers = TypeBuilder.with_many(parse_number, listsep=\",\")\n\n schema = \"List: {numbers:ManyNumbers}\"\n parser = Parser(schema, dict(ManyNumbers=parse_numbers))\n result = parser.parse(\"List: 1, 2, 3\")\n assert result[\"numbers\"] == [1, 2, 3]\n\n\nCreate an type converter for an \"OptionalNumbers\" with cardinality \"0..1 = ?\"\n(optional) from the type converter for a \"Number\".\n\n.. code-block:: python\n\n # -- USE CASE: Create new type converter with cardinality constraint.\n # CARDINALITY: optional := zero or one (0..1)\n from parse import Parser\n from parse_type import TypeBuilder\n\n parse_optional_number = TypeBuilder.with_optional(parse_number)\n schema = \"Optional: {number:OptionalNumber}\"\n parser = Parser(schema, dict(OptionalNumber=parse_optional_number))\n result = parser.parse(\"Optional: 42\")\n assert result[\"number\"] == 42\n result = parser.parse(\"Optional: \")\n assert result[\"number\"] == None\n\n\nEnumeration (Name-to-Value Mapping)\n-------------------------------------------------------------------------------\n\nCreate an type converter for an \"Enumeration\" from the description of\nthe mapping as dictionary.\n\n.. code-block:: python\n\n # -- USE CASE: Create a type converter for an enumeration.\n from parse import Parser\n from parse_type import TypeBuilder\n\n parse_enum_yesno = TypeBuilder.make_enum({\"yes\": True, \"no\": False})\n parser = Parser(\"Answer: {answer:YesNo}\", dict(YesNo=parse_enum_yesno))\n result = parser.parse(\"Answer: yes\")\n assert result[\"answer\"] == True\n\n\nCreate an type converter for an \"Enumeration\" from the description of\nthe mapping as an enumeration class (`Python 3.4 enum`_ or the `enum34`_\nbackport; see also: `PEP-0435`_).\n\n.. code-block:: python\n\n # -- USE CASE: Create a type converter for enum34 enumeration class.\n # NOTE: Use Python 3.4 or enum34 backport.\n from parse import Parser\n from parse_type import TypeBuilder\n from enum import Enum\n\n class Color(Enum):\n red = 1\n green = 2\n blue = 3\n\n parse_enum_color = TypeBuilder.make_enum(Color)\n parser = Parser(\"Select: {color:Color}\", dict(Color=parse_enum_color))\n result = parser.parse(\"Select: red\")\n assert result[\"color\"] is Color.red\n\n.. _`Python 3.4 enum`: http://docs.python.org/3.4/library/enum.html#module-enum\n.. _enum34: http://pypi.python.org/pypi/enum34\n.. _PEP-0435: http://www.python.org/dev/peps/pep-0435\n\n\nChoice (Name Enumeration)\n-------------------------------------------------------------------------------\n\nA Choice data type allows to select one of several strings.\n\nCreate an type converter for an \"Choice\" list, a list of unique names\n(as string).\n\n.. code-block:: python\n\n from parse import Parser\n from parse_type import TypeBuilder\n\n parse_choice_yesno = TypeBuilder.make_choice([\"yes\", \"no\"])\n schema = \"Answer: {answer:ChoiceYesNo}\"\n parser = Parser(schema, dict(ChoiceYesNo=parse_choice_yesno))\n result = parser.parse(\"Answer: yes\")\n assert result[\"answer\"] == \"yes\"\n\n\nVariant (Type Alternatives)\n-------------------------------------------------------------------------------\n\nSometimes you need a type converter that can accept text for multiple\ntype converter alternatives. This is normally called a \"variant\" (or: union).\n\nCreate an type converter for an \"Variant\" type that accepts:\n\n* Numbers (positive numbers, as integer)\n* Color enum values (by name)\n\n.. code-block:: python\n\n from parse import Parser, with_pattern\n from parse_type import TypeBuilder\n from enum import Enum\n\n class Color(Enum):\n red = 1\n green = 2\n blue = 3\n\n @with_pattern(r\"\\d+\")\n def parse_number(text):\n return int(text)\n\n # -- MAKE VARIANT: Alternatives of different type converters.\n parse_color = TypeBuilder.make_enum(Color)\n parse_variant = TypeBuilder.make_variant([parse_number, parse_color])\n schema = \"Variant: {variant:Number_or_Color}\"\n parser = Parser(schema, dict(Number_or_Color=parse_variant))\n\n # -- TEST VARIANT: With number, color and mismatch.\n result = parser.parse(\"Variant: 42\")\n assert result[\"variant\"] == 42\n result = parser.parse(\"Variant: blue\")\n assert result[\"variant\"] is Color.blue\n result = parser.parse(\"Variant: __MISMATCH__\")\n assert not result\n\n\n\nExtended Parser with CardinalityField support\n-------------------------------------------------------------------------------\n\nThe parser extends the ``parse.Parser`` and adds the following functionality:\n\n* supports the CardinalityField naming scheme\n* automatically creates missing type variants for types with\n a CardinalityField by using the primary type converter for cardinality=1\n* extends the provide type converter dictionary with new type variants.\n\nExample:\n\n.. code-block:: python\n\n # -- USE CASE: Parser with CardinalityField support.\n # NOTE: Automatically adds missing type variants with CardinalityField part.\n # USE: parse_number() type converter from above.\n from parse_type.cfparse import Parser\n\n # -- PREPARE: parser, adds missing type variant for cardinality 1..* (many)\n type_dict = dict(Number=parse_number)\n schema = \"List: {numbers:Number+}\"\n parser = Parser(schema, type_dict)\n assert \"Number+\" in type_dict, \"Created missing type variant based on: Number\"\n\n # -- USE: parser.\n result = parser.parse(\"List: 1, 2, 3\")\n assert result[\"numbers\"] == [1, 2, 3]\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Simplifies to build parse types based on the parse module",
"version": "0.6.4",
"project_urls": {
"Download": "https://pypi.org/project/parse_type/",
"Homepage": "https://github.com/jenisys/parse_type",
"Issue Tracker": "https://github.com/jenisys/parse_type/issues/",
"Source Code": "https://github.com/jenisys/parse_type"
},
"split_keywords": [
"parse",
" parsing"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d5b3f6cc950042bfdbe98672e7c834d930f85920fb7d3359f59096e8d2799617",
"md5": "2955cc0d03ee24b944996a773006954f",
"sha256": "83d41144a82d6b8541127bf212dd76c7f01baff680b498ce8a4d052a7a5bce4c"
},
"downloads": -1,
"filename": "parse_type-0.6.4-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "2955cc0d03ee24b944996a773006954f",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": "!=3.0.*,!=3.1.*,>=2.7",
"size": 27442,
"upload_time": "2024-10-03T11:50:58",
"upload_time_iso_8601": "2024-10-03T11:50:58.519348Z",
"url": "https://files.pythonhosted.org/packages/d5/b3/f6cc950042bfdbe98672e7c834d930f85920fb7d3359f59096e8d2799617/parse_type-0.6.4-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "17e9a3b2ae5f8a852542788ac1f1865dcea0c549cc40af243f42cabfa0acf24d",
"md5": "058912a402ae35c0e2958860c9ed80f1",
"sha256": "5e1ec10440b000c3f818006033372939e693a9ec0176f446d9303e4db88489a6"
},
"downloads": -1,
"filename": "parse_type-0.6.4.tar.gz",
"has_sig": false,
"md5_digest": "058912a402ae35c0e2958860c9ed80f1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "!=3.0.*,!=3.1.*,>=2.7",
"size": 96480,
"upload_time": "2024-10-03T11:51:00",
"upload_time_iso_8601": "2024-10-03T11:51:00.353277Z",
"url": "https://files.pythonhosted.org/packages/17/e9/a3b2ae5f8a852542788ac1f1865dcea0c549cc40af243f42cabfa0acf24d/parse_type-0.6.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-03 11:51:00",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jenisys",
"github_project": "parse_type",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"tox": true,
"lcname": "parse-type"
}