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

DM-13349: Define storage classes in config yaml #11

Merged
merged 17 commits into from Feb 1, 2018
Merged

Conversation

timj
Copy link
Member

@timj timj commented Jan 31, 2018

  • Moved the formatter factory registry to a new class MappingFactory.
  • Allow the factory registry to take classes as well as string definitions.
  • Replace StorageClass definitions in code with a new registry and ability to dynamically create them from strings.
  • Update posix data store to dynamically generate storage classes from the YAML.
  • Update tests to read storage classes from factory.

* Moved the formatter factory registry to a new class MappingFactory.
* Allow the factory registry to take classes as well as string
  definitions.
* Replace StorageClass definitions in code with a new registry
  and ability to dynamically create them from strings.
* Update posix data store to dynamically generate storage classes
  from the YAML.
* Update tests to read storage classes from factory.
pass
typeName = self._registry[self._getName(storageClass)]
return self._getInstanceOf(typeName)
return self.getFromRegistry(storageClass, override=datasetType)
Copy link
Member Author

Choose a reason for hiding this comment

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

I can switch this to using composition if you prefer since the get and put methods do not have the same names as the base class implementation

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, that way we can also get rid of my other gripe (having refType specified) and move that to an argument (e.g. self.mappingFactory = MappingFactory(Formatter)).

@timj timj requested a review from pschella January 31, 2018 23:21
@timj
Copy link
Member Author

timj commented Feb 1, 2018

I've also relocated doImport from daf_persistence and added some tests to it.

We are using one of the functions and core daf_butler should
not directly depend on daf_persistence. Transferring the whole
file for now since we might use a function.
"""

refType = None
"""Type of instances expected to be returned from factory."""
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't this be documented in the attributes section of the class documentation instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

I spent ten minutes reading numpydoc documentation and this seemed to be the way they wanted me to document class attributes. I admit it was somewhat unclear to me (and I'm about to delete that line anyhow).

Copy link
Member Author

Choose a reason for hiding this comment

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

Now that I read the numpydoc docs again I see the attributes section (as opposed to parameters for __init__).

photoCalib: "TablePersistable"
visitInfo: "TablePersistable"
apCorr: "TablePersistable"
coaddInputs: "TablePersistable"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are the quotes needed for the component storage classes? I'd like to specify them without quotes (or as YAML references), since they are internal references. Oh, and we better hope they don't become circular ;)

Copy link
Member Author

Choose a reason for hiding this comment

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

I can remove the quotes. Making them YAML references is something I'd have to look at (currently I need them to be strings to look up in the registry rather than items to look up from the YAML tree).

storageClassName = "Image"
self.factory.registerFormatter(storageClassName, formatterName)
f = self.factory.getFormatter(storageClassName)
self.assertIsInstance(f, formatter.Formatter)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also test the explicit subclass type?


with self.assertRaises(ValueError):
# Try to store something that is not a Formatter but is a class
self.factory.registerFormatter("NotFormatter", "lsst.daf.butler.core.formatter.FormatterFactory")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can be misleading if a value error is raised on the first argument instead of the second. Better reuse the same working identifier.

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean the cases where "NotFormatter" is in the registry already? Shame I can't use KeyError for the "key already in use" error. What do you mean by "same working identifier"?

self.factory.registerFormatter("NotFormatter", "lsst.daf.butler")

with self.assertRaises(ValueError):
# Try to store something that is not a Formatter but does not exist
Copy link
Collaborator

Choose a reason for hiding this comment

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

and does not exist.

self.assertIsInstance(sc, storageClass.StorageClass)
self.assertEqual(sc.name, className)
self.assertIsNone(sc.components)
self.assertEqual(sc.type, dict)
Copy link
Collaborator

Choose a reason for hiding this comment

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

ptype / pytype here too?

Copy link
Member Author

Choose a reason for hiding this comment

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

I did change all the type attributes to pytype at one point but then changed them back because I wasn't entirely sure that type was a bad name for the attribute (and keeping it meant changing less code). I'm fine with making it explicitly pytype so there is no confusion as to what the storage class is referring to.

self.assertEqual(sc.type, dict)

# Check that this class is listed in the subclasses
self.assertIn(className, newclass.subclasses)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Now that we moved the registry to an explicit factory, I don't think we need StorageClass's 'fancy' metaclass registration anymore (so subclasses and components dict can go I think).
It used to be responsible for mapping names to instances, but non-configurable and without overrides.

Copy link
Member Author

Choose a reason for hiding this comment

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

I might leave it in for a little just in case I have a problem where I need a storage class that has been made concrete somewhere else but is not in this registry.



class PythonType:
"""A dummy class to test the registory of Python types."""
Copy link
Collaborator

Choose a reason for hiding this comment

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

registry?

pass
typeName = self._registry[self._getName(storageClass)]
return self._getInstanceOf(typeName)
return self.getFromRegistry(storageClass, override=datasetType)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, that way we can also get rid of my other gripe (having refType specified) and move that to an argument (e.g. self.mappingFactory = MappingFactory(Formatter)).

Get item from registry associated with this target class, unless
override : `str` or object supporting `.name` attribute, optional
If given, look if an override has been specified for this and,
if so return that instead.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps make it slightly more generic? By taking *targetClasses and thus allowing for multiple overrides?

@timj timj merged commit 02c2778 into master Feb 1, 2018
@ktlim ktlim deleted the tickets/DM-13349 branch August 25, 2018 06:49
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.

None yet

3 participants