diff --git a/doc/news/refactor-create-examples.rst b/doc/news/refactor-create-examples.rst new file mode 100644 index 0000000..de64cd6 --- /dev/null +++ b/doc/news/refactor-create-examples.rst @@ -0,0 +1,11 @@ +**Added:** + +* Added ``Entry.create_example(name=None)`` which returns a single example entry. Defaults to ``'alves_2011_electrochemistry_6010_f1a_solid'`` when no name is provided. + +**Changed:** + +* Changed ``Collection.create_example`` to use ``Collection.from_local`` internally. + +**Removed:** + +* Removed ``Entry.create_examples``. Use ``Entry.create_example`` instead. diff --git a/unitpackage/collection.py b/unitpackage/collection.py index d7e641f..aa7f201 100644 --- a/unitpackage/collection.py +++ b/unitpackage/collection.py @@ -47,6 +47,7 @@ # along with unitpackage. If not, see . # ******************************************************************** import logging +import os.path from frictionless import Package @@ -121,21 +122,9 @@ def create_example(cls): Entry('no_bibliography')] """ + example_dir = os.path.join(os.path.dirname(__file__), "..", "examples", "local") - entries = ( - cls.Entry.create_examples("alves_2011_electrochemistry_6010") - + cls.Entry.create_examples("engstfeld_2018_polycrystalline_17743") - + cls.Entry.create_examples("no_bibliography") - ) - - package = Package() - - for entry in entries: - package.add_resource(entry.resource) - - return cls( - package=package, - ) + return cls.from_local(example_dir) def filter(self, predicate): r""" diff --git a/unitpackage/database/echemdb_entry.py b/unitpackage/database/echemdb_entry.py index 7cd12df..1bb5ef4 100644 --- a/unitpackage/database/echemdb_entry.py +++ b/unitpackage/database/echemdb_entry.py @@ -95,7 +95,7 @@ def __repr__(self): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry Echemdb('alves_2011_electrochemistry_6010_f1a_solid') @@ -109,14 +109,14 @@ def bibliography(self): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry.bibliography # doctest: +NORMALIZE_WHITESPACE Entry('article', fields=[ ('title', ... ... - >>> entry_no_bib = EchemdbEntry.create_examples(name="no_bibliography")[0] + >>> entry_no_bib = EchemdbEntry.create_example(name="no_bibliography") >>> entry_no_bib.bibliography '' @@ -144,7 +144,7 @@ def citation(self, backend="text"): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry.citation(backend='text') 'O. B. Alves et al. Electrochemistry at Ru(0001) in a flowing CO-saturated electrolyte—reactive and inert adlayer phases. Physical Chemistry Chemical Physics, 13(13):6010–6021, 2011.' >>> print(entry.citation(backend='md')) @@ -210,7 +210,7 @@ def get_electrode(self, name): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry.get_electrode('WE') # doctest: +NORMALIZE_WHITESPACE {'name': 'WE', 'function': 'workingElectrode', 'type': 'single crystal', 'crystallographicOrientation': '0001', 'material': 'Ru', @@ -245,7 +245,7 @@ def rescale(self, units): These units must be defined in the metadata of the resource, within the key ``figureDescription.fields``:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> rescaled_entry = entry.rescale(units='original') >>> rescaled_entry.fields # doctest: +NORMALIZE_WHITESPACE [{'name': 't', 'type': 'number', 'unit': 's'}, @@ -270,7 +270,7 @@ def scan_rate(self): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry.scan_rate @@ -297,7 +297,7 @@ def rescale_scan_rate(self, field_name=None, *, value, unit): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry.scan_rate @@ -361,7 +361,7 @@ def _normalize_field_name(self, field_name): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry._normalize_field_name('j') 'j' >>> entry._normalize_field_name('x') @@ -382,7 +382,7 @@ def thumbnail(self, width=96, height=72, dpi=72, **kwds): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> thumb = entry.thumbnail() >>> thumb.startswith(b'\x89PNG') True @@ -432,7 +432,7 @@ def plot(self, x_label="E", y_label="j", name=None): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry.plot() Figure(...) @@ -496,7 +496,7 @@ def rescale_reference(self, new_reference=None, field_name=None, ph=None): EXAMPLES:: - >>> entry = EchemdbEntry.create_examples()[0] + >>> entry = EchemdbEntry.create_example() >>> entry.resource.schema.get_field('E') # doctest: +NORMALIZE_WHITESPACE {'name': 'E', 'type': 'number', 'unit': 'V', 'reference': 'RHE'} diff --git a/unitpackage/descriptor.py b/unitpackage/descriptor.py index 7dc1092..9906952 100644 --- a/unitpackage/descriptor.py +++ b/unitpackage/descriptor.py @@ -170,7 +170,7 @@ class QuantityDescriptor(GenericDescriptor): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> temperature = entry.echemdb.system.electrolyte.temperature >>> temperature 298.15 K @@ -187,7 +187,7 @@ def quantity(self): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> temperature = entry.echemdb.system.electrolyte.temperature >>> temperature.quantity @@ -204,7 +204,7 @@ def __repr__(self): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> temperature = entry.echemdb.system.electrolyte.temperature >>> temperature 298.15 K diff --git a/unitpackage/entry.py b/unitpackage/entry.py index ca721dc..09951dc 100644 --- a/unitpackage/entry.py +++ b/unitpackage/entry.py @@ -15,7 +15,7 @@ Metadata included in an entry is accessible as an attribute:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.echemdb.source # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE {'citationKey': 'alves_2011_electrochemistry_6010', 'url': 'https://doi.org/10.1039/C0CP01001D', @@ -25,7 +25,7 @@ The data of the entry can be called as a pandas dataframe:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df t E j 0 0.000000 -0.103158 -0.998277 @@ -141,7 +141,7 @@ def metadata(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata['echemdb']['source']['citationKey'] 'alves_2011_electrochemistry_6010' @@ -150,14 +150,14 @@ def metadata(self): Load metadata from a dict:: - >>> new_entry = Entry.create_examples()[0] + >>> new_entry = Entry.create_example() >>> new_entry.metadata.from_dict({'echemdb': {'test': 'data'}}) >>> new_entry.metadata['echemdb']['test'] 'data' The descriptor is cached but still sees metadata updates:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> descriptor1 = entry.metadata >>> entry.metadata.from_dict({'custom': {'key': 'value'}}) >>> descriptor2 = entry.metadata @@ -183,7 +183,7 @@ def load_metadata(self, filename, file_format=None, key=None): >>> import os >>> import tempfile >>> import yaml - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f: ... yaml.dump({'source': {'citationKey': 'chain_test'}}, f) ... temp_path = f.name @@ -196,7 +196,7 @@ def load_metadata(self, filename, file_format=None, key=None): >>> import os >>> import json >>> import tempfile - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f: ... json.dump({'custom': {'data': 'value'}}, f) ... temp_path = f.name @@ -237,7 +237,7 @@ def identifier(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.identifier 'alves_2011_electrochemistry_6010_f1a_solid' @@ -252,9 +252,9 @@ def __dir__(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> dir(entry) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - [... 'add_offset', 'apply_scaling_factor', 'create_examples', 'default_metadata_key', + [... 'add_offset', 'apply_scaling_factor', 'create_example', 'default_metadata_key', 'df', 'echemdb', 'field_unit', 'fields', 'from_csv', 'from_df', 'from_local', 'identifier', 'load_metadata', 'metadata', 'plot', 'remove_column', 'remove_columns', 'rename_field', 'rename_fields', @@ -269,7 +269,7 @@ def __getattr__(self, name): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.echemdb.source # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE {'citationKey': 'alves_2011_electrochemistry_6010', 'url': 'https://doi.org/10.1039/C0CP01001D', @@ -291,7 +291,7 @@ def __getitem__(self, name): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry["echemdb"]["source"] # doctest: +NORMALIZE_WHITESPACE {'citationKey': 'alves_2011_electrochemistry_6010', 'url': 'https://doi.org/10.1039/C0CP01001D', @@ -319,7 +319,7 @@ def _descriptor(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry._descriptor # doctest: +ELLIPSIS {'echemdb': ...} @@ -340,7 +340,7 @@ def _metadata(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry._metadata # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE {...'echemdb': {...'source': {'citationKey': 'alves_2011_electrochemistry_6010',...}...} @@ -359,7 +359,7 @@ def _default_metadata(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry._default_metadata # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE {...'echemdb': {...'source': {'citationKey': 'alves_2011_electrochemistry_6010',...}...} @@ -378,7 +378,7 @@ def fields(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.fields [{'name': 't', 'type': 'number', 'unit': 's'}, {'name': 'E', 'type': 'number', 'unit': 'V', 'reference': 'RHE'}, @@ -393,7 +393,7 @@ def field_unit(self, field_name): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.field_unit('E') 'V' @@ -415,7 +415,7 @@ def rescale(self, units): The units without any rescaling:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.fields [{'name': 't', 'type': 'number', 'unit': 's'}, {'name': 'E', 'type': 'number', 'unit': 'V', 'reference': 'RHE'}, @@ -477,7 +477,7 @@ def add_offset(self, field_name=None, offset=None, unit=""): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df.head() # doctest: +NORMALIZE_WHITESPACE t E j 0 0.00 -0.103158 -0.998277 @@ -586,7 +586,7 @@ def apply_scaling_factor(self, field_name=None, scaling_factor=None): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df.head() # doctest: +NORMALIZE_WHITESPACE t E j 0 0.00 -0.103158 -0.998277 @@ -673,7 +673,7 @@ def _create_new_df_resource(self, df, schema=None, field_updates=None): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> df = entry.df.copy() >>> new_resource = entry._create_new_df_resource(df) >>> new_resource.name == entry.resource.name @@ -717,7 +717,7 @@ def _df_resource(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> resource = entry._df_resource >>> resource.format 'pandas' @@ -752,7 +752,7 @@ def df(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df t E j 0 0.000000 -0.103158 -0.998277 @@ -788,7 +788,7 @@ def add_columns(self, df, new_fields): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df t E j 0 0.000000 -0.103158 -0.998277 @@ -847,7 +847,7 @@ def remove_column(self, field_name): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df t E j 0 0.000000 -0.103158 -0.998277 @@ -890,7 +890,7 @@ def remove_columns(self, *field_names): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df t E j 0 0.000000 -0.103158 -0.998277 @@ -938,7 +938,7 @@ def __repr__(self): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry Entry('alves_2011_electrochemistry_6010_f1a_solid') @@ -946,48 +946,30 @@ def __repr__(self): return f"Entry({repr(self.identifier)})" @classmethod - def create_examples(cls, name=""): + def create_example(cls, name=None): r""" - Return some example entries for use in automated tests. + Return an example entry for use in automated tests. The examples are created from Data Packages in the unitpackage's examples directory. These are only available from the development environment. EXAMPLES:: - >>> Entry.create_examples() - [Entry('alves_2011_electrochemistry_6010_f1a_solid'), Entry('engstfeld_2018_polycrystalline_17743_f4b_1'), Entry('no_bibliography')] - - An entry without associated BIB file. + >>> Entry.create_example() + Entry('alves_2011_electrochemistry_6010_f1a_solid') - >>> Entry.create_examples(name="no_bibliography") - [Entry('no_bibliography')] + >>> Entry.create_example(name="no_bibliography") + Entry('no_bibliography') """ - example_dir = os.path.join( - os.path.dirname(__file__), "..", "examples", "local", name - ) - - if not os.path.exists(example_dir): - raise ValueError( - f"No subdirectory in examples/ for {name}, i.e., could not find {example_dir}." - ) - - from unitpackage.local import collect_datapackages - - packages = collect_datapackages(example_dir) + if name is None: + name = "alves_2011_electrochemistry_6010_f1a_solid" - if len(packages) == 0: - from glob import glob - - raise ValueError( - f"No literature data found for {name}. The directory for this data {example_dir} exists. But we could not find any datapackages in there. " - f"There is probably some outdated data in {example_dir}. The contents of that directory are: { glob(os.path.join(example_dir,'**')) }" - ) + from unitpackage.collection import Collection - from unitpackage.local import collect_resources + collection = Collection.create_example() - return [cls(resource=resource) for resource in collect_resources(packages)] + return cls(resource=collection[name].resource) def plot(self, x_label=None, y_label=None, name=None): r""" @@ -997,7 +979,7 @@ def plot(self, x_label=None, y_label=None, name=None): EXAMPLES:: - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.plot() Figure(...) @@ -1061,7 +1043,7 @@ def update_fields(self, fields): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.fields # doctest: +NORMALIZE_WHITESPACE [{'name': 't', 'type': 'number', 'unit': 's'}, {'name': 'E', 'type': 'number', 'unit': 'V', 'reference': 'RHE'}, @@ -1230,7 +1212,7 @@ def rename_field(self, field_name, new_name, keep_original_name_as=None): The original dataframe:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df t E j 0 0.000000 -0.103158 -0.998277 @@ -1288,7 +1270,7 @@ def rename_fields(self, field_names, keep_original_name_as=None): The original dataframe:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.df t E j 0 0.000000 -0.103158 -0.998277 @@ -1445,7 +1427,7 @@ def save(self, *, outdir, basename=None): The output files are named ``identifier.csv`` and ``identifier.json`` using the identifier of the original resource:: >>> import os - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.save(outdir='./test/generated') >>> basename = entry.identifier >>> os.path.exists(f'test/generated/{basename}.json') and os.path.exists(f'test/generated/{basename}.csv') @@ -1461,7 +1443,7 @@ def save(self, *, outdir, basename=None): A valid basename:: >>> import os - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> basename = 'save_basename' >>> entry.save(basename=basename, outdir='./test/generated') >>> os.path.exists(f'test/generated/{basename}.json') and os.path.exists(f'test/generated/{basename}.csv') diff --git a/unitpackage/metadata.py b/unitpackage/metadata.py index 1bd0e70..554dc4c 100644 --- a/unitpackage/metadata.py +++ b/unitpackage/metadata.py @@ -10,7 +10,7 @@ Access metadata with dict-style or attribute-style syntax:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata['echemdb']['source']['citationKey'] 'alves_2011_electrochemistry_6010' @@ -55,7 +55,7 @@ class MetadataDescriptor: EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata # doctest: +ELLIPSIS {'echemdb': {'experimental': ... @@ -88,7 +88,7 @@ def __getitem__(self, key): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata['echemdb']['source']['citationKey'] 'alves_2011_electrochemistry_6010' @@ -102,7 +102,7 @@ def __setitem__(self, key, value): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata['custom_key'] = {'data': 'value'} >>> entry.metadata['custom_key'] {'data': 'value'} @@ -117,7 +117,7 @@ def __getattr__(self, name): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata.echemdb.source.citationKey 'alves_2011_electrochemistry_6010' @@ -131,7 +131,7 @@ def from_dict(self, data): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata.from_dict({'echemdb': {'source': {'citationKey': 'test'}}}) >>> entry.metadata['echemdb']['source']['citationKey'] 'test' @@ -146,7 +146,7 @@ def _add_metadata(self, key, data): EXAMPLES:: >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> entry.metadata._add_metadata('custom_key', {'data': 'value'}) >>> entry.metadata['custom_key'] {'data': 'value'} @@ -177,7 +177,7 @@ def from_yaml(self, filename, key=None): >>> import tempfile >>> import yaml >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f: ... yaml.dump({'source': {'citationKey': 'yaml_test'}}, f) ... temp_path = f.name @@ -207,7 +207,7 @@ def from_json(self, filename, key=None): >>> import json >>> import tempfile >>> from unitpackage.entry import Entry - >>> entry = Entry.create_examples()[0] + >>> entry = Entry.create_example() >>> with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f: ... json.dump({'source': {'citationKey': 'json_test'}}, f) ... temp_path = f.name