Skip to content

Commit

Permalink
Merge pull request #138 from davidhassell/performance2
Browse files Browse the repository at this point in the history
Performance improvements, and associated API changes
  • Loading branch information
davidhassell authored May 10, 2021
2 parents fb4679a + 0a60a47 commit 4120dcf
Show file tree
Hide file tree
Showing 109 changed files with 6,790 additions and 4,305 deletions.
5 changes: 4 additions & 1 deletion cfdm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@
Configuration,
Constant,
ConstantAccess,
is_log_level_debug,
is_log_level_detail,
is_log_level_info,
)

# Though these are internal-use methods, include them in the namespace
Expand Down Expand Up @@ -156,7 +159,7 @@

from .read_write import read, write

from .examplefield import example_field
from .examplefield import example_field, example_fields, example_domain

from .abstract import Container

Expand Down
12 changes: 9 additions & 3 deletions cfdm/bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,13 @@ def get_data(self, default=ValueError(), _units=True, _fill_value=True):
data = super().get_data(
default=None, _units=_units, _fill_value=_fill_value
)

if data is None:
return super().get_data(default=default)
if default is None:
return

return self._default(
default, f"{self.__class__.__name__} has no data"
)

if _units or _fill_value:
inherited_properties = self._get_component(
Expand Down Expand Up @@ -276,7 +280,9 @@ def identity(self, default=""):
'longitude'
"""
inherited_properties = self._get_component("inherited_properties", {})
inherited_properties = self._get_component(
"inherited_properties", None
)
if inherited_properties:
bounds = self.copy()
properties = bounds.properties()
Expand Down
37 changes: 30 additions & 7 deletions cfdm/cellmeasure.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ def identity(self, default=""):

return default

def identities(self):
def identities(self, generator=False, **kwargs):
"""Return all possible identities.
The identities comprise:
Expand All @@ -416,9 +416,23 @@ def identities(self):
.. seealso:: `identity`
:Parameters:
generator: `bool`, optional
If True then return a generator for the identities,
rather than a list.
.. versionadded:: (cfdm) 1.8.9.0
kwargs: optional
Additional configuration parameters. Currently
none. Unrecognised parameters are ignored.
.. versionadded:: (cfdm) 1.8.9.0
:Returns:
`list`
`list` or generator
The identities.
**Examples:**
Expand All @@ -434,12 +448,21 @@ def identities(self):
'cell_measure'
>>> c.identities()
['measure:area', 'units=km2', 'ncvar%cell_measure']
>>> for i in c.identities(generator=True):
... print(i)
...
measure:area
units=km2
ncvar%cell_measure
"""
out = super().identities()
measure = self.get_measure(None)
if measure is not None:
pre = ((f"measure:{measure}",),)
pre0 = kwargs.pop("pre", None)
if pre0:
pre = tuple(pre0) + pre

n = self.get_measure(None)
if n is not None:
out.insert(0, f"measure:{n}")
kwargs["pre"] = pre

return out
return super().identities(generator=generator, **kwargs)
108 changes: 64 additions & 44 deletions cfdm/cellmethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ def __str__(self):

return " ".join(string)

def _identities_iter(self):
"""Return all possible identities.
See `identities` for details and examples.
:Returns:
generator
The identities.
"""
n = self.get_method(None)
if n is not None:
yield f"method:{n}"

def creation_commands(
self, namespace=None, indent=0, string=True, name="c", header=True
):
Expand Down Expand Up @@ -184,8 +199,8 @@ def creation_commands(
def dump(self, display=True, _title=None, _level=0):
"""A full description of the cell method construct.
Returns a description the method, all qualifiers and the axes to
which it applies.
Returns a description the method, all qualifiers and the axes
to which it applies.
.. versionadded:: (cfdm) 1.7.0
Expand Down Expand Up @@ -227,14 +242,14 @@ def equals(
The axes of the cell method constructs are *not* considered,
because they may only be correctly interpreted by the field
constructs that contain the cell method constructs in
question. They are, however, taken into account when two fields
constructs are tested for equality.
question. They are, however, taken into account when two
fields constructs are tested for equality.
{{equals tolerance}}
Any type of object may be tested but, in general, equality is only
possible with another cell method construct, or a subclass of
one. See the *ignore_type* parameter.
Any type of object may be tested but, in general, equality is
only possible with another cell method construct, or a
subclass of one. See the *ignore_type* parameter.
{{equals tolerance}}
Expand Down Expand Up @@ -285,12 +300,9 @@ def equals(
# ------------------------------------------------------------
if self.get_method(None) != other.get_method(None):
logger.info(
"{0}: Different methods: {1!r} != {2!r}".format(
self.__class__.__name__,
self.get_method(None),
other.get_method(None),
)
)
f"{self.__class__.__name__}: Different methods: "
f"{self.get_method(None)!r} != {other.get_method(None)!r}"
) # pragma: no cover
return False

# ------------------------------------------------------------
Expand All @@ -308,10 +320,8 @@ def equals(
other_qualifiers
):
logger.info(
"{0}: Non-common qualifier: {1!r}".format(
self.__class__.__name__, q
)
)
f"{self.__class__.__name__}: Non-common qualifier: {q!r}"
) # pragma: no cover
return False

for qualifier, x in self_qualifiers.items():
Expand All @@ -324,12 +334,12 @@ def equals(
atol=atol,
ignore_data_type=True,
verbose=verbose,
basic=True,
):
logger.info(
"{0}: Different {1} qualifiers: {2!r}, {3!r}".format(
self.__class__.__name__, prop, x, y
)
)
f"{self.__class__.__name__}: Different {prop} "
f"qualifiers: {x!r}, {y!r}"
) # pragma: no cover
return False

if "interval" in ignore_qualifiers:
Expand All @@ -340,19 +350,17 @@ def equals(
if intervals0:
if not intervals1:
logger.info(
"{0}: Different interval qualifiers: "
"{1!r} != {2!r}".format(
self.__class__.__name__, intervals0, intervals1
)
)
f"{self.__class__.__name__}: Different interval "
f"qualifiers: {intervals0!r} != {intervals1!r}"
) # pragma: no cover
return False

if len(intervals0) != len(intervals1):
logger.info(
"{0}: Different numbers of interval qualifiers: "
"{1!r} != {2!r}".format(
self.__class__.__name__, intervals0, intervals1
)
) # pragma: no cover
)
return False

Expand All @@ -367,19 +375,16 @@ def equals(
ignore_fill_value=True,
):
logger.info(
"{0}: Different interval qualifiers: "
"{1!r} != {2!r}".format(
self.__class__.__name__, intervals0, intervals1
)
)
f"{self.__class__.__name__}: Different interval "
f"qualifiers: {intervals0!r} != {intervals1!r}"
) # pragma: no cover
return False

elif intervals1:
logger.info(
"{}: Different intervals: {!r} != {!r}".format(
self.__class__.__name__, intervals0, intervals1
)
)
f"{self.__class__.__name__}: Different intervals: "
f"{intervals0!r} != {intervals1!r}"
) # pragma: no cover
return False

# ------------------------------------------------------------
Expand Down Expand Up @@ -432,7 +437,7 @@ def identity(self, default=""):

return default

def identities(self):
def identities(self, generator=False, **kwargs):
"""Return all possible identities.
The identities comprise:
Expand All @@ -443,9 +448,23 @@ def identities(self):
.. seealso:: `identity`
:Parameters:
generator: `bool`, optional
If True then return a generator for the identities,
rather than a list.
.. versionadded:: (cfdm) 1.8.9.0
kwargs: optional
Additional configuration parameters. Currently
none. Unrecognised parameters are ignored.
.. versionadded:: (cfdm) 1.8.9.0
:Returns:
`list`
`list` or generator
The identities.
**Examples:**
Expand All @@ -460,15 +479,16 @@ def identities(self):
'maximum'
>>> c.identities()
[]
>>> for i in c.identities(generator=True):
... print(i)
...
"""
out = []
g = self._iter(body=self._identities_iter(), **kwargs)
if generator:
return g

n = self.get_method(None)
if n is not None:
out.append(f"method:{n}")

return out
return list(g)

def sorted(self, indices=None):
"""Return a new cell method construct with sorted axes.
Expand Down
Loading

0 comments on commit 4120dcf

Please sign in to comment.