Skip to content

Commit

Permalink
[Examples] Trait versioning design sketch
Browse files Browse the repository at this point in the history
Closes OpenAssetIO#88. As due diligence before going ahead with an implementation,
we need to sketch out what a versioned trait package would look like,
and how hosts and managers would interact with it.

So add a contrived trait package with two versions. The "generated"
view classes have been manually created to reflect what the `traitgen`
output should be, once implemented.

These view classes are then used in a tutorial notebook that describes
how one would go about working with versioned traits.

This work may be abandoned or adapted in favour of more concrete
documentation as the feature is developed.

Signed-off-by: David Feltell <david.feltell@foundry.com>
  • Loading branch information
feltech committed Apr 17, 2024
1 parent b356f0e commit f3e0225
Show file tree
Hide file tree
Showing 14 changed files with 1,816 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
An example traits schema
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from .v2 import *
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
An example traits schema
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from . import traits
from . import specifications
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Specifications defined in the 'openassetio-example' package.
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from . import example
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@

"""
Specification definitions in the 'example' namespace.
Test specifications.
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from openassetio.trait import TraitsData


from .. import traits



class ExampleSpecification:
"""
An example.
Usage: entity
"""
kTraitSet = {
# 'openassetio-example:example.Unchanged'
traits.example.UnchangedTrait.kId,
# 'openassetio-example:example.Updated'
traits.example.UpdatedTrait.kId,

}

def __init__(self, traitsData):
"""
Constructs the specification as a view on the supplied
shared @fqref{TraitsData} "TraitsData" instance.
@param traitsData @fqref{TraitsData} "TraitsData"
@warning Specifications are always a view on the supplied data,
which is held by reference. Any changes made to the data will be
visible to any other specifications or @ref trait "traits" that
wrap the same TraitsData instance.
"""
if not isinstance(traitsData, TraitsData):
raise TypeError("Specifications must be constructed with a TraitsData instance")
self.__data = traitsData

def traitsData(self):
"""
Returns the underlying (shared) @fqref{TraitsData} "TraitsData"
instance held by this specification.
"""
return self.__data

@classmethod
def create(cls):
"""
Returns a new instance of the Specification, holding a new
@fqref{TraitsData} "TraitsData" instance, pre-populated with all
of the specifications traits.
"""
data = TraitsData(cls.kTraitSet)
return cls(data)


def unchangedTrait(self):
"""
Returns the view for the 'openassetio-example:example.Unchanged' trait wrapped around
the data held in this instance.
"""
return traits.example.UnchangedTrait(self.traitsData())

def updatedTrait(self):
"""
Returns the view for the 'openassetio-example:example.Updated' trait wrapped around
the data held in this instance.
"""
return traits.example.UpdatedTrait(self.traitsData())

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Traits defined in the 'openassetio-example' package.
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from . import example
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@

"""
Trait definitions in the 'example' namespace.
Example namespace
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from typing import Union

from openassetio.trait import TraitsData


class RemovedTrait:
"""
An example.
Usage: entity, locale, relationship
"""
kId = "openassetio-example:example.Removed.v1"

def __init__(self, traitsData):
"""
Construct this trait view, wrapping the given data.
@param traitsData @fqref{TraitsData}} "TraitsData" The target
data that holds/will hold the traits properties.
"""
self.__data = traitsData

def isImbued(self):
"""
Checks whether the data this trait has been applied to
actually has this trait.
@return `True` if the underlying data has this trait, `False`
otherwise.
"""
return self.isImbuedTo(self.__data)

@classmethod
def isImbuedTo(cls, traitsData):
"""
Checks whether the given data actually has this trait.
@param traitsData: Data to check for trait.
@return `True` if the underlying data has this trait, `False`
otherwise.
"""
return traitsData.hasTrait(cls.kId)

def imbue(self):
"""
Adds this trait to the held data.
If the data already has this trait, it is a no-op.
"""
self.__data.addTrait(self.kId)

@classmethod
def imbueTo(cls, traitsData):
"""
Adds this trait to the provided data.
If the data already has this trait, it is a no-op.
"""
traitsData.addTrait(cls.kId)




class UnchangedTrait:
"""
An example.
Usage: entity, locale, relationship
"""
kId = "openassetio-example:example.Unchanged.v1"

def __init__(self, traitsData):
"""
Construct this trait view, wrapping the given data.
@param traitsData @fqref{TraitsData}} "TraitsData" The target
data that holds/will hold the traits properties.
"""
self.__data = traitsData

def isImbued(self):
"""
Checks whether the data this trait has been applied to
actually has this trait.
@return `True` if the underlying data has this trait, `False`
otherwise.
"""
return self.isImbuedTo(self.__data)

@classmethod
def isImbuedTo(cls, traitsData):
"""
Checks whether the given data actually has this trait.
@param traitsData: Data to check for trait.
@return `True` if the underlying data has this trait, `False`
otherwise.
"""
return traitsData.hasTrait(cls.kId)

def imbue(self):
"""
Adds this trait to the held data.
If the data already has this trait, it is a no-op.
"""
self.__data.addTrait(self.kId)

@classmethod
def imbueTo(cls, traitsData):
"""
Adds this trait to the provided data.
If the data already has this trait, it is a no-op.
"""
traitsData.addTrait(cls.kId)




class UpdatedTrait:
"""
An example.
Usage: entity, locale, relationship
"""
kId = "openassetio-example:example.Updated.v1"

def __init__(self, traitsData):
"""
Construct this trait view, wrapping the given data.
@param traitsData @fqref{TraitsData}} "TraitsData" The target
data that holds/will hold the traits properties.
"""
self.__data = traitsData

def isImbued(self):
"""
Checks whether the data this trait has been applied to
actually has this trait.
@return `True` if the underlying data has this trait, `False`
otherwise.
"""
return self.isImbuedTo(self.__data)

@classmethod
def isImbuedTo(cls, traitsData):
"""
Checks whether the given data actually has this trait.
@param traitsData: Data to check for trait.
@return `True` if the underlying data has this trait, `False`
otherwise.
"""
return traitsData.hasTrait(cls.kId)

def imbue(self):
"""
Adds this trait to the held data.
If the data already has this trait, it is a no-op.
"""
self.__data.addTrait(self.kId)

@classmethod
def imbueTo(cls, traitsData):
"""
Adds this trait to the provided data.
If the data already has this trait, it is a no-op.
"""
traitsData.addTrait(cls.kId)


def setPropertyToKeep(self, propertyToKeep: str):
"""
Sets the propertyToKeep property.
A property that is unchanged between versions.
"""
if not isinstance(propertyToKeep, str):
raise TypeError("propertyToKeep must be a 'str'.")
self.__data.setTraitProperty(self.kId, "propertyToKeep", propertyToKeep)

def getPropertyToKeep(self, defaultValue: str=None) -> Union[str, None]:
"""
Gets the value of the propertyToKeep property or the supplied default.
A property that is unchanged between versions.
"""
value = self.__data.getTraitProperty(self.kId, "propertyToKeep")
if value is None:
return defaultValue

if not isinstance(value, str):
if defaultValue is None:
raise TypeError(f"Invalid stored value type: '{type(value).__name__}' should be 'str'.")
return defaultValue
return value

def setPropertyToRemove(self, propertyToRemove: bool):
"""
Sets the propertyToRemove property.
A defunct property that should be removed in the next version.
"""
if not isinstance(propertyToRemove, bool):
raise TypeError("propertyToRemove must be a 'bool'.")
self.__data.setTraitProperty(self.kId, "propertyToRemove", propertyToRemove)

def getPropertyToRemove(self, defaultValue: bool=None) -> Union[bool, None]:
"""
Gets the value of the propertyToRemove property or the supplied default.
A defunct property that should be removed in the next version.
"""
value = self.__data.getTraitProperty(self.kId, "propertyToRemove")
if value is None:
return defaultValue

if not isinstance(value, bool):
if defaultValue is None:
raise TypeError(f"Invalid stored value type: '{type(value).__name__}' should be 'bool'.")
return defaultValue
return value

def setPropertyToRename(self, propertyToRename: bool):
"""
Sets the propertyToRename property.
A property that has an inappropriate name and should be renamed
in the next version.
"""
if not isinstance(propertyToRename, bool):
raise TypeError("propertyToRename must be a 'bool'.")
self.__data.setTraitProperty(self.kId, "propertyToRename", propertyToRename)

def getPropertyToRename(self, defaultValue: bool=None) -> Union[bool, None]:
"""
Gets the value of the propertyToRename property or the supplied default.
A property that has an inappropriate name and should be renamed
in the next version.
"""
value = self.__data.getTraitProperty(self.kId, "propertyToRename")
if value is None:
return defaultValue

if not isinstance(value, bool):
if defaultValue is None:
raise TypeError(f"Invalid stored value type: '{type(value).__name__}' should be 'bool'.")
return defaultValue
return value



Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
An example traits schema
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from . import traits
from . import specifications
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Specifications defined in the 'openassetio-example' package.
"""

# WARNING: This file is auto-generated by openassetio-traitgen, do not edit.

from . import example
Loading

0 comments on commit f3e0225

Please sign in to comment.