Compare commits

..

No commits in common. "main" and "misc-updates" have entirely different histories.

23 changed files with 404 additions and 377 deletions

View file

@ -1,13 +0,0 @@
# SPDX-FileCopyrightText: 2021 Adafruit Industries
#
# SPDX-License-Identifier: MIT
Thank you for contributing! Before you submit a pull request, please read the following.
Make sure any changes you're submitting are in line with the CircuitPython Design Guide, available here: https://docs.circuitpython.org/en/latest/docs/design_guide.html
If your changes are to documentation, please verify that the documentation builds locally by following the steps found here: https://adafru.it/build-docs
Before submitting the pull request, make sure you've run Pylint and Black locally on your code. You can do this manually or using pre-commit. Instructions are available here: https://adafru.it/check-your-code
Please remove all of this text before submitting. Include an explanation or list of changes included in your PR, as well as, if applicable, a link to any related issues.

View file

@ -8,9 +8,90 @@ on: [pull_request, push]
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Run Build CI workflow
uses: adafruit/workflows-circuitpython-libs/build@main
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Translate Repo Name For Build Tools filename_prefix
id: repo-name
run: |
echo ::set-output name=repo-name::$(
echo ${{ github.repository }} |
awk -F '\/' '{ print tolower($2) }' |
tr '_' '-'
)
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
package-prefix: jepler_udecimal
python-version: 3.7
- name: Versions
run: |
python3 --version
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install dependencies
# (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.)
run: |
source actions-ci/install.sh
- name: Pip install pylint, Sphinx, pre-commit
run: |
pip install --force-reinstall pylint Sphinx sphinx-rtd-theme pre-commit sphinx-autoapi
- name: Library version
run: git describe --dirty --always --tags
- name: Pre-commit hooks
run: |
pre-commit run --all-files
- name: PyLint
run: |
pylint $( find . -path './jepler*.py' )
([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace $( find . -path "./examples/*.py" ))
- name: Clone and build circuitpython unix port
run: |
set -e
[ -e circuitpython/py/py.mk ] || git clone --depth=1 https://github.com/adafruit/circuitpython
[ -e circuitpython/lib/libffi/autogen.sh ] || (cd circuitpython && git submodule update --init lib/libffi lib/axtls lib/berkeley-db-1.xx tools/huffman lib/uzlib extmod/ulab)
[ -x circuitpython/ports/unix/micropython ] || (
make -C circuitpython/mpy-cross -j$(nproc)
make -C circuitpython/ports/unix -j$(nproc) deplibs
make -C circuitpython/ports/unix -j$(nproc) DEBUG=1 STRIP=:
)
- name: Unit Test
run: |
python -m jepler_udecimal.test
if ! env MICROPYPATH=. PYTHONPATH=. MICROPY_MICROPYTHON=circuitpython/ports/unix/micropython circuitpython/tests/run-tests -d examples; then
for exp in *.exp; do
testbase=$(basename $exp .exp);
echo -e "\nFAILURE $testbase";
diff -u $testbase.exp $testbase.out;
done
fi
- name: Build assets
run: circuitpython-build-bundles --package_folder_prefix jepler --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Build docs
working-directory: docs
run: sphinx-build -E -W -b html . _build/html
- name: Archive bundles
uses: actions/upload-artifact@v2
with:
name: bundles
path: ${{ github.workspace }}/bundles/
- name: Check For setup.py
id: need-pypi
run: |
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Build Python package
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: |
pip install --upgrade setuptools wheel twine readme_renderer testresources
python setup.py sdist
python setup.py bdist_wheel --universal
twine check dist/*

View file

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2021 Scott Shawcroft for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: Failure help text
on:
workflow_run:
workflows: ["Build CI"]
types:
- completed
jobs:
post-help:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }}
steps:
- name: Post comment to help
uses: adafruit/circuitpython-action-library-ci-failed@v1

85
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,85 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: Release Actions
on:
release:
types: [published]
jobs:
upload-release-assets:
runs-on: ubuntu-20.04
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Translate Repo Name For Build Tools filename_prefix
id: repo-name
run: |
echo ::set-output name=repo-name::$(
echo ${{ github.repository }} |
awk -F '\/' '{ print tolower($2) }' |
tr '_' '-'
)
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Versions
run: |
python3 --version
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install deps
run: |
source actions-ci/install.sh
- name: Build assets
run: circuitpython-build-bundles --package_folder_prefix jepler --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Upload Release Assets
# the 'official' actions version does not yet support dynamically
# supplying asset names to upload. @csexton's version chosen based on
# discussion in the issue below, as its the simplest to implement and
# allows for selecting files with a pattern.
# https://github.com/actions/upload-release-asset/issues/4
#uses: actions/upload-release-asset@v1.0.1
uses: csexton/release-asset-action@master
with:
pattern: "bundles/*"
github-token: ${{ secrets.GITHUB_TOKEN }}
upload-pypi:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v1
- name: Check For setup.py
id: need-pypi
run: |
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Set up Python
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.pypi_token }}
run: |
python setup.py sdist
twine upload dist/*

View file

@ -1,20 +0,0 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: GitHub Release Actions
on:
release:
types: [published]
jobs:
upload-release-assets:
runs-on: ubuntu-latest
steps:
- name: Run GitHub Release CI workflow
uses: adafruit/workflows-circuitpython-libs/release-gh@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
upload-url: ${{ github.event.release.upload_url }}
package-prefix: jepler_udecimal

View file

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: PyPI Release Actions
on:
release:
types: [published]
jobs:
upload-release-assets:
runs-on: ubuntu-latest
steps:
- name: Run PyPI Release CI workflow
uses: adafruit/workflows-circuitpython-libs/release-pypi@main
with:
pypi-username: __token__
pypi-password: ${{ secrets.pypi_token }}

1
.gitignore vendored
View file

@ -20,4 +20,3 @@ docs/api
circuitpython
/*.exp
/*.out
*/__version__.py

View file

@ -3,44 +3,17 @@
# SPDX-License-Identifier: Unlicense
repos:
- repo: https://github.com/psf/black
rev: 25.1.0
- repo: https://github.com/python/black
rev: 19.10b0
hooks:
- id: black
- repo: https://github.com/fsfe/reuse-tool
rev: v5.0.2
rev: v0.12.1
hooks:
- id: reuse
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v2.3.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/pylint
rev: v3.3.4
hooks:
- id: pylint
name: lint (examples)
types: [python]
files: ^examples/
args:
- --disable=missing-docstring,invalid-name
- id: pylint
name: lint (code)
types: [python]
exclude: "^(docs/|examples/|setup.py$)"
- repo: local
hooks:
- id: mypy
name: mypy
entry: "mypy --no-warn-unused-ignores jepler_udecimal"
language: python
additional_dependencies: ["mypy==0.910"]
types: [python]
# use require_serial so that script
# is only called once per commit
require_serial: true
# Print the number of files as a sanity-check
verbose: true
pass_filenames: false

View file

@ -56,7 +56,7 @@ confidence=
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
disable=raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,import-error,consider-using-f-string,unnecessary-dunder-call
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
@ -226,6 +226,12 @@ max-line-length=100
# Maximum number of lines in a module
max-module-lines=1000
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
@ -252,22 +258,38 @@ min-similarity-lines=4
[BASIC]
# Naming hint for argument names
argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct argument names
argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Naming hint for attribute names
attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct attribute names
attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# Naming hint for class attribute names
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming hint for class names
# class-name-hint=[A-Z_][a-zA-Z0-9]+$
class-name-hint=[A-Z_][a-zA-Z0-9_]+$
# Regular expression matching correct class names
# class-rgx=[A-Z_][a-zA-Z0-9]+$
class-rgx=[A-Z_][a-zA-Z0-9_]+$
# Naming hint for constant names
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
@ -275,6 +297,9 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# ones are exempt.
docstring-min-length=-1
# Naming hint for function names
function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct function names
function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
@ -285,12 +310,21 @@ good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Naming hint for inline iteration names
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for method names
method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct method names
method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
@ -306,6 +340,9 @@ no-docstring-rgx=^_
# to this list to register other decorators that produce valid properties.
property-classes=abc.abstractproperty
# Naming hint for variable names
variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct variable names
variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
@ -391,3 +428,10 @@ max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=1
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

View file

@ -1,19 +0,0 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
build:
os: ubuntu-20.04
tools:
python: "3"
python:
install:
- requirements: docs/requirements.txt
- requirements: requirements.txt

7
.readthedocs.yml Normal file
View file

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
python:
version: 3
requirements_file: requirements.txt

View file

@ -17,10 +17,6 @@ Introduction
:target: https://github.com/psf/black
:alt: Code Style: Black
.. image:: https://results.pre-commit.ci/badge/github/jepler/Jepler_CircuitPython_udecimal/main.svg
:target: https://results.pre-commit.ci/latest/github/jepler/Jepler_CircuitPython_udecimal/main
:alt: pre-commit.ci status
Reduced version of the decimal library for CircuitPython

View file

@ -9,12 +9,17 @@ echo "=== Create and set up virtual environment"
. .env/bin/activate
echo "=== Install requirements"
pip3 install wheel
pip3 install -r requirements_dev.txt
pip3 install -r requirements.txt
echo "=== Run pre-commit"
pre-commit run --all-files
echo "=== Run pylint"
pylint jepler_udecimal
if [ -d examples ]; then
pylint --disable=missing-docstring,invalid-name,bad-whitespace examples
fi
echo "=== Clone and build circuitpython unix port"
[ -e circuitpython/py/py.mk ] || git clone --shallow-since=2021-07-01 https://github.com/adafruit/circuitpython
[ -e circuitpython/py/py.mk ] || git clone --depth=1 https://github.com/adafruit/circuitpython
[ -e circuitpython/lib/libffi/autogen.sh ] || (cd circuitpython && git submodule update --init lib/libffi lib/axtls lib/berkeley-db-1.xx tools/huffman lib/uzlib extmod/ulab)
[ -x circuitpython/ports/unix/micropython ] || (
make -C circuitpython/mpy-cross -j$(nproc)
@ -25,14 +30,12 @@ make -C circuitpython/ports/unix -j$(nproc) DEBUG=1 STRIP=:
echo "=== Run tests"
python -m jepler_udecimal.test
run-tests () {
env MICROPYPATH=. PYTHONPATH=. MICROPY_MICROPYTHON=circuitpython/ports/unix/micropython circuitpython/tests/run-tests.py "$@"
}
run-tests --clean-failures
if ! run-tests -d examples; then
run-tests --print-failures
exit 1
if ! env MICROPYPATH=. PYTHONPATH=. MICROPY_MICROPYTHON=circuitpython/ports/unix/micropython circuitpython/tests/run-tests -d examples; then
for exp in *.exp; do
testbase=$(basename $exp .exp);
echo -e "\nFAILURE $testbase";
diff -u $testbase.exp $testbase.out;
done
fi
PYTHONPATH=. python examples/test_udecimal.py > test_udecimal.exp

View file

@ -68,7 +68,7 @@ release = "1.0"
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@ -109,6 +109,18 @@ napoleon_numpy_docstring = False
#
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if not on_rtd: # only import and set the theme if we're building docs locally
try:
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except:
html_theme = "default"
html_theme_path = ["."]
else:
html_theme_path = ["."]
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".

View file

@ -1,6 +0,0 @@
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
sphinx>=4.0.0
sphinx-autoapi

View file

@ -103,9 +103,3 @@ try:
except Exception as e:
print("exception")
print(Decimal("2").atan())
print(Decimal("1").asin())
print(Decimal("-1").asin())
print(Decimal(".5").asin())
print(Decimal("1").acos())
print(Decimal("-1").acos())
print(Decimal(".5").asin())

View file

@ -1,69 +0,0 @@
# SPDX-FileCopyrightText: © 2004 Python Software Foundation. <https://www.python.org/psf/>
#
# SPDX-License-Identifier: Python-2.0
# All rights reserved.
# pylint: disable=redefined-builtin,too-many-arguments,too-many-locals
from jepler_udecimal import Decimal
def moneyfmt(
value, *, places=2, curr="", sep=",", dp=".", pos="", neg="-", trailneg=""
):
"""Convert Decimal to a money formatted string.
places: required number of places after the decimal point
curr: optional currency symbol before the sign (may be blank)
sep: optional grouping separator (comma, period, space, or blank)
dp: decimal point indicator (comma or period)
only specify as blank when places is zero
pos: optional sign for positive numbers: '+', space or blank
neg: optional sign for negative numbers: '-', '(', space or blank
trailneg:optional trailing minus indicator: '-', ')', space or blank
>>> d = Decimal('-1234567.8901')
>>> moneyfmt(d, curr='$')
'-$1,234,567.89'
>>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
'1.234.568-'
>>> moneyfmt(d, curr='$', neg='(', trailneg=')')
'($1,234,567.89)'
>>> moneyfmt(Decimal(123456789), sep=' ')
'123 456 789.00'
>>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
'<0.02>'
"""
q = Decimal(10) ** -places # 2 places --> '0.01'
sign, digits, _ = value.quantize(q).as_tuple()
result = []
digits = list(map(str, digits))
build, next = result.append, digits.pop
if sign:
build(trailneg)
for i in range(places):
build(next() if digits else "0")
if places:
build(dp)
if not digits:
build("0")
i = 0
while digits:
build(next())
i += 1
if i == 3 and digits:
i = 0
build(sep)
build(curr)
build(neg if sign else pos)
return "".join(reversed(result))
if __name__ == "__main__":
d = Decimal("-1234567.8901")
print(moneyfmt(d, curr="$"))
print(moneyfmt(d, places=0, sep=".", dp="", neg="", trailneg="-"))
print(moneyfmt(d, curr="$", neg="(", trailneg=")"))
print(moneyfmt(Decimal(123456789), sep=" "))
print(moneyfmt(Decimal("-0.02"), neg="<", trailneg=">"))

View file

@ -13,7 +13,7 @@
# Adapted to CircuitPython by Jeff Epler <jepler@gmail.com>
#
# pylint: disable=line-too-long,superfluous-parens,too-many-lines,redefined-builtin,bare-except
# pylint: disable=protected-access,invalid-name,self-cls-assignment,no-else-return,no-else-raise,too-many-public-methods,useless-object-inheritance,invalid-unary-operand-type,unused-argument,too-many-branches,too-many-return-statements,no-else-break,unused-variable,arguments-differ,missing-function-docstring,inconsistent-return-statements,global-statement,too-many-statements,attribute-defined-outside-init,consider-using-in,dangerous-default-value,using-constant-test,too-many-locals,too-many-arguments,keyword-arg-before-vararg
# pylint: disable=protected-access,invalid-name,no-self-use,self-cls-assignment,no-else-return,no-else-raise,too-many-public-methods,useless-object-inheritance,invalid-unary-operand-type,unused-argument,too-many-branches,too-many-return-statements,no-else-break,unused-variable,arguments-differ,missing-function-docstring,inconsistent-return-statements,global-statement,too-many-statements,attribute-defined-outside-init,consider-using-in,dangerous-default-value,using-constant-test,too-many-locals,too-many-arguments,keyword-arg-before-vararg
"""
Reduced version of the decimal library for CircuitPython. It runs on
CircuitPython as well as standard Python, though you should probably
@ -141,10 +141,7 @@ try:
DecimalTuple = _namedtuple("DecimalTuple", "sign digits exponent")
except ImportError:
def DecimalTuple(*args): # type: ignore
return args
DecimalTuple = lambda *args: args
# Rounding
ROUND_DOWN = "ROUND_DOWN"
@ -157,7 +154,7 @@ ROUND_HALF_DOWN = "ROUND_HALF_DOWN"
ROUND_05UP = "ROUND_05UP"
try:
NotImplemented # pylint: disable=used-before-assignment
NotImplemented
except NameError:
NotImplemented = object()
@ -172,6 +169,7 @@ if sys.implementation.name == "circuitpython":
else:
return m, (1 << (-e))
else:
_as_integer_ratio = float.as_integer_ratio
@ -694,7 +692,7 @@ class Decimal(object):
context = getcontext()
context._raise_error(
FloatOperation,
"strict semantics for mixing floats and Decimals are enabled",
"strict semantics for mixing floats and Decimals are " "enabled",
)
value = Decimal.from_float(value)
self._exp = value._exp
@ -741,7 +739,7 @@ class Decimal(object):
sign = 1
n, d = _as_integer_ratio(abs(f))
k = d.bit_length() - 1
coeff = str(n * 5**k)
coeff = str(n * 5 ** k)
else:
raise TypeError("argument must be int or float.")
@ -1351,9 +1349,9 @@ class Decimal(object):
op1 = _WorkRep(self)
op2 = _WorkRep(other)
if shift >= 0:
coeff, remainder = divmod(op1.int * 10**shift, op2.int)
coeff, remainder = divmod(op1.int * 10 ** shift, op2.int)
else:
coeff, remainder = divmod(op1.int, op2.int * 10**-shift)
coeff, remainder = divmod(op1.int, op2.int * 10 ** -shift)
if remainder:
# result is not exact; adjust to ensure correct rounding
if coeff % 5 == 0:
@ -1394,7 +1392,7 @@ class Decimal(object):
else:
op2.int *= 10 ** (op2.exp - op1.exp)
q, r = divmod(op1.int, op2.int)
if q < 10**context.prec:
if q < 10 ** context.prec:
return (
_dec_from_triple(sign, str(q), 0),
_dec_from_triple(self._sign, str(r), ideal_exp),
@ -1554,7 +1552,7 @@ class Decimal(object):
r -= op2.int
q += 1
if q >= 10**context.prec:
if q >= 10 ** context.prec:
return context._raise_error(DivisionImpossible)
# result has same sign as self unless r is negative
@ -1621,7 +1619,7 @@ class Decimal(object):
raise OverflowError("Cannot convert infinity to integer")
s = (-1) ** self._sign
if self._exp >= 0:
return s * int(self._int) * 10**self._exp
return s * int(self._int) * 10 ** self._exp
else:
return s * int(self._int[: self._exp] or "0")
@ -1798,16 +1796,16 @@ class Decimal(object):
else:
return -self._round_down(prec)
_pick_rounding_function = {
ROUND_DOWN: _round_down,
ROUND_UP: _round_up,
ROUND_HALF_UP: _round_half_up,
ROUND_HALF_DOWN: _round_half_down,
ROUND_HALF_EVEN: _round_half_even,
ROUND_CEILING: _round_ceiling,
ROUND_FLOOR: _round_floor,
ROUND_05UP: _round_05up,
}
_pick_rounding_function = dict(
ROUND_DOWN=_round_down,
ROUND_UP=_round_up,
ROUND_HALF_UP=_round_half_up,
ROUND_HALF_DOWN=_round_half_down,
ROUND_HALF_EVEN=_round_half_even,
ROUND_CEILING=_round_ceiling,
ROUND_FLOOR=_round_floor,
ROUND_05UP=_round_05up,
)
def __round__(self, n=None):
"""Round self to the nearest integer, or to a given precision.
@ -1983,7 +1981,7 @@ class Decimal(object):
ye += 1
if ye < 0:
return None
exponent = xe * 10**ye
exponent = xe * 10 ** ye
if y.sign == 1:
exponent = -exponent
# if other is a nonnegative integer, use ideal exponent
@ -2042,13 +2040,13 @@ class Decimal(object):
if e > emax:
return None
xc = 5**e
xc = 5 ** e
elif last_digit == 5:
# e >= log_5(xc) if xc is a power of 5; we have
# equality all the way up to xc=5**2658
e = _nbits(xc) * 28 // 65
xc, remainder = divmod(5**e, xc)
xc, remainder = divmod(5 ** e, xc)
if remainder:
return None
while xc % 5 == 0:
@ -2069,18 +2067,18 @@ class Decimal(object):
if e > emax:
return None
xc = 2**e
xc = 2 ** e
else:
return None
if xc >= 10**p:
if xc >= 10 ** p:
return None
xe = -e - xe
return _dec_from_triple(0, str(xc), xe)
# now y is positive; find m and n such that y = m/n
if ye >= 0:
m, n = yc * 10**ye, 1
m, n = yc * 10 ** ye, 1
else:
if xe != 0 and len(str(abs(yc * xe))) <= -ye:
return None
@ -2124,9 +2122,9 @@ class Decimal(object):
# 10**p and the result is not representable.
if xc > 1 and m > p * 100 // _log10_lb(xc):
return None
xc = xc**m
xc = xc ** m
xe *= m
if xc > 10**p:
if xc > 10 ** p:
return None
# by this point the result *is* exactly representable
@ -2571,15 +2569,15 @@ class Decimal(object):
# rescale so that c has exactly prec base 100 'digits'
shift = prec - l
if shift >= 0:
c *= 100**shift
c *= 100 ** shift
exact = True
else:
c, remainder = divmod(c, 100**-shift)
c, remainder = divmod(c, 100 ** -shift)
exact = not remainder
e -= shift
# find n = floor(sqrt(c)) using Newton's method
n = 10**prec
n = 10 ** prec
while True:
q = c // n
if n <= q:
@ -2592,9 +2590,9 @@ class Decimal(object):
# result is exact; rescale to use ideal exponent e
if shift >= 0:
# assert n % 10**shift == 0
n //= 10**shift
n //= 10 ** shift
else:
n *= 10**-shift
n *= 10 ** -shift
e += shift
else:
# result is not exact; fix last digit as described above
@ -2814,7 +2812,7 @@ class Decimal(object):
return s.compare_total(o)
def copy_abs(self):
"""Returns a copy with the sign set to 0."""
"""Returns a copy with the sign set to 0. """
return _dec_from_triple(0, self._int, self._exp, self._is_special)
def copy_negate(self):
@ -2978,11 +2976,11 @@ class Decimal(object):
c, e = op.int, op.exp
if adj == 0:
# 1 < self < 10
num = str(c - 10**-e)
num = str(c - 10 ** -e)
den = str(c)
return len(num) - len(den) - (num < den)
# adj == -1, 0.1 <= self < 1
return e + len(str(10**-e - c)) - 1
return e + len(str(10 ** -e - c)) - 1
def ln(self, context=None):
"""Returns the natural (base e) logarithm of self."""
@ -3056,11 +3054,11 @@ class Decimal(object):
c, e = op.int, op.exp
if adj == 0:
# 1 < self < 10
num = str(c - 10**-e)
num = str(c - 10 ** -e)
den = str(231 * c)
return len(num) - len(den) - (num < den) + 2
# adj == -1, 0.1 <= self < 1
num = str(10**-e - c)
num = str(10 ** -e - c)
return len(num) + e - (num < "231") - 1
def log10(self, context=None):
@ -3114,7 +3112,7 @@ class Decimal(object):
return ans
def logb(self, context=None):
"""Returns the exponent of the magnitude of self's MSD.
""" Returns the exponent of the magnitude of self's MSD.
The result is the integer which is the exponent of the magnitude
of the most significant digit of self (as though it were truncated
@ -3326,8 +3324,8 @@ def _dec_from_triple(sign, coefficient, exponent, special=False):
class _ContextManager(object):
"""Context manager class to support localcontext().
Sets a copy of the supplied context in __enter__() and restores
the previous decimal context in __exit__()
Sets a copy of the supplied context in __enter__() and restores
the previous decimal context in __exit__()
"""
def __init__(self, new_context):
@ -3357,7 +3355,7 @@ class Context(object):
:param bool clamp: If true, change exponents if too high
"""
def __init__( # pylint: disable=too-many-positional-arguments
def __init__(
self,
prec=None,
rounding=None,
@ -3577,7 +3575,7 @@ class Context(object):
self._ignored_flags.remove(flag)
# We inherit object.__hash__, so we must deny this explicitly
__hash__ = None # type: ignore
__hash__ = None
def Etiny(self):
"""Returns Etiny (= Emin - prec + 1)"""
@ -3615,7 +3613,7 @@ class Context(object):
if isinstance(num, str) and (num != num.strip() or "_" in num):
return self._raise_error(
ConversionSyntax,
"trailing or leading whitespace and underscores are not permitted.",
"trailing or leading whitespace and " "underscores are not permitted.",
)
d = Decimal(num, context=self)
@ -4204,7 +4202,7 @@ class Context(object):
return a.log10(context=self)
def logb(self, a):
"""Returns the exponent of the magnitude of the operand's MSD.
""" Returns the exponent of the magnitude of the operand's MSD.
The result is the integer which is the exponent of the magnitude
of the most significant digit of the operand (as though the
@ -4904,7 +4902,7 @@ _nbits = int.bit_length
def _decimal_lshift_exact(n, e):
"""Given integers n and e, return n * 10**e if it's an integer, else None.
""" Given integers n and e, return n * 10**e if it's an integer, else None.
The computation is designed to avoid computing large powers of 10
unnecessarily.
@ -4917,12 +4915,12 @@ def _decimal_lshift_exact(n, e):
if n == 0:
return 0
elif e >= 0:
return n * 10**e
return n * 10 ** e
else:
# val_n = largest power of 10 dividing n.
str_n = str(abs(n))
val_n = len(str_n) - len(str_n.rstrip("0"))
return None if val_n < -e else n // 10**-e
return None if val_n < -e else n // 10 ** -e
def _sqrt_nearest(n, a):
@ -5025,12 +5023,12 @@ def _dlog10(c, e, p):
f = e + l - (e + l >= 1)
if p > 0:
M = 10**p
M = 10 ** p
k = e + p - f
if k >= 0:
c *= 10**k
c *= 10 ** k
else:
c = _div_nearest(c, 10**-k)
c = _div_nearest(c, 10 ** -k)
log_d = _ilog(c, M) # error < 5 + 22 = 27
log_10 = _log10_digits(p) # error < 1
@ -5038,7 +5036,7 @@ def _dlog10(c, e, p):
log_tenpower = f * M # exact
else:
log_d = 0 # error < 2.31
log_tenpower = _div_nearest(f, 10**-p) # error < 0.5
log_tenpower = _div_nearest(f, 10 ** -p) # error < 0.5
return _div_nearest(log_tenpower + log_d, 100)
@ -5062,12 +5060,12 @@ def _dlog(c, e, p):
if p > 0:
k = e + p - f
if k >= 0:
c *= 10**k
c *= 10 ** k
else:
c = _div_nearest(c, 10**-k) # error of <= 0.5 in c
c = _div_nearest(c, 10 ** -k) # error of <= 0.5 in c
# _ilog magnifies existing error in c by a factor of at most 10
log_d = _ilog(c, 10**p) # error < 5 + 22 = 27
log_d = _ilog(c, 10 ** p) # error < 5 + 22 = 27
else:
# p <= 0: just approximate the whole thing by 0; error < 2.31
log_d = 0
@ -5078,7 +5076,7 @@ def _dlog(c, e, p):
if p + extra >= 0:
# error in f * _log10_digits(p+extra) < |f| * 1 = |f|
# after division, error < |f|/10**extra + 0.5 < 10 + 0.5 < 11
f_log_ten = _div_nearest(f * _log10_digits(p + extra), 10**extra)
f_log_ten = _div_nearest(f * _log10_digits(p + extra), 10 ** extra)
else:
f_log_ten = 0
else:
@ -5191,16 +5189,16 @@ def _dexp(c, e, p):
# rounding down
shift = e + q
if shift >= 0:
cshift = c * 10**shift
cshift = c * 10 ** shift
else:
cshift = c // 10**-shift
cshift = c // 10 ** -shift
quot, rem = divmod(cshift, _log10_digits(q))
# reduce remainder back to original precision
rem = _div_nearest(rem, 10**extra)
rem = _div_nearest(rem, 10 ** extra)
# error in result of _iexp < 120; error after division < 0.62
return _div_nearest(_iexp(rem, 10**p), 1000), quot - p + 3
return _div_nearest(_iexp(rem, 10 ** p), 1000), quot - p + 3
def _dpower(xc, xe, yc, ye, p):
@ -5227,9 +5225,9 @@ def _dpower(xc, xe, yc, ye, p):
# compute product y*log(x) = yc*lxc*10**(-p-b-1+ye) = pc*10**(-p-1)
shift = ye - b
if shift >= 0:
pc = lxc * yc * 10**shift
pc = lxc * yc * 10 ** shift
else:
pc = _div_nearest(lxc * yc, 10**-shift)
pc = _div_nearest(lxc * yc, 10 ** -shift)
if pc == 0:
# we prefer a result that isn't exactly 1; this makes it
@ -5237,7 +5235,7 @@ def _dpower(xc, xe, yc, ye, p):
if (len(str(xc)) + xe >= 1) == (yc > 0): # if x**y > 1:
coeff, exp = 10 ** (p - 1) + 1, 1 - p
else:
coeff, exp = 10**p - 1, -p
coeff, exp = 10 ** p - 1, -p
else:
coeff, exp = _dexp(pc, -(p + 1), p + 1)
coeff = _div_nearest(coeff, 10)
@ -5350,12 +5348,7 @@ BasicContext = Context(
flags=[],
)
ExtendedContext = Context(
prec=9,
rounding=ROUND_HALF_EVEN,
traps=[],
flags=[],
)
ExtendedContext = Context(prec=9, rounding=ROUND_HALF_EVEN, traps=[], flags=[],)
##### crud for parsing strings #############################################
@ -5375,7 +5368,7 @@ ExtendedContext = Context(
try:
import re
except:
import ure as re # type: ignore
import ure as re
_parser = re.compile( # A numeric string consists of:
r"([-+])?" # an optional sign, followed by either... # 1

View file

@ -34,7 +34,7 @@ Here are some examples of using utrig:
>>> Decimal('.7').atan()
Decimal('0.6107259643892086165437588765')
>>> Decimal('.1').acos()
Decimal('1.470628905633336822885798512')
Decimal('1.47062890563333682288579851219')
>>> Decimal('-.1').asin()
Decimal('-0.1001674211615597963455231795')
>>> Decimal('.4').tan()
@ -43,11 +43,6 @@ Decimal('0.4227932187381617619816354272')
Decimal('0.8775825618903727161162815826')
>>> Decimal('.6').sin()
Decimal('0.5646424733950353572009454457')
>>> Decimal('1').asin()
Decimal('1.570796326794896619231321692')
>>> Decimal('-1').acos()
Decimal('3.141592653589793238462643383')
"""
@ -203,12 +198,7 @@ def asin(x, context=None):
with localcontext(context) as ctx:
ctx.prec += 2
if x == 1:
r = atan(Decimal(1)) * 2 # pi * 1/2 radians
elif x == -1:
r = atan(Decimal(1)) * -2 # pi * -1/2 radians
else:
r = atan(x / (1 - x * x).sqrt())
r = atan(x / (1 - x * x).sqrt())
return r / 1
@ -228,15 +218,10 @@ def acos(x, context=None):
with localcontext(context) as ctx:
ctx.prec += 2
if x == 1:
r = Decimal(0) # 0 radians
elif x == -1:
r = atan(Decimal(1)) * 4 # pi radians
else:
r = atan((1 - x * x).sqrt() / x)
r = atan((1 - x * x).sqrt() / x)
if r < 0:
r += 4 * atan(1)
return r / 1
return r
for name in __all__:

View file

@ -1,17 +0,0 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2020 jepler for Unpythonic Networks
#
# SPDX-License-Identifier: MIT
pre-commit
recommonmark==0.6.0
sphinx
sphinx-autoapi
sphinxcontrib-svg2pdfconverter==0.1.0
sphinx-rtd-theme
setuptools
setuptools_scm
wheel
twine
readme_renderer
testresources
circuitpython-build-tools

View file

@ -2,48 +2,5 @@
#
# SPDX-License-Identifier: Unlicense
[build-system]
requires = [
"setuptools",
"wheel",
"setuptools-scm",
]
[project]
name = "circuitpython-jepler-udecimal"
description = "Reduced version of the decimal library for CircuitPython"
version = "0.0.0+auto.0"
readme = "README.rst"
authors = [
{name = "Jeff Epler", email = "jepler@gmail.com"}
]
urls = { Source = "https://github.com/jepler/Jepler_CircuitPython_udecimal", Documentation = "https://jepler-udecimal.readthedocs.io/en/latest/api/jepler_udecimal/index.html", Tracker = "https://github.com/jepler/Jepler_CircuitPython_udecimal/issues" }
# "Pull Requests" = "https://github.com/jepler/Jepler_CircuitPython_udecimal/pulls",
keywords = [
"adafruit",
"blinka",
"circuitpython",
"micropython",
"udecimal",
"numeric",
"helper",
"arbitraryprecision",
"math",
]
license = {text = "MIT"}
classifiers = [
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Embedded Systems",
"Topic :: System :: Hardware",
"License :: OSI Approved :: MIT License",
"License :: OSI Approved :: Python Software Foundation License",
"Programming Language :: Python :: 3",
]
dynamic = ["dependencies", "optional-dependencies"]
[tool.setuptools]
packages=['jepler_udecimal']
[tool.setuptools_scm]
write_to = "jepler_udecimal/__version__.py"
[tool.black]
target-version = ['py35']

View file

@ -2,3 +2,18 @@
# SPDX-FileCopyrightText: Copyright (c) 2020 jepler for Unpythonic Networks
#
# SPDX-License-Identifier: MIT
astroid
black
isort
pre-commit
recommonmark==0.6.0
sphinx<4
sphinx-autoapi
sphinxcontrib-svg2pdfconverter==0.1.0
sphinx-rtd-theme
setuptools
wheel
twine
readme_renderer
testresources
circuitpython-build-tools

65
setup.py Normal file
View file

@ -0,0 +1,65 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2020 jepler for Unpythonic Networks
#
# SPDX-License-Identifier: MIT
"""A setuptools based setup module.
See:
https://packaging.python.org/en/latest/distributing.html
https://github.com/pypa/sampleproject
"""
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
long_description = f.read()
setup(
name="jepler-circuitpython-udecimal",
use_scm_version=True,
setup_requires=["setuptools_scm"],
description="Reduced version of the decimal library for CircuitPython",
long_description=long_description,
long_description_content_type="text/x-rst",
# The project's main homepage.
url="https://github.com/jepler/Jepler_CircuitPython_udecimal",
project_urls={
"Source": "https://github.com/jepler/Jepler_CircuitPython_udecimal",
"Documentation": "https://jepler-udecimal.readthedocs.io/en/latest/api/jepler_udecimal/index.html",
"Tracker": "https://github.com/jepler/Jepler_CircuitPython_udecimal/issues",
"Pull Requests": "https://github.com/jepler/Jepler_CircuitPython_udecimal/pulls",
},
# Author details
author="Jeff Epler",
author_email="jepler@gmail.com",
install_requires=[],
# Choose your license
license="MIT",
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"License :: OSI Approved :: MIT License",
"License :: OSI Approved :: Python Software Foundation License ",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
],
# What does your project relate to?
keywords="adafruit blinka circuitpython micropython udecimal numeric helper "
"arbitraryprecision math",
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
packages=["jepler_udecimal"],
)