Skip to content

Commit

Permalink
improve base ccy price plugin
Browse files Browse the repository at this point in the history
* do not fail if we don't have an fx rate
* do not generate entry if there is already a price entry on that date
* add tests
* Fixes #16
  • Loading branch information
tarioch committed May 9, 2020
1 parent 291bb10 commit 783b89d
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 52 deletions.
89 changes: 46 additions & 43 deletions .github/workflows/build-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,49 @@ jobs:
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@master
with:
fetch-depth: 0
- uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Install flake8
run: >-
pip install
flake8
- name: Lint
run: >-
flake8
- name: Install pep517
run: >-
python -m
pip install
pep517
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
pep517.build
--source
--binary
--out-dir dist/
.
- name: Publish distribution 📦 to Test PyPI
if: contains(github.ref, 'refs/heads/master')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.test_pypi_password }}
TWINE_REPOSITORY_URL: https://test.pypi.org/legacy/
run: >-
pip install twine && twine upload dist/*
- name: Publish distribution 📦 to PyPI
if: contains(github.ref, 'refs/tags/v')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.pypi_password }}
TWINE_REPOSITORY_URL: https://upload.pypi.org/legacy/
run: >-
pip install twine && twine upload dist/*
- uses: actions/checkout@master
with:
fetch-depth: 0
- uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Install flake8
run: >-
pip install
flake8
- name: Lint
run: >-
flake8
- name: Test
run: >-
python setup.py test
- name: Install pep517
run: >-
python -m
pip install
pep517
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
pep517.build
--source
--binary
--out-dir dist/
.
- name: Publish distribution 📦 to Test PyPI
if: contains(github.ref, 'refs/heads/master')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.test_pypi_password }}
TWINE_REPOSITORY_URL: https://test.pypi.org/legacy/
run: >-
pip install twine && twine upload dist/*
- name: Publish distribution 📦 to PyPI
if: contains(github.ref, 'refs/tags/v')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.pypi_password }}
TWINE_REPOSITORY_URL: https://upload.pypi.org/legacy/
run: >-
pip install twine && twine upload dist/*
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ extras = True
# e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml
# in order to write a coverage file that can be read by Jenkins.
addopts =
--cov beancounttools --cov-report term-missing
# -s
--verbose
norecursedirs =
dist
Expand Down
27 changes: 19 additions & 8 deletions src/tariochbctools/plugins/generate_base_ccy_prices.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,27 @@ def generate(entries, options_map, baseCcy):
additionalEntries = []
for entry in entries:
if isinstance(entry, data.Price) and entry.amount.currency != baseCcy:
fxRate = prices.get_price(priceMap, tuple([entry.amount.currency, baseCcy]), entry.date)
priceInBaseCcy = amount.Amount(entry.amount.number * fxRate[1], baseCcy)
fxTuple = tuple([entry.amount.currency, baseCcy])
fxRate = prices.get_price(priceMap, fxTuple, entry.date)
if fxRate[1] and not _alreadyExistingPrice(priceMap, tuple([entry.currency, baseCcy]), entry.date):
priceInBaseCcy = amount.Amount(entry.amount.number * fxRate[1], baseCcy)

additionalEntries.append(data.Price(
entry.meta,
entry.date,
entry.currency,
priceInBaseCcy
))
additionalEntries.append(data.Price(
entry.meta,
entry.date,
entry.currency,
priceInBaseCcy
))

entries.extend(additionalEntries)

return entries, errors


def _alreadyExistingPrice(priceMap, fxTuple, date):
if fxTuple in priceMap:
for alreadyExistingPriceDates in priceMap[fxTuple]:
if date == alreadyExistingPriceDates[0]:
return True

return False
Empty file added tests/__init__.py
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
2020-01-01 price USD 1.2 CHF
2020-01-02 price FOO 1 USD
2020-01-02 price FOO 1.7 CHF
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
plugin "tariochbctools.plugins.generate_base_ccy_prices" "CHF"
2020-01-01 price USD 1.2 CHF
2020-01-02 price FOO 1 USD
2020-01-02 price FOO 1.7 CHF
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2020-01-02 price FOO 1 USD
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
plugin "tariochbctools.plugins.generate_base_ccy_prices" "CHF"
2020-01-02 price FOO 1 USD
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
2020-01-01 price USD 1.2 CHF
2020-01-02 price FOO 1 USD
2020-01-02 price FOO 1.2 CHF
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
plugin "tariochbctools.plugins.generate_base_ccy_prices" "CHF"
2020-01-01 price USD 1.2 CHF
2020-01-02 price FOO 1 USD
35 changes: 35 additions & 0 deletions tests/tariochbctools/plugins/test_generate_base_ccy_prices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import os
from io import StringIO
from beancount.parser import printer
from beancount import loader
import pytest


@pytest.mark.parametrize("testCase", [
"normal",
"missing_fx",
"entry_already_exists"
])
def test_data(testCase):
dataDir = os.path.join(
os.path.dirname(__file__), "data", "generate_base_ccy_prices"
)
inputPath = os.path.join(dataDir, testCase + "_input.beancount")
expectedPath = os.path.join(dataDir, testCase + "_expected.beancount")

entries, errors, _ = loader.load_file(inputPath)
if errors:
printer.print_errors(errors)
assert False

actualStrIo = StringIO()
printer.print_entries(entries, file=actualStrIo)
actual = actualStrIo.getvalue()

if os.path.isfile(expectedPath):
with open(expectedPath, 'r') as expectedFile:
expected = expectedFile.read()
assert actual == expected
else:
with open(expectedPath, 'w') as expectedFile:
expectedFile.write(actual)

0 comments on commit 783b89d

Please sign in to comment.