Skip to content

Commit

Permalink
Merge pull request #31 from quantmind/ls-docs
Browse files Browse the repository at this point in the history
mypy & docs
  • Loading branch information
lsbardel committed Jul 22, 2023
2 parents a0843cd + f684000 commit 8a64a9b
Show file tree
Hide file tree
Showing 34 changed files with 3,362 additions and 1,500 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,20 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: make install
run: make install-dev
- name: run lint
run: make lint
- name: run tests
run: make test
- name: upload coverage
if: matrix.python-version == '3.11'
run: make codecov
- name: build book
if: ${{ matrix.python-version == '3.11' }}
run: make book
- name: publish book
if: ${{ matrix.python-version == '3.11' }}
run: make publish-book
- name: publish
if: ${{ github.ref == 'refs/heads/main' && matrix.python-version == '3.10' && github.event.head_commit.message == 'release' }}
run: make publish
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ MANIFEST
release-notes.md
.settings
.coverage
.env

*.ipynb
.ipynb_checkpoints
14 changes: 11 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ clean: ## remove python cache files
docs: ## build docs
cd docs && make docs

install: ## install packages for development
@pip install -U pip poetry
@poetry install
install-dev: ## install packages for development
@./dev/install

lint: ## Run linters
@poetry run ./dev/lint fix
Expand All @@ -32,3 +31,12 @@ test: ## test with python 3.8 with coverage

publish: ## release to pypi and github tag
@poetry publish --build -u lsbardel -p $(PYPI_PASSWORD)

notebook: ## Run Jupyter notebook server
@poetry run ./dev/start-jupyter 9095

book: ## Build static jupyter {book}
poetry run jupyter-book build docs --all

publish-book: ## publish the book to github pages
poetry run ghp-import -n -p -f docs/_build/html
44 changes: 0 additions & 44 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,50 +152,6 @@ eurozone is tuple of country ISO codes::
Spain


Date and Periods
===================

The module is shipped with a ``date`` module for manipulating time periods and
converting dates between different formats. The *period* function can be used
to create ``Period`` instances::

>>> from ccy import period
>>> p = period('1m')
>>> p
1M
>>> p += '2w'
>>> p
1M2W
>>> P += '3m'
>>> p
4M2W


Installation
================
This library works for Python 2.6 and higher, including Python 3.
In addition, it requires:

* pytz_ for Countries information.
* dateutils_ for date calculations

Install using ``pip``::

pip install ccy

or from source::

python setup.py install


Running tests
~~~~~~~~~~~~~~~~~~~~~

From within the package directory::

python setup.py test


.. _pytz: http://pytz.sourceforge.net/
.. _`ISO 3166-1 alpha-2`: http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
.. _`ISO 4217`: http://en.wikipedia.org/wiki/ISO_4217
Expand Down
6 changes: 2 additions & 4 deletions ccy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
countryccy,
eurozone,
print_eurozone,
set_country_map,
set_new_country,
)
from .core.currency import (
Expand Down Expand Up @@ -50,7 +49,6 @@
"countryccy",
"set_new_country",
"countries",
"set_country_map",
"country_map",
"CountryError",
"eurozone",
Expand All @@ -72,11 +70,11 @@


# Shortcuts
def cross(code):
def cross(code: str) -> str:
return currency(code).as_cross()


def crossover(code):
def crossover(code: str) -> str:
return currency(code).as_cross("/")


Expand Down
64 changes: 18 additions & 46 deletions ccy/core/country.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
from __future__ import annotations

from typing import Protocol
from typing import TYPE_CHECKING, Protocol

from .currency import currencydb

if TYPE_CHECKING:
pass

# Eurozone countries (officially the euro area)
# see http://en.wikipedia.org/wiki/Eurozone
# using ISO 3166-1 alpha-2 country codes
# see http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
#
eurozone = tuple(
("AT BE CY DE EE ES FI FR GR IE IT LU LV LT MT NL PT SI SK").split(" ")
("AT BE CY DE EE ES FI FR GR HR IE IT LU LV LT MT NL PT SI SK").split(" ")
)


def print_eurozone():
for c in sorted(map(country, eurozone)):
def print_eurozone() -> None:
for c in sorted(country(c).name for c in eurozone):
print(c)


_countries: dict[str, Country] = {}
_country_ccys = None
_country_maps = {}
_country_ccys: dict[str, str] = {}
_country_maps: dict[str, str] = {}


class Country(Protocol):
Expand All @@ -34,16 +37,16 @@ class CountryError(Exception):
pass


def country(code):
def country(code: str) -> Country:
cdb = countries()
code = country_map(code)
return cdb.get(code, "")
return cdb[code]


def countryccy(code):
def countryccy(code: str) -> str:
cdb = countryccys()
code = str(code).upper()
return cdb.get(code, None)
return cdb.get(code, "")


def countries() -> dict[str, Country]:
Expand All @@ -61,55 +64,24 @@ def countries() -> dict[str, Country]:
return _countries


def countryccys():
def countryccys() -> dict[str, str]:
"""
Create a dictionary with keys given by countries ISO codes and values
given by their currencies
"""
global _country_ccys
if not _country_ccys:
v = {}
v: dict[str, str] = {}
_country_ccys = v
ccys = currencydb()
for c in eurozone:
v[c] = "EUR"
for euc in eurozone:
v[euc] = "EUR"
for c in ccys.values():
if c.default_country:
v[c.default_country] = c.code
return _country_ccys


def set_country_map(cfrom, cto, name=None, replace=True):
"""
Set a mapping between a country code to another code
"""
global _country_maps
cdb = countries()
cfrom = str(cfrom).upper()
c = cdb.get(cfrom)
if c:
if name:
c = name
cto = str(cto).upper()
if cto in cdb:
raise CountryError("Country %s already in database" % cto)
cdb[cto] = c
_country_maps[cfrom] = cto
ccys = currencydb()
cccys = countryccys()
ccy = cccys[cfrom]
cccys[cto] = ccy

# If set, remove cfrom from database
if replace:
ccy = ccys.get(ccy)
ccy.default_country = cto
cdb.pop(cfrom)
cccys.pop(cfrom)
else:
raise CountryError("Country %s not in database" % c)


def set_new_country(code: str, ccy: str, name: str) -> None:
"""
Add new country code to database
Expand All @@ -132,7 +104,7 @@ def set_new_country(code: str, ccy: str, name: str) -> None:
cccys[code] = ccy


def country_map(code):
def country_map(code: str) -> str:
"""
Country mapping
"""
Expand Down
30 changes: 2 additions & 28 deletions ccy/core/currency.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ def printinfo(self, stream: Any | None = None) -> None:
for k, v in info.items():
stream.write(to_string("%s: %s\n" % (k, v)))

def __repr__(self) -> str:
return "%s: %s" % (self.__class__.__name__, self.code)

def __str__(self) -> str:
return self.code

Expand Down Expand Up @@ -207,31 +204,8 @@ def make_ccypairs() -> dict[str, ccy_pair]:
return db


def dump_currency_table():
headers = [
"code",
"name",
("isonumber", "iso"),
("html", "symbol"),
("default_country", "country"),
"order",
"rounding",
]
all = []
data = []
all.append(data)
for h in headers:
if isinstance(h, tuple):
h = h[1]
data.append(h)
for c in sorted(currencydb().values(), key=lambda x: x.order):
data = []
all.append(data)
for h in headers:
if isinstance(h, tuple):
h = h[0]
data.append(getattr(c, h))
return all
def dump_currency_table() -> list:
return [c._asdict() for c in sorted(currencydb().values(), key=lambda x: x.order)]


_ccys: ccydb = ccydb()
Expand Down
36 changes: 30 additions & 6 deletions ccy/core/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from .currency import ccydb


def make_ccys(db: ccydb):
def make_ccys(db: ccydb) -> None:
"""
Create the currency dictionary
"""
Expand Down Expand Up @@ -466,7 +466,17 @@ def make_ccys(db: ccydb):
symbol_raw=r"Ft",
html="Ft",
)
insert("RON", "946", "RN", 34, "Romanian Leu", dfr, "RO", "ACT/360", "ACT/360")
insert(
"RON",
"946",
"RN",
34,
"Romanian Leu",
dfr,
"RO",
"ACT/360",
"ACT/360",
)
insert(
"UAH",
"980",
Expand All @@ -493,8 +503,6 @@ def make_ccys(db: ccydb):
symbol_raw=r"\u0440\u0443\u0431",
)
# TODO: Check towletters code and position
insert("HRK", "191", "HK", 410, "Croatian kuna", dfr, "HR", symbol_raw=r"kn")
# TODO: Check towletters code and position
insert(
"KZT",
"398",
Expand Down Expand Up @@ -534,7 +542,15 @@ def make_ccys(db: ccydb):
html="₪",
)
# TODO: Check towletters code and position
insert("AED", "784", "AE", 410, "United Arab Emirates Dirham", dfr, "AE")
insert(
"AED",
"784",
"AE",
410,
"United Arab Emirates Dirham",
dfr,
"AE",
)
# TODO: Check towletters code and position
insert(
"QAR",
Expand Down Expand Up @@ -597,5 +613,13 @@ def make_ccys(db: ccydb):

# BITCOIN
insert(
"XBT", "000", "BT", -1, "Bitcoin", 8, "WW", symbol_raw=r"\u0e3f", html="฿"
"XBT",
"000",
"BT",
-1,
"Bitcoin",
8,
"WW",
symbol_raw=r"\u0e3f",
html="฿",
)
Loading

0 comments on commit 8a64a9b

Please sign in to comment.