Skip to content

Commit

Permalink
Merge pull request #82 from davidhassell/creation_commands
Browse files Browse the repository at this point in the history
Creation commands
  • Loading branch information
sadielbartholomew authored Sep 25, 2020
2 parents a1fce91 + 951ba8b commit 2d99270
Show file tree
Hide file tree
Showing 30 changed files with 1,204 additions and 11 deletions.
4 changes: 4 additions & 0 deletions Changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ version 1.8.7.0
**2020-09-??**

* New keyword parameter to `cfdm.Field.set_data`: ``inplace``
* New method: `cfdm.Field.creation_commands`
* New method: `cfdm.Data.creation_commands`
* New class: `cfdm.core.meta.DocstringRewriteMeta`
* New method: `cfdm.Field._docstring_special_substitutions`
* New method: `cfdm.Field._docstring_substitutions`
* New method: `cfdm.Field._docstring_package_depth`
* New method: `cfdm.Field._docstring_method_exclusions`
* New function: `cfdm.unique_domains`
* Enabled "creation commands" methods
(https://github.com/NCAS-CMS/cfdm/issues/53)
* Fixed bug that caused failures when reading or writing a dataset
that contains multiple geometry containers
(https://github.com/NCAS-CMS/cfdm/issues/65)
Expand Down
1 change: 0 additions & 1 deletion cfdm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@
_manage_log_level_via_verbosity,
)


from .constructs import Constructs

from .data import (Data,
Expand Down
47 changes: 47 additions & 0 deletions cfdm/cellmeasure.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,53 @@ def __init__(self, measure=None, properties=None, data=None,

self._initialise_netcdf(source)

def creation_commands(self, representative_data=False,
namespace=None, indent=0, string=True,
name='c', data_name='data', header=True):
'''Return the commands that would create the cell measure construct.
.. versionadded:: (cfdm) 1.8.7.0
.. seealso:: `{{package}}.Data.creation_commands`,
`{{package}}.Field.creation_commands`
:Parameters:
{{representative_data: `bool`, optional}}
{{namespace: `str`, optional}}
{{indent: `int`, optional}}
{{string: `bool`, optional}}
{{header: `bool`, optional}}
:Returns:
{{returns creation_commands}}
**Examples:**
TODO
'''
out = super().creation_commands(
representative_data=representative_data, indent=0,
namespace=namespace, string=False, name=name,
data_name=data_name, header=header)

measure = self.get_measure(None)
if measure is not None:
out.append("{}.set_measure({!r})".format(name, measure))

if string:
indent = ' ' * indent
out[0] = indent + out[0]
out = ('\n' + indent).join(out)

return out

def dump(self, display=True, _omit_properties=None, _key=None,
_level=0, _title=None, _axes=None, _axis_names=None):
'''A full description of the cell measure construct.
Expand Down
95 changes: 95 additions & 0 deletions cfdm/cellmethod.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import logging

from copy import deepcopy

import numpy

from .data import Data

from . import mixin
from . import core

Expand Down Expand Up @@ -32,6 +36,16 @@ class CellMethod(mixin.Container,
.. versionadded:: (cfdm) 1.7.0
'''
def __new__(cls, *args, **kwargs):
'''This must be overridden in subclasses.
.. versionadded:: (cfdm) 1.8.7.0
'''
instance = super().__new__(cls)
instance._Data = Data
return instance

def __str__(self):
'''Called by the `str` built-in function.
Expand Down Expand Up @@ -77,6 +91,87 @@ def __str__(self):

return ' '.join(string)

def creation_commands(self, namespace=None, indent=0, string=True,
name='c', header=True):
'''Return the commands that would create the cell measure construct.
.. versionadded:: (cfdm) 1.8.7.0
.. seealso:: `{{package}}.Data.creation_commands`,
`{{package}}.Field.creation_commands`
:Parameters:
{{namespace: `str`, optional}}
{{indent: `int`, optional}}
{{string: `bool`, optional}}
{{header: `bool`, optional}}
:Returns:
{{returns creation_commands}}
**Examples:**
TODO
'''
namespace0 = namespace
if namespace is None:
namespace = self._package() + '.'
elif namespace and not namespace.endswith('.'):
namespace += '.'

out = []

method = self.get_method(None)

if header:
out.append('#')
out.append("# {}:".format(self.construct_type))
if method is not None:
out[-1] += " {}".format(method)
# --- End: if

out.append("{} = {}{}()".format(name, namespace,
self.__class__.__name__))

if method is not None:
out.append("{}.set_method({!r})".format(name, method))

axes = self.get_axes(None)
if axes is not None:
out.append("{}.set_axes({!r})".format(name, axes))

for term, value in self.qualifiers().items():
if term == 'interval':
value = deepcopy(value)
for i, data in enumerate(value[:]):
if isinstance(data, self._Data):
value[i] = data.creation_commands(
name=None, namespace=namespace0,
indent=0, string=True)
else:
value[i] = str(data)
# --- End: for

value = ', '.join(value)
value = "["+value+"]"
else:
value = repr(value)

out.append("{}.set_qualifier({!r}, {})".format(name, term,
value))

if string:
indent = ' ' * indent
out[0] = indent + out[0]
out = ('\n' + indent).join(out)

return out

def dump(self, display=True, _title=None, _level=0):
'''A full description of the cell method construct.
Expand Down
112 changes: 111 additions & 1 deletion cfdm/coordinatereference.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from . import CoordinateConversion
from . import Datum

from .data import Data

from .decorators import _manage_log_level_via_verbosity


Expand Down Expand Up @@ -60,7 +62,6 @@ class CoordinateReference(mixin.NetCDFVariable,
coordinate reference construct relates the coordinate values of
the field to locations in a planetary reference frame.
**NetCDF interface**
The netCDF grid mapping variable name of a coordinate reference
Expand All @@ -81,6 +82,7 @@ def __new__(cls, *args, **kwargs):
'''
instance = super().__new__(cls)
instance._CoordinateConversion = CoordinateConversion
instance._Data = Data
instance._Datum = Datum
return instance

Expand Down Expand Up @@ -147,6 +149,114 @@ def __str__(self):
'''
return self.identity(default=self.nc_get_variable(''))

def creation_commands(self, namespace=None, indent=0, string=True,
name='c', header=True):
'''Return the commands that would create the field construct.
**Construct keys**
The *key* parameter of the output `set_construct` commands is
utilised in order minimise the number of commands needed to
implement cross-referencing between constructs (e.g. between a
coordinate reference construct and coordinate constructs). This is
usually not necessary when building field constructs, as by
default the `set_construct` method returns a unique construct key
for the construct being set.
.. versionadded:: (cfdm) 1.8.7.0
.. seealso:: `{{package}}.Data.creation_commands`,
`{{package}}.Field.creation_commands`
:Parameters:
{{namespace: `str`, optional}}
{{indent: `int`, optional}}
{{string: `bool`, optional}}
{{header: `bool`, optional}}
:Returns:
{{returns creation_commands}}
**Examples:**
TODO
'''
namespace0 = namespace
if namespace is None:
namespace = self._package() + '.'
elif namespace and not namespace.endswith('.'):
namespace += '.'

out = []

if header:
out.append('#')
out.append("# {}:".format(self.construct_type))
identity = self.identity()
if identity:
out[-1] += " {}".format(identity)
# -- End: if

out.append("{} = {}{}()".format(name, namespace,
self.__class__.__name__))

nc = self.nc_get_variable(None)
if nc is not None:
out.append("{}.nc_set_variable({!r})".format(name, nc))

coordinates = self.coordinates()
if coordinates:
out.append("{}.set_coordinates({})".format(name,
coordinates))

for term, value in self.datum.parameters().items():
if isinstance(value, self._Data):
value = value.creation_commands(name=None,
namespace=namespace0,
indent=0,
string=False,
header=header)
else:
value = repr(value)

out.append("{}.datum.set_parameter({!r}, {})".format(
name, term, value))

for term, value in self.coordinate_conversion.parameters().items():
if isinstance(value, self._Data):
value = value.creation_commands(name=None,
namespace=namespace0,
indent=0,
string=False,
header=header)
else:
value = repr(value)

out.append(
"{}.coordinate_conversion.set_parameter({!r}, {})".format(
name, term, value)
)

domain_ancillaries = self.coordinate_conversion.domain_ancillaries()
if domain_ancillaries:
out.append(
"{}.coordinate_conversion.set_domain_ancillaries({})".format(
name, domain_ancillaries)
)

if string:
indent = ' ' * indent
out[0] = indent + out[0]
out = ('\n' + indent).join(out)

return out

def dump(self, display=True, _omit_properties=None, field=None,
key='', _level=0, _title=None, _construct_names=None,
_auxiliary_coordinates=None, _dimension_coordinates=None):
Expand Down
Loading

0 comments on commit 2d99270

Please sign in to comment.