Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docstrings to NumPy standard (importers) #172

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 140 additions & 20 deletions bw2io/importers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,111 @@


class ImportBase(object):
"""Base class for format-specific importers.

Defines workflow for applying strategies."""
"""
Base class for format-specific importers.
Defines workflow for applying strategies.

"""
def __init__(self, *args, **kwargs):
"""
Initialize the ImportBase object.

Parameters
----------
*args :
Variable length argument list.
**kwargs :
Arbitrary keyword arguments.

Raises
------
NotImplemented :
This class should be subclassed.
"""
raise NotImplemented("This class should be subclassed")

def __iter__(self):
"""
Iterate over the data and yield the current data.

Yields
------
ds :
The current data being iterated over.
"""
for ds in self.data:
yield ds

def apply_strategy(self, strategy, verbose=True):
"""Apply ``strategy`` transform to ``self.data``.
"""
Apply the specified strategy transform to the importer's data.

Adds strategy name to ``self.applied_strategies``. If ``StrategyError`` is raised, print error message, but don't raise error.
This method applies a given strategy to the importer's data and logs the applied strategy's name to
`self.applied_strategies`. If the strategy raises a `StrategyError`, the error message is printed but
not raised.

.. note:: Strategies should not partially modify data before raising ``StrategyError``.
Parameters
----------
strategy : callable
The strategy function to apply to the importer's data.
verbose : bool, optional
If True, print a message indicating which strategy is being applied. Defaults to True.

Args:
*strategy* (callable)
Returns
-------
None
Modifies the importer's data in place.

Returns:
Nothing, but modifies ``self.data``, and strategy to ``self.applied_strategies``.
Raises
------
None
If the strategy raises a `StrategyError`, the error message is printed but not raised.

Notes
-----
Strategies should not partially modify data before raising a `StrategyError`.

"""
if not hasattr(self, "applied_strategies"):
self.applied_strategies = []

try:
func_name = strategy.__name__
except AttributeError: # Curried function
func_name = strategy.func.__name__

if verbose:
print("Applying strategy: {}".format(func_name))

try:
self.data = strategy(self.data)
self.applied_strategies.append(func_name)
except StrategyError as err:
print("Couldn't apply strategy {}:\n\t{}".format(func_name, err))

def apply_strategies(self, strategies=None, verbose=True):
"""Apply a list of strategies.
"""
Apply a list of strategies to the importer's data.

Uses the default list ``self.strategies`` if ``strategies`` is ``None``.
This method applies a list of given strategies to the importer's data and logs the applied strategies' names to
`self.applied_strategies`. If no list of strategies is provided, it uses `self.strategies`.

Args:
*strategies* (list, optional): List of strategies to apply. Defaults to ``self.strategies``.
Parameters
----------
strategies : list, optional
List of strategies to apply. Defaults to `self.strategies`.
verbose : bool, optional
If True, print a message indicating which strategy is being applied. Defaults to True.

Returns:
Nothings, but modifies ``self.data``, and adds each strategy to ``self.applied_strategies``.
Returns
-------
None
Modifies the importer's data in place.

Notes
-----
The method `apply_strategy` is called to apply each individual strategy to the importer's data. Strategies
that partially modify data before raising a `StrategyError` should be avoided.

"""
start = time()
Expand All @@ -78,9 +134,17 @@ def apply_strategies(self, strategies=None, verbose=True):

@property
def unlinked(self):
"""Iterate through unique unlinked exchanges.
"""
Iterate through unique unlinked exchanges.

Uniqueness is determined by ``activity_hash``."""
Uniqueness is determined by `activity_hash`.

Yields
------
exc :
The unlinked exchange that is currently being iterated over.

"""
seen = set()
for ds in self.data:
for exc in ds.get("exchanges", []):
Expand All @@ -90,10 +154,22 @@ def unlinked(self):
continue
else:
seen.add(ah)
yield exc
yield exc

def write_unlinked(self, name):
"""Write all data to an ``UnlikedData`` data store (not a ``Database``!)"""
"""
Write all data to an `UnlinkedData` data store.

This method writes all of the importer's data to an `UnlinkedData` data store with the specified `name`. The
`UnlinkedData` object is created with the importer's class name appended to the `name`. The applied strategies
are logged to the `unlinked_data` dictionary.

Parameters
----------
name : str
The name of the `UnlinkedData` data store to be written.

"""
with warnings.catch_warnings():
warnings.simplefilter("ignore")
udb = UnlinkedData(name + " " + self.__class__.__name__)
Expand All @@ -109,6 +185,28 @@ def write_unlinked(self, name):
print("Saved unlinked data: {}".format(udb.name))

def _migrate_datasets(self, migration_name):
"""
Apply a migration function to the importer's datasets.

This method applies a given migration function to the importer's datasets, using `migrate_datasets`. The
migration function must be specified by name in the `migrations` dictionary.

Parameters
----------
migration_name : str
The name of the migration function to apply to the importer's datasets.

Returns
-------
None
Modifies the importer's data in place.

Raises
------
AssertionError
If the specified migration function is not in the `migrations` dictionary.

"""
assert migration_name in migrations, "Can't find migration {}".format(
migration_name
)
Expand All @@ -117,6 +215,28 @@ def _migrate_datasets(self, migration_name):
)

def _migrate_exchanges(self, migration_name):
"""
Apply a migration function to the importer's exchanges.

This method applies a given migration function to the importer's exchanges, using `migrate_exchanges`. The
migration function must be specified by name in the `migrations` dictionary.

Parameters
----------
migration_name : str
The name of the migration function to apply to the importer's exchanges.

Returns
-------
None
Modifies the importer's data in place.

Raises
------
AssertionError
If the specified migration function is not in the `migrations` dictionary.

"""
assert migration_name in migrations, "Can't find migration {}".format(
migration_name
)
Expand Down
41 changes: 41 additions & 0 deletions bw2io/importers/ecospold2.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,29 @@


class SingleOutputEcospold2Importer(LCIImporter):

"""
Class for importing single-output ecospold2 format LCI databases.

Parameters
----------
dirpath : str
Path to the directory containing the ecospold2 file.
db_name : str
Name of the LCI database.
extractor : class
Class for extracting data from the ecospold2 file, by default Ecospold2DataExtractor.
use_mp : bool
Flag to indicate whether to use multiprocessing, by default True.
signal : object
Object to indicate the status of the import process, by default None.

Raises
------
MultiprocessingError
If an error occurs during multiprocessing.
"""

format = u"Ecospold2"

def __init__(
Expand All @@ -43,6 +66,24 @@ def __init__(
use_mp=True,
signal=None,
):

"""
Initializes the SingleOutputEcospold2Importer class instance.

Parameters
----------
dirpath : str
Path to the directory containing the ecospold2 file.
db_name : str
Name of the LCI database.
extractor : class
Class for extracting data from the ecospold2 file, by default Ecospold2DataExtractor.
use_mp : bool
Flag to indicate whether to use multiprocessing, by default True.
signal : object
Object to indicate the status of the import process, by default None.
"""

self.dirpath = dirpath
self.db_name = db_name
self.signal = signal
Expand Down