Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Toniof 352 support typespecifiers #354

Merged
merged 12 commits into from
Nov 5, 2020
Merged

Conversation

TonioF
Copy link
Contributor

@TonioF TonioF commented Nov 2, 2020

Solves #352

@TonioF TonioF requested review from forman and pont-us November 2, 2020 17:12
Copy link
Member

@forman forman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good and exhaustive work, thanks!

In addition to my comments and suggests abovebelow:

  • Please include a description of type specifiers and their usages into DataStore's class documentation. Refer to that doc from the methods that have a type_specifier argument are return type specifiers.
  • We also need to get right when to raise DataStoreError and when ValuError. Note, I often see that when you raise a ValueError, you include a type name in the message rather than the argument's name. Please make sure you include the argument names. ValueErrors are mainly developer errors.

Comment on lines 21 to 23
try:
descriptor_dict = dict(data_id='xyz', type_id='tsr')
DatasetDescriptor.from_dict(descriptor_dict)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
try:
descriptor_dict = dict(data_id='xyz', type_id='tsr')
DatasetDescriptor.from_dict(descriptor_dict)
with self.assertRaises(ValueError) as cm:
descriptor_dict = dict(data_id='xyz', type_id='tsr')
DatasetDescriptor.from_dict(descriptor_dict)
self.assertEqual('...', f'{cm.exception}')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change that, but I'd like to point out that this is not part of the pull request.

raise ValueError(f'TypeId must be compatible with "geodataframe" type id, was {type_id}')
def _assert_type_specifier(self, type_specifier: str):
if not TYPE_SPECIFIER_GEODATAFRAME.is_compatible(type_specifier):
raise ValueError(f'TypeSpecifier must be compatible with "geodataframe" type specifier, '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError(f'TypeSpecifier must be compatible with "geodataframe" type specifier, '
raise ValueError(f'type_specifier must be compatible with "geodataframe" type specifier, '

xcube/core/store/descriptor.py Outdated Show resolved Hide resolved
raise ValueError(f'TypeId must be compatible with "mldataset" type id, was {type_id}')
def _assert_type_specifier(self, type_specifier: str):
if not TYPE_SPECIFIER_MULTILEVEL_DATASET.is_compatible(type_specifier):
raise ValueError(f'TypeSpecifier must be compatible with "mldataset" type specifier, was {type_specifier}')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError(f'TypeSpecifier must be compatible with "mldataset" type specifier, was {type_specifier}')
raise ValueError(f'type_specifier must be compatible with "mldataset" type specifier, was {type_specifier}')

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeSpecifier is not the argument's name, it is type_specifier.

if type_specifier:
data_type_specifier = get_type_specifier(self._data_dict[data_id])
if not data_type_specifier.is_compatible(type_specifier):
raise ValueError(f'Data resource "{data_id}" is not available as type {type_specifier}. '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError(f'Data resource "{data_id}" is not available as type {type_specifier}. '
raise ValueError(f'Data resource "{data_id}" is not compatible with type specifier "{type_specifier}". '

If a store implementation supports only a single data type, it should verify that *type_id* is either None
or equal to that single data type.
If a store implementation supports only a single data type, it should verify that *type_specifier*
is either None or equal to that single data type.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
is either None or equal to that single data type.
is either None or compatible with the supported data type.

"""
Get the descriptor for the data resource given by *data_id*.

Raises if *data_id* does not exist in this store.
Raises a DataStoreError if *data_id* does not exist in this store
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Raises a DataStoreError if *data_id* does not exist in this store
Raises a :class:DataStoreError if *data_id* does not exist in this store

Not clear yet when we raise class:DataStoreError and when ValueError. For example in some modules, we raise ValueError if type_specifieris not compatible. That doesn't seem consistent to me.

"""
Get the tuple of data type specifiers that are supported for the given *data_id*.
In case the type specifier allows one ore more flags, they are listed in brackets
following the specifier's name, e.g., dataset[CUBE, MULTILEVEL].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
following the specifier's name, e.g., dataset[CUBE, MULTILEVEL].
following the specifier's name, e.g., "dataset[cube,multilevel]".

If *type_specifier* is omitted, all data resource identifiers are returned.

If a store implementation supports only a single data type, it should verify that *type_specifier*
is either None or equal to that single data type.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
is either None or equal to that single data type.
is either None or compatible with the supported data type.

xcube/core/store/store.py Show resolved Hide resolved
@@ -17,7 +17,7 @@ def test_from_dict_no_data_id(self):
except ValueError:
pass

def test_from_dict_wrong_type_id(self):
def test_from_dict_wrong_type_specifier(self):
try:
descriptor_dict = dict(data_id='xyz', type_id='tsr')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
descriptor_dict = dict(data_id='xyz', type_id='tsr')
descriptor_dict = dict(data_id='xyz', type_specifier='tsr')

xcube/core/store/descriptor.py Outdated Show resolved Hide resolved

:param type_specifier: If given, only data identifiers that are available as this type are returned. If this is
omitted, all available data identifiers are returned
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
omitted, all available data identifiers are returned
omitted, all available data identifiers are returned.


:param type_specifier: If given, only data identifiers that are available as this type are returned. If this is
omitted, all available data identifiers are returned
:param include_titles: If true, the store will attempt to also provide a title
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:param include_titles: If true, the store will attempt to also provide a title
:param include_titles: If true, the store will attempt to also provide a title.

"""
A type id denotes a type of data. It is used to group similar types of data and discern different types of data.
It can be used by stores to state what types of data can be read from and/or written to them.
A type specifier denotes a type of data. It is used to group similar types of data and discern
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A type specifier denotes a type of data. It is used to group similar types of data and discern
A type specifier denotes a type of data. It is used to group similar types of data and distinguish between

I think this is clearer (hopefully I interpreted the intended meaning of "discern" correctly enough for a successful rephrasing...).

def describe_data(self, data_id: str) -> DataDescriptor:
if not data_id in self._data_dict:
return False
if type_specifier:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if type_specifier:
if type_specifier is not None:

There are a few things (other than None) that may evaluate to False in this test, so I prefer an explicit None check. Admittedly it's unlikely that we'd be using e.g. 0 or the empty string as a type specifier, but if something like that is passed by mistake I think it's preferable to process it here (probably producing False or an error) rather than falling through to returning True.

self._assert_valid_data_id(data_id)
if type_specifier:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if type_specifier:
if type_specifier is not None:

See previous comment.


`<type_specifier>:<format_identifier>:<storage_identifier>`

`<type_specifier>` MUST be a valid string that specifies a data type.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the definition of "valid" in this context?

`<type_specifier>:<format_identifier>:<storage_identifier>`

`<type_specifier>` MUST be a valid string that specifies a data type.
In case the type specifier has flags, the flags MUST be given in brackets, in alphabetic order, without spaces (e.g., `dataset[cube,multilevel]`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In case the type specifier has flags, the flags MUST be given in brackets, in alphabetic order, without spaces (e.g., `dataset[cube,multilevel]`).
In case the type specifier has flags, the flags MUST be given in square brackets, in alphabetic order, separated by single commas, without spaces (e.g., `dataset[cube,multilevel]`).


`<type_specifier>` MUST be a valid string that specifies a data type.
In case the type specifier has flags, the flags MUST be given in brackets, in alphabetic order, without spaces (e.g., `dataset[cube,multilevel]`).
Note that `*` is a valid value in case that any type is supported.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Note that `*` is a valid value in case that any type is supported.
Note that `*` is a special value indicating that any type is supported.

@forman forman self-requested a review November 4, 2020 14:12

`<type_specifier>:<format_identifier>:<storage_identifier>`

`<type_specifier>` MUST be a valid string that specifies a data type.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`<type_specifier>` MUST be a valid string that specifies a data type.
`<type_specifier>` is a string that specifies a data type. Its intention and format is described below.


`<type_specifier>` MUST be a valid string that specifies a data type.
In case the type specifier has flags, the flags MUST be given in brackets, in alphabetic order, without spaces (e.g., `dataset[cube,multilevel]`).
Note that `*` is a valid value in case that any type is supported.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want users to "note" everything in this doc. It is a (our) convention. So we define what things means and how they are used.

`<type_specifier>:<format_identifier>:<storage_identifier>`

`<type_specifier>` MUST be a valid string that specifies a data type.
In case the type specifier has flags, the flags MUST be given in brackets, in alphabetic order, without spaces (e.g., `dataset[cube,multilevel]`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case the type specifier has flags, the flags MUST be given in brackets...

This is our convention and we have to tell users about the usage and the general syntax of type specifiers. How can a user know if their specifier has flags or not, if it is not explained what these flags are and how they are used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide a clear and unambiguous syntax descroiption (Backus Naur) and some explained examples.

raise ValueError(f'TypeId must be compatible with "dataset" type id, was {type_id}')
def _assert_type_specifier(self, type_specifier: str):
if not TYPE_SPECIFIER_DATASET.is_compatible(type_specifier):
raise ValueError(f'TypeSpecifier must be compatible with "dataset" type specifier, was {type_specifier}')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError(f'TypeSpecifier must be compatible with "dataset" type specifier, was {type_specifier}')
raise ValueError(f'type_specifier must be compatible with "dataset" type specifier, was "{type_specifier}"')

obtain in-memory representations. A data resource may be available as different types. Therefore, many functions
allow to specify the data type using a TypeSpecifier. A type specifier consists of a name and an arbitrary set of
flags, given in brackets. These flags are used to define characteristics of a type, e.g., the type specifier
dataset[cube] denotes a dataset which also meets the requirements of a cube. A dataset specified by
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dataset[cube] denotes a dataset which also meets the requirements of a cube. A dataset specified by
"dataset[cube]" denotes a dataset which also meets the requirements of a cube. A dataset specified by

allow to specify the data type using a TypeSpecifier. A type specifier consists of a name and an arbitrary set of
flags, given in brackets. These flags are used to define characteristics of a type, e.g., the type specifier
dataset[cube] denotes a dataset which also meets the requirements of a cube. A dataset specified by
dataset[cube, multilevel] is a cube and has multiple levels. A type specifier with a flag is compatible to a type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dataset[cube, multilevel] is a cube and has multiple levels. A type specifier with a flag is compatible to a type
"dataset[cube, multilevel]" is a cube and has multiple levels. A type specifier with a flag is compatible to a type

@TonioF TonioF requested review from forman and pont-us November 5, 2020 10:14
xcube/core/store/store.py Show resolved Hide resolved
Copy link
Member

@forman forman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah!

@TonioF TonioF merged commit 33cd069 into master Nov 5, 2020
@TonioF TonioF deleted the toniof-352-support-typespecifiers branch November 5, 2020 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants