{"id":13540828,"url":"https://github.com/carlospalol/money","last_synced_at":"2025-12-18T02:04:42.597Z","repository":{"id":11881362,"uuid":"14442636","full_name":"carlospalol/money","owner":"carlospalol","description":"Python money class with optional CLDR-backed locale-aware formatting and an extensible currency exchange solution.","archived":false,"fork":false,"pushed_at":"2023-04-08T19:03:59.000Z","size":139,"stargazers_count":237,"open_issues_count":12,"forks_count":35,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-10-19T14:51:35.090Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carlospalol.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2013-11-16T06:03:45.000Z","updated_at":"2025-05-14T07:41:19.000Z","dependencies_parsed_at":"2024-01-29T18:51:45.000Z","dependency_job_id":null,"html_url":"https://github.com/carlospalol/money","commit_stats":{"total_commits":146,"total_committers":4,"mean_commits":36.5,"dds":"0.020547945205479423","last_synced_commit":"1e51f651f93edd62c16eb3d7aa034fec03096046"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/carlospalol/money","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospalol%2Fmoney","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospalol%2Fmoney/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospalol%2Fmoney/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospalol%2Fmoney/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carlospalol","download_url":"https://codeload.github.com/carlospalol/money/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlospalol%2Fmoney/sbom","scorecard":{"id":266272,"data":{"date":"2025-08-11","repo":{"name":"github.com/carlospalol/money","commit":"1e51f651f93edd62c16eb3d7aa034fec03096046"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-17T12:07:41.795Z","repository_id":11881362,"created_at":"2025-08-17T12:07:41.795Z","updated_at":"2025-08-17T12:07:41.795Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27789411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-18T02:00:09.725Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T10:00:33.508Z","updated_at":"2025-12-18T02:04:42.564Z","avatar_url":"https://github.com/carlospalol.png","language":"Python","funding_links":[],"categories":["E-commerce","资源列表","Python","电子商务","E-commerce [🔝](#readme)","Awesome Python","Libraries"],"sub_categories":["电子商务","E-commerce","Python"],"readme":"\n============\nPython Money\n============\n\nMoney class with optional CLDR-backed locale-aware formatting and an extensible currency exchange solution.\n\n.. RADAR: version\n\n**This is version 1.4.0-dev**.\n\n:Development: https://github.com/carlospalol/money\n:Latest release: https://pypi.python.org/pypi/money/\n\nThis package is compatible with Python 2.7, 3.4, 3.5, but there are important `Differences between Python versions`_. All code examples use Python 3.5.\n\n**Contents**\n\n.. contents::\n    :local:\n    :backlinks: none\n\n\nInstallation\n============\n\nInstall the latest release with:\n\n::\n\n    pip install money\n\nFor locale-aware formatting, also install the latest version of `Babel \u003chttps://pypi.python.org/pypi/Babel\u003e`_ (2.2 or 2.3 required):\n\n::\n\n    pip install babel\n\n\nUsage\n=====\n\n.. code:: python\n\n    \u003e\u003e\u003e from money import Money\n    \u003e\u003e\u003e m = Money(amount='2.22', currency='EUR')\n    \u003e\u003e\u003e m\n    EUR 2.22\n\n*amount* can be any valid value in ``decimal.Decimal(value)`` and *currency* should be a three-letter currency code. Money objects are immutable by convention and hashable. Once created, you can use read-only properties ``amount`` (decimal.Decimal) and ``currency`` (str) to access its internal components:\n\n.. code:: python\n\n    \u003e\u003e\u003e m = Money(2, 'USD')\n    \u003e\u003e\u003e m.amount\n    Decimal('2')\n    \u003e\u003e\u003e m.currency\n    'USD'\n\nMoney emulates a numeric type and you can apply most arithmetic and comparison operators between money objects, as well as addition, subtraction, and division with integers (int) and decimal numbers (decimal.Decimal):\n\n.. code:: python\n\n    \u003e\u003e\u003e m = Money('2.22', 'EUR')\n    \u003e\u003e\u003e m / 2\n    EUR 1.11\n    \u003e\u003e\u003e m + Money('7.77', 'EUR')\n    EUR 9.99\n\nMore formally, with *AAA* and *BBB* being different currencies:\n\n+-----------+---------------+-----------+-----------+-----------------+\n|           | Operator      | Money AAA | Money BBB | int, Decimal    |\n+===========+===============+===========+===========+=================+\n| **Money   | ``+``, ``-``  | Money     | N/A       | Money           |\n+ AAA**     +---------------+-----------+-----------+-----------------+\n|           | ``*``         | N/A       | N/A       | Money           |\n+           +---------------+-----------+-----------+-----------------+\n|           | ``/``, ``//`` | Decimal   | N/A       | Money           |\n+           +---------------+-----------+-----------+-----------------+\n|           | ``\u003e``, ``\u003e=`` | Compares  | N/A       | N/A             |\n|           | ``\u003c``, ``\u003c=`` | amount.   |           |                 |\n+           +---------------+           +-----------+-----------------+\n|           | ``==``        |           | False     | False           |\n|           |               |           |           |                 |\n+-----------+---------------+-----------+-----------+-----------------+\n\nArithmetic operations with floats are not directly supported. If you need to operate with floats, you must first convert the float to a Decimal, or the Money object to a float (i.e. float(m)). Please be aware of the `issues and limitations of floating point arithmetics \u003chttps://docs.python.org/3/tutorial/floatingpoint.html\u003e`_.\n\n\nCurrency presets\n----------------\n\nIf you use fixed currencies in your code, you may find convenient to create currency-preset Money subclasses:\n\n.. code:: python\n\n    class EUR(Money):\n        def __init__(self, amount='0'):\n            super().__init__(amount=amount, currency='EUR')\n    \n    price = EUR('9.99')\n\n\nFormatting\n==========\n\nMoney objects are printed by default with en_US formatting and the currency code.\n\n.. code:: python\n\n    \u003e\u003e\u003e m = Money('1234.567', 'EUR')\n    \u003e\u003e\u003e str(m)\n    'EUR 1,234.57'\n\nUse ``format(locale=LC_NUMERIC, pattern=None, currency_digits=True, format_type='standard')`` for locale-aware formatting with currency expansion. ``format()`` relies on ``babel.numbers.format_currency()``, and **requires Babel** to be installed.\n\n.. code:: python\n\n    \u003e\u003e\u003e m = Money('1234.567', 'USD')\n    \u003e\u003e\u003e m.format('en_US')\n    '$1,234.57'\n    \u003e\u003e\u003e m.format('es_ES')\n    '1.234,57\\xa0$'\n\nThe character ``\\xa0`` is an unicode non-breaking space. If no locale is passed, Babel will use your system's locale. You can also provide a specific pattern to format():\n\n.. code:: python\n\n    \u003e\u003e\u003e m = Money('-1234.567', 'USD')\n    \u003e\u003e\u003e # Regular US format:\n    \u003e\u003e\u003e m.format('en_US', '¤#,##0.00') \n    '-$1,234.57'\n    \u003e\u003e\u003e # Custom negative format:\n    \u003e\u003e\u003e m.format('en_US', '¤#,##0.00;\u003c¤#,##0.00\u003e')\n    '\u003c$1,234.57\u003e'\n    \u003e\u003e\u003e # Spanish format, full currency name:\n    \u003e\u003e\u003e m.format('es_ES', '#,##0.00 ¤¤¤')\n    '-1.234,57 dólares estadounidenses'\n    \u003e\u003e\u003e # Same as above, but rounding (overriding currency natural format):\n    \u003e\u003e\u003e m.format('es_ES', '#0 ¤¤¤', currency_digits=False)\n    '-1235 dólares estadounidenses'\n\nFor more details on formatting see `Babel docs on currency formatting \u003chttp://babel.pocoo.org/en/latest/api/numbers.html#babel.numbers.format_currency\u003e`_. To learn more about the formatting pattern syntax check out `Unicode TR35 \u003chttp://www.unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns\u003e`_.\n\nCurrency exchange\n=================\n\nCurrency exchange works by \"installing\" a **backend** class that implements the abstract base class (`abc \u003chttps://docs.python.org/3/library/abc.html\u003e`_) ``money.exchange.BackendBase``. Its API is exposed through ``money.xrates``, along with setup functions ``xrates.install(pythonpath)``, ``xrates.uninstall()``, and ``xrates.backend_name``.\n\nA simple proof-of-concept backend ``money.exchange.SimpleBackend`` is included:\n\n.. code:: python\n\n    from decimal import Decimal\n    from money import Money, xrates\n\n    xrates.install('money.exchange.SimpleBackend')\n    xrates.base = 'USD'\n    xrates.setrate('AAA', Decimal('2'))\n    xrates.setrate('BBB', Decimal('8'))\n    \n    a = Money(1, 'AAA')\n    b = Money(1, 'BBB')\n    \n    assert a.to('BBB') == Money('4', 'BBB')\n    assert b.to('AAA') == Money('0.25', 'AAA')\n    assert a + b.to('AAA') == Money('1.25', 'AAA')\n\n\n\nXMoney\n======\n\nYou can use ``money.XMoney`` (a subclass of Money), for automatic currency conversion while adding, subtracting, and dividing money objects (+, +=, -, -=, /, //). This is useful when aggregating lots of money objects with heterogeneous currencies. The currency of the leftmost object has priority.\n\n.. code:: python\n\n    from money import XMoney\n    \n    # Register backend and rates as above...\n    \n    a = XMoney(1, 'AAA')\n    b = XMoney(1, 'BBB')\n    \n    assert sum([a, b]) == XMoney('1.25', 'AAA')\n\n\nExceptions\n==========\n\nFound in ``money.exceptions``.\n\n``MoneyException(Exception)``\n    Base class for all exceptions.\n\n``CurrencyMismatch(MoneyException, ValueError)``\n    Thrown when mixing different currencies, e.g. ``Money(2, 'EUR') + Money(2, 'USD')``. Money objects must be converted first to the same currency, or XMoney could be used for automatic conversion.\n\n``InvalidOperandType(MoneyException, TypeError)``\n    Thrown when attempting invalid operations, e.g. multiplication between money objects.\n\n``ExchangeError(MoneyException)``\n    Base class for exchange exceptions.\n\n``ExchangeBackendNotInstalled(ExchangeError)``\n    Thrown if a conversion is attempted, but there is no backend available.\n\n``ExchangeRateNotFound(ExchangeError)``\n    The installed backend failed to provide a suitable exchange rate between the origin and target currencies.\n\n\nHierarchy\n---------\n\n* ``MoneyException``\n    * ``CurrencyMismatch``\n    * ``InvalidOperandType``\n    * ``ExchangeError``\n        * ``ExchangeBackendNotInstalled``\n        * ``ExchangeRateNotFound``\n\n\n\n.. _python-differences:\n\nDifferences between Python versions\n===================================\n\n.. list-table::\n    :header-rows: 1\n    :stub-columns: 1\n    \n    * - Expression\n      - Python 2.x\n      - Python 3.x\n    \n    * - ``round(Money('2.5', 'EUR'))``\n      - Returns ``3.0``, a **float** rounded amount **away from zero**.\n      - Returns ``EUR 2``, a **Money object** with rounded amount to the **nearest even**.\n    \n    * - ``Money('0', 'EUR').amount \u003c '0'``\n      - Returns ``True``. This is the weird but expected behaviour in Python 2.x when comparing Decimal objects with non-numerical objects (Note the '0' is a string). `See note in docs \u003chttps://docs.python.org/2/library/stdtypes.html#comparisons\u003e`_.\n      - TypeError: unorderable types: decimal.Decimal() \u003e str()\n\n\n\nDesign decisions\n================\n\nThere are several design decisions in *money* that differ from currently available money class implementations:\n\nLocalization\n------------\n\nDo not keep any kind of locale conventions database inside this package. Locale conventions are extensive and change over time; keeping track of them is a project of its own. There is already such a project and database (the Unicode Common Locale Data Repository), and an excellent python API for it: `Babel \u003chttps://pypi.python.org/pypi/Babel\u003e`_.\n\nCurrency\n--------\n\nThere is no need for a currency class. A currency is fully identified by its ISO 4217 code, and localization or exchange rates data are expected to be centralized as databases/services because of their changing nature.\n\nAlso:\n\n+ **Modulo operator (%)**: do not override to mean \"percentage\".\n+ **Numeric type**: you **can** mix numbers and money in binary operations, and objects evaluate to False if their amount is zero.\n+ **Global default currency**: subclassing is a safer solution.\n\n\nContributions\n=============\n\nContributions are welcome. You can use the `regular github mechanisms \u003chttps://help.github.com/\u003e`_.\n\nTo test your changes you will need `tox \u003chttps://pypi.python.org/pypi/tox\u003e`_ and python 2.7, 3.4, and 3.5. Simply cd to the package root (by setup.py) and run ``tox``.\n\n\nLicense\n=======\n\nmoney is released under the **MIT license**, which can be found in the file ``LICENSE``.\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlospalol%2Fmoney","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarlospalol%2Fmoney","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlospalol%2Fmoney/lists"}