Skip to content

Commit f7875e6

Browse files
Ghesselinkaothms
authored andcommitted
Align header with IfcOpenShell structure
1 parent 8a5349f commit f7875e6

File tree

3 files changed

+157
-1
lines changed

3 files changed

+157
-1
lines changed

__init__.py

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,63 @@ class ValidationError(Exception):
1616
pass
1717

1818

19+
HEADER_FIELDS = {
20+
"file_description": [
21+
"description",
22+
"implementation_level",
23+
],
24+
"file_name": [
25+
"name",
26+
"time_stamp",
27+
"author",
28+
"organization",
29+
"preprocessor_version",
30+
"originating_system",
31+
"authorization",
32+
],
33+
"file_schema": [
34+
"schema_identifiers",
35+
],
36+
}
37+
38+
class HeaderWrapper:
39+
def __init__(self, field_names, values):
40+
self._fields = field_names
41+
self._values = values
42+
for k, v in zip(field_names, values):
43+
setattr(self, k, v)
44+
45+
def __getitem__(self, index):
46+
"""
47+
Allows for the object to be subscriptable, avoiding conflicts with the validation service. Can be removed after service is fully compatible.
48+
e.g.
49+
>>> f.header.file_name[0]
50+
'Header example2.ifc'
51+
>>> f.header.file_name.name
52+
'Header example2.ifc'
53+
"""
54+
return self._values[index]
55+
56+
def __len__(self):
57+
return len(self._values)
58+
59+
def __iter__(self):
60+
return iter(self._values)
61+
62+
def __repr__(self):
63+
"""
64+
Representing custom header object when debugging, e.g.
65+
>>> f.header.file_name
66+
<HeaderWrapper name='Header example2.ifc', time_stamp='2022-09-16T10:35:07',
67+
author=('Evandro Alfieri',), organization=('buildingSMART Int.',),
68+
preprocessor_version='IFC Motor 1.0', originating_system='Company - Application - 26.0.0.0',
69+
authorization='none'>
70+
"""
71+
return f"<{self.__class__.__name__} " + ", ".join(
72+
f"{k}={repr(getattr(self, k))}" for k in self._fields
73+
) + ">"
74+
75+
1976
class SyntaxError(ValidationError):
2077
def __init__(self, filecontent, exception):
2178
self.filecontent = filecontent
@@ -433,9 +490,26 @@ def schema_version(self) -> tuple[int, int, int, int]:
433490
version.append(int(number.group(1)) if number else 0)
434491
return tuple(version)
435492

493+
# @property
494+
# def header(self):
495+
# mapping = {
496+
# "file_description": file_description,
497+
# "file_name": file_name,
498+
# "file_schema": file_schema,
499+
# }
500+
501+
# return types.SimpleNamespace(**{
502+
# k.lower(): mapping[k.lower()](v)
503+
# for k, v in self.header_.items()
504+
# if k.lower() in mapping
505+
# })
436506
@property
437507
def header(self):
438-
return types.SimpleNamespace(**{k.lower(): v for k, v in self.header_.items()})
508+
return types.SimpleNamespace(**{
509+
name: HeaderWrapper(fields, self.header_[name.upper()])
510+
for name, fields in HEADER_FIELDS.items()
511+
if name.upper() in self.header_
512+
})
439513

440514
def __getitem__(self, key: numbers.Integral) -> entity_instance:
441515
return self.by_id(key)
@@ -472,3 +546,22 @@ def by_type(self, type: str) -> list[entity_instance]:
472546

473547
def open(fn) -> file:
474548
return file(parse(filename=fn, with_tree=True, with_header=True))
549+
550+
class file_description:
551+
def __init__(self, values):
552+
self.description = values[0]
553+
self.implementation_level = values[1]
554+
555+
class file_name:
556+
def __init__(self, values):
557+
self.name = values[0]
558+
self.time_stamp = values[1]
559+
self.author = values[2]
560+
self.organization = values[3]
561+
self.preprocessor_version = values[4]
562+
self.originating_system = values[5]
563+
self.authorization = values[6]
564+
565+
class file_schema:
566+
def __init__(self, values):
567+
self.schema_identifiers = values[0]

fixtures/passing_header.ifc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
ISO-10303-21;
2+
HEADER;
3+
FILE_DESCRIPTION(('ViewDefinition [Alignment-basedView]'),'2;1');
4+
FILE_NAME('Header example2.ifc', '2022-09-16T10:35:07', ('Evandro Alfieri'), ('buildingSMART Int.'), 'IFC Motor 1.0', 'Company - Application - 26.0.0.0', 'none');
5+
FILE_SCHEMA(('IFC4X3_ADD2'));
6+
ENDSEC;
7+
DATA;
8+
#1=IFCPERSON($,$,'',$,$,$,$,$);
9+
#2=IFCORGANIZATION($,'',$,$,$);
10+
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
11+
#4=IFCAPPLICATION(#2,'v0.7.0-6c9e130ca','IfcOpenShell-v0.7.0-6c9e130ca','');
12+
#5=IFCOWNERHISTORY(#3,#4,$,.NOTDEFINED.,$,#3,#4,1700419055);
13+
#6=IFCDIRECTION((1.,0.,0.));
14+
#7=IFCDIRECTION((0.,0.,1.));
15+
#8=IFCCARTESIANPOINT((0.,0.,0.));
16+
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
17+
#10=IFCDIRECTION((0.,1.));
18+
#11=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#10);
19+
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
20+
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
21+
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
22+
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
23+
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
24+
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
25+
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
26+
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
27+
#20=IFCPROJECT('0iDmeiiLP3AOllitM2Favn',#5,'',$,$,$,$,(#11),#19);
28+
#21=IFCSITE('3rg2jGkIH10RFhrQsGZKRk',#5,$,$,$,$,$,$,$,$,$,$,$,$);
29+
ENDSEC;
30+
END-ISO-10303-21;

test_parser.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,36 @@ def test_parse_features():
3232
assert f[1][0] is None
3333
assert f.header.file_description[0][0] == 'ViewDefinition [CoordinationView]'
3434
assert f.by_type('ifcapplication')[1][2] == "Nested ' quotes"
35+
36+
37+
def test_parse_valid_header():
38+
f = open('fixtures/passing_header.ifc')
39+
40+
expected_description = {
41+
"description": ('ViewDefinition [Alignment-basedView]',),
42+
"implementation_level": '2;1',
43+
}
44+
45+
expected_name = {
46+
"name": 'Header example2.ifc',
47+
"time_stamp": '2022-09-16T10:35:07',
48+
"author": ('Evandro Alfieri',),
49+
"organization": ('buildingSMART Int.',),
50+
"preprocessor_version": 'IFC Motor 1.0',
51+
"originating_system": 'Company - Application - 26.0.0.0',
52+
"authorization": 'none',
53+
}
54+
55+
expected_schema = {
56+
"schema_identifiers": ('IFC4X3_ADD2',),
57+
}
58+
59+
for key, val in expected_description.items():
60+
assert getattr(f.header.file_description, key) == val, f"{key} mismatch"
61+
62+
for key, val in expected_name.items():
63+
assert getattr(f.header.file_name, key) == val, f"{key} mismatch"
64+
65+
for key, val in expected_schema.items():
66+
assert getattr(f.header.file_schema, key) == val, f"{key} mismatch"
67+

0 commit comments

Comments
 (0)