Source code for standard_names.standardname
#! /usr/bin/env python
"""A CSDMS standard name."""
import re
from six import string_types
from .error import BadNameError
_PREFIX_REGEX = "^[a-z]([a-zA-Z0-9~-]|_(?!_))*"
_SUFFIX_REGEX = "[a-z0-9]([a-z0-9~-]|_(?!_))*[a-z0-9]$"
STANDARD_NAME_REGEX = re.compile(_PREFIX_REGEX + "(__)" + _SUFFIX_REGEX)
# '^[a-z][a-z0-9_]*[a-z0-9](__)[a-z0-9][a-z0-9_]*[a-z0-9]$'
[docs]def is_valid_name(name):
"""Check if a string is a valid standard name.
Parameters
----------
name : str
Standard name as a string
Returns
-------
bool
``True`` if the string is a valid standard name
"""
return bool(STANDARD_NAME_REGEX.match(name))
[docs]class StandardName(object):
"""A CSDMS standard name.
Examples
--------
>>> import standard_names as csn
>>> name = csn.StandardName('air__temperature')
>>> name == 'air__temperature'
True
>>> repr(name)
"StandardName('air__temperature')"
>>> name.object = 'water'
>>> repr(name)
"StandardName('water__temperature')"
>>> name.quantity = 'density'
>>> repr(name)
"StandardName('water__density')"
>>> name.operators = ('max', )
>>> repr(name)
"StandardName('water__max_of_density')"
>>> name.operators = 'min'
>>> repr(name)
"StandardName('water__min_of_density')"
"""
re = _PREFIX_REGEX + "(__)" + _SUFFIX_REGEX
def __init__(self, name):
"""Create a standard name object from a string.
Parameters
----------
name : str
A Standard Name.
"""
if not is_valid_name(name):
raise BadNameError(name)
self._name = name
(self._object, self._quantity, self._operators) = StandardName.decompose_name(
name
)
[docs] @staticmethod
def decompose_name(name):
"""Decompose a name into its parts.
Decompose the *name* standard name string into it's constituent
parts (object, quantity, and operator). Returns a tuple of
(object, quantity, operator) where object and quantitiy are strings,
and operator is itself a tuple of strings (or empty).
Parameters
----------
name : str
A CSDMS Standard Name.
Returns
-------
tuple of str
The parts of a name as ``(object, quantity, operators)``
Examples
--------
>>> import standard_names as csn
>>> name = 'atmosphere_air__elevation_angle_of_gradient_of_temperature'
>>> csn.StandardName.decompose_name(name)
('atmosphere_air', 'temperature', ('elevation_angle', 'gradient'))
>>> try:
... StandardName.decompose_name('air_temperature')
... except BadNameError:
... pass
"""
try:
(object_part, quantity_clause) = name.split("__")
except ValueError:
raise BadNameError(name)
(operators, quantity_part) = StandardName.decompose_quantity(quantity_clause)
return object_part, quantity_part, operators
[docs] @staticmethod
def compose_name(object, quantity, operators=()):
"""Create a string from the parts of StandardName.
Parameters
----------
object : str
An StandardName object.
quantity : str
An StandardName quantity.
operators : iterable of str, optional
Operators applied to the quantity.
Returns
-------
str
The standard name composed of the given elements.
Examples
--------
>>> import standard_names as csn
>>> name = 'atmosphere_air__elevation_angle_of_gradient_of_temperature'
>>> parts = csn.StandardName.decompose_name(name)
>>> csn.StandardName.compose_name(*parts) == name
True
>>> csn.StandardName.compose_name('air', 'temperature')
'air__temperature'
"""
operator = "_of_".join(operators)
if len(operator) > 0:
quantity = "_of_".join([operator, quantity])
return "__".join((object, quantity))
[docs] @staticmethod
def decompose_quantity(quantity_clause):
"""Decompose a quantity into operators and quantities.
Decompose the *quantity_clause* string into operator and base
quantity constituents. Because multiple operators can act on a
quantity, the operators are given as a tuple regardless of the
number of operators actually present. Returns the parts of the
quantity as a tuple of (operators, base_quantity)
Parameters
----------
quantity_clause : str
A CSDMS Standard Name quantity.
Returns
-------
tuple of str
The parts of the quantity as ``(operators, quantity)``.
"""
quantity_parts = quantity_clause.split("_of_")
quantity = quantity_parts[-1]
operators = tuple(quantity_parts[:-1])
return operators, quantity
@property
def name(self):
"""The full standard name as a string."""
return self._name
@property
def object(self):
"""The object part of the standard name."""
return self._object
@object.setter
def object(self, value):
self._object = value
self._name = StandardName.compose_name(
self.object, self.quantity, self.operators
)
@property
def quantity(self):
"""The quantity part of the standard name."""
return self._quantity
@quantity.setter
def quantity(self, value):
self._quantity = value
self._name = StandardName.compose_name(
self.object, self.quantity, self.operators
)
@property
def operators(self):
"""The operator part of the standard name."""
return self._operators
@operators.setter
def operators(self, value):
if isinstance(value, string_types):
value = (value,)
self._operators = value
self._name = StandardName.compose_name(
self.object, self.quantity, self.operators
)
def __repr__(self):
return "StandardName(%r)" % self.name
def __str__(self):
return self.name
def __eq__(self, that):
return self.name == str(that)
def __ne__(self, that):
return self.name != str(that)
def __lt__(self, that):
return self.name < str(that)
def __gt__(self, that):
return self.name > str(that)
def __cmp__(self, that):
return self.name == str(that)
def __hash__(self):
return hash(self.name)