Skip to content

Commit

Permalink
add empty attribute, better error for timeseries() on empty dataf…
Browse files Browse the repository at this point in the history
…rame (#297)

* add `empty` attribute and unit tests

* raise `AttributeError` for `timeseries()` on empty data and units test

* fix docstring formatting

* add to release notes

* switch to ValueError when calling `timeseries()` on empty

suggested by @znicholls

* minor edit in docstring

* expect `ValueError` in unit test for `timeseries()`

* add more lenient timeout for iiasa-dbs test (slow response)

* fix timeout-value formatting
  • Loading branch information
danielhuppmann committed Nov 30, 2019
1 parent 16c0ea5 commit d582a41
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 4 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

# Next Release

- [#297](https://github.com/IAMconsortium/pyam/pull/297) Add `empty` attribute, better error for `timeseries()` on empty dataframe
- [#292](https://github.com/IAMconsortium/pyam/pull/292) Add warning message if `data` is empty at initialization (after formatting)
- [#288](https://github.com/IAMconsortium/pyam/pull/288) Put `pyam` logger in its own namespace (see [here](https://docs.python-guide.org/writing/logging/#logging-in-a-library>))

Expand Down
17 changes: 16 additions & 1 deletion pyam/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ def tail(self, *args, **kwargs):
"""Identical to pd.DataFrame.tail() operating on data"""
return self.data.tail(*args, **kwargs)

@property
def empty(self):
"""Indicator whether ``IamDataFrame`` is empty"""
return self.data.empty

def models(self):
"""Get a list of models"""
return pd.Series(self.meta.index.levels[0])
Expand Down Expand Up @@ -373,14 +378,24 @@ def _discover_meta_cols(self, **kwargs):
return list(cols)

def timeseries(self, iamc_index=False):
"""Returns a pd.DataFrame in wide format (years or timedate as columns)
"""Returns a pd.DataFrame in wide format (years or datetime as columns)
Parameters
----------
iamc_index: bool, default False
if True, use `['model', 'scenario', 'region', 'variable', 'unit']`;
else, use all `data` columns
Raises
------
ValueError
``IamDataFrame`` is empty
ValueError
reducing to IAMC-index yields an index with duplicates
"""
if self.empty:
raise ValueError('this `IamDataFrame` is empty')

index = IAMC_IDX if iamc_index else IAMC_IDX + self.extra_cols
df = (
self.data
Expand Down
10 changes: 10 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ def test_init_empty_message(test_pd_df, caplog):
assert caplog.records[message_idx].levelno == logging.WARNING


def test_empty_attribute(test_df_year):
assert not test_df_year.empty
assert test_df_year.filter(model='foo').empty


def test_to_excel(test_df):
fname = 'foo_testing.xlsx'
test_df.to_excel(fname)
Expand Down Expand Up @@ -491,6 +496,11 @@ def test_timeseries(test_df):
npt.assert_array_equal(obs, exp)


def test_timeseries_raises(test_df_year):
_df = test_df_year.filter(model='foo')
pytest.raises(ValueError, _df.timeseries)


def test_read_pandas():
df = IamDataFrame(os.path.join(TEST_DATA_DIR, 'testing_data_2.csv'))
assert list(df.variables()) == ['Primary Energy']
Expand Down
6 changes: 3 additions & 3 deletions tests/test_tutorials.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
# https://blog.thedataincubator.com/2016/06/testing-jupyter-notebooks/


def _notebook_run(path, kernel=None, capsys=None):
def _notebook_run(path, kernel=None, timeout=60, capsys=None):
"""Execute a notebook via nbconvert and collect output.
:returns (parsed nb object, execution errors)
"""
Expand All @@ -39,7 +39,7 @@ def _notebook_run(path, kernel=None, capsys=None):
fname = os.path.join(here, 'test.ipynb')
args = [
"jupyter", "nbconvert", "--to", "notebook", "--execute",
"--ExecutePreprocessor.timeout=60",
"--ExecutePreprocessor.timeout={}".format(timeout),
"--ExecutePreprocessor.kernel_name={}".format(kernel),
"--output", fname, path]
subprocess.check_call(args)
Expand Down Expand Up @@ -87,7 +87,7 @@ def test_pyam_logo():
@pytest.mark.skipif(not pandoc_installed, reason=pandoc_reason)
def test_iiasa_dbs():
fname = os.path.join(tut_path, 'iiasa_dbs.ipynb')
nb, errors = _notebook_run(fname)
nb, errors = _notebook_run(fname, timeout=600)
assert errors == []


Expand Down

0 comments on commit d582a41

Please sign in to comment.