anoy 0.1.3__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {anoy-0.1.3/src/anoy.egg-info → anoy-0.2.1}/PKG-INFO +24 -2
- {anoy-0.1.3 → anoy-0.2.1}/README.md +23 -1
- {anoy-0.1.3 → anoy-0.2.1}/pyproject.toml +1 -1
- {anoy-0.1.3 → anoy-0.2.1/src/anoy.egg-info}/PKG-INFO +24 -2
- anoy-0.2.1/src/anoyModule/__init__.py +3 -0
- {anoy-0.1.3 → anoy-0.2.1}/src/anoyModule/anoyErrors.py +6 -6
- anoy-0.2.1/src/anoyModule/dictTraversal.py +642 -0
- {anoy-0.1.3 → anoy-0.2.1}/src/cli.py +1 -1
- anoy-0.1.3/src/anoyModule/__init__.py +0 -3
- anoy-0.1.3/src/anoyModule/dictTraversal.py +0 -219
- {anoy-0.1.3 → anoy-0.2.1}/LICENSE.txt +0 -0
- {anoy-0.1.3 → anoy-0.2.1}/setup.cfg +0 -0
- {anoy-0.1.3 → anoy-0.2.1}/src/anoy.egg-info/SOURCES.txt +0 -0
- {anoy-0.1.3 → anoy-0.2.1}/src/anoy.egg-info/dependency_links.txt +0 -0
- {anoy-0.1.3 → anoy-0.2.1}/src/anoy.egg-info/entry_points.txt +0 -0
- {anoy-0.1.3 → anoy-0.2.1}/src/anoy.egg-info/requires.txt +0 -0
- {anoy-0.1.3 → anoy-0.2.1}/src/anoy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: anoy
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: This is a library that provides simple type checking for YAML.
|
|
5
5
|
Author-email: masaniki <masaniki.software@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -143,7 +143,7 @@ When there is an issue with the annotation YAML, `anoy` outputs as follows.
|
|
|
143
143
|
... (omission) ...
|
|
144
144
|
src.anoyModule.anoyErrors.ConfigurationYamlError: `@Auther` is not defined.
|
|
145
145
|
```
|
|
146
|
-
# For
|
|
146
|
+
# For Developers
|
|
147
147
|
|
|
148
148
|
## Testing
|
|
149
149
|
|
|
@@ -152,3 +152,25 @@ This project uses `pytest`.
|
|
|
152
152
|
If you want to test, put in following command.
|
|
153
153
|
|
|
154
154
|
`pytest tests\unit\test_dictTraversal.py`
|
|
155
|
+
|
|
156
|
+
## Next To Do
|
|
157
|
+
|
|
158
|
+
- [ ] test caseを全てのdata型に拡大。
|
|
159
|
+
- [ ] `!Float`のtest.
|
|
160
|
+
- [ ] `!AnnoMap`のtest.
|
|
161
|
+
- [ ] `!FreeMap`のtest.
|
|
162
|
+
|
|
163
|
+
## Ideas
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
- key01
|
|
167
|
+
- key02
|
|
168
|
+
- key03
|
|
169
|
+
```
|
|
170
|
+
と
|
|
171
|
+
```
|
|
172
|
+
- {key01:value01}
|
|
173
|
+
- {key02:value02}
|
|
174
|
+
- {key03:value03}
|
|
175
|
+
```
|
|
176
|
+
を等価に扱うsystemが欲しい。
|
|
@@ -122,7 +122,7 @@ When there is an issue with the annotation YAML, `anoy` outputs as follows.
|
|
|
122
122
|
... (omission) ...
|
|
123
123
|
src.anoyModule.anoyErrors.ConfigurationYamlError: `@Auther` is not defined.
|
|
124
124
|
```
|
|
125
|
-
# For
|
|
125
|
+
# For Developers
|
|
126
126
|
|
|
127
127
|
## Testing
|
|
128
128
|
|
|
@@ -131,3 +131,25 @@ This project uses `pytest`.
|
|
|
131
131
|
If you want to test, put in following command.
|
|
132
132
|
|
|
133
133
|
`pytest tests\unit\test_dictTraversal.py`
|
|
134
|
+
|
|
135
|
+
## Next To Do
|
|
136
|
+
|
|
137
|
+
- [ ] test caseを全てのdata型に拡大。
|
|
138
|
+
- [ ] `!Float`のtest.
|
|
139
|
+
- [ ] `!AnnoMap`のtest.
|
|
140
|
+
- [ ] `!FreeMap`のtest.
|
|
141
|
+
|
|
142
|
+
## Ideas
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
- key01
|
|
146
|
+
- key02
|
|
147
|
+
- key03
|
|
148
|
+
```
|
|
149
|
+
と
|
|
150
|
+
```
|
|
151
|
+
- {key01:value01}
|
|
152
|
+
- {key02:value02}
|
|
153
|
+
- {key03:value03}
|
|
154
|
+
```
|
|
155
|
+
を等価に扱うsystemが欲しい。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: anoy
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: This is a library that provides simple type checking for YAML.
|
|
5
5
|
Author-email: masaniki <masaniki.software@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -143,7 +143,7 @@ When there is an issue with the annotation YAML, `anoy` outputs as follows.
|
|
|
143
143
|
... (omission) ...
|
|
144
144
|
src.anoyModule.anoyErrors.ConfigurationYamlError: `@Auther` is not defined.
|
|
145
145
|
```
|
|
146
|
-
# For
|
|
146
|
+
# For Developers
|
|
147
147
|
|
|
148
148
|
## Testing
|
|
149
149
|
|
|
@@ -152,3 +152,25 @@ This project uses `pytest`.
|
|
|
152
152
|
If you want to test, put in following command.
|
|
153
153
|
|
|
154
154
|
`pytest tests\unit\test_dictTraversal.py`
|
|
155
|
+
|
|
156
|
+
## Next To Do
|
|
157
|
+
|
|
158
|
+
- [ ] test caseを全てのdata型に拡大。
|
|
159
|
+
- [ ] `!Float`のtest.
|
|
160
|
+
- [ ] `!AnnoMap`のtest.
|
|
161
|
+
- [ ] `!FreeMap`のtest.
|
|
162
|
+
|
|
163
|
+
## Ideas
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
- key01
|
|
167
|
+
- key02
|
|
168
|
+
- key03
|
|
169
|
+
```
|
|
170
|
+
と
|
|
171
|
+
```
|
|
172
|
+
- {key01:value01}
|
|
173
|
+
- {key02:value02}
|
|
174
|
+
- {key03:value03}
|
|
175
|
+
```
|
|
176
|
+
を等価に扱うsystemが欲しい。
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
class
|
|
2
|
+
class AnoyError(Exception):
|
|
3
3
|
"""
|
|
4
4
|
@Summ: annotation yaml上のError。
|
|
5
5
|
"""
|
|
@@ -7,20 +7,20 @@ class AnnotationYamlError(Exception):
|
|
|
7
7
|
super().__init__(*args)
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class
|
|
10
|
+
class AnoyTypeError(Exception):
|
|
11
11
|
"""
|
|
12
12
|
@Summ: annotation yaml上のdata型のError。
|
|
13
13
|
"""
|
|
14
|
-
def __init__(self,
|
|
14
|
+
def __init__(self,type:str,fileName:str,path:list):
|
|
15
15
|
super().__init__()
|
|
16
|
-
self.fileName=fileName
|
|
17
16
|
self.type=type
|
|
17
|
+
self.fileName=fileName
|
|
18
18
|
self.path=path
|
|
19
19
|
|
|
20
20
|
def __str__(self):
|
|
21
|
-
return f"
|
|
21
|
+
return f"{self.type} contradiction:\n {self.fileName}: {self.path}"
|
|
22
22
|
|
|
23
|
-
class
|
|
23
|
+
class ConfigYamlError(Exception):
|
|
24
24
|
"""
|
|
25
25
|
@Summ: annotation yaml上のError。
|
|
26
26
|
"""
|
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
import yaml
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from .anoyErrors import AnoyError,ConfigYamlError,AnoyTypeError
|
|
5
|
+
|
|
6
|
+
class DictTraversal():
|
|
7
|
+
"""
|
|
8
|
+
@Summ: 辞書型の中身を探索するclass.
|
|
9
|
+
|
|
10
|
+
@InsVars:
|
|
11
|
+
_configDict:
|
|
12
|
+
@Summ: config yamlを構文解析した後の値を格納する。
|
|
13
|
+
@Desc:
|
|
14
|
+
- !Childの値は{"!Child": {typeString(str):typOption(dict)}}という形式に直す。
|
|
15
|
+
- typeStringはdata型を表す文字列。
|
|
16
|
+
- typeOptionはdata型の詳細な設定を表すdict型である。
|
|
17
|
+
- つまり、str-format data typeもmap-format data typeに直すということ。
|
|
18
|
+
- map-format data typeが無いBool型は{"!Bool":{}}とする。
|
|
19
|
+
- annotation keyを使った否かを"isVisit" keyに記録する。
|
|
20
|
+
@Type: Dict
|
|
21
|
+
_visitQueue:
|
|
22
|
+
@Summ: 探索queue
|
|
23
|
+
@Desc: BFSなのでFIFO。
|
|
24
|
+
@Type: List
|
|
25
|
+
_pathQueue:
|
|
26
|
+
@Summ: 探索する要素の相対pathを格納する。
|
|
27
|
+
@Desc:
|
|
28
|
+
- visitQueueと要素番号を共有する。
|
|
29
|
+
- []でroot要素を表す。
|
|
30
|
+
@Type: List
|
|
31
|
+
_curFile:
|
|
32
|
+
@Summ: 現在探索中のANOY file名。
|
|
33
|
+
@ComeFrom: current file.
|
|
34
|
+
@Type: Str
|
|
35
|
+
_curPath:
|
|
36
|
+
@Summ: _curFile内での現在地。
|
|
37
|
+
@ComeFrom: current path/
|
|
38
|
+
@Type: List
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self,configDict:dict):
|
|
42
|
+
"""
|
|
43
|
+
@Summ: constructor.
|
|
44
|
+
"""
|
|
45
|
+
self._configDict=self.checkConfig(configDict)
|
|
46
|
+
print(self._configDict)
|
|
47
|
+
self._visitQueue=[]
|
|
48
|
+
self._pathQueue=[]
|
|
49
|
+
self._curFile=""
|
|
50
|
+
self._curPath=[]
|
|
51
|
+
|
|
52
|
+
def checkConfig(self,configDict:dict)->dict:
|
|
53
|
+
"""
|
|
54
|
+
@Summ: config yamlの中身を構文解析する関数。
|
|
55
|
+
|
|
56
|
+
@Desc
|
|
57
|
+
- config yamlは、annotation keyかconfig keyの記述しか許さない。
|
|
58
|
+
- configDictに"isVisit" keyを追加し、annotation keyを使用したかを記録する。
|
|
59
|
+
|
|
60
|
+
@Args:
|
|
61
|
+
configDict:
|
|
62
|
+
@Summ: config yamlの中身。
|
|
63
|
+
@Type: Dict
|
|
64
|
+
@Returns:
|
|
65
|
+
@Summ: 型確認して、余計なものを取り除いたconfigDict。
|
|
66
|
+
@Type: dict
|
|
67
|
+
"""
|
|
68
|
+
newConfigDict={} # 整形されたconfigDict
|
|
69
|
+
for annoKey in configDict.keys():
|
|
70
|
+
newAnnoValue={} #annotation keyに対応する値。
|
|
71
|
+
if(annoKey[0]!="@"):
|
|
72
|
+
raise ConfigYamlError(f"{annoKey} is invalid definition.")
|
|
73
|
+
valueDict=configDict[annoKey]
|
|
74
|
+
if(type(valueDict)!=dict):
|
|
75
|
+
raise ConfigYamlError(f"{annoKey} is invalid definition.")
|
|
76
|
+
for key,value in valueDict.items():
|
|
77
|
+
if(key[0]=="@"):
|
|
78
|
+
continue
|
|
79
|
+
elif(key=="!Parent"):
|
|
80
|
+
validConfParent=self.checkParent(annoKey,value)
|
|
81
|
+
newAnnoValue["!Parent"]=validConfParent
|
|
82
|
+
elif(key=="!Child"):
|
|
83
|
+
validConfChild=self.checkChild(annoKey,value)
|
|
84
|
+
newAnnoValue["!Child"]=validConfChild
|
|
85
|
+
else:
|
|
86
|
+
raise ConfigYamlError(f"{annoKey} is invalid definition.")
|
|
87
|
+
# isVisit keyの追加。
|
|
88
|
+
newAnnoValue["isVisit"]=False
|
|
89
|
+
newConfigDict[annoKey]=newAnnoValue
|
|
90
|
+
return newConfigDict
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def checkParent(cls,annoKey,confParent):
|
|
94
|
+
"""
|
|
95
|
+
@Summ: `!Parent`に対応する値を型確認する関数。
|
|
96
|
+
|
|
97
|
+
@Args:
|
|
98
|
+
annoKey:
|
|
99
|
+
@Summ: `!Parent`の親となるannotation key.
|
|
100
|
+
@Type: Str
|
|
101
|
+
confParent:
|
|
102
|
+
@Summ: `!Parent`の子。
|
|
103
|
+
@Type: Any
|
|
104
|
+
@Returns:
|
|
105
|
+
@Summ: `!Parent`のvalueとして有効な値。
|
|
106
|
+
@Type: List
|
|
107
|
+
"""
|
|
108
|
+
if(type(confParent)!=list):
|
|
109
|
+
raise ConfigYamlError(f"{annoKey} is invalid definition.")
|
|
110
|
+
for item in confParent:
|
|
111
|
+
if(item is None):
|
|
112
|
+
continue
|
|
113
|
+
if(item[0]!="@"):
|
|
114
|
+
raise ConfigYamlError(f"{annoKey} is invalid definition.")
|
|
115
|
+
return confParent.copy()
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def checkChild(cls,annoKey,confChild):
|
|
119
|
+
"""
|
|
120
|
+
@Summ: `!Child`に対応する値を型確認する関数。
|
|
121
|
+
|
|
122
|
+
@Args:
|
|
123
|
+
annoKey:
|
|
124
|
+
@Summ: `!Child`の親となるannotation key.
|
|
125
|
+
@Type: Str
|
|
126
|
+
confChild:
|
|
127
|
+
@Summ: `!Child`の子。
|
|
128
|
+
@Type: Any
|
|
129
|
+
@Returns:
|
|
130
|
+
@Summ: `!Child`のvalueとして有効な値。
|
|
131
|
+
@Type: Dict
|
|
132
|
+
"""
|
|
133
|
+
if(type(confChild)==str):
|
|
134
|
+
match confChild:
|
|
135
|
+
case "!Str":
|
|
136
|
+
return {"!Str":{"length":None,"min":None,"max":None}}
|
|
137
|
+
case "!Bool":
|
|
138
|
+
return {"!Bool":{}}
|
|
139
|
+
case "!Int":
|
|
140
|
+
return {"!Int":{"min":None,"max":None}}
|
|
141
|
+
case "!Float":
|
|
142
|
+
return {"!Float":{"min":None,"max":None}}
|
|
143
|
+
case "!List":
|
|
144
|
+
return {"!List":{"type":None,"length":None}}
|
|
145
|
+
case "!FreeMap":
|
|
146
|
+
return {"!FreeMap":{}}
|
|
147
|
+
case "!AnnoMap":
|
|
148
|
+
return {"!AnnoMap":[]}
|
|
149
|
+
case _:
|
|
150
|
+
raise ConfigYamlError(f"{annoKey} is invalid definition.")
|
|
151
|
+
elif(type(confChild)==dict):
|
|
152
|
+
confChildKey=list(confChild.keys())
|
|
153
|
+
if(len(confChildKey)!=1):
|
|
154
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
155
|
+
typeStr=confChildKey[0]
|
|
156
|
+
typeOption=confChild[typeStr]
|
|
157
|
+
match typeStr:
|
|
158
|
+
case "!Str":
|
|
159
|
+
if(type(typeOption)!=dict):
|
|
160
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
161
|
+
strLength=None
|
|
162
|
+
strMin=None
|
|
163
|
+
strMax=None
|
|
164
|
+
for strKey,strVal in typeOption.items():
|
|
165
|
+
match strKey:
|
|
166
|
+
case "length":
|
|
167
|
+
if(strMin is None and strMax is None):
|
|
168
|
+
strLength=strVal
|
|
169
|
+
else:
|
|
170
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
171
|
+
case "min":
|
|
172
|
+
if(strLength is None):
|
|
173
|
+
strMin=strVal
|
|
174
|
+
else:
|
|
175
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
176
|
+
case "max":
|
|
177
|
+
if(strLength is None):
|
|
178
|
+
strMax=strVal
|
|
179
|
+
else:
|
|
180
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
181
|
+
case _:
|
|
182
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
183
|
+
return {"!Str":{"length":strLength,"min":strMin,"max":strMax}}
|
|
184
|
+
case "!Int":
|
|
185
|
+
if(type(typeOption)!=dict):
|
|
186
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
187
|
+
intMin=None
|
|
188
|
+
intMax=None
|
|
189
|
+
for intKey,intVal in typeOption.items():
|
|
190
|
+
match intKey:
|
|
191
|
+
case "min":
|
|
192
|
+
intMin=intVal
|
|
193
|
+
case "max":
|
|
194
|
+
intMax=intVal
|
|
195
|
+
case _:
|
|
196
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
197
|
+
return {"!Int":{"min":intMin,"max":intMax}}
|
|
198
|
+
case "!Float":
|
|
199
|
+
if(type(typeOption)!=dict):
|
|
200
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
201
|
+
floatMin=None
|
|
202
|
+
floatMax=None
|
|
203
|
+
for floatKey,floatVal in typeOption.items():
|
|
204
|
+
match floatKey:
|
|
205
|
+
case "min":
|
|
206
|
+
floatMin=floatVal
|
|
207
|
+
case "max":
|
|
208
|
+
floatMax=floatVal
|
|
209
|
+
case _:
|
|
210
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
211
|
+
return {"!Float":{"min":floatMin,"max":floatMax}}
|
|
212
|
+
case "!Enum":
|
|
213
|
+
if(type(typeOption)!=list):
|
|
214
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
215
|
+
enumOption=[]
|
|
216
|
+
for item in typeOption:
|
|
217
|
+
if(type(item)==list):
|
|
218
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
219
|
+
elif(type(item)==dict):
|
|
220
|
+
keyList=list(item.keys())
|
|
221
|
+
if(len(keyList)!=1):
|
|
222
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
223
|
+
enumOption.append(keyList[0])
|
|
224
|
+
else:
|
|
225
|
+
enumOption.append(item)
|
|
226
|
+
return {"!Enum":enumOption}
|
|
227
|
+
case "!List":
|
|
228
|
+
if(type(typeOption)!=dict):
|
|
229
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
230
|
+
listType=None
|
|
231
|
+
listLength=None
|
|
232
|
+
for listKey,listVal in typeOption.items():
|
|
233
|
+
match listKey:
|
|
234
|
+
case "type":
|
|
235
|
+
listType=listVal
|
|
236
|
+
case "length":
|
|
237
|
+
listLength=listVal
|
|
238
|
+
case _:
|
|
239
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
240
|
+
return {"!List":{"type":listType,"length":listLength}}
|
|
241
|
+
case "!AnnoDict":
|
|
242
|
+
if(type(typeOption)!=list):
|
|
243
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
244
|
+
for i in len(typeOption):
|
|
245
|
+
item=typeOption[i]
|
|
246
|
+
if(item[0]!="@"):
|
|
247
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
248
|
+
return {"!AnnoDict":typeOption}
|
|
249
|
+
case _:
|
|
250
|
+
raise ConfigYamlError(f"`{annoKey}` has invalid definition.")
|
|
251
|
+
else:
|
|
252
|
+
raise ConfigYamlError(f"{annoKey} is invalid definition.")
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def dirDFS(self,anoyPath:Path):
|
|
256
|
+
"""
|
|
257
|
+
@Summ: directory内を深さ優先探索する関数。
|
|
258
|
+
|
|
259
|
+
@Desc:
|
|
260
|
+
- fileならばYAMLかどうかを確認して、内部のdict型を探索する。
|
|
261
|
+
- directoryならば、子要素を再帰的に探索する。
|
|
262
|
+
|
|
263
|
+
@Args:
|
|
264
|
+
anoyPath:
|
|
265
|
+
@Summ: 探索するfileやdirectoryのpath名。
|
|
266
|
+
@Type: Path
|
|
267
|
+
"""
|
|
268
|
+
if(anoyPath.is_file()):
|
|
269
|
+
suffix=anoyPath.suffix
|
|
270
|
+
if(suffix==".yaml" or suffix==".yml" or suffix==".anoy"):
|
|
271
|
+
with open(anoyPath, mode="r", encoding="utf-8") as f:
|
|
272
|
+
anoyDict=yaml.safe_load(f)
|
|
273
|
+
self._curFile=anoyPath
|
|
274
|
+
self.dictBFS(anoyDict)
|
|
275
|
+
else:
|
|
276
|
+
for childPath in anoyPath.iterdir():
|
|
277
|
+
self.dirDFS(childPath)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def dictBFS(self,anoyDict:dict):
|
|
281
|
+
"""
|
|
282
|
+
@Summ: anoyDictの中を幅優先探索を開始する関数。
|
|
283
|
+
|
|
284
|
+
@Desc:
|
|
285
|
+
- list型は単純に探索する。
|
|
286
|
+
- dict型は型確認しながら探索する。
|
|
287
|
+
- visitQueueには(key(str),value(any))のtupleを入れる。
|
|
288
|
+
- list型の時は、(key(int),value(any))になる。
|
|
289
|
+
@Args:
|
|
290
|
+
anoyDict:
|
|
291
|
+
@Summ: annotation yamlのdict型。
|
|
292
|
+
"""
|
|
293
|
+
self._visitQueue=[(None,anoyDict)]
|
|
294
|
+
self._pathQueue=[[]]
|
|
295
|
+
while(True):
|
|
296
|
+
if(self._visitQueue==[]):
|
|
297
|
+
break
|
|
298
|
+
key,value=self._visitQueue.pop(0)
|
|
299
|
+
self._curPath=self._pathQueue.pop(0)
|
|
300
|
+
print(key,value)
|
|
301
|
+
print(self._curPath)
|
|
302
|
+
self.checkAnoy(key,value)
|
|
303
|
+
|
|
304
|
+
def checkAnoy(self,parentKey:str|None,childValue):
|
|
305
|
+
"""
|
|
306
|
+
"@Summ": anoyの中身を探索する関数。
|
|
307
|
+
|
|
308
|
+
"@Desc":
|
|
309
|
+
- 型確認は"!Parent"と"!Child"の2つだ。
|
|
310
|
+
- parentKeyの`!Child`がchildValueを制限する。
|
|
311
|
+
- childValueの`!parent`がparentKeyを制限する。
|
|
312
|
+
- parentKeyがannotationKeyでない時は、"!Parent"も"!Child"も効力を発揮しないので無視。
|
|
313
|
+
- !Childが無い時は、childValue=Noneとして考える。
|
|
314
|
+
- `!Parent`による型確認は、childValueが`!AnnoMap`型の時のみ行われる。
|
|
315
|
+
|
|
316
|
+
"@Args":
|
|
317
|
+
parentKey:
|
|
318
|
+
"@Summ": 探索するdict型のkey。
|
|
319
|
+
"@Desc":
|
|
320
|
+
- nullは親要素が存在しないことを表す(つまりvalueがroot要素である)。
|
|
321
|
+
"@Type":
|
|
322
|
+
Union:
|
|
323
|
+
- Str
|
|
324
|
+
- null
|
|
325
|
+
childValue:
|
|
326
|
+
"@Summ": 探索するdict型のvalue。
|
|
327
|
+
"@Type": Any
|
|
328
|
+
"@Error":
|
|
329
|
+
- AnnotationYamlError
|
|
330
|
+
- AnnotationYamlTypeError
|
|
331
|
+
- ConfigurationYamlError
|
|
332
|
+
"""
|
|
333
|
+
if(parentKey is None):
|
|
334
|
+
confChild=None #confChild=Noneの時は型確認をしない。
|
|
335
|
+
elif(type(parentKey)!=str):
|
|
336
|
+
confChild=None
|
|
337
|
+
elif(parentKey[0]=="@"):
|
|
338
|
+
confDictVal=self._configDict.get(parentKey)
|
|
339
|
+
if(confDictVal is None):
|
|
340
|
+
raise AnoyError(f"{parentKey} is not found.")
|
|
341
|
+
confChild=confDictVal.get("!Child")
|
|
342
|
+
else:
|
|
343
|
+
confChild=None
|
|
344
|
+
# anoyの型確認
|
|
345
|
+
if(confChild is None): #Noneの処理方法は不明。
|
|
346
|
+
# nestになるlistとdictだけ対処する。
|
|
347
|
+
if(type(childValue)==list):
|
|
348
|
+
for i in range(len(childValue)):
|
|
349
|
+
element=childValue[i]
|
|
350
|
+
newPath=self._curPath+[i]
|
|
351
|
+
self._visitQueue.append((i,element))
|
|
352
|
+
self._pathQueue.append(newPath)
|
|
353
|
+
elif(type(childValue)==dict):
|
|
354
|
+
for key,value in childValue.items():
|
|
355
|
+
newPath=self._curPath+[key]
|
|
356
|
+
self._visitQueue.append((key,value))
|
|
357
|
+
self._pathQueue.append(newPath)
|
|
358
|
+
return
|
|
359
|
+
typeStr=list(confChild.keys())[0]
|
|
360
|
+
typeOption=confChild[typeStr]
|
|
361
|
+
match typeStr:
|
|
362
|
+
case "!Str":
|
|
363
|
+
self.checkStr(childValue,**typeOption)
|
|
364
|
+
case "!Bool":
|
|
365
|
+
self.checkBool(childValue)
|
|
366
|
+
case "!Int":
|
|
367
|
+
self.checkInt(childValue,**typeOption)
|
|
368
|
+
case "!Float":
|
|
369
|
+
self.checkFloat(childValue,**typeOption)
|
|
370
|
+
case "!FreeMap":
|
|
371
|
+
self.checkFreeMap(childValue)
|
|
372
|
+
case "!AnnoMap":
|
|
373
|
+
self.checkAnnoMap(parentKey,childValue,typeOption)
|
|
374
|
+
case "!List":
|
|
375
|
+
self.checkList(parentKey,childValue,elementType=typeOption["type"],length=typeOption["length"])
|
|
376
|
+
case "!Enum":
|
|
377
|
+
self.checkEnum(childValue,typeOption)
|
|
378
|
+
case _:
|
|
379
|
+
raise ConfigYamlError(f"{parentKey} is invalid definition.")
|
|
380
|
+
|
|
381
|
+
def checkStr(self,anoyValue,length=None,min=None,max=None):
|
|
382
|
+
"""
|
|
383
|
+
@Summ: !Str型を型確認する関数。
|
|
384
|
+
|
|
385
|
+
@Desc:
|
|
386
|
+
- <length>と<min>、<length>と<max>の両立は不可能であるが、この関数ではその確認を行わない。
|
|
387
|
+
- 呼び出し時にその確認を行うべきである。
|
|
388
|
+
|
|
389
|
+
@Args:
|
|
390
|
+
anoyValue:
|
|
391
|
+
@Summ: 型確認する値。
|
|
392
|
+
length:
|
|
393
|
+
@Summ: 文字列の長さ。
|
|
394
|
+
@Desc: min,maxとの両立は不可能。
|
|
395
|
+
min:
|
|
396
|
+
@Summ: 文字列の長さの最小値。
|
|
397
|
+
@Desc:
|
|
398
|
+
- lengthとの両立は不可能。
|
|
399
|
+
- min-1からerror.
|
|
400
|
+
max:
|
|
401
|
+
@Summ: 文字列の長さの最大値。
|
|
402
|
+
@Desc:
|
|
403
|
+
- lengthとの両立は不可能。
|
|
404
|
+
- max+1からerror.
|
|
405
|
+
"""
|
|
406
|
+
if(type(anoyValue)==str):
|
|
407
|
+
if(length is not None):
|
|
408
|
+
if(len(anoyValue)==length):
|
|
409
|
+
return
|
|
410
|
+
else:
|
|
411
|
+
raise AnoyTypeError("!Str",self._curFile,self._curPath)
|
|
412
|
+
else:
|
|
413
|
+
if(min is not None):
|
|
414
|
+
if(len(anoyValue)<min):
|
|
415
|
+
raise AnoyTypeError("!Str",self._curFile,self._curPath)
|
|
416
|
+
if(max is not None):
|
|
417
|
+
if(max<len(anoyValue)):
|
|
418
|
+
raise AnoyTypeError("!Str",self._curFile,self._curPath)
|
|
419
|
+
return
|
|
420
|
+
else:
|
|
421
|
+
raise AnoyTypeError("!Str",self._curFile,self._curPath)
|
|
422
|
+
|
|
423
|
+
def checkBool(self,anoyValue):
|
|
424
|
+
"""
|
|
425
|
+
@Summ: !Bool型を型確認する関数。
|
|
426
|
+
|
|
427
|
+
@Args:
|
|
428
|
+
anoyValue:
|
|
429
|
+
@Summ: 型確認する値。
|
|
430
|
+
"""
|
|
431
|
+
if(type(anoyValue)!=bool):
|
|
432
|
+
raise AnoyTypeError("!Bool",self._curFile,self._curPath)
|
|
433
|
+
|
|
434
|
+
def checkInt(self,anoyValue,min=None,max=None):
|
|
435
|
+
"""
|
|
436
|
+
@Summ: !Int型を型確認する関数。
|
|
437
|
+
|
|
438
|
+
@Args:
|
|
439
|
+
anoyValue:
|
|
440
|
+
@Summ: 型確認する値。
|
|
441
|
+
min:
|
|
442
|
+
@Summ: 最小値。
|
|
443
|
+
max:
|
|
444
|
+
@Summ: 最大値。
|
|
445
|
+
"""
|
|
446
|
+
if(type(anoyValue)==int):
|
|
447
|
+
if(min is not None):
|
|
448
|
+
if(anoyValue<min):
|
|
449
|
+
raise AnoyTypeError("!Int",self._curFile,self._curPath)
|
|
450
|
+
if(max is not None):
|
|
451
|
+
if(max<anoyValue):
|
|
452
|
+
raise AnoyTypeError("!Int",self._curFile,self._curPath)
|
|
453
|
+
return
|
|
454
|
+
else:
|
|
455
|
+
raise AnoyTypeError("!Int",self._curFile,self._curPath)
|
|
456
|
+
|
|
457
|
+
def checkFloat(self,anoyValue,min=None,max=None):
|
|
458
|
+
"""
|
|
459
|
+
@Summ: !Float型を型確認する関数。
|
|
460
|
+
|
|
461
|
+
@Args:
|
|
462
|
+
anoyValue:
|
|
463
|
+
@Summ: 型確認する値。
|
|
464
|
+
min:
|
|
465
|
+
@Summ: 最小値。
|
|
466
|
+
max:
|
|
467
|
+
@Summ: 最大値。
|
|
468
|
+
"""
|
|
469
|
+
if(type(anoyValue)==float):
|
|
470
|
+
if(min is not None):
|
|
471
|
+
if(anoyValue<min):
|
|
472
|
+
raise AnoyTypeError("!Float",self._curFile,self._curPath)
|
|
473
|
+
if(max is not None):
|
|
474
|
+
if(max<anoyValue):
|
|
475
|
+
raise AnoyTypeError("!Float",self._curFile,self._curPath)
|
|
476
|
+
return
|
|
477
|
+
else:
|
|
478
|
+
raise AnoyTypeError("!Float",self._curFile,self._curPath)
|
|
479
|
+
|
|
480
|
+
def checkFreeMap(self,anoyValue):
|
|
481
|
+
"""
|
|
482
|
+
@Summ: !FreeMap型を型確認する関数。
|
|
483
|
+
|
|
484
|
+
@Args:
|
|
485
|
+
anoyValue:
|
|
486
|
+
@Summ: 型確認する値。
|
|
487
|
+
"""
|
|
488
|
+
if(type(anoyValue)==dict):
|
|
489
|
+
for key,value in anoyValue.items():
|
|
490
|
+
newPath=self._curPath+[key]
|
|
491
|
+
self._visitQueue.append((key,value))
|
|
492
|
+
self._pathQueue.append(newPath)
|
|
493
|
+
if(key[0]=="@"):
|
|
494
|
+
raise AnoyTypeError("!FreeMap",self._curFile,newPath)
|
|
495
|
+
else:
|
|
496
|
+
raise AnoyTypeError("!FreeMap",self._curFile,self._curPath)
|
|
497
|
+
|
|
498
|
+
def checkAnnoMap(self,parentKey,anoyValue,annoKeyList:list=[]):
|
|
499
|
+
"""
|
|
500
|
+
@Summ: !FreeMap型を型確認する関数。
|
|
501
|
+
|
|
502
|
+
@Desc:
|
|
503
|
+
- <annoKeyList>は最低限必要なannotation keyのlistが入る。
|
|
504
|
+
- 最低限なので、<annoKeyList>以外のannotation keyも許容される。
|
|
505
|
+
|
|
506
|
+
@Args:
|
|
507
|
+
parentKey:
|
|
508
|
+
@Summ: 親要素のannotation key。
|
|
509
|
+
@Type: Str
|
|
510
|
+
anoyValue:
|
|
511
|
+
@Summ: 型確認する値。
|
|
512
|
+
annoKeyList:
|
|
513
|
+
@Summ: annotation keyのlist。
|
|
514
|
+
@Type: List
|
|
515
|
+
@Default: []
|
|
516
|
+
"""
|
|
517
|
+
if(type(anoyValue)==dict):
|
|
518
|
+
for key,value in anoyValue.items():
|
|
519
|
+
newPath=self._curPath+[key]
|
|
520
|
+
self._visitQueue.append((key,value))
|
|
521
|
+
self._pathQueue.append(newPath)
|
|
522
|
+
# !Parentの確認。
|
|
523
|
+
configValue=self._configDict.get(key)
|
|
524
|
+
if(configValue is None):
|
|
525
|
+
raise AnoyError(f"{parentKey} is not found.")
|
|
526
|
+
confParent=configValue.get("!Parent")
|
|
527
|
+
if(confParent is not None):
|
|
528
|
+
if(parentKey not in confParent):
|
|
529
|
+
raise AnoyTypeError("!Parent",self._curFile,newPath)
|
|
530
|
+
if(annoKeyList!=[]):
|
|
531
|
+
if(key not in annoKeyList):
|
|
532
|
+
raise AnoyTypeError("!AnnoMap",self._curFile,self._curPath)
|
|
533
|
+
else:
|
|
534
|
+
raise AnoyTypeError("!AnnoMap",self._curFile,self._curPath)
|
|
535
|
+
|
|
536
|
+
def checkList(self,parentKey,anoyValue,elementType:str=None,length:int=None):
|
|
537
|
+
"""
|
|
538
|
+
@Summ: !List型を型確認する関数。
|
|
539
|
+
|
|
540
|
+
@Desc:
|
|
541
|
+
- <typeOption>は最低限必要なannotation keyのlistが入る。
|
|
542
|
+
- 最低限なので、<typeOption>以外のannotation keyも許容される。
|
|
543
|
+
|
|
544
|
+
@Args:
|
|
545
|
+
parentKey:
|
|
546
|
+
@Summ: 親のkey。
|
|
547
|
+
@Type: Str
|
|
548
|
+
anoyValue:
|
|
549
|
+
@Summ: 型確認する値。
|
|
550
|
+
elementType:
|
|
551
|
+
@Summ: list型の子要素のdata型。
|
|
552
|
+
@Desc:
|
|
553
|
+
- [!Bool,!Str,!Int,!Float]を指定できる。
|
|
554
|
+
- Noneの時はdata型を確認しない。
|
|
555
|
+
@Type: Str
|
|
556
|
+
length:
|
|
557
|
+
@Summ: listの長さ
|
|
558
|
+
@Type: Int
|
|
559
|
+
"""
|
|
560
|
+
if(type(anoyValue)==list):
|
|
561
|
+
if(length is not None):
|
|
562
|
+
if(length!=len(anoyValue)):
|
|
563
|
+
raise AnoyTypeError("!List",self._curFile,self._curPath)
|
|
564
|
+
for i in range(len(anoyValue)):
|
|
565
|
+
element=anoyValue[i]
|
|
566
|
+
newPath=self._curPath+[i]
|
|
567
|
+
if(elementType is not None):
|
|
568
|
+
match elementType:
|
|
569
|
+
case "!Str":
|
|
570
|
+
if(type(element)!=str):
|
|
571
|
+
raise AnoyTypeError("!List",self._curFile,newPath)
|
|
572
|
+
case "!Bool":
|
|
573
|
+
if(type(element)!=bool):
|
|
574
|
+
raise AnoyTypeError("!List",self._curFile,newPath)
|
|
575
|
+
case "!Int":
|
|
576
|
+
if(type(element)!=int):
|
|
577
|
+
raise AnoyTypeError("!List",self._curFile,newPath)
|
|
578
|
+
case "!Float":
|
|
579
|
+
if(type(element)!=float):
|
|
580
|
+
raise AnoyTypeError("!List",self._curFile,newPath)
|
|
581
|
+
case _:
|
|
582
|
+
raise ConfigYamlError(f"{parentKey} is invalid definition.")
|
|
583
|
+
self._visitQueue.append((i,element))
|
|
584
|
+
self._pathQueue.append(newPath)
|
|
585
|
+
else:
|
|
586
|
+
raise AnoyTypeError("!List",self._curFile,self._curPath)
|
|
587
|
+
|
|
588
|
+
def checkEnum(self,anoyValue,optionList:list):
|
|
589
|
+
"""
|
|
590
|
+
@Summ: !Enum型を型確認する関数。
|
|
591
|
+
|
|
592
|
+
@Desc:
|
|
593
|
+
- 他の言語のUnion型の役割も兼ねている。
|
|
594
|
+
- 選択できるdata型は、[null,!Bool,!Str,!Int,!Float,!List,!FreeMap]である。
|
|
595
|
+
- 入れ子の下層までは確認しない(浅いdata型確認)。
|
|
596
|
+
|
|
597
|
+
@Args:
|
|
598
|
+
anoyValue:
|
|
599
|
+
@Summ: 型確認する値。
|
|
600
|
+
optionList:
|
|
601
|
+
@Summ: Enum型の選択肢を格納するlist型。
|
|
602
|
+
@Type: List
|
|
603
|
+
"""
|
|
604
|
+
for i in range(len(optionList)):
|
|
605
|
+
option=optionList[i]
|
|
606
|
+
if(option is None and anoyValue is None):
|
|
607
|
+
return
|
|
608
|
+
match option:
|
|
609
|
+
case "!Str":
|
|
610
|
+
if(type(anoyValue)==str):
|
|
611
|
+
return
|
|
612
|
+
case "!Bool":
|
|
613
|
+
if(type(anoyValue)==bool):
|
|
614
|
+
return
|
|
615
|
+
case "!Int":
|
|
616
|
+
if(type(anoyValue)==int):
|
|
617
|
+
return
|
|
618
|
+
case "!Float":
|
|
619
|
+
if(type(anoyValue)==float):
|
|
620
|
+
return
|
|
621
|
+
case "!List":
|
|
622
|
+
if(type(anoyValue)==list):
|
|
623
|
+
return
|
|
624
|
+
case "!FreeMap":
|
|
625
|
+
if(type(anoyValue)==dict):
|
|
626
|
+
return
|
|
627
|
+
case _:
|
|
628
|
+
if(anoyValue==option):
|
|
629
|
+
return
|
|
630
|
+
raise AnoyTypeError("!Enum",self._curFile,self._curPath)
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
if(__name__=="__main__"):
|
|
634
|
+
configPath=r"C:\Users\tomot\Backup\sourcecode\python\projects\annotation_yaml\tests\unit\case01\config01.yaml"
|
|
635
|
+
anoyPath=r"C:\Users\tomot\Backup\sourcecode\python\projects\annotation_yaml\tests\unit\case01\int_false.yaml"
|
|
636
|
+
with open(configPath,mode="r",encoding="utf-8") as f:
|
|
637
|
+
configDict=yaml.safe_load(f)
|
|
638
|
+
with open(anoyPath,mode="r",encoding="utf-8") as f:
|
|
639
|
+
anoyDict=yaml.safe_load(f)
|
|
640
|
+
tree01=DictTraversal(configDict)
|
|
641
|
+
tree01.dictBFS(anoyDict)
|
|
642
|
+
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import yaml
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
from .anoyErrors import AnnotationYamlError,ConfigurationYamlError,AnnotationYamlTypeError
|
|
5
|
-
|
|
6
|
-
class DictTraversal():
|
|
7
|
-
"""
|
|
8
|
-
@Summ: 辞書型の中身を探索するclass
|
|
9
|
-
|
|
10
|
-
@InsVars:
|
|
11
|
-
_configDict:
|
|
12
|
-
@Summ: configuration yamlの中身。
|
|
13
|
-
@Type: Dict
|
|
14
|
-
_configVisit:
|
|
15
|
-
@Summ: configuration yaml内のannotationKeyを使った否かを記録する変数。
|
|
16
|
-
@Desc: {annotationKey(str):訪れた⇒True(bool)}
|
|
17
|
-
@Type: Dict
|
|
18
|
-
_visitQueue:
|
|
19
|
-
@Summ: 探索queue
|
|
20
|
-
@Desc: BFSなのでFIFO。
|
|
21
|
-
@Type: List
|
|
22
|
-
_pathQueue:
|
|
23
|
-
@Summ: 探索する要素の相対pathを格納する。
|
|
24
|
-
@Desc:
|
|
25
|
-
- visitQueueと要素番号を共有する。
|
|
26
|
-
- []でroot要素を表す。
|
|
27
|
-
@Type: List
|
|
28
|
-
_curAnoy:
|
|
29
|
-
@Summ: 現在探索中のANOY file.
|
|
30
|
-
@ComeFrom: current ANOY.
|
|
31
|
-
@Type: Str
|
|
32
|
-
"""
|
|
33
|
-
def __init__(self,configDict:dict):
|
|
34
|
-
"""
|
|
35
|
-
@Summ: constructor.
|
|
36
|
-
"""
|
|
37
|
-
self._configDict=configDict
|
|
38
|
-
self._visitQueue=[]
|
|
39
|
-
self._pathQueue=[]
|
|
40
|
-
self._configVisit={key:False for key in configDict.keys()}
|
|
41
|
-
self._curAnoy=""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def dirDFS(self,anoyPath:Path):
|
|
45
|
-
"""
|
|
46
|
-
@Summ: directory内を深さ優先探索する関数。
|
|
47
|
-
|
|
48
|
-
@Desc:
|
|
49
|
-
- fileならばYAMLかどうかを確認して、内部のdict型を探索する。
|
|
50
|
-
- directoryならば、子要素を再帰的に探索する。
|
|
51
|
-
|
|
52
|
-
@Args:
|
|
53
|
-
anoyPath:
|
|
54
|
-
@Summ: 探索するfileやdirectoryのpath名。
|
|
55
|
-
@Type: Path
|
|
56
|
-
"""
|
|
57
|
-
if(anoyPath.is_file()):
|
|
58
|
-
suffix=anoyPath.suffix
|
|
59
|
-
if(suffix==".yaml" or suffix==".yml" or suffix==".anoy"):
|
|
60
|
-
with open(anoyPath, mode="r", encoding="utf-8") as f:
|
|
61
|
-
anoyDict=yaml.safe_load(f)
|
|
62
|
-
self._curAnoy=anoyPath
|
|
63
|
-
self.dictBFS(anoyDict)
|
|
64
|
-
else:
|
|
65
|
-
for childPath in anoyPath.iterdir():
|
|
66
|
-
self.dirDFS(childPath)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def dictBFS(self,anoyDict:dict):
|
|
70
|
-
"""
|
|
71
|
-
@Summ: anoyDictの中を幅優先探索を開始する関数。
|
|
72
|
-
|
|
73
|
-
@Desc:
|
|
74
|
-
- list型は単純に探索する。
|
|
75
|
-
- dict型は型確認しながら探索する。
|
|
76
|
-
- visitQueueには(key(str),value(any))のtupleを入れる。
|
|
77
|
-
- list型の時は、(key(int),value(any))になる。
|
|
78
|
-
@Args:
|
|
79
|
-
anoyDict:
|
|
80
|
-
@Summ: annotation yamlのdict型。
|
|
81
|
-
"""
|
|
82
|
-
self._visitQueue=[(None,anoyDict)]
|
|
83
|
-
self._pathQueue=[[]]
|
|
84
|
-
while(True):
|
|
85
|
-
if(self._visitQueue==[]):
|
|
86
|
-
break
|
|
87
|
-
key,value=self._visitQueue.pop(0)
|
|
88
|
-
pathList=self._pathQueue.pop(0)
|
|
89
|
-
# print(key,value)
|
|
90
|
-
# print(pathList)
|
|
91
|
-
self.typeCheck(key,value,pathList)
|
|
92
|
-
|
|
93
|
-
def typeCheck(self,parentKey:str|None,childValue,path:list):
|
|
94
|
-
"""
|
|
95
|
-
"@Summ": annoDict内を探索する関数。
|
|
96
|
-
|
|
97
|
-
"@Desc":
|
|
98
|
-
- 型確認は"!ParentKey"と"!ChildValue"の2つだ。
|
|
99
|
-
- annotationKeyが親でない時は、"!ParentKey"も"!ChildValue"も効力を発揮しないので無視。
|
|
100
|
-
- ただし、annoKeyがNoneの時は、"!ParentKey"が効力を発揮する場合がある。
|
|
101
|
-
- !ChildValueが無い時は何もしない。
|
|
102
|
-
- !ChildValueが無い時は、childValue=nullとして考える。
|
|
103
|
-
- valueがanoyDict型の時のみ、!ParentKeyの型確認が行われる。
|
|
104
|
-
|
|
105
|
-
"@Args":
|
|
106
|
-
parentKey:
|
|
107
|
-
"@Summ": 探索するdict型のkey。
|
|
108
|
-
"@Desc":
|
|
109
|
-
- nullは親要素が存在しないことを表す(つまりvalueがroot要素である)。
|
|
110
|
-
"@Type":
|
|
111
|
-
Union:
|
|
112
|
-
- Str
|
|
113
|
-
- null
|
|
114
|
-
childValue:
|
|
115
|
-
"@Summ": 探索するdict型のvalue。
|
|
116
|
-
"@Type": Any
|
|
117
|
-
path:
|
|
118
|
-
@Summ: 今まで経由したkeyのlist。
|
|
119
|
-
@Type: List
|
|
120
|
-
"@Error":
|
|
121
|
-
- AnnotationYamlError
|
|
122
|
-
- AnnotationYamlTypeError
|
|
123
|
-
- ConfigurationYamlError
|
|
124
|
-
"""
|
|
125
|
-
if(parentKey is None):
|
|
126
|
-
confChildVal=None #confChild=Noneの時は型確認をしない。
|
|
127
|
-
elif(type(parentKey)!=str):
|
|
128
|
-
confChildVal=None
|
|
129
|
-
elif(parentKey[0]=="@"):
|
|
130
|
-
confChild=self._configDict.get(parentKey)
|
|
131
|
-
if(confChild is None):
|
|
132
|
-
raise ConfigurationYamlError(f"`{parentKey}` is not defined.")
|
|
133
|
-
confChildVal=confChild.get("!ChildValue")
|
|
134
|
-
else:
|
|
135
|
-
confChildVal=None
|
|
136
|
-
if(type(confChildVal)==dict):
|
|
137
|
-
#Enum型の型確認。
|
|
138
|
-
# config yaml側の型確認。
|
|
139
|
-
confKeyList=list(confChildVal.keys())
|
|
140
|
-
if(len(confKeyList)!=1 or confKeyList[0]!="Enum"):
|
|
141
|
-
raise ConfigurationYamlError(f"`{parentKey}` has invalid definition.")
|
|
142
|
-
confValueList=confChildVal["Enum"]
|
|
143
|
-
if(type(confValueList)!=list):
|
|
144
|
-
raise ConfigurationYamlError(f"`{parentKey}` has invalid definition.")
|
|
145
|
-
# annotaion yaml側の型確認。
|
|
146
|
-
for i in range(len(confValueList)):
|
|
147
|
-
if(childValue==confValueList[i]):
|
|
148
|
-
return
|
|
149
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"Enum",path)
|
|
150
|
-
elif(type(childValue)==bool):
|
|
151
|
-
if((confChildVal is None) or confChildVal=="Bool"):
|
|
152
|
-
return
|
|
153
|
-
else:
|
|
154
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"Bool",path)
|
|
155
|
-
elif(type(childValue)==str):
|
|
156
|
-
if((confChildVal is None or confChildVal=="Str")):
|
|
157
|
-
return
|
|
158
|
-
else:
|
|
159
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),type="Str",path=path)
|
|
160
|
-
elif(type(childValue)==int):
|
|
161
|
-
if((confChildVal is None) or confChildVal=="Int"):
|
|
162
|
-
return
|
|
163
|
-
else:
|
|
164
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"Int",path)
|
|
165
|
-
elif(type(childValue)==float):
|
|
166
|
-
if((confChildVal is None) or confChildVal=="Float"):
|
|
167
|
-
return
|
|
168
|
-
else:
|
|
169
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"Float",path)
|
|
170
|
-
elif(type(childValue)==list):
|
|
171
|
-
if((confChildVal is None) or confChildVal=="List"):
|
|
172
|
-
for i in range(len(childValue)):
|
|
173
|
-
newPath=path+[i]
|
|
174
|
-
self._visitQueue.append((i,childValue[i]))
|
|
175
|
-
self._pathQueue.append(newPath)
|
|
176
|
-
return
|
|
177
|
-
else:
|
|
178
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"List",path)
|
|
179
|
-
elif(type(childValue)==dict):
|
|
180
|
-
if(confChildVal is None):
|
|
181
|
-
for key,childValue in childValue.items():
|
|
182
|
-
newPath=path+[key]
|
|
183
|
-
self._visitQueue.append((key,childValue))
|
|
184
|
-
self._pathQueue.append(newPath)
|
|
185
|
-
return
|
|
186
|
-
elif(confChildVal=="FreeDict"):
|
|
187
|
-
for key,childValue in childValue.items():
|
|
188
|
-
newPath=path+[key]
|
|
189
|
-
self._visitQueue.append((key,childValue))
|
|
190
|
-
self._pathQueue.append(newPath)
|
|
191
|
-
if(key[0]=="@"):
|
|
192
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"FreeDict",path)
|
|
193
|
-
return
|
|
194
|
-
elif(confChildVal=="AnnoDict"):
|
|
195
|
-
for key,childValue in childValue.items():
|
|
196
|
-
newPath=path+[key]
|
|
197
|
-
self._visitQueue.append((key,childValue))
|
|
198
|
-
self._pathQueue.append(newPath)
|
|
199
|
-
confParent=self._configDict[key].get("!ParentKey")
|
|
200
|
-
if(key[0]!="@"):
|
|
201
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"AnnoDict",path)
|
|
202
|
-
if(confParent is None):
|
|
203
|
-
pass
|
|
204
|
-
elif(parentKey not in confParent):
|
|
205
|
-
raise AnnotationYamlTypeError(str(self._curAnoy),"AnnoDict",path)
|
|
206
|
-
return
|
|
207
|
-
else:
|
|
208
|
-
raise AnnotationYamlError(f" invalid value is found at:\n {str(self._curAnoy)}: `{path}`.")
|
|
209
|
-
|
|
210
|
-
if(__name__=="__main__"):
|
|
211
|
-
configPath=r"C:\Users\tomot\Backup\sourcecode\python\projects\annotation_yaml\tests\unit\case01\config01.yaml"
|
|
212
|
-
anoyPath=r"C:\Users\tomot\Backup\sourcecode\python\projects\annotation_yaml\tests\unit\case01\int_false.yaml"
|
|
213
|
-
with open(configPath,mode="r",encoding="utf-8") as f:
|
|
214
|
-
configDict=yaml.safe_load(f)
|
|
215
|
-
with open(anoyPath,mode="r",encoding="utf-8") as f:
|
|
216
|
-
anoyDict=yaml.safe_load(f)
|
|
217
|
-
tree01=DictTraversal(configDict)
|
|
218
|
-
tree01.dictBFS(anoyDict)
|
|
219
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|