Source code for landlab._registry

#! /usr/bin/env python
r"""Registry of landlab components being used.

The landlab registry keeps track of landlab components that have
be instantiated by a user. A user can then get a list of all
the components in use and then print a list of citations for
all of the components they have used.

Examples
--------
>>> from landlab import registry

>>> registry.registered
('landlab',)
>>> print(registry.format_citations())
# Citations
## landlab
    @article{hobley2017creative,
    title={Creative computing with Landlab: an open-source toolkit
        for building, coupling, and exploring two-dimensional
        numerical models of Earth-surface dynamics},
    author={Hobley, Daniel EJ and Adams, Jordan M and Nudurupati,
        Sai Siddhartha and Hutton, Eric WH and Gasparini, Nicole M and
        Istanbulluoglu, Erkan and Tucker, Gregory E},
    journal={Earth Surface Dynamics},
    volume={5},
    number={1},
    pages={21},
    year={2017},
    publisher={Copernicus GmbH}
    }
    @article{barnhart2020short,
    author = {Barnhart, K. R. and Hutton, E. W. H. and Tucker, G. E.
        and Gasparini, N. M. and Istanbulluoglu, E. and Hobley,
        D. E. J. and Lyons, N. J. and Mouchene, M. and Nudurupati,
        S. S. and Adams, J. M. and Bandaragoda, C.},
    title = {Short communication: Landlab v2.0: A software package
        for Earth surface dynamics},
    journal = {Earth Surface Dynamics Discussions},
    volume = {2020},
    year = {2020},
    pages = {1--25},
    url = {https://www.earth-surf-dynam-discuss.net/esurf-2020-12/},
    doi = {10.5194/esurf-2020-12}
    }

When a component contains citation information, and the component has been
instantiated (not just imported) the component citation is also included.

>>> from landlab import RasterModelGrid
>>> from landlab.components import Flexure

>>> grid = RasterModelGrid((4, 5))
>>> _ = grid.add_zeros("lithosphere__overlying_pressure_increment", at="node")
>>> _ = grid.add_zeros("lithosphere_surface__elevation_increment", at="node")
>>> flexure = Flexure(grid)
>>> print(registry.format_citations())
# Citations
## landlab
    @article{hobley2017creative,
    title={Creative computing with Landlab: an open-source toolkit
        for building, coupling, and exploring two-dimensional
        numerical models of Earth-surface dynamics},
    author={Hobley, Daniel EJ and Adams, Jordan M and Nudurupati,
        Sai Siddhartha and Hutton, Eric WH and Gasparini, Nicole M and
        Istanbulluoglu, Erkan and Tucker, Gregory E},
    journal={Earth Surface Dynamics},
    volume={5},
    number={1},
    pages={21},
    year={2017},
    publisher={Copernicus GmbH}
    }
    @article{barnhart2020short,
    author = {Barnhart, K. R. and Hutton, E. W. H. and Tucker, G. E.
        and Gasparini, N. M. and Istanbulluoglu, E. and Hobley,
        D. E. J. and Lyons, N. J. and Mouchene, M. and Nudurupati,
        S. S. and Adams, J. M. and Bandaragoda, C.},
    title = {Short communication: Landlab v2.0: A software package
        for Earth surface dynamics},
    journal = {Earth Surface Dynamics Discussions},
    volume = {2020},
    year = {2020},
    pages = {1--25},
    url = {https://www.earth-surf-dynam-discuss.net/esurf-2020-12/},
    doi = {10.5194/esurf-2020-12}
    }
<BLANKLINE>
## Flexure
    @article{hutton2008sedflux,
    title={Sedflux 2.0: An advanced process-response model that
        generates three-dimensional stratigraphy},
    author={Hutton, Eric WH and Syvitski, James PM},
    journal={Computers \& Geosciences},
    volume={34},
    number={10},
    pages={1319--1337},
    year={2008},
    publisher={Pergamon}
    }

Finally, the component's citation information is accessible through an
attribute called ``cite_as``:

>>> print(Flexure.cite_as)
    @article{hutton2008sedflux,
    title={Sedflux 2.0: An advanced process-response model that
        generates three-dimensional stratigraphy},
    author={Hutton, Eric WH and Syvitski, James PM},
    journal={Computers \& Geosciences},
    volume={34},
    number={10},
    pages={1319--1337},
    year={2008},
    publisher={Pergamon}
    }

"""

import os

from . import _info
from .core.messages import indent_and_wrap


[docs] class ComponentRegistry: """A registry for instantiated landlab components.""" def __init__(self, objs=None): self._registered = [] if objs is not None: try: [self.add(obj) for obj in objs] except TypeError: self.add(objs)
[docs] def add(self, cls): """Add a class to the registry. Parameters ---------- cls : Component A landlab component to register as used. """ if cls not in self._registered: self._registered.append(cls)
@property def registered(self): """All registered classes. Returns ------- tuple The components in the registry. Examples -------- >>> from landlab._registry import ComponentRegistry >>> registry = ComponentRegistry() >>> registry.registered () >>> class FooBar(object): ... pass ... >>> registry.add(FooBar) >>> registry.registered ('FooBar',) """ return tuple(ComponentRegistry.get_name(obj) for obj in self._registered)
[docs] @staticmethod def format_citation(obj): """Format a single citation. Parameters ---------- obj : Component A landlab component class or instance. Returns ------- str The formatted citation, or "None" if there is no citation given. Examples -------- >>> from landlab._registry import ComponentRegistry >>> registry = ComponentRegistry() >>> class DoNothingComponent(object): ... pass ... >>> print(registry.format_citation(DoNothingComponent)) ## DoNothingComponent None >>> class SorterAndSearcher(object): ... _cite_as = ''' ... @book{knuth1998art, ... title={The art of computer programming: sorting and searching}, ... author={Knuth, Donald Ervin}, ... volume={3}, ... year={1998}, ... publisher={Pearson Education} ... }''' ... >>> print(registry.format_citation(SorterAndSearcher)) ## SorterAndSearcher @book{knuth1998art, title={The art of computer programming: sorting and searching}, author={Knuth, Donald Ervin}, volume={3}, year={1998}, publisher={Pearson Education} } """ name = ComponentRegistry.get_name(obj) header = [f"## {name}"] cite_as = ComponentRegistry.get_citations(obj) body = [] for citation in cite_as: body.append(indent_and_wrap(citation, indent=" " * 4)) return os.linesep.join(header + body)
[docs] @staticmethod def get_name(obj): """Get the display name for an object. Examples -------- >>> from landlab._registry import ComponentRegistry >>> class MontyPython(object): ... name = "Eric Idle" ... >>> ComponentRegistry.get_name(MontyPython) 'Eric Idle' >>> class MontyPython(object): ... _name = "Graham Chapman" ... >>> ComponentRegistry.get_name(MontyPython) 'Graham Chapman' >>> class MontyPython(object): ... pass ... >>> ComponentRegistry.get_name(MontyPython) 'MontyPython' """ name = "Unknown" for attr in ("name", "_name", "__name__"): try: name = getattr(obj, attr) except AttributeError: pass else: break return name
[docs] @staticmethod def get_citations(obj): """Get a list of citations from an object.""" citations = "None" for attr in ("cite_as", "_cite_as"): try: citations = getattr(obj, attr) except AttributeError: pass else: break if isinstance(citations, str): citations = [citations] return citations
[docs] def format_citations(self): """Format citations for all registered components. Returns ------- str The formatted citations. Examples -------- >>> from landlab._registry import ComponentRegistry >>> registry = ComponentRegistry() >>> class HolyGrailFinder(object): ... _name = "Monty Python" ... _cite_as = [ ... '''@book{python2000holy, ... title={the Holy Grail}, ... author={Python, Monty and Chapman, Graham and Cleese, John and Gilliam, Terry and Jones, Terry and Idle, Eric and Palin, Michael}, ... year={2000}, ... publisher={EMI Records} ... }''', ... '''@book{chapman1989complete, ... title={The Complete Monty Python's Flying Circus: All the Words. Volume one}, ... author={Chapman, Graham and Python, Monty}, ... volume={1}, ... year={1989}, ... publisher={Pantheon} ... }''', ... ] ... >>> class Evolution(object): ... _cite_as = ''' ... @book{darwin1859origin, ... title={On the origin of species}, ... author={Darwin, Charles}, ... year={1859}, ... publisher={Lulu. com} ... }''' ... >>> registry.add(HolyGrailFinder) >>> registry.add(Evolution) >>> print(registry.format_citations()) # Citations ## Monty Python @book{python2000holy, title={the Holy Grail}, author={Python, Monty and Chapman, Graham and Cleese, John and Gilliam, Terry and Jones, Terry and Idle, Eric and Palin, Michael}, year={2000}, publisher={EMI Records} } @book{chapman1989complete, title={The Complete Monty Python's Flying Circus: All the Words. Volume one}, author={Chapman, Graham and Python, Monty}, volume={1}, year={1989}, publisher={Pantheon} } <BLANKLINE> ## Evolution @book{darwin1859origin, title={On the origin of species}, author={Darwin, Charles}, year={1859}, publisher={Lulu. com} } """ # noqa: B950 header = ["# Citations"] body = [] for cls in self._registered: body.append(self.format_citation(cls)) return os.linesep.join(header + [(2 * os.linesep).join(body)])
def __repr__(self): return f"ComponentRegistry({repr(self.registered)})"
registry = ComponentRegistry(_info)