Skip to content

Commit c167abc

Browse files
committed
Merge remote-tracking branch 'github/PoC-validator' into sync_with_github_PoC-Validator_branch
2 parents ef01196 + acfddcb commit c167abc

9 files changed

Lines changed: 210 additions & 17 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#name: Deply to GitHub Container Registry
2+
run-name: Releasing next version 🚀
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
8+
jobs:
9+
publish-docker-image:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout sources
13+
uses: actions/checkout@v2
14+
15+
- name: Login to Docker Hub
16+
uses: docker/login-action@v3
17+
with:
18+
username: ${{ secrets.DOCKERHUB_CONTAINER_PUSH_USERNAME }}
19+
password: ${{ secrets.DOCKERHUB_CONTAINER_PUSH }}
20+
21+
- name: Build the container image
22+
run: |
23+
docker build . --tag esdlmapeditoressim/esdlvalidator:latest --tag esdlmapeditoressim/esdlvalidator:${{ github.ref_name}}
24+
docker push esdlmapeditoressim/esdlvalidator:latest
25+
docker push esdlmapeditoressim/esdlvalidator:${{ github.ref_name}}

README.md

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,153 @@
22

33
Service for validating ESDL files against validation schemas
44

5+
## Usage
6+
7+
To start the service locally run
8+
9+
```bash
10+
docker-compose up
11+
```
12+
13+
Then go to `localhost:3011` to see the available endpoints.
14+
First upload the validation schema `testdata/schemas/schema_Poc.json` using `POST /schema`.
15+
`GET /schema` returns a list of the available schema id's, names and descriptions.
16+
`GET /schema/{schema_id_or_name}` returns a schema by id.
17+
18+
To run the validation use `POST /validationToMessages/` with the esdl as string (for instance
19+
`testdata/esdls/Single_pipes.esdl`) and the schema id.
20+
This should return a response with errors and warnings:
21+
22+
```json
23+
[
24+
{
25+
"assetID": "6f45c6f8-e8e2-4378-a910-45140337b9dd",
26+
"messages": [
27+
{
28+
"message": "Only one of supplyTemperature or returnTemperature must be defined for asset 6f45c6f8-e8e2-4378-a910-45140337b9dd (HotSide)",
29+
"severity": "ERROR"
30+
},
31+
{
32+
"message": "6f45c6f8-e8e2-4378-a910-45140337b9dd (HotSide) does not have a parallel return asset with the name (HotSide_ret)",
33+
"severity": "ERROR"
34+
}
35+
]
36+
},
37+
{
38+
"assetID": "e11a2daa-2e56-4635-afb3-1e23c6d08c33",
39+
"messages": [
40+
{
41+
"message": "e11a2daa-2e56-4635-afb3-1e23c6d08c33's OutPort is unconnected",
42+
"severity": "WARNING"
43+
}
44+
]
45+
},
46+
{
47+
"assetID": "c407387a-ebfd-41b7-af1b-9cae7aec842b",
48+
"messages": [
49+
{
50+
"message": "c407387a-ebfd-41b7-af1b-9cae7aec842b's InPort is unconnected",
51+
"severity": "WARNING"
52+
}
53+
]
54+
},
55+
{
56+
"assetID": "e677bac5-48e0-4ac0-b2a9-5a329b00b0d6",
57+
"messages": [
58+
{
59+
"message": "e677bac5-48e0-4ac0-b2a9-5a329b00b0d6's OutPort is unconnected",
60+
"severity": "WARNING"
61+
}
62+
]
63+
},
64+
{
65+
"assetID": "737494af-8ac4-4ebe-a11a-e89f6f2c415a",
66+
"messages": [
67+
{
68+
"message": "737494af-8ac4-4ebe-a11a-e89f6f2c415a's InPort is unconnected",
69+
"severity": "WARNING"
70+
},
71+
{
72+
"message": "737494af-8ac4-4ebe-a11a-e89f6f2c415a (Pipe_7374) does not have a parallel return asset with the name (Pipe_7374_ret)",
73+
"severity": "ERROR"
74+
}
75+
]
76+
},
77+
{
78+
"assetID": "363103d6-a32e-40a6-b3a9-ae376c944f6b",
79+
"messages": [
80+
{
81+
"message": "363103d6-a32e-40a6-b3a9-ae376c944f6b (Pipe_3631) does not have a parallel return asset with the name (Pipe_3631_ret)",
82+
"severity": "ERROR"
83+
}
84+
]
85+
},
86+
{
87+
"assetID": "83582c37-b692-4432-8430-4e3407ed4c08",
88+
"messages": [
89+
{
90+
"message": "83582c37-b692-4432-8430-4e3407ed4c08 (Pipe_8358) does not have a parallel return asset with the name (Pipe_8358_ret)",
91+
"severity": "ERROR"
92+
}
93+
]
94+
},
95+
{
96+
"assetID": "a5142229-9331-4313-a52b-70c3da15f4a9",
97+
"messages": [
98+
{
99+
"message": "a5142229-9331-4313-a52b-70c3da15f4a9 (Pipe_a514) does not have a parallel return asset with the name (Pipe_a514_ret)",
100+
"severity": "ERROR"
101+
}
102+
]
103+
},
104+
{
105+
"assetID": "0fc640c8-7f6b-45ae-8e40-2966c1377761",
106+
"messages": [
107+
{
108+
"message": "0fc640c8-7f6b-45ae-8e40-2966c1377761 (Pipe_0fc6) does not have a parallel return asset with the name (Pipe_0fc6_ret)",
109+
"severity": "ERROR"
110+
}
111+
]
112+
},
113+
{
114+
"assetID": "a0b0a95a-76c6-4afa-a319-f41297c5be6e",
115+
"messages": [
116+
{
117+
"message": "a0b0a95a-76c6-4afa-a319-f41297c5be6e (Pipe_a0b0) does not have a parallel return asset with the name (Pipe_a0b0_ret)",
118+
"severity": "ERROR"
119+
}
120+
]
121+
},
122+
{
123+
"assetID": "f6779198-7d2a-456b-997b-58b9a02cdb2d",
124+
"messages": [
125+
{
126+
"message": "f6779198-7d2a-456b-997b-58b9a02cdb2d (Joint_f677) does not have a parallel return asset with the name (Joint_f677_ret)",
127+
"severity": "ERROR"
128+
}
129+
]
130+
},
131+
{
132+
"assetID": "7aae2f5f-c3d4-4041-9577-d0a46124df09",
133+
"messages": [
134+
{
135+
"message": "7aae2f5f-c3d4-4041-9577-d0a46124df09 (Joint_7aae) does not have a parallel return asset with the name (Joint_7aae_ret)",
136+
"severity": "ERROR"
137+
}
138+
]
139+
},
140+
{
141+
"assetID": "f5214b94-d097-4fa9-a86a-110a1386f884",
142+
"messages": [
143+
{
144+
"message": "f5214b94-d097-4fa9-a86a-110a1386f884 (Joint_f521) does not have a parallel return asset with the name (Joint_f521_ret)",
145+
"severity": "ERROR"
146+
}
147+
]
148+
}
149+
]
150+
```
151+
5152
## Status
6153

7154
**work in progress**

docker-compose.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ networks:
33

44
services:
55
esdl_validator:
6-
build: ./
6+
# build: .
7+
image: esdlmapeditoressim/esdlvalidator:0.0.7
78
ports:
89
- "3011:5000"
910
environment:
@@ -13,13 +14,21 @@ services:
1314
- validator-storage:/storage
1415
networks:
1516
- esdl_val_net
17+
depends_on:
18+
mongo:
19+
condition: service_healthy
1620

1721
mongo:
18-
image: mongo:latest
22+
image: mvertes/alpine-mongo
1923
ports:
2024
- "27017:27017"
2125
volumes:
2226
- mongo-storage:/data/db
27+
healthcheck:
28+
test: echo 'db.runCommand("ping").ok' | mongo mongo:27017/test --quiet
29+
interval: 10s
30+
timeout: 10s
31+
retries: 5
2332
networks:
2433
- esdl_val_net
2534

esdlvalidator/api/setup.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ def setup_logger(logLevel: str):
3030
werkzeug.setLevel(logLevel)
3131
waitress.setLevel(logLevel)
3232

33-
logging.basicConfig(level=logLevel, format="%(asctime)s | %(name)s | %(levelname)s | %(message)s", datefmt="%Y-%m-%dT%H:%M:%S%z")
33+
logging.basicConfig(
34+
level=logLevel,
35+
format="%(asctime)s | %(name)s | %(levelname)s | %(message)s",
36+
datefmt="%Y-%m-%dT%H:%M:%S%z"
37+
)
3438

3539

3640
class AppConfig:
@@ -46,6 +50,7 @@ def __init__(self):
4650

4751
# Setup flask/restx, namespaces
4852
self.apiBlueprint = Blueprint("api", __name__)
49-
self.api = Api(self.apiBlueprint, version=self.settings.version, title=self.settings.title, description=self.settings.description)
53+
self.api = Api(self.apiBlueprint, version=self.settings.version, title=self.settings.title,
54+
description=self.settings.description)
5055
self.ns_validation = self.api.namespace("validation", "ESDL validation endpoint")
5156
self.ns_schema = self.api.namespace("schema", "Validation schema endpoint")

esdlvalidator/validation/functions/check_child_attribute_not_null.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,11 @@ def check_units(self, prop, qau):
164164
correct = 0
165165
msg = {"offending_asset": self.value.id}
166166
for i in range(0, len(self.args["unit_type"])):
167-
unittype = getattr(qau, self.args["unit_type"][i])
168-
unit = self.args["unit"][i]
169-
if str(unittype.name).lower() == str(unit).lower():
170-
correct += 1
167+
if hasattr(qau, self.args["unit_type"][i]):
168+
unittype = getattr(qau, self.args["unit_type"][i])
169+
unit = self.args["unit"][i]
170+
if str(unittype.name).lower() == str(unit).lower():
171+
correct += 1
171172
if correct != len(self.args["unit_type"]):
172173
result = self.__create_message("{0} should contain {1} of type {2}".format(prop, self.args["unit_type"],
173174
self.args["unit"]), self.value)

esdlvalidator/validation/functions/check_not_null.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from esdl import esdl
2+
13
from esdlvalidator.validation.functions import utils
24
from esdlvalidator.validation.functions.function import FunctionFactory, FunctionCheck, FunctionDefinition, ArgDefinition, FunctionType, CheckResult
35

@@ -27,7 +29,10 @@ def execute(self):
2729
# Some esdl entity values have a default of undefined or none when not set
2830
include.extend(["undefined", "none"])
2931
value = self.value
30-
msg = {"offending_asset": self.value.id}
32+
if isinstance(value, esdl.Port):
33+
msg = {"offending_asset": self.value.eContainer().id}
34+
else:
35+
msg = {"offending_asset": self.value.id}
3136

3237
if hasProp:
3338
if not utils.has_attribute(value, prop):
@@ -48,15 +53,15 @@ def execute(self):
4853
else:
4954
return CheckResult(False, result)
5055

51-
return self.check_includes(include, prop, value, self.value)
56+
return self.check_includes(include, prop, value, self.value, msg)
5257

53-
def check_includes(self, include, prop, value, originalValue):
54-
msg = {"offending_asset": self.value.id}
58+
def check_includes(self, include, prop, value, originalValue, msg):
59+
# msg = {"offending_asset": self.value.id}
5560
for includeValue in include:
5661
if isinstance(value, list):
5762
ret = []
5863
for v in value:
59-
ret.append(self.check_includes(include, prop, v, originalValue))
64+
ret.append(self.check_includes(include, prop, v, originalValue, msg))
6065
for r in ret:
6166
if not r.ok:
6267
return r

esdlvalidator/validation/functions/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
def has_attribute(obj, name: str) -> bool:
77
# give a default "nothing_found" since None can be the actual returned value
88
result = get_attribute(obj, name, "nothing_found")
9-
return False if result is "nothing_found" else True
9+
return False if result == "nothing_found" else True
1010

1111

1212
def get_attribute(obj, name: str, default=None):
@@ -15,7 +15,8 @@ def get_attribute(obj, name: str, default=None):
1515
Args:
1616
obj: List, class or dictionary to get a property value from
1717
name (str): The property to get
18-
default (Object): Optional default value that will return when property not found, defaults to None
18+
default (Object): Optional default value that will return when property not found,
19+
defaults to None
1920
2021
Returns:
2122
property value: The property value found for given name, default if not found

esdlvalidator/validation/tests/test_validator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def test_validate_poc_scheme(self):
108108
elif validation.name == "costinformation_exists":
109109
self.assertEqual(len(validation.warnings), 8)
110110
elif validation.name == "investmentcost_per_power_undefined":
111-
self.assertEqual(len(validation.errors), 1)
111+
self.assertEqual(len(validation.errors), 2)
112112
elif validation.name == "fixed_opex_undefined":
113113
self.assertEqual(len(validation.errors), 1)
114114
elif validation.name == "var_opex_undefined":

testdata/esdls/PoC_validator with return network.esdl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<profileQuantityAndUnit xsi:type="esdl:QuantityAndUnitType" perUnit="WATT" unit="EURO" id="dbe7fea2-c345-4aab-9df0-3afc27ff1751" description="Cost in EUR/kW" perMultiplier="KILO" physicalQuantity="COST"/>
2222
</installationCosts>
2323
<investmentCosts xsi:type="esdl:SingleValue" value="10.0" id="c162cc99-7c02-4866-8813-b68e72cc1d34">
24-
<profileQuantityAndUnit xsi:type="esdl:QuantityAndUnitType" perUnit="WATT" unit="EURO" id="aeeb19dc-815c-4801-9681-9f6058bbbaf1" description="Cost in EUR/kW" perMultiplier="KILO" physicalQuantity="COST"/>
24+
<profileQuantityAndUnit xsi:type="esdl:QuantityAndUnitType" unit="EURO" id="aeeb19dc-815c-4801-9681-9f6058bbbaf1" description="Cost in EUR/kW" perMultiplier="KILO" physicalQuantity="COST"/>
2525
</investmentCosts>
2626
</costInformation>
2727
</asset>

0 commit comments

Comments
 (0)