z3c.currency


Namez3c.currency JSON
Version 2.0 PyPI version JSON
download
home_pagehttps://github.com/zopefoundation/z3c.currency
SummaryA currency field and support for ``z3c.form``.
upload_time2023-02-08 15:00:13
maintainer
docs_urlNone
authorStephan Richter and the Zope Community
requires_python>=3.7
licenseZPL 2.1
keywords zope3 currency schema field widget form
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
.. image:: https://github.com/zopefoundation/z3c.currency/actions/workflows/tests.yml/badge.svg
   :target: https://github.com/zopefoundation/z3c.currency/actions/workflows/tests.yml

.. image:: https://coveralls.io/repos/github/zopefoundation/z3c.currency/badge.svg?branch=master
   :target: https://coveralls.io/github/zopefoundation/z3c.currency?branch=master

.. image:: https://img.shields.io/pypi/v/z3c.currency.svg
    :target: https://pypi.python.org/pypi/z3c.currency

.. image:: https://img.shields.io/pypi/pyversions/z3c.currency.svg
    :target: https://pypi.python.org/pypi/z3c.currency/


A package implementing a currency field for ``zope.schema`` and support for
using the field with ``z3c.form``.


Detailed Documentation
**********************

==================
The Currency Field
==================

The currency field is a numerical field, specifically designed to manage
monetary values.

  >>> from z3c.currency import field, interfaces

  >>> price = field.Currency(
  ...    title='Price',
  ...    description='The price of the item.')

Besides the common attributes, the currency field also provides two additional
attributes, the precision and unit. The precision is intended to allow for
specifying whether the value is provided whole units or 1/100th of the whole
unit -- in the US dollar and cents. By default this field is set to cents:

  >>> price.precision is interfaces.CENTS
  True

It can be set to be dollars:

  >>> price.precision = interfaces.DOLLARS
  >>> price.precision is interfaces.DOLLARS
  True

For financial applications, we also sometimes needsub-cents:

  >>> price.precision = interfaces.SUBCENTS
  >>> price.precision is interfaces.SUBCENTS
  True


Note: Is there a more "internationalized" word for the whole unit of a
currency?

The unit specifies the symbol of the currency used. It is also used for
formatting the numerical value to a string.

  >>> price.unit
  '$'
  >>> price.unit = 'SEK'
  >>> price.unit
  'SEK'

Of course, both of those attributes are available as constructor arguments:

  >>> price = field.Currency(
  ...    title='Price',
  ...    description='The price of the item.',
  ...    precision=interfaces.DOLLARS,
  ...    unit='SEK')

  >>> price.precision is interfaces.DOLLARS
  True
  >>> price.unit
  'SEK'

Let's now have a look at the validation. First of all, the value must always
be a decimal:

  >>> import decimal
  >>> price.validate(decimal.Decimal('12'))

  >>> price.validate(12)
  Traceback (most recent call last):
  ...
  z3c.currency.interfaces.WrongCurrencyType: int

  >>> price.validate(12.0)
  Traceback (most recent call last):
  ...
  z3c.currency.interfaces.WrongCurrencyType: float

Also, when the precision is set to DOLLARS as it is the case here, the value
must be a whole number:

  >>> price.validate(decimal.Decimal('12'))

  >>> price.validate(decimal.Decimal('12.01'))
  Traceback (most recent call last):
  ...
  z3c.currency.interfaces.IncorrectValuePrecision: 0

  >>> price.validate(decimal.Decimal('12.00'))
  Traceback (most recent call last):
  ...
  z3c.currency.interfaces.IncorrectValuePrecision: 0

When the precision is set to cents,

  >>> price.precision = interfaces.CENTS

then values only with two decimal places are accepted:

  >>> price.validate(decimal.Decimal('12.00'))

  >>> price.validate(decimal.Decimal('12'))
  Traceback (most recent call last):
  ...
  z3c.currency.interfaces.IncorrectValuePrecision: 1

  >>> price.validate(decimal.Decimal('12.0'))
  Traceback (most recent call last):
  ...
  z3c.currency.interfaces.IncorrectValuePrecision: 1

If we allow sub-cents,

  >>> price.precision = interfaces.SUBCENTS

any precision is allowed:

  >>> price.validate(decimal.Decimal('12.0'))
  >>> price.validate(decimal.Decimal('12'))
  >>> price.validate(decimal.Decimal('12.00001'))

If the field is not required, ...

  >>> price.required = False

let's make sure that the validation still passes.

  >>> price.validate(None)

Note that the ``IFromUnicode`` interface is purposefully not supported:

  >>> price.fromUnicode
  Traceback (most recent call last):
  ...
  AttributeError: 'Currency' object has no attribute 'fromUnicode'


``z3c.form`` Support
--------------------

This package also provides support for integration with the ``z3c.form``
package. In particular it implements a data converter from the ``Currency``
field to any widget accepting a unicode string.

  >>> from z3c.currency import converter
  >>> conv = converter.CurrencyConverter(price, None)
  >>> conv
  <DataConverter from Currency to NoneType>

The converter easily produces a string from any value:

  >>> conv.toWidgetValue(decimal.Decimal(12))
  '12'
  >>> conv.toWidgetValue(decimal.Decimal(1200))
  '1,200'
  >>> conv.toWidgetValue(decimal.Decimal(-12))
  '-12'
  >>> conv.toWidgetValue(decimal.Decimal('-12.0'))
  '-12.00'
  >>> conv.toWidgetValue(decimal.Decimal('-12.00'))
  '-12.00'

Note that always two decimal places are printed. You can also set the
precision to DOLLARS:

  >>> conv.field.precision = interfaces.DOLLARS

  >>> conv.toWidgetValue(decimal.Decimal(12))
  '12'
  >>> conv.toWidgetValue(decimal.Decimal('12.00'))
  '12'

Let's try sub-cents as well:

  >>> conv.field.precision = interfaces.SUBCENTS

  >>> conv.toWidgetValue(decimal.Decimal('12.00'))
  '12.00'
  >>> conv.toWidgetValue(decimal.Decimal('12'))
  '12'
  >>> conv.toWidgetValue(decimal.Decimal('12.0001'))
  '12.0001'

If the value is missing, then handle it gracefully.

  >>> conv.toWidgetValue(None)
  ''

Let's now parse a value. The parser is a little bit flexible, not only
accepting the output values, ...

  >>> conv.field.precision = interfaces.CENTS
  >>> conv.toFieldValue('12')
  Decimal('12.00')
  >>> conv.toFieldValue('1,200')
  Decimal('1200.00')
  >>> conv.toFieldValue('-12')
  Decimal('-12.00')
  >>> conv.toFieldValue('-12.00')
  Decimal('-12.00')

  >>> conv.field.precision = interfaces.DOLLARS
  >>> conv.toFieldValue('12')
  Decimal('12')
  >>> conv.toFieldValue('12.00')
  Decimal('12')

  >>> conv.field.precision = interfaces.SUBCENTS
  >>> conv.toFieldValue('12')
  Decimal('12')
  >>> conv.toFieldValue('12.00')
  Decimal('12.00')
  >>> conv.toFieldValue('12.0000')
  Decimal('12.0000')
  >>> conv.toFieldValue('12.0001')
  Decimal('12.0001')

but also other input values:

  >>> conv.toFieldValue('1200')
  Decimal('1200')

If the browser sends an empty string, then handle it gracefully.

  >>> conv.toFieldValue('')


=======
CHANGES
=======

2.0 (2023-02-08)
----------------

- Drop support for Python 2.7, 3.5, 3.6.

- Add support for Python 3.8, 3.9, 3.10, 3.11.

- Drop deprecated support for running the tests using ``python setup.py test``.


1.2.0 (2018-11-14)
------------------

- Python 3.6 and 3.7 support. Drop Python 2.6.

- Tests now run with ``python setup.py test``.


1.1.1 (2015-11-09)
------------------

- Standardize namespace __init__


1.1.0 (2013-09-27)
------------------

- Added new precision value "sub-cents" (``interfaces.SUBCENTS``), which
  allows precision beyond pennies, which is needed for financial and other
  business applications.


1.0.0 (2013-08-16)
------------------

- Updated Trove classifiers.

- Moved code to GitHub.

- Changed validation to raise custom validation errors, since the upstream
  code looks at the doc string of the exception instead of the first argument.

- Improved converter to

  * Ensure proper precision of decimal after initial parsing.

  * Format the value to the proper precision.

- Changed "precision" field in `ICurrency` interface to be a choice, so that
  UIs generate nicely.

- Cleaned up code a little bit.


0.1.0 (2007-09-12)
------------------

- Initial Release

  * Implementation of ``Currency`` field supporting precision and a unit.

  * Implementation of data converter.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/zopefoundation/z3c.currency",
    "name": "z3c.currency",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "zope3 currency schema field widget form",
    "author": "Stephan Richter and the Zope Community",
    "author_email": "zope-dev@zope.dev",
    "download_url": "https://files.pythonhosted.org/packages/42/9a/1bd5701fb87f7b81c6792a47a5a849142aff78b20c1a066eb4058ed3d823/z3c.currency-2.0.tar.gz",
    "platform": null,
    "description": "\n.. image:: https://github.com/zopefoundation/z3c.currency/actions/workflows/tests.yml/badge.svg\n   :target: https://github.com/zopefoundation/z3c.currency/actions/workflows/tests.yml\n\n.. image:: https://coveralls.io/repos/github/zopefoundation/z3c.currency/badge.svg?branch=master\n   :target: https://coveralls.io/github/zopefoundation/z3c.currency?branch=master\n\n.. image:: https://img.shields.io/pypi/v/z3c.currency.svg\n    :target: https://pypi.python.org/pypi/z3c.currency\n\n.. image:: https://img.shields.io/pypi/pyversions/z3c.currency.svg\n    :target: https://pypi.python.org/pypi/z3c.currency/\n\n\nA package implementing a currency field for ``zope.schema`` and support for\nusing the field with ``z3c.form``.\n\n\nDetailed Documentation\n**********************\n\n==================\nThe Currency Field\n==================\n\nThe currency field is a numerical field, specifically designed to manage\nmonetary values.\n\n  >>> from z3c.currency import field, interfaces\n\n  >>> price = field.Currency(\n  ...    title='Price',\n  ...    description='The price of the item.')\n\nBesides the common attributes, the currency field also provides two additional\nattributes, the precision and unit. The precision is intended to allow for\nspecifying whether the value is provided whole units or 1/100th of the whole\nunit -- in the US dollar and cents. By default this field is set to cents:\n\n  >>> price.precision is interfaces.CENTS\n  True\n\nIt can be set to be dollars:\n\n  >>> price.precision = interfaces.DOLLARS\n  >>> price.precision is interfaces.DOLLARS\n  True\n\nFor financial applications, we also sometimes needsub-cents:\n\n  >>> price.precision = interfaces.SUBCENTS\n  >>> price.precision is interfaces.SUBCENTS\n  True\n\n\nNote: Is there a more \"internationalized\" word for the whole unit of a\ncurrency?\n\nThe unit specifies the symbol of the currency used. It is also used for\nformatting the numerical value to a string.\n\n  >>> price.unit\n  '$'\n  >>> price.unit = 'SEK'\n  >>> price.unit\n  'SEK'\n\nOf course, both of those attributes are available as constructor arguments:\n\n  >>> price = field.Currency(\n  ...    title='Price',\n  ...    description='The price of the item.',\n  ...    precision=interfaces.DOLLARS,\n  ...    unit='SEK')\n\n  >>> price.precision is interfaces.DOLLARS\n  True\n  >>> price.unit\n  'SEK'\n\nLet's now have a look at the validation. First of all, the value must always\nbe a decimal:\n\n  >>> import decimal\n  >>> price.validate(decimal.Decimal('12'))\n\n  >>> price.validate(12)\n  Traceback (most recent call last):\n  ...\n  z3c.currency.interfaces.WrongCurrencyType: int\n\n  >>> price.validate(12.0)\n  Traceback (most recent call last):\n  ...\n  z3c.currency.interfaces.WrongCurrencyType: float\n\nAlso, when the precision is set to DOLLARS as it is the case here, the value\nmust be a whole number:\n\n  >>> price.validate(decimal.Decimal('12'))\n\n  >>> price.validate(decimal.Decimal('12.01'))\n  Traceback (most recent call last):\n  ...\n  z3c.currency.interfaces.IncorrectValuePrecision: 0\n\n  >>> price.validate(decimal.Decimal('12.00'))\n  Traceback (most recent call last):\n  ...\n  z3c.currency.interfaces.IncorrectValuePrecision: 0\n\nWhen the precision is set to cents,\n\n  >>> price.precision = interfaces.CENTS\n\nthen values only with two decimal places are accepted:\n\n  >>> price.validate(decimal.Decimal('12.00'))\n\n  >>> price.validate(decimal.Decimal('12'))\n  Traceback (most recent call last):\n  ...\n  z3c.currency.interfaces.IncorrectValuePrecision: 1\n\n  >>> price.validate(decimal.Decimal('12.0'))\n  Traceback (most recent call last):\n  ...\n  z3c.currency.interfaces.IncorrectValuePrecision: 1\n\nIf we allow sub-cents,\n\n  >>> price.precision = interfaces.SUBCENTS\n\nany precision is allowed:\n\n  >>> price.validate(decimal.Decimal('12.0'))\n  >>> price.validate(decimal.Decimal('12'))\n  >>> price.validate(decimal.Decimal('12.00001'))\n\nIf the field is not required, ...\n\n  >>> price.required = False\n\nlet's make sure that the validation still passes.\n\n  >>> price.validate(None)\n\nNote that the ``IFromUnicode`` interface is purposefully not supported:\n\n  >>> price.fromUnicode\n  Traceback (most recent call last):\n  ...\n  AttributeError: 'Currency' object has no attribute 'fromUnicode'\n\n\n``z3c.form`` Support\n--------------------\n\nThis package also provides support for integration with the ``z3c.form``\npackage. In particular it implements a data converter from the ``Currency``\nfield to any widget accepting a unicode string.\n\n  >>> from z3c.currency import converter\n  >>> conv = converter.CurrencyConverter(price, None)\n  >>> conv\n  <DataConverter from Currency to NoneType>\n\nThe converter easily produces a string from any value:\n\n  >>> conv.toWidgetValue(decimal.Decimal(12))\n  '12'\n  >>> conv.toWidgetValue(decimal.Decimal(1200))\n  '1,200'\n  >>> conv.toWidgetValue(decimal.Decimal(-12))\n  '-12'\n  >>> conv.toWidgetValue(decimal.Decimal('-12.0'))\n  '-12.00'\n  >>> conv.toWidgetValue(decimal.Decimal('-12.00'))\n  '-12.00'\n\nNote that always two decimal places are printed. You can also set the\nprecision to DOLLARS:\n\n  >>> conv.field.precision = interfaces.DOLLARS\n\n  >>> conv.toWidgetValue(decimal.Decimal(12))\n  '12'\n  >>> conv.toWidgetValue(decimal.Decimal('12.00'))\n  '12'\n\nLet's try sub-cents as well:\n\n  >>> conv.field.precision = interfaces.SUBCENTS\n\n  >>> conv.toWidgetValue(decimal.Decimal('12.00'))\n  '12.00'\n  >>> conv.toWidgetValue(decimal.Decimal('12'))\n  '12'\n  >>> conv.toWidgetValue(decimal.Decimal('12.0001'))\n  '12.0001'\n\nIf the value is missing, then handle it gracefully.\n\n  >>> conv.toWidgetValue(None)\n  ''\n\nLet's now parse a value. The parser is a little bit flexible, not only\naccepting the output values, ...\n\n  >>> conv.field.precision = interfaces.CENTS\n  >>> conv.toFieldValue('12')\n  Decimal('12.00')\n  >>> conv.toFieldValue('1,200')\n  Decimal('1200.00')\n  >>> conv.toFieldValue('-12')\n  Decimal('-12.00')\n  >>> conv.toFieldValue('-12.00')\n  Decimal('-12.00')\n\n  >>> conv.field.precision = interfaces.DOLLARS\n  >>> conv.toFieldValue('12')\n  Decimal('12')\n  >>> conv.toFieldValue('12.00')\n  Decimal('12')\n\n  >>> conv.field.precision = interfaces.SUBCENTS\n  >>> conv.toFieldValue('12')\n  Decimal('12')\n  >>> conv.toFieldValue('12.00')\n  Decimal('12.00')\n  >>> conv.toFieldValue('12.0000')\n  Decimal('12.0000')\n  >>> conv.toFieldValue('12.0001')\n  Decimal('12.0001')\n\nbut also other input values:\n\n  >>> conv.toFieldValue('1200')\n  Decimal('1200')\n\nIf the browser sends an empty string, then handle it gracefully.\n\n  >>> conv.toFieldValue('')\n\n\n=======\nCHANGES\n=======\n\n2.0 (2023-02-08)\n----------------\n\n- Drop support for Python 2.7, 3.5, 3.6.\n\n- Add support for Python 3.8, 3.9, 3.10, 3.11.\n\n- Drop deprecated support for running the tests using ``python setup.py test``.\n\n\n1.2.0 (2018-11-14)\n------------------\n\n- Python 3.6 and 3.7 support. Drop Python 2.6.\n\n- Tests now run with ``python setup.py test``.\n\n\n1.1.1 (2015-11-09)\n------------------\n\n- Standardize namespace __init__\n\n\n1.1.0 (2013-09-27)\n------------------\n\n- Added new precision value \"sub-cents\" (``interfaces.SUBCENTS``), which\n  allows precision beyond pennies, which is needed for financial and other\n  business applications.\n\n\n1.0.0 (2013-08-16)\n------------------\n\n- Updated Trove classifiers.\n\n- Moved code to GitHub.\n\n- Changed validation to raise custom validation errors, since the upstream\n  code looks at the doc string of the exception instead of the first argument.\n\n- Improved converter to\n\n  * Ensure proper precision of decimal after initial parsing.\n\n  * Format the value to the proper precision.\n\n- Changed \"precision\" field in `ICurrency` interface to be a choice, so that\n  UIs generate nicely.\n\n- Cleaned up code a little bit.\n\n\n0.1.0 (2007-09-12)\n------------------\n\n- Initial Release\n\n  * Implementation of ``Currency`` field supporting precision and a unit.\n\n  * Implementation of data converter.\n",
    "bugtrack_url": null,
    "license": "ZPL 2.1",
    "summary": "A currency field and support for ``z3c.form``.",
    "version": "2.0",
    "split_keywords": [
        "zope3",
        "currency",
        "schema",
        "field",
        "widget",
        "form"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b8d5ce4f02eb9c5ebcf76280a1486935c112f8dcf372d3bc2d3b0c0fffb644fb",
                "md5": "0368dd8a43640184ec37b4b09d6336e1",
                "sha256": "888b5c5866224ffbab1ff5beec501a80374dfc73aeab5d06c6a69db8132780ba"
            },
            "downloads": -1,
            "filename": "z3c.currency-2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0368dd8a43640184ec37b4b09d6336e1",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 12137,
            "upload_time": "2023-02-08T15:00:10",
            "upload_time_iso_8601": "2023-02-08T15:00:10.532540Z",
            "url": "https://files.pythonhosted.org/packages/b8/d5/ce4f02eb9c5ebcf76280a1486935c112f8dcf372d3bc2d3b0c0fffb644fb/z3c.currency-2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "429a1bd5701fb87f7b81c6792a47a5a849142aff78b20c1a066eb4058ed3d823",
                "md5": "732bdd09a80d5cb116e61072aa59e953",
                "sha256": "38e11ee70ac5a441b086f40abf3af01ee8060fb46a255df59f368856493cf900"
            },
            "downloads": -1,
            "filename": "z3c.currency-2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "732bdd09a80d5cb116e61072aa59e953",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 10261,
            "upload_time": "2023-02-08T15:00:13",
            "upload_time_iso_8601": "2023-02-08T15:00:13.183395Z",
            "url": "https://files.pythonhosted.org/packages/42/9a/1bd5701fb87f7b81c6792a47a5a849142aff78b20c1a066eb4058ed3d823/z3c.currency-2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-02-08 15:00:13",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "zopefoundation",
    "github_project": "z3c.currency",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "z3c.currency"
}
        
Elapsed time: 0.03867s