mdform


Namemdform JSON
Version 0.6 PyPI version JSON
download
home_page
SummaryParse Markdown form and generate useful templates and data.
upload_time2023-01-03 00:28:41
maintainer
docs_urlNone
author
requires_python>=3.8
licenseCopyright (c) 2021 by Hernan E. Grecco and contributors. See AUTHORS for more details. Some rights reserved. Redistribution and use in source and binary forms of the software as well as documentation, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
keywords markdown form
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Latest Version](https://img.shields.io/pypi/v/mdform.svg)](https://pypi.python.org/pypi/mdform)

[![License](https://img.shields.io/pypi/l/mdform.svg)](https://pypi.python.org/pypi/mdform)

[![Python Versions](https://img.shields.io/pypi/pyversions/mdform.svg)](https://pypi.python.org/pypi/mdform)

[![CI](https://github.com/hgrecco/mdform/workflows/CI/badge.svg)](https://github.com/hgrecco/mdform/actions?query=workflow%3ACI)

[![LINTER](https://github.com/hgrecco/mdform/workflows/Lint/badge.svg)](https://github.com/hgrecco/mdform/actions?query=workflow%3ALint)

[![Coverage](https://coveralls.io/repos/github/hgrecco/mdform/badge.svg?branch=master)](https://coveralls.io/github/hgrecco/mdform?branch=master)

# mdform

An extension for [python-markdown](https://python-markdown.github.io/)
to parse forms in a Markdown document.

This document:

```text
Please fill this form:

name* = ___
email = @

And also this important question:

Do you like this = () YES () NO
```

will generate the following html template:

```jinja2
Please fill this form:

{{ form.name }}
{{ form.email }}

And also this important question:

{{ form.do_you_like_this }}
```

and this form definition dictionary:

```python
{
    "name": Field(
        original_label="name", required=True, specific_field=StringField(length=None)
    ),
    "email": Field(original_label="email", required=False, specific_field=EmailField()),
    "do_you_like_this": Field(
        original_label="Do you like this",
        required=False,
        specific_field=RadioField(choices=("Y", "N"), default=None),
    ),
}
```

that you can consume to generate a form. See how we use it in
[flask-mdform](https://github.com/hgrecco/flask-mdform)

## Installation

```bash
pip install mdform
```

## Usage

```python
>>> import mdform
>>> html, form_definition = mdform.parse(text)
```

## Syntax

The syntax is strongly based on this
[wmd](https://github.com/brikis98/wmd) fork. Briefly, each field has a
label, an optional flag to indicate if the field is required and, after
the equal, the specification of the type of field

For example, a required text field (notice the `*`):

```text
name* = ___
```

An optional text field (notice the lack of `*`):

```text
name = ___
```

An optional email field (notice the `___` is now`@`):

```text
email = @
```

Each field is parsed into an object with the following attributes

- **original_label**: `str`, label as given in the markdown
  text.
- **required**: `bool`, indicate if the `*`  was
  present.
- **specific_field**: `object`, describing the field in more
  detail that might contain additional attributes.

Additionally, it has two properties:

- **is_label_hidden**: bool, indicates if `original_label`
  starts with `_` which can be used downstream to
  indicate the label should not be displayed.
- **label**: str, a clean version of `original_label` in which
  `_` prefix has been removed.

In the following lines, we will describe the syntax for each specific
field.

### Text fields (StringField)

```text
name = ___
```

or:

```text
name = ___[50]
```

Exactly 3 underscores will be matched. More will be handled as
standard underline directives.

Customizing:

```text
name = ___[length]
```

Specific field attributes:

- **length**: int or None (default)

### Integer fields (IntegerField)

```text
value = ###
```

or:

```text
value = ###[0:2:1]
```

Exactly 3 numeral will be matched. Any more will be handled as standard
directives.

Customizing:

```text
value = ###[range]
```

The `range` is parsed like a numpy range.

Specific field attributes:

- **min**: int or None (default)
- **max**: int or None (default)
- **step**: int or None (default)

### Float fields (FloatField)

```text
value = #.#f
```

or:

```text
value = #.#f[0:2:0.5]
```

Exactly 3 numbers will be matched. More will be handled as standard
directives.

Customizing:

```text
value = #.#f[range]
```

The `range` is parsed like a numpy range.

Specific field attributes:

- **min**: float or None (default)
- **max**: float or None (default)
- **step**: float or None (default)

### Decimal fields (DecimalField)

```text
value = #.#
```

or:

```text
value = #.#[0:2:0.5:1]
```

Exactly 4 numbers will be matched. More will be handled as standard
directives.

Customizing:

```text
value = #.#[range:places]
```

The `range` is parsed like a numpy range. The last (fourth
position) is always the place

Specific field attributes:

- **min**: float or None (default)
- **max**: float or None (default)
- **step**: float or None (default)
- **step**: int (default = 2)

### Text area (TextAreaField)

```text
name = AAA
```

or:

```text
name = AAA[50]
```

Exactly 3 slashes will be matched.

Customizing:

```text
name = ___[length]
```

Specific field attributes:

- **length**: int or None (default)

### Radio buttons (RadioField)

```text
sex = (x) male () female
```

Optionally, an `x` can be used to indicate the default
value.

Specific field attributes:

- **values**: tuple of str
- **default**: str

### Check boxes (CheckboxField)

```text
phones = [] Android [x] iPhone [x] Blackberry
```

Optionally, an `x` can be used to indicate the default
values.

Specific field attributes:

- **values**: tuple of strings
- **default**: tuple of str

### Drop down (SelectField)

```text
city = {BOS, SFO, (NYC)}
```

Or with user-friendly labels:

```text
city = {BOS -> Boston, SFO -> San Francisco, (NYC -> New York City)}
```

```text
city = {BOS, SFO, (NYC -> New York City)}
```

The option in parentheses will be the default.

Specific field attributes:

- **choices**: tuple of (str, str) (key, value)
- **default**: str
- **collapse_on**: str or None Item used to collapse. Format "~value"
  or "value"

### File Field (FileField)

```text
name = ...
```

or:

```text
name = ...[png]
```

```text
name = ...[png,jpg]
```

```text
name = ...[png,jpg;Only image files]
```

Specific field attributes:

- **allowed**: tuple of str
- **description**: str

### Date Field (DateField)

```text
name = d/m/y
```

### Time Field (TimeField)

```text
name = hh:mm
```

### Sections

In certain cases is useful to create a named section.

```text
[section:university]

name = ___

[section:school]

name = ___
```

will render as:

```jinja2
{{ form.university_name }}
{{ form.school_name }}
```

and the form definition dictionary:

```python
{
    "university_name": Field(
        original_label="name", required=True, specific_field=StringField(length=None)
    ),
    "school_name": Field(
        original_label="name", required=True, specific_field=StringField(length=None)
    ),
}
```

Notice that the key in the form definition dictionary (referred in the
code as `variable_name`) is not just the label: it now
contains the section name allowing multiple field with the same label.

Sections are labeled from top to bottom without nesting. To remove a
section name just do it this way.

```text
[section:university]

name = ___

[section]

name = ___
```

will render as:

```jinja2
{{ form.university_name }}
{{ form.name }}
```

### Collapsable parts

In certain cases is useful to create a part of the form which collapses
based on the value of a dropdown box. Just use the modifier
`[c]` or the dropdown item that will collapse the part of
the html and enclose the collapsable part as shown:

```text
extra = {Yes, (No[c])}

[collapse:extra]

name = ___

[endcollapse]
```

The `extra` in the `collapse` tag indicates
which dropdown box is used as control.

Alternative, you can specify in which option to open a collapsable part
with the modifier `o`:

```text
extra = {Yes[o], (No)}

[collapse:extra]

name = ___

[endcollapse]
```

## Syntax summary

```
Labeled field               <label> =
Labeled required field      <label>* =

Specific fields:
    - StringField           ___[length]         (length is optional)
    - IntegerField          ###[min:max:step]   (min, max, step are optional)
    - DecimalField          #.#[min:max:step:places]   (min, max, step, places are optional)
    - FloatField            #.#f[min:max:step]   (min, max, step are optional)
    - TextAreaField         AAA[length]         (length is optional)
    - DateField             d/m/y
    - TimeField             hh:mm
    - EmailField            @
    - RadioField            (x) A () B          (the x is optional, defines a default choice)
    - CheckboxField         [x] A [] B          (the x is optional, defines a default choice)
    - SelectField           {(A), B}            (the parenthesis are optional, defines a default choice)
    - FileField             ...[allowed]        (allowed is optional, extensions; description)

Organization:
    - Section
        [section:name]      name is a string which is prepended to the field names
    - Collapsable part      control is the name of the field controlling open and close
        [collapse:control]      of this part.
        [endcollapse]           - Use [o] to indicate that selecting that option should open the part
                                - Use [c] to indicate that selecting that option should close the part
```

## Customizing HTML output

The HTML field output can be fully customized by means of the formatter
parameter. For example, if you want to generate a
[Mako](https://www.makotemplates.org/) template just do the following:

```python
>>> def mako_field_formatter(variable_name, field):
        return "${ " + f"form.{variable_name}" + " }"
>>>
>>> import mdform
>>> html, form_definition = mdform.parse(text, formatter=mako_field_formatter)
```

will generate the following html template:

```mako
Please fill this form:

${ form.name }
${ form.email }

And also this important question:

${ form.do_you_like_this }
```

The formatter function must take two arguments: the variable name and
the field object.

## Combining with other MD extensions

If you need to integrate `mdform` an existing workflow with
other extensions, just instantiate the markdown object as you normally
do it and pass the `FormExtension`. For example, here I am
combining `mdform` with the
[meta](https://python-markdown.github.io/extensions/meta_data/)
extension.

```python
>>> from mdform import FormExtension, Markdown # Markdown is just re-exported from python-markdown
>>> md = Markdown(extensions = [FormExtension(), 'meta'])
>>> html = md.convert(text)           # this is the jinja template
>>> form_def = md.mdform_definition   # this is the form definition
```

The form definition dict is now accesible through
`mdform_definition` attribute of the markdown object

To customize the formatter:

```python
>>> md = Markdown(extensions = [FormExtension(formatter=mako_field_formatter), 'meta'])
```

______________________________________________________________________

See [AUTHORS](https://github.com/hgrecco/mdform/blob/master/AUTHORS) for
a list of the maintainers.

To review an ordered list of notable changes for each version of a
project, see
[CHANGES](https://github.com/hgrecco/mdform/blob/master/CHANGES)

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "mdform",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "markdown,form",
    "author": "",
    "author_email": "\"Hern\u00e1n E. Grecco\" <hernan.grecco@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/fb/c9/afea3fe2e1332181134b4c7ec60d90d4871389d77a3750c98af7215ef068/mdform-0.6.tar.gz",
    "platform": null,
    "description": "[![Latest Version](https://img.shields.io/pypi/v/mdform.svg)](https://pypi.python.org/pypi/mdform)\n\n[![License](https://img.shields.io/pypi/l/mdform.svg)](https://pypi.python.org/pypi/mdform)\n\n[![Python Versions](https://img.shields.io/pypi/pyversions/mdform.svg)](https://pypi.python.org/pypi/mdform)\n\n[![CI](https://github.com/hgrecco/mdform/workflows/CI/badge.svg)](https://github.com/hgrecco/mdform/actions?query=workflow%3ACI)\n\n[![LINTER](https://github.com/hgrecco/mdform/workflows/Lint/badge.svg)](https://github.com/hgrecco/mdform/actions?query=workflow%3ALint)\n\n[![Coverage](https://coveralls.io/repos/github/hgrecco/mdform/badge.svg?branch=master)](https://coveralls.io/github/hgrecco/mdform?branch=master)\n\n# mdform\n\nAn extension for [python-markdown](https://python-markdown.github.io/)\nto parse forms in a Markdown document.\n\nThis document:\n\n```text\nPlease fill this form:\n\nname* = ___\nemail = @\n\nAnd also this important question:\n\nDo you like this = () YES () NO\n```\n\nwill generate the following html template:\n\n```jinja2\nPlease fill this form:\n\n{{ form.name }}\n{{ form.email }}\n\nAnd also this important question:\n\n{{ form.do_you_like_this }}\n```\n\nand this form definition dictionary:\n\n```python\n{\n    \"name\": Field(\n        original_label=\"name\", required=True, specific_field=StringField(length=None)\n    ),\n    \"email\": Field(original_label=\"email\", required=False, specific_field=EmailField()),\n    \"do_you_like_this\": Field(\n        original_label=\"Do you like this\",\n        required=False,\n        specific_field=RadioField(choices=(\"Y\", \"N\"), default=None),\n    ),\n}\n```\n\nthat you can consume to generate a form. See how we use it in\n[flask-mdform](https://github.com/hgrecco/flask-mdform)\n\n## Installation\n\n```bash\npip install mdform\n```\n\n## Usage\n\n```python\n>>> import mdform\n>>> html, form_definition = mdform.parse(text)\n```\n\n## Syntax\n\nThe syntax is strongly based on this\n[wmd](https://github.com/brikis98/wmd) fork. Briefly, each field has a\nlabel, an optional flag to indicate if the field is required and, after\nthe equal, the specification of the type of field\n\nFor example, a required text field (notice the `*`):\n\n```text\nname* = ___\n```\n\nAn optional text field (notice the lack of `*`):\n\n```text\nname = ___\n```\n\nAn optional email field (notice the `___` is now`@`):\n\n```text\nemail = @\n```\n\nEach field is parsed into an object with the following attributes\n\n- **original_label**: `str`, label as given in the markdown\n  text.\n- **required**: `bool`, indicate if the `*`  was\n  present.\n- **specific_field**: `object`, describing the field in more\n  detail that might contain additional attributes.\n\nAdditionally, it has two properties:\n\n- **is_label_hidden**: bool, indicates if `original_label`\n  starts with `_` which can be used downstream to\n  indicate the label should not be displayed.\n- **label**: str, a clean version of `original_label` in which\n  `_` prefix has been removed.\n\nIn the following lines, we will describe the syntax for each specific\nfield.\n\n### Text fields (StringField)\n\n```text\nname = ___\n```\n\nor:\n\n```text\nname = ___[50]\n```\n\nExactly 3 underscores will be matched. More will be handled as\nstandard underline directives.\n\nCustomizing:\n\n```text\nname = ___[length]\n```\n\nSpecific field attributes:\n\n- **length**: int or None (default)\n\n### Integer fields (IntegerField)\n\n```text\nvalue = ###\n```\n\nor:\n\n```text\nvalue = ###[0:2:1]\n```\n\nExactly 3 numeral will be matched. Any more will be handled as standard\ndirectives.\n\nCustomizing:\n\n```text\nvalue = ###[range]\n```\n\nThe `range` is parsed like a numpy range.\n\nSpecific field attributes:\n\n- **min**: int or None (default)\n- **max**: int or None (default)\n- **step**: int or None (default)\n\n### Float fields (FloatField)\n\n```text\nvalue = #.#f\n```\n\nor:\n\n```text\nvalue = #.#f[0:2:0.5]\n```\n\nExactly 3 numbers will be matched. More will be handled as standard\ndirectives.\n\nCustomizing:\n\n```text\nvalue = #.#f[range]\n```\n\nThe `range` is parsed like a numpy range.\n\nSpecific field attributes:\n\n- **min**: float or None (default)\n- **max**: float or None (default)\n- **step**: float or None (default)\n\n### Decimal fields (DecimalField)\n\n```text\nvalue = #.#\n```\n\nor:\n\n```text\nvalue = #.#[0:2:0.5:1]\n```\n\nExactly 4 numbers will be matched. More will be handled as standard\ndirectives.\n\nCustomizing:\n\n```text\nvalue = #.#[range:places]\n```\n\nThe `range` is parsed like a numpy range. The last (fourth\nposition) is always the place\n\nSpecific field attributes:\n\n- **min**: float or None (default)\n- **max**: float or None (default)\n- **step**: float or None (default)\n- **step**: int (default = 2)\n\n### Text area (TextAreaField)\n\n```text\nname = AAA\n```\n\nor:\n\n```text\nname = AAA[50]\n```\n\nExactly 3 slashes will be matched.\n\nCustomizing:\n\n```text\nname = ___[length]\n```\n\nSpecific field attributes:\n\n- **length**: int or None (default)\n\n### Radio buttons (RadioField)\n\n```text\nsex = (x) male () female\n```\n\nOptionally, an `x` can be used to indicate the default\nvalue.\n\nSpecific field attributes:\n\n- **values**: tuple of str\n- **default**: str\n\n### Check boxes (CheckboxField)\n\n```text\nphones = [] Android [x] iPhone [x] Blackberry\n```\n\nOptionally, an `x` can be used to indicate the default\nvalues.\n\nSpecific field attributes:\n\n- **values**: tuple of strings\n- **default**: tuple of str\n\n### Drop down (SelectField)\n\n```text\ncity = {BOS, SFO, (NYC)}\n```\n\nOr with user-friendly labels:\n\n```text\ncity = {BOS -> Boston, SFO -> San Francisco, (NYC -> New York City)}\n```\n\n```text\ncity = {BOS, SFO, (NYC -> New York City)}\n```\n\nThe option in parentheses will be the default.\n\nSpecific field attributes:\n\n- **choices**: tuple of (str, str) (key, value)\n- **default**: str\n- **collapse_on**: str or None Item used to collapse. Format \"~value\"\n  or \"value\"\n\n### File Field (FileField)\n\n```text\nname = ...\n```\n\nor:\n\n```text\nname = ...[png]\n```\n\n```text\nname = ...[png,jpg]\n```\n\n```text\nname = ...[png,jpg;Only image files]\n```\n\nSpecific field attributes:\n\n- **allowed**: tuple of str\n- **description**: str\n\n### Date Field (DateField)\n\n```text\nname = d/m/y\n```\n\n### Time Field (TimeField)\n\n```text\nname = hh:mm\n```\n\n### Sections\n\nIn certain cases is useful to create a named section.\n\n```text\n[section:university]\n\nname = ___\n\n[section:school]\n\nname = ___\n```\n\nwill render as:\n\n```jinja2\n{{ form.university_name }}\n{{ form.school_name }}\n```\n\nand the form definition dictionary:\n\n```python\n{\n    \"university_name\": Field(\n        original_label=\"name\", required=True, specific_field=StringField(length=None)\n    ),\n    \"school_name\": Field(\n        original_label=\"name\", required=True, specific_field=StringField(length=None)\n    ),\n}\n```\n\nNotice that the key in the form definition dictionary (referred in the\ncode as `variable_name`) is not just the label: it now\ncontains the section name allowing multiple field with the same label.\n\nSections are labeled from top to bottom without nesting. To remove a\nsection name just do it this way.\n\n```text\n[section:university]\n\nname = ___\n\n[section]\n\nname = ___\n```\n\nwill render as:\n\n```jinja2\n{{ form.university_name }}\n{{ form.name }}\n```\n\n### Collapsable parts\n\nIn certain cases is useful to create a part of the form which collapses\nbased on the value of a dropdown box. Just use the modifier\n`[c]` or the dropdown item that will collapse the part of\nthe html and enclose the collapsable part as shown:\n\n```text\nextra = {Yes, (No[c])}\n\n[collapse:extra]\n\nname = ___\n\n[endcollapse]\n```\n\nThe `extra` in the `collapse` tag indicates\nwhich dropdown box is used as control.\n\nAlternative, you can specify in which option to open a collapsable part\nwith the modifier `o`:\n\n```text\nextra = {Yes[o], (No)}\n\n[collapse:extra]\n\nname = ___\n\n[endcollapse]\n```\n\n## Syntax summary\n\n```\nLabeled field               <label> =\nLabeled required field      <label>* =\n\nSpecific fields:\n    - StringField           ___[length]         (length is optional)\n    - IntegerField          ###[min:max:step]   (min, max, step are optional)\n    - DecimalField          #.#[min:max:step:places]   (min, max, step, places are optional)\n    - FloatField            #.#f[min:max:step]   (min, max, step are optional)\n    - TextAreaField         AAA[length]         (length is optional)\n    - DateField             d/m/y\n    - TimeField             hh:mm\n    - EmailField            @\n    - RadioField            (x) A () B          (the x is optional, defines a default choice)\n    - CheckboxField         [x] A [] B          (the x is optional, defines a default choice)\n    - SelectField           {(A), B}            (the parenthesis are optional, defines a default choice)\n    - FileField             ...[allowed]        (allowed is optional, extensions; description)\n\nOrganization:\n    - Section\n        [section:name]      name is a string which is prepended to the field names\n    - Collapsable part      control is the name of the field controlling open and close\n        [collapse:control]      of this part.\n        [endcollapse]           - Use [o] to indicate that selecting that option should open the part\n                                - Use [c] to indicate that selecting that option should close the part\n```\n\n## Customizing HTML output\n\nThe HTML field output can be fully customized by means of the formatter\nparameter. For example, if you want to generate a\n[Mako](https://www.makotemplates.org/) template just do the following:\n\n```python\n>>> def mako_field_formatter(variable_name, field):\n        return \"${ \" + f\"form.{variable_name}\" + \" }\"\n>>>\n>>> import mdform\n>>> html, form_definition = mdform.parse(text, formatter=mako_field_formatter)\n```\n\nwill generate the following html template:\n\n```mako\nPlease fill this form:\n\n${ form.name }\n${ form.email }\n\nAnd also this important question:\n\n${ form.do_you_like_this }\n```\n\nThe formatter function must take two arguments: the variable name and\nthe field object.\n\n## Combining with other MD extensions\n\nIf you need to integrate `mdform` an existing workflow with\nother extensions, just instantiate the markdown object as you normally\ndo it and pass the `FormExtension`. For example, here I am\ncombining `mdform` with the\n[meta](https://python-markdown.github.io/extensions/meta_data/)\nextension.\n\n```python\n>>> from mdform import FormExtension, Markdown # Markdown is just re-exported from python-markdown\n>>> md = Markdown(extensions = [FormExtension(), 'meta'])\n>>> html = md.convert(text)           # this is the jinja template\n>>> form_def = md.mdform_definition   # this is the form definition\n```\n\nThe form definition dict is now accesible through\n`mdform_definition` attribute of the markdown object\n\nTo customize the formatter:\n\n```python\n>>> md = Markdown(extensions = [FormExtension(formatter=mako_field_formatter), 'meta'])\n```\n\n______________________________________________________________________\n\nSee [AUTHORS](https://github.com/hgrecco/mdform/blob/master/AUTHORS) for\na list of the maintainers.\n\nTo review an ordered list of notable changes for each version of a\nproject, see\n[CHANGES](https://github.com/hgrecco/mdform/blob/master/CHANGES)\n",
    "bugtrack_url": null,
    "license": "Copyright (c) 2021 by Hernan E. Grecco and contributors.  See AUTHORS for more details.  Some rights reserved.  Redistribution and use in source and binary forms of the software as well as documentation, with or without modification, are permitted provided that the following conditions are met:  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.  * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.  THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ",
    "summary": "Parse Markdown form and generate useful templates and data.",
    "version": "0.6",
    "split_keywords": [
        "markdown",
        "form"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5ab7afbf5962c3af18ac52d8ea946196616b4c7ea8528634f138f3e18d26139e",
                "md5": "925b2b6b375e7e42db232dc89a2b9fc0",
                "sha256": "80fcaf80144151b19d20b0b67a094f3e735016e31e9a97fb03082250da167a2a"
            },
            "downloads": -1,
            "filename": "mdform-0.6-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "925b2b6b375e7e42db232dc89a2b9fc0",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 15420,
            "upload_time": "2023-01-03T00:28:39",
            "upload_time_iso_8601": "2023-01-03T00:28:39.614427Z",
            "url": "https://files.pythonhosted.org/packages/5a/b7/afbf5962c3af18ac52d8ea946196616b4c7ea8528634f138f3e18d26139e/mdform-0.6-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fbc9afea3fe2e1332181134b4c7ec60d90d4871389d77a3750c98af7215ef068",
                "md5": "14b92e6a8e351e63ccc3e4e1d3690137",
                "sha256": "dad7caf5e60970fc9665be14b6ca0a3f620dfd9491e29934b30070f45a970169"
            },
            "downloads": -1,
            "filename": "mdform-0.6.tar.gz",
            "has_sig": false,
            "md5_digest": "14b92e6a8e351e63ccc3e4e1d3690137",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 19750,
            "upload_time": "2023-01-03T00:28:41",
            "upload_time_iso_8601": "2023-01-03T00:28:41.027889Z",
            "url": "https://files.pythonhosted.org/packages/fb/c9/afea3fe2e1332181134b4c7ec60d90d4871389d77a3750c98af7215ef068/mdform-0.6.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-01-03 00:28:41",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "lcname": "mdform"
}
        
Elapsed time: 0.02309s