Skip to content

Commit

Permalink
Merge pull request #355 from tcmitchell/301-singleton-initial-value
Browse files Browse the repository at this point in the history
Progress on implicit list wrapping for singleton initial values
  • Loading branch information
tcmitchell authored Nov 16, 2021
2 parents fc60ea1 + f890e84 commit 1353ccb
Show file tree
Hide file tree
Showing 27 changed files with 281 additions and 104 deletions.
5 changes: 3 additions & 2 deletions sbol3/attachment.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Any
from typing import List, Any, Optional

from . import *

Expand All @@ -11,7 +11,8 @@ class Attachment(TopLevel):
"""

def __init__(self, identity: str, source: str,
*, format: str = None, size: int = None,
*, format: Optional[str] = None,
size: int = None,
hash: str = None, hash_algorithm: str = None,
namespace: str = None,
attachments: List[str] = None,
Expand Down
4 changes: 2 additions & 2 deletions sbol3/combderiv.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import math
from typing import Union, List, Any
from typing import Union, List, Any, Optional

from . import *

Expand All @@ -18,7 +18,7 @@ class properties template, hasVariableFeature, and strategy.
"""

def __init__(self, identity: str, template: Union[Component, str],
*, strategy: str = None,
*, strategy: Optional[str] = None,
variable_features: List[str] = None,
namespace: str = None,
attachments: List[str] = None,
Expand Down
42 changes: 24 additions & 18 deletions sbol3/component.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
from __future__ import annotations

import math
from typing import List, Union, Any
from typing import Any, Optional
import typing

from . import *
from .typing import *


class Component(TopLevel):

def __init__(self, identity: str, types: Union[List[str], str],
*, roles: List[str] = None,
sequences: List[str] = None,
features: List[Feature] = None,
constraints: List[Constraint] = None,
interactions: List[Interaction] = None,
interface: Interface = None,
models: List[str] = None,
namespace: str = None,
attachments: List[str] = None,
name: str = None, description: str = None,
derived_from: List[str] = None, generated_by: List[str] = None,
measures: List[SBOLObject] = None, type_uri: str = SBOL_COMPONENT):
def __init__(self, identity: str, types: Optional[Union[str, typing.Sequence[str]]],
*, # Keywords only after this
roles: Optional[Union[str, typing.Sequence[str]]] = None,
sequences: Optional[refobj_list_arg] = None,
features: Union[Feature, typing.Sequence[Feature]] = None,
constraints: Union[Constraint, typing.Sequence[Constraint]] = None,
interactions: Union[Interaction, typing.Sequence[Interaction]] = None,
interface: Union[Interface, typing.Sequence[Interface]] = None,
models: Optional[refobj_list_arg] = None,
namespace: Optional[str] = None,
attachments: Optional[refobj_list_arg] = None,
name: Optional[str] = None,
description: Optional[str] = None,
derived_from: Optional[Union[str, typing.Sequence[str]]] = None,
generated_by: Optional[refobj_list_arg] = None,
measures: Optional[ownedobj_list_arg] = None,
type_uri: str = SBOL_COMPONENT) -> None:
super().__init__(identity=identity, type_uri=type_uri,
namespace=namespace,
attachments=attachments, name=name,
description=description, derived_from=derived_from,
generated_by=generated_by, measures=measures)
if isinstance(types, str):
types = [types]
self.types: Union[List, Property] = URIProperty(self, SBOL_TYPE, 1, math.inf,
initial_value=types)
self.types = URIProperty(self, SBOL_TYPE, 1, math.inf,
initial_value=types)
self.roles = URIProperty(self, SBOL_ROLE, 0, math.inf,
initial_value=roles)
self.sequences = ReferencedObject(self, SBOL_SEQUENCES, 0, math.inf,
Expand Down
7 changes: 4 additions & 3 deletions sbol3/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# import typing for typing.Sequence, which we don't want to confuse
# with sbol3.Sequence
import typing
import typing as pytyping

import pyshacl
import rdflib
Expand Down Expand Up @@ -284,7 +284,7 @@ def assign_document(x: Identified):
obj.traverse(assign_document)
return obj

def _add_all(self, objects: typing.Sequence[TopLevel]) -> typing.Sequence[TopLevel]:
def _add_all(self, objects: pytyping.Sequence[TopLevel]) -> pytyping.Sequence[TopLevel]:
# Perform type check of all objects.
# We do this to avoid finding out part way through that an
# object can't be added. That would leave the document in an
Expand All @@ -302,7 +302,8 @@ def _add_all(self, objects: typing.Sequence[TopLevel]) -> typing.Sequence[TopLev
# return the passed argument
return objects

def add(self, objects: Union[TopLevel, typing.Sequence[TopLevel]]) -> Union[TopLevel, typing.Sequence[TopLevel]]:
def add(self,
objects: Union[TopLevel, pytyping.Sequence[TopLevel]]) -> Union[TopLevel, pytyping.Sequence[TopLevel]]:
# objects must be TopLevel or iterable. If neither, raise a TypeError.
#
# Note: Python documentation for collections.abc says "The only
Expand Down
3 changes: 2 additions & 1 deletion sbol3/extdef.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
import math
from typing import Any

Expand All @@ -15,7 +16,7 @@ class ExternallyDefined(Feature):
"""

def __init__(self, types: List[str], definition: str,
def __init__(self, types: Union[str, list[str]], definition: str,
*, roles: List[str] = None, orientation: str = None,
name: str = None, description: str = None,
derived_from: List[str] = None,
Expand Down
16 changes: 10 additions & 6 deletions sbol3/feature.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
from __future__ import annotations
import abc
import math
from typing import List
from typing import List, Optional

from . import *

from .typing import *


class Feature(Identified, abc.ABC):
"""Feature is an abstract base class."""

def __init__(self, identity: str, type_uri: str,
*, roles: List[str] = None, orientation: str = None,
*, roles: Optional[str, list[str]] = None,
orientation: Optional[str] = None,
name: str = None, description: str = None,
derived_from: List[str] = None,
generated_by: List[str] = None,
measures: List[SBOLObject] = None) -> None:
super().__init__(identity=identity, type_uri=type_uri, name=name,
description=description, derived_from=derived_from,
generated_by=generated_by, measures=measures)
self.roles = URIProperty(self, SBOL_ROLE, 0, math.inf,
initial_value=roles)
self.orientation = URIProperty(self, SBOL_ORIENTATION, 0, 1,
initial_value=orientation)
self.roles: uri_list = URIProperty(self, SBOL_ROLE, 0, math.inf,
initial_value=roles)
self.orientation: uri_singleton = URIProperty(self, SBOL_ORIENTATION, 0, 1,
initial_value=orientation)

def validate(self, report: ValidationReport = None) -> ValidationReport:
report = super().validate(report)
Expand Down
15 changes: 9 additions & 6 deletions sbol3/identified.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import abc
from __future__ import annotations
import math
import posixpath
from typing import Union, List, Callable, Any
from typing import Callable, Any, Optional
import typing
from urllib.parse import urlparse

import rdflib

from . import *
from .typing import *
from .utils import parse_class_name


Expand All @@ -20,9 +22,11 @@ class Identified(SBOLObject):
"""

def __init__(self, identity: str, type_uri: str,
*, name: str = None, description: str = None,
derived_from: List[str] = None, generated_by: List[str] = None,
measures: List[SBOLObject] = None) -> None:
*, name: Optional[str] = None,
description: Optional[str] = None,
derived_from: Optional[Union[str, typing.Sequence[str]]] = None,
generated_by: Optional[refobj_list_arg] = None,
measures: Optional[ownedobj_list_arg] = None) -> None:
"""
:param identity: this object's Uniform Resource Identifier (URI).
this URI MUST be globally unique among all other Identified
Expand Down Expand Up @@ -235,7 +239,6 @@ def serialize(self, graph: rdflib.Graph):
graph.add((identity, rdf_prop, rdflib.URIRef(item.identity)))
item.serialize(graph)

@abc.abstractmethod
def accept(self, visitor: Any) -> Any:
"""
An abstract method for concrete classes to override. This
Expand Down
8 changes: 5 additions & 3 deletions sbol3/interaction.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations
import math
from typing import List, Any

from . import *
from .typing import *


class Interaction(Identified):
Expand All @@ -19,7 +21,7 @@ class Interaction(Identified):
"""

def __init__(self, types: List[str],
def __init__(self, types: Union[str, list[str]],
*, participations: List[Participation] = None,
name: str = None, description: str = None,
derived_from: List[str] = None,
Expand All @@ -31,8 +33,8 @@ def __init__(self, types: List[str],
name=name, description=description,
derived_from=derived_from, generated_by=generated_by,
measures=measures)
self.types = URIProperty(self, SBOL_TYPE, 1, math.inf,
initial_value=types)
self.types: uri_list = URIProperty(self, SBOL_TYPE, 1, math.inf,
initial_value=types)
self.participations = OwnedObject(self, SBOL_PARTICIPATIONS, 0, math.inf,
initial_value=participations,
type_constraint=Participation)
Expand Down
3 changes: 2 additions & 1 deletion sbol3/localsub.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
import math
from typing import Any

Expand All @@ -15,7 +16,7 @@ class LocalSubComponent(Feature):
"""

def __init__(self, types: List[str],
def __init__(self, types: Union[str, list[str]],
*, locations: List[Location] = None,
roles: List[str] = None, orientation: str = None,
name: str = None, description: str = None,
Expand Down
9 changes: 5 additions & 4 deletions sbol3/location.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import abc
from typing import Union, Any
from typing import Union, Any, Optional

from . import *
from .typing import uri_singleton

int_property = Union[IntProperty, int]

Expand All @@ -15,11 +16,11 @@ class Location(Identified, abc.ABC):

def __init__(self, sequence: Union[Sequence, str],
identity: str, type_uri: str,
*, orientation: str = None,
*, orientation: Optional[str] = None,
order: int = None) -> None:
super().__init__(identity, type_uri)
self.orientation = URIProperty(self, SBOL_ORIENTATION, 0, 1,
initial_value=orientation)
self.orientation: uri_singleton = URIProperty(self, SBOL_ORIENTATION, 0, 1,
initial_value=orientation)
self.order = IntProperty(self, SBOL_ORDER, 0, 1,
initial_value=order)
self.sequence = ReferencedObject(self, SBOL_SEQUENCES, 1, 1,
Expand Down
13 changes: 7 additions & 6 deletions sbol3/model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List, Any

from . import *
from .typing import uri_singleton


class Model(TopLevel):
Expand All @@ -27,12 +28,12 @@ def __init__(self, identity: str, source: str, language: str,
attachments=attachments, name=name,
description=description, derived_from=derived_from,
generated_by=generated_by, measures=measures)
self.source = URIProperty(self, SBOL_SOURCE, 1, 1,
initial_value=source)
self.language = URIProperty(self, SBOL_LANGUAGE, 1, 1,
initial_value=language)
self.framework = URIProperty(self, SBOL_FRAMEWORK, 1, 1,
initial_value=framework)
self.source: uri_singleton = URIProperty(self, SBOL_SOURCE, 1, 1,
initial_value=source)
self.language: uri_singleton = URIProperty(self, SBOL_LANGUAGE, 1, 1,
initial_value=language)
self.framework: uri_singleton = URIProperty(self, SBOL_FRAMEWORK, 1, 1,
initial_value=framework)

def validate(self, report: ValidationReport = None) -> ValidationReport:
report = super().validate(report)
Expand Down
14 changes: 8 additions & 6 deletions sbol3/om_unit.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from __future__ import annotations
import abc
import math
from typing import Union, List, Any
from typing import Union, List, Any, Optional

from . import *
from .om_prefix import Prefix
from .typing import *


class Unit(CustomTopLevel, abc.ABC):
Expand Down Expand Up @@ -55,7 +57,7 @@ class Measure(CustomIdentified):
"""

def __init__(self, value: float, unit: str,
*, types: List[str] = None,
*, types: Optional[str, list[str]] = None,
name: str = None, description: str = None,
derived_from: List[str] = None,
generated_by: List[str] = None,
Expand All @@ -68,10 +70,10 @@ def __init__(self, value: float, unit: str,
measures=measures)
self.value = FloatProperty(self, OM_HAS_NUMERICAL_VALUE, 1, 1,
initial_value=value)
self.types = URIProperty(self, SBOL_TYPE, 0, math.inf,
initial_value=types)
self.unit = URIProperty(self, OM_HAS_UNIT, 1, 1,
initial_value=unit)
self.types: uri_list = URIProperty(self, SBOL_TYPE, 0, math.inf,
initial_value=types)
self.unit: uri_singleton = URIProperty(self, OM_HAS_UNIT, 1, 1,
initial_value=unit)

def accept(self, visitor: Any) -> Any:
"""Invokes `visit_measure` on `visitor` with `self` as the only
Expand Down
4 changes: 4 additions & 0 deletions sbol3/ownedobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ def __init__(self, property_owner: Any, property_uri: str,
# to accept unknown keyword arguments.
self.type_constraint = type_constraint
if initial_value is not None:
if isinstance(initial_value, SBOLObject):
# coerce the singleton into a list
# see https://github.com/SynBioDex/pySBOL3/issues/301
initial_value = [initial_value]
self.set(initial_value)

def validate(self, name: str, report: ValidationReport):
Expand Down
3 changes: 2 additions & 1 deletion sbol3/participation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
import math
from typing import Any

Expand All @@ -11,7 +12,7 @@ class Participation(Identified):
"""

def __init__(self, roles: List[str],
def __init__(self, roles: Union[str, list[str]],
participant: Union[SBOLObject, str],
*, name: str = None, description: str = None,
derived_from: List[str] = None,
Expand Down
Loading

0 comments on commit 1353ccb

Please sign in to comment.