From c549ed52c56620ffd2fd1d07adab924c576ea22b Mon Sep 17 00:00:00 2001 From: Geert Hesselink Date: Mon, 5 May 2025 19:18:16 +0100 Subject: [PATCH 1/3] check for invalid header entity --- __init__.py | 27 +++++++++++----------- fixtures/extended_mvd.ifc | 29 ++++++++++++++++++++++++ fixtures/fail_invalid_header_entity.ifc | 30 +++++++++++++++++++++++++ test_parser.py | 2 ++ 4 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 fixtures/extended_mvd.ifc create mode 100644 fixtures/fail_invalid_header_entity.ifc diff --git a/__init__.py b/__init__.py index 01671a4..133dca6 100644 --- a/__init__.py +++ b/__init__.py @@ -10,7 +10,10 @@ from lark import Lark, Transformer, Tree, Token from lark.exceptions import UnexpectedToken, UnexpectedCharacters -from .mvd_info import MvdInfo, LARK_AVAILABLE +try: + from .mvd_info import MvdInfo, LARK_AVAILABLE +except ImportError: # in case of running module locally (e.g. test_parser.py) + from mvd_info import MvdInfo, LARK_AVAILABLE class ValidationError(Exception): pass @@ -87,8 +90,10 @@ def build(): subsuper_record : "(" simple_record_list ")" simple_record_list:simple_record simple_record* simple_record: keyword "("parameter_list?")" -header_entity :keyword "(" parameter_list ")" ";" -header_entity_list: header_entity header_entity* +header_entity_list: file_description file_name file_schema +file_description: "FILE_DESCRIPTION" "(" parameter_list ")" ";" +file_name: "FILE_NAME" "(" parameter_list ")" ";" +file_schema: "FILE_SCHEMA" "(" parameter_list ")" ";" id: /#[0-9]+/ keyword: /[A-Z][0-9A-Z_]*/ parameter: untyped_parameter|typed_parameter|omitted_parameter @@ -285,17 +290,18 @@ def traverse(fn, x): attributes, (min(lines), max(lines)), ) + +def make_header_ent(ast): + rule = ast.data + params = T(visit_tokens=True).transform(ast.children[0]) + return rule.upper(), params + def process_tree(filecontent, file_tree, with_progress, with_header=False): ents = defaultdict(list) header, data = file_tree.children - def make_header_ent(ast): - kw, param_list = ast.children - kw = kw.children[0].value - return kw, T(visit_tokens=True).transform(param_list) - if with_header: header = dict(map(make_header_ent, header.children[0].children)) @@ -366,11 +372,6 @@ def replace_fn(match): header_tree = ast.children[0] # HEADER section - def make_header_ent(ast): - kw, param_list = ast.children - kw = kw.children[0].value - return kw, T(visit_tokens=True).transform(param_list) - header = dict(map(make_header_ent, header_tree.children[0].children)) return header diff --git a/fixtures/extended_mvd.ifc b/fixtures/extended_mvd.ifc new file mode 100644 index 0000000..1486c09 --- /dev/null +++ b/fixtures/extended_mvd.ifc @@ -0,0 +1,29 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION(('ViewDefinition [ReferenceView_V1.2]', 'ViewDefinition [QuantityTakeOffAddOnView]', 'Option [ExcludedObjects: Stair, Ramp, Space; SplitLevel: On]', 'ExchangeRequirement [CustomRequirement: Value1, Value2]', 'Remark [SomeKey: SomeValue; AnotherKey: AnotherValue]', 'Comment [This is a free text comment, or a comma-separated list of items]'),'2;1'); +FILE_NAME('','2022-05-04T08:08:30',(''),(''),'IfcOpenShell-0.7.0','IfcOpenShell-0.7.0',''); +FILE_SCHEMA(('IFC4')); +ENDSEC; +DATA; +#1=IFCPERSON($,$,'',,$,$,$,$); +#2=IFCORGANIZATION($,'',$,$,$); +#3=IFCPERSONANDORGANIZATION(#1,#2,$); +#4=IFCAPPLICATION(#2,'0.7.0','IfcOpenShell-0.7.0',''); +#5=IFCOWNERHISTORY(#3,#4,$,.ADDED.,$,#3,#4,1651651710); +#6=IFCDIRECTION((1.,0.,0.)); +#7=IFCDIRECTION((0.,0.,1.)); +#8=IFCCARTESIANPOINT((0.,0.,0.)); +#9=IFCAXIS2PLACEMENT3D(#8,#7,#6); +#10=IFCDIRECTION((0.,1.,0.)); +#11=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#10); +#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0); +#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.); +#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.); +#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.); +#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.); +#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16); +#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17); +#19=IFCUNITASSIGNMENT((#13,#14,#15,#18)); +#20=IFCPROJECT('2AyG2X0sb16Bjd4gQc07yZ',#5,'',$,$,$,$,(#11),#19); +ENDSEC; +END-ISO-10303-21; diff --git a/fixtures/fail_invalid_header_entity.ifc b/fixtures/fail_invalid_header_entity.ifc new file mode 100644 index 0000000..4f13ee8 --- /dev/null +++ b/fixtures/fail_invalid_header_entity.ifc @@ -0,0 +1,30 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION(('ViewDefinition [Alignment-basedView]'),'2;1'); +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'); +FILE_SCHEMA(('IFC4X3_ADD2')); +ENDSEC; +DATA; +#1=IFCPERSON($,$,'',$,$,$,$,$); +#2=IFCORGANIZATION($,'',$,$,$); +#3=IFCPERSONANDORGANIZATION(#1,#2,$); +#4=IFCAPPLICATION(#2,'v0.7.0-6c9e130ca','IfcOpenShell-v0.7.0-6c9e130ca',''); +#5=IFCOWNERHISTORY(#3,#4,$,.NOTDEFINED.,$,#3,#4,1700419055); +#6=IFCDIRECTION((1.,0.,0.)); +#7=IFCDIRECTION((0.,0.,1.)); +#8=IFCCARTESIANPOINT((0.,0.,0.)); +#9=IFCAXIS2PLACEMENT3D(#8,#7,#6); +#10=IFCDIRECTION((0.,1.)); +#11=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#10); +#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0); +#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.); +#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.); +#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.); +#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.); +#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16); +#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17); +#19=IFCUNITASSIGNMENT((#13,#14,#15,#18)); +#20=IFCPROJECT('0iDmeiiLP3AOllitM2Favn',#5,'',$,$,$,$,(#11),#19); +#21=IFCSITE('3rg2jGkIH10RFhrQsGZKRk',#5,$,$,$,$,$,$,$,$,$,$,$,$); +ENDSEC; +END-ISO-10303-21; diff --git a/test_parser.py b/test_parser.py index 635e308..fb2565a 100644 --- a/test_parser.py +++ b/test_parser.py @@ -104,3 +104,5 @@ def test_file_mvd_attr(): assert 'Ramp' in f.mvd.options['ExcludedObjects'] assert f.mvd.Remark['SomeKey'] == 'SomeValue' assert len(f.mvd.comments) == 2 + assert all(v in vars(f.header).keys() for v in ['file_description', 'file_name', 'file_schema']) + assert len(f.header.file_name) == 7 \ No newline at end of file From 4d24ad867b07f87feb443ab9e2cd56b630c1fe85 Mon Sep 17 00:00:00 2001 From: Geert Hesselink Date: Mon, 5 May 2025 19:23:10 +0100 Subject: [PATCH 2/3] add file_info to invalid testfile --- fixtures/fail_invalid_header_entity.ifc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fixtures/fail_invalid_header_entity.ifc b/fixtures/fail_invalid_header_entity.ifc index 4f13ee8..7f2dcb2 100644 --- a/fixtures/fail_invalid_header_entity.ifc +++ b/fixtures/fail_invalid_header_entity.ifc @@ -3,6 +3,22 @@ HEADER; FILE_DESCRIPTION(('ViewDefinition [Alignment-basedView]'),'2;1'); 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'); FILE_SCHEMA(('IFC4X3_ADD2')); +FILE_INFO( +'Report Date', '2025-04-21 18:16:37', +'IFC Schema', 'IFC2X3', +'MVD(s)', 'None', +'File Name in Header', 'generated (2).ifc', +'File Name', 'generated (2).ifc', +'File Size', '0.41 kB', +'File Date', '2025-04-21 18:16:37', +'Originating System', 'PHP Script', +'Preprocessor Version', '1.0.0', +'Company Name', 'Your Company Name', +'Application Name', 'IFC Generator PHP Script', +'Application Version', '1.0.0', +'Author', 'Your Name', +'Organization', 'Your Company Name' +); ENDSEC; DATA; #1=IFCPERSON($,$,'',$,$,$,$,$); From 3cc3615c8f876f7210e042d3f98654da6fc2a378 Mon Sep 17 00:00:00 2001 From: Geert Hesselink Date: Mon, 5 May 2025 19:26:40 +0100 Subject: [PATCH 3/3] fix testfile error --- fixtures/extended_mvd.ifc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fixtures/extended_mvd.ifc b/fixtures/extended_mvd.ifc index 1486c09..47d8019 100644 --- a/fixtures/extended_mvd.ifc +++ b/fixtures/extended_mvd.ifc @@ -5,7 +5,7 @@ FILE_NAME('','2022-05-04T08:08:30',(''),(''),'IfcOpenShell-0.7.0','IfcOpenShell- FILE_SCHEMA(('IFC4')); ENDSEC; DATA; -#1=IFCPERSON($,$,'',,$,$,$,$); +#1=IFCPERSON($,$,'',$,$,$,$); #2=IFCORGANIZATION($,'',$,$,$); #3=IFCPERSONANDORGANIZATION(#1,#2,$); #4=IFCAPPLICATION(#2,'0.7.0','IfcOpenShell-0.7.0','');