Coverage for python/lsst/verify/naming.py : 97%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# # LSST Data Management System # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # See COPYRIGHT file at the top of the source tree. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see <https://www.lsstcorp.org/LegalNotices/>. # specifications. """
"""Semantic name of a package, `~lsst.verify.Metric` or `~lsst.verify.Specification` in the `lsst.verify` framework.
``Name`` instances are immutable and can be used as keys in mappings.
Parameters ---------- package : `str` or `Name` Name of the package, either as a string (``'validate_drp'``, for example) or as a `~lsst.verify.Name` object (``Name(package='validate_drp')`` for example).
The ``package`` field can also be fully specified:
>>> Name(package='validate_drp.PA1.design_gri') Name('validate_drp', 'PA1', 'design_gri')
Or the ``package`` field can be used as the sole positional argument:
>>> Name('validate_drp.PA1.design_gri') Name('validate_drp', 'PA1', 'design_gri')
metric : `str` or `Name` Name of the metric. The name can be relative (``'PA'``) or fully-specified (``'validate_drp.PA1'``).
spec : `str` or `Name` Name of the specification. The name can be bare (``'design_gri'``), metric-relative (``'PA1.design_gri'``) or fully-specified (``'validate_drp.PA1.design_gri'``)
Raises ------ TypeError Raised when arguments cannot be parsed or conflict (for example, if two different package names are specified through two different fields).
Notes ----- Names in the Verification Framework are formatted as::
package.metric.specification
A **fully-qualified name** is one that has all components included. For example, a fully specified metric name is::
validate_drp.PA1
This means: "the ``PA1`` metric in the ``validate_drp`` package.
An example of a fully-specificed *specification* name::
validate_drp.PA1.design
This means: "the ``design`` specification of the ``PA1`` metric in the ``validate_drp`` package.
A **relative name** is one that's missing a component. For example::
PA1.design
Asserting this is a relative specification name, the package is not known.
Examples --------
**Creation**
There are many patterns for creating Name instances. Different patterns are useful in different circumstances.
You can create a metric name from its components:
>>> Name(package='validate_drp', metric='PA1') Name('validate_drp', 'PA1')
Or a specification name from components:
>>> Name(package='validate_drp', metric='PA1', spec='design') Name('validate_drp', 'PA1', 'design')
You can equivalently create ``Name``\ s from fully-qualified strings:
>>> Name('validate_drp.PA1') Name('validate_drp', 'PA1')
>>> Name('validate_drp.PA1.design') Name('validate_drp', 'PA1', 'design')
You can also use an existing name to specify some components of the name:
>>> metric_name = Name('validate_drp.PA1') >>> Name(metric=metric_name, spec='design') Name('validate_drp', 'PA1', 'design')
A `TypeError` is raised if any components of the input names conflict.
Fully-specified metric names can be mixed with a ``spec`` component:
>>> Name(metric='validate_drp.PA1', spec='design') Name('validate_drp', 'PA1', 'design')
**String representation**
Converting a ``Name`` into a `str` gives you the canonical string representation, as fully-specified as possible:
>>> str(Name('validate_drp', 'PA1', 'design')) 'validate_drp.PA1.design'
Alternatively, obtain the fully-qualified metric name from the `Name.fqn` property:
>>> name = Name('validate_drp', 'PA1', 'design') >>> name.fqn 'validate_drp.PA1.design'
The relative name of a specification omits the package component:
>>> name = Name('validate_drp.PA1.design') >>> name.relative_name 'PA1.design' """
else: # Assume a string type Name._parse_fqn_string(package) except ValueError as e: # Want to raise TypeError in __init__ raise TypeError(str(e))
'metric={metric!r} argument does not include metric ' 'information.'.format(metric=metric)) else: Name._parse_metric_name_string(metric) except ValueError as e: # Want to raise TypeError in __init__ raise TypeError(str(e))
# Ensure none of the new information is inconsistent
'spec={spec!r} argument does not include ' 'specification information'.format(spec=spec)) else: Name._parse_spec_name_string(spec) except ValueError as e: # want to raise TypeError in __init__ raise TypeError(str(e))
# Ensure none of the new information is inconsistent
# Ensure the name doesn't have a metric gap and self._spec is not None \ and self._metric is None: "spec={spec!r}".format(package=package, spec=spec))
"""Check and add new package information (for __init__).""" # There's new or consistent package info else:
"""Check and add new metric information (for __init__).""" # There's new or consistent metric info else:
"""Check and add new spec information (for __init__).""" # There's new or consistent spec info else:
def _parse_fqn_string(fqn): """Parse a fully-qualified name. """ # Must be a package name alone # Must be a fully-qualified metric name # Must be a fully-qualified specification name else: # Don't know what this string is raise ValueError('Cannot parse fully qualified name: ' '{0!r}'.format(fqn))
def _parse_metric_name_string(name): """Parse a metric name.""" # Must be a fully-qualified metric name # A bare metric name else: # Don't know what this string is raise ValueError('Cannot parse metric name: ' '{0!r}'.format(name))
def _parse_spec_name_string(name): """Parse a specification name.""" # Bare specification name # metric-relative specification name # fully-qualified specification name else: # Don't know what this string is raise ValueError('Cannot parse specification name: ' '{0!r}'.format(name))
def package(self): """Package name (`str`).
>>> name = Name('validate_drp.PA1.design') >>> name.package 'validate_drp' """
def metric(self): """Metric name (`str`).
>>> name = Name('validate_drp.PA1.design') >>> name.metric 'PA1' """
def spec(self): """Specification name (`str`).
>>> name = Name('validate_drp.PA1.design') >>> name.spec 'design' """
"""Test equality of two specifications.
Examples -------- >>> name1 = Name('validate_drp.PA1.design') >>> name2 = Name('validate_drp', 'PA1', 'design') >>> name1 == name2 True """ (self.metric == other.metric) and \ (self.spec == other.spec)
"""Test self < other to support name ordering.""" # test package component first
# test metric component second if packages equal
# test spec component lastly if everything else equal
# They're equal
"""Test self > other to support name ordering.""" # test package component first
# test metric component second if packages equal
# test spec component lastly if everything else equal
# They're equal
"""Test self <= other to support name ordering.""" else:
"""Test self >= other to support name ordering.""" else:
"""Test if another Name is contained by this Name.
A specification can be in a metric and a package. A metric can be in a package.
Examples -------- >>> spec_name = Name('validate_drp.PA1.design') >>> metric_name = Name('validate_drp.PA1') >>> package_name = Name('validate_drp') >>> spec_name in metric_name True >>> package_name in metric_name False """
else:
else:
else: # Must be a specification, which cannot 'contain' anything
def has_package(self): """`True` if this object contains a package name (`bool`).
>>> Name('validate_drp.PA1').has_package True >>> Name(spec='design').has_package False """ else:
def has_spec(self): """`True` if this object contains a specification name, either relative or fully-qualified (`bool`).
>>> Name(spec='design').has_spec True >>> Name('validate_drp.PA1').has_spec False """ else:
def has_metric(self): """`True` if this object contains a metric name, either relative or fully-qualified (`bool`).
>>> Name('validate_drp.PA1').has_metric True >>> Name(spec='design').has_metric False """ else:
def has_relative(self): """`True` if a relative specification name can be formed from this object, i.e., `metric` and `spec` attributes are set (`bool`). """ else:
def is_package(self): """`True` if this object is a package name (`bool`).
>>> Name('validate_drp').is_package True >>> Name('validate_drp.PA1').is_package False """ self.is_metric is False and \ self.is_spec is False: else:
def is_metric(self): """`True` if this object is a metric name, either relative or fully-qualified (`bool`).
>>> Name('validate_drp.PA1').is_metric True >>> Name('validate_drp.PA1.design').is_metric False """ else:
def is_spec(self): """`True` if this object is a specification name, either relative or fully-qualified (`bool`).
>>> Name('validate_drp.PA1').is_spec False >>> Name('validate_drp.PA1.design').is_spec True """ else:
def is_fq(self): """`True` if this object is a fully-qualified name of either a package, metric or specification (`bool`).
Examples -------- A fully-qualified package name:
>>> Name('validate_drp').is_fq True
A fully-qualified metric name:
>>> Name('validate_drp.PA1').is_fq True
A fully-qualified specification name:
>>> Name('validate_drp.PA1.design_gri').is_fq True """ # package names are by definition fully qualified # fully-qualified metric # fully-qualified specification else:
def is_relative(self): """`True` if this object is a specification name that's not fully-qualified, but is relative to a metric name (`bool`). relative to a base name. (`bool`).
Package and metric names are never relative.
A relative specification name:
>>> Name(spec='PA1.design_gri').is_relative True
But not:
>>> Name('validate_drp.PA1.design_gri').is_relative False """ self.has_metric is True and \ self.has_package is False: else:
self=self) self=self) self=self) else: # Should be a fully-qualified specification
"""Canonical string representation of a Name (`str`).
Examples:
>>> str(Name(package='validate_drp')) 'validate_drp' >>> str(Name(package='validate_drp', metric='PA1')) 'validate_drp.PA1' >>> str(Name(package='validate_drp', metric='PA1', spec='design')) 'validate_drp.PA1.design' >>> str(Name(metric='PA1', spec='design')) 'PA1.design' """ else: # Should be a fully-qualified specification self=self)
def fqn(self): """The fully-qualified name (`str`).
Raises ------ AttributeError If the name is not a fully-qualified name (check `is_fq`)
Examples -------- >>> Name('validate_drp', 'PA1').fqn 'validate_drp.PA1' >>> Name('validate_drp', 'PA1', 'design').fqn 'validate_drp.PA1.design' """ else:
def relative_name(self): """The relative specification name (`str`).
Raises ------ AttributeError If the object does not represent a specification, or if a relative name cannot be formed because the `metric` is None.
Examples -------- >>> Name('validate_drp.PA1.design').relative_name 'PA1.design' """ else: |