Skip to content

Commit 7cda334

Browse files
committed
updates to make the code more consistent and cleaner
1 parent 0ecb479 commit 7cda334

File tree

1 file changed

+43
-49
lines changed

1 file changed

+43
-49
lines changed
Lines changed: 43 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
'''
22
TODO
3-
maybe there should be a way to check if a project has an existing ontology, and that it would overwrite it?
3+
Option.add_option() currently creates a new Classification object. however, this does not work for certain Classification options.
4+
Example:
5+
Classification.Type.DROPDOWN -> the options for this class_type should only generate more nested dropdowns
6+
-> Dropdowns are supposed to be removed moving forward, but this is a current problem
7+
-> This is the most major issue because going to the doubly nested class will break the UI
8+
Classification.Type.CHECKLIST & Classification.Type.TEXT-> the option cannot have a nested Classification.
9+
-> this reflects accurately in the UI without issues, but when you query via graphql, it shows what was input
10+
-> this is a lesser issue because the UI will not reflect the unavailable fields
11+
Is there an effective way to enforce limitations on Option.add_option()?
12+
-> Maybe a way to check if the Option itself has options when adding it to a Classification?
413
'''
514

615
from dataclasses import dataclass, field
@@ -14,47 +23,41 @@
1423
class InconsistentOntologyException(Exception):
1524
pass
1625

17-
class Classification:
18-
pass
19-
2026
@dataclass
2127
class Option:
2228
value: str
2329
schema_id: Optional[str] = None
2430
feature_schema_id: Optional[str] = None
25-
options: List[Classification] = field(default_factory=list)
31+
options: List["Classification"] = field(default_factory=list)
2632

2733
@property
2834
def label(self):
2935
return self.value
3036

31-
def to_dict(self,for_different_project=False) -> Dict[str, str]:
37+
def asdict(self) -> Dict[str, str]:
3238
return {
33-
"schemaNodeId": None if for_different_project else self.schema_id,
34-
"featureSchemaId": None if for_different_project else self.feature_schema_id,
39+
"schemaNodeId": self.schema_id,
40+
"featureSchemaId": self.feature_schema_id,
3541
"label": self.label,
3642
"value": self.value,
37-
"options": [classification.to_dict(for_different_project) for classification in self.options]
43+
"options": [c.asdict() for c in self.options]
3844
}
3945

4046
@classmethod
4147
def from_dict(cls, dictionary: Dict[str,str]):
42-
def has_nested_classifications(dictionary: Dict[str,str]):
43-
return [Classification.from_dict(nested_class) for nested_class in dictionary.get("options", [])]
44-
4548
return Option(
4649
value = dictionary["value"],
4750
schema_id = dictionary["schemaNodeId"],
4851
feature_schema_id = dictionary["featureSchemaId"],
49-
options = has_nested_classifications(dictionary)
52+
options = [Classification.from_dict(nested_class) for nested_class in dictionary.get("options", [])]
5053
)
5154

52-
def add_nested_class(self, *args, **kwargs):
53-
new_classification = Classification(*args, **kwargs)
54-
if new_classification.instructions in (classification.instructions for classification in self.options):
55-
raise InconsistentOntologyException(f"Duplicate nested classification '{new_classification.instructions}' for option '{self.label}'")
56-
self.options.append(new_classification)
57-
return new_classification
55+
def add_option(self, *args, **kwargs):
56+
new_option = Classification(*args, **kwargs)
57+
if new_option.instructions in (c.instructions for c in self.options):
58+
raise InconsistentOntologyException(f"Duplicate nested classification '{new_option.instructions}' for option '{self.label}'")
59+
self.options.append(new_option)
60+
return new_option
5861

5962
@dataclass
6063
class Classification:
@@ -65,32 +68,30 @@ class Type(Enum):
6568
RADIO = "radio"
6669
DROPDOWN = "dropdown"
6770

71+
_REQUIRES_OPTIONS = set((Type.CHECKLIST, Type.RADIO, Type.DROPDOWN))
72+
6873
class_type: Type
6974
instructions: str
7075
required: bool = False
7176
options: List[Option] = field(default_factory=list)
7277
schema_id: Optional[str] = None
7378
feature_schema_id: Optional[str] = None
7479

75-
@staticmethod
76-
def requires_options():
77-
return set((Classification.Type.CHECKLIST, Classification.Type.RADIO, Classification.Type.DROPDOWN))
78-
7980
@property
8081
def name(self):
8182
return self.instructions
8283

83-
def to_dict(self, for_different_project=False) -> Dict[str,str]:
84-
if self.class_type in Classification.requires_options() and len(self.options) < 1:
84+
def asdict(self) -> Dict[str,str]:
85+
if self.class_type in Classification._REQUIRES_OPTIONS and len(self.options) < 1:
8586
raise InconsistentOntologyException(f"Classification '{self.instructions}' requires options.")
8687
return {
8788
"type": self.class_type.value,
8889
"instructions": self.instructions,
8990
"name": self.name,
9091
"required": self.required,
91-
"options": [option.to_dict(for_different_project) for option in self.options],
92-
"schemaNodeId": None if for_different_project else self.schema_id,
93-
"featureSchemaId": None if for_different_project else self.feature_schema_id
92+
"options": [o.asdict() for o in self.options],
93+
"schemaNodeId": self.schema_id,
94+
"featureSchemaId": self.feature_schema_id
9495
}
9596

9697
@classmethod
@@ -99,14 +100,14 @@ def from_dict(cls, dictionary: Dict[str,str]):
99100
class_type = Classification.Type(dictionary["type"]),
100101
instructions = dictionary["instructions"],
101102
required = dictionary["required"],
102-
options = [Option.from_dict(option) for option in dictionary["options"]],
103+
options = [Option.from_dict(o) for o in dictionary["options"]],
103104
schema_id = dictionary["schemaNodeId"],
104105
feature_schema_id = dictionary["schemaNodeId"]
105106
)
106107

107108
def add_option(self, *args, **kwargs):
108109
new_option = Option(*args, **kwargs)
109-
if new_option.value in (option.value for option in self.options):
110+
if new_option.value in (o.value for o in self.options):
110111
raise InconsistentOntologyException(f"Duplicate option '{new_option.value}' for classification '{self.name}'.")
111112
self.options.append(new_option)
112113
return new_option
@@ -130,15 +131,15 @@ class Type(Enum):
130131
schema_id: Optional[str] = None
131132
feature_schema_id: Optional[str] = None
132133

133-
def to_dict(self,for_different_project=False) -> Dict[str,str]:
134+
def asdict(self) -> Dict[str,str]:
134135
return {
135136
"tool": self.tool.value,
136137
"name": self.name,
137138
"required": self.required,
138139
"color": self.color,
139-
"classifications": [classification.to_dict(for_different_project) for classification in self.classifications],
140-
"schemaNodeId": None if for_different_project else self.schema_id,
141-
"featureSchemaId": None if for_different_project else self.feature_schema_id
140+
"classifications": [c.asdict() for c in self.classifications],
141+
"schemaNodeId": self.schema_id,
142+
"featureSchemaId": self.feature_schema_id
142143
}
143144

144145
@classmethod
@@ -149,13 +150,13 @@ def from_dict(cls, dictionary: Dict[str,str]):
149150
feature_schema_id = dictionary["featureSchemaId"],
150151
required = dictionary["required"],
151152
tool = Tool.Type(dictionary["tool"]),
152-
classifications = [Classification.from_dict(classification) for classification in dictionary["classifications"]],
153+
classifications = [Classification.from_dict(c) for c in dictionary["classifications"]],
153154
color = dictionary["color"]
154155
)
155156

156157
def add_nested_class(self, *args, **kwargs):
157158
new_classification = Classification(*args, **kwargs)
158-
if new_classification.instructions in (classification.instructions for classification in self.classifications):
159+
if new_classification.instructions in (c.instructions for c in self.classifications):
159160
raise InconsistentOntologyException(f"Duplicate nested classification '{new_classification.instructions}' for option '{self.label}'")
160161
self.classifications.append(new_classification)
161162
return new_classification
@@ -168,8 +169,6 @@ class Ontology:
168169

169170
@classmethod
170171
def from_project(cls, project: Project):
171-
#TODO: consider if this should take in a Project object, or the project.uid.
172-
#if we take in project.uid, we need to then get the project from a client object.
173172
ontology = project.ontology().normalized
174173
return_ontology = Ontology()
175174

@@ -183,34 +182,29 @@ def from_project(cls, project: Project):
183182

184183
def add_tool(self, *args, **kwargs) -> Tool:
185184
new_tool = Tool(*args, **kwargs)
186-
if new_tool.name in (tool.name for tool in self.tools):
185+
if new_tool.name in (t.name for t in self.tools):
187186
raise InconsistentOntologyException(f"Duplicate tool name '{new_tool.name}'. ")
188187
self.tools.append(new_tool)
189188
return new_tool
190189

191190
def add_classification(self, *args, **kwargs) -> Classification:
192191
new_classification = Classification(*args, **kwargs)
193-
if new_classification.instructions in (classification.instructions for classification in self.classifications):
192+
if new_classification.instructions in (c.instructions for c in self.classifications):
194193
raise InconsistentOntologyException(f"Duplicate classifications instructions '{new_classification.instructions}'. ")
195194
self.classifications.append(new_classification)
196195
return new_classification
197196

198-
def build(self, for_different_project=False):
197+
def asdict(self):
199198
all_tools = []
200199
all_classifications = []
201200

202201
for tool in self.tools:
203-
all_tools.append(tool.to_dict(for_different_project))
202+
all_tools.append(tool.asdict())
204203

205204
for classification in self.classifications:
206-
all_classifications.append(classification.to_dict(for_different_project))
205+
all_classifications.append(classification.asdict())
207206

208207
return {"tools": all_tools, "classifications": all_classifications}
209208

210209
if __name__ == "__main__":
211-
pass
212-
213-
214-
215-
216-
210+
pass

0 commit comments

Comments
 (0)