Skip to content

Commit

Permalink
ci template github actions
Browse files Browse the repository at this point in the history
use pytest.approx, black style
  • Loading branch information
scivision committed Nov 11, 2019
1 parent 787cd06 commit 3176507
Show file tree
Hide file tree
Showing 18 changed files with 130 additions and 93 deletions.
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These are supported funding model platforms

github: [scivision]
ko_fi: scivision
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: ci

on:
push:
paths:
- "**.py"
pull_request:
paths:
- "**.py"

jobs:

linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: pip install .[tests,lint]
- run: flake8
- run: mypy .
- run: pytest
working-directory: tests

integration:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, macos-latest]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- run: pip install .[tests]
- run: pytest
working-directory: tests
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
[![image](https://zenodo.org/badge/81351748.svg)](https://zenodo.org/badge/latestdoi/81351748)
[![image](https://travis-ci.org/scivision/sciencedates.svg?branch=master)](https://travis-ci.org/scivision/sciencedates)
[![image](https://coveralls.io/repos/github/scivision/sciencedates/badge.svg?branch=master)](https://coveralls.io/github/scivision/sciencedates?branch=master)
[![image](https://ci.appveyor.com/api/projects/status/r6adn3fdvk1qcx4r?svg=true)](https://ci.appveyor.com/project/scivision/sciencedates)
[![Maintainability](https://api.codeclimate.com/v1/badges/47852e6e896d404d20a5/maintainability)](https://codeclimate.com/github/scivision/sciencedates/maintainability)
[![Actions Status](https://github.com/scivision/sciencedates/workflows/ci/badge.svg)](https://github.com/scivision/sciencedates/actions)

[![Python versions (PyPI)](https://img.shields.io/pypi/pyversions/sciencedates.svg)](https://pypi.python.org/pypi/sciencedates)
[![PyPi Download stats](http://pepy.tech/badge/sciencedates)](http://pepy.tech/project/sciencedates)

# Science Dates & Times

Date & time conversions used in the sciences.
Date & time conversions used in the sciences.
The assumption is that datetimes are **timezone-naive**, as this is required in Numpy *et al* for `numpy.datetime64`.


## Install

```sh
python -m pip install -e .
python -m pip install sciencedates
```

## Usage
Expand Down Expand Up @@ -45,5 +43,5 @@ Matlab / GNU Octave [examples](./matlab) are provided
## Fortran

Fortran [examples](./fortran) are provided.
For Python-like modern Fortran datetime, see
For Python-like modern Fortran datetime, see
[Datetime-Fortran](https://github.com/wavebitscientific/datetime-fortran).
3 changes: 1 addition & 2 deletions .appveyor.yml → archive/.appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ init:

install: pip install -e .[tests]

test_script: pytest -rsv

test_script: pytest
4 changes: 1 addition & 3 deletions .travis.yml → archive/.travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
language: python
group: travis_latest
dist: xenial

git:
depth: 25
Expand Down Expand Up @@ -33,5 +32,4 @@ matrix:

install: pip install -e .[tests]

script: pytest -rsv

script: pytest
8 changes: 7 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
[mypy]
ignore_missing_imports = True
strict_optional = False
allow_redefinition = True
allow_redefinition = True
show_error_context = False
show_column_numbers = True
warn_unreachable = False

[mypy-xarray]
follow_imports = skip
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[build-system]
requires = ["setuptools", "wheel"]

[tool.black]
line-length = 132
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
addopts = -ra -v
3 changes: 1 addition & 2 deletions randomdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

def main():
p = ArgumentParser(description='generate random date in year')
p.add_argument('year', type=int,
nargs='?', default=date.today().year)
p.add_argument('year', type=int, nargs='?', default=date.today().year)
P = p.parse_args()

print(randomdate(P.year))
Expand Down
26 changes: 13 additions & 13 deletions sciencedates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import Union, Tuple, List

from .findnearest import find_nearest # noqa: F401

try:
from .tz import forceutc # noqa: F401
except ImportError:
Expand All @@ -32,13 +33,12 @@ def datetime2yeardoy(time: Union[str, datetime.datetime]) -> Tuple[int, float]:
t = parse(t)

utsec[i] = datetime2utsec(t)
yd[i] = t.year*1000 + int(t.strftime('%j'))
yd[i] = t.year * 1000 + int(t.strftime('%j'))

return yd.squeeze()[()], utsec.squeeze()[()]


def yeardoy2datetime(yeardate: int,
utsec: Union[float, int] = None) -> datetime.datetime:
def yeardoy2datetime(yeardate: int, utsec: Union[float, int] = None) -> datetime.datetime:
"""
Inputs:
yd: yyyyddd four digit year, 3 digit day of year (INTEGER 7 digits)
Expand Down Expand Up @@ -93,8 +93,9 @@ def date2doy(time: Union[str, datetime.datetime]) -> Tuple[int, int]:
return doy, year


def datetime2gtd(time: Union[str, datetime.datetime, np.datetime64],
glon: Union[float, List[float], np.ndarray] = np.nan) -> Tuple[int, float, float]:
def datetime2gtd(
time: Union[str, datetime.datetime, np.datetime64], glon: Union[float, List[float], np.ndarray] = np.nan
) -> Tuple[int, float, float]:
"""
Inputs:
time: Numpy 1-D array of datetime.datetime OR string for dateutil.parser.parse
Expand All @@ -105,7 +106,7 @@ def datetime2gtd(time: Union[str, datetime.datetime, np.datetime64],
utsec: seconds from midnight utc
stl: local solar time
"""
# %%
# %%
T = np.atleast_1d(time)
glon = np.asarray(glon)
doy = np.empty_like(T, int)
Expand All @@ -121,12 +122,12 @@ def datetime2gtd(time: Union[str, datetime.datetime, np.datetime64],
pass
else:
raise TypeError('unknown time datatype {}'.format(type(t)))
# %% Day of year
# %% Day of year
doy[i] = int(t.strftime('%j'))
# %% seconds since utc midnight
# %% seconds since utc midnight
utsec[i] = datetime2utsec(t)

stl[i, ...] = utsec[i] / 3600. + glon / 15.
stl[i, ...] = utsec[i] / 3600.0 + glon / 15.0

return doy, utsec, stl

Expand All @@ -139,14 +140,13 @@ def datetime2utsec(t: Union[str, datetime.date, datetime.datetime, np.datetime64
if isinstance(t, (tuple, list, np.ndarray)):
return np.asarray([datetime2utsec(T) for T in t])
elif isinstance(t, datetime.date) and not isinstance(t, datetime.datetime):
return 0.
return 0.0
elif isinstance(t, np.datetime64):
t = t.astype(datetime.datetime)
elif isinstance(t, str):
t = parse(t)

return datetime.timedelta.total_seconds(t - datetime.datetime.combine(t.date(),
datetime.datetime.min.time()))
return datetime.timedelta.total_seconds(t - datetime.datetime.combine(t.date(), datetime.datetime.min.time()))


def yeardec2datetime(atime: float) -> datetime.datetime:
Expand All @@ -161,7 +161,7 @@ def yeardec2datetime(atime: float) -> datetime.datetime:
In Python, go from decimal year (YYYY.YYY) to datetime,
and from datetime to decimal year.
"""
# %%
# %%
if isinstance(atime, (float, int)): # typically a float

year = int(atime)
Expand Down
8 changes: 4 additions & 4 deletions sciencedates/findnearest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ def find_nearest(x, x0) -> Tuple[int, Any]:
"""
x = np.asanyarray(x) # for indexing upon return
x0 = np.atleast_1d(x0)
# %%
# %%
if x.size == 0 or x0.size == 0:
raise ValueError('empty input(s)')

if x0.ndim not in (0, 1):
raise ValueError('2-D x0 not handled yet')
# %%
# %%
ind = np.empty_like(x0, dtype=int)

# NOTE: not trapping IndexError (all-nan) becaues returning None can surprise with slice indexing
for i, xi in enumerate(x0):
if xi is not None and (isinstance(xi, (datetime.datetime, datetime.date, np.datetime64)) or np.isfinite(xi)):
ind[i] = np.nanargmin(abs(x-xi))
ind[i] = np.nanargmin(abs(x - xi))
else:
raise ValueError('x0 must NOT be None or NaN to avoid surprising None return value')

return ind.squeeze()[()], x[ind].squeeze()[()] # [()] to pop scalar from 0d array while being OK with ndim>0
return ind.squeeze()[()], x[ind].squeeze()[()] # [()] to pop scalar from 0d array while being OK with ndim>0
2 changes: 1 addition & 1 deletion sciencedates/ticks.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ def timeticks(tdiff):
return SecondLocator(bysecond=range(0, 60, 10)), SecondLocator(bysecond=range(0, 60, 2))

else:
return SecondLocator(bysecond=range(0, 60, 2)), SecondLocator(bysecond=range(0, 60, 1))
return SecondLocator(bysecond=range(0, 60, 2)), SecondLocator(bysecond=range(0, 60, 1))
4 changes: 2 additions & 2 deletions sciencedates/tz.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def forceutc(t: Union[str, datetime.datetime, datetime.date, np.datetime64]) ->
output: utc datetime
"""
# need to passthrough None for simpler external logic.
# %% polymorph to datetime
# %% polymorph to datetime
if isinstance(t, str):
t = parse(t)
elif isinstance(t, np.datetime64):
Expand All @@ -26,7 +26,7 @@ def forceutc(t: Union[str, datetime.datetime, datetime.date, np.datetime64]) ->
return np.asarray([forceutc(T) for T in t])
else:
raise TypeError('datetime only input')
# %% enforce UTC on datetime
# %% enforce UTC on datetime
if t.tzinfo is None: # datetime-naive
t = t.replace(tzinfo=UTC)
else: # datetime-aware
Expand Down
17 changes: 3 additions & 14 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = sciencedates
version = 1.4.4
version = 1.4.5
author = Michael Hirsch, Ph.D.
author_email = [email protected]
url = https://github.com/scivision/sciencedates
Expand All @@ -17,8 +17,7 @@ classifiers =
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy
Programming Language :: Python :: 3.9
Topic :: Utilities
license_files =
LICENSE.txt
Expand All @@ -27,9 +26,6 @@ long_description_content_type = text/markdown

[options]
python_requires = >= 3.5
setup_requires =
setuptools >= 38.6
pip >= 10
packages = find:
scripts =
date2doy.py
Expand All @@ -42,18 +38,11 @@ install_requires =
[options.extras_require]
tests =
pytest
cov =
pytest-cov
coveralls
lint =
flake8
mypy
plot =
xarray
matplotlib
timezone =
pytz

[options.entry_points]
console_scripts =
date2doy = date2doy:main
randomdate = randomdate:main
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env python
from setuptools import setup

setup()
32 changes: 15 additions & 17 deletions tests/test_conv.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
import datetime
from dateutil.parser import parse
import numpy as np
from numpy.testing import assert_allclose, assert_equal
from pytest import approx
import pytest
import sciencedates as sd
import sys
#
T = [datetime.datetime(2013, 7, 2, 12, 0, 0)]
import typing
import sciencedates as sd

T: typing.List[typing.Any] = [datetime.datetime(2013, 7, 2, 12, 0, 0)]
T.append(T[0].date())
T.append(np.datetime64(T[0]))
T.append(str(T[0]))

Tdt = (T[0],)*3
Tdt = (T[0],) * 3
OLDPY = sys.version_info < (3, 6)


Expand All @@ -33,9 +34,9 @@ def test_yearint():
assert sd.yeardoy2datetime(yd, utsec).date() == t

assert utsec == utsec2
# %% array
# %% array
y, s = sd.datetime2yeardoy(Tdt)
assert_equal(sd.yeardoy2datetime(y, s), T[0])
assert (sd.yeardoy2datetime(y, s) == T[0]).all()


def test_date2doy():
Expand All @@ -44,26 +45,26 @@ def test_date2doy():

assert year == T[0].year
assert doy == 183
# %% array
# %% array
doy, year = sd.date2doy(Tdt)
assert_equal(year, T[0].year)
assert_equal(doy, 183)
assert (year == T[0].year).all()
assert (doy == 183).all()


def test_yeardec():
for t, r in zip(T, (2013.5, 2013.4986301369863)):
yeardec = sd.datetime2yeardec(t)

assert_allclose(yeardec, r)
assert yeardec == approx(r)
if isinstance(t, datetime.datetime):
assert sd.yeardec2datetime(yeardec) == t
else:
assert sd.yeardec2datetime(yeardec).date() == t
# %% array
assert_equal(sd.yeardec2datetime(sd.datetime2yeardec(Tdt)), T[0])
# %% array
assert (sd.yeardec2datetime(sd.datetime2yeardec(Tdt)) == T[0]).all()


@pytest.mark.xfail(OLDPY, reason='py36+')
@pytest.mark.skip(OLDPY, reason='py36+')
def test_utc():
pytz = pytest.importorskip('pytz')

Expand All @@ -79,6 +80,3 @@ def test_utc():

if __name__ == '__main__':
pytest.main([__file__])

if __name__ == '__main__':
pytest.main()
Loading

0 comments on commit 3176507

Please sign in to comment.