mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-22 20:02:30 +00:00
Run black on utils
This commit is contained in:
@@ -18,6 +18,7 @@ GNU Lesser General Public License for more details.
|
|||||||
You should have received a copy of the GNU Lesser General Public License
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
along with BCF. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import zipfile
|
import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Copyright (c) 2017-2020 Anthon van der Neut, Ruamel bvba
|
|||||||
|
|
||||||
original idea from https://stackoverflow.com/a/19722365/1307905
|
original idea from https://stackoverflow.com/a/19722365/1307905
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import zipfile
|
import zipfile
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from os import PathLike
|
from os import PathLike
|
||||||
@@ -13,8 +14,7 @@ from typing import Any, Optional, Protocol
|
|||||||
|
|
||||||
|
|
||||||
class ZipFileInterface(Protocol):
|
class ZipFileInterface(Protocol):
|
||||||
def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None:
|
def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None: ...
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
class InMemoryZipFile:
|
class InMemoryZipFile:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""BCF XML V2 handler."""
|
"""BCF XML V2 handler."""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
import warnings
|
import warnings
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class BimSnippet:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "isExternal",
|
"name": "isExternal",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ class HeaderFile:
|
|||||||
"name": "Filename",
|
"name": "Filename",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
date: Optional[XmlDateTime] = field(
|
date: Optional[XmlDateTime] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -72,7 +72,7 @@ class HeaderFile:
|
|||||||
"name": "Date",
|
"name": "Date",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
reference: Optional[str] = field(
|
reference: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -80,7 +80,7 @@ class HeaderFile:
|
|||||||
"name": "Reference",
|
"name": "Reference",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
ifc_project: Optional[str] = field(
|
ifc_project: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -89,7 +89,7 @@ class HeaderFile:
|
|||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"length": 22,
|
"length": 22,
|
||||||
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
ifc_spatial_structure_element: Optional[str] = field(
|
ifc_spatial_structure_element: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -98,14 +98,14 @@ class HeaderFile:
|
|||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"length": 22,
|
"length": 22,
|
||||||
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
is_external: bool = field(
|
is_external: bool = field(
|
||||||
default=True,
|
default=True,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "isExternal",
|
"name": "isExternal",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ class TopicDocumentReference:
|
|||||||
"name": "ReferencedDocument",
|
"name": "ReferencedDocument",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
description: Optional[str] = field(
|
description: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -128,7 +128,7 @@ class TopicDocumentReference:
|
|||||||
"name": "Description",
|
"name": "Description",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: Optional[str] = field(
|
guid: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -136,14 +136,14 @@ class TopicDocumentReference:
|
|||||||
"name": "Guid",
|
"name": "Guid",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
"pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
is_external: bool = field(
|
is_external: bool = field(
|
||||||
default=False,
|
default=False,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "isExternal",
|
"name": "isExternal",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ class ViewPoint:
|
|||||||
"name": "Viewpoint",
|
"name": "Viewpoint",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
snapshot: Optional[str] = field(
|
snapshot: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -178,7 +178,7 @@ class ViewPoint:
|
|||||||
"name": "Snapshot",
|
"name": "Snapshot",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
index: Optional[int] = field(
|
index: Optional[int] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -186,7 +186,7 @@ class ViewPoint:
|
|||||||
"name": "Index",
|
"name": "Index",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -230,7 +230,7 @@ class Comment:
|
|||||||
"name": "Viewpoint",
|
"name": "Viewpoint",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
modified_date: Optional[XmlDateTime] = field(
|
modified_date: Optional[XmlDateTime] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -238,7 +238,7 @@ class Comment:
|
|||||||
"name": "ModifiedDate",
|
"name": "ModifiedDate",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
modified_author: Optional[str] = field(
|
modified_author: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -246,7 +246,7 @@ class Comment:
|
|||||||
"name": "ModifiedAuthor",
|
"name": "ModifiedAuthor",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -267,7 +267,7 @@ class Header:
|
|||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_occurs": 1,
|
"min_occurs": 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ class Topic:
|
|||||||
"name": "ReferenceLink",
|
"name": "ReferenceLink",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
title: str = field(
|
title: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -295,7 +295,7 @@ class Topic:
|
|||||||
"name": "Priority",
|
"name": "Priority",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
index: Optional[int] = field(
|
index: Optional[int] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -303,7 +303,7 @@ class Topic:
|
|||||||
"name": "Index",
|
"name": "Index",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
labels: List[str] = field(
|
labels: List[str] = field(
|
||||||
default_factory=list,
|
default_factory=list,
|
||||||
@@ -311,7 +311,7 @@ class Topic:
|
|||||||
"name": "Labels",
|
"name": "Labels",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
creation_date: XmlDateTime = field(
|
creation_date: XmlDateTime = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -335,7 +335,7 @@ class Topic:
|
|||||||
"name": "ModifiedDate",
|
"name": "ModifiedDate",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
modified_author: Optional[str] = field(
|
modified_author: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -343,7 +343,7 @@ class Topic:
|
|||||||
"name": "ModifiedAuthor",
|
"name": "ModifiedAuthor",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
due_date: Optional[XmlDateTime] = field(
|
due_date: Optional[XmlDateTime] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -351,7 +351,7 @@ class Topic:
|
|||||||
"name": "DueDate",
|
"name": "DueDate",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
assigned_to: Optional[str] = field(
|
assigned_to: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -359,7 +359,7 @@ class Topic:
|
|||||||
"name": "AssignedTo",
|
"name": "AssignedTo",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
stage: Optional[str] = field(
|
stage: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -367,7 +367,7 @@ class Topic:
|
|||||||
"name": "Stage",
|
"name": "Stage",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
description: Optional[str] = field(
|
description: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -375,7 +375,7 @@ class Topic:
|
|||||||
"name": "Description",
|
"name": "Description",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
bim_snippet: Optional[BimSnippet] = field(
|
bim_snippet: Optional[BimSnippet] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -383,7 +383,7 @@ class Topic:
|
|||||||
"name": "BimSnippet",
|
"name": "BimSnippet",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
document_reference: List[TopicDocumentReference] = field(
|
document_reference: List[TopicDocumentReference] = field(
|
||||||
default_factory=list,
|
default_factory=list,
|
||||||
@@ -391,7 +391,7 @@ class Topic:
|
|||||||
"name": "DocumentReference",
|
"name": "DocumentReference",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
related_topic: List[TopicRelatedTopic] = field(
|
related_topic: List[TopicRelatedTopic] = field(
|
||||||
default_factory=list,
|
default_factory=list,
|
||||||
@@ -399,7 +399,7 @@ class Topic:
|
|||||||
"name": "RelatedTopic",
|
"name": "RelatedTopic",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -414,14 +414,14 @@ class Topic:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "TopicType",
|
"name": "TopicType",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
topic_status: Optional[str] = field(
|
topic_status: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "TopicStatus",
|
"name": "TopicStatus",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -433,7 +433,7 @@ class Markup:
|
|||||||
"name": "Header",
|
"name": "Header",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
topic: Topic = field(
|
topic: Topic = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -449,7 +449,7 @@ class Markup:
|
|||||||
"name": "Comment",
|
"name": "Comment",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
viewpoints: List[ViewPoint] = field(
|
viewpoints: List[ViewPoint] = field(
|
||||||
default_factory=list,
|
default_factory=list,
|
||||||
@@ -457,5 +457,5 @@ class Markup:
|
|||||||
"name": "Viewpoints",
|
"name": "Viewpoints",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Project:
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
project_id: str = field(
|
project_id: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -29,7 +29,7 @@ class ProjectExtension:
|
|||||||
"name": "Project",
|
"name": "Project",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
extension_schema: str = field(
|
extension_schema: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ class Version:
|
|||||||
"name": "DetailedVersion",
|
"name": "DetailedVersion",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
version_id: Optional[str] = field(
|
version_id: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "VersionId",
|
"name": "VersionId",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ class Component:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "OriginatingSystem",
|
"name": "OriginatingSystem",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
authoring_tool_id: Optional[str] = field(
|
authoring_tool_id: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "AuthoringToolId",
|
"name": "AuthoringToolId",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
ifc_guid: Optional[str] = field(
|
ifc_guid: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -31,7 +31,7 @@ class Component:
|
|||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"length": 22,
|
"length": 22,
|
||||||
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
"pattern": r"[0-9,A-Z,a-z,_$]*",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -92,21 +92,21 @@ class ViewSetupHints:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "SpacesVisible",
|
"name": "SpacesVisible",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
space_boundaries_visible: Optional[bool] = field(
|
space_boundaries_visible: Optional[bool] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "SpaceBoundariesVisible",
|
"name": "SpaceBoundariesVisible",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
openings_visible: Optional[bool] = field(
|
openings_visible: Optional[bool] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "OpeningsVisible",
|
"name": "OpeningsVisible",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ class ComponentColoringColor:
|
|||||||
"name": "Component",
|
"name": "Component",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_occurs": 1,
|
"min_occurs": 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
color: Optional[str] = field(
|
color: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -147,7 +147,7 @@ class ComponentColoringColor:
|
|||||||
"name": "Color",
|
"name": "Color",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"pattern": r"[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?",
|
"pattern": r"[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ class ComponentSelection:
|
|||||||
"name": "Component",
|
"name": "Component",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_occurs": 1,
|
"min_occurs": 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ class ComponentVisibilityExceptions:
|
|||||||
"name": "Component",
|
"name": "Component",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_occurs": 1,
|
"min_occurs": 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -205,6 +205,7 @@ class OrthogonalCamera:
|
|||||||
camera_up_vector:
|
camera_up_vector:
|
||||||
view_to_world_scale: view's visible size in meters
|
view_to_world_scale: view's visible size in meters
|
||||||
"""
|
"""
|
||||||
|
|
||||||
camera_view_point: Point = field(
|
camera_view_point: Point = field(
|
||||||
metadata={
|
metadata={
|
||||||
"name": "CameraViewPoint",
|
"name": "CameraViewPoint",
|
||||||
@@ -247,6 +248,7 @@ class PerspectiveCamera:
|
|||||||
release and viewers should be expect values outside this
|
release and viewers should be expect values outside this
|
||||||
range in current implementations.
|
range in current implementations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
camera_view_point: Point = field(
|
camera_view_point: Point = field(
|
||||||
metadata={
|
metadata={
|
||||||
"name": "CameraViewPoint",
|
"name": "CameraViewPoint",
|
||||||
@@ -336,7 +338,7 @@ class ComponentColoring:
|
|||||||
"name": "Color",
|
"name": "Color",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_occurs": 1,
|
"min_occurs": 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -347,14 +349,14 @@ class ComponentVisibility:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Exceptions",
|
"name": "Exceptions",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
default_visibility: Optional[bool] = field(
|
default_visibility: Optional[bool] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "DefaultVisibility",
|
"name": "DefaultVisibility",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -368,7 +370,7 @@ class VisualizationInfoClippingPlanes:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "ClippingPlane",
|
"name": "ClippingPlane",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -383,7 +385,7 @@ class VisualizationInfoLines:
|
|||||||
"name": "Line",
|
"name": "Line",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_occurs": 1,
|
"min_occurs": 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -394,14 +396,14 @@ class Components:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "ViewSetupHints",
|
"name": "ViewSetupHints",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
selection: Optional[ComponentSelection] = field(
|
selection: Optional[ComponentSelection] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Selection",
|
"name": "Selection",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
visibility: ComponentVisibility = field(
|
visibility: ComponentVisibility = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -415,7 +417,7 @@ class Components:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Coloring",
|
"name": "Coloring",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -424,47 +426,48 @@ class VisualizationInfo:
|
|||||||
"""
|
"""
|
||||||
VisualizationInfo documentation.
|
VisualizationInfo documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
components: Optional[Components] = field(
|
components: Optional[Components] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Components",
|
"name": "Components",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
orthogonal_camera: Optional[OrthogonalCamera] = field(
|
orthogonal_camera: Optional[OrthogonalCamera] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "OrthogonalCamera",
|
"name": "OrthogonalCamera",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
perspective_camera: Optional[PerspectiveCamera] = field(
|
perspective_camera: Optional[PerspectiveCamera] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "PerspectiveCamera",
|
"name": "PerspectiveCamera",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
lines: Optional[VisualizationInfoLines] = field(
|
lines: Optional[VisualizationInfoLines] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Lines",
|
"name": "Lines",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
|
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "ClippingPlanes",
|
"name": "ClippingPlanes",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
bitmap: List[VisualizationInfoBitmap] = field(
|
bitmap: List[VisualizationInfoBitmap] = field(
|
||||||
default_factory=list,
|
default_factory=list,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Bitmap",
|
"name": "Bitmap",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""BCF XML V2 Topic handler."""
|
"""BCF XML V2 Topic handler."""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import tempfile
|
import tempfile
|
||||||
import uuid
|
import uuid
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""BCF XML V3 handlers."""
|
"""BCF XML V3 handlers."""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
import warnings
|
import warnings
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""BCF XML V3 Documents handler."""
|
"""BCF XML V3 Documents handler."""
|
||||||
|
|
||||||
import zipfile
|
import zipfile
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class Document:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -45,7 +45,7 @@ class DocumentInfoDocuments:
|
|||||||
"name": "Document",
|
"name": "Document",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -57,5 +57,5 @@ class DocumentInfo:
|
|||||||
"name": "Documents",
|
"name": "Documents",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ExtensionsPriorities:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ class ExtensionsSnippetTypes:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ class ExtensionsStages:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ class ExtensionsTopicLabels:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ class ExtensionsTopicStatuses:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ class ExtensionsTopicTypes:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ class ExtensionsUsers:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ class Extensions:
|
|||||||
"name": "TopicTypes",
|
"name": "TopicTypes",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
topic_statuses: Optional[ExtensionsTopicStatuses] = field(
|
topic_statuses: Optional[ExtensionsTopicStatuses] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -137,7 +137,7 @@ class Extensions:
|
|||||||
"name": "TopicStatuses",
|
"name": "TopicStatuses",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
priorities: Optional[ExtensionsPriorities] = field(
|
priorities: Optional[ExtensionsPriorities] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -145,7 +145,7 @@ class Extensions:
|
|||||||
"name": "Priorities",
|
"name": "Priorities",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
topic_labels: Optional[ExtensionsTopicLabels] = field(
|
topic_labels: Optional[ExtensionsTopicLabels] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -153,7 +153,7 @@ class Extensions:
|
|||||||
"name": "TopicLabels",
|
"name": "TopicLabels",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
users: Optional[ExtensionsUsers] = field(
|
users: Optional[ExtensionsUsers] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -161,7 +161,7 @@ class Extensions:
|
|||||||
"name": "Users",
|
"name": "Users",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
snippet_types: Optional[ExtensionsSnippetTypes] = field(
|
snippet_types: Optional[ExtensionsSnippetTypes] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -169,7 +169,7 @@ class Extensions:
|
|||||||
"name": "SnippetTypes",
|
"name": "SnippetTypes",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
stages: Optional[ExtensionsStages] = field(
|
stages: Optional[ExtensionsStages] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -177,5 +177,5 @@ class Extensions:
|
|||||||
"name": "Stages",
|
"name": "Stages",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class BimSnippet:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "IsExternal",
|
"name": "IsExternal",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ class DocumentReference:
|
|||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
url: Optional[str] = field(
|
url: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -78,7 +78,7 @@ class DocumentReference:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
description: Optional[str] = field(
|
description: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -88,7 +88,7 @@ class DocumentReference:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -110,7 +110,7 @@ class File:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
date: Optional[XmlDateTime] = field(
|
date: Optional[XmlDateTime] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -118,7 +118,7 @@ class File:
|
|||||||
"name": "Date",
|
"name": "Date",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
reference: Optional[str] = field(
|
reference: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -128,7 +128,7 @@ class File:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
ifc_project: Optional[str] = field(
|
ifc_project: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -137,7 +137,7 @@ class File:
|
|||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"length": 22,
|
"length": 22,
|
||||||
"pattern": r"[0-9A-Za-z_$]*",
|
"pattern": r"[0-9A-Za-z_$]*",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
ifc_spatial_structure_element: Optional[str] = field(
|
ifc_spatial_structure_element: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -146,14 +146,14 @@ class File:
|
|||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"length": 22,
|
"length": 22,
|
||||||
"pattern": r"[0-9A-Za-z_$]*",
|
"pattern": r"[0-9A-Za-z_$]*",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
is_external: bool = field(
|
is_external: bool = field(
|
||||||
default=True,
|
default=True,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "IsExternal",
|
"name": "IsExternal",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ class TopicLabels:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ class TopicReferenceLinks:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ class ViewPoint:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
snapshot: Optional[str] = field(
|
snapshot: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -226,7 +226,7 @@ class ViewPoint:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
index: Optional[int] = field(
|
index: Optional[int] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -234,7 +234,7 @@ class ViewPoint:
|
|||||||
"name": "Index",
|
"name": "Index",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -274,7 +274,7 @@ class Comment:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
viewpoint: Optional[CommentViewpoint] = field(
|
viewpoint: Optional[CommentViewpoint] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -282,7 +282,7 @@ class Comment:
|
|||||||
"name": "Viewpoint",
|
"name": "Viewpoint",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
modified_date: Optional[XmlDateTime] = field(
|
modified_date: Optional[XmlDateTime] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -290,7 +290,7 @@ class Comment:
|
|||||||
"name": "ModifiedDate",
|
"name": "ModifiedDate",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
modified_author: Optional[str] = field(
|
modified_author: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -300,7 +300,7 @@ class Comment:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -323,7 +323,7 @@ class HeaderFiles:
|
|||||||
"name": "File",
|
"name": "File",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@ class TopicDocumentReferences:
|
|||||||
"name": "DocumentReference",
|
"name": "DocumentReference",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ class TopicRelatedTopics:
|
|||||||
"name": "RelatedTopic",
|
"name": "RelatedTopic",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ class TopicViewpoints:
|
|||||||
"name": "ViewPoint",
|
"name": "ViewPoint",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ class Header:
|
|||||||
"name": "Files",
|
"name": "Files",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ class TopicComments:
|
|||||||
"name": "Comment",
|
"name": "Comment",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -407,7 +407,7 @@ class Topic:
|
|||||||
"name": "ReferenceLinks",
|
"name": "ReferenceLinks",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
title: str = field(
|
title: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -427,7 +427,7 @@ class Topic:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
index: Optional[int] = field(
|
index: Optional[int] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -435,7 +435,7 @@ class Topic:
|
|||||||
"name": "Index",
|
"name": "Index",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
labels: Optional[TopicLabels] = field(
|
labels: Optional[TopicLabels] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -443,7 +443,7 @@ class Topic:
|
|||||||
"name": "Labels",
|
"name": "Labels",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
creation_date: XmlDateTime = field(
|
creation_date: XmlDateTime = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -469,7 +469,7 @@ class Topic:
|
|||||||
"name": "ModifiedDate",
|
"name": "ModifiedDate",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
modified_author: Optional[str] = field(
|
modified_author: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -479,7 +479,7 @@ class Topic:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
due_date: Optional[XmlDateTime] = field(
|
due_date: Optional[XmlDateTime] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -487,7 +487,7 @@ class Topic:
|
|||||||
"name": "DueDate",
|
"name": "DueDate",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
assigned_to: Optional[str] = field(
|
assigned_to: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -497,7 +497,7 @@ class Topic:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
stage: Optional[str] = field(
|
stage: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -507,7 +507,7 @@ class Topic:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
description: Optional[str] = field(
|
description: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -517,7 +517,7 @@ class Topic:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
bim_snippet: Optional[BimSnippet] = field(
|
bim_snippet: Optional[BimSnippet] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -525,7 +525,7 @@ class Topic:
|
|||||||
"name": "BimSnippet",
|
"name": "BimSnippet",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
document_references: Optional[TopicDocumentReferences] = field(
|
document_references: Optional[TopicDocumentReferences] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -533,7 +533,7 @@ class Topic:
|
|||||||
"name": "DocumentReferences",
|
"name": "DocumentReferences",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
related_topics: Optional[TopicRelatedTopics] = field(
|
related_topics: Optional[TopicRelatedTopics] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -541,7 +541,7 @@ class Topic:
|
|||||||
"name": "RelatedTopics",
|
"name": "RelatedTopics",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
comments: Optional[TopicComments] = field(
|
comments: Optional[TopicComments] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -549,7 +549,7 @@ class Topic:
|
|||||||
"name": "Comments",
|
"name": "Comments",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
viewpoints: Optional[TopicViewpoints] = field(
|
viewpoints: Optional[TopicViewpoints] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -557,7 +557,7 @@ class Topic:
|
|||||||
"name": "Viewpoints",
|
"name": "Viewpoints",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -574,7 +574,7 @@ class Topic:
|
|||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
topic_type: str = field(
|
topic_type: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
@@ -604,7 +604,7 @@ class Markup:
|
|||||||
"name": "Header",
|
"name": "Header",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"namespace": "",
|
"namespace": "",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
topic: Topic = field(
|
topic: Topic = field(
|
||||||
metadata={
|
metadata={
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class Project:
|
|||||||
"namespace": "",
|
"namespace": "",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
project_id: str = field(
|
project_id: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Component:
|
|||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
authoring_tool_id: Optional[str] = field(
|
authoring_tool_id: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -26,7 +26,7 @@ class Component:
|
|||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_length": 1,
|
"min_length": 1,
|
||||||
"white_space": "collapse",
|
"white_space": "collapse",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
ifc_guid: Optional[str] = field(
|
ifc_guid: Optional[str] = field(
|
||||||
default=None,
|
default=None,
|
||||||
@@ -35,7 +35,7 @@ class Component:
|
|||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
"length": 22,
|
"length": 22,
|
||||||
"pattern": r"[0-9A-Za-z_$]*",
|
"pattern": r"[0-9A-Za-z_$]*",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -96,21 +96,21 @@ class ViewSetupHints:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "SpacesVisible",
|
"name": "SpacesVisible",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
space_boundaries_visible: bool = field(
|
space_boundaries_visible: bool = field(
|
||||||
default=False,
|
default=False,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "SpaceBoundariesVisible",
|
"name": "SpaceBoundariesVisible",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
openings_visible: bool = field(
|
openings_visible: bool = field(
|
||||||
default=False,
|
default=False,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "OpeningsVisible",
|
"name": "OpeningsVisible",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ class ComponentColoringColorComponents:
|
|||||||
"name": "Component",
|
"name": "Component",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
"min_occurs": 1,
|
"min_occurs": 1,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ class ComponentSelection:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Component",
|
"name": "Component",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ class ComponentVisibilityExceptions:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Component",
|
"name": "Component",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -249,6 +249,7 @@ class OrthogonalCamera:
|
|||||||
aspect_ratio: Proportional relationship between the width and
|
aspect_ratio: Proportional relationship between the width and
|
||||||
the height of the view (w/h).
|
the height of the view (w/h).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
camera_view_point: Point = field(
|
camera_view_point: Point = field(
|
||||||
metadata={
|
metadata={
|
||||||
"name": "CameraViewPoint",
|
"name": "CameraViewPoint",
|
||||||
@@ -302,6 +303,7 @@ class PerspectiveCamera:
|
|||||||
aspect_ratio: Proportional relationship between the width and
|
aspect_ratio: Proportional relationship between the width and
|
||||||
the height of the view (w/h).
|
the height of the view (w/h).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
camera_view_point: Point = field(
|
camera_view_point: Point = field(
|
||||||
metadata={
|
metadata={
|
||||||
"name": "CameraViewPoint",
|
"name": "CameraViewPoint",
|
||||||
@@ -371,21 +373,21 @@ class ComponentVisibility:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "ViewSetupHints",
|
"name": "ViewSetupHints",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
exceptions: Optional[ComponentVisibilityExceptions] = field(
|
exceptions: Optional[ComponentVisibilityExceptions] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Exceptions",
|
"name": "Exceptions",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
default_visibility: bool = field(
|
default_visibility: bool = field(
|
||||||
default=False,
|
default=False,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "DefaultVisibility",
|
"name": "DefaultVisibility",
|
||||||
"type": "Attribute",
|
"type": "Attribute",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -399,7 +401,7 @@ class VisualizationInfoBitmaps:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Bitmap",
|
"name": "Bitmap",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -413,7 +415,7 @@ class VisualizationInfoClippingPlanes:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "ClippingPlane",
|
"name": "ClippingPlane",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -427,7 +429,7 @@ class VisualizationInfoLines:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Line",
|
"name": "Line",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -438,7 +440,7 @@ class ComponentColoring:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Color",
|
"name": "Color",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -449,21 +451,21 @@ class Components:
|
|||||||
metadata={
|
metadata={
|
||||||
"name": "Selection",
|
"name": "Selection",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
visibility: Optional[ComponentVisibility] = field(
|
visibility: Optional[ComponentVisibility] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Visibility",
|
"name": "Visibility",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
coloring: Optional[ComponentColoring] = field(
|
coloring: Optional[ComponentColoring] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Coloring",
|
"name": "Coloring",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -472,47 +474,48 @@ class VisualizationInfo:
|
|||||||
"""
|
"""
|
||||||
VisualizationInfo documentation.
|
VisualizationInfo documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
components: Optional[Components] = field(
|
components: Optional[Components] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Components",
|
"name": "Components",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
orthogonal_camera: Optional[OrthogonalCamera] = field(
|
orthogonal_camera: Optional[OrthogonalCamera] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "OrthogonalCamera",
|
"name": "OrthogonalCamera",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
perspective_camera: Optional[PerspectiveCamera] = field(
|
perspective_camera: Optional[PerspectiveCamera] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "PerspectiveCamera",
|
"name": "PerspectiveCamera",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
lines: Optional[VisualizationInfoLines] = field(
|
lines: Optional[VisualizationInfoLines] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Lines",
|
"name": "Lines",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
|
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "ClippingPlanes",
|
"name": "ClippingPlanes",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
bitmaps: Optional[VisualizationInfoBitmaps] = field(
|
bitmaps: Optional[VisualizationInfoBitmaps] = field(
|
||||||
default=None,
|
default=None,
|
||||||
metadata={
|
metadata={
|
||||||
"name": "Bitmaps",
|
"name": "Bitmaps",
|
||||||
"type": "Element",
|
"type": "Element",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
guid: str = field(
|
guid: str = field(
|
||||||
metadata={
|
metadata={
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""BCF XML V3 Topic handler."""
|
"""BCF XML V3 Topic handler."""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import uuid
|
import uuid
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""XML Parser and Serializer factories."""
|
"""XML Parser and Serializer factories."""
|
||||||
|
|
||||||
from typing import Optional, Protocol, Type, TypeVar
|
from typing import Optional, Protocol, Type, TypeVar
|
||||||
|
|
||||||
from xsdata.formats.dataclass.context import XmlContext
|
from xsdata.formats.dataclass.context import XmlContext
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""BCF XML tests."""
|
"""BCF XML tests."""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""BCF XML tests."""
|
"""BCF XML tests."""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
|||||||
+21
-10
@@ -3,39 +3,50 @@ from bsdd import Client
|
|||||||
client = Client()
|
client = Client()
|
||||||
|
|
||||||
ifc4x3_uri = [l["uri"] for l in client.get_dictionary()["dictionaries"] if "4.3" in l["uri"]][0]
|
ifc4x3_uri = [l["uri"] for l in client.get_dictionary()["dictionaries"] if "4.3" in l["uri"]][0]
|
||||||
nbs_uri = [l["uri"] for l in client.get_dictionary()["dictionaries"] if 'Uniclass 2015' == l["name"]][0]
|
nbs_uri = [l["uri"] for l in client.get_dictionary()["dictionaries"] if "Uniclass 2015" == l["name"]][0]
|
||||||
|
|
||||||
|
|
||||||
def get_ifc_classes():
|
def get_ifc_classes():
|
||||||
return client.get_classes(ifc4x3_uri, use_nested_classes= False, class_type="Class")
|
return client.get_classes(ifc4x3_uri, use_nested_classes=False, class_type="Class")
|
||||||
|
|
||||||
|
|
||||||
def get_nbs_classes():
|
def get_nbs_classes():
|
||||||
return client.get_classes(nbs_uri, use_nested_classes= False, class_type="Class", offset=0, limit=5)
|
return client.get_classes(nbs_uri, use_nested_classes=False, class_type="Class", offset=0, limit=5)
|
||||||
|
|
||||||
|
|
||||||
def test_get_dictionary():
|
def test_get_dictionary():
|
||||||
li_names = [l["name"] for l in client.get_dictionary()["dictionaries"]]
|
li_names = [l["name"] for l in client.get_dictionary()["dictionaries"]]
|
||||||
assert 'Uniclass 2015' and 'IFC' in li_names
|
assert "Uniclass 2015" and "IFC" in li_names
|
||||||
|
|
||||||
|
|
||||||
def test_get_ifc_classes():
|
def test_get_ifc_classes():
|
||||||
ifc4x3_classes = get_ifc_classes()
|
ifc4x3_classes = get_ifc_classes()
|
||||||
assert "IfcBoiler" and "IfcLightFixture" in [l["code"] for l in ifc4x3_classes["classes"]]
|
assert "IfcBoiler" and "IfcLightFixture" in [l["code"] for l in ifc4x3_classes["classes"]]
|
||||||
|
|
||||||
|
|
||||||
def test_get_nbs_classes():
|
def test_get_nbs_classes():
|
||||||
nbs_classes = get_nbs_classes()
|
nbs_classes = get_nbs_classes()
|
||||||
assert "Ac" in [l["code"] for l in nbs_classes["classes"]]
|
assert "Ac" in [l["code"] for l in nbs_classes["classes"]]
|
||||||
|
|
||||||
|
|
||||||
def test_get_class():
|
def test_get_class():
|
||||||
uri_light_fixture = [l for l in get_ifc_classes()["classes"] if "IfcLightFixture" == l["code"]][0]["uri"]
|
uri_light_fixture = [l for l in get_ifc_classes()["classes"] if "IfcLightFixture" == l["code"]][0]["uri"]
|
||||||
ifc4x3_light_fixture = client.get_class(uri_light_fixture)
|
ifc4x3_light_fixture = client.get_class(uri_light_fixture)
|
||||||
assert 'Maintenance Factor' and 'Light Fixture Mounting Type' in [l["name"] for l in ifc4x3_light_fixture["classProperties"]]
|
assert "Maintenance Factor" and "Light Fixture Mounting Type" in [
|
||||||
|
l["name"] for l in ifc4x3_light_fixture["classProperties"]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_search_class():
|
def test_search_class():
|
||||||
ss_heat_pump_sys = client.search_class("Ss_60_40_36", [nbs_uri] )
|
ss_heat_pump_sys = client.search_class("Ss_60_40_36", [nbs_uri])
|
||||||
li = [l + "source heat pump systems" for l in ["Air ", "Ground ", "Water "]]
|
li = [l + "source heat pump systems" for l in ["Air ", "Ground ", "Water "]]
|
||||||
assert len(li) < 8 # I think it should be 4 but just validating it isn't overfetching with some space for future change
|
assert (
|
||||||
for l in li:
|
len(li) < 8
|
||||||
|
) # I think it should be 4 but just validating it isn't overfetching with some space for future change
|
||||||
|
for l in li:
|
||||||
assert l in [_["name"] for _ in ss_heat_pump_sys["classes"]]
|
assert l in [_["name"] for _ in ss_heat_pump_sys["classes"]]
|
||||||
|
|
||||||
|
|
||||||
def test_get_properties():
|
def test_get_properties():
|
||||||
pr = client.get_properties(ifc4x3_uri, offset=0, limit=5)
|
pr = client.get_properties(ifc4x3_uri, offset=0, limit=5)
|
||||||
assert len(pr["properties"]) == 5
|
assert len(pr["properties"]) == 5
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Ifc2CA - IFC Code_Aster utility
|
# Ifc2CA - IFC Code_Aster utility
|
||||||
# Copyright (C) 2020, 2021 Ioannis P. Christovasilis <ipc@aethereng.com>
|
# Copyright (C) 2020, 2021 Ioannis P. Christovasilis <ipc@aethereng.com>
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ class COMMANDFILE:
|
|||||||
conn["relatedElements"] = []
|
conn["relatedElements"] = []
|
||||||
for el in elements:
|
for el in elements:
|
||||||
for rel in el["connections"]:
|
for rel in el["connections"]:
|
||||||
conn = [
|
conn = [c for c in connections if c["referenceName"] == rel["relatedConnection"]][0]
|
||||||
c for c in connections if c["referenceName"] == rel["relatedConnection"]
|
|
||||||
][0]
|
|
||||||
conn["relatedElements"].append(rel)
|
conn["relatedElements"].append(rel)
|
||||||
# End <--
|
# End <--
|
||||||
|
|
||||||
@@ -65,27 +63,17 @@ class COMMANDFILE:
|
|||||||
profiles = data["db"]["profiles"]
|
profiles = data["db"]["profiles"]
|
||||||
|
|
||||||
edgeGroupNames = tuple(
|
edgeGroupNames = tuple(
|
||||||
[
|
[self.getGroupName(el["referenceName"]) for el in elements if el["geometryType"] == "line"]
|
||||||
self.getGroupName(el["referenceName"])
|
|
||||||
for el in elements
|
|
||||||
if el["geometryType"] == "line"
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
faceGroupNames = tuple(
|
faceGroupNames = tuple(
|
||||||
[
|
[self.getGroupName(el["referenceName"]) for el in elements if el["geometryType"] == "surface"]
|
||||||
self.getGroupName(el["referenceName"])
|
|
||||||
for el in elements
|
|
||||||
if el["geometryType"] == "surface"
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
rigidLinkGroupNames = []
|
rigidLinkGroupNames = []
|
||||||
for conn in connections:
|
for conn in connections:
|
||||||
rigidLinkGroupNames.extend(
|
rigidLinkGroupNames.extend(
|
||||||
[
|
[
|
||||||
self.getGroupName(rel["relatingElement"])
|
self.getGroupName(rel["relatingElement"]) + "_1DR_" + self.getGroupName(conn["referenceName"])
|
||||||
+ "_1DR_"
|
|
||||||
+ self.getGroupName(conn["referenceName"])
|
|
||||||
for rel in conn["relatedElements"]
|
for rel in conn["relatedElements"]
|
||||||
if rel["eccentricity"]
|
if rel["eccentricity"]
|
||||||
]
|
]
|
||||||
@@ -192,20 +180,16 @@ model = AFFE_MODELE(
|
|||||||
else:
|
else:
|
||||||
if "shearModulus" in material["mechProps"]:
|
if "shearModulus" in material["mechProps"]:
|
||||||
poissonRatio = (
|
poissonRatio = (
|
||||||
material["mechProps"]["youngModulus"]
|
material["mechProps"]["youngModulus"] / 2.0 / material["mechProps"]["shearModulus"]
|
||||||
/ 2.0
|
|
||||||
/ material["mechProps"]["shearModulus"]
|
|
||||||
) - 1
|
) - 1
|
||||||
else:
|
else:
|
||||||
poissonRatio = 0.0
|
poissonRatio = 0.0
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"matNameID": "mat" + "_%s" % i,
|
"matNameID": "mat" + "_%s" % i,
|
||||||
"youngModulus": float(material["mechProps"]["youngModulus"])
|
"youngModulus": float(material["mechProps"]["youngModulus"]) * ScaleFactor**2,
|
||||||
* ScaleFactor ** 2,
|
|
||||||
"poissonRatio": float(poissonRatio),
|
"poissonRatio": float(poissonRatio),
|
||||||
"massDensity": float(material["commonProps"]["massDensity"])
|
"massDensity": float(material["commonProps"]["massDensity"]) * ScaleFactor**3,
|
||||||
* ScaleFactor ** 3,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f.write(template.format(**context))
|
f.write(template.format(**context))
|
||||||
@@ -225,9 +209,7 @@ material = AFFE_MATERIAU(
|
|||||||
),"""
|
),"""
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"groupNames": tuple(
|
"groupNames": tuple([self.getGroupName(rel) for rel in material["relatedElements"]]),
|
||||||
[self.getGroupName(rel) for rel in material["relatedElements"]]
|
|
||||||
),
|
|
||||||
"matNameID": "mat" + "_%s" % i,
|
"matNameID": "mat" + "_%s" % i,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,10 +242,7 @@ element = AFFE_CARA_ELEM(
|
|||||||
)
|
)
|
||||||
|
|
||||||
for profile in profiles:
|
for profile in profiles:
|
||||||
if (
|
if profile["profileShape"] == "rectangular" and profile["profileType"] == "AREA":
|
||||||
profile["profileShape"] == "rectangular"
|
|
||||||
and profile["profileType"] == "AREA"
|
|
||||||
):
|
|
||||||
template = """
|
template = """
|
||||||
_F(
|
_F(
|
||||||
GROUP_MA = {groupNames},
|
GROUP_MA = {groupNames},
|
||||||
@@ -273,9 +252,7 @@ element = AFFE_CARA_ELEM(
|
|||||||
),"""
|
),"""
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"groupNames": tuple(
|
"groupNames": tuple([self.getGroupName(rel) for rel in profile["relatedElements"]]),
|
||||||
[self.getGroupName(rel) for rel in profile["relatedElements"]]
|
|
||||||
),
|
|
||||||
"profileDimensions": (
|
"profileDimensions": (
|
||||||
profile["xDim"] / ScaleFactor,
|
profile["xDim"] / ScaleFactor,
|
||||||
profile["yDim"] / ScaleFactor,
|
profile["yDim"] / ScaleFactor,
|
||||||
@@ -284,10 +261,7 @@ element = AFFE_CARA_ELEM(
|
|||||||
|
|
||||||
f.write(template.format(**context))
|
f.write(template.format(**context))
|
||||||
|
|
||||||
elif (
|
elif profile["profileShape"] == "iSymmetrical" and profile["profileType"] == "AREA":
|
||||||
profile["profileShape"] == "iSymmetrical"
|
|
||||||
and profile["profileType"] == "AREA"
|
|
||||||
):
|
|
||||||
template = """
|
template = """
|
||||||
_F(
|
_F(
|
||||||
GROUP_MA = {groupNames},
|
GROUP_MA = {groupNames},
|
||||||
@@ -297,14 +271,12 @@ element = AFFE_CARA_ELEM(
|
|||||||
),"""
|
),"""
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"groupNames": tuple(
|
"groupNames": tuple([self.getGroupName(rel) for rel in profile["relatedElements"]]),
|
||||||
[self.getGroupName(rel) for rel in profile["relatedElements"]]
|
|
||||||
),
|
|
||||||
"profileProperties": (
|
"profileProperties": (
|
||||||
profile["mechProps"]["crossSectionArea"] / ScaleFactor ** 2,
|
profile["mechProps"]["crossSectionArea"] / ScaleFactor**2,
|
||||||
profile["mechProps"]["momentOfInertiaY"] / ScaleFactor ** 4,
|
profile["mechProps"]["momentOfInertiaY"] / ScaleFactor**4,
|
||||||
profile["mechProps"]["momentOfInertiaZ"] / ScaleFactor ** 4,
|
profile["mechProps"]["momentOfInertiaZ"] / ScaleFactor**4,
|
||||||
profile["mechProps"]["torsionalConstantX"] / ScaleFactor ** 4,
|
profile["mechProps"]["torsionalConstantX"] / ScaleFactor**4,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,9 +544,7 @@ if __name__ == "__main__":
|
|||||||
files = fileNames
|
files = fileNames
|
||||||
|
|
||||||
for fileName in files:
|
for fileName in files:
|
||||||
BASE_PATH = Path(
|
BASE_PATH = Path("/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/")
|
||||||
"/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/"
|
|
||||||
)
|
|
||||||
DATAFILENAME = BASE_PATH / fileName / f"{fileName}.json"
|
DATAFILENAME = BASE_PATH / fileName / f"{fileName}.json"
|
||||||
ASTERFILENAME = BASE_PATH / fileName / f"{fileName}.comm"
|
ASTERFILENAME = BASE_PATH / fileName / f"{fileName}.comm"
|
||||||
COMMANDFILE(DATAFILENAME, ASTERFILENAME)
|
COMMANDFILE(DATAFILENAME, ASTERFILENAME)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
flatten = itertools.chain.from_iterable
|
flatten = itertools.chain.from_iterable
|
||||||
|
|
||||||
|
|
||||||
class MODEL:
|
class MODEL:
|
||||||
def __init__(self, dataFilename, medFilename, meshSize, zGround):
|
def __init__(self, dataFilename, medFilename, meshSize, zGround):
|
||||||
self.dataFilename = dataFilename
|
self.dataFilename = dataFilename
|
||||||
@@ -97,9 +98,7 @@ class MODEL:
|
|||||||
shapeType = "EDGE"
|
shapeType = "EDGE"
|
||||||
if geometryType == "surface":
|
if geometryType == "surface":
|
||||||
shapeType = "FACE"
|
shapeType = "FACE"
|
||||||
return self.geompy.MakePartition(
|
return self.geompy.MakePartition(objects, [], [], [], self.geompy.ShapeType[shapeType], 0, [], 1)
|
||||||
objects, [], [], [], self.geompy.ShapeType[shapeType], 0, [], 1
|
|
||||||
)
|
|
||||||
|
|
||||||
def getLinkGeometry(self, ecc, orientation, finalPoint):
|
def getLinkGeometry(self, ecc, orientation, finalPoint):
|
||||||
vector = np.array(orientation).transpose().dot(ecc["vector"])
|
vector = np.array(orientation).transpose().dot(ecc["vector"])
|
||||||
@@ -195,29 +194,21 @@ class MODEL:
|
|||||||
|
|
||||||
el["linkObjs"] = [None for _ in el["connections"]]
|
el["linkObjs"] = [None for _ in el["connections"]]
|
||||||
for j, rel in enumerate(el["connections"]):
|
for j, rel in enumerate(el["connections"]):
|
||||||
conn = [
|
conn = [c for c in connections if c["referenceName"] == rel["relatedConnection"]][0]
|
||||||
c for c in connections if c["referenceName"] == rel["relatedConnection"]
|
|
||||||
][0]
|
|
||||||
if rel["eccentricity"]:
|
if rel["eccentricity"]:
|
||||||
rel["index"] = len(conn["relatedElements"]) + 1
|
rel["index"] = len(conn["relatedElements"]) + 1
|
||||||
|
|
||||||
geometry = self.getLinkGeometry(
|
geometry = self.getLinkGeometry(rel["eccentricity"], el["orientation"], conn["geometry"])
|
||||||
rel["eccentricity"], el["orientation"], conn["geometry"]
|
|
||||||
)
|
|
||||||
el["linkObjs"][j] = self.makeObject(geometry, "line")
|
el["linkObjs"][j] = self.makeObject(geometry, "line")
|
||||||
conn["relatedElements"].append(rel)
|
conn["relatedElements"].append(rel)
|
||||||
|
|
||||||
# Make assemble of Building Object
|
# Make assemble of Building Object
|
||||||
bldObjs = []
|
bldObjs = []
|
||||||
bldObjs.extend([el["elemObj"] for el in elements])
|
bldObjs.extend([el["elemObj"] for el in elements])
|
||||||
bldObjs.extend(
|
bldObjs.extend(flatten([[link for link in el["linkObjs"] if link] for el in elements]))
|
||||||
flatten([[link for link in el["linkObjs"] if link] for el in elements])
|
|
||||||
)
|
|
||||||
|
|
||||||
# bldComp = geompy.MakeCompound(bldObjs)
|
# bldComp = geompy.MakeCompound(bldObjs)
|
||||||
bldComp = geompy.MakePartition(
|
bldComp = geompy.MakePartition(bldObjs, [], [], [], self.geompy.ShapeType[buildingShapeType], 0, [], 1)
|
||||||
bldObjs, [], [], [], self.geompy.ShapeType[buildingShapeType], 0, [], 1
|
|
||||||
)
|
|
||||||
geompy.addToStudy(bldComp, "bldComp")
|
geompy.addToStudy(bldComp, "bldComp")
|
||||||
|
|
||||||
elapsed_time = time.time() - init_time
|
elapsed_time = time.time() - init_time
|
||||||
@@ -227,25 +218,19 @@ class MODEL:
|
|||||||
# Define and add groups for all curve, surface and rigid members
|
# Define and add groups for all curve, surface and rigid members
|
||||||
if len([e for e in elements if e["geometryType"] == "line"]) > 0:
|
if len([e for e in elements if e["geometryType"] == "line"]) > 0:
|
||||||
# Make compound of requested group
|
# Make compound of requested group
|
||||||
compoundTemp = geompy.MakeCompound(
|
compoundTemp = geompy.MakeCompound([e["elemObj"] for e in elements if e["geometryType"] == "line"])
|
||||||
[e["elemObj"] for e in elements if e["geometryType"] == "line"]
|
|
||||||
)
|
|
||||||
# Define group object and add to study
|
# Define group object and add to study
|
||||||
curveCompound = geompy.GetInPlace(bldComp, compoundTemp, True)
|
curveCompound = geompy.GetInPlace(bldComp, compoundTemp, True)
|
||||||
geompy.addToStudyInFather(bldComp, curveCompound, "CurveMembers")
|
geompy.addToStudyInFather(bldComp, curveCompound, "CurveMembers")
|
||||||
|
|
||||||
if len([e for e in elements if e["geometryType"] == "surface"]) > 0:
|
if len([e for e in elements if e["geometryType"] == "surface"]) > 0:
|
||||||
# Make compound of requested group
|
# Make compound of requested group
|
||||||
compoundTemp = geompy.MakeCompound(
|
compoundTemp = geompy.MakeCompound([e["elemObj"] for e in elements if e["geometryType"] == "surface"])
|
||||||
[e["elemObj"] for e in elements if e["geometryType"] == "surface"]
|
|
||||||
)
|
|
||||||
# Define group object and add to study
|
# Define group object and add to study
|
||||||
surfaceCompound = geompy.GetInPlace(bldComp, compoundTemp, True)
|
surfaceCompound = geompy.GetInPlace(bldComp, compoundTemp, True)
|
||||||
geompy.addToStudyInFather(bldComp, surfaceCompound, "SurfaceMembers")
|
geompy.addToStudyInFather(bldComp, surfaceCompound, "SurfaceMembers")
|
||||||
|
|
||||||
linkObjs = list(
|
linkObjs = list(flatten([[obj for obj in el["linkObjs"] if obj] for el in elements]))
|
||||||
flatten([[obj for obj in el["linkObjs"] if obj] for el in elements])
|
|
||||||
)
|
|
||||||
if len(linkObjs) > 0:
|
if len(linkObjs) > 0:
|
||||||
# Make compound of requested group
|
# Make compound of requested group
|
||||||
compoundTemp = geompy.MakeCompound(linkObjs)
|
compoundTemp = geompy.MakeCompound(linkObjs)
|
||||||
@@ -256,21 +241,15 @@ class MODEL:
|
|||||||
for el in elements:
|
for el in elements:
|
||||||
# el['partObj'] = geompy.RestoreGivenSubShapes(bldComp, [el['partObj']], GEOM.FSM_GetInPlace, False, False)[0]
|
# el['partObj'] = geompy.RestoreGivenSubShapes(bldComp, [el['partObj']], GEOM.FSM_GetInPlace, False, False)[0]
|
||||||
el["elemObj"] = geompy.GetInPlace(bldComp, el["elemObj"], True)
|
el["elemObj"] = geompy.GetInPlace(bldComp, el["elemObj"], True)
|
||||||
geompy.addToStudyInFather(
|
geompy.addToStudyInFather(bldComp, el["elemObj"], self.getGroupName(el["referenceName"]))
|
||||||
bldComp, el["elemObj"], self.getGroupName(el["referenceName"])
|
|
||||||
)
|
|
||||||
|
|
||||||
for j, rel in enumerate(el["connections"]):
|
for j, rel in enumerate(el["connections"]):
|
||||||
if rel["eccentricity"]: # point geometry
|
if rel["eccentricity"]: # point geometry
|
||||||
el["linkObjs"][j] = geompy.GetInPlace(
|
el["linkObjs"][j] = geompy.GetInPlace(bldComp, el["linkObjs"][j], True)
|
||||||
bldComp, el["linkObjs"][j], True
|
|
||||||
)
|
|
||||||
geompy.addToStudyInFather(
|
geompy.addToStudyInFather(
|
||||||
bldComp,
|
bldComp,
|
||||||
el["linkObjs"][j],
|
el["linkObjs"][j],
|
||||||
self.getGroupName(el["referenceName"])
|
self.getGroupName(el["referenceName"]) + "_1DR_" + self.getGroupName(rel["relatedConnection"]),
|
||||||
+ "_1DR_"
|
|
||||||
+ self.getGroupName(rel["relatedConnection"]),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
elapsed_time = time.time() - init_time
|
elapsed_time = time.time() - init_time
|
||||||
@@ -307,9 +286,7 @@ class MODEL:
|
|||||||
NETGEN2D_Pars.SetFuseEdges(254)
|
NETGEN2D_Pars.SetFuseEdges(254)
|
||||||
|
|
||||||
isDone = bldMesh.Compute()
|
isDone = bldMesh.Compute()
|
||||||
coincident_nodes_on_part = bldMesh.FindCoincidentNodesOnPart(
|
coincident_nodes_on_part = bldMesh.FindCoincidentNodesOnPart([bldMesh], tolLoc, [], 0)
|
||||||
[bldMesh], tolLoc, [], 0
|
|
||||||
)
|
|
||||||
if coincident_nodes_on_part:
|
if coincident_nodes_on_part:
|
||||||
# bldMesh.MergeNodes(coincident_nodes_on_part, [], 0)
|
# bldMesh.MergeNodes(coincident_nodes_on_part, [], 0)
|
||||||
# print(f'{len(coincident_nodes_on_part)} Sets of Coincident Nodes Found and Merged')
|
# print(f'{len(coincident_nodes_on_part)} Sets of Coincident Nodes Found and Merged')
|
||||||
@@ -349,25 +326,19 @@ class MODEL:
|
|||||||
shapeType = SMESH.EDGE
|
shapeType = SMESH.EDGE
|
||||||
if el["geometryType"] == "surface":
|
if el["geometryType"] == "surface":
|
||||||
shapeType = SMESH.FACE
|
shapeType = SMESH.FACE
|
||||||
tempgroup = bldMesh.GroupOnGeom(
|
tempgroup = bldMesh.GroupOnGeom(el["elemObj"], self.getGroupName(el["referenceName"]), shapeType)
|
||||||
el["elemObj"], self.getGroupName(el["referenceName"]), shapeType
|
|
||||||
)
|
|
||||||
smesh.SetName(tempgroup, self.getGroupName(el["referenceName"]))
|
smesh.SetName(tempgroup, self.getGroupName(el["referenceName"]))
|
||||||
|
|
||||||
for j, rel in enumerate(el["connections"]):
|
for j, rel in enumerate(el["connections"]):
|
||||||
if rel["eccentricity"]:
|
if rel["eccentricity"]:
|
||||||
tempgroup = bldMesh.GroupOnGeom(
|
tempgroup = bldMesh.GroupOnGeom(
|
||||||
el["linkObjs"][j],
|
el["linkObjs"][j],
|
||||||
self.getGroupName(el["referenceName"])
|
self.getGroupName(el["referenceName"]) + "_1DR_" + self.getGroupName(rel["relatedConnection"]),
|
||||||
+ "_1DR_"
|
|
||||||
+ self.getGroupName(rel["relatedConnection"]),
|
|
||||||
SMESH.EDGE,
|
SMESH.EDGE,
|
||||||
)
|
)
|
||||||
smesh.SetName(
|
smesh.SetName(
|
||||||
tempgroup,
|
tempgroup,
|
||||||
self.getGroupName(el["referenceName"])
|
self.getGroupName(el["referenceName"]) + "_1DR_" + self.getGroupName(rel["relatedConnection"]),
|
||||||
+ "_1DR_"
|
|
||||||
+ self.getGroupName(rel["relatedConnection"]),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mesh = bldMesh
|
self.mesh = bldMesh
|
||||||
@@ -420,9 +391,7 @@ if __name__ == "__main__":
|
|||||||
zGround = 0
|
zGround = 0
|
||||||
|
|
||||||
for fileName in files:
|
for fileName in files:
|
||||||
BASE_PATH = Path(
|
BASE_PATH = Path("/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/")
|
||||||
"/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/"
|
|
||||||
)
|
|
||||||
DATAFILENAME = BASE_PATH / fileName / f"{fileName}.json"
|
DATAFILENAME = BASE_PATH / fileName / f"{fileName}.json"
|
||||||
MEDFILENAME = BASE_PATH / fileName / f"{fileName}.med"
|
MEDFILENAME = BASE_PATH / fileName / f"{fileName}.med"
|
||||||
model = MODEL(DATAFILENAME, str(MEDFILENAME), meshSize, zGround)
|
model = MODEL(DATAFILENAME, str(MEDFILENAME), meshSize, zGround)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Ifc2CA - IFC Code_Aster utility
|
# Ifc2CA - IFC Code_Aster utility
|
||||||
# Copyright (C) 2020, 2021, 2023, 2024 Ioannis P. Christovasilis <ipc@aethereng.com>
|
# Copyright (C) 2020, 2021, 2023, 2024 Ioannis P. Christovasilis <ipc@aethereng.com>
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -24,10 +24,12 @@ from pathlib import Path
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
import ifcopenshell as ios
|
import ifcopenshell as ios
|
||||||
|
|
||||||
# import ifcopenshell.geom
|
# import ifcopenshell.geom
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
import ifcopenshell.util.placement
|
import ifcopenshell.util.placement
|
||||||
import ifcopenshell.util.representation
|
import ifcopenshell.util.representation
|
||||||
|
|
||||||
# import ifcopenshell.util.shape
|
# import ifcopenshell.util.shape
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|||||||
+18
-14
@@ -9,23 +9,26 @@ from ifc4d.pp2ifc import PP2Ifc
|
|||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser .add_argument('-f','--file', action='store', type=str,
|
parser.add_argument("-f", "--file", action="store", type=str, required=True, help="schedule file name to be parsed")
|
||||||
required=True, help="schedule file name to be parsed")
|
parser.add_argument(
|
||||||
parser .add_argument('-s','--schedule', action='store', required=True,
|
"-s", "--schedule", action="store", required=True, type=str, help="file format as xer, p6xml, mspxml, pp"
|
||||||
type=str, help='file format as xer, p6xml, mspxml, pp')
|
)
|
||||||
parser .add_argument('-i', '--ifcfile', action='store', required=False,
|
parser.add_argument(
|
||||||
type=str, help='ifc file name as string e.g. \"file.ifc\"')
|
"-i", "--ifcfile", action="store", required=False, type=str, help='ifc file name as string e.g. "file.ifc"'
|
||||||
parser .add_argument('-o', '--output', action='store', required=True,
|
)
|
||||||
type=str, help='ifc file name as string e.g. \"file.ifc\"')
|
parser.add_argument(
|
||||||
args = parser .parse_args()
|
"-o", "--output", action="store", required=True, type=str, help='ifc file name as string e.g. "file.ifc"'
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
def get_file():
|
def get_file():
|
||||||
ifcfile = None
|
ifcfile = None
|
||||||
if args.ifcfile:
|
if args.ifcfile:
|
||||||
ifcfile = ifcopenshell.open(args.ifcfile)
|
ifcfile = ifcopenshell.open(args.ifcfile)
|
||||||
elif args.output:
|
elif args.output:
|
||||||
ifc = ifcopenshell.file(schema='IFC4')
|
ifc = ifcopenshell.file(schema="IFC4")
|
||||||
ifc.create_entity("IfcWorkPlan")
|
ifc.create_entity("IfcWorkPlan")
|
||||||
ifc.create_entity("IfcProject")
|
ifc.create_entity("IfcProject")
|
||||||
ifc.write(args.output)
|
ifc.write(args.output)
|
||||||
@@ -34,6 +37,7 @@ def get_file():
|
|||||||
ifcfile = None
|
ifcfile = None
|
||||||
return ifcfile
|
return ifcfile
|
||||||
|
|
||||||
|
|
||||||
if not args.ifcfile:
|
if not args.ifcfile:
|
||||||
print("You need to provide an ifc file to add schedule")
|
print("You need to provide an ifc file to add schedule")
|
||||||
print("Examples python ifc4d -i model.ifc -s xer -f schedule.xer -o newifc.ifc")
|
print("Examples python ifc4d -i model.ifc -s xer -f schedule.xer -o newifc.ifc")
|
||||||
@@ -41,7 +45,7 @@ elif not args.output:
|
|||||||
print("an output file is required to save changes")
|
print("an output file is required to save changes")
|
||||||
print("python ifc4d -o newfile.ifc -s xer -f schedule.xer")
|
print("python ifc4d -o newfile.ifc -s xer -f schedule.xer")
|
||||||
|
|
||||||
elif args.schedule== "xer":
|
elif args.schedule == "xer":
|
||||||
p6xer = P6XER2Ifc()
|
p6xer = P6XER2Ifc()
|
||||||
p6xer.xer = args.file
|
p6xer.xer = args.file
|
||||||
p6xer.output = args.output
|
p6xer.output = args.output
|
||||||
@@ -49,7 +53,8 @@ elif args.schedule== "xer":
|
|||||||
if ifcfile:
|
if ifcfile:
|
||||||
p6xer.file = ifcfile
|
p6xer.file = ifcfile
|
||||||
p6xer.execute()
|
p6xer.execute()
|
||||||
else: raise Exception("No files provided for output")
|
else:
|
||||||
|
raise Exception("No files provided for output")
|
||||||
elif args.schedule == "mspxml":
|
elif args.schedule == "mspxml":
|
||||||
msp = MSP2Ifc()
|
msp = MSP2Ifc()
|
||||||
msp.xml = args.file()
|
msp.xml = args.file()
|
||||||
@@ -76,4 +81,3 @@ elif args.schedule == "pp":
|
|||||||
pp.execute()
|
pp.execute()
|
||||||
else:
|
else:
|
||||||
print("schedule type you selected is not implemented at the moment")
|
print("schedule type you selected is not implemented at the moment")
|
||||||
|
|
||||||
|
|||||||
@@ -246,12 +246,11 @@ class ScheduleIfcGenerator:
|
|||||||
"ScheduleStart": activity["StartDate"],
|
"ScheduleStart": activity["StartDate"],
|
||||||
"ScheduleFinish": activity["FinishDate"],
|
"ScheduleFinish": activity["FinishDate"],
|
||||||
"DurationType": "WORKTIME" if activity["PlannedDuration"] else None,
|
"DurationType": "WORKTIME" if activity["PlannedDuration"] else None,
|
||||||
"ScheduleDuration": timedelta(
|
"ScheduleDuration": (
|
||||||
days=float(activity["PlannedDuration"]) / float(calendar["HoursPerDay"] or 8)
|
timedelta(days=float(activity["PlannedDuration"]) / float(calendar["HoursPerDay"] or 8)) or None
|
||||||
)
|
if activity["PlannedDuration"]
|
||||||
or None
|
else None
|
||||||
if activity["PlannedDuration"]
|
),
|
||||||
else None,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -86,12 +86,36 @@ class Csv2Ifc:
|
|||||||
|
|
||||||
task_relationships = self.parse_task_rel(row[self.headers["Relationships"]])
|
task_relationships = self.parse_task_rel(row[self.headers["Relationships"]])
|
||||||
|
|
||||||
scheduled_start_date = ifcopenshell.util.date.string_to_date(row[self.headers["ScheduleStart"]]) if row[self.headers["ScheduleStart"]] else None
|
scheduled_start_date = (
|
||||||
scheduled_finish_date = ifcopenshell.util.date.string_to_date(row[self.headers["ScheduleFinish"]]) if row[self.headers["ScheduleFinish"]] else None
|
ifcopenshell.util.date.string_to_date(row[self.headers["ScheduleStart"]])
|
||||||
scheduled_duration = ifcopenshell.util.date.string_to_duration(row[self.headers["ScheduleDuration"]]) if row[self.headers["ScheduleDuration"]] else None
|
if row[self.headers["ScheduleStart"]]
|
||||||
actual_start_date = ifcopenshell.util.date.string_to_date(row[self.headers["ActualStart"]]) if row[self.headers["ActualStart"]] else None
|
else None
|
||||||
actual_finish_date = ifcopenshell.util.date.string_to_date(row[self.headers["ActualFinish"]]) if row[self.headers["ActualFinish"]] else None
|
)
|
||||||
actual_duration = ifcopenshell.util.date.string_to_duration(row[self.headers["ActualDuration"]]) if row[self.headers["ActualDuration"]] else None
|
scheduled_finish_date = (
|
||||||
|
ifcopenshell.util.date.string_to_date(row[self.headers["ScheduleFinish"]])
|
||||||
|
if row[self.headers["ScheduleFinish"]]
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
scheduled_duration = (
|
||||||
|
ifcopenshell.util.date.string_to_duration(row[self.headers["ScheduleDuration"]])
|
||||||
|
if row[self.headers["ScheduleDuration"]]
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
actual_start_date = (
|
||||||
|
ifcopenshell.util.date.string_to_date(row[self.headers["ActualStart"]])
|
||||||
|
if row[self.headers["ActualStart"]]
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
actual_finish_date = (
|
||||||
|
ifcopenshell.util.date.string_to_date(row[self.headers["ActualFinish"]])
|
||||||
|
if row[self.headers["ActualFinish"]]
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
actual_duration = (
|
||||||
|
ifcopenshell.util.date.string_to_duration(row[self.headers["ActualDuration"]])
|
||||||
|
if row[self.headers["ActualDuration"]]
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"Hierarchy": hierarchy,
|
"Hierarchy": hierarchy,
|
||||||
@@ -191,7 +215,7 @@ class Csv2Ifc:
|
|||||||
self.file,
|
self.file,
|
||||||
related_process=task_2,
|
related_process=task_2,
|
||||||
relating_process=task_1,
|
relating_process=task_1,
|
||||||
sequence_type = rel_type,
|
sequence_type=rel_type,
|
||||||
)
|
)
|
||||||
if rel_type:
|
if rel_type:
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ class Ifc2P6:
|
|||||||
self.root = ET.Element("APIBusinessObjects")
|
self.root = ET.Element("APIBusinessObjects")
|
||||||
self.root.attrib["xmlns"] = "http://xmlns.oracle.com/Primavera/P6Professional/V18.8/API/BusinessObjects"
|
self.root.attrib["xmlns"] = "http://xmlns.oracle.com/Primavera/P6Professional/V18.8/API/BusinessObjects"
|
||||||
self.root.attrib["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
|
self.root.attrib["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
self.root.attrib[
|
self.root.attrib["xsi:schemaLocation"] = (
|
||||||
"xsi:schemaLocation"
|
"http://xmlns.oracle.com/Primavera/P6Professional/V18.8/API/BusinessObjects http://xmlns.oracle.com/Primavera/P6Professional/V18.8/API/p6apibo.xsd"
|
||||||
] = "http://xmlns.oracle.com/Primavera/P6Professional/V18.8/API/BusinessObjects http://xmlns.oracle.com/Primavera/P6Professional/V18.8/API/p6apibo.xsd"
|
)
|
||||||
|
|
||||||
self.schedule = self.file.by_type("IfcWorkSchedule")[0]
|
self.schedule = self.file.by_type("IfcWorkSchedule")[0]
|
||||||
|
|
||||||
|
|||||||
+37
-29
@@ -112,13 +112,12 @@ class MSP2Ifc:
|
|||||||
# If first column = "all" then retrieve all columns
|
# If first column = "all" then retrieve all columns
|
||||||
if len(self.optionalColumns) and self.optionalColumns[0] == "all":
|
if len(self.optionalColumns) and self.optionalColumns[0] == "all":
|
||||||
self.optionalColumns = [child.tag.split("}")[1] for child in task]
|
self.optionalColumns = [child.tag.split("}")[1] for child in task]
|
||||||
|
|
||||||
for column in self.optionalColumns:
|
for column in self.optionalColumns:
|
||||||
if not self.tasks[task_id].get(column):
|
if not self.tasks[task_id].get(column):
|
||||||
self.tasks[task_id][column] = task.find(f"pr:{column}", self.ns).text if task.find(f"pr:{column}", self.ns) else None
|
self.tasks[task_id][column] = (
|
||||||
|
task.find(f"pr:{column}", self.ns).text if task.find(f"pr:{column}", self.ns) else None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_calendar_xml(self, project):
|
def parse_calendar_xml(self, project):
|
||||||
def parse_working_times(day):
|
def parse_working_times(day):
|
||||||
@@ -139,27 +138,37 @@ class MSP2Ifc:
|
|||||||
work_times = parse_working_times(exception)
|
work_times = parse_working_times(exception)
|
||||||
time_period = exception.find("pr:TimePeriod", self.ns)
|
time_period = exception.find("pr:TimePeriod", self.ns)
|
||||||
data = {
|
data = {
|
||||||
"Name": exception.find("pr:Name", self.ns).text
|
"Name": (
|
||||||
if exception.find("pr:Name", self.ns) is not None
|
exception.find("pr:Name", self.ns).text if exception.find("pr:Name", self.ns) is not None else None
|
||||||
else None,
|
),
|
||||||
"FromDate": datetime.datetime.fromisoformat(time_period.find("pr:FromDate", self.ns).text)
|
"FromDate": (
|
||||||
if time_period is not None
|
datetime.datetime.fromisoformat(time_period.find("pr:FromDate", self.ns).text)
|
||||||
else None,
|
if time_period is not None
|
||||||
"ToDate": datetime.datetime.fromisoformat(time_period.find("pr:ToDate", self.ns).text)
|
else None
|
||||||
if time_period is not None
|
),
|
||||||
else None,
|
"ToDate": (
|
||||||
"Occurrences": int(exception.find("pr:Occurrences", self.ns).text)
|
datetime.datetime.fromisoformat(time_period.find("pr:ToDate", self.ns).text)
|
||||||
if exception.find("pr:Occurrences", self.ns) is not None
|
if time_period is not None
|
||||||
else None,
|
else None
|
||||||
"Month": exception.find("pr:Month", self.ns).text
|
),
|
||||||
if exception.find("pr:Month", self.ns) is not None
|
"Occurrences": (
|
||||||
else None,
|
int(exception.find("pr:Occurrences", self.ns).text)
|
||||||
"MonthDay": exception.find("pr:MonthDay", self.ns).text
|
if exception.find("pr:Occurrences", self.ns) is not None
|
||||||
if exception.find("pr:MonthDay", self.ns) is not None
|
else None
|
||||||
else None,
|
),
|
||||||
"Type": exception.find("pr:Type", self.ns).text
|
"Month": (
|
||||||
if exception.find("pr:Type", self.ns) is not None
|
exception.find("pr:Month", self.ns).text
|
||||||
else None,
|
if exception.find("pr:Month", self.ns) is not None
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"MonthDay": (
|
||||||
|
exception.find("pr:MonthDay", self.ns).text
|
||||||
|
if exception.find("pr:MonthDay", self.ns) is not None
|
||||||
|
else None
|
||||||
|
),
|
||||||
|
"Type": (
|
||||||
|
exception.find("pr:Type", self.ns).text if exception.find("pr:Type", self.ns) is not None else None
|
||||||
|
),
|
||||||
"WorkingTimes": work_times,
|
"WorkingTimes": work_times,
|
||||||
"ifc": None,
|
"ifc": None,
|
||||||
}
|
}
|
||||||
@@ -283,16 +292,15 @@ class MSP2Ifc:
|
|||||||
for subtask_id in task["subtasks"]:
|
for subtask_id in task["subtasks"]:
|
||||||
self.create_task(self.tasks[subtask_id], parent_task=task)
|
self.create_task(self.tasks[subtask_id], parent_task=task)
|
||||||
|
|
||||||
|
|
||||||
# create pset for optional columns
|
# create pset for optional columns
|
||||||
if len(self.optionalColumns):
|
if len(self.optionalColumns):
|
||||||
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=task["ifc"] , name="Pset_MSP_Task")
|
pset = ifcopenshell.api.run("pset.add_pset", self.file, product=task["ifc"], name="Pset_MSP_Task")
|
||||||
|
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"pset.edit_pset",
|
"pset.edit_pset",
|
||||||
self.file,
|
self.file,
|
||||||
pset=pset,
|
pset=pset,
|
||||||
properties= {name: str(task[name]) for name in self.optionalColumns if task[name]}
|
properties={name: str(task[name]) for name in self.optionalColumns if task[name]},
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_working_week(self, week, calendar):
|
def process_working_week(self, week, calendar):
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class AstaCalendarWorkPattern:
|
|||||||
if wp["DayOfWeek"] == days[lang][index]:
|
if wp["DayOfWeek"] == days[lang][index]:
|
||||||
wp["DayOfWeek"] = days["en"][index]
|
wp["DayOfWeek"] = days["en"][index]
|
||||||
return
|
return
|
||||||
|
|
||||||
translate_days(self.Days, self.dict_wp[-1])
|
translate_days(self.Days, self.dict_wp[-1])
|
||||||
|
|
||||||
for day in self.Days["en"]:
|
for day in self.Days["en"]:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ from bimtester.ifc import IfcStore
|
|||||||
from bimtester.lang import _
|
from bimtester.lang import _
|
||||||
|
|
||||||
|
|
||||||
@step(u'There must be at least one "{ifc_class}" element')
|
@step('There must be at least one "{ifc_class}" element')
|
||||||
def step_impl(context, ifc_class):
|
def step_impl(context, ifc_class):
|
||||||
assert len(IfcStore.file.by_type(ifc_class)) >= 1, _("An element of {} could not be found").format(ifc_class)
|
assert len(IfcStore.file.by_type(ifc_class)) >= 1, _("An element of {} could not be found").format(ifc_class)
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ def check_ifc4_geolocation(entity_name, prop_name=None, value=None, should_asser
|
|||||||
return actual_value
|
return actual_value
|
||||||
|
|
||||||
|
|
||||||
@step(u"The project must have coordinate reference system data")
|
@step("The project must have coordinate reference system data")
|
||||||
def step_impl(context):
|
def step_impl(context):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -77,7 +77,7 @@ def step_impl(context):
|
|||||||
check_ifc4_geolocation("IfcProjectedCRS")
|
check_ifc4_geolocation("IfcProjectedCRS")
|
||||||
|
|
||||||
|
|
||||||
@step(u'The name of the CRS must be "{coordinate_reference_name}"')
|
@step('The name of the CRS must be "{coordinate_reference_name}"')
|
||||||
def step_impl(context, coordinate_reference_name):
|
def step_impl(context, coordinate_reference_name):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -86,7 +86,7 @@ def step_impl(context, coordinate_reference_name):
|
|||||||
check_ifc4_geolocation("IfcProjectedCRS", "Name", coordinate_reference_name)
|
check_ifc4_geolocation("IfcProjectedCRS", "Name", coordinate_reference_name)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The description of the CRS must be "{value}"')
|
@step('The description of the CRS must be "{value}"')
|
||||||
def step_impl(context, value):
|
def step_impl(context, value):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -95,7 +95,7 @@ def step_impl(context, value):
|
|||||||
check_ifc4_geolocation("IfcProjectedCRS", "Description", value)
|
check_ifc4_geolocation("IfcProjectedCRS", "Description", value)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The geodetic datum must be "{coordinate_reference_name}"')
|
@step('The geodetic datum must be "{coordinate_reference_name}"')
|
||||||
def step_impl(context, coordinate_reference_name):
|
def step_impl(context, coordinate_reference_name):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -104,7 +104,7 @@ def step_impl(context, coordinate_reference_name):
|
|||||||
check_ifc4_geolocation("IfcProjectedCRS", "GeodeticDatum", coordinate_reference_name)
|
check_ifc4_geolocation("IfcProjectedCRS", "GeodeticDatum", coordinate_reference_name)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The vertical datum must be "{coordinate_reference_name}"')
|
@step('The vertical datum must be "{coordinate_reference_name}"')
|
||||||
def step_impl(context, coordinate_reference_name):
|
def step_impl(context, coordinate_reference_name):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -113,7 +113,7 @@ def step_impl(context, coordinate_reference_name):
|
|||||||
check_ifc4_geolocation("IfcProjectedCRS", "VerticalDatum", coordinate_reference_name)
|
check_ifc4_geolocation("IfcProjectedCRS", "VerticalDatum", coordinate_reference_name)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The map projection must be "{coordinate_reference_name}"')
|
@step('The map projection must be "{coordinate_reference_name}"')
|
||||||
def step_impl(context, coordinate_reference_name):
|
def step_impl(context, coordinate_reference_name):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -122,7 +122,7 @@ def step_impl(context, coordinate_reference_name):
|
|||||||
check_ifc4_geolocation("IfcProjectedCRS", "MapProjection", coordinate_reference_name)
|
check_ifc4_geolocation("IfcProjectedCRS", "MapProjection", coordinate_reference_name)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The map zone must be "{coordinate_reference_name}"')
|
@step('The map zone must be "{coordinate_reference_name}"')
|
||||||
def step_impl(context, coordinate_reference_name):
|
def step_impl(context, coordinate_reference_name):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -131,7 +131,7 @@ def step_impl(context, coordinate_reference_name):
|
|||||||
check_ifc4_geolocation("IfcProjectedCRS", "MapZone", coordinate_reference_name)
|
check_ifc4_geolocation("IfcProjectedCRS", "MapZone", coordinate_reference_name)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The map unit must be "{unit}"')
|
@step('The map unit must be "{unit}"')
|
||||||
def step_impl(context, unit):
|
def step_impl(context, unit):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -148,7 +148,7 @@ def step_impl(context, unit):
|
|||||||
assert actual_value == unit, _('We expected a value of "{}" but instead got "{}"').format(unit, actual_value)
|
assert actual_value == unit, _('We expected a value of "{}" but instead got "{}"').format(unit, actual_value)
|
||||||
|
|
||||||
|
|
||||||
@step(u"The project must have coordinate transformations to convert from local to global coordinates")
|
@step("The project must have coordinate transformations to convert from local to global coordinates")
|
||||||
def step_impl(context):
|
def step_impl(context):
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
for site in IfcStore.file.by_type("IfcSite"):
|
for site in IfcStore.file.by_type("IfcSite"):
|
||||||
@@ -156,7 +156,7 @@ def step_impl(context):
|
|||||||
check_ifc4_geolocation("IfcMapConversion")
|
check_ifc4_geolocation("IfcMapConversion")
|
||||||
|
|
||||||
|
|
||||||
@step(u'The eastings of the model must be offset by "{number}" to derive its global coordinates')
|
@step('The eastings of the model must be offset by "{number}" to derive its global coordinates')
|
||||||
def step_impl(context, number):
|
def step_impl(context, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
@@ -166,7 +166,7 @@ def step_impl(context, number):
|
|||||||
check_ifc4_geolocation("IfcMapConversion", "Eastings", number)
|
check_ifc4_geolocation("IfcMapConversion", "Eastings", number)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The northings of the model must be offset by "{number}" to derive its global coordinates')
|
@step('The northings of the model must be offset by "{number}" to derive its global coordinates')
|
||||||
def step_impl(context, number):
|
def step_impl(context, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
@@ -176,7 +176,7 @@ def step_impl(context, number):
|
|||||||
check_ifc4_geolocation("IfcMapConversion", "Northings", number)
|
check_ifc4_geolocation("IfcMapConversion", "Northings", number)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The height of the model must be offset by "{number}" to derive its global coordinates')
|
@step('The height of the model must be offset by "{number}" to derive its global coordinates')
|
||||||
def step_impl(context, number):
|
def step_impl(context, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
@@ -186,7 +186,7 @@ def step_impl(context, number):
|
|||||||
check_ifc4_geolocation("IfcMapConversion", "OrthogonalHeight", number)
|
check_ifc4_geolocation("IfcMapConversion", "OrthogonalHeight", number)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The model must be rotated clockwise by "{number}" to derive its global coordinates')
|
@step('The model must be rotated clockwise by "{number}" to derive its global coordinates')
|
||||||
def step_impl(context, number):
|
def step_impl(context, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
@@ -198,7 +198,7 @@ def step_impl(context, number):
|
|||||||
assert actual_value == value, _('We expected a value of "{}" but instead got "{}"').format(value, actual_value)
|
assert actual_value == value, _('We expected a value of "{}" but instead got "{}"').format(value, actual_value)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The model must be scaled along the horizontal axis by "{number}" to derive its global coordinates')
|
@step('The model must be scaled along the horizontal axis by "{number}" to derive its global coordinates')
|
||||||
def step_impl(context, number):
|
def step_impl(context, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
if IfcStore.file.schema == "IFC2X3":
|
if IfcStore.file.schema == "IFC2X3":
|
||||||
@@ -208,7 +208,7 @@ def step_impl(context, number):
|
|||||||
check_ifc4_geolocation("IfcMapConversion", "Scale", number)
|
check_ifc4_geolocation("IfcMapConversion", "Scale", number)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The model must be rotated clockwise by "{number}" for true north to point up')
|
@step('The model must be rotated clockwise by "{number}" for true north to point up')
|
||||||
def step_impl(context, number):
|
def step_impl(context, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
project = IfcStore.file.by_type("IfcProject")[0]
|
project = IfcStore.file.by_type("IfcProject")[0]
|
||||||
@@ -228,7 +228,7 @@ def step_impl(context, number):
|
|||||||
assert False, _("True north is not defined in the file")
|
assert False, _("True north is not defined in the file")
|
||||||
|
|
||||||
|
|
||||||
@step(u'The site "{guid}" has a longitude of "{number}"')
|
@step('The site "{guid}" has a longitude of "{number}"')
|
||||||
def step_impl(context, guid, number):
|
def step_impl(context, guid, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
site = util.assert_guid(IfcStore.file, guid)
|
site = util.assert_guid(IfcStore.file, guid)
|
||||||
@@ -238,7 +238,7 @@ def step_impl(context, guid, number):
|
|||||||
util.assert_attribute(site, "RefLongitude", number)
|
util.assert_attribute(site, "RefLongitude", number)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The site "{guid}" has a latitude of "{number}"')
|
@step('The site "{guid}" has a latitude of "{number}"')
|
||||||
def step_impl(context, guid, number):
|
def step_impl(context, guid, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
site = util.assert_guid(IfcStore.file, guid)
|
site = util.assert_guid(IfcStore.file, guid)
|
||||||
@@ -248,7 +248,7 @@ def step_impl(context, guid, number):
|
|||||||
util.assert_attribute(site, "RefLatitude", number)
|
util.assert_attribute(site, "RefLatitude", number)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The site "{guid}" has an elevation of "{number}"')
|
@step('The site "{guid}" has an elevation of "{number}"')
|
||||||
def step_impl(context, guid, number):
|
def step_impl(context, guid, number):
|
||||||
number = util.assert_number(number)
|
number = util.assert_number(number)
|
||||||
site = util.assert_guid(IfcStore.file, guid)
|
site = util.assert_guid(IfcStore.file, guid)
|
||||||
@@ -256,7 +256,7 @@ def step_impl(context, guid, number):
|
|||||||
util.assert_attribute(site, "RefElevation", number)
|
util.assert_attribute(site, "RefElevation", number)
|
||||||
|
|
||||||
|
|
||||||
@step(u'The site "{guid}" must be coincident with the project origin')
|
@step('The site "{guid}" must be coincident with the project origin')
|
||||||
def step_impl(context, guid):
|
def step_impl(context, guid):
|
||||||
site = util.assert_guid(IfcStore.file, guid)
|
site = util.assert_guid(IfcStore.file, guid)
|
||||||
util.assert_type(site, "IfcSite")
|
util.assert_type(site, "IfcSite")
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ from behave.__main__ import main as behave_main
|
|||||||
from logging import StreamHandler
|
from logging import StreamHandler
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestRunner:
|
class TestRunner:
|
||||||
def __init__(self, ifc_path, schema_path=None, ifc=None):
|
def __init__(self, ifc_path, schema_path=None, ifc=None):
|
||||||
IfcStore.path = ifc_path
|
IfcStore.path = ifc_path
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
|
|||||||
|
|
||||||
me.from_pydata(verts, [], faces)
|
me.from_pydata(verts, [], faces)
|
||||||
me.validate()
|
me.validate()
|
||||||
|
|
||||||
# MATERIAL CREATION
|
# MATERIAL CREATION
|
||||||
def add_material(mname, props):
|
def add_material(mname, props):
|
||||||
if mname in bpy.data.materials:
|
if mname in bpy.data.materials:
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import argparse
|
|||||||
from cjio import cityjson
|
from cjio import cityjson
|
||||||
from .cityjson2ifc import Cityjson2ifc
|
from .cityjson2ifc import Cityjson2ifc
|
||||||
|
|
||||||
|
|
||||||
def cmdline():
|
def cmdline():
|
||||||
# Example:
|
# Example:
|
||||||
# python ifccityjson.py -i example/3DBAG_example.json -o example/output.ifc -n identificatie
|
# python ifccityjson.py -i example/3DBAG_example.json -o example/output.ifc -n identificatie
|
||||||
@@ -28,10 +29,10 @@ def cmdline():
|
|||||||
parser.add_argument("-i", "--input", type=str, help="input CityJSON file", required=True)
|
parser.add_argument("-i", "--input", type=str, help="input CityJSON file", required=True)
|
||||||
parser.add_argument("-o", "--output", type=str, help="output IFC file. Standard is output.ifc")
|
parser.add_argument("-o", "--output", type=str, help="output IFC file. Standard is output.ifc")
|
||||||
parser.add_argument("-n", "--name", type=str, help="Attribute containing the name")
|
parser.add_argument("-n", "--name", type=str, help="Attribute containing the name")
|
||||||
parser.add_argument('--split-lod', dest='split', action='store_true',
|
parser.add_argument("--split-lod", dest="split", action="store_true", help="Split the file in multiple LoDs")
|
||||||
help="Split the file in multiple LoDs")
|
parser.add_argument(
|
||||||
parser.add_argument('--no-split-lod', dest='split', action='store_false',
|
"--no-split-lod", dest="split", action="store_false", help="Do not split the file in multiple LoDs"
|
||||||
help="Do not split the file in multiple LoDs")
|
)
|
||||||
parser.add_argument("--lod", type=str, help="extract LOD value (example: 1.2)")
|
parser.add_argument("--lod", type=str, help="extract LOD value (example: 1.2)")
|
||||||
parser.set_defaults(split=True)
|
parser.set_defaults(split=True)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@@ -50,5 +51,6 @@ def cmdline():
|
|||||||
converter.configuration(**data)
|
converter.configuration(**data)
|
||||||
converter.convert(city_model)
|
converter.convert(city_model)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
cmdline()
|
cmdline()
|
||||||
|
|||||||
@@ -16,4 +16,4 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with ifccityjson. If not, see <http://www.gnu.org/licenses/>.
|
# along with ifccityjson. If not, see <http://www.gnu.org/licenses/>.
|
||||||
__version__ = "0.1.0"
|
__version__ = "0.1.0"
|
||||||
from .cityjson2ifc import *
|
from .cityjson2ifc import *
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# IfcClash - IFC-based clash detection.
|
# IfcClash - IFC-based clash detection.
|
||||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
#
|
#
|
||||||
@@ -18,4 +17,3 @@
|
|||||||
# along with IfcClash. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcClash. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import ifcclash.__main__
|
import ifcclash.__main__
|
||||||
|
|
||||||
|
|||||||
@@ -24,4 +24,3 @@ import subprocess
|
|||||||
|
|
||||||
cmd = "pyinstaller ./bootstrap.py --name ifcclash --onefile --clean"
|
cmd = "pyinstaller ./bootstrap.py --name ifcclash --onefile --clean"
|
||||||
subprocess.check_output(cmd, shell=True)
|
subprocess.check_output(cmd, shell=True)
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,13 @@ parser.add_argument(
|
|||||||
help="The FM standard to extract. Built-in preset standards include cobie24, cobie3, aohbsem, and basic.",
|
help="The FM standard to extract. Built-in preset standards include cobie24, cobie3, aohbsem, and basic.",
|
||||||
)
|
)
|
||||||
parser.add_argument("-i", "--ifc", type=str, required=True, help="The IFC file")
|
parser.add_argument("-i", "--ifc", type=str, required=True, help="The IFC file")
|
||||||
parser.add_argument("-s", "--spreadsheet", type=str, default="output.ods", help="The spreadsheet file, or directory if the format is csv. Defaults to output.ods")
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--spreadsheet",
|
||||||
|
type=str,
|
||||||
|
default="output.ods",
|
||||||
|
help="The spreadsheet file, or directory if the format is csv. Defaults to output.ods",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-f", "--format", type=str, default="ods", help="The format, chosen from csv, ods, or xlsx. Defaults to ods."
|
"-f", "--format", type=str, default="ods", help="The format, chosen from csv, ods, or xlsx. Defaults to ods."
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class Patcher:
|
|||||||
if face.normal.z < 0.5:
|
if face.normal.z < 0.5:
|
||||||
faces_to_delete.append(face)
|
faces_to_delete.append(face)
|
||||||
|
|
||||||
bmesh.ops.delete(bm, geom=faces_to_delete, context='FACES_ONLY')
|
bmesh.ops.delete(bm, geom=faces_to_delete, context="FACES_ONLY")
|
||||||
|
|
||||||
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.01)
|
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.01)
|
||||||
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method="BEAUTY", ngon_method="BEAUTY")
|
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method="BEAUTY", ngon_method="BEAUTY")
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ class TestMergeProject(test.bootstrap.IFC4):
|
|||||||
ifcopenshell.api.geometry.assign_representation(self.file, product=wall1, representation=rep)
|
ifcopenshell.api.geometry.assign_representation(self.file, product=wall1, representation=rep)
|
||||||
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall1)
|
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall1)
|
||||||
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
||||||
assert np.any(np.all(np.isclose(np.array((1., 2., 3.)), verts), axis=1))
|
assert np.any(np.all(np.isclose(np.array((1.0, 2.0, 3.0)), verts), axis=1))
|
||||||
assert np.any(np.all(np.isclose(np.array((3., 4., 5.)), verts), axis=1))
|
assert np.any(np.all(np.isclose(np.array((3.0, 4.0, 5.0)), verts), axis=1))
|
||||||
|
|
||||||
# Second file is in millimeters with a different false origin
|
# Second file is in millimeters with a different false origin
|
||||||
wall1 = second_file.by_type("IfcWall")[0]
|
wall1 = second_file.by_type("IfcWall")[0]
|
||||||
@@ -134,8 +134,8 @@ class TestMergeProject(test.bootstrap.IFC4):
|
|||||||
ifcopenshell.api.geometry.assign_representation(second_file, product=wall1, representation=rep)
|
ifcopenshell.api.geometry.assign_representation(second_file, product=wall1, representation=rep)
|
||||||
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall1)
|
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall1)
|
||||||
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
||||||
assert np.any(np.all(np.isclose(np.array((1., 2., 3.)), verts), axis=1))
|
assert np.any(np.all(np.isclose(np.array((1.0, 2.0, 3.0)), verts), axis=1))
|
||||||
assert np.any(np.all(np.isclose(np.array((3., 4., 5.)), verts), axis=1))
|
assert np.any(np.all(np.isclose(np.array((3.0, 4.0, 5.0)), verts), axis=1))
|
||||||
|
|
||||||
output = ifcpatch.execute({"file": self.file, "recipe": "MergeProject", "arguments": [second_file]})
|
output = ifcpatch.execute({"file": self.file, "recipe": "MergeProject", "arguments": [second_file]})
|
||||||
|
|
||||||
@@ -155,17 +155,17 @@ class TestMergeProject(test.bootstrap.IFC4):
|
|||||||
m2 = ifcopenshell.util.placement.get_local_placement(wall2.ObjectPlacement)
|
m2 = ifcopenshell.util.placement.get_local_placement(wall2.ObjectPlacement)
|
||||||
assert np.allclose(m1[:, 3], (1, 2, 3, 1))
|
assert np.allclose(m1[:, 3], (1, 2, 3, 1))
|
||||||
# assert np.allclose(m2[:, 3], (8.321, 29.321, 3, 1), atol=1e-3)
|
# assert np.allclose(m2[:, 3], (8.321, 29.321, 3, 1), atol=1e-3)
|
||||||
assert np.allclose(m2[:, 3], (17.847, 24.707, 3., 1.), atol=1e-3)
|
assert np.allclose(m2[:, 3], (17.847, 24.707, 3.0, 1.0), atol=1e-3)
|
||||||
|
|
||||||
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall1)
|
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall1)
|
||||||
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
||||||
assert np.any(np.all(np.isclose(np.array((1., 2., 3.)), verts), axis=1))
|
assert np.any(np.all(np.isclose(np.array((1.0, 2.0, 3.0)), verts), axis=1))
|
||||||
assert np.any(np.all(np.isclose(np.array((3., 4., 5.)), verts), axis=1))
|
assert np.any(np.all(np.isclose(np.array((3.0, 4.0, 5.0)), verts), axis=1))
|
||||||
|
|
||||||
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall2)
|
shape = ifcopenshell.geom.create_shape(ifcopenshell.geom.settings(), wall2)
|
||||||
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
verts = ifcopenshell.util.shape.get_shape_vertices(shape, shape.geometry)
|
||||||
assert np.any(np.all(np.isclose(np.array((17.847, 24.707, 3.)), verts, atol=1e-3), axis=1))
|
assert np.any(np.all(np.isclose(np.array((17.847, 24.707, 3.0)), verts, atol=1e-3), axis=1))
|
||||||
assert np.any(np.all(np.isclose(np.array((20.410, 25.902, 5.)), verts, atol=1e-3), axis=1))
|
assert np.any(np.all(np.isclose(np.array((20.410, 25.902, 5.0)), verts, atol=1e-3), axis=1))
|
||||||
|
|
||||||
|
|
||||||
class TestMergeProjectIFC2X3(test.bootstrap.IFC2X3, TestMergeProject):
|
class TestMergeProjectIFC2X3(test.bootstrap.IFC2X3, TestMergeProject):
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ class SvIfcAddPset(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIf
|
|||||||
self.outputs.new("SvStringsSocket", "Entity")
|
self.outputs.new("SvStringsSocket", "Entity")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Add a property set and corresponding properties to IfcElements."
|
||||||
).tooltip = "Add a property set and corresponding properties to IfcElements."
|
)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
if not any(socket.is_linked for socket in self.outputs):
|
if not any(socket.is_linked for socket in self.outputs):
|
||||||
@@ -83,9 +83,7 @@ class SvIfcAddPset(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIf
|
|||||||
def create(self, name, properties, elements):
|
def create(self, name, properties, elements):
|
||||||
results = []
|
results = []
|
||||||
for element in elements:
|
for element in elements:
|
||||||
result = ifcopenshell.api.run(
|
result = ifcopenshell.api.run("pset.add_pset", self.file, product=element, name=name)
|
||||||
"pset.add_pset", self.file, product=element, name=name
|
|
||||||
)
|
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"pset.edit_pset",
|
"pset.edit_pset",
|
||||||
self.file,
|
self.file,
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ from bpy.props import StringProperty, EnumProperty
|
|||||||
from sverchok.node_tree import SverchCustomTreeNode
|
from sverchok.node_tree import SverchCustomTreeNode
|
||||||
from sverchok.data_structure import updateNode
|
from sverchok.data_structure import updateNode
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger('sverchok.ifc')
|
|
||||||
|
logger = logging.getLogger("sverchok.ifc")
|
||||||
|
|
||||||
|
|
||||||
def update_usecase(self, context):
|
def update_usecase(self, context):
|
||||||
|
|||||||
@@ -42,9 +42,7 @@ from sverchok.core.socket_data import sv_get_socket
|
|||||||
from itertools import chain, cycle
|
from itertools import chain, cycle
|
||||||
|
|
||||||
|
|
||||||
class SvIfcBMeshToIfcRepr(
|
class SvIfcBMeshToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||||
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
Triggers: BMesh to Ifc Repr
|
Triggers: BMesh to Ifc Repr
|
||||||
Tooltip: Blender mesh to Ifc Shape Representation
|
Tooltip: Blender mesh to Ifc Shape Representation
|
||||||
@@ -61,9 +59,7 @@ class SvIfcBMeshToIfcRepr(
|
|||||||
self.process()
|
self.process()
|
||||||
self.refresh_local = False
|
self.refresh_local = False
|
||||||
|
|
||||||
refresh_local: BoolProperty(
|
refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node)
|
||||||
name="Update Node", description="Update Node", update=refresh_node
|
|
||||||
)
|
|
||||||
|
|
||||||
context_types = [
|
context_types = [
|
||||||
("Model", "Model", "Context type: Model", 0),
|
("Model", "Model", "Context type: Model", 0),
|
||||||
@@ -113,20 +109,16 @@ class SvIfcBMeshToIfcRepr(
|
|||||||
|
|
||||||
def sv_init(self, context):
|
def sv_init(self, context):
|
||||||
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
|
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
|
||||||
self.inputs.new(
|
self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier"
|
||||||
"SvStringsSocket", "context_identifier"
|
|
||||||
).prop_name = "context_identifier"
|
|
||||||
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
|
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
|
||||||
self.inputs.new(
|
self.inputs.new("SvObjectSocket", "blender_objects").prop_name = "blender_objects" # no prop for now
|
||||||
"SvObjectSocket", "blender_objects"
|
|
||||||
).prop_name = "blender_objects" # no prop for now
|
|
||||||
self.outputs.new("SvVerticesSocket", "Representations")
|
self.outputs.new("SvVerticesSocket", "Representations")
|
||||||
self.outputs.new("SvMatrixSocket", "Locations")
|
self.outputs.new("SvMatrixSocket", "Locations")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries.\nDeconstructs joined geometries and creates a separate representation for each."
|
||||||
).tooltip = "Blender mesh to Ifc Shape Representation. \nTakes one or multiple geometries.\nDeconstructs joined geometries and creates a separate representation for each."
|
)
|
||||||
|
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
|
row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
|
||||||
@@ -136,9 +128,7 @@ class SvIfcBMeshToIfcRepr(
|
|||||||
self.sv_input_names = [i.name for i in self.inputs]
|
self.sv_input_names = [i.name for i in self.inputs]
|
||||||
|
|
||||||
if hash(self) not in self.node_dict:
|
if hash(self) not in self.node_dict:
|
||||||
self.node_dict[
|
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads
|
||||||
hash(self)
|
|
||||||
] = {} # happens if node is already on canvas when blender loads
|
|
||||||
if not self.node_dict[hash(self)]:
|
if not self.node_dict[hash(self)]:
|
||||||
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
|
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
|
||||||
|
|
||||||
@@ -211,21 +201,17 @@ class SvIfcBMeshToIfcRepr(
|
|||||||
context=context,
|
context=context,
|
||||||
)
|
)
|
||||||
if not representation:
|
if not representation:
|
||||||
raise Exception(
|
raise Exception("Couldn't create representation. Possibly wrong context.")
|
||||||
"Couldn't create representation. Possibly wrong context."
|
|
||||||
)
|
|
||||||
|
|
||||||
representations_ids_obj.append([representation.id()])
|
representations_ids_obj.append([representation.id()])
|
||||||
locations_obj.append([obj.matrix_world])
|
locations_obj.append([obj.matrix_world])
|
||||||
representations_ids.append(representations_ids_obj)
|
representations_ids.append(representations_ids_obj)
|
||||||
locations.append(locations_obj)
|
locations.append(locations_obj)
|
||||||
|
|
||||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
|
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(
|
||||||
"Representations", []
|
representations_ids_obj
|
||||||
).append(representations_ids_obj)
|
)
|
||||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
|
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Locations", []).append(locations_obj)
|
||||||
"Locations", []
|
|
||||||
).append(locations_obj)
|
|
||||||
bpy.ops.object.select_all(action="DESELECT")
|
bpy.ops.object.select_all(action="DESELECT")
|
||||||
return representations_ids, locations
|
return representations_ids, locations
|
||||||
|
|
||||||
@@ -248,13 +234,9 @@ class SvIfcBMeshToIfcRepr(
|
|||||||
self.file, self.context_type, self.context_identifier, self.target_view
|
self.file, self.context_type, self.context_identifier, self.target_view
|
||||||
)
|
)
|
||||||
if not context:
|
if not context:
|
||||||
parent = ifcopenshell.util.representation.get_context(
|
parent = ifcopenshell.util.representation.get_context(self.file, self.context_type)
|
||||||
self.file, self.context_type
|
|
||||||
)
|
|
||||||
if not parent:
|
if not parent:
|
||||||
parent = ifcopenshell.api.run(
|
parent = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type)
|
||||||
"context.add_context", self.file, context_type=self.context_type
|
|
||||||
)
|
|
||||||
context = ifcopenshell.api.run(
|
context = ifcopenshell.api.run(
|
||||||
"context.add_context",
|
"context.add_context",
|
||||||
self.file,
|
self.file,
|
||||||
@@ -263,9 +245,7 @@ class SvIfcBMeshToIfcRepr(
|
|||||||
target_view=self.target_view,
|
target_view=self.target_view,
|
||||||
parent=parent,
|
parent=parent,
|
||||||
)
|
)
|
||||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
|
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id())
|
||||||
"Contexts", []
|
|
||||||
).append(context.id())
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def sv_free(self):
|
def sv_free(self):
|
||||||
@@ -286,14 +266,10 @@ class SvIfcBMeshToIfcRepr(
|
|||||||
if not self.file.get_inverse(context):
|
if not self.file.get_inverse(context):
|
||||||
if self.file.by_id(context_id).ParentContext:
|
if self.file.by_id(context_id).ParentContext:
|
||||||
parent = self.file.by_id(context_id).ParentContext
|
parent = self.file.by_id(context_id).ParentContext
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run("context.remove_context", self.file, context=context)
|
||||||
"context.remove_context", self.file, context=context
|
|
||||||
)
|
|
||||||
if parent:
|
if parent:
|
||||||
if not self.file.get_inverse(parent):
|
if not self.file.get_inverse(parent):
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run("context.remove_context", self.file, context=parent)
|
||||||
"context.remove_context", self.file, context=parent
|
|
||||||
)
|
|
||||||
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
|
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
|
||||||
del SvIfcStore.id_map[self.node_id]
|
del SvIfcStore.id_map[self.node_id]
|
||||||
del self.node_dict[hash(self)]
|
del self.node_dict[hash(self)]
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ class SvIfcByGuid(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
|
|||||||
self.outputs.new("SvStringsSocket", "Entities")
|
self.outputs.new("SvStringsSocket", "Entities")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Get IFC element by guid. Takes one or multiple guids."
|
||||||
).tooltip = "Get IFC element by guid. Takes one or multiple guids."
|
)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.guids = flatten_data(self.inputs["guid"].sv_get(), target_level=1)
|
self.guids = flatten_data(self.inputs["guid"].sv_get(), target_level=1)
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ class SvIfcById(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCo
|
|||||||
self.outputs.new("SvStringsSocket", "Entities")
|
self.outputs.new("SvStringsSocket", "Entities")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Get IFC element by step id. Takes one or multiple step ids."
|
||||||
).tooltip = "Get IFC element by step id. Takes one or multiple step ids."
|
)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.ids = flatten_data(self.inputs["id"].sv_get(), target_level=1)
|
self.ids = flatten_data(self.inputs["id"].sv_get(), target_level=1)
|
||||||
|
|||||||
@@ -108,17 +108,15 @@ class SvIfcByType(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfc
|
|||||||
def sv_init(self, context):
|
def sv_init(self, context):
|
||||||
self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product"
|
self.inputs.new("SvStringsSocket", "ifc_product").prop_name = "ifc_product"
|
||||||
self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class"
|
self.inputs.new("SvStringsSocket", "ifc_class").prop_name = "ifc_class"
|
||||||
self.inputs.new(
|
self.inputs.new("SvStringsSocket", "custom_ifc_class").prop_name = "custom_ifc_class"
|
||||||
"SvStringsSocket", "custom_ifc_class"
|
|
||||||
).prop_name = "custom_ifc_class"
|
|
||||||
self.outputs.new("SvStringsSocket", "Entities")
|
self.outputs.new("SvStringsSocket", "Entities")
|
||||||
self.outputs.new("SvStringsSocket", "Entity Ids")
|
self.outputs.new("SvStringsSocket", "Entity Ids")
|
||||||
self.width = 200
|
self.width = 200
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass."
|
||||||
).tooltip = "Get IFC element(s) in file by type. \nPick an IfcProduct and an IfcClass or give a custom IfcClass."
|
)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.file = SvIfcStore.get_file()
|
self.file = SvIfcStore.get_file()
|
||||||
|
|||||||
@@ -32,9 +32,7 @@ from sverchok.data_structure import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SvIfcCreateEntity(
|
class SvIfcCreateEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||||
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
|
|
||||||
):
|
|
||||||
bl_idname = "SvIfcCreateEntity"
|
bl_idname = "SvIfcCreateEntity"
|
||||||
bl_label = "IFC Create Entity"
|
bl_label = "IFC Create Entity"
|
||||||
node_dict = {}
|
node_dict = {}
|
||||||
@@ -46,9 +44,7 @@ class SvIfcCreateEntity(
|
|||||||
self.process()
|
self.process()
|
||||||
self.refresh_local = False
|
self.refresh_local = False
|
||||||
|
|
||||||
refresh_local: BoolProperty(
|
refresh_local: BoolProperty(name="Update Node", description="Update Node", update=refresh_node)
|
||||||
name="Update Node", description="Update Node", update=refresh_node
|
|
||||||
)
|
|
||||||
|
|
||||||
Names: StringProperty(
|
Names: StringProperty(
|
||||||
name="Names",
|
name="Names",
|
||||||
@@ -76,18 +72,16 @@ class SvIfcCreateEntity(
|
|||||||
self.inputs.new("SvStringsSocket", "Names").prop_name = "Names"
|
self.inputs.new("SvStringsSocket", "Names").prop_name = "Names"
|
||||||
self.inputs.new("SvStringsSocket", "Descriptions").prop_name = "Descriptions"
|
self.inputs.new("SvStringsSocket", "Descriptions").prop_name = "Descriptions"
|
||||||
self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass"
|
self.inputs.new("SvStringsSocket", "IfcClass").prop_name = "IfcClass"
|
||||||
self.inputs.new(
|
self.inputs.new("SvStringsSocket", "Representations").prop_name = "Representations"
|
||||||
"SvStringsSocket", "Representations"
|
|
||||||
).prop_name = "Representations"
|
|
||||||
self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False
|
self.inputs.new("SvMatrixSocket", "Locations").is_mandatory = False
|
||||||
# self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties"
|
# self.inputs.new("SvStringsSocket", "Properties").prop_name = "Properties"
|
||||||
self.outputs.new("SvStringsSocket", "Entities")
|
self.outputs.new("SvStringsSocket", "Entities")
|
||||||
self.node_dict[hash(self)] = {}
|
self.node_dict[hash(self)] = {}
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Create IFC Entity. Takes one or multiple inputs. \nIf 'Representation(s)' is given, that determines number of output entities. Otherwise, 'Names' is used."
|
||||||
).tooltip = "Create IFC Entity. Takes one or multiple inputs. \nIf 'Representation(s)' is given, that determines number of output entities. Otherwise, 'Names' is used."
|
)
|
||||||
|
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
|
row.prop(self, "is_interactive", icon="SCENE_DATA", icon_only=True)
|
||||||
@@ -95,26 +89,16 @@ class SvIfcCreateEntity(
|
|||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1)
|
self.names = flatten_data(self.inputs["Names"].sv_get(), target_level=1)
|
||||||
self.descriptions = flatten_data(
|
self.descriptions = flatten_data(self.inputs["Descriptions"].sv_get(), target_level=1)
|
||||||
self.inputs["Descriptions"].sv_get(), target_level=1
|
self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[0]
|
||||||
)
|
self.representations = ensure_min_nesting(self.inputs["Representations"].sv_get(), 3)
|
||||||
self.ifc_class = flatten_data(self.inputs["IfcClass"].sv_get(), target_level=1)[
|
|
||||||
0
|
|
||||||
]
|
|
||||||
self.representations = ensure_min_nesting(
|
|
||||||
self.inputs["Representations"].sv_get(), 3
|
|
||||||
)
|
|
||||||
self.representations = flatten_data(self.representations, target_level=3)
|
self.representations = flatten_data(self.representations, target_level=3)
|
||||||
self.locations = ensure_min_nesting(
|
self.locations = ensure_min_nesting(self.inputs["Locations"].sv_get(default=[]), 3)
|
||||||
self.inputs["Locations"].sv_get(default=[]), 3
|
|
||||||
)
|
|
||||||
self.locations = flatten_data(self.locations, target_level=3)
|
self.locations = flatten_data(self.locations, target_level=3)
|
||||||
self.sv_input_names = [i.name for i in self.inputs]
|
self.sv_input_names = [i.name for i in self.inputs]
|
||||||
|
|
||||||
if hash(self) not in self.node_dict:
|
if hash(self) not in self.node_dict:
|
||||||
self.node_dict[
|
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads
|
||||||
hash(self)
|
|
||||||
] = {} # happens if node is already on canvas when blender loads
|
|
||||||
if not self.node_dict[hash(self)]:
|
if not self.node_dict[hash(self)]:
|
||||||
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
|
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
|
||||||
if not self.inputs["IfcClass"].sv_get()[0][0]:
|
if not self.inputs["IfcClass"].sv_get()[0][0]:
|
||||||
@@ -122,9 +106,7 @@ class SvIfcCreateEntity(
|
|||||||
|
|
||||||
edit = False
|
edit = False
|
||||||
for i in range(len(self.inputs)):
|
for i in range(len(self.inputs)):
|
||||||
input = self.inputs[self.sv_input_names[i]].sv_get(
|
input = self.inputs[self.sv_input_names[i]].sv_get(deepcopy=True, default=[])
|
||||||
deepcopy=True, default=[]
|
|
||||||
)
|
|
||||||
if (
|
if (
|
||||||
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
|
isinstance(self.node_dict[hash(self)][self.inputs[i].name], list)
|
||||||
and input != self.node_dict[hash(self)][self.inputs[i].name]
|
and input != self.node_dict[hash(self)][self.inputs[i].name]
|
||||||
@@ -142,27 +124,18 @@ class SvIfcCreateEntity(
|
|||||||
for group in self.representations:
|
for group in self.representations:
|
||||||
try:
|
try:
|
||||||
group_representations = [
|
group_representations = [
|
||||||
[self.file.by_id(step_id) for step_id in representation]
|
[self.file.by_id(step_id) for step_id in representation] for representation in group
|
||||||
for representation in group
|
|
||||||
]
|
]
|
||||||
representations.append(group_representations)
|
representations.append(group_representations)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise
|
raise
|
||||||
names.append(
|
names.append(self.repeat_input_unique(self.names, len(group_representations)))
|
||||||
self.repeat_input_unique(self.names, len(group_representations))
|
descriptions.append(self.repeat_input_unique(self.descriptions, len(group_representations)))
|
||||||
)
|
|
||||||
descriptions.append(
|
|
||||||
self.repeat_input_unique(
|
|
||||||
self.descriptions, len(group_representations)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.representations = representations
|
self.representations = representations
|
||||||
self.names = names
|
self.names = names
|
||||||
self.descriptions = descriptions
|
self.descriptions = descriptions
|
||||||
elif not self.representations[0][0][0]:
|
elif not self.representations[0][0][0]:
|
||||||
self.descriptions = self.repeat_input_unique(
|
self.descriptions = self.repeat_input_unique(self.descriptions, len(self.names))
|
||||||
self.descriptions, len(self.names)
|
|
||||||
)
|
|
||||||
self.names = ensure_min_nesting(self.names, 2)
|
self.names = ensure_min_nesting(self.names, 2)
|
||||||
self.descriptions = ensure_min_nesting(self.descriptions, 2)
|
self.descriptions = ensure_min_nesting(self.descriptions, 2)
|
||||||
if self.node_id not in SvIfcStore.id_map:
|
if self.node_id not in SvIfcStore.id_map:
|
||||||
@@ -193,7 +166,7 @@ class SvIfcCreateEntity(
|
|||||||
self.file,
|
self.file,
|
||||||
ifc_class=self.ifc_class,
|
ifc_class=self.ifc_class,
|
||||||
name=self.names[i][j],
|
name=self.names[i][j],
|
||||||
#description=self.descriptions[i][j],
|
# description=self.descriptions[i][j],
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
for repr in self.representations[i][j]:
|
for repr in self.representations[i][j]:
|
||||||
@@ -266,9 +239,7 @@ class SvIfcCreateEntity(
|
|||||||
pass
|
pass
|
||||||
if entity.is_a() != self.ifc_class:
|
if entity.is_a() != self.ifc_class:
|
||||||
SvIfcStore.id_map[self.node_id][i].remove(step_id)
|
SvIfcStore.id_map[self.node_id][i].remove(step_id)
|
||||||
entity = ifcopenshell.util.schema.reassign_class(
|
entity = ifcopenshell.util.schema.reassign_class(self.file, entity, self.ifc_class)
|
||||||
self.file, entity, self.ifc_class
|
|
||||||
)
|
|
||||||
group_entities_ids.append(entity.id())
|
group_entities_ids.append(entity.id())
|
||||||
entities_ids.append(group_entities_ids)
|
entities_ids.append(group_entities_ids)
|
||||||
|
|
||||||
@@ -280,12 +251,10 @@ class SvIfcCreateEntity(
|
|||||||
if input[0]:
|
if input[0]:
|
||||||
if flag:
|
if flag:
|
||||||
return [
|
return [
|
||||||
[a] if not (s := sum(j == a for j in input[:i])) else [f"{a}-{s+1}"]
|
[a] if not (s := sum(j == a for j in input[:i])) else [f"{a}-{s+1}"] for i, a in enumerate(input)
|
||||||
for i, a in enumerate(input)
|
|
||||||
]
|
]
|
||||||
input = [
|
input = [
|
||||||
a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}"
|
a if not (s := sum(j == a for j in input[:i])) else f"{a}-{s+1}" for i, a in enumerate(input)
|
||||||
for i, a in enumerate(input)
|
|
||||||
] # add number to duplicates
|
] # add number to duplicates
|
||||||
return input
|
return input
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ class SvIfcCreateProject(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helpe
|
|||||||
self.outputs.new("SvVerticesSocket", "file")
|
self.outputs.new("SvVerticesSocket", "file")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
op = layout.operator(
|
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Adds project, unit and context to IFC file"
|
||||||
).tooltip = "Adds project, unit and context to IFC file"
|
)
|
||||||
# op.tooltip = self.tooltip
|
# op.tooltip = self.tooltip
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ class SvIfcCreateShape(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.
|
|||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.operator(
|
row.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Create Blender shape from IfcEntity Id. Takes one or multiple IfcEntity IDs."
|
||||||
).tooltip = "Create Blender shape from IfcEntity Id. Takes one or multiple IfcEntity IDs."
|
)
|
||||||
row.prop(self, "refresh_local", icon="FILE_REFRESH")
|
row.prop(self, "refresh_local", icon="FILE_REFRESH")
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ from sverchok.node_tree import SverchCustomTreeNode
|
|||||||
from sverchok.data_structure import updateNode, flatten_data
|
from sverchok.data_structure import updateNode, flatten_data
|
||||||
|
|
||||||
|
|
||||||
class SvIfcGetAttribute(
|
class SvIfcGetAttribute(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||||
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
|
|
||||||
):
|
|
||||||
bl_idname = "SvIfcGetAttribute"
|
bl_idname = "SvIfcGetAttribute"
|
||||||
bl_label = "IFC Get Attribute"
|
bl_label = "IFC Get Attribute"
|
||||||
entity: StringProperty(name="Entity Ids", update=updateNode)
|
entity: StringProperty(name="Entity Ids", update=updateNode)
|
||||||
@@ -40,30 +38,22 @@ class SvIfcGetAttribute(
|
|||||||
|
|
||||||
def sv_init(self, context):
|
def sv_init(self, context):
|
||||||
self.inputs.new("SvStringsSocket", "entity").prop_name = "entity"
|
self.inputs.new("SvStringsSocket", "entity").prop_name = "entity"
|
||||||
self.inputs.new(
|
self.inputs.new("SvStringsSocket", "attribute_name").prop_name = "attribute_name"
|
||||||
"SvStringsSocket", "attribute_name"
|
|
||||||
).prop_name = "attribute_name"
|
|
||||||
self.outputs.new("SvStringsSocket", "value")
|
self.outputs.new("SvStringsSocket", "value")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
|
||||||
).tooltip = (
|
|
||||||
"Get the value of an attribute of an IfcEntity. Can take multiple entities."
|
"Get the value of an attribute of an IfcEntity. Can take multiple entities."
|
||||||
)
|
)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.value_out = []
|
self.value_out = []
|
||||||
entity_nested_input_ids = flatten_data(
|
entity_nested_input_ids = flatten_data(self.inputs["entity"].sv_get(), target_level=1)
|
||||||
self.inputs["entity"].sv_get(), target_level=1
|
|
||||||
)
|
|
||||||
if not entity_nested_input_ids[0]:
|
if not entity_nested_input_ids[0]:
|
||||||
return
|
return
|
||||||
self.file = SvIfcStore.get_file()
|
self.file = SvIfcStore.get_file()
|
||||||
try:
|
try:
|
||||||
entity_nested_inputs = [
|
entity_nested_inputs = [self.file.by_id(int(step_id)) for step_id in entity_nested_input_ids]
|
||||||
self.file.by_id(int(step_id)) for step_id in entity_nested_input_ids
|
|
||||||
]
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception("Instance ID not found", e)
|
raise Exception("Instance ID not found", e)
|
||||||
attribute_name = self.inputs["attribute_name"].sv_get()[0][0]
|
attribute_name = self.inputs["attribute_name"].sv_get()[0][0]
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ from sverchok.node_tree import SverchCustomTreeNode
|
|||||||
from sverchok.data_structure import updateNode, flatten_data
|
from sverchok.data_structure import updateNode, flatten_data
|
||||||
|
|
||||||
|
|
||||||
class SvIfcGetProperty(
|
class SvIfcGetProperty(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||||
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
|
|
||||||
):
|
|
||||||
bl_idname = "SvIfcGetProperty"
|
bl_idname = "SvIfcGetProperty"
|
||||||
bl_label = "IFC Get Property"
|
bl_label = "IFC Get Property"
|
||||||
entity: StringProperty(name="Entity Ids", update=updateNode)
|
entity: StringProperty(name="Entity Ids", update=updateNode)
|
||||||
@@ -50,9 +48,7 @@ class SvIfcGetProperty(
|
|||||||
self.outputs.new("SvStringsSocket", "value")
|
self.outputs.new("SvStringsSocket", "value")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
|
||||||
).tooltip = (
|
|
||||||
"Get the value of a property of an IfcEntity. Can take multiple entity ids."
|
"Get the value of a property of an IfcEntity. Can take multiple entity ids."
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -72,9 +68,7 @@ class SvIfcGetProperty(
|
|||||||
self.value_out = []
|
self.value_out = []
|
||||||
for entity in self.entities:
|
for entity in self.entities:
|
||||||
try:
|
try:
|
||||||
self.value_out.append(
|
self.value_out.append(ifcopenshell.util.element.get_psets(entity)[pset_name][prop_name])
|
||||||
ifcopenshell.util.element.get_psets(entity)[pset_name][prop_name]
|
|
||||||
)
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self.outputs["value"].sv_set(self.value_out)
|
self.outputs["value"].sv_set(self.value_out)
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ class SvIfcQuickProjectSetup(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.h
|
|||||||
self.outputs.new("SvVerticesSocket", "file")
|
self.outputs.new("SvVerticesSocket", "file")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
op = layout.operator(
|
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Quick Project Setup: creates Ifc file and sets up a basic project"
|
||||||
).tooltip = "Quick Project Setup: creates Ifc file and sets up a basic project"
|
)
|
||||||
# op.tooltip = self.tooltip
|
# op.tooltip = self.tooltip
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ from sverchok.node_tree import SverchCustomTreeNode
|
|||||||
from sverchok.data_structure import updateNode, ensure_min_nesting, flatten_data
|
from sverchok.data_structure import updateNode, ensure_min_nesting, flatten_data
|
||||||
|
|
||||||
|
|
||||||
class SvIfcReadEntity(
|
class SvIfcReadEntity(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||||
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
|
|
||||||
):
|
|
||||||
bl_idname = "SvIfcReadEntity"
|
bl_idname = "SvIfcReadEntity"
|
||||||
bl_label = "IFC Read Entity"
|
bl_label = "IFC Read Entity"
|
||||||
entity: StringProperty(name="Entity Id", update=updateNode)
|
entity: StringProperty(name="Entity Id", update=updateNode)
|
||||||
@@ -39,9 +37,7 @@ class SvIfcReadEntity(
|
|||||||
self.outputs.new("SvStringsSocket", "is_a")
|
self.outputs.new("SvStringsSocket", "is_a")
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
layout.operator(
|
layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
|
||||||
).tooltip = (
|
|
||||||
"Decompose an IfcEntity into its attributes. Takes one entity id as input"
|
"Decompose an IfcEntity into its attributes. Takes one entity id as input"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,7 @@ from sverchok.node_tree import SverchCustomTreeNode
|
|||||||
from sverchok.data_structure import updateNode, ensure_min_nesting
|
from sverchok.data_structure import updateNode, ensure_min_nesting
|
||||||
|
|
||||||
|
|
||||||
class SvIfcSverchokToIfcRepr(
|
class SvIfcSverchokToIfcRepr(bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore):
|
||||||
bpy.types.Node, SverchCustomTreeNode, ifcsverchok.helper.SvIfcCore
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
Triggers: Sv to Ifc Repr
|
Triggers: Sv to Ifc Repr
|
||||||
Tooltip: Sverchok geometry to Ifc Shape Representation
|
Tooltip: Sverchok geometry to Ifc Shape Representation
|
||||||
@@ -85,9 +83,7 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
|
|
||||||
def sv_init(self, context):
|
def sv_init(self, context):
|
||||||
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
|
self.inputs.new("SvStringsSocket", "context_type").prop_name = "context_type"
|
||||||
self.inputs.new(
|
self.inputs.new("SvStringsSocket", "context_identifier").prop_name = "context_identifier"
|
||||||
"SvStringsSocket", "context_identifier"
|
|
||||||
).prop_name = "context_identifier"
|
|
||||||
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
|
self.inputs.new("SvStringsSocket", "target_view").prop_name = "target_view"
|
||||||
self.inputs.new("SvVerticesSocket", "Vertices")
|
self.inputs.new("SvVerticesSocket", "Vertices")
|
||||||
self.inputs.new("SvStringsSocket", "Edges")
|
self.inputs.new("SvStringsSocket", "Edges")
|
||||||
@@ -97,9 +93,9 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
self.node_dict[hash(self)] = {}
|
self.node_dict[hash(self)] = {}
|
||||||
|
|
||||||
def draw_buttons(self, context, layout):
|
def draw_buttons(self, context, layout):
|
||||||
op = layout.operator(
|
op = layout.operator("node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False).tooltip = (
|
||||||
"node.sv_ifc_tooltip", text="", icon="QUESTION", emboss=False
|
"Sverchok geometry to Ifc Shape Representation. \nTakes one or multiple geometries."
|
||||||
).tooltip = "Sverchok geometry to Ifc Shape Representation. \nTakes one or multiple geometries."
|
)
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
if not any(socket.is_linked for socket in self.inputs):
|
if not any(socket.is_linked for socket in self.inputs):
|
||||||
@@ -108,9 +104,7 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
self.sv_input_names = [i.name for i in self.inputs]
|
self.sv_input_names = [i.name for i in self.inputs]
|
||||||
|
|
||||||
if hash(self) not in self.node_dict:
|
if hash(self) not in self.node_dict:
|
||||||
self.node_dict[
|
self.node_dict[hash(self)] = {} # happens if node is already on canvas when blender loads
|
||||||
hash(self)
|
|
||||||
] = {} # happens if node is already on canvas when blender loads
|
|
||||||
if not self.node_dict[hash(self)]:
|
if not self.node_dict[hash(self)]:
|
||||||
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
|
self.node_dict[hash(self)].update(dict.fromkeys(self.sv_input_names, 0))
|
||||||
|
|
||||||
@@ -124,9 +118,7 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
edit = True
|
edit = True
|
||||||
self.node_dict[hash(self)][self.inputs[i].name] = input
|
self.node_dict[hash(self)][self.inputs[i].name] = input
|
||||||
|
|
||||||
self.vertices = ensure_min_nesting(
|
self.vertices = ensure_min_nesting(self.inputs["Vertices"].sv_get(deepcopy=False), 4)
|
||||||
self.inputs["Vertices"].sv_get(deepcopy=False), 4
|
|
||||||
)
|
|
||||||
self.edges = ensure_min_nesting(self.inputs["Edges"].sv_get(deepcopy=False), 4)
|
self.edges = ensure_min_nesting(self.inputs["Edges"].sv_get(deepcopy=False), 4)
|
||||||
self.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4)
|
self.faces = ensure_min_nesting(self.inputs["Faces"].sv_get(deepcopy=False), 4)
|
||||||
data = list(zip(self.vertices, self.edges, self.faces))
|
data = list(zip(self.vertices, self.edges, self.faces))
|
||||||
@@ -160,14 +152,12 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
faces=[list(map(tuple, item[2]))],
|
faces=[list(map(tuple, item[2]))],
|
||||||
)
|
)
|
||||||
if not representation:
|
if not representation:
|
||||||
raise Exception(
|
raise Exception("Couldn't create representation. Possibly wrong context.")
|
||||||
"Couldn't create representation. Possibly wrong context."
|
|
||||||
)
|
|
||||||
representations_ids_obj.append([representation.id()])
|
representations_ids_obj.append([representation.id()])
|
||||||
representations_ids.append(representations_ids_obj)
|
representations_ids.append(representations_ids_obj)
|
||||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
|
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Representations", []).append(
|
||||||
"Representations", []
|
representations_ids_obj
|
||||||
).append(representations_ids_obj)
|
)
|
||||||
return representations_ids
|
return representations_ids
|
||||||
|
|
||||||
def edit(self):
|
def edit(self):
|
||||||
@@ -188,13 +178,9 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
self.file, self.context_type, self.context_identifier, self.target_view
|
self.file, self.context_type, self.context_identifier, self.target_view
|
||||||
)
|
)
|
||||||
if not context:
|
if not context:
|
||||||
parent = ifcopenshell.util.representation.get_context(
|
parent = ifcopenshell.util.representation.get_context(self.file, self.context_type)
|
||||||
self.file, self.context_type
|
|
||||||
)
|
|
||||||
if not parent:
|
if not parent:
|
||||||
parent = ifcopenshell.api.run(
|
parent = ifcopenshell.api.run("context.add_context", self.file, context_type=self.context_type)
|
||||||
"context.add_context", self.file, context_type=self.context_type
|
|
||||||
)
|
|
||||||
context = ifcopenshell.api.run(
|
context = ifcopenshell.api.run(
|
||||||
"context.add_context",
|
"context.add_context",
|
||||||
self.file,
|
self.file,
|
||||||
@@ -203,9 +189,7 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
target_view=self.target_view,
|
target_view=self.target_view,
|
||||||
parent=parent,
|
parent=parent,
|
||||||
)
|
)
|
||||||
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault(
|
SvIfcStore.id_map.setdefault(self.node_id, {}).setdefault("Contexts", []).append(context.id())
|
||||||
"Contexts", []
|
|
||||||
).append(context.id())
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def sv_free(self):
|
def sv_free(self):
|
||||||
@@ -225,14 +209,10 @@ class SvIfcSverchokToIfcRepr(
|
|||||||
if not self.file.get_inverse(context):
|
if not self.file.get_inverse(context):
|
||||||
if self.file.by_id(context_id).ParentContext:
|
if self.file.by_id(context_id).ParentContext:
|
||||||
parent = self.file.by_id(context_id).ParentContext
|
parent = self.file.by_id(context_id).ParentContext
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run("context.remove_context", self.file, context=context)
|
||||||
"context.remove_context", self.file, context=context
|
|
||||||
)
|
|
||||||
if parent:
|
if parent:
|
||||||
if not self.file.get_inverse(parent):
|
if not self.file.get_inverse(parent):
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run("context.remove_context", self.file, context=parent)
|
||||||
"context.remove_context", self.file, context=parent
|
|
||||||
)
|
|
||||||
# print("Removed context with step ID: ", context_id)
|
# print("Removed context with step ID: ", context_id)
|
||||||
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
|
SvIfcStore.id_map[self.node_id]["Contexts"].remove(context_id)
|
||||||
del SvIfcStore.id_map[self.node_id]
|
del SvIfcStore.id_map[self.node_id]
|
||||||
|
|||||||
@@ -17,4 +17,5 @@
|
|||||||
# along with IfcTester. If not, see <http://www.gnu.org/licenses/>.
|
# along with IfcTester. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .ids import open
|
from .ids import open
|
||||||
|
|
||||||
__version__ = version = "0.0.0"
|
__version__ = version = "0.0.0"
|
||||||
|
|||||||
@@ -27,18 +27,10 @@ from . import reporter
|
|||||||
parser = argparse.ArgumentParser(description="Uses an IDS to audit an IFC")
|
parser = argparse.ArgumentParser(description="Uses an IDS to audit an IFC")
|
||||||
parser.add_argument("ids", type=str, help="Path to an IDS")
|
parser.add_argument("ids", type=str, help="Path to an IDS")
|
||||||
parser.add_argument("ifc", type=str, help="Path to an IFC", nargs="?")
|
parser.add_argument("ifc", type=str, help="Path to an IFC", nargs="?")
|
||||||
parser.add_argument(
|
parser.add_argument("-r", "--reporter", type=str, help="The reporting method to view audit results", default="Console")
|
||||||
"-r", "--reporter", type=str, help="The reporting method to view audit results", default="Console"
|
parser.add_argument("--no-color", help="Disable colour output (supported by Console reporting)", action="store_true")
|
||||||
)
|
parser.add_argument("--excel-safe", help="Make sure exported ODS is safely exported for Excel", action="store_true")
|
||||||
parser.add_argument(
|
parser.add_argument("-o", "--output", help="Output file (supported for all types of reporting except Console)")
|
||||||
"--no-color", help="Disable colour output (supported by Console reporting)", action="store_true"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--excel-safe", help="Make sure exported ODS is safely exported for Excel", action="store_true"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"-o", "--output", help="Output file (supported for all types of reporting except Console)"
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
specs = ids.open(args.ids)
|
specs = ids.open(args.ids)
|
||||||
|
|||||||
@@ -444,7 +444,6 @@ class Html(Json):
|
|||||||
requirement["total_omitted_passes"] = total_passed_entities - entity_limit
|
requirement["total_omitted_passes"] = total_passed_entities - entity_limit
|
||||||
requirement["has_omitted_passes"] = total_passed_entities > entity_limit
|
requirement["has_omitted_passes"] = total_passed_entities > entity_limit
|
||||||
|
|
||||||
|
|
||||||
def to_string(self) -> str:
|
def to_string(self) -> str:
|
||||||
import pystache
|
import pystache
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
from fastapi import APIRouter, Depends, UploadFile, HTTPException
|
from fastapi import APIRouter, Depends, UploadFile, HTTPException
|
||||||
from fastapi.responses import FileResponse
|
from fastapi.responses import FileResponse
|
||||||
|
|
||||||
from security.secure import get_current_active_user
|
from security.secure import get_current_active_user
|
||||||
@@ -46,38 +46,40 @@ router = APIRouter(route_class=LoggingRoute)
|
|||||||
@router.get("/bcf/3.0/projects", tags=["projects_get"])
|
@router.get("/bcf/3.0/projects", tags=["projects_get"])
|
||||||
def projects_get(current_user: User = Depends(get_current_active_user)) -> List[ProjectGET]:
|
def projects_get(current_user: User = Depends(get_current_active_user)) -> List[ProjectGET]:
|
||||||
projects_response = bcf_db.get_projects(current_user)
|
projects_response = bcf_db.get_projects(current_user)
|
||||||
bcf_db.debug(endpoint='projects_get',
|
bcf_db.debug(
|
||||||
request={},
|
endpoint="projects_get",
|
||||||
response={count: value.dict() for count, value in enumerate(projects_response)})
|
request={},
|
||||||
|
response={count: value.dict() for count, value in enumerate(projects_response)},
|
||||||
|
)
|
||||||
return projects_response
|
return projects_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}", tags=["project_get"])
|
@router.get("/bcf/3.0/projects/{project_id}", tags=["project_get"])
|
||||||
def project_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> ProjectGET:
|
def project_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> ProjectGET:
|
||||||
project_response = bcf_db.get_project(project_id, current_user)
|
project_response = bcf_db.get_project(project_id, current_user)
|
||||||
bcf_db.debug(endpoint='project_get',
|
bcf_db.debug(endpoint="project_get", request={"project_id": project_id}, response=project_response.dict())
|
||||||
request={'project_id': project_id},
|
|
||||||
response=project_response.dict())
|
|
||||||
return project_response
|
return project_response
|
||||||
|
|
||||||
|
|
||||||
@router.put("/bcf/3.0/projects/{project_id}", tags=["project_put"], status_code=200)
|
@router.put("/bcf/3.0/projects/{project_id}", tags=["project_put"], status_code=200)
|
||||||
def project_put(project_id: UUID, project_request: ProjectPUT,
|
def project_put(
|
||||||
current_user: User = Depends(get_current_active_user)) -> ProjectGET:
|
project_id: UUID, project_request: ProjectPUT, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> ProjectGET:
|
||||||
project_response = bcf_db.put_project(project_id, project_request, current_user)
|
project_response = bcf_db.put_project(project_id, project_request, current_user)
|
||||||
bcf_db.debug(endpoint='project_put',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'project_request': project_request},
|
endpoint="project_put",
|
||||||
response=project_response.dict())
|
request={"project_id": project_id, "project_request": project_request},
|
||||||
|
response=project_response.dict(),
|
||||||
|
)
|
||||||
return project_response
|
return project_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/extensions", tags=["project_extensions_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/extensions", tags=["project_extensions_get"])
|
||||||
def project_extensions_get(project_id: UUID,
|
def project_extensions_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> ExtensionsGET:
|
||||||
current_user: User = Depends(get_current_active_user)) -> ExtensionsGET:
|
|
||||||
extensions_response = bcf_db.get_project_extensions(project_id, current_user)
|
extensions_response = bcf_db.get_project_extensions(project_id, current_user)
|
||||||
bcf_db.debug(endpoint='project_extensions_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id},
|
endpoint="project_extensions_get", request={"project_id": project_id}, response=extensions_response.dict()
|
||||||
response=extensions_response.dict())
|
)
|
||||||
return extensions_response
|
return extensions_response
|
||||||
|
|
||||||
|
|
||||||
@@ -86,62 +88,68 @@ def project_extensions_get(project_id: UUID,
|
|||||||
#
|
#
|
||||||
# Topics
|
# Topics
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics", tags=["topics_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics", tags=["topics_get"])
|
||||||
def topics_get(project_id: str,
|
def topics_get(project_id: str, current_user: User = Depends(get_current_active_user)) -> List[TopicGET]:
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[TopicGET]:
|
|
||||||
topics_response = bcf_db.get_topics(project_id, current_user)
|
topics_response = bcf_db.get_topics(project_id, current_user)
|
||||||
bcf_db.debug(endpoint='topics_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id},
|
endpoint="topics_get",
|
||||||
response={count: value.dict() for count, value in enumerate(topics_response)})
|
request={"project_id": project_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(topics_response)},
|
||||||
|
)
|
||||||
return topics_response
|
return topics_response
|
||||||
|
|
||||||
|
|
||||||
@router.post("/bcf/3.0/projects/{project_id}/topics", tags=["topic_post"], status_code=201)
|
@router.post("/bcf/3.0/projects/{project_id}/topics", tags=["topic_post"], status_code=201)
|
||||||
def topic_post(project_id: UUID, topic_request: TopicPOST,
|
def topic_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
project_id: UUID, topic_request: TopicPOST, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> TopicGET:
|
||||||
topic_response = bcf_db.post_topic(project_id, topic_request, current_user)
|
topic_response = bcf_db.post_topic(project_id, topic_request, current_user)
|
||||||
if topic_response is None:
|
if topic_response is None:
|
||||||
raise HTTPException(status_code=400, detail="Could not create topic.")
|
raise HTTPException(status_code=400, detail="Could not create topic.")
|
||||||
bcf_db.debug(endpoint='topic_post',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_request': topic_request.dict()},
|
endpoint="topic_post",
|
||||||
response=topic_response.dict())
|
request={"project_id": project_id, "topic_request": topic_request.dict()},
|
||||||
|
response=topic_response.dict(),
|
||||||
|
)
|
||||||
return topic_response
|
return topic_response
|
||||||
|
|
||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_get"])
|
||||||
def topic_get(project_id: UUID, topic_id: UUID,
|
def topic_get(project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
||||||
current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
|
||||||
topic_response = bcf_db.get_topic(project_id, topic_id, current_user)
|
topic_response = bcf_db.get_topic(project_id, topic_id, current_user)
|
||||||
if topic_response is None:
|
if topic_response is None:
|
||||||
raise HTTPException(status_code=404, detail="Item not found.")
|
raise HTTPException(status_code=404, detail="Item not found.")
|
||||||
bcf_db.debug(endpoint='topic_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="topic_get", request={"project_id": project_id, "topic_id": topic_id}, response=topic_response.dict()
|
||||||
response=topic_response.dict())
|
)
|
||||||
return topic_response
|
return topic_response
|
||||||
|
|
||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_put"], status_code=200)
|
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_put"], status_code=200)
|
||||||
def topic_put(project_id: UUID, topic_id: UUID, topic_request: TopicPUT,
|
def topic_put(
|
||||||
current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
project_id: UUID, topic_id: UUID, topic_request: TopicPUT, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> TopicGET:
|
||||||
topic_response = bcf_db.put_topic(project_id, topic_id, topic_request, current_user)
|
topic_response = bcf_db.put_topic(project_id, topic_id, topic_request, current_user)
|
||||||
bcf_db.debug(endpoint='topic_put',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'topic_request': topic_request.dict()},
|
endpoint="topic_put",
|
||||||
response=topic_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id, "topic_request": topic_request.dict()},
|
||||||
|
response=topic_response.dict(),
|
||||||
|
)
|
||||||
return topic_response
|
return topic_response
|
||||||
|
|
||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.delete("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_delete"], status_code=200)
|
@router.delete("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_delete"], status_code=200)
|
||||||
def topic_delete(project_id: UUID, topic_id: UUID,
|
def topic_delete(project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)) -> int:
|
||||||
current_user: User = Depends(get_current_active_user)) -> int:
|
|
||||||
topic_response = bcf_db.delete_topic(project_id, topic_id, current_user)
|
topic_response = bcf_db.delete_topic(project_id, topic_id, current_user)
|
||||||
if topic_response is None:
|
if topic_response is None:
|
||||||
raise HTTPException(status_code=404, detail="Item not found.")
|
raise HTTPException(status_code=404, detail="Item not found.")
|
||||||
bcf_db.debug(endpoint='topic_delete',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="topic_delete", request={"project_id": project_id, "topic_id": topic_id}, response={topic_response}
|
||||||
response={topic_response})
|
)
|
||||||
return topic_response
|
return topic_response
|
||||||
|
|
||||||
|
|
||||||
@@ -153,25 +161,31 @@ def topic_delete(project_id: UUID, topic_id: UUID,
|
|||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/snippet", tags=["bim_snippet_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/snippet", tags=["bim_snippet_get"])
|
||||||
def bim_snippet_get(project_id: UUID, topic_id: UUID,
|
def bim_snippet_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> BimSnippet:
|
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> BimSnippet:
|
||||||
bim_snippet_response = bcf_db.get_bim_snippet(project_id, topic_id, current_user)
|
bim_snippet_response = bcf_db.get_bim_snippet(project_id, topic_id, current_user)
|
||||||
if bim_snippet_response is None:
|
if bim_snippet_response is None:
|
||||||
raise HTTPException(status_code=404, detail="Item not found.")
|
raise HTTPException(status_code=404, detail="Item not found.")
|
||||||
bcf_db.debug(endpoint='bim_snippet_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="bim_snippet_get",
|
||||||
response=bim_snippet_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id},
|
||||||
|
response=bim_snippet_response.dict(),
|
||||||
|
)
|
||||||
return bim_snippet_response
|
return bim_snippet_response
|
||||||
|
|
||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/snippet", tags=["bim_snippet_put"], status_code=200)
|
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/snippet", tags=["bim_snippet_put"], status_code=200)
|
||||||
def bim_snippet_put(project_id: UUID, topic_id: UUID, snippet: BimSnippet,
|
def bim_snippet_put(
|
||||||
current_user: User = Depends(get_current_active_user)) -> BimSnippet:
|
project_id: UUID, topic_id: UUID, snippet: BimSnippet, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> BimSnippet:
|
||||||
bim_snippet_response = bcf_db.put_bim_snippet(project_id, topic_id, snippet, current_user)
|
bim_snippet_response = bcf_db.put_bim_snippet(project_id, topic_id, snippet, current_user)
|
||||||
bcf_db.debug(endpoint='bim_snippet_put',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'snippet': snippet.dict()},
|
endpoint="bim_snippet_put",
|
||||||
response=bim_snippet_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id, "snippet": snippet.dict()},
|
||||||
|
response=bim_snippet_response.dict(),
|
||||||
|
)
|
||||||
return bim_snippet_response
|
return bim_snippet_response
|
||||||
|
|
||||||
|
|
||||||
@@ -182,36 +196,45 @@ def bim_snippet_put(project_id: UUID, topic_id: UUID, snippet: BimSnippet,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/files_information", tags=["files_information_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/files_information", tags=["files_information_get"])
|
||||||
def files_information_get(project_id: UUID,
|
def files_information_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[ProjectFileInformation]:
|
project_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[ProjectFileInformation]:
|
||||||
files_information_response = bcf_db.get_files_information(project_id, current_user)
|
files_information_response = bcf_db.get_files_information(project_id, current_user)
|
||||||
bcf_db.debug(endpoint='files_information_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id},
|
endpoint="files_information_get",
|
||||||
response={count: value.dict() for count, value in enumerate(files_information_response)})
|
request={"project_id": project_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(files_information_response)},
|
||||||
|
)
|
||||||
return files_information_response
|
return files_information_response
|
||||||
|
|
||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/files", tags=["files_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/files", tags=["files_get"])
|
||||||
def files_get(project_id: UUID, topic_id: UUID,
|
def files_get(project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)) -> List[FileGET]:
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[FileGET]:
|
|
||||||
files_response = bcf_db.get_files(project_id, topic_id, current_user)
|
files_response = bcf_db.get_files(project_id, topic_id, current_user)
|
||||||
bcf_db.debug(endpoint='files_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="files_get",
|
||||||
response={count: value.dict() for count, value in enumerate(files_response)})
|
request={"project_id": project_id, "topic_id": topic_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(files_response)},
|
||||||
|
)
|
||||||
return files_response
|
return files_response
|
||||||
|
|
||||||
|
|
||||||
# request body file = FilePUT
|
# request body file = FilePUT
|
||||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/files", tags=["files_put"], status_code=200)
|
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/files", tags=["files_put"], status_code=200)
|
||||||
def files_put(project_id: UUID, topic_id: UUID, files: List[FilePUT],
|
def files_put(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[FileGET]:
|
project_id: UUID, topic_id: UUID, files: List[FilePUT], current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[FileGET]:
|
||||||
files_response = bcf_db.put_files(project_id, topic_id, files, current_user)
|
files_response = bcf_db.put_files(project_id, topic_id, files, current_user)
|
||||||
bcf_db.debug(endpoint='files_put',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id,
|
endpoint="files_put",
|
||||||
'topic_id': topic_id,
|
request={
|
||||||
'files': {count: value.dict() for count, value in enumerate(files)}},
|
"project_id": project_id,
|
||||||
response={count: value.dict() for count, value in enumerate(files_response)})
|
"topic_id": topic_id,
|
||||||
|
"files": {count: value.dict() for count, value in enumerate(files)},
|
||||||
|
},
|
||||||
|
response={count: value.dict() for count, value in enumerate(files_response)},
|
||||||
|
)
|
||||||
return files_response
|
return files_response
|
||||||
|
|
||||||
|
|
||||||
@@ -222,58 +245,80 @@ def files_put(project_id: UUID, topic_id: UUID, files: List[FilePUT],
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments", tags=["comments_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments", tags=["comments_get"])
|
||||||
def comments_get(project_id: UUID, topic_id: UUID,
|
def comments_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[CommentGET]:
|
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[CommentGET]:
|
||||||
comments_response = bcf_db.get_comments(project_id, topic_id, current_user)
|
comments_response = bcf_db.get_comments(project_id, topic_id, current_user)
|
||||||
bcf_db.debug(endpoint='comments_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="comments_get",
|
||||||
response={count: value.dict() for count, value in enumerate(comments_response)})
|
request={"project_id": project_id, "topic_id": topic_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(comments_response)},
|
||||||
|
)
|
||||||
return comments_response
|
return comments_response
|
||||||
|
|
||||||
|
|
||||||
# request body comment = CommentPOST
|
# request body comment = CommentPOST
|
||||||
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments", tags=["comment_post"], status_code=201)
|
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments", tags=["comment_post"], status_code=201)
|
||||||
def comment_post(project_id: UUID, topic_id: UUID, comment: CommentPOST,
|
def comment_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> CommentGET:
|
project_id: UUID, topic_id: UUID, comment: CommentPOST, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> CommentGET:
|
||||||
comment_response = bcf_db.post_comment(project_id, topic_id, comment, current_user)
|
comment_response = bcf_db.post_comment(project_id, topic_id, comment, current_user)
|
||||||
bcf_db.debug(endpoint='comment_post',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment': comment},
|
endpoint="comment_post",
|
||||||
response=comment_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id, "comment": comment},
|
||||||
|
response=comment_response.dict(),
|
||||||
|
)
|
||||||
return comment_response
|
return comment_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_get"])
|
||||||
def comment_get(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
def comment_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> CommentGET:
|
project_id: UUID, topic_id: UUID, comment_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> CommentGET:
|
||||||
comment_response = bcf_db.get_comment(project_id, topic_id, comment_id, current_user)
|
comment_response = bcf_db.get_comment(project_id, topic_id, comment_id, current_user)
|
||||||
bcf_db.debug(endpoint='comment_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment_id': comment_id},
|
endpoint="comment_get",
|
||||||
response=comment_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id, "comment_id": comment_id},
|
||||||
|
response=comment_response.dict(),
|
||||||
|
)
|
||||||
return comment_response
|
return comment_response
|
||||||
|
|
||||||
|
|
||||||
# request body comment = CommentPUT
|
# request body comment = CommentPUT
|
||||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_put"], status_code=200)
|
@router.put(
|
||||||
def comment_put(project_id: UUID, topic_id: UUID, comment_id: UUID, comment: CommentPUT,
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_put"], status_code=200
|
||||||
current_user: User = Depends(get_current_active_user)) -> CommentGET:
|
)
|
||||||
|
def comment_put(
|
||||||
|
project_id: UUID,
|
||||||
|
topic_id: UUID,
|
||||||
|
comment_id: UUID,
|
||||||
|
comment: CommentPUT,
|
||||||
|
current_user: User = Depends(get_current_active_user),
|
||||||
|
) -> CommentGET:
|
||||||
comment_response = bcf_db.put_comment(project_id, topic_id, comment_id, comment, current_user)
|
comment_response = bcf_db.put_comment(project_id, topic_id, comment_id, comment, current_user)
|
||||||
bcf_db.debug(endpoint='comment_put',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment': comment},
|
endpoint="comment_put",
|
||||||
response=comment_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id, "comment": comment},
|
||||||
|
response=comment_response.dict(),
|
||||||
|
)
|
||||||
return comment_response
|
return comment_response
|
||||||
|
|
||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.delete("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}",
|
@router.delete(
|
||||||
tags=["comment_delete"], status_code=200)
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_delete"], status_code=200
|
||||||
def comment_delete(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
)
|
||||||
current_user: User = Depends(get_current_active_user)) -> int:
|
def comment_delete(
|
||||||
|
project_id: UUID, topic_id: UUID, comment_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> int:
|
||||||
comment_response = bcf_db.delete_comment(project_id, topic_id, comment_id, current_user)
|
comment_response = bcf_db.delete_comment(project_id, topic_id, comment_id, current_user)
|
||||||
if comment_response is None:
|
if comment_response is None:
|
||||||
raise HTTPException(status_code=404, detail="Item not found.")
|
raise HTTPException(status_code=404, detail="Item not found.")
|
||||||
bcf_db.debug(endpoint='comment_delete',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment_id': comment_id},
|
endpoint="comment_delete",
|
||||||
response={comment_response})
|
request={"project_id": project_id, "topic_id": topic_id, "comment_id": comment_id},
|
||||||
|
response={comment_response},
|
||||||
|
)
|
||||||
return comment_response
|
return comment_response
|
||||||
|
|
||||||
|
|
||||||
@@ -284,113 +329,160 @@ def comment_delete(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints", tags=["viewpoints_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints", tags=["viewpoints_get"])
|
||||||
def viewpoints_get(project_id: UUID, topic_id: UUID,
|
def viewpoints_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[ViewpointGET]:
|
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[ViewpointGET]:
|
||||||
viewpoints_response = bcf_db.get_viewpoints(project_id, topic_id, current_user)
|
viewpoints_response = bcf_db.get_viewpoints(project_id, topic_id, current_user)
|
||||||
bcf_db.debug(endpoint='viewpoints_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="viewpoints_get",
|
||||||
response={count: value.dict() for count, value in enumerate(viewpoints_response)})
|
request={"project_id": project_id, "topic_id": topic_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(viewpoints_response)},
|
||||||
|
)
|
||||||
return viewpoints_response
|
return viewpoints_response
|
||||||
|
|
||||||
|
|
||||||
# request body viewpoint = viewpointPOST
|
# request body viewpoint = viewpointPOST
|
||||||
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints", tags=["viewpoint_post"], status_code=201)
|
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints", tags=["viewpoint_post"], status_code=201)
|
||||||
def viewpoint_post(project_id: UUID, topic_id: UUID, viewpoint: ViewpointPOST,
|
def viewpoint_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> ViewpointGET:
|
project_id: UUID, topic_id: UUID, viewpoint: ViewpointPOST, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> ViewpointGET:
|
||||||
viewpoint_response = bcf_db.post_viewpoint(project_id, topic_id, viewpoint, current_user)
|
viewpoint_response = bcf_db.post_viewpoint(project_id, topic_id, viewpoint, current_user)
|
||||||
bcf_db.debug(endpoint='viewpoint_post',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint': viewpoint.dict()},
|
endpoint="viewpoint_post",
|
||||||
response=viewpoint_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint": viewpoint.dict()},
|
||||||
|
response=viewpoint_response.dict(),
|
||||||
|
)
|
||||||
return viewpoint_response
|
return viewpoint_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}", tags=["viewpoint_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}", tags=["viewpoint_get"])
|
||||||
def viewpoint_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
def viewpoint_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> ViewpointGET:
|
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> ViewpointGET:
|
||||||
viewpoint_response = bcf_db.get_viewpoint(project_id, topic_id, viewpoint_id, current_user)
|
viewpoint_response = bcf_db.get_viewpoint(project_id, topic_id, viewpoint_id, current_user)
|
||||||
bcf_db.debug(endpoint='viewpoint_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
endpoint="viewpoint_get",
|
||||||
response=viewpoint_response.dict())
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||||
|
response=viewpoint_response.dict(),
|
||||||
|
)
|
||||||
return viewpoint_response
|
return viewpoint_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/snapshot",
|
@router.get(
|
||||||
tags=["viewpoint_snapshot_get"])
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/snapshot",
|
||||||
async def viewpoint_snapshot_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
tags=["viewpoint_snapshot_get"],
|
||||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
)
|
||||||
|
async def viewpoint_snapshot_get(
|
||||||
|
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> FileResponse:
|
||||||
viewpoint_snapshot_response = bcf_db.get_viewpoint_snapshot(project_id, topic_id, viewpoint_id, current_user)
|
viewpoint_snapshot_response = bcf_db.get_viewpoint_snapshot(project_id, topic_id, viewpoint_id, current_user)
|
||||||
bcf_db.debug(endpoint='viewpoint_snapshot_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
endpoint="viewpoint_snapshot_get",
|
||||||
response=viewpoint_snapshot_response)
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||||
snapshot_name = 'snapshot_' + str(viewpoint_id)
|
response=viewpoint_snapshot_response,
|
||||||
file_ending = '.' + viewpoint_snapshot_response.split('/', 2)[1]
|
)
|
||||||
snapshot_path = 'data/snapshots/' + snapshot_name + file_ending
|
snapshot_name = "snapshot_" + str(viewpoint_id)
|
||||||
|
file_ending = "." + viewpoint_snapshot_response.split("/", 2)[1]
|
||||||
|
snapshot_path = "data/snapshots/" + snapshot_name + file_ending
|
||||||
snapshot_type = viewpoint_snapshot_response
|
snapshot_type = viewpoint_snapshot_response
|
||||||
return FileResponse(path=snapshot_path,
|
return FileResponse(path=snapshot_path, media_type=snapshot_type)
|
||||||
media_type=snapshot_type)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/bitmaps/{bitmap_id}",
|
@router.get(
|
||||||
tags=["viewpoint_bitmap_get"])
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/bitmaps/{bitmap_id}",
|
||||||
async def viewpoint_bitmap_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID, bitmap_id: UUID,
|
tags=["viewpoint_bitmap_get"],
|
||||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
)
|
||||||
|
async def viewpoint_bitmap_get(
|
||||||
|
project_id: UUID,
|
||||||
|
topic_id: UUID,
|
||||||
|
viewpoint_id: UUID,
|
||||||
|
bitmap_id: UUID,
|
||||||
|
current_user: User = Depends(get_current_active_user),
|
||||||
|
) -> FileResponse:
|
||||||
viewpoint_bitmap_response = bcf_db.get_viewpoint_bitmap(project_id, topic_id, viewpoint_id, bitmap_id, current_user)
|
viewpoint_bitmap_response = bcf_db.get_viewpoint_bitmap(project_id, topic_id, viewpoint_id, bitmap_id, current_user)
|
||||||
bcf_db.debug(endpoint='viewpoint_bitmap_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id,
|
endpoint="viewpoint_bitmap_get",
|
||||||
'viewpoint_id': viewpoint_id, 'bitmap_id': bitmap_id},
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id, "bitmap_id": bitmap_id},
|
||||||
response=viewpoint_bitmap_response.dict())
|
response=viewpoint_bitmap_response.dict(),
|
||||||
bitmap_name = 'bitmap_' + str(viewpoint_id)
|
)
|
||||||
file_ending = '.' + viewpoint_bitmap_response['bitmap_type'].split('/', 2)[1]
|
bitmap_name = "bitmap_" + str(viewpoint_id)
|
||||||
bitmap_path = 'data/bitmaps/' + bitmap_name + file_ending
|
file_ending = "." + viewpoint_bitmap_response["bitmap_type"].split("/", 2)[1]
|
||||||
bitmap_type = viewpoint_bitmap_response['bitmap_type']
|
bitmap_path = "data/bitmaps/" + bitmap_name + file_ending
|
||||||
return FileResponse(path=bitmap_path,
|
bitmap_type = viewpoint_bitmap_response["bitmap_type"]
|
||||||
media_type=bitmap_type)
|
return FileResponse(path=bitmap_path, media_type=bitmap_type)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/coloring",
|
@router.get(
|
||||||
tags=["viewpoint_colored_components_get"])
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/coloring",
|
||||||
def viewpoint_colored_components_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
tags=["viewpoint_colored_components_get"],
|
||||||
current_user: User = Depends(get_current_active_user)) -> ColoringGET:
|
)
|
||||||
viewpoint_colored_components_response = bcf_db.get_viewpoint_colored_components(project_id, topic_id, viewpoint_id, current_user)
|
def viewpoint_colored_components_get(
|
||||||
bcf_db.debug(endpoint='viewpoint_colored_components_get',
|
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
) -> ColoringGET:
|
||||||
response=viewpoint_colored_components_response.dict())
|
viewpoint_colored_components_response = bcf_db.get_viewpoint_colored_components(
|
||||||
|
project_id, topic_id, viewpoint_id, current_user
|
||||||
|
)
|
||||||
|
bcf_db.debug(
|
||||||
|
endpoint="viewpoint_colored_components_get",
|
||||||
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||||
|
response=viewpoint_colored_components_response.dict(),
|
||||||
|
)
|
||||||
return viewpoint_colored_components_response
|
return viewpoint_colored_components_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/selection",
|
@router.get(
|
||||||
tags=["viewpoint_selected_components_get"])
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/selection",
|
||||||
def viewpoint_selected_components_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
tags=["viewpoint_selected_components_get"],
|
||||||
current_user: User = Depends(get_current_active_user)) -> SelectionGET:
|
)
|
||||||
viewpoint_selected_components_response = bcf_db.get_viewpoint_selected_components(project_id, topic_id, viewpoint_id, current_user)
|
def viewpoint_selected_components_get(
|
||||||
bcf_db.debug(endpoint='viewpoint_selected_components_get',
|
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
) -> SelectionGET:
|
||||||
response=viewpoint_selected_components_response.dict())
|
viewpoint_selected_components_response = bcf_db.get_viewpoint_selected_components(
|
||||||
|
project_id, topic_id, viewpoint_id, current_user
|
||||||
|
)
|
||||||
|
bcf_db.debug(
|
||||||
|
endpoint="viewpoint_selected_components_get",
|
||||||
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||||
|
response=viewpoint_selected_components_response.dict(),
|
||||||
|
)
|
||||||
return viewpoint_selected_components_response
|
return viewpoint_selected_components_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/visibility",
|
@router.get(
|
||||||
tags=["viewpoint_components_visibility_get"])
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/visibility",
|
||||||
def viewpoint_components_visibility_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
tags=["viewpoint_components_visibility_get"],
|
||||||
current_user: User = Depends(get_current_active_user)) -> VisibilityGET:
|
)
|
||||||
viewpoint_components_visibility_response = bcf_db.get_viewpoint_components_visibility(project_id, topic_id, viewpoint_id, current_user)
|
def viewpoint_components_visibility_get(
|
||||||
bcf_db.debug(endpoint='viewpoint_components_visibility_get',
|
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
) -> VisibilityGET:
|
||||||
response=viewpoint_components_visibility_response.dict())
|
viewpoint_components_visibility_response = bcf_db.get_viewpoint_components_visibility(
|
||||||
|
project_id, topic_id, viewpoint_id, current_user
|
||||||
|
)
|
||||||
|
bcf_db.debug(
|
||||||
|
endpoint="viewpoint_components_visibility_get",
|
||||||
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||||
|
response=viewpoint_components_visibility_response.dict(),
|
||||||
|
)
|
||||||
return viewpoint_components_visibility_response
|
return viewpoint_components_visibility_response
|
||||||
|
|
||||||
|
|
||||||
# Implemented
|
# Implemented
|
||||||
@router.delete("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
|
@router.delete(
|
||||||
tags=["viewpoint_delete"], status_code=200)
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
|
||||||
def viewpoint_delete(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
tags=["viewpoint_delete"],
|
||||||
current_user: User = Depends(get_current_active_user)) -> int:
|
status_code=200,
|
||||||
|
)
|
||||||
|
def viewpoint_delete(
|
||||||
|
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> int:
|
||||||
viewpoint_response = bcf_db.delete_viewpoint(project_id, topic_id, viewpoint_id, current_user)
|
viewpoint_response = bcf_db.delete_viewpoint(project_id, topic_id, viewpoint_id, current_user)
|
||||||
if viewpoint_response is None:
|
if viewpoint_response is None:
|
||||||
raise HTTPException(status_code=404, detail="Item not found.")
|
raise HTTPException(status_code=404, detail="Item not found.")
|
||||||
bcf_db.debug(endpoint='viewpoint_delete',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
endpoint="viewpoint_delete",
|
||||||
response={viewpoint_response})
|
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||||
|
response={viewpoint_response},
|
||||||
|
)
|
||||||
return viewpoint_response
|
return viewpoint_response
|
||||||
|
|
||||||
|
|
||||||
@@ -401,24 +493,38 @@ def viewpoint_delete(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/related_topics", tags=["related_topics_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/related_topics", tags=["related_topics_get"])
|
||||||
def related_topics_get(project_id: UUID, topic_id: UUID,
|
def related_topics_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[RelatedTopicGET]:
|
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[RelatedTopicGET]:
|
||||||
related_topics_response = bcf_db.get_related_topics(project_id, topic_id, current_user)
|
related_topics_response = bcf_db.get_related_topics(project_id, topic_id, current_user)
|
||||||
bcf_db.debug(endpoint='related_topics_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="related_topics_get",
|
||||||
response={count: value.dict() for count, value in enumerate(related_topics_response)})
|
request={"project_id": project_id, "topic_id": topic_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(related_topics_response)},
|
||||||
|
)
|
||||||
return related_topics_response
|
return related_topics_response
|
||||||
|
|
||||||
|
|
||||||
# request body related_topic = RelatedTopicPUT
|
# request body related_topic = RelatedTopicPUT
|
||||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/related_topics", tags=["related_topics_put"], status_code=200)
|
@router.put(
|
||||||
def related_topics_put(project_id: UUID, topic_id: UUID, related_topics: List[RelatedTopicPUT],
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/related_topics", tags=["related_topics_put"], status_code=200
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[RelatedTopicGET]:
|
)
|
||||||
|
def related_topics_put(
|
||||||
|
project_id: UUID,
|
||||||
|
topic_id: UUID,
|
||||||
|
related_topics: List[RelatedTopicPUT],
|
||||||
|
current_user: User = Depends(get_current_active_user),
|
||||||
|
) -> List[RelatedTopicGET]:
|
||||||
related_topics_response = bcf_db.put_related_topics(project_id, topic_id, related_topics, current_user)
|
related_topics_response = bcf_db.put_related_topics(project_id, topic_id, related_topics, current_user)
|
||||||
bcf_db.debug(endpoint='related_topics_put',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id,
|
endpoint="related_topics_put",
|
||||||
'related_topics': {count: value.dict() for count, value in enumerate(related_topics)}},
|
request={
|
||||||
response={count: value.dict() for count, value in enumerate(related_topics_response)})
|
"project_id": project_id,
|
||||||
|
"topic_id": topic_id,
|
||||||
|
"related_topics": {count: value.dict() for count, value in enumerate(related_topics)},
|
||||||
|
},
|
||||||
|
response={count: value.dict() for count, value in enumerate(related_topics_response)},
|
||||||
|
)
|
||||||
return related_topics_response
|
return related_topics_response
|
||||||
|
|
||||||
|
|
||||||
@@ -428,51 +534,70 @@ def related_topics_put(project_id: UUID, topic_id: UUID, related_topics: List[Re
|
|||||||
# Document references <- from topic
|
# Document references <- from topic
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references",
|
@router.get(
|
||||||
tags=["topic_document_references_get"])
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references", tags=["topic_document_references_get"]
|
||||||
def topic_document_references_get(project_id: UUID, topic_id: UUID,
|
)
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[DocumentReferenceGET]:
|
def topic_document_references_get(
|
||||||
|
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[DocumentReferenceGET]:
|
||||||
topic_document_references_response = bcf_db.get_topic_document_references(project_id, topic_id, current_user)
|
topic_document_references_response = bcf_db.get_topic_document_references(project_id, topic_id, current_user)
|
||||||
bcf_db.debug(endpoint='topic_document_references_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="topic_document_references_get",
|
||||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)})
|
request={"project_id": project_id, "topic_id": topic_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(topic_document_references_response)},
|
||||||
|
)
|
||||||
return topic_document_references_response
|
return topic_document_references_response
|
||||||
|
|
||||||
|
|
||||||
# request body document_reference = DocumentReferencePOST
|
# request body document_reference = DocumentReferencePOST
|
||||||
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references",
|
@router.post(
|
||||||
tags=["topic_document_references_post"],
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references",
|
||||||
status_code=201)
|
tags=["topic_document_references_post"],
|
||||||
def topic_document_reference_post(project_id: UUID, topic_id: UUID, document_reference: DocumentReferencePOST,
|
status_code=201,
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentReferenceGET:
|
)
|
||||||
topic_document_references_response = bcf_db.post_topic_document_references(project_id,
|
def topic_document_reference_post(
|
||||||
topic_id,
|
project_id: UUID,
|
||||||
document_reference,
|
topic_id: UUID,
|
||||||
current_user)
|
document_reference: DocumentReferencePOST,
|
||||||
bcf_db.debug(endpoint='topic_document_references_post',
|
current_user: User = Depends(get_current_active_user),
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'document_reference': document_reference},
|
) -> DocumentReferenceGET:
|
||||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)})
|
topic_document_references_response = bcf_db.post_topic_document_references(
|
||||||
|
project_id, topic_id, document_reference, current_user
|
||||||
|
)
|
||||||
|
bcf_db.debug(
|
||||||
|
endpoint="topic_document_references_post",
|
||||||
|
request={"project_id": project_id, "topic_id": topic_id, "document_reference": document_reference},
|
||||||
|
response={count: value.dict() for count, value in enumerate(topic_document_references_response)},
|
||||||
|
)
|
||||||
return topic_document_references_response
|
return topic_document_references_response
|
||||||
|
|
||||||
|
|
||||||
# request body document_reference = DocumentReferencePUT
|
# request body document_reference = DocumentReferencePUT
|
||||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references/{reference_id}",
|
@router.put(
|
||||||
tags=["topic_document_references_put"],
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references/{reference_id}",
|
||||||
status_code=200)
|
tags=["topic_document_references_put"],
|
||||||
def topic_document_references_put(project_id: UUID, topic_id: UUID, reference_id: UUID,
|
status_code=200,
|
||||||
document_reference: DocumentReferencePUT,
|
)
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentReferenceGET:
|
def topic_document_references_put(
|
||||||
topic_document_references_response = bcf_db.put_topic_document_references(project_id,
|
project_id: UUID,
|
||||||
topic_id,
|
topic_id: UUID,
|
||||||
reference_id,
|
reference_id: UUID,
|
||||||
document_reference,
|
document_reference: DocumentReferencePUT,
|
||||||
current_user)
|
current_user: User = Depends(get_current_active_user),
|
||||||
bcf_db.debug(endpoint='topic_document_references_put',
|
) -> DocumentReferenceGET:
|
||||||
request={'project_id': project_id,
|
topic_document_references_response = bcf_db.put_topic_document_references(
|
||||||
'topic_id': topic_id,
|
project_id, topic_id, reference_id, document_reference, current_user
|
||||||
'reference_id': reference_id,
|
)
|
||||||
'document_reference': document_reference.dict()},
|
bcf_db.debug(
|
||||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)})
|
endpoint="topic_document_references_put",
|
||||||
|
request={
|
||||||
|
"project_id": project_id,
|
||||||
|
"topic_id": topic_id,
|
||||||
|
"reference_id": reference_id,
|
||||||
|
"document_reference": document_reference.dict(),
|
||||||
|
},
|
||||||
|
response={count: value.dict() for count, value in enumerate(topic_document_references_response)},
|
||||||
|
)
|
||||||
return topic_document_references_response
|
return topic_document_references_response
|
||||||
|
|
||||||
|
|
||||||
@@ -485,30 +610,34 @@ def topic_document_references_put(project_id: UUID, topic_id: UUID, reference_id
|
|||||||
@router.get("/bcf/3.0/projects/{project_id}/documents", tags=["documents_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/documents", tags=["documents_get"])
|
||||||
def documents_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> List[DocumentGET]:
|
def documents_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> List[DocumentGET]:
|
||||||
documents_response = bcf_db.get_documents(project_id, current_user)
|
documents_response = bcf_db.get_documents(project_id, current_user)
|
||||||
bcf_db.debug(endpoint='documents_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id},
|
endpoint="documents_get",
|
||||||
response={count: value.dict() for count, value in enumerate(documents_response)})
|
request={"project_id": project_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(documents_response)},
|
||||||
|
)
|
||||||
return documents_response
|
return documents_response
|
||||||
|
|
||||||
|
|
||||||
# request body file = UploadFile
|
# request body file = UploadFile
|
||||||
@router.post("/bcf/3.0/projects/{project_id}/documents", tags=["document_post"], status_code=201)
|
@router.post("/bcf/3.0/projects/{project_id}/documents", tags=["document_post"], status_code=201)
|
||||||
async def document_post(project_id: UUID, file: UploadFile,
|
async def document_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentGET:
|
project_id: UUID, file: UploadFile, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentGET:
|
||||||
document_response = bcf_db.post_document(project_id, file, current_user)
|
document_response = bcf_db.post_document(project_id, file, current_user)
|
||||||
bcf_db.debug(endpoint='document_post',
|
bcf_db.debug(endpoint="document_post", request={"project_id": project_id}, response=document_response.dict())
|
||||||
request={'project_id': project_id},
|
|
||||||
response=document_response.dict())
|
|
||||||
return document_response
|
return document_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/documents/{document_id}", tags=["document_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/documents/{document_id}", tags=["document_get"])
|
||||||
def document_get(project_id: UUID, document_id: UUID,
|
def document_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentGET:
|
project_id: UUID, document_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentGET:
|
||||||
document_response = bcf_db.get_document(project_id, document_id, current_user)
|
document_response = bcf_db.get_document(project_id, document_id, current_user)
|
||||||
bcf_db.debug(endpoint='document_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'document_id': document_id},
|
endpoint="document_get",
|
||||||
response=document_response.dict())
|
request={"project_id": project_id, "document_id": document_id},
|
||||||
|
response=document_response.dict(),
|
||||||
|
)
|
||||||
return document_response
|
return document_response
|
||||||
|
|
||||||
|
|
||||||
@@ -520,22 +649,26 @@ def document_get(project_id: UUID, document_id: UUID,
|
|||||||
|
|
||||||
# ...
|
# ...
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/events", tags=["topics_events_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/events", tags=["topics_events_get"])
|
||||||
def topics_events_get(project_id: UUID,
|
def topics_events_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> List[TopicEventGET]:
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[TopicEventGET]:
|
|
||||||
topic_events_response = bcf_db.get_topics_events(project_id, current_user)
|
topic_events_response = bcf_db.get_topics_events(project_id, current_user)
|
||||||
bcf_db.debug(endpoint='topics_events_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id},
|
endpoint="topics_events_get",
|
||||||
response={count: value.dict() for count, value in enumerate(topic_events_response)})
|
request={"project_id": project_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(topic_events_response)},
|
||||||
|
)
|
||||||
return topic_events_response
|
return topic_events_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/events", tags=["topic_events_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/events", tags=["topic_events_get"])
|
||||||
def topic_events_get(project_id: UUID, topic_id: UUID,
|
def topic_events_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[TopicEventGET]:
|
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[TopicEventGET]:
|
||||||
topic_events_response = bcf_db.get_topic_events(project_id, topic_id, current_user)
|
topic_events_response = bcf_db.get_topic_events(project_id, topic_id, current_user)
|
||||||
bcf_db.debug(endpoint='topic_events_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id},
|
endpoint="topic_events_get",
|
||||||
response={count: value.dict() for count, value in enumerate(topic_events_response)})
|
request={"project_id": project_id, "topic_id": topic_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(topic_events_response)},
|
||||||
|
)
|
||||||
return topic_events_response
|
return topic_events_response
|
||||||
|
|
||||||
|
|
||||||
@@ -546,21 +679,28 @@ def topic_events_get(project_id: UUID, topic_id: UUID,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/comments/events", tags=["comments_events_get"])
|
@router.get("/bcf/3.0/projects/{project_id}/topics/comments/events", tags=["comments_events_get"])
|
||||||
def comments_events_get(project_id: UUID,
|
def comments_events_get(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[CommentEventGET]:
|
project_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[CommentEventGET]:
|
||||||
comments_events_response = bcf_db.get_comments_events(project_id, current_user)
|
comments_events_response = bcf_db.get_comments_events(project_id, current_user)
|
||||||
bcf_db.debug(endpoint='comments_events_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id},
|
endpoint="comments_events_get",
|
||||||
response={count: value.dict() for count, value in enumerate(comments_events_response)})
|
request={"project_id": project_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(comments_events_response)},
|
||||||
|
)
|
||||||
return comments_events_response
|
return comments_events_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}/events",
|
@router.get(
|
||||||
tags=["comment_events_get"])
|
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}/events", tags=["comment_events_get"]
|
||||||
def comment_events_get(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
)
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[CommentEventGET]:
|
def comment_events_get(
|
||||||
|
project_id: UUID, topic_id: UUID, comment_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[CommentEventGET]:
|
||||||
comment_events_response = bcf_db.get_comment_events(project_id, topic_id, comment_id, current_user)
|
comment_events_response = bcf_db.get_comment_events(project_id, topic_id, comment_id, current_user)
|
||||||
bcf_db.debug(endpoint='comment_events_get',
|
bcf_db.debug(
|
||||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment_id': comment_id},
|
endpoint="comment_events_get",
|
||||||
response={count: value.dict() for count, value in enumerate(comment_events_response)})
|
request={"project_id": project_id, "topic_id": topic_id, "comment_id": comment_id},
|
||||||
|
response={count: value.dict() for count, value in enumerate(comment_events_response)},
|
||||||
|
)
|
||||||
return comment_events_response
|
return comment_events_response
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@@ -6,7 +5,7 @@ import traceback
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from fastapi import HTTPException, status, APIRouter, Request, Depends
|
from fastapi import HTTPException, status, APIRouter, Request, Depends
|
||||||
from fastapi import UploadFile, Form
|
from fastapi import UploadFile, Form
|
||||||
from fastapi.responses import FileResponse, HTMLResponse
|
from fastapi.responses import FileResponse, HTMLResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
@@ -87,12 +86,15 @@ templates = Jinja2Templates(directory="templates")
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/upload-documents", tags=[""])
|
@router.post("/documents/1.0/upload-documents", tags=[""])
|
||||||
def upload_documents_post(upload_documents: UploadDocuments,
|
def upload_documents_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentUploadSessionInitialization:
|
upload_documents: UploadDocuments, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentUploadSessionInitialization:
|
||||||
post_upload_documents_response = doc_db.post_upload_documents(upload_documents, current_user)
|
post_upload_documents_response = doc_db.post_upload_documents(upload_documents, current_user)
|
||||||
doc_db.debug(endpoint='upload_documents_post',
|
doc_db.debug(
|
||||||
request={'upload_documents': upload_documents},
|
endpoint="upload_documents_post",
|
||||||
response=post_upload_documents_response.dict())
|
request={"upload_documents": upload_documents},
|
||||||
|
response=post_upload_documents_response.dict(),
|
||||||
|
)
|
||||||
return post_upload_documents_response
|
return post_upload_documents_response
|
||||||
|
|
||||||
|
|
||||||
@@ -101,20 +103,23 @@ def upload_documents_post(upload_documents: UploadDocuments,
|
|||||||
def upload_documents_get(request: Request, upload_session: UUID):
|
def upload_documents_get(request: Request, upload_session: UUID):
|
||||||
|
|
||||||
data_for_upload_documents = doc_db.get_data_for_upload_documents(upload_session)
|
data_for_upload_documents = doc_db.get_data_for_upload_documents(upload_session)
|
||||||
print('Data for site: ', data_for_upload_documents)
|
print("Data for site: ", data_for_upload_documents)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
'upload_files.html',
|
"upload_files.html",
|
||||||
{'request': request,
|
{
|
||||||
'upload_session': upload_session,
|
"request": request,
|
||||||
'username': data_for_upload_documents.current_user.username,
|
"upload_session": upload_session,
|
||||||
'email': data_for_upload_documents.current_user.email,
|
"username": data_for_upload_documents.current_user.username,
|
||||||
'full_name': data_for_upload_documents.current_user.full_name,
|
"email": data_for_upload_documents.current_user.email,
|
||||||
'server_context': data_for_upload_documents.server_context,
|
"full_name": data_for_upload_documents.current_user.full_name,
|
||||||
'callback_url': data_for_upload_documents.callback.url,
|
"server_context": data_for_upload_documents.server_context,
|
||||||
'callback_expires_in': data_for_upload_documents.callback.expires_in,
|
"callback_url": data_for_upload_documents.callback.url,
|
||||||
'documents': data_for_upload_documents.documents,
|
"callback_expires_in": data_for_upload_documents.callback.expires_in,
|
||||||
'projects': data_for_upload_documents.projects})
|
"documents": data_for_upload_documents.documents,
|
||||||
|
"projects": data_for_upload_documents.projects,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/save-metadata-for-documents", tags=[""])
|
@router.post("/documents/1.0/save-metadata-for-documents", tags=[""])
|
||||||
@@ -127,29 +132,29 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
|||||||
print(form_data_json)
|
print(form_data_json)
|
||||||
|
|
||||||
documents = collections.defaultdict(dict)
|
documents = collections.defaultdict(dict)
|
||||||
names = ('session_file_id', 'document', 'title', 'version_number', 'filename')
|
names = ("session_file_id", "document", "title", "version_number", "filename")
|
||||||
|
|
||||||
for whole_form_key, value in form_data_json.items():
|
for whole_form_key, value in form_data_json.items():
|
||||||
if whole_form_key.startswith(names):
|
if whole_form_key.startswith(names):
|
||||||
start_form_key, document_id = whole_form_key.split("@", 1)
|
start_form_key, document_id = whole_form_key.split("@", 1)
|
||||||
print('New field: ', start_form_key, ' for document id: ', document_id)
|
print("New field: ", start_form_key, " for document id: ", document_id)
|
||||||
documents[document_id][start_form_key] = value
|
documents[document_id][start_form_key] = value
|
||||||
|
|
||||||
print("Documents: ")
|
print("Documents: ")
|
||||||
print(documents)
|
print(documents)
|
||||||
|
|
||||||
username = form_data_json['username']
|
username = form_data_json["username"]
|
||||||
upload_session = form_data_json['upload_session']
|
upload_session = form_data_json["upload_session"]
|
||||||
server_context = form_data_json['server_context']
|
server_context = form_data_json["server_context"]
|
||||||
callback_url = form_data_json['callback_url']
|
callback_url = form_data_json["callback_url"]
|
||||||
callback_expires_in = form_data_json['callback_expires_in']
|
callback_expires_in = form_data_json["callback_expires_in"]
|
||||||
project = form_data_json['project']
|
project = form_data_json["project"]
|
||||||
|
|
||||||
documents_saved = list()
|
documents_saved = list()
|
||||||
|
|
||||||
for key in documents:
|
for key in documents:
|
||||||
try:
|
try:
|
||||||
documents[key]['project'] = project
|
documents[key]["project"] = project
|
||||||
document = DocumentMetadata(**documents[key])
|
document = DocumentMetadata(**documents[key])
|
||||||
save_metadata_response = doc_db.save_metadata_for_documents(document, upload_session, username)
|
save_metadata_response = doc_db.save_metadata_for_documents(document, upload_session, username)
|
||||||
documents_saved.append(save_metadata_response)
|
documents_saved.append(save_metadata_response)
|
||||||
@@ -157,9 +162,11 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
|||||||
print(e)
|
print(e)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
doc_db.debug(endpoint='save_metadata_for_documents_post',
|
doc_db.debug(
|
||||||
request={'documents': documents},
|
endpoint="save_metadata_for_documents_post",
|
||||||
response={'response': documents_saved})
|
request={"documents": documents},
|
||||||
|
response={"response": documents_saved},
|
||||||
|
)
|
||||||
|
|
||||||
return documents_saved
|
return documents_saved
|
||||||
|
|
||||||
@@ -167,22 +174,30 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
|||||||
# http://localhost:8080/cde-callback-example?upload_documents_url=
|
# http://localhost:8080/cde-callback-example?upload_documents_url=
|
||||||
# https%3A%2F%2Fcde.example.com%2Fupload-instructions%3Fupload_session%3Dee56b8f3-8f93-4819-976e-46a45a5a996f
|
# https%3A%2F%2Fcde.example.com%2Fupload-instructions%3Fupload_session%3Dee56b8f3-8f93-4819-976e-46a45a5a996f
|
||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/upload-instructions", tags=[""])
|
@router.post("/documents/1.0/upload-instructions", tags=[""])
|
||||||
def upload_instructions(session_id: str, server_context: str, upload_files: UploadFileDetails,
|
def upload_instructions(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentsToUpload:
|
session_id: str,
|
||||||
|
server_context: str,
|
||||||
|
upload_files: UploadFileDetails,
|
||||||
|
current_user: User = Depends(get_current_active_user),
|
||||||
|
) -> DocumentsToUpload:
|
||||||
documents_to_upload_model = DocumentsToUpload()
|
documents_to_upload_model = DocumentsToUpload()
|
||||||
documents_to_upload_model.server_context = server_context
|
documents_to_upload_model.server_context = server_context
|
||||||
documents_to_upload_model.documents_to_upload = list()
|
documents_to_upload_model.documents_to_upload = list()
|
||||||
for upload_file in upload_files.files:
|
for upload_file in upload_files.files:
|
||||||
get_upload_instructions_response = doc_db.get_upload_instructions(session_id, server_context, upload_file, current_user)
|
get_upload_instructions_response = doc_db.get_upload_instructions(
|
||||||
doc_db.debug(endpoint='upload_instructions',
|
session_id, server_context, upload_file, current_user
|
||||||
request={'session_id': session_id,
|
)
|
||||||
'server_context': server_context,
|
doc_db.debug(
|
||||||
'document': upload_file},
|
endpoint="upload_instructions",
|
||||||
response=get_upload_instructions_response.dict())
|
request={"session_id": session_id, "server_context": server_context, "document": upload_file},
|
||||||
|
response=get_upload_instructions_response.dict(),
|
||||||
|
)
|
||||||
documents_to_upload_model.documents_to_upload.append(get_upload_instructions_response)
|
documents_to_upload_model.documents_to_upload.append(get_upload_instructions_response)
|
||||||
return documents_to_upload_model
|
return documents_to_upload_model
|
||||||
|
|
||||||
|
|
||||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||||
# summary: 'Upload a single file part'
|
# summary: 'Upload a single file part'
|
||||||
#
|
#
|
||||||
@@ -206,8 +221,7 @@ def upload_instructions(session_id: str, server_context: str, upload_files: Uplo
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/upload-part/{part_id}", tags=[""])
|
@router.post("/documents/1.0/upload-part/{part_id}", tags=[""])
|
||||||
async def upload_part(part_id: str, request: Request,
|
async def upload_part(part_id: str, request: Request, current_user: User = Depends(get_current_active_user)):
|
||||||
current_user: User = Depends(get_current_active_user)):
|
|
||||||
|
|
||||||
# file_name = doc_db.safe_path(part_id)
|
# file_name = doc_db.safe_path(part_id)
|
||||||
file_name = part_id
|
file_name = part_id
|
||||||
@@ -222,33 +236,31 @@ async def upload_part(part_id: str, request: Request,
|
|||||||
|
|
||||||
# try to receive the uploaded part
|
# try to receive the uploaded part
|
||||||
try:
|
try:
|
||||||
print('File contents: ', request_body)
|
print("File contents: ", request_body)
|
||||||
|
|
||||||
# use document_id instead as dir_name
|
# use document_id instead as dir_name
|
||||||
# dir_name = doc_db.safe_path(document.document_id)
|
# dir_name = doc_db.safe_path(document.document_id)
|
||||||
dir_name = document.document_id
|
dir_name = document.document_id
|
||||||
|
|
||||||
path = './data/document_parts/' + dir_name + '/'
|
path = "./data/document_parts/" + dir_name + "/"
|
||||||
|
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
|
|
||||||
with open(path + file_name, 'wb') as f:
|
with open(path + file_name, "wb") as f:
|
||||||
f.write(request_body)
|
f.write(request_body)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
print('Error uploading file')
|
print("Error uploading file")
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
print('Error uploading file')
|
print("Error uploading file")
|
||||||
print(sys.exc_info()[2])
|
print(sys.exc_info()[2])
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# We will write to the database, information about part successfully uploaded.
|
# We will write to the database, information about part successfully uploaded.
|
||||||
doc_db.mark_part_as_uploaded(part_id, current_user)
|
doc_db.mark_part_as_uploaded(part_id, current_user)
|
||||||
|
|
||||||
doc_db.debug(endpoint='upload-part',
|
doc_db.debug(endpoint="upload-part", request={"part_id": part_id}, response={"uploaded": True})
|
||||||
request={'part_id': part_id},
|
|
||||||
response={'uploaded': True})
|
|
||||||
|
|
||||||
return {"message": f"Successfully uploaded part {file_name}"}
|
return {"message": f"Successfully uploaded part {file_name}"}
|
||||||
|
|
||||||
@@ -269,9 +281,11 @@ async def upload_part(part_id: str, request: Request,
|
|||||||
# /server-provided-path-document-upload-cancellation
|
# /server-provided-path-document-upload-cancellation
|
||||||
# description: This operation should be called to cancel the upload
|
# description: This operation should be called to cancel the upload
|
||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/upload-completion", tags=[""])
|
@router.post("/documents/1.0/upload-completion", tags=[""])
|
||||||
def upload_completion(upload_session: str,
|
def upload_completion(
|
||||||
current_user: User = Depends(get_current_active_user)) -> Union[DocumentVersion, bool]:
|
upload_session: str, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> Union[DocumentVersion, bool]:
|
||||||
|
|
||||||
# check if all parts really are marked as uploaded in database
|
# check if all parts really are marked as uploaded in database
|
||||||
# retrieve document_id, file_type, file_ending, and parts_id (in order)
|
# retrieve document_id, file_type, file_ending, and parts_id (in order)
|
||||||
@@ -280,23 +294,23 @@ def upload_completion(upload_session: str,
|
|||||||
raise HTTPException(status_code=400, detail="All parts not uploaded.")
|
raise HTTPException(status_code=400, detail="All parts not uploaded.")
|
||||||
|
|
||||||
parts = doc_db.retrieve_uploaded_parts(upload_session, current_user)
|
parts = doc_db.retrieve_uploaded_parts(upload_session, current_user)
|
||||||
print('Number of parts: ' + str(len(parts)))
|
print("Number of parts: " + str(len(parts)))
|
||||||
document = doc_db.get_document_from_session(upload_session, current_user)
|
document = doc_db.get_document_from_session(upload_session, current_user)
|
||||||
|
|
||||||
# check if all parts really are uploaded to document_id-dir
|
# check if all parts really are uploaded to document_id-dir
|
||||||
document_name = doc_db.safe_path(document.document_id)
|
document_name = doc_db.safe_path(document.document_id)
|
||||||
|
|
||||||
path = './data/document_parts/' + document_name + '/'
|
path = "./data/document_parts/" + document_name + "/"
|
||||||
|
|
||||||
for part in parts:
|
for part in parts:
|
||||||
part = doc_db.safe_path(part)
|
part = doc_db.safe_path(part)
|
||||||
print('Checking for part ' + part + ' in dir ' + path)
|
print("Checking for part " + part + " in dir " + path)
|
||||||
|
|
||||||
if not os.path.isfile(path + part):
|
if not os.path.isfile(path + part):
|
||||||
print(part + ' is not in dir ' + path)
|
print(part + " is not in dir " + path)
|
||||||
raise HTTPException(status_code=400, detail="All parts not in dir.")
|
raise HTTPException(status_code=400, detail="All parts not in dir.")
|
||||||
else:
|
else:
|
||||||
print(part + ' is in dir ' + path)
|
print(part + " is in dir " + path)
|
||||||
|
|
||||||
# merge parts to a new temporary document
|
# merge parts to a new temporary document
|
||||||
temp_doc_path = path
|
temp_doc_path = path
|
||||||
@@ -304,14 +318,14 @@ def upload_completion(upload_session: str,
|
|||||||
if not os.path.exists(temp_doc_path):
|
if not os.path.exists(temp_doc_path):
|
||||||
os.makedirs(temp_doc_path)
|
os.makedirs(temp_doc_path)
|
||||||
|
|
||||||
new_doc_path = './data/documents/'
|
new_doc_path = "./data/documents/"
|
||||||
new_doc_path_name = new_doc_path + document.file_description.name
|
new_doc_path_name = new_doc_path + document.file_description.name
|
||||||
|
|
||||||
# Read parts and write to temp doc.
|
# Read parts and write to temp doc.
|
||||||
with open(temp_doc_file_name, 'ab') as temp_doc:
|
with open(temp_doc_file_name, "ab") as temp_doc:
|
||||||
for part in parts:
|
for part in parts:
|
||||||
part = doc_db.safe_path(part)
|
part = doc_db.safe_path(part)
|
||||||
with open(temp_doc_path + part, 'rb') as part_doc:
|
with open(temp_doc_path + part, "rb") as part_doc:
|
||||||
temp_doc.write(part_doc.read())
|
temp_doc.write(part_doc.read())
|
||||||
|
|
||||||
# move document to new location in documents dir
|
# move document to new location in documents dir
|
||||||
@@ -329,13 +343,12 @@ def upload_completion(upload_session: str,
|
|||||||
# get DocumentVersion
|
# get DocumentVersion
|
||||||
document = doc_db.get_document_version(document.document_id, document.version_index, current_user)
|
document = doc_db.get_document_version(document.document_id, document.version_index, current_user)
|
||||||
|
|
||||||
doc_db.debug(endpoint='upload_completion',
|
doc_db.debug(endpoint="upload_completion", request={"upload_session": upload_session}, response=document.dict())
|
||||||
request={'upload_session': upload_session},
|
|
||||||
response=document.dict())
|
|
||||||
return document
|
return document
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||||
# summary: 'Cancel the upload of a single file'
|
# summary: 'Cancel the upload of a single file'
|
||||||
#
|
#
|
||||||
@@ -355,14 +368,14 @@ def upload_cancellation(upload_session: str, current_user: User = Depends(get_cu
|
|||||||
|
|
||||||
# clean temp dir
|
# clean temp dir
|
||||||
document_name = doc_db.safe_path(document.document_id)
|
document_name = doc_db.safe_path(document.document_id)
|
||||||
path = './data/document_parts/' + document_name + '/'
|
path = "./data/document_parts/" + document_name + "/"
|
||||||
shutil.rmtree(path)
|
shutil.rmtree(path)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
print('Upload cancellation complete.')
|
print("Upload cancellation complete.")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -399,17 +412,17 @@ def upload_cancellation(upload_session: str, current_user: User = Depends(get_cu
|
|||||||
# that has been flagged to have a new version in the response.
|
# that has been flagged to have a new version in the response.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/document-versions", tags=[""])
|
@router.post("/documents/1.0/document-versions", tags=[""])
|
||||||
def document_versions_post(document_ids: List[UUID],
|
def document_versions_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> List[DocumentVersion]:
|
document_ids: List[UUID], current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> List[DocumentVersion]:
|
||||||
|
|
||||||
document_versions = list()
|
document_versions = list()
|
||||||
for document_id in document_ids:
|
for document_id in document_ids:
|
||||||
document_versions.append(doc_db.get_document_version(document_id, 1, current_user))
|
document_versions.append(doc_db.get_document_version(document_id, 1, current_user))
|
||||||
|
|
||||||
doc_db.debug(endpoint='document_versions_post',
|
doc_db.debug(endpoint="document_versions_post", request={document_ids}, response={document_versions})
|
||||||
request={document_ids},
|
|
||||||
response={document_versions})
|
|
||||||
|
|
||||||
return document_versions
|
return document_versions
|
||||||
|
|
||||||
@@ -460,12 +473,15 @@ def document_versions_post(document_ids: List[UUID],
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/select-documents", tags=[""])
|
@router.post("/documents/1.0/select-documents", tags=[""])
|
||||||
def select_documents_post(select_documents: SelectDocuments,
|
def select_documents_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentDiscoverySessionInitialization:
|
select_documents: SelectDocuments, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentDiscoverySessionInitialization:
|
||||||
post_select_documents_response = doc_db.post_select_documents(select_documents, current_user)
|
post_select_documents_response = doc_db.post_select_documents(select_documents, current_user)
|
||||||
doc_db.debug(endpoint='select_documents_post',
|
doc_db.debug(
|
||||||
request={'select_documents': select_documents},
|
endpoint="select_documents_post",
|
||||||
response=post_select_documents_response.dict())
|
request={"select_documents": select_documents},
|
||||||
|
response=post_select_documents_response.dict(),
|
||||||
|
)
|
||||||
print("Returns ", post_select_documents_response)
|
print("Returns ", post_select_documents_response)
|
||||||
return post_select_documents_response
|
return post_select_documents_response
|
||||||
|
|
||||||
@@ -490,19 +506,22 @@ def select_documents_post(select_documents: SelectDocuments,
|
|||||||
|
|
||||||
# documents/1.0/document-selection?selection_session=7cf3dd70-c880-4fb1-9897-f60472959533
|
# documents/1.0/document-selection?selection_session=7cf3dd70-c880-4fb1-9897-f60472959533
|
||||||
|
|
||||||
|
|
||||||
@router.get("/documents/1.0/document-selection", tags=[""], response_class=HTMLResponse)
|
@router.get("/documents/1.0/document-selection", tags=[""], response_class=HTMLResponse)
|
||||||
def selected_documents_get(request: Request,
|
def selected_documents_get(request: Request, selection_session: UUID):
|
||||||
selection_session: UUID):
|
|
||||||
data_for_document_selection = doc_db.get_data_for_document_selection(selection_session)
|
data_for_document_selection = doc_db.get_data_for_document_selection(selection_session)
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
'select_files.html',
|
"select_files.html",
|
||||||
{'request': request,
|
{
|
||||||
'selection_session': selection_session,
|
"request": request,
|
||||||
'current_user': data_for_document_selection.current_user,
|
"selection_session": selection_session,
|
||||||
'server_context': data_for_document_selection.server_context,
|
"current_user": data_for_document_selection.current_user,
|
||||||
'callback_url': data_for_document_selection.callback.url,
|
"server_context": data_for_document_selection.server_context,
|
||||||
'callback_expires_in': data_for_document_selection.callback.expires_in,
|
"callback_url": data_for_document_selection.callback.url,
|
||||||
'projects': data_for_document_selection.projects})
|
"callback_expires_in": data_for_document_selection.callback.expires_in,
|
||||||
|
"projects": data_for_document_selection.projects,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/mark-documents-as-selected", tags=[""])
|
@router.post("/documents/1.0/mark-documents-as-selected", tags=[""])
|
||||||
@@ -516,45 +535,52 @@ async def mark_documents_as_selected_post(request: Request) -> DocumentsMarkedAs
|
|||||||
|
|
||||||
documents = list()
|
documents = list()
|
||||||
for key, value in form_data_json.items():
|
for key, value in form_data_json.items():
|
||||||
if 'document_' in key:
|
if "document_" in key:
|
||||||
document_id = key.split("ocument_", 1)[1]
|
document_id = key.split("ocument_", 1)[1]
|
||||||
documents.append(document_id)
|
documents.append(document_id)
|
||||||
|
|
||||||
print("Sends ", documents)
|
print("Sends ", documents)
|
||||||
|
|
||||||
get_selected_response = doc_db.post_mark_documents_as_selected(documents, form_data_json['selection_session'])
|
get_selected_response = doc_db.post_mark_documents_as_selected(documents, form_data_json["selection_session"])
|
||||||
doc_db.debug(endpoint='mark_some_documents_as_selected_post',
|
doc_db.debug(
|
||||||
request={'documents': documents,
|
endpoint="mark_some_documents_as_selected_post",
|
||||||
'form_data_json[selection_session]': form_data_json['selection_session']},
|
request={"documents": documents, "form_data_json[selection_session]": form_data_json["selection_session"]},
|
||||||
response=get_selected_response.dict())
|
response=get_selected_response.dict(),
|
||||||
|
)
|
||||||
|
|
||||||
return get_selected_response
|
return get_selected_response
|
||||||
|
|
||||||
|
|
||||||
@router.get("/documents/1.0/download-instructions", tags=[""])
|
@router.get("/documents/1.0/download-instructions", tags=[""])
|
||||||
def download_instructions(session_id: UUID, server_context: str,
|
def download_instructions(
|
||||||
current_user: User = Depends(get_current_active_user)) -> SelectedDocuments:
|
session_id: UUID, server_context: str, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> SelectedDocuments:
|
||||||
get_download_instructions_response = doc_db.get_download_instructions(session_id, server_context, current_user)
|
get_download_instructions_response = doc_db.get_download_instructions(session_id, server_context, current_user)
|
||||||
doc_db.debug(endpoint='download_instructions',
|
doc_db.debug(
|
||||||
request={'session_id': session_id,
|
endpoint="download_instructions",
|
||||||
'server_context': server_context},
|
request={"session_id": session_id, "server_context": server_context},
|
||||||
response=get_download_instructions_response.dict())
|
response=get_download_instructions_response.dict(),
|
||||||
|
)
|
||||||
return get_download_instructions_response
|
return get_download_instructions_response
|
||||||
|
|
||||||
|
|
||||||
# download links
|
# download links
|
||||||
|
|
||||||
|
|
||||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}", tags=[""])
|
@router.get("/documents/1.0/document/{document_id}/version/{version_index}", tags=[""])
|
||||||
def document_version(document_id: str, version_index: int,
|
def document_version(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentVersion:
|
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentVersion:
|
||||||
# This endpoint returns the document version model itself.
|
# This endpoint returns the document version model itself.
|
||||||
get_document_version = doc_db.get_document_version(document_id, version_index, current_user)
|
get_document_version = doc_db.get_document_version(document_id, version_index, current_user)
|
||||||
doc_db.debug(endpoint='document_version',
|
doc_db.debug(
|
||||||
request={'document_id': document_id,
|
endpoint="document_version",
|
||||||
'version_index': version_index},
|
request={"document_id": document_id, "version_index": version_index},
|
||||||
response=get_document_version.dict())
|
response=get_document_version.dict(),
|
||||||
|
)
|
||||||
return get_document_version
|
return get_document_version
|
||||||
|
|
||||||
|
|
||||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||||
# summary: 'Get document metadata for a single document'
|
# summary: 'Get document metadata for a single document'
|
||||||
#
|
#
|
||||||
@@ -573,16 +599,21 @@ def document_version(document_id: str, version_index: int,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/metadata", tags=[""])
|
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/metadata", tags=[""])
|
||||||
def document_version_metadata(document_id: str, version_index: int,
|
def document_version_metadata(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentMetadataEntries:
|
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentMetadataEntries:
|
||||||
# The metadata for document versions is a list of key-value pairs
|
# The metadata for document versions is a list of key-value pairs
|
||||||
get_document_version_metadata_result = doc_db.get_document_version_metadata(document_id, version_index, current_user)
|
get_document_version_metadata_result = doc_db.get_document_version_metadata(
|
||||||
doc_db.debug(endpoint='document_version',
|
document_id, version_index, current_user
|
||||||
request={'document_id': document_id,
|
)
|
||||||
'version_index': version_index},
|
doc_db.debug(
|
||||||
response=get_document_version_metadata_result.dict())
|
endpoint="document_version",
|
||||||
|
request={"document_id": document_id, "version_index": version_index},
|
||||||
|
response=get_document_version_metadata_result.dict(),
|
||||||
|
)
|
||||||
return get_document_version_metadata_result
|
return get_document_version_metadata_result
|
||||||
|
|
||||||
|
|
||||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||||
# summary: 'Download the document'
|
# summary: 'Download the document'
|
||||||
#
|
#
|
||||||
@@ -601,47 +632,48 @@ def document_version_metadata(document_id: str, version_index: int,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/download", tags=[""])
|
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/download", tags=[""])
|
||||||
def document_version_download(document_id: str, version_index: int,
|
def document_version_download(
|
||||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> FileResponse:
|
||||||
# The url to download the binary content of this document version.
|
# The url to download the binary content of this document version.
|
||||||
# May either directly return the result or redirect to a storage provider
|
# May either directly return the result or redirect to a storage provider
|
||||||
keep_characters = (' ', '.', '_', '-')
|
keep_characters = (" ", ".", "_", "-")
|
||||||
document_id = "".join(c for c in document_id if c.isalnum() or c in keep_characters).rstrip()
|
document_id = "".join(c for c in document_id if c.isalnum() or c in keep_characters).rstrip()
|
||||||
file_location = './data/documents/' + document_id + '.ifc'
|
file_location = "./data/documents/" + document_id + ".ifc"
|
||||||
return FileResponse(file_location,
|
return FileResponse(
|
||||||
media_type='application/x-step',
|
file_location, media_type="application/x-step", filename="6dbd4d52-14db-11ee-be56-0242ac120002.ifc"
|
||||||
filename='6dbd4d52-14db-11ee-be56-0242ac120002.ifc')
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/versions", tags=[""])
|
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/versions", tags=[""])
|
||||||
def document_versions(document_id: str, version_index: int,
|
def document_versions(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentVersions:
|
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentVersions:
|
||||||
# This url returns a list of all document versions for the parent document.
|
# This url returns a list of all document versions for the parent document.
|
||||||
# The client can use this URL to monitor for new document versions
|
# The client can use this URL to monitor for new document versions
|
||||||
get_document_versions_result = doc_db.get_document_versions(document_id, current_user)
|
get_document_versions_result = doc_db.get_document_versions(document_id, current_user)
|
||||||
doc_db.debug(endpoint='document_version',
|
doc_db.debug(
|
||||||
request={'document_id': document_id},
|
endpoint="document_version", request={"document_id": document_id}, response=get_document_versions_result.dict()
|
||||||
response=get_document_versions_result.dict())
|
)
|
||||||
return get_document_versions_result
|
return get_document_versions_result
|
||||||
|
|
||||||
|
|
||||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/details", tags=[""],
|
@router.get(
|
||||||
response_class=HTMLResponse)
|
"/documents/1.0/document/{document_id}/version/{version_index}/details", tags=[""], response_class=HTMLResponse
|
||||||
def document_version_details(request: Request,
|
)
|
||||||
document_id: str,
|
def document_version_details(
|
||||||
version_index: int,
|
request: Request, document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||||
current_user: User = Depends(get_current_active_user)):
|
):
|
||||||
# This url returns a list of all document versions for the parent document.
|
# This url returns a list of all document versions for the parent document.
|
||||||
# The client can use this URL to monitor for new document versions
|
# The client can use this URL to monitor for new document versions
|
||||||
details = doc_db.get_document_version(document_id, version_index, current_user)
|
details = doc_db.get_document_version(document_id, version_index, current_user)
|
||||||
doc_db.debug(endpoint='document_version',
|
doc_db.debug(
|
||||||
request={'document_id': document_id,
|
endpoint="document_version",
|
||||||
'version_index': version_index},
|
request={"document_id": document_id, "version_index": version_index},
|
||||||
response=details.dict())
|
response=details.dict(),
|
||||||
return templates.TemplateResponse(
|
)
|
||||||
'document_details.html',
|
return templates.TemplateResponse("document_details.html", {"request": request, "details": details})
|
||||||
{'request': request,
|
|
||||||
'details': details})
|
|
||||||
|
|
||||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||||
# summary: 'Get the versions of a single document'
|
# summary: 'Get the versions of a single document'
|
||||||
@@ -699,7 +731,9 @@ def document_version_details(request: Request,
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/documents/1.0/upload_file_to_project", tags=[""])
|
@router.post("/documents/1.0/upload_file_to_project", tags=[""])
|
||||||
async def upload_documents_post(file: UploadFile, project: str = Form(...), selection_session: str = Form(...)) -> Document:
|
async def upload_documents_post(
|
||||||
|
file: UploadFile, project: str = Form(...), selection_session: str = Form(...)
|
||||||
|
) -> Document:
|
||||||
|
|
||||||
# Get the file size (in bytes)
|
# Get the file size (in bytes)
|
||||||
file.file.seek(0, 2)
|
file.file.seek(0, 2)
|
||||||
@@ -713,49 +747,46 @@ async def upload_documents_post(file: UploadFile, project: str = Form(...), sele
|
|||||||
|
|
||||||
# Find file name ending and create new storage file name
|
# Find file name ending and create new storage file name
|
||||||
if file.filename.lower().endswith(tuple(file_types)):
|
if file.filename.lower().endswith(tuple(file_types)):
|
||||||
file_ending = file.filename.split('.')[-1].lower()
|
file_ending = file.filename.split(".")[-1].lower()
|
||||||
name = document_id + '.' + file_ending
|
name = document_id + "." + file_ending
|
||||||
else:
|
else:
|
||||||
file_ending = ''
|
file_ending = ""
|
||||||
name = document_id
|
name = document_id
|
||||||
|
|
||||||
# Get mime type and file type
|
# Get mime type and file type
|
||||||
mime_type = ''
|
mime_type = ""
|
||||||
file_type = ''
|
file_type = ""
|
||||||
if hasattr(file_types, file_ending):
|
if hasattr(file_types, file_ending):
|
||||||
mime_type = file_types[file_ending]['mime_type']
|
mime_type = file_types[file_ending]["mime_type"]
|
||||||
file_type = file_types[file_ending]['file_type']
|
file_type = file_types[file_ending]["file_type"]
|
||||||
|
|
||||||
# Create document data
|
# Create document data
|
||||||
document_version_dict = {
|
document_version_dict = {
|
||||||
'document_id': document_id,
|
"document_id": document_id,
|
||||||
'session_file_id': '',
|
"session_file_id": "",
|
||||||
'version_index': 1,
|
"version_index": 1,
|
||||||
'version_number': '1',
|
"version_number": "1",
|
||||||
'creation_date': doc_db.timestamp(),
|
"creation_date": doc_db.timestamp(),
|
||||||
'title': file.filename,
|
"title": file.filename,
|
||||||
'original_file_name': file.filename,
|
"original_file_name": file.filename,
|
||||||
'file_ending': file_ending,
|
"file_ending": file_ending,
|
||||||
'mime_type': mime_type,
|
"mime_type": mime_type,
|
||||||
'file_type': file_type,
|
"file_type": file_type,
|
||||||
'project': project,
|
"project": project,
|
||||||
'file_description': {
|
"file_description": {"name": name, "size_in_bytes": file_size},
|
||||||
'name': name,
|
|
||||||
'size_in_bytes': file_size
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document_version_model = Document(**document_version_dict)
|
document_version_model = Document(**document_version_dict)
|
||||||
|
|
||||||
# Save file to disc
|
# Save file to disc
|
||||||
upload_directory = './data/documents/'
|
upload_directory = "./data/documents/"
|
||||||
destination_path = os.path.join(upload_directory, name)
|
destination_path = os.path.join(upload_directory, name)
|
||||||
with open(destination_path, 'wb') as buffer:
|
with open(destination_path, "wb") as buffer:
|
||||||
shutil.copyfileobj(file.file, buffer)
|
shutil.copyfileobj(file.file, buffer)
|
||||||
|
|
||||||
# create database record
|
# create database record
|
||||||
inserted_document = doc_db.create_node_for_uploaded_file(selection_session, project, document_version_model)
|
inserted_document = doc_db.create_node_for_uploaded_file(selection_session, project, document_version_model)
|
||||||
print('Created node for document id: ' + str(inserted_document.document_id))
|
print("Created node for document id: " + str(inserted_document.document_id))
|
||||||
doc_db.create_ifc_graph_for_document(inserted_document.document_id)
|
doc_db.create_ifc_graph_for_document(inserted_document.document_id)
|
||||||
|
|
||||||
# return document version of database record
|
# return document version of database record
|
||||||
|
|||||||
@@ -28,11 +28,10 @@ authorization_code = None
|
|||||||
templates = Jinja2Templates(directory="templates")
|
templates = Jinja2Templates(directory="templates")
|
||||||
|
|
||||||
clients = {
|
clients = {
|
||||||
os.environ['KONTROLL_CLIENT_ID']:
|
os.environ["KONTROLL_CLIENT_ID"]: {
|
||||||
{
|
"name": os.environ["KONTROLL_CLIENT_NAME"],
|
||||||
'name': os.environ['KONTROLL_CLIENT_NAME'],
|
"secret": secrets["kontroll_client_secret"],
|
||||||
'secret': secrets['kontroll_client_secret']
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||||
@@ -60,21 +59,25 @@ clients = {
|
|||||||
@router.get("/foundation/versions", tags=["api_versions_get"])
|
@router.get("/foundation/versions", tags=["api_versions_get"])
|
||||||
def api_versions_get():
|
def api_versions_get():
|
||||||
return {
|
return {
|
||||||
"versions": [{
|
"versions": [
|
||||||
"api_id": "foundation",
|
{
|
||||||
"version_id": "1.0",
|
"api_id": "foundation",
|
||||||
"detailed_version": "https://github.com/BuildingSMART/foundation-API/tree/release_1_0"
|
"version_id": "1.0",
|
||||||
}, {
|
"detailed_version": "https://github.com/BuildingSMART/foundation-API/tree/release_1_0",
|
||||||
"api_id": "bcf",
|
},
|
||||||
"version_id": "3.0",
|
{
|
||||||
"detailed_version": "https://github.com/buildingSMART/BCF-API/tree/release_3_0",
|
"api_id": "bcf",
|
||||||
"api_base_url": os.environ['KONTROLL_BASE_URL'] + "bcf/3.0"
|
"version_id": "3.0",
|
||||||
}, {
|
"detailed_version": "https://github.com/buildingSMART/BCF-API/tree/release_3_0",
|
||||||
"api_id": "documents",
|
"api_base_url": os.environ["KONTROLL_BASE_URL"] + "bcf/3.0",
|
||||||
"version_id": "1.0",
|
},
|
||||||
"detailed_version": "https://github.com/buildingSMART/documents-API/tree/release_1_0",
|
{
|
||||||
"api_base_url": os.environ['KONTROLL_BASE_URL'] + "documents/1.0"
|
"api_id": "documents",
|
||||||
}]
|
"version_id": "1.0",
|
||||||
|
"detailed_version": "https://github.com/buildingSMART/documents-API/tree/release_1_0",
|
||||||
|
"api_base_url": os.environ["KONTROLL_BASE_URL"] + "documents/1.0",
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -95,18 +98,15 @@ def api_versions_get():
|
|||||||
# is not supported by the server.
|
# is not supported by the server.
|
||||||
|
|
||||||
|
|
||||||
@router.get("/foundation/1.0/auth",
|
@router.get("/foundation/1.0/auth", tags=["foundation_auth_get"])
|
||||||
tags=["foundation_auth_get"])
|
|
||||||
def authentication_get():
|
def authentication_get():
|
||||||
|
|
||||||
return_variable = {
|
return_variable = {
|
||||||
"oauth2_auth_url": os.environ['KONTROLL_BASE_URL'] + "foundation/oauth2/auth",
|
"oauth2_auth_url": os.environ["KONTROLL_BASE_URL"] + "foundation/oauth2/auth",
|
||||||
"oauth2_token_url": os.environ['KONTROLL_BASE_URL'] + "foundation/oauth2/token",
|
"oauth2_token_url": os.environ["KONTROLL_BASE_URL"] + "foundation/oauth2/token",
|
||||||
# "oauth2_dynamic_client_reg_url": os.environ['KONTROLL_BASE_URL'] + "foundation/oauth2/reg",
|
# "oauth2_dynamic_client_reg_url": os.environ['KONTROLL_BASE_URL'] + "foundation/oauth2/reg",
|
||||||
"http_basic_supported": True,
|
"http_basic_supported": True,
|
||||||
"supported_oauth2_flows": [
|
"supported_oauth2_flows": ["authorization_code_grant"],
|
||||||
"authorization_code_grant"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
print(return_variable)
|
print(return_variable)
|
||||||
return return_variable
|
return return_variable
|
||||||
@@ -135,23 +135,25 @@ def authentication_get():
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/foundation/oauth2/auth", response_class=HTMLResponse)
|
@router.get("/foundation/oauth2/auth", response_class=HTMLResponse)
|
||||||
def authorization(request: Request,
|
def authorization(
|
||||||
response_type: str,
|
request: Request,
|
||||||
client_id: str,
|
response_type: str,
|
||||||
state: str,
|
client_id: str,
|
||||||
scope: str,
|
state: str,
|
||||||
redirect_uri: str,
|
scope: str,
|
||||||
):
|
redirect_uri: str,
|
||||||
|
):
|
||||||
|
|
||||||
client_name = clients[client_id]['name']
|
client_name = clients[client_id]["name"]
|
||||||
|
|
||||||
print(f"Response type: {response_type}, "
|
print(
|
||||||
f"Client_id: {client_id}, "
|
f"Response type: {response_type}, "
|
||||||
f"Client_name: {client_name}, "
|
f"Client_id: {client_id}, "
|
||||||
f"State: {state}, "
|
f"Client_name: {client_name}, "
|
||||||
f"Scope: {scope},"
|
f"State: {state}, "
|
||||||
f"Redirect_URI: {redirect_uri}."
|
f"Scope: {scope},"
|
||||||
)
|
f"Redirect_URI: {redirect_uri}."
|
||||||
|
)
|
||||||
|
|
||||||
# 3. Solibri sends the user to oauth2_auth_url with the following parameters:
|
# 3. Solibri sends the user to oauth2_auth_url with the following parameters:
|
||||||
# response_type=code, client_id=solibri_test_001, state=..., redirect_uri=uri, scope=...
|
# response_type=code, client_id=solibri_test_001, state=..., redirect_uri=uri, scope=...
|
||||||
@@ -159,38 +161,41 @@ def authorization(request: Request,
|
|||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
"login.html",
|
"login.html",
|
||||||
{"request": request,
|
{
|
||||||
"response_type": response_type,
|
"request": request,
|
||||||
"client_id": client_id,
|
"response_type": response_type,
|
||||||
"client_name": client_name,
|
"client_id": client_id,
|
||||||
"state": state,
|
"client_name": client_name,
|
||||||
"scope": scope,
|
"state": state,
|
||||||
"redirect_uri": redirect_uri,
|
"scope": scope,
|
||||||
})
|
"redirect_uri": redirect_uri,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/foundation/oauth2/code")
|
@router.get("/foundation/oauth2/code")
|
||||||
def code(username: str,
|
def code(
|
||||||
password: str,
|
username: str,
|
||||||
response_type: str,
|
password: str,
|
||||||
client_id,
|
response_type: str,
|
||||||
client_name,
|
client_id,
|
||||||
state: str,
|
client_name,
|
||||||
redirect_uri: str,
|
state: str,
|
||||||
scope: str = ''
|
redirect_uri: str,
|
||||||
):
|
scope: str = "",
|
||||||
|
):
|
||||||
|
|
||||||
global oauth2_state
|
global oauth2_state
|
||||||
oauth2_state = state
|
oauth2_state = state
|
||||||
|
|
||||||
print('Username: ' + username + '. Password: ' + password)
|
print("Username: " + username + ". Password: " + password)
|
||||||
user = authenticate_user(username, password)
|
user = authenticate_user(username, password)
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
detail="Incorrect username or password",
|
detail="Incorrect username or password",
|
||||||
headers={"WWW-Authenticate": "Bearer"}
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
)
|
)
|
||||||
|
|
||||||
# The user is signed in, now the main purpose of this function is to generate the authorization code.
|
# The user is signed in, now the main purpose of this function is to generate the authorization code.
|
||||||
@@ -242,36 +247,35 @@ def code(username: str,
|
|||||||
# POST https://example.com/foundation/oauth2/token?grant_type=authorization_code&code=<your_authorization_code>
|
# POST https://example.com/foundation/oauth2/token?grant_type=authorization_code&code=<your_authorization_code>
|
||||||
|
|
||||||
|
|
||||||
@router.post("/foundation/oauth2/token",
|
@router.post("/foundation/oauth2/token", tags=["login_for_access_token_post"], status_code=201)
|
||||||
tags=["login_for_access_token_post"],
|
|
||||||
status_code=201)
|
|
||||||
def login_for_access_token(
|
def login_for_access_token(
|
||||||
grant_type: Optional[str] = Form(None),
|
grant_type: Optional[str] = Form(None),
|
||||||
refresh_token: Optional[str] = Form(None),
|
refresh_token: Optional[str] = Form(None),
|
||||||
code: Optional[str] = Form(None),
|
code: Optional[str] = Form(None),
|
||||||
credentials: HTTPBasicCredentials = Depends(http_basic)):
|
credentials: HTTPBasicCredentials = Depends(http_basic),
|
||||||
|
):
|
||||||
|
|
||||||
print('grant_type: ', grant_type)
|
print("grant_type: ", grant_type)
|
||||||
print('refresh_token: ', refresh_token)
|
print("refresh_token: ", refresh_token)
|
||||||
print('code: ', code)
|
print("code: ", code)
|
||||||
print('credentials: ', credentials)
|
print("credentials: ", credentials)
|
||||||
|
|
||||||
# The API should check that the credentials (client_id and client_secret) are correct
|
# The API should check that the credentials (client_id and client_secret) are correct
|
||||||
# credentials.username contains the client_id
|
# credentials.username contains the client_id
|
||||||
# credentials.password contains the client_secret
|
# credentials.password contains the client_secret
|
||||||
if credentials.username not in clients or credentials.password != clients[credentials.username]['secret']:
|
if credentials.username not in clients or credentials.password != clients[credentials.username]["secret"]:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
detail="Incorrect client_id or client_secret",
|
detail="Incorrect client_id or client_secret",
|
||||||
)
|
)
|
||||||
|
|
||||||
if grant_type == 'authorization_code':
|
if grant_type == "authorization_code":
|
||||||
# use authorization code,
|
# use authorization code,
|
||||||
# create access token and refresh token,
|
# create access token and refresh token,
|
||||||
# delete authorization code
|
# delete authorization code
|
||||||
user_info = foundation_db.use_authorization_code(code)
|
user_info = foundation_db.use_authorization_code(code)
|
||||||
|
|
||||||
elif grant_type == 'refresh_token':
|
elif grant_type == "refresh_token":
|
||||||
# use refresh token to get access token
|
# use refresh token to get access token
|
||||||
# delete old access token and old refresh token
|
# delete old access token and old refresh token
|
||||||
# create new access token and a new refresh token
|
# create new access token and a new refresh token
|
||||||
@@ -279,8 +283,8 @@ def login_for_access_token(
|
|||||||
user_info = foundation_db.use_refresh_token(refresh_token)
|
user_info = foundation_db.use_refresh_token(refresh_token)
|
||||||
|
|
||||||
user_info.token_type = "Bearer"
|
user_info.token_type = "Bearer"
|
||||||
user_info.expires_in = int(os.environ['SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS'])
|
user_info.expires_in = int(os.environ["SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS"])
|
||||||
print('user_info: ', user_info)
|
print("user_info: ", user_info)
|
||||||
return user_info
|
return user_info
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import httpx
|
|||||||
|
|
||||||
|
|
||||||
def log_info(req_body, res_body, route_url):
|
def log_info(req_body, res_body, route_url):
|
||||||
logging.info('request:' + route_url + ':' + str(req_body))
|
logging.info("request:" + route_url + ":" + str(req_body))
|
||||||
logging.info('response:' + route_url + ':' + str(res_body))
|
logging.info("response:" + route_url + ":" + str(res_body))
|
||||||
|
|
||||||
|
|
||||||
class LoggingRoute(APIRoute):
|
class LoggingRoute(APIRoute):
|
||||||
@@ -22,21 +22,26 @@ class LoggingRoute(APIRoute):
|
|||||||
response = await original_route_handler(request)
|
response = await original_route_handler(request)
|
||||||
route_url = str(request.url)
|
route_url = str(request.url)
|
||||||
if isinstance(response, StreamingResponse):
|
if isinstance(response, StreamingResponse):
|
||||||
res_body = b''
|
res_body = b""
|
||||||
async for item in response.body_iterator:
|
async for item in response.body_iterator:
|
||||||
res_body += item
|
res_body += item
|
||||||
task = BackgroundTask(log_info, req_body, res_body, route_url)
|
task = BackgroundTask(log_info, req_body, res_body, route_url)
|
||||||
return Response(content=res_body, status_code=response.status_code,
|
return Response(
|
||||||
headers=dict(response.headers), media_type=response.media_type, background=task)
|
content=res_body,
|
||||||
|
status_code=response.status_code,
|
||||||
|
headers=dict(response.headers),
|
||||||
|
media_type=response.media_type,
|
||||||
|
background=task,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if hasattr(response, 'body'):
|
if hasattr(response, "body"):
|
||||||
res_body = response.body
|
res_body = response.body
|
||||||
else:
|
else:
|
||||||
res_body = {'no response': True}
|
res_body = {"no response": True}
|
||||||
response.background = BackgroundTask(log_info, req_body, res_body, route_url)
|
response.background = BackgroundTask(log_info, req_body, res_body, route_url)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
return custom_route_handler
|
return custom_route_handler
|
||||||
|
|
||||||
|
|
||||||
logging.basicConfig(filename='logs/info.log', level=logging.DEBUG)
|
logging.basicConfig(filename="logs/info.log", level=logging.DEBUG)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from fastapi import APIRouter, Request, Depends
|
from fastapi import APIRouter, Request, Depends
|
||||||
from fastapi.responses import FileResponse, HTMLResponse
|
from fastapi.responses import FileResponse, HTMLResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
@@ -30,13 +29,17 @@ templates = Jinja2Templates(directory="templates")
|
|||||||
# UPLOAD FLOW
|
# UPLOAD FLOW
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
|
|
||||||
@router.post("/user/1.0/upload-documents", tags=[""])
|
@router.post("/user/1.0/upload-documents", tags=[""])
|
||||||
def upload_documents_post(upload_documents: UploadDocuments,
|
def upload_documents_post(
|
||||||
current_user: User = Depends(get_current_active_user)) -> DocumentUploadSessionInitialization:
|
upload_documents: UploadDocuments, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> DocumentUploadSessionInitialization:
|
||||||
post_upload_documents_response = doc_db.post_upload_documents(upload_documents, current_user)
|
post_upload_documents_response = doc_db.post_upload_documents(upload_documents, current_user)
|
||||||
doc_db.debug(endpoint='upload_documents_post',
|
doc_db.debug(
|
||||||
request={'upload_documents': upload_documents},
|
endpoint="upload_documents_post",
|
||||||
response=post_upload_documents_response.dict())
|
request={"upload_documents": upload_documents},
|
||||||
|
response=post_upload_documents_response.dict(),
|
||||||
|
)
|
||||||
return post_upload_documents_response
|
return post_upload_documents_response
|
||||||
|
|
||||||
|
|
||||||
@@ -45,20 +48,23 @@ def upload_documents_post(upload_documents: UploadDocuments,
|
|||||||
def upload_documents_get(request: Request, upload_session: UUID):
|
def upload_documents_get(request: Request, upload_session: UUID):
|
||||||
|
|
||||||
data_for_upload_documents = doc_db.get_data_for_upload_documents(upload_session)
|
data_for_upload_documents = doc_db.get_data_for_upload_documents(upload_session)
|
||||||
print('Data for site: ', data_for_upload_documents)
|
print("Data for site: ", data_for_upload_documents)
|
||||||
|
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
'upload_files.html',
|
"upload_files.html",
|
||||||
{'request': request,
|
{
|
||||||
'upload_session': upload_session,
|
"request": request,
|
||||||
'username': data_for_upload_documents.current_user.username,
|
"upload_session": upload_session,
|
||||||
'email': data_for_upload_documents.current_user.email,
|
"username": data_for_upload_documents.current_user.username,
|
||||||
'full_name': data_for_upload_documents.current_user.full_name,
|
"email": data_for_upload_documents.current_user.email,
|
||||||
'server_context': data_for_upload_documents.server_context,
|
"full_name": data_for_upload_documents.current_user.full_name,
|
||||||
'callback_url': data_for_upload_documents.callback.url,
|
"server_context": data_for_upload_documents.server_context,
|
||||||
'callback_expires_in': data_for_upload_documents.callback.expires_in,
|
"callback_url": data_for_upload_documents.callback.url,
|
||||||
'documents': data_for_upload_documents.documents,
|
"callback_expires_in": data_for_upload_documents.callback.expires_in,
|
||||||
'projects': data_for_upload_documents.projects})
|
"documents": data_for_upload_documents.documents,
|
||||||
|
"projects": data_for_upload_documents.projects,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/user/1.0/save-metadata-for-documents", tags=[""])
|
@router.post("/user/1.0/save-metadata-for-documents", tags=[""])
|
||||||
@@ -71,29 +77,29 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
|||||||
print(form_data_json)
|
print(form_data_json)
|
||||||
|
|
||||||
documents = collections.defaultdict(dict)
|
documents = collections.defaultdict(dict)
|
||||||
names = ('session_file_id', 'document', 'title', 'version_number', 'filename')
|
names = ("session_file_id", "document", "title", "version_number", "filename")
|
||||||
|
|
||||||
for whole_form_key, value in form_data_json.items():
|
for whole_form_key, value in form_data_json.items():
|
||||||
if whole_form_key.startswith(names):
|
if whole_form_key.startswith(names):
|
||||||
start_form_key, document_id = whole_form_key.split("@", 1)
|
start_form_key, document_id = whole_form_key.split("@", 1)
|
||||||
print('New field: ', start_form_key, ' for document id: ', document_id)
|
print("New field: ", start_form_key, " for document id: ", document_id)
|
||||||
documents[document_id][start_form_key] = value
|
documents[document_id][start_form_key] = value
|
||||||
|
|
||||||
print("Documents: ")
|
print("Documents: ")
|
||||||
print(documents)
|
print(documents)
|
||||||
|
|
||||||
username = form_data_json['username']
|
username = form_data_json["username"]
|
||||||
upload_session = form_data_json['upload_session']
|
upload_session = form_data_json["upload_session"]
|
||||||
server_context = form_data_json['server_context']
|
server_context = form_data_json["server_context"]
|
||||||
callback_url = form_data_json['callback_url']
|
callback_url = form_data_json["callback_url"]
|
||||||
callback_expires_in = form_data_json['callback_expires_in']
|
callback_expires_in = form_data_json["callback_expires_in"]
|
||||||
project = form_data_json['project']
|
project = form_data_json["project"]
|
||||||
|
|
||||||
documents_saved = list()
|
documents_saved = list()
|
||||||
|
|
||||||
for key in documents:
|
for key in documents:
|
||||||
try:
|
try:
|
||||||
documents[key]['project'] = project
|
documents[key]["project"] = project
|
||||||
document = DocumentMetadata(**documents[key])
|
document = DocumentMetadata(**documents[key])
|
||||||
save_metadata_response = doc_db.save_metadata_for_documents(document, upload_session, username)
|
save_metadata_response = doc_db.save_metadata_for_documents(document, upload_session, username)
|
||||||
documents_saved.append(save_metadata_response)
|
documents_saved.append(save_metadata_response)
|
||||||
@@ -101,9 +107,11 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
|||||||
print(e)
|
print(e)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
doc_db.debug(endpoint='save_metadata_for_documents_post',
|
doc_db.debug(
|
||||||
request={'documents': documents},
|
endpoint="save_metadata_for_documents_post",
|
||||||
response={'response': documents_saved})
|
request={"documents": documents},
|
||||||
|
response={"response": documents_saved},
|
||||||
|
)
|
||||||
|
|
||||||
return documents_saved
|
return documents_saved
|
||||||
|
|
||||||
@@ -113,8 +121,7 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/user/1.0/upload-part/{part_id}", tags=[""])
|
@router.post("/user/1.0/upload-part/{part_id}", tags=[""])
|
||||||
async def upload_part(part_id: str, request: Request,
|
async def upload_part(part_id: str, request: Request, current_user: User = Depends(get_current_active_user)):
|
||||||
current_user: User = Depends(get_current_active_user)):
|
|
||||||
|
|
||||||
# file_name = doc_db.safe_path(part_id)
|
# file_name = doc_db.safe_path(part_id)
|
||||||
file_name = part_id
|
file_name = part_id
|
||||||
@@ -129,33 +136,31 @@ async def upload_part(part_id: str, request: Request,
|
|||||||
|
|
||||||
# try to receive the uploaded part
|
# try to receive the uploaded part
|
||||||
try:
|
try:
|
||||||
print('File contents: ', request_body)
|
print("File contents: ", request_body)
|
||||||
|
|
||||||
# use document_id instead as dir_name
|
# use document_id instead as dir_name
|
||||||
# dir_name = doc_db.safe_path(document.document_id)
|
# dir_name = doc_db.safe_path(document.document_id)
|
||||||
dir_name = document.document_id
|
dir_name = document.document_id
|
||||||
|
|
||||||
path = './data/document_parts/' + dir_name + '/'
|
path = "./data/document_parts/" + dir_name + "/"
|
||||||
|
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
|
|
||||||
with open(path + file_name, 'wb') as f:
|
with open(path + file_name, "wb") as f:
|
||||||
f.write(request_body)
|
f.write(request_body)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
print('Error uploading file')
|
print("Error uploading file")
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
print('Error uploading file')
|
print("Error uploading file")
|
||||||
print(sys.exc_info()[2])
|
print(sys.exc_info()[2])
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# We will write to the database, information about part successfully uploaded.
|
# We will write to the database, information about part successfully uploaded.
|
||||||
doc_db.mark_part_as_uploaded(part_id, current_user)
|
doc_db.mark_part_as_uploaded(part_id, current_user)
|
||||||
|
|
||||||
doc_db.debug(endpoint='upload-part',
|
doc_db.debug(endpoint="upload-part", request={"part_id": part_id}, response={"uploaded": True})
|
||||||
request={'part_id': part_id},
|
|
||||||
response={'uploaded': True})
|
|
||||||
|
|
||||||
return {"message": f"Successfully uploaded part {file_name}"}
|
return {"message": f"Successfully uploaded part {file_name}"}
|
||||||
|
|
||||||
@@ -166,13 +171,14 @@ async def upload_part(part_id: str, request: Request,
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/user/1.0/document/{document_id}/version/{version_index}/download", tags=[""])
|
@router.get("/user/1.0/document/{document_id}/version/{version_index}/download", tags=[""])
|
||||||
def document_version_download(document_id: str, version_index: int,
|
def document_version_download(
|
||||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||||
|
) -> FileResponse:
|
||||||
# The url to download the binary content of this document version.
|
# The url to download the binary content of this document version.
|
||||||
# May either directly return the result or redirect to a storage provider
|
# May either directly return the result or redirect to a storage provider
|
||||||
keep_characters = (' ', '.', '_', '-')
|
keep_characters = (" ", ".", "_", "-")
|
||||||
document_id = "".join(c for c in document_id if c.isalnum() or c in keep_characters).rstrip()
|
document_id = "".join(c for c in document_id if c.isalnum() or c in keep_characters).rstrip()
|
||||||
file_location = './data/documents/' + document_id + '.ifc'
|
file_location = "./data/documents/" + document_id + ".ifc"
|
||||||
return FileResponse(file_location,
|
return FileResponse(
|
||||||
media_type='application/x-step',
|
file_location, media_type="application/x-step", filename="6dbd4d52-14db-11ee-be56-0242ac120002.ifc"
|
||||||
filename='6dbd4d52-14db-11ee-be56-0242ac120002.ifc')
|
)
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ get_secrets()
|
|||||||
# otherwise the environment variable will have a value of neo4j://kontroll_neo4j:27687
|
# otherwise the environment variable will have a value of neo4j://kontroll_neo4j:27687
|
||||||
# kontroll_neo4j is the docker-compose network.
|
# kontroll_neo4j is the docker-compose network.
|
||||||
|
|
||||||
driver = GraphDatabase.driver(os.environ['NEO4J_URI'],
|
driver = GraphDatabase.driver(
|
||||||
auth=(os.environ['NEO4J_USER'],
|
os.environ["NEO4J_URI"], auth=(os.environ["NEO4J_USER"], os.environ["NEO4J_INITIAL_PASSWORD"])
|
||||||
os.environ['NEO4J_INITIAL_PASSWORD']))
|
)
|
||||||
|
|
||||||
# initial password should be changed to secret password
|
# initial password should be changed to secret password
|
||||||
|
|
||||||
@@ -33,33 +33,38 @@ class MyDB:
|
|||||||
|
|
||||||
def __init__(self, object_driver):
|
def __init__(self, object_driver):
|
||||||
self.driver = object_driver
|
self.driver = object_driver
|
||||||
self.database = 'neo4j'
|
self.database = "neo4j"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def timestamp():
|
def timestamp():
|
||||||
return datetime.now(timezone.utc).isoformat(sep='T', timespec='milliseconds')
|
return datetime.now(timezone.utc).isoformat(sep="T", timespec="milliseconds")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bcf_time(any_datetime):
|
def bcf_time(any_datetime):
|
||||||
if isinstance(any_datetime, type('str')):
|
if isinstance(any_datetime, type("str")):
|
||||||
datetime_any = parser.parse(any_datetime).astimezone(pytz.utc)
|
datetime_any = parser.parse(any_datetime).astimezone(pytz.utc)
|
||||||
elif isinstance(any_datetime, type(datetime.now())):
|
elif isinstance(any_datetime, type(datetime.now())):
|
||||||
datetime_any = any_datetime.astimezone(pytz.utc)
|
datetime_any = any_datetime.astimezone(pytz.utc)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
string_date = datetime_any.isoformat(sep='T', timespec='milliseconds')
|
string_date = datetime_any.isoformat(sep="T", timespec="milliseconds")
|
||||||
return str(string_date)
|
return str(string_date)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def safe_path(path_name):
|
def safe_path(path_name):
|
||||||
safe_path_name = ''.join(x for x in path_name if x.isalnum() or '-')
|
safe_path_name = "".join(x for x in path_name if x.isalnum() or "-")
|
||||||
return safe_path_name
|
return safe_path_name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def debug(endpoint: str, request, response):
|
def debug(endpoint: str, request, response):
|
||||||
print("\n\n\nEndpoint: ", jsonpickle.dumps(endpoint),
|
print(
|
||||||
"\nRequest: ", jsonpickle.dumps(request),
|
"\n\n\nEndpoint: ",
|
||||||
"\nResponse: ", jsonpickle.dumps(response))
|
jsonpickle.dumps(endpoint),
|
||||||
|
"\nRequest: ",
|
||||||
|
jsonpickle.dumps(request),
|
||||||
|
"\nResponse: ",
|
||||||
|
jsonpickle.dumps(response),
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def node_to_json(node):
|
def node_to_json(node):
|
||||||
@@ -89,11 +94,12 @@ class MyDB:
|
|||||||
cypher_file = open(cypher_file_path, "r")
|
cypher_file = open(cypher_file_path, "r")
|
||||||
cypher_data = cypher_file.read()
|
cypher_data = cypher_file.read()
|
||||||
cypher_file.close()
|
cypher_file.close()
|
||||||
cypher_statements = cypher_data.split(';')
|
cypher_statements = cypher_data.split(";")
|
||||||
cypher_statements.pop()
|
cypher_statements.pop()
|
||||||
for cypher_statement in cypher_statements:
|
for cypher_statement in cypher_statements:
|
||||||
tx.run(cypher_statement)
|
tx.run(cypher_statement)
|
||||||
return
|
return
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_write(initialize_db_work)
|
return session.execute_write(initialize_db_work)
|
||||||
|
|
||||||
@@ -113,8 +119,10 @@ class MyDB:
|
|||||||
user_dict = self.node_to_json(user_node)
|
user_dict = self.node_to_json(user_node)
|
||||||
user = UserInDB(**user_dict)
|
user = UserInDB(**user_dict)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_read(get_user_work, username_work=username)
|
return session.execute_read(get_user_work, username_work=username)
|
||||||
|
|
||||||
|
|
||||||
db = MyDB(driver)
|
db = MyDB(driver)
|
||||||
db.initialize_db()
|
db.initialize_db()
|
||||||
|
|||||||
@@ -28,24 +28,24 @@ from py2neo import Graph
|
|||||||
def create_pure_node_from_ifc_entity(ifc_entity, ifc_file, hierarchy=True):
|
def create_pure_node_from_ifc_entity(ifc_entity, ifc_file, hierarchy=True):
|
||||||
node = Node()
|
node = Node()
|
||||||
if ifc_entity.id() != 0:
|
if ifc_entity.id() != 0:
|
||||||
node['id'] = ifc_entity.id()
|
node["id"] = ifc_entity.id()
|
||||||
else:
|
else:
|
||||||
node['id'] = str(uuid4())
|
node["id"] = str(uuid4())
|
||||||
node['name'] = ifc_entity.is_a()
|
node["name"] = ifc_entity.is_a()
|
||||||
if hierarchy:
|
if hierarchy:
|
||||||
for label in ifc_file.wrapped_data.types_with_super():
|
for label in ifc_file.wrapped_data.types_with_super():
|
||||||
if ifc_entity.is_a(label):
|
if ifc_entity.is_a(label):
|
||||||
node.add_label(label)
|
node.add_label(label)
|
||||||
else:
|
else:
|
||||||
node.add_label(ifc_entity.is_a())
|
node.add_label(ifc_entity.is_a())
|
||||||
attributes_type = ['ENTITY INSTANCE', 'AGGREGATE OF ENTITY INSTANCE', 'DERIVED']
|
attributes_type = ["ENTITY INSTANCE", "AGGREGATE OF ENTITY INSTANCE", "DERIVED"]
|
||||||
for i in range(ifc_entity.__len__()):
|
for i in range(ifc_entity.__len__()):
|
||||||
if not ifc_entity.wrapped_data.get_argument_type(i) in attributes_type:
|
if not ifc_entity.wrapped_data.get_argument_type(i) in attributes_type:
|
||||||
name = ifc_entity.wrapped_data.get_argument_name(i)
|
name = ifc_entity.wrapped_data.get_argument_name(i)
|
||||||
name_value = ifc_entity.wrapped_data.get_argument(i)
|
name_value = ifc_entity.wrapped_data.get_argument(i)
|
||||||
node[name]= name_value
|
node[name] = name_value
|
||||||
node.__primarylabel__ = 'Root'
|
node.__primarylabel__ = "Root"
|
||||||
node.__primarykey__ = 'id'
|
node.__primarykey__ = "id"
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
@@ -55,14 +55,14 @@ def create_graph_from_ifc_entity_all(graph, ifc_entity, ifc_file):
|
|||||||
graph.merge(node)
|
graph.merge(node)
|
||||||
for i in range(ifc_entity.__len__()):
|
for i in range(ifc_entity.__len__()):
|
||||||
if ifc_entity[i]:
|
if ifc_entity[i]:
|
||||||
if ifc_entity.wrapped_data.get_argument_type(i) == 'ENTITY INSTANCE':
|
if ifc_entity.wrapped_data.get_argument_type(i) == "ENTITY INSTANCE":
|
||||||
if ifc_entity[i].is_a() in ['IfcOwnerHistory'] and ifc_entity.is_a() != 'IfcProject':
|
if ifc_entity[i].is_a() in ["IfcOwnerHistory"] and ifc_entity.is_a() != "IfcProject":
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
sub_node = create_pure_node_from_ifc_entity(ifc_entity[i], ifc_file)
|
sub_node = create_pure_node_from_ifc_entity(ifc_entity[i], ifc_file)
|
||||||
REL = Relationship(node, ifc_entity.wrapped_data.get_argument_name(i), sub_node)
|
REL = Relationship(node, ifc_entity.wrapped_data.get_argument_name(i), sub_node)
|
||||||
graph.merge(REL)
|
graph.merge(REL)
|
||||||
elif ifc_entity.wrapped_data.get_argument_type(i) == 'AGGREGATE OF ENTITY INSTANCE':
|
elif ifc_entity.wrapped_data.get_argument_type(i) == "AGGREGATE OF ENTITY INSTANCE":
|
||||||
for sub_entity in ifc_entity[i]:
|
for sub_entity in ifc_entity[i]:
|
||||||
sub_node = create_pure_node_from_ifc_entity(sub_entity, ifc_file)
|
sub_node = create_pure_node_from_ifc_entity(sub_entity, ifc_file)
|
||||||
REL = Relationship(node, ifc_entity.wrapped_data.get_argument_name(i), sub_node)
|
REL = Relationship(node, ifc_entity.wrapped_data.get_argument_name(i), sub_node)
|
||||||
@@ -83,7 +83,7 @@ def create_full_graph(graph, ifc_file):
|
|||||||
length = len(ifc_file.wrapped_data.entity_names())
|
length = len(ifc_file.wrapped_data.entity_names())
|
||||||
for entity_id in ifc_file.wrapped_data.entity_names():
|
for entity_id in ifc_file.wrapped_data.entity_names():
|
||||||
entity = ifc_file.by_id(entity_id)
|
entity = ifc_file.by_id(entity_id)
|
||||||
print(idx, '/', length, entity)
|
print(idx, "/", length, entity)
|
||||||
create_graph_from_ifc_entity_all(graph, entity, ifc_file)
|
create_graph_from_ifc_entity_all(graph, entity, ifc_file)
|
||||||
idx += 1
|
idx += 1
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -13,79 +13,110 @@ endpoint_metadata = [
|
|||||||
{"name": "authentication_get", "description": "/authentication"},
|
{"name": "authentication_get", "description": "/authentication"},
|
||||||
{"name": "login_for_access_token_post", "description": "/foundation/oauth2/token"},
|
{"name": "login_for_access_token_post", "description": "/foundation/oauth2/token"},
|
||||||
{"name": "current_user_get", "description": "/foundation/1.0/current-user"},
|
{"name": "current_user_get", "description": "/foundation/1.0/current-user"},
|
||||||
{"name": "projects_get",
|
{
|
||||||
"description": "Retrieve a collection of projects that the currently logged on user has access to."},
|
"name": "projects_get",
|
||||||
{"name": "project_get",
|
"description": "Retrieve a collection of projects that the currently logged on user has access to.",
|
||||||
"description": "Retrieve a specific project. The top level data container is known as the BCF project, "
|
},
|
||||||
"with a UUID and a project name attribute."},
|
{
|
||||||
{"name": "project_put",
|
"name": "project_get",
|
||||||
"description": "Modify a specific project. This operation is only possible when the server returns the update "
|
"description": "Retrieve a specific project. The top level data container is known as the BCF project, "
|
||||||
"flag in the Project authorization."},
|
"with a UUID and a project name attribute.",
|
||||||
{"name": "project_extensions_get",
|
},
|
||||||
"description": "Retrieve a specific projects extensions. Project extensions are used to define possible values "
|
{
|
||||||
"that can be used in topics and comments, for example topic labels and priorities. They may "
|
"name": "project_put",
|
||||||
"change during the course of a project. The most recent extensions state which values are valid "
|
"description": "Modify a specific project. This operation is only possible when the server returns the update "
|
||||||
"at a given moment for newly created topics and comments."},
|
"flag in the Project authorization.",
|
||||||
{"name": "topics_get",
|
},
|
||||||
"description": "Retrieve a collection of topics related to a project (default sort order is creation_date)."},
|
{
|
||||||
{"name": "topic_post",
|
"name": "project_extensions_get",
|
||||||
"description": "Add a new topic. The BCF project contains zero or more topics. Each topic represents a model "
|
"description": "Retrieve a specific projects extensions. Project extensions are used to define possible values "
|
||||||
"issue. A topic will have a UUID, a title, description, priority, stage, labels (similar to "
|
"that can be used in topics and comments, for example topic labels and priorities. They may "
|
||||||
"tags), creation date / author, due date, and assigned to. If modified, it may contain the "
|
"change during the course of a project. The most recent extensions state which values are valid "
|
||||||
"modification date and author."},
|
"at a given moment for newly created topics and comments.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "topics_get",
|
||||||
|
"description": "Retrieve a collection of topics related to a project (default sort order is creation_date).",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "topic_post",
|
||||||
|
"description": "Add a new topic. The BCF project contains zero or more topics. Each topic represents a model "
|
||||||
|
"issue. A topic will have a UUID, a title, description, priority, stage, labels (similar to "
|
||||||
|
"tags), creation date / author, due date, and assigned to. If modified, it may contain the "
|
||||||
|
"modification date and author.",
|
||||||
|
},
|
||||||
{"name": "topic_get", "description": "Retrieve a specific topic."},
|
{"name": "topic_get", "description": "Retrieve a specific topic."},
|
||||||
{"name": "topic_put", "description": "Modify a specific topic, description similar to POST."},
|
{"name": "topic_put", "description": "Modify a specific topic, description similar to POST."},
|
||||||
{"name": "bim_snippet_get",
|
{
|
||||||
"description": "Retrieves a topics BIM-Snippet as binary file. BIM snippet has been in BCF specification since "
|
"name": "bim_snippet_get",
|
||||||
"the very beginning, but is has never been used. Snippets have originally been added to provide "
|
"description": "Retrieves a topics BIM-Snippet as binary file. BIM snippet has been in BCF specification since "
|
||||||
"for 'changes in IFC'. To get this really working in a CDE environment changes to the IFC format "
|
"the very beginning, but is has never been used. Snippets have originally been added to provide "
|
||||||
"is necessary."},
|
"for 'changes in IFC'. To get this really working in a CDE environment changes to the IFC format "
|
||||||
{"name": "bim_snippet_put",
|
"is necessary.",
|
||||||
"description": "Puts a new BIM Snippet binary file to a topic. If this is used, the parent topics BIM Snippet "
|
},
|
||||||
"property is_external must be set to false and the reference must be the file name with "
|
{
|
||||||
"extension."},
|
"name": "bim_snippet_put",
|
||||||
|
"description": "Puts a new BIM Snippet binary file to a topic. If this is used, the parent topics BIM Snippet "
|
||||||
|
"property is_external must be set to false and the reference must be the file name with "
|
||||||
|
"extension.",
|
||||||
|
},
|
||||||
{"name": "files_get", "description": "Retrieve a collection of file references as topic header."},
|
{"name": "files_get", "description": "Retrieve a collection of file references as topic header."},
|
||||||
{"name": "files_put", "description": "Update a collection of file references on the topic header."},
|
{"name": "files_put", "description": "Update a collection of file references on the topic header."},
|
||||||
{"name": "comments_get",
|
{
|
||||||
"description": "Retrieve a collection of all comments related to a topic (default ordering is date)."},
|
"name": "comments_get",
|
||||||
|
"description": "Retrieve a collection of all comments related to a topic (default ordering is date).",
|
||||||
|
},
|
||||||
{"name": "comment_post", "description": "Add a new comment to a topic."},
|
{"name": "comment_post", "description": "Add a new comment to a topic."},
|
||||||
{"name": "comment_put", "description": "Update a single comment, description similar to POST."},
|
{"name": "comment_put", "description": "Update a single comment, description similar to POST."},
|
||||||
{"name": "comment_get", "description": "Get a single comment."},
|
{"name": "comment_get", "description": "Get a single comment."},
|
||||||
{"name": "viewpoints_get", "description": "Retrieve a collection of all viewpoints related to a topic."},
|
{"name": "viewpoints_get", "description": "Retrieve a collection of all viewpoints related to a topic."},
|
||||||
{"name": "viewpoint_post",
|
{
|
||||||
"description": "Add a new viewpoint. Viewpoints are immutable, meaning that they should never change. "
|
"name": "viewpoint_post",
|
||||||
"Requirements for different visualizations should be handled by creating new viewpoint elements."},
|
"description": "Add a new viewpoint. Viewpoints are immutable, meaning that they should never change. "
|
||||||
|
"Requirements for different visualizations should be handled by creating new viewpoint elements.",
|
||||||
|
},
|
||||||
{"name": "viewpoint_get", "description": "Retrieve a specific viewpoint."},
|
{"name": "viewpoint_get", "description": "Retrieve a specific viewpoint."},
|
||||||
{"name": "viewpoint_selected_components_get",
|
{
|
||||||
"description": "Retrieve a collection of all selected components in a viewpoint."},
|
"name": "viewpoint_selected_components_get",
|
||||||
{"name": "viewpoint_colored_components_get",
|
"description": "Retrieve a collection of all selected components in a viewpoint.",
|
||||||
"description": "Retrieve a collection of all colored components in a viewpoint."},
|
},
|
||||||
|
{
|
||||||
|
"name": "viewpoint_colored_components_get",
|
||||||
|
"description": "Retrieve a collection of all colored components in a viewpoint.",
|
||||||
|
},
|
||||||
{"name": "viewpoint_components_visibility_get", "description": "Retrieve visibility of components in a viewpoint."},
|
{"name": "viewpoint_components_visibility_get", "description": "Retrieve visibility of components in a viewpoint."},
|
||||||
{"name": "viewpoint_snapshot_get", "description": "Retrieve a specific viewpoints bitmap image file (png or jpg)."},
|
{"name": "viewpoint_snapshot_get", "description": "Retrieve a specific viewpoints bitmap image file (png or jpg)."},
|
||||||
{"name": "related_topics_get", "description": "Retrieve a collection of all related topics to a topic."},
|
{"name": "related_topics_get", "description": "Retrieve a collection of all related topics to a topic."},
|
||||||
{"name": "related_topics_put", "description": "Add or update a collection of all related topics to a topic."},
|
{"name": "related_topics_put", "description": "Add or update a collection of all related topics to a topic."},
|
||||||
{"name": "topic_document_references_get",
|
{
|
||||||
"description": "Retrieve a collection of all document references to a topic."},
|
"name": "topic_document_references_get",
|
||||||
|
"description": "Retrieve a collection of all document references to a topic.",
|
||||||
|
},
|
||||||
{"name": "topic_document_references_post", "description": "Add or update document references to a topic."},
|
{"name": "topic_document_references_post", "description": "Add or update document references to a topic."},
|
||||||
{"name": "topic_document_references_put", "description": "Add or update document references to a topic."},
|
{"name": "topic_document_references_put", "description": "Add or update document references to a topic."},
|
||||||
{"name": "documents_get", "description": "Retrieve a collection of all documents uploaded to a project."},
|
{"name": "documents_get", "description": "Retrieve a collection of all documents uploaded to a project."},
|
||||||
{"name": "document_post", "description": "Upload a document (binary file) to a project."},
|
{"name": "document_post", "description": "Upload a document (binary file) to a project."},
|
||||||
{"name": "document_get", "description": "Retrieves a document as binary file."},
|
{"name": "document_get", "description": "Retrieves a document as binary file."},
|
||||||
{"name": "topics_events_get",
|
{
|
||||||
"description": "Retrieve a collection of topic events related to a project (default sort order is date)."},
|
"name": "topics_events_get",
|
||||||
{"name": "topic_events_get",
|
"description": "Retrieve a collection of topic events related to a project (default sort order is date).",
|
||||||
"description": "Retrieve a collection of topic events related to a project (default sort order is date)."},
|
},
|
||||||
{"name": "comments_events_get",
|
{
|
||||||
"description": "Retrieve a collection of comment events related to a project (default sort order is date)."},
|
"name": "topic_events_get",
|
||||||
{"name": "comment_events_get",
|
"description": "Retrieve a collection of topic events related to a project (default sort order is date).",
|
||||||
"description": "Retrieve a collection of comment events related to a comment (default sort order is date)."}
|
},
|
||||||
|
{
|
||||||
|
"name": "comments_events_get",
|
||||||
|
"description": "Retrieve a collection of comment events related to a project (default sort order is date).",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "comment_events_get",
|
||||||
|
"description": "Retrieve a collection of comment events related to a comment (default sort order is date).",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="Kontroll API",
|
title="Kontroll API", description="Implementering av BCF API 3.0", version="0.0.1", openapi_tags=endpoint_metadata
|
||||||
description="Implementering av BCF API 3.0",
|
|
||||||
version="0.0.1",
|
|
||||||
openapi_tags=endpoint_metadata
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure app to accept requests from anywhere
|
# Configure app to accept requests from anywhere
|
||||||
@@ -98,23 +129,21 @@ app.add_middleware(
|
|||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
app.include_router(foundation.router, prefix='')
|
app.include_router(foundation.router, prefix="")
|
||||||
app.include_router(bcf.router, prefix='')
|
app.include_router(bcf.router, prefix="")
|
||||||
app.include_router(documents.router, prefix='')
|
app.include_router(documents.router, prefix="")
|
||||||
|
|
||||||
templates = Jinja2Templates(directory="templates")
|
templates = Jinja2Templates(directory="templates")
|
||||||
|
|
||||||
|
|
||||||
@app.get("/", response_class=HTMLResponse)
|
@app.get("/", response_class=HTMLResponse)
|
||||||
def index(request: Request):
|
def index(request: Request):
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse("index.html", {"request": request})
|
||||||
"index.html",
|
|
||||||
{"request": request})
|
|
||||||
|
|
||||||
|
|
||||||
favicon_path = 'favicon.ico'
|
favicon_path = "favicon.ico"
|
||||||
|
|
||||||
|
|
||||||
@app.get('/favicon.ico', include_in_schema=False)
|
@app.get("/favicon.ico", include_in_schema=False)
|
||||||
async def favicon():
|
async def favicon():
|
||||||
return FileResponse(favicon_path)
|
return FileResponse(favicon_path)
|
||||||
|
|||||||
@@ -55,13 +55,13 @@ class ClippingPlane(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class SnapshotType(Enum):
|
class SnapshotType(Enum):
|
||||||
jpg = 'jpg'
|
jpg = "jpg"
|
||||||
png = 'png'
|
png = "png"
|
||||||
|
|
||||||
|
|
||||||
class BitmapType(Enum):
|
class BitmapType(Enum):
|
||||||
jpg = 'jpg'
|
jpg = "jpg"
|
||||||
png = 'png'
|
png = "png"
|
||||||
|
|
||||||
|
|
||||||
class Component(BaseModel):
|
class Component(BaseModel):
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ from models.bcf_common import *
|
|||||||
|
|
||||||
|
|
||||||
class ProjectAction(Enum):
|
class ProjectAction(Enum):
|
||||||
update = 'update'
|
update = "update"
|
||||||
createTopic = 'createTopic'
|
createTopic = "createTopic"
|
||||||
createDocument = 'createDocument'
|
createDocument = "createDocument"
|
||||||
|
|
||||||
|
|
||||||
class ProjectGETAuthorization(BaseModel):
|
class ProjectGETAuthorization(BaseModel):
|
||||||
@@ -18,19 +18,19 @@ class ProjectGET(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class TopicAction(Enum):
|
class TopicAction(Enum):
|
||||||
update = 'update'
|
update = "update"
|
||||||
updateBimSnippet = 'updateBimSnippet'
|
updateBimSnippet = "updateBimSnippet"
|
||||||
updateRelatedTopics = 'updateRelatedTopics'
|
updateRelatedTopics = "updateRelatedTopics"
|
||||||
updateDocumentReferences = 'updateDocumentReferences'
|
updateDocumentReferences = "updateDocumentReferences"
|
||||||
updateFiles = 'updateFiles'
|
updateFiles = "updateFiles"
|
||||||
createComment = 'createComment'
|
createComment = "createComment"
|
||||||
createViewpoint = 'createViewpoint'
|
createViewpoint = "createViewpoint"
|
||||||
delete = 'delete'
|
delete = "delete"
|
||||||
|
|
||||||
|
|
||||||
class CommentAction(Enum):
|
class CommentAction(Enum):
|
||||||
update = 'update'
|
update = "update"
|
||||||
delete = 'delete'
|
delete = "delete"
|
||||||
|
|
||||||
|
|
||||||
class ExtensionsGET(BaseModel):
|
class ExtensionsGET(BaseModel):
|
||||||
@@ -123,7 +123,7 @@ class SnapshotGET(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class ViewpointAction(Enum):
|
class ViewpointAction(Enum):
|
||||||
delete = 'delete'
|
delete = "delete"
|
||||||
|
|
||||||
|
|
||||||
class ViewpointGETAuthorization(BaseModel):
|
class ViewpointGETAuthorization(BaseModel):
|
||||||
@@ -174,6 +174,8 @@ class TopicEventGET(BaseModel):
|
|||||||
topic_guid: str
|
topic_guid: str
|
||||||
date: str
|
date: str
|
||||||
author: str
|
author: str
|
||||||
|
|
||||||
|
|
||||||
# actions: Optional[List[EventAction]] = Field(None, min_items=1)
|
# actions: Optional[List[EventAction]] = Field(None, min_items=1)
|
||||||
|
|
||||||
|
|
||||||
@@ -182,6 +184,8 @@ class CommentEventGET(BaseModel):
|
|||||||
topic_guid: str
|
topic_guid: str
|
||||||
date: str
|
date: str
|
||||||
author: str
|
author: str
|
||||||
|
|
||||||
|
|
||||||
# actions: Optional[List[EventAction]] = Field(None, min_items=1)
|
# actions: Optional[List[EventAction]] = Field(None, min_items=1)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ from typing import List, Optional
|
|||||||
|
|
||||||
class CallbackLink(BaseModel):
|
class CallbackLink(BaseModel):
|
||||||
url: constr(min_length=1) = Field(
|
url: constr(min_length=1) = Field(
|
||||||
description='The server will web-browser-redirect to this URL once the user has completed selecting '
|
description="The server will web-browser-redirect to this URL once the user has completed selecting "
|
||||||
'documents or entering document metadata on the CDE'
|
"documents or entering document metadata on the CDE"
|
||||||
)
|
|
||||||
expires_in: int = Field(
|
|
||||||
description='The expiry period for the URL, in seconds'
|
|
||||||
)
|
)
|
||||||
|
expires_in: int = Field(description="The expiry period for the URL, in seconds")
|
||||||
|
|
||||||
|
|
||||||
# ---- RESPONSE MODELS ---- #
|
# ---- RESPONSE MODELS ---- #
|
||||||
@@ -35,62 +33,52 @@ class DocumentVersionLinks(BaseModel):
|
|||||||
|
|
||||||
class FileDescription(BaseModel):
|
class FileDescription(BaseModel):
|
||||||
name: constr(min_length=1) = Field(
|
name: constr(min_length=1) = Field(
|
||||||
description='The name of the document version file on the server. The files are named by '
|
description="The name of the document version file on the server. The files are named by "
|
||||||
'document_id.file_ending',
|
"document_id.file_ending",
|
||||||
example='908e1cd4-2e09-11ee-be56-0242ac120002.ifc'
|
example="908e1cd4-2e09-11ee-be56-0242ac120002.ifc",
|
||||||
)
|
|
||||||
size_in_bytes: int = Field(
|
|
||||||
description='The size of the file in bytes',
|
|
||||||
example='124563'
|
|
||||||
)
|
)
|
||||||
|
size_in_bytes: int = Field(description="The size of the file in bytes", example="124563")
|
||||||
|
|
||||||
|
|
||||||
class Document(BaseModel):
|
class Document(BaseModel):
|
||||||
document_id: constr(min_length=1) = Field(
|
document_id: constr(min_length=1) = Field(
|
||||||
description='A machine readable identifier that can be used to uniquely identify this version in future calls '
|
description="A machine readable identifier that can be used to uniquely identify this version in future calls "
|
||||||
'UUID is used - see `Query` section',
|
"UUID is used - see `Query` section",
|
||||||
example='908e1cd4-2e09-11ee-be56-0242ac120002'
|
example="908e1cd4-2e09-11ee-be56-0242ac120002",
|
||||||
)
|
)
|
||||||
session_file_id: Optional[str] = Field(
|
session_file_id: Optional[str] = Field(
|
||||||
description='A machine readable identifier that can be used to uniquely the file '
|
description="A machine readable identifier that can be used to uniquely the file "
|
||||||
'during the upload session, UUID is used',
|
"during the upload session, UUID is used",
|
||||||
example='908e1cd4-2e09-11ee-be56-0242ac120002'
|
example="908e1cd4-2e09-11ee-be56-0242ac120002",
|
||||||
)
|
)
|
||||||
version_index: int = Field(
|
version_index: int = Field(
|
||||||
description='A machine readable sequence number of the version of the document. The sequence must be ordered, '
|
description="A machine readable sequence number of the version of the document. The sequence must be ordered, "
|
||||||
'so that newer versions have higher values than previous ones. Each version index must be unique '
|
"so that newer versions have higher values than previous ones. Each version index must be unique "
|
||||||
'for that document, but there may be gaps in the sequence',
|
"for that document, but there may be gaps in the sequence",
|
||||||
example='12'
|
example="12",
|
||||||
)
|
)
|
||||||
version_number: Optional[constr(min_length=1)] = Field(
|
version_number: Optional[constr(min_length=1)] = Field(
|
||||||
description='A human readable version number. This is not expected to be in any specific format across CDEs '
|
description="A human readable version number. This is not expected to be in any specific format across CDEs "
|
||||||
'and may hold any value',
|
"and may hold any value",
|
||||||
example='V2.0-larger'
|
example="V2.0-larger",
|
||||||
)
|
)
|
||||||
creation_date: str = Field(
|
creation_date: str = Field(
|
||||||
description='The creation date of the document revision',
|
description="The creation date of the document revision", example="2016-04-28T16:31:12.270+02:00"
|
||||||
example='2016-04-28T16:31:12.270+02:00'
|
|
||||||
)
|
)
|
||||||
title: Optional[constr(min_length=1)] = Field(
|
title: Optional[constr(min_length=1)] = Field(
|
||||||
description='A human readable code or identifier. Metadata entered by user in CDE.',
|
description="A human readable code or identifier. Metadata entered by user in CDE.", example="Large garage"
|
||||||
example='Large garage'
|
|
||||||
)
|
)
|
||||||
original_file_name: Optional[str] = Field(
|
original_file_name: Optional[str] = Field(
|
||||||
description='The full name of the file as sent to the API',
|
description="The full name of the file as sent to the API", example="First_floor_vent.ifc"
|
||||||
example='First_floor_vent.ifc')
|
)
|
||||||
file_ending: Optional[str] = Field(
|
file_ending: Optional[str] = Field(description="The ending of the file name, including the dot", example=".ifc")
|
||||||
description='The ending of the file name, including the dot',
|
mime_type: Optional[str] = Field(description="The mime type identifier", example="application/x-step")
|
||||||
example='.ifc')
|
file_type: Optional[str] = Field(description="The full name of the file type", example="STEP Physical File (SPF)")
|
||||||
mime_type: Optional[str] = Field(
|
|
||||||
description='The mime type identifier',
|
|
||||||
example='application/x-step')
|
|
||||||
file_type: Optional[str] = Field(
|
|
||||||
description='The full name of the file type',
|
|
||||||
example='STEP Physical File (SPF)')
|
|
||||||
project: Optional[str] = Field(
|
project: Optional[str] = Field(
|
||||||
description='The project to which the document will belong once it has been uploaded,'
|
description="The project to which the document will belong once it has been uploaded,"
|
||||||
'this information is added as metadata by the user in the CDE',
|
"this information is added as metadata by the user in the CDE",
|
||||||
example='908e1cd4-2e09-11ee-be56-0242ac120003')
|
example="908e1cd4-2e09-11ee-be56-0242ac120003",
|
||||||
|
)
|
||||||
file_description: FileDescription
|
file_description: FileDescription
|
||||||
parts: Optional[List[str]]
|
parts: Optional[List[str]]
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ class ProjectOnly(BaseModel):
|
|||||||
class DataForUploadDocuments(BaseModel):
|
class DataForUploadDocuments(BaseModel):
|
||||||
server_context: Optional[str] = Field(
|
server_context: Optional[str] = Field(
|
||||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||||
'the CDE will attemp to load the UI at the same place.'
|
"the CDE will attemp to load the UI at the same place."
|
||||||
)
|
)
|
||||||
documents: List[FileToUpload]
|
documents: List[FileToUpload]
|
||||||
callback: Optional[CallbackLink]
|
callback: Optional[CallbackLink]
|
||||||
@@ -32,25 +32,24 @@ class DataForUploadDocuments(BaseModel):
|
|||||||
|
|
||||||
# ---- DOWNLOAD MODELS ----
|
# ---- DOWNLOAD MODELS ----
|
||||||
|
|
||||||
|
|
||||||
class DocumentMetadataEntries(BaseModel):
|
class DocumentMetadataEntries(BaseModel):
|
||||||
metadata: List[DocumentMetadataEntry] = Field(
|
metadata: List[DocumentMetadataEntry] = Field(description="An array of metadata entries")
|
||||||
description='An array of metadata entries'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Project(BaseModel):
|
class Project(BaseModel):
|
||||||
project_id: str
|
project_id: str
|
||||||
name: str
|
name: str
|
||||||
documents: Optional[List[Document]] = Field(
|
documents: Optional[List[Document]] = Field(
|
||||||
description='An array containing all the documents selected by the user'
|
description="An array containing all the documents selected by the user"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DataForDocumentSelection(BaseModel):
|
class DataForDocumentSelection(BaseModel):
|
||||||
server_context: Optional[str] = Field(
|
server_context: Optional[str] = Field(
|
||||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||||
'the CDE will attemp to load the UI at the same place.'
|
"the CDE will attemp to load the UI at the same place."
|
||||||
)
|
)
|
||||||
projects: List[Project]
|
projects: List[Project]
|
||||||
callback: Optional[CallbackLink]
|
callback: Optional[CallbackLink]
|
||||||
@@ -61,24 +60,8 @@ class DataForDocumentSelection(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
file_types = {
|
file_types = {
|
||||||
'smc': {
|
"smc": {"file_type": "Solibri Model Checker", "file_ending": ".smc", "mime_type": "application/octet-stream"},
|
||||||
'file_type': 'Solibri Model Checker',
|
"ifc": {"file_type": "STEP Physical File", "file_ending": ".ifc", "mime_type": "application/x-step"},
|
||||||
'file_ending': '.smc',
|
"ifczip": {"file_type": "ZIP of a STEP Physical File", "file_ending": ".ifcZIP", "mime_type": "application/zip"},
|
||||||
'mime_type': 'application/octet-stream'
|
"pdf": {"file_type": "Adobe Portable Document Format", "file_ending": ".pdf", "mime_type": "application/pdf"},
|
||||||
},
|
|
||||||
'ifc': {
|
|
||||||
'file_type': 'STEP Physical File',
|
|
||||||
'file_ending': '.ifc',
|
|
||||||
'mime_type': 'application/x-step'
|
|
||||||
},
|
|
||||||
'ifczip': {
|
|
||||||
'file_type': 'ZIP of a STEP Physical File',
|
|
||||||
'file_ending': '.ifcZIP',
|
|
||||||
'mime_type': 'application/zip'
|
|
||||||
},
|
|
||||||
'pdf': {
|
|
||||||
'file_type': 'Adobe Portable Document Format',
|
|
||||||
'file_ending': '.pdf',
|
|
||||||
'mime_type': 'application/pdf'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,15 +13,15 @@ from models.documents_common import CallbackLink
|
|||||||
|
|
||||||
class FileToUpload(BaseModel):
|
class FileToUpload(BaseModel):
|
||||||
file_name: constr(min_length=1) = Field(
|
file_name: constr(min_length=1) = Field(
|
||||||
description='The CDE UI will display this value to the User when entering document metadata. This is the '
|
description="The CDE UI will display this value to the User when entering document metadata. This is the "
|
||||||
'original name of the file. This attribute is the same as the name attribute in a document model.'
|
"original name of the file. This attribute is the same as the name attribute in a document model."
|
||||||
)
|
)
|
||||||
session_file_id: constr(min_length=1) = Field(
|
session_file_id: constr(min_length=1) = Field(
|
||||||
description='This is a client provided id to differentiate between multiple files that are being uploaded in '
|
description="This is a client provided id to differentiate between multiple files that are being uploaded in "
|
||||||
'the same session'
|
"the same session"
|
||||||
)
|
)
|
||||||
document_id: Optional[constr(min_length=1)] = Field(
|
document_id: Optional[constr(min_length=1)] = Field(
|
||||||
description='When present, indicates that this upload is a new version of an existing document'
|
description="When present, indicates that this upload is a new version of an existing document"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -29,19 +29,17 @@ class UploadDocuments(BaseModel):
|
|||||||
callback: CallbackLink
|
callback: CallbackLink
|
||||||
server_context: Optional[str] = Field(
|
server_context: Optional[str] = Field(
|
||||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||||
'the CDE will attemp to load the UI at the same place.'
|
"the CDE will attemp to load the UI at the same place."
|
||||||
)
|
)
|
||||||
files: List[FileToUpload]
|
files: List[FileToUpload]
|
||||||
|
|
||||||
|
|
||||||
class UploadFileDetail(BaseModel):
|
class UploadFileDetail(BaseModel):
|
||||||
size_in_bytes: int = Field(
|
size_in_bytes: int = Field(description="The uploaded file size")
|
||||||
description='The uploaded file size'
|
|
||||||
)
|
|
||||||
session_file_id: constr(min_length=1) = Field(
|
session_file_id: constr(min_length=1) = Field(
|
||||||
description='This is a client provided id to differentiate between multiple files that are being uploaded in '
|
description="This is a client provided id to differentiate between multiple files that are being uploaded in "
|
||||||
'the same session'
|
"the same session"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -56,37 +54,31 @@ class SelectDocuments(BaseModel):
|
|||||||
callback: CallbackLink
|
callback: CallbackLink
|
||||||
server_context: Optional[str] = Field(
|
server_context: Optional[str] = Field(
|
||||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||||
'the CDE will attemp to load the UI at the same place.'
|
"the CDE will attemp to load the UI at the same place."
|
||||||
)
|
)
|
||||||
supported_file_extensions: Optional[List[str]] = Field(
|
supported_file_extensions: Optional[List[str]] = Field(
|
||||||
description='The client may optionally provide an array of accepted file extensions that should be opened '
|
description="The client may optionally provide an array of accepted file extensions that should be opened "
|
||||||
'during this flow. The CDE server UI should make an attempt to only show files matching these '
|
"during this flow. The CDE server UI should make an attempt to only show files matching these "
|
||||||
'extensions to the user for the download selection or help the user in selecting the desired '
|
"extensions to the user for the download selection or help the user in selecting the desired "
|
||||||
'files. However, the server does not have to guarantee that only files matching the extensions '
|
"files. However, the server does not have to guarantee that only files matching the extensions "
|
||||||
'will be selected. The extensions here must contain the dot separator.',
|
"will be selected. The extensions here must contain the dot separator.",
|
||||||
example=['.ifc', '.ifczip']
|
example=[".ifc", ".ifczip"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DataType(Enum):
|
class DataType(Enum):
|
||||||
string = 'string'
|
string = "string"
|
||||||
boolean = 'boolean'
|
boolean = "boolean"
|
||||||
date_time = 'date-time'
|
date_time = "date-time"
|
||||||
date = 'date'
|
date = "date"
|
||||||
integer32 = 'integer32'
|
integer32 = "integer32"
|
||||||
integer64 = 'integer64'
|
integer64 = "integer64"
|
||||||
number = 'number'
|
number = "number"
|
||||||
url = 'url'
|
url = "url"
|
||||||
|
|
||||||
|
|
||||||
class DocumentMetadataEntry(BaseModel):
|
class DocumentMetadataEntry(BaseModel):
|
||||||
name: constr(min_length=1) = Field(
|
name: constr(min_length=1) = Field(description="The name of the metadata property")
|
||||||
description='The name of the metadata property'
|
value: List[constr(min_length=1)] = Field(description="The value of the metadata property, can be a list")
|
||||||
)
|
data_type: DataType = Field(description="The data type of the items in the value array")
|
||||||
value: List[constr(min_length=1)] = Field(
|
|
||||||
description='The value of the metadata property, can be a list'
|
|
||||||
)
|
|
||||||
data_type: DataType = Field(
|
|
||||||
description='The data type of the items in the value array'
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -13,20 +13,18 @@ from models.documents_common import DocumentVersion, LinkData
|
|||||||
|
|
||||||
class DocumentUploadSessionInitialization(BaseModel):
|
class DocumentUploadSessionInitialization(BaseModel):
|
||||||
upload_ui_url: constr(min_length=1) = Field(
|
upload_ui_url: constr(min_length=1) = Field(
|
||||||
description='A CDE UI URL for the client to open in a local browser. The user would enter document metadata '
|
description="A CDE UI URL for the client to open in a local browser. The user would enter document metadata "
|
||||||
'directly in the CDE'
|
"directly in the CDE"
|
||||||
)
|
|
||||||
expires_in: int = Field(
|
|
||||||
description='`upload_ui_url` expiry in seconds'
|
|
||||||
)
|
)
|
||||||
|
expires_in: int = Field(description="`upload_ui_url` expiry in seconds")
|
||||||
max_size_in_bytes: int = Field(
|
max_size_in_bytes: int = Field(
|
||||||
description='The maximum file size supported by the CDE. Attempts to upload a larger file will fail'
|
description="The maximum file size supported by the CDE. Attempts to upload a larger file will fail"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class HttpMethod(Enum):
|
class HttpMethod(Enum):
|
||||||
POST = 'POST'
|
POST = "POST"
|
||||||
PUT = 'PUT'
|
PUT = "PUT"
|
||||||
|
|
||||||
|
|
||||||
class HeaderValue(BaseModel):
|
class HeaderValue(BaseModel):
|
||||||
@@ -40,12 +38,12 @@ class Headers(BaseModel):
|
|||||||
|
|
||||||
class MultipartFormData(BaseModel):
|
class MultipartFormData(BaseModel):
|
||||||
prefix: str = Field(
|
prefix: str = Field(
|
||||||
description='This is a server provided value. Its value must be prefixed to the binary content body when '
|
description="This is a server provided value. Its value must be prefixed to the binary content body when "
|
||||||
'uploading this part'
|
"uploading this part"
|
||||||
)
|
)
|
||||||
suffix: str = Field(
|
suffix: str = Field(
|
||||||
description='This is a server provided value. Its value must be suffixed to the binary content body when '
|
description="This is a server provided value. Its value must be suffixed to the binary content body when "
|
||||||
'uploading this part. Typically, this is the end boundary for a multipart/form-data request'
|
"uploading this part. Typically, this is the end boundary for a multipart/form-data request"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -54,26 +52,22 @@ class UploadFilePartInstruction(BaseModel):
|
|||||||
http_method: HttpMethod
|
http_method: HttpMethod
|
||||||
additional_headers: Optional[Headers] = None
|
additional_headers: Optional[Headers] = None
|
||||||
include_authorization: Optional[bool] = Field(
|
include_authorization: Optional[bool] = Field(
|
||||||
description='Whether or not to include the authorization request header in the file upload request. '
|
description="Whether or not to include the authorization request header in the file upload request. "
|
||||||
'Including the authorization header with some cloud storage providers might fail the request'
|
"Including the authorization header with some cloud storage providers might fail the request"
|
||||||
)
|
)
|
||||||
multipart_form_data: Optional[MultipartFormData] = None
|
multipart_form_data: Optional[MultipartFormData] = None
|
||||||
content_range_start: int = Field(
|
content_range_start: int = Field(description="The inclusive, zero index based start for this part")
|
||||||
description='The inclusive, zero index based start for this part'
|
content_range_end: int = Field(description="The inclusive, zero index based end for this part")
|
||||||
)
|
|
||||||
content_range_end: int = Field(
|
|
||||||
description='The inclusive, zero index based end for this part'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DocumentToUpload(BaseModel):
|
class DocumentToUpload(BaseModel):
|
||||||
session_file_id: constr(min_length=1) = Field(
|
session_file_id: constr(min_length=1) = Field(
|
||||||
description='A client-provided identifier that allows matching the specification with the correct file on the '
|
description="A client-provided identifier that allows matching the specification with the correct file on the "
|
||||||
"user's machine"
|
"user's machine"
|
||||||
)
|
)
|
||||||
upload_file_parts: List[UploadFilePartInstruction] = Field(
|
upload_file_parts: List[UploadFilePartInstruction] = Field(
|
||||||
description='An array of request specifications detailing how to split the file to parts and upload each part '
|
description="An array of request specifications detailing how to split the file to parts and upload each part "
|
||||||
'to the CDE'
|
"to the CDE"
|
||||||
# min_length=1,
|
# min_length=1,
|
||||||
)
|
)
|
||||||
upload_completion: LinkData
|
upload_completion: LinkData
|
||||||
@@ -83,8 +77,8 @@ class DocumentToUpload(BaseModel):
|
|||||||
class DocumentsToUpload(BaseModel):
|
class DocumentsToUpload(BaseModel):
|
||||||
server_context: Optional[str] = Field(
|
server_context: Optional[str] = Field(
|
||||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||||
'the CDE will attemp to load the UI at the same place.'
|
"the CDE will attemp to load the UI at the same place."
|
||||||
)
|
)
|
||||||
documents_to_upload: Optional[List[DocumentToUpload]]
|
documents_to_upload: Optional[List[DocumentToUpload]]
|
||||||
|
|
||||||
@@ -94,12 +88,10 @@ class DocumentsToUpload(BaseModel):
|
|||||||
|
|
||||||
class DocumentDiscoverySessionInitialization(BaseModel):
|
class DocumentDiscoverySessionInitialization(BaseModel):
|
||||||
select_documents_url: constr(min_length=1) = Field(
|
select_documents_url: constr(min_length=1) = Field(
|
||||||
description='A CDE UI URL for the client to open in a local browser. The user would search and select '
|
description="A CDE UI URL for the client to open in a local browser. The user would search and select "
|
||||||
'documents directly in the CDE'
|
"documents directly in the CDE"
|
||||||
)
|
|
||||||
expires_in: int = Field(
|
|
||||||
description='`select_documents_url` expiry in seconds'
|
|
||||||
)
|
)
|
||||||
|
expires_in: int = Field(description="`select_documents_url` expiry in seconds")
|
||||||
|
|
||||||
|
|
||||||
class DocumentsMarkedAsSelected(BaseModel):
|
class DocumentsMarkedAsSelected(BaseModel):
|
||||||
@@ -109,29 +101,25 @@ class DocumentsMarkedAsSelected(BaseModel):
|
|||||||
class SelectedDocuments(BaseModel):
|
class SelectedDocuments(BaseModel):
|
||||||
server_context: Optional[str] = Field(
|
server_context: Optional[str] = Field(
|
||||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||||
'the CDE will attemp to load the UI at the same place.'
|
"the CDE will attemp to load the UI at the same place."
|
||||||
)
|
|
||||||
documents: List[DocumentVersion] = Field(
|
|
||||||
description='An array containing all the documents selected by the user'
|
|
||||||
)
|
)
|
||||||
|
documents: List[DocumentVersion] = Field(description="An array containing all the documents selected by the user")
|
||||||
|
|
||||||
|
|
||||||
class DocumentMetadata(BaseModel):
|
class DocumentMetadata(BaseModel):
|
||||||
session_file_id: constr(min_length=1) = Field(
|
session_file_id: constr(min_length=1) = Field(
|
||||||
description='This is a client provided id to differentiate between multiple files that are being uploaded in '
|
description="This is a client provided id to differentiate between multiple files that are being uploaded in "
|
||||||
'the same session'
|
"the same session"
|
||||||
)
|
)
|
||||||
document_id: Optional[constr(min_length=1)] = Field(
|
document_id: Optional[constr(min_length=1)] = Field(
|
||||||
description='When present, indicates that this upload is a new version of an existing document'
|
description="When present, indicates that this upload is a new version of an existing document"
|
||||||
)
|
)
|
||||||
version_number: constr(min_length=1) = Field(
|
version_number: constr(min_length=1) = Field(
|
||||||
description='A human readable version number. This is not expected to be in any specific format across CDEs '
|
description="A human readable version number. This is not expected to be in any specific format across CDEs "
|
||||||
'and may hold any value'
|
"and may hold any value"
|
||||||
)
|
|
||||||
title: constr(min_length=1) = Field(
|
|
||||||
description='A human readable code or identifier'
|
|
||||||
)
|
)
|
||||||
|
title: constr(min_length=1) = Field(description="A human readable code or identifier")
|
||||||
project: Optional[str]
|
project: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1 @@
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -25,41 +25,42 @@ class DOCDB(MyDB):
|
|||||||
|
|
||||||
def document_node_to_model(self, document_node):
|
def document_node_to_model(self, document_node):
|
||||||
document_json = self.node_to_json(document_node)
|
document_json = self.node_to_json(document_node)
|
||||||
document_json['creation_date'] = self.bcf_time(document_json['creation_date'])
|
document_json["creation_date"] = self.bcf_time(document_json["creation_date"])
|
||||||
document_json['file_description'] = {
|
document_json["file_description"] = {
|
||||||
'name': document_json.pop('name', '<no name>'),
|
"name": document_json.pop("name", "<no name>"),
|
||||||
'size_in_bytes': document_json.pop('size_in_bytes', 0)
|
"size_in_bytes": document_json.pop("size_in_bytes", 0),
|
||||||
}
|
}
|
||||||
document_json['links'] = self.document_version_links(document_json)
|
document_json["links"] = self.document_version_links(document_json)
|
||||||
return DocumentVersion(**document_json)
|
return DocumentVersion(**document_json)
|
||||||
|
|
||||||
def get_document(self, document_id, version_index=False):
|
def get_document(self, document_id, version_index=False):
|
||||||
def get_document_work(tx) -> Union[Document, bool]:
|
def get_document_work(tx) -> Union[Document, bool]:
|
||||||
|
|
||||||
if version_index is None or version_index is False or not isinstance(version_index, int):
|
if version_index is None or version_index is False or not isinstance(version_index, int):
|
||||||
version_index_criteria = ''
|
version_index_criteria = ""
|
||||||
else:
|
else:
|
||||||
version_index_criteria = 'AND d.version_index = $version_index'
|
version_index_criteria = "AND d.version_index = $version_index"
|
||||||
|
|
||||||
cypher = """
|
cypher = (
|
||||||
|
"""
|
||||||
MATCH (d:Document)
|
MATCH (d:Document)
|
||||||
WHERE d.document_id = $document_id
|
WHERE d.document_id = $document_id
|
||||||
%s
|
%s
|
||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
ORDER by d.version_index DESC
|
ORDER by d.version_index DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""" % version_index_criteria
|
"""
|
||||||
|
% version_index_criteria
|
||||||
|
)
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, document_id=document_id, version_index=version_index)
|
||||||
document_id=document_id,
|
|
||||||
version_index=version_index)
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
print('There were no such document version.')
|
print("There were no such document version.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
document_node = first.get('document')
|
document_node = first.get("document")
|
||||||
return self.document_node_to_model(document_node)
|
return self.document_node_to_model(document_node)
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
@@ -88,21 +89,23 @@ class DOCDB(MyDB):
|
|||||||
d.name = $name,
|
d.name = $name,
|
||||||
d.size_in_bytes = $size_in_bytes
|
d.size_in_bytes = $size_in_bytes
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
selection_session=selection_session,
|
cypher,
|
||||||
project=project,
|
selection_session=selection_session,
|
||||||
document_id=document_version.document_id,
|
project=project,
|
||||||
session_file_id=document_version.session_file_id,
|
document_id=document_version.document_id,
|
||||||
version_index=document_version.version_index,
|
session_file_id=document_version.session_file_id,
|
||||||
version_number=document_version.version_number,
|
version_index=document_version.version_index,
|
||||||
creation_date=document_version.creation_date,
|
version_number=document_version.version_number,
|
||||||
title=document_version.title,
|
creation_date=document_version.creation_date,
|
||||||
original_file_name=document_version.original_file_name,
|
title=document_version.title,
|
||||||
file_ending=document_version.file_ending,
|
original_file_name=document_version.original_file_name,
|
||||||
mime_type=document_version.mime_type,
|
file_ending=document_version.file_ending,
|
||||||
file_type=document_version.file_type,
|
mime_type=document_version.mime_type,
|
||||||
name=document_version.file_description.name,
|
file_type=document_version.file_type,
|
||||||
size_in_bytes=document_version.file_description.size_in_bytes)
|
name=document_version.file_description.name,
|
||||||
|
size_in_bytes=document_version.file_description.size_in_bytes,
|
||||||
|
)
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created < 1:
|
if summary.counters.nodes_created < 1:
|
||||||
@@ -122,10 +125,10 @@ class DOCDB(MyDB):
|
|||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
print('There were no such document version.')
|
print("There were no such document version.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
document_node = first.get('document')
|
document_node = first.get("document")
|
||||||
return self.document_node_to_model(document_node)
|
return self.document_node_to_model(document_node)
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
@@ -134,20 +137,21 @@ class DOCDB(MyDB):
|
|||||||
|
|
||||||
def create_ifc_graph_for_document(self, document_id):
|
def create_ifc_graph_for_document(self, document_id):
|
||||||
document = self.get_document(document_id)
|
document = self.get_document(document_id)
|
||||||
my_ifc_file = ifcopenshell.open('./data/documents/' + document.file_description.name)
|
my_ifc_file = ifcopenshell.open("./data/documents/" + document.file_description.name)
|
||||||
my_graph = Graph(os.environ['NEO4J_URI'], auth=(os.environ['NEO4J_USER'], os.environ['NEO4J_INITIAL_PASSWORD']))
|
my_graph = Graph(os.environ["NEO4J_URI"], auth=(os.environ["NEO4J_USER"], os.environ["NEO4J_INITIAL_PASSWORD"]))
|
||||||
create_full_graph(my_graph, my_ifc_file)
|
create_full_graph(my_graph, my_ifc_file)
|
||||||
|
|
||||||
# ---- UPLOAD FUNCTIONS ----
|
# ---- UPLOAD FUNCTIONS ----
|
||||||
|
|
||||||
def post_upload_documents(self, upload_documents: UploadDocuments,
|
def post_upload_documents(
|
||||||
current_user: User) -> DocumentUploadSessionInitialization:
|
self, upload_documents: UploadDocuments, current_user: User
|
||||||
|
) -> DocumentUploadSessionInitialization:
|
||||||
def post_upload_documents_work(tx) -> DocumentUploadSessionInitialization:
|
def post_upload_documents_work(tx) -> DocumentUploadSessionInitialization:
|
||||||
|
|
||||||
session_uuid = str(uuid4())
|
session_uuid = str(uuid4())
|
||||||
session_callback_timedelta = int(upload_documents.callback.expires_in)
|
session_callback_timedelta = int(upload_documents.callback.expires_in)
|
||||||
session_url_validity_timedelta = 10 + int(os.environ['SESSION_URL_VALIDITY_SECONDS'])
|
session_url_validity_timedelta = 10 + int(os.environ["SESSION_URL_VALIDITY_SECONDS"])
|
||||||
if not hasattr(upload_documents, 'server_context') or not upload_documents.server_context:
|
if not hasattr(upload_documents, "server_context") or not upload_documents.server_context:
|
||||||
upload_documents.server_context = False
|
upload_documents.server_context = False
|
||||||
|
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -165,13 +169,15 @@ class DOCDB(MyDB):
|
|||||||
s.session_callback_timedelta = $session_callback_timedelta
|
s.session_callback_timedelta = $session_callback_timedelta
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=current_user.username,
|
cypher,
|
||||||
session_callback_timedelta=session_callback_timedelta,
|
username=current_user.username,
|
||||||
session_url_timedelta=session_url_validity_timedelta,
|
session_callback_timedelta=session_callback_timedelta,
|
||||||
server_context=upload_documents.server_context,
|
session_url_timedelta=session_url_validity_timedelta,
|
||||||
upload_session=session_uuid,
|
server_context=upload_documents.server_context,
|
||||||
callback=upload_documents.callback.url)
|
upload_session=session_uuid,
|
||||||
|
callback=upload_documents.callback.url,
|
||||||
|
)
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created < 2:
|
if summary.counters.nodes_created < 2:
|
||||||
@@ -197,54 +203,60 @@ class DOCDB(MyDB):
|
|||||||
d.file_type = $file_type
|
d.file_type = $file_type
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not hasattr(file, 'document_id') or not file.document_id:
|
if not hasattr(file, "document_id") or not file.document_id:
|
||||||
# When document_id is present, this indicates that
|
# When document_id is present, this indicates that
|
||||||
# this upload is a new version of an existing document.
|
# this upload is a new version of an existing document.
|
||||||
# When not present, we create a new uuid as new document_id.
|
# When not present, we create a new uuid as new document_id.
|
||||||
file.document_id = doc_db.new_uuid()
|
file.document_id = doc_db.new_uuid()
|
||||||
|
|
||||||
if file.file_name.lower().endswith(tuple(file_types)):
|
if file.file_name.lower().endswith(tuple(file_types)):
|
||||||
file_ending = file.file_name.split('.')[-1].lower()
|
file_ending = file.file_name.split(".")[-1].lower()
|
||||||
name = file.document_id + '.' + file_ending
|
name = file.document_id + "." + file_ending
|
||||||
else:
|
else:
|
||||||
file_ending = ''
|
file_ending = ""
|
||||||
name = file.document_id
|
name = file.document_id
|
||||||
|
|
||||||
print('File ending: ', file_ending)
|
print("File ending: ", file_ending)
|
||||||
|
|
||||||
mime_type = ''
|
mime_type = ""
|
||||||
file_type = ''
|
file_type = ""
|
||||||
|
|
||||||
if hasattr(file_types, file_ending):
|
if hasattr(file_types, file_ending):
|
||||||
|
|
||||||
print('We have this file ending in dict: ', file_ending)
|
print("We have this file ending in dict: ", file_ending)
|
||||||
|
|
||||||
mime_type = file_types[file_ending]['mime_type']
|
mime_type = file_types[file_ending]["mime_type"]
|
||||||
file_type = file_types[file_ending]['file_type']
|
file_type = file_types[file_ending]["file_type"]
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=current_user.username,
|
cypher,
|
||||||
upload_session=session_uuid,
|
username=current_user.username,
|
||||||
session_callback_timedelta=session_callback_timedelta,
|
upload_session=session_uuid,
|
||||||
original_file_name=file.file_name,
|
session_callback_timedelta=session_callback_timedelta,
|
||||||
name=name,
|
original_file_name=file.file_name,
|
||||||
session_file_id=file.session_file_id,
|
name=name,
|
||||||
document_id=file.document_id,
|
session_file_id=file.session_file_id,
|
||||||
creation_date=doc_db.timestamp(),
|
document_id=file.document_id,
|
||||||
file_ending=file_ending,
|
creation_date=doc_db.timestamp(),
|
||||||
mime_type=mime_type,
|
file_ending=file_ending,
|
||||||
file_type=file_type)
|
mime_type=mime_type,
|
||||||
|
file_type=file_type,
|
||||||
|
)
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created < 1:
|
if summary.counters.nodes_created < 1:
|
||||||
raise HTTPException(status_code=400, detail="Document node was not created.")
|
raise HTTPException(status_code=400, detail="Document node was not created.")
|
||||||
|
|
||||||
session_init = DocumentUploadSessionInitialization(**{
|
session_init = DocumentUploadSessionInitialization(
|
||||||
'upload_ui_url': os.environ['KONTROLL_BASE_URL'] + 'documents/1.0/' \
|
**{
|
||||||
+ "document-upload?upload_session=" + session_uuid,
|
"upload_ui_url": os.environ["KONTROLL_BASE_URL"]
|
||||||
'expires_in': os.environ['SESSION_URL_VALIDITY_SECONDS'],
|
+ "documents/1.0/"
|
||||||
'max_size_in_bytes': os.environ['SESSION_MAX_FILE_SIZE_BYTES'],
|
+ "document-upload?upload_session="
|
||||||
})
|
+ session_uuid,
|
||||||
|
"expires_in": os.environ["SESSION_URL_VALIDITY_SECONDS"],
|
||||||
|
"max_size_in_bytes": os.environ["SESSION_MAX_FILE_SIZE_BYTES"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return session_init
|
return session_init
|
||||||
|
|
||||||
@@ -261,15 +273,14 @@ class DOCDB(MyDB):
|
|||||||
WHERE us.upload_session = $upload_session
|
WHERE us.upload_session = $upload_session
|
||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
"""
|
"""
|
||||||
results = tx.run(cypher,
|
results = tx.run(cypher, upload_session=str(upload_session))
|
||||||
upload_session=str(upload_session))
|
|
||||||
document_list = list()
|
document_list = list()
|
||||||
for result in results:
|
for result in results:
|
||||||
document_json = self.node_to_json(result.get('document'))
|
document_json = self.node_to_json(result.get("document"))
|
||||||
file_to_upload = {
|
file_to_upload = {
|
||||||
'file_name': document_json['original_file_name'],
|
"file_name": document_json["original_file_name"],
|
||||||
'session_file_id': document_json['session_file_id'],
|
"session_file_id": document_json["session_file_id"],
|
||||||
'document_id': document_json['document_id']
|
"document_id": document_json["document_id"],
|
||||||
}
|
}
|
||||||
document_model = FileToUpload(**file_to_upload)
|
document_model = FileToUpload(**file_to_upload)
|
||||||
document_list.append(document_model)
|
document_list.append(document_model)
|
||||||
@@ -280,16 +291,15 @@ class DOCDB(MyDB):
|
|||||||
WHERE us.upload_session = $upload_session
|
WHERE us.upload_session = $upload_session
|
||||||
RETURN p AS project
|
RETURN p AS project
|
||||||
"""
|
"""
|
||||||
results = tx.run(cypher,
|
results = tx.run(cypher, upload_session=str(upload_session))
|
||||||
upload_session=str(upload_session))
|
|
||||||
project_list = list()
|
project_list = list()
|
||||||
for result in results:
|
for result in results:
|
||||||
project_json = self.node_to_json(result.get('project'))
|
project_json = self.node_to_json(result.get("project"))
|
||||||
project = {
|
project = {
|
||||||
'project_id': project_json['project_id'],
|
"project_id": project_json["project_id"],
|
||||||
'name': project_json['name'],
|
"name": project_json["name"],
|
||||||
}
|
}
|
||||||
print('Project: ', project)
|
print("Project: ", project)
|
||||||
project_list.append(project)
|
project_list.append(project)
|
||||||
|
|
||||||
# to get the user and some session data
|
# to get the user and some session data
|
||||||
@@ -302,31 +312,30 @@ class DOCDB(MyDB):
|
|||||||
us.session_callback_timedelta AS session_callback_timedelta,
|
us.session_callback_timedelta AS session_callback_timedelta,
|
||||||
u AS user
|
u AS user
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, upload_session=str(upload_session))
|
||||||
upload_session=str(upload_session))
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
raise HTTPException(status_code=401, detail="No session or link.")
|
raise HTTPException(status_code=401, detail="No session or link.")
|
||||||
|
|
||||||
user_node = first.get('user')
|
user_node = first.get("user")
|
||||||
user_dict = self.node_to_json(user_node)
|
user_dict = self.node_to_json(user_node)
|
||||||
|
|
||||||
for_upload_documents_dict = dict()
|
for_upload_documents_dict = dict()
|
||||||
for_upload_documents_dict['server_context'] = first.get('server_context')
|
for_upload_documents_dict["server_context"] = first.get("server_context")
|
||||||
|
|
||||||
callback_link = dict()
|
callback_link = dict()
|
||||||
callback_link['url'] = first.get('callback')
|
callback_link["url"] = first.get("callback")
|
||||||
callback_link['expires_in'] = first.get('session_callback_timedelta')
|
callback_link["expires_in"] = first.get("session_callback_timedelta")
|
||||||
|
|
||||||
for_upload_documents_dict['callback'] = callback_link
|
for_upload_documents_dict["callback"] = callback_link
|
||||||
for_upload_documents_dict['documents'] = document_list
|
for_upload_documents_dict["documents"] = document_list
|
||||||
print('Project list: ', project_list)
|
print("Project list: ", project_list)
|
||||||
|
|
||||||
for_upload_documents_dict['projects'] = project_list
|
for_upload_documents_dict["projects"] = project_list
|
||||||
for_upload_documents_dict['current_user'] = user_dict
|
for_upload_documents_dict["current_user"] = user_dict
|
||||||
|
|
||||||
print('Documents list:', document_list)
|
print("Documents list:", document_list)
|
||||||
|
|
||||||
for_upload_documents_model = DataForUploadDocuments(**for_upload_documents_dict)
|
for_upload_documents_model = DataForUploadDocuments(**for_upload_documents_dict)
|
||||||
|
|
||||||
@@ -348,14 +357,16 @@ class DOCDB(MyDB):
|
|||||||
d.title = $title,
|
d.title = $title,
|
||||||
d.project = $project
|
d.project = $project
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=username,
|
cypher,
|
||||||
upload_session=upload_session,
|
username=username,
|
||||||
session_file_id=document.session_file_id,
|
upload_session=upload_session,
|
||||||
version_number=document.version_number,
|
session_file_id=document.session_file_id,
|
||||||
version_index=False,
|
version_number=document.version_number,
|
||||||
title=document.title,
|
version_index=False,
|
||||||
project=document.project)
|
title=document.title,
|
||||||
|
project=document.project,
|
||||||
|
)
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.properties_set < 4:
|
if summary.counters.properties_set < 4:
|
||||||
@@ -376,11 +387,13 @@ class DOCDB(MyDB):
|
|||||||
SET
|
SET
|
||||||
d.size_in_bytes = $size_in_bytes
|
d.size_in_bytes = $size_in_bytes
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=user.username,
|
cypher,
|
||||||
upload_session=upload_session,
|
username=user.username,
|
||||||
session_file_id=document.session_file_id,
|
upload_session=upload_session,
|
||||||
size_in_bytes=document.size_in_bytes)
|
session_file_id=document.session_file_id,
|
||||||
|
size_in_bytes=document.size_in_bytes,
|
||||||
|
)
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.properties_set < 1:
|
if summary.counters.properties_set < 1:
|
||||||
raise HTTPException(status_code=400, detail="Property was not set.")
|
raise HTTPException(status_code=400, detail="Property was not set.")
|
||||||
@@ -390,18 +403,20 @@ class DOCDB(MyDB):
|
|||||||
session.execute_write(update_file_size_work)
|
session.execute_write(update_file_size_work)
|
||||||
|
|
||||||
# link creation
|
# link creation
|
||||||
base_url = os.environ['KONTROLL_BASE_URL'] + 'documents/1.0/'
|
base_url = os.environ["KONTROLL_BASE_URL"] + "documents/1.0/"
|
||||||
upload_session_url = '?upload_session=' + upload_session
|
upload_session_url = "?upload_session=" + upload_session
|
||||||
upload_complete_url = base_url + 'upload-completion' + upload_session_url
|
upload_complete_url = base_url + "upload-completion" + upload_session_url
|
||||||
upload_cancellation_url = base_url + 'upload-cancellation' + upload_session_url
|
upload_cancellation_url = base_url + "upload-cancellation" + upload_session_url
|
||||||
upload_completion = LinkData(**{'url': upload_complete_url})
|
upload_completion = LinkData(**{"url": upload_complete_url})
|
||||||
upload_cancellation = LinkData(**{'url': upload_cancellation_url})
|
upload_cancellation = LinkData(**{"url": upload_cancellation_url})
|
||||||
document_to_upload_model = DocumentToUpload(**{
|
document_to_upload_model = DocumentToUpload(
|
||||||
'session_file_id': document.session_file_id,
|
**{
|
||||||
'upload_file_parts': list(),
|
"session_file_id": document.session_file_id,
|
||||||
'upload_completion': upload_completion,
|
"upload_file_parts": list(),
|
||||||
'upload_cancellation': upload_cancellation
|
"upload_completion": upload_completion,
|
||||||
})
|
"upload_cancellation": upload_cancellation,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def add_part_work(tx) -> UUID:
|
def add_part_work(tx) -> UUID:
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -416,15 +431,17 @@ class DOCDB(MyDB):
|
|||||||
p.content_range_end = $content_range_end,
|
p.content_range_end = $content_range_end,
|
||||||
p.content_length = $content_length
|
p.content_length = $content_length
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=user.username,
|
cypher,
|
||||||
upload_session=upload_session,
|
username=user.username,
|
||||||
session_file_id=document.session_file_id,
|
upload_session=upload_session,
|
||||||
part_number=part_number,
|
session_file_id=document.session_file_id,
|
||||||
part_uuid=str(upload_part_uuid),
|
part_number=part_number,
|
||||||
content_range_start=content_range_start,
|
part_uuid=str(upload_part_uuid),
|
||||||
content_range_end=content_range_end,
|
content_range_start=content_range_start,
|
||||||
content_length=content_length)
|
content_range_end=content_range_end,
|
||||||
|
content_length=content_length,
|
||||||
|
)
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created != 1:
|
if summary.counters.nodes_created != 1:
|
||||||
@@ -432,7 +449,7 @@ class DOCDB(MyDB):
|
|||||||
return upload_part_uuid
|
return upload_part_uuid
|
||||||
|
|
||||||
# calculate the number of file parts to send
|
# calculate the number of file parts to send
|
||||||
number_of_parts = math.ceil(int(document.size_in_bytes) / int(os.environ['SESSION_MAX_FILE_SIZE_BYTES']))
|
number_of_parts = math.ceil(int(document.size_in_bytes) / int(os.environ["SESSION_MAX_FILE_SIZE_BYTES"]))
|
||||||
part_length = math.ceil(int(document.size_in_bytes) / number_of_parts)
|
part_length = math.ceil(int(document.size_in_bytes) / number_of_parts)
|
||||||
for part_number in range(number_of_parts):
|
for part_number in range(number_of_parts):
|
||||||
content_range_start = part_number * part_length
|
content_range_start = part_number * part_length
|
||||||
@@ -441,23 +458,18 @@ class DOCDB(MyDB):
|
|||||||
content_range_end = document.size_in_bytes - 1
|
content_range_end = document.size_in_bytes - 1
|
||||||
content_length = content_range_end - content_range_start + 1
|
content_length = content_range_end - content_range_start + 1
|
||||||
upload_part_uuid = uuid4()
|
upload_part_uuid = uuid4()
|
||||||
upload_part_url = 'upload-part/' + str(upload_part_uuid)
|
upload_part_url = "upload-part/" + str(upload_part_uuid)
|
||||||
additional_headers = {
|
additional_headers = {"values": [{"name": "Content-Length", "value": content_length}]}
|
||||||
'values': [
|
part_instruction = UploadFilePartInstruction(
|
||||||
{
|
**{
|
||||||
'name': 'Content-Length',
|
"url": base_url + upload_part_url,
|
||||||
'value': content_length
|
"http_method": "POST",
|
||||||
}
|
"additional_headers": additional_headers,
|
||||||
]
|
"include_authorization": True,
|
||||||
}
|
"content_range_start": content_range_start,
|
||||||
part_instruction = UploadFilePartInstruction(**{
|
"content_range_end": content_range_end,
|
||||||
'url': base_url + upload_part_url,
|
}
|
||||||
'http_method': 'POST',
|
)
|
||||||
'additional_headers': additional_headers,
|
|
||||||
'include_authorization': True,
|
|
||||||
'content_range_start': content_range_start,
|
|
||||||
'content_range_end': content_range_end
|
|
||||||
})
|
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
added_part = session.execute_write(add_part_work)
|
added_part = session.execute_write(add_part_work)
|
||||||
@@ -476,19 +488,17 @@ class DOCDB(MyDB):
|
|||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, part_id=part_id)
|
||||||
username=current_user.username,
|
|
||||||
part_id=part_id)
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
print('There were no parts in graph!')
|
print("There were no parts in graph!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
document_node = first.get('document')
|
document_node = first.get("document")
|
||||||
document = self.document_node_to_model(document_node)
|
document = self.document_node_to_model(document_node)
|
||||||
|
|
||||||
print('User had this part ' + part_id + ' in document id: ' + document.document_id)
|
print("User had this part " + part_id + " in document id: " + document.document_id)
|
||||||
return document
|
return document
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
@@ -503,9 +513,7 @@ class DOCDB(MyDB):
|
|||||||
SET p.uploaded = True
|
SET p.uploaded = True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, part_id=part_id)
|
||||||
username=current_user.username,
|
|
||||||
part_id=part_id)
|
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.properties_set < 1:
|
if summary.counters.properties_set < 1:
|
||||||
@@ -526,26 +534,24 @@ class DOCDB(MyDB):
|
|||||||
RETURN count(p) as parts
|
RETURN count(p) as parts
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session)
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
number_of_parts = first.get('parts')
|
number_of_parts = first.get("parts")
|
||||||
|
|
||||||
print('There are number of parts not uploaded: ', number_of_parts)
|
print("There are number of parts not uploaded: ", number_of_parts)
|
||||||
|
|
||||||
if number_of_parts > 0:
|
if number_of_parts > 0:
|
||||||
raise HTTPException(status_code=400, detail="All parts not uploaded.")
|
raise HTTPException(status_code=400, detail="All parts not uploaded.")
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_read(check_uploaded_parts_work)
|
return session.execute_read(check_uploaded_parts_work)
|
||||||
|
|
||||||
|
|
||||||
def retrieve_uploaded_parts(self, upload_session: str, current_user: User) -> list:
|
def retrieve_uploaded_parts(self, upload_session: str, current_user: User) -> list:
|
||||||
def retrieve_uploaded_parts_work(tx) -> list:
|
def retrieve_uploaded_parts_work(tx) -> list:
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -556,14 +562,12 @@ class DOCDB(MyDB):
|
|||||||
RETURN p as part
|
RETURN p as part
|
||||||
ORDER BY part.number
|
ORDER BY part.number
|
||||||
"""
|
"""
|
||||||
results = tx.run(cypher,
|
results = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session)
|
|
||||||
|
|
||||||
parts_list = list()
|
parts_list = list()
|
||||||
for result in results:
|
for result in results:
|
||||||
part_json = self.node_to_json(result.get("part"))
|
part_json = self.node_to_json(result.get("part"))
|
||||||
parts_list.append(part_json['uuid'])
|
parts_list.append(part_json["uuid"])
|
||||||
return parts_list
|
return parts_list
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
@@ -579,12 +583,10 @@ class DOCDB(MyDB):
|
|||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session)
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
document_node = first.get('document')
|
document_node = first.get("document")
|
||||||
return self.document_node_to_model(document_node)
|
return self.document_node_to_model(document_node)
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
@@ -604,10 +606,7 @@ class DOCDB(MyDB):
|
|||||||
DELETE r2
|
DELETE r2
|
||||||
CREATE (proj)-[r4:CONTAINS]->(d)
|
CREATE (proj)-[r4:CONTAINS]->(d)
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, upload_session=upload_session, project=project)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session,
|
|
||||||
project=project)
|
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_deleted < 1:
|
if summary.counters.nodes_deleted < 1:
|
||||||
@@ -627,15 +626,13 @@ class DOCDB(MyDB):
|
|||||||
AND us.upload_session = $upload_session
|
AND us.upload_session = $upload_session
|
||||||
RETURN d as document
|
RETURN d as document
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session)
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
document_node = first.get('document')
|
document_node = first.get("document")
|
||||||
return self.document_node_to_model(document_node)
|
return self.document_node_to_model(document_node)
|
||||||
|
|
||||||
def upload_cancellation_work(tx) -> bool:
|
def upload_cancellation_work(tx) -> bool:
|
||||||
@@ -645,9 +642,7 @@ class DOCDB(MyDB):
|
|||||||
AND us.upload_session = $upload_session
|
AND us.upload_session = $upload_session
|
||||||
DETACH DELETE us, d, p
|
DETACH DELETE us, d, p
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session)
|
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_deleted < 1:
|
if summary.counters.nodes_deleted < 1:
|
||||||
@@ -662,14 +657,15 @@ class DOCDB(MyDB):
|
|||||||
|
|
||||||
# ---- DOWNLOAD FUNCTIONS ----
|
# ---- DOWNLOAD FUNCTIONS ----
|
||||||
|
|
||||||
def post_select_documents(self, select_documents: SelectDocuments,
|
def post_select_documents(
|
||||||
current_user: User) -> DocumentDiscoverySessionInitialization:
|
self, select_documents: SelectDocuments, current_user: User
|
||||||
|
) -> DocumentDiscoverySessionInitialization:
|
||||||
def post_select_documents_work(tx) -> DocumentDiscoverySessionInitialization:
|
def post_select_documents_work(tx) -> DocumentDiscoverySessionInitialization:
|
||||||
|
|
||||||
session_uuid = str(uuid4())
|
session_uuid = str(uuid4())
|
||||||
session_callback_timedelta = int(select_documents.callback.expires_in)
|
session_callback_timedelta = int(select_documents.callback.expires_in)
|
||||||
session_url_validity_timedelta = 10 + int(os.environ['SESSION_URL_VALIDITY_SECONDS'])
|
session_url_validity_timedelta = 10 + int(os.environ["SESSION_URL_VALIDITY_SECONDS"])
|
||||||
if not hasattr(select_documents, 'server_context') or not select_documents.server_context:
|
if not hasattr(select_documents, "server_context") or not select_documents.server_context:
|
||||||
select_documents.server_context = str(uuid4())
|
select_documents.server_context = str(uuid4())
|
||||||
|
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -687,22 +683,28 @@ class DOCDB(MyDB):
|
|||||||
s.session_callback_timedelta = $session_callback_timedelta
|
s.session_callback_timedelta = $session_callback_timedelta
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=current_user.username,
|
cypher,
|
||||||
session_callback_timedelta=session_callback_timedelta,
|
username=current_user.username,
|
||||||
session_url_timedelta=session_url_validity_timedelta,
|
session_callback_timedelta=session_callback_timedelta,
|
||||||
server_context=select_documents.server_context,
|
session_url_timedelta=session_url_validity_timedelta,
|
||||||
selection_session=str(session_uuid),
|
server_context=select_documents.server_context,
|
||||||
callback=select_documents.callback.url)
|
selection_session=str(session_uuid),
|
||||||
|
callback=select_documents.callback.url,
|
||||||
|
)
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created < 2:
|
if summary.counters.nodes_created < 2:
|
||||||
raise HTTPException(status_code=400, detail="Session or link node was not created.")
|
raise HTTPException(status_code=400, detail="Session or link node was not created.")
|
||||||
|
|
||||||
session_init_dict = dict()
|
session_init_dict = dict()
|
||||||
session_init_dict['select_documents_url'] = os.environ['KONTROLL_BASE_URL'] + 'documents/1.0/' \
|
session_init_dict["select_documents_url"] = (
|
||||||
+ "document-selection?selection_session=" + session_uuid
|
os.environ["KONTROLL_BASE_URL"]
|
||||||
session_init_dict['expires_in'] = os.environ['SESSION_URL_VALIDITY_SECONDS']
|
+ "documents/1.0/"
|
||||||
|
+ "document-selection?selection_session="
|
||||||
|
+ session_uuid
|
||||||
|
)
|
||||||
|
session_init_dict["expires_in"] = os.environ["SESSION_URL_VALIDITY_SECONDS"]
|
||||||
session_init_model = DocumentDiscoverySessionInitialization(**session_init_dict)
|
session_init_model = DocumentDiscoverySessionInitialization(**session_init_dict)
|
||||||
|
|
||||||
return session_init_model
|
return session_init_model
|
||||||
@@ -719,13 +721,12 @@ class DOCDB(MyDB):
|
|||||||
RETURN p AS project
|
RETURN p AS project
|
||||||
ORDER BY project.name
|
ORDER BY project.name
|
||||||
"""
|
"""
|
||||||
project_results = tx.run(cypher,
|
project_results = tx.run(cypher, selection_session=str(selection_session))
|
||||||
selection_session=str(selection_session))
|
|
||||||
|
|
||||||
project_list = list()
|
project_list = list()
|
||||||
for project_result in project_results:
|
for project_result in project_results:
|
||||||
project_json = self.node_to_json(project_result.get('project'))
|
project_json = self.node_to_json(project_result.get("project"))
|
||||||
project_json['documents'] = list()
|
project_json["documents"] = list()
|
||||||
project_model = Project(**project_json)
|
project_model = Project(**project_json)
|
||||||
|
|
||||||
# to get the documents
|
# to get the documents
|
||||||
@@ -736,12 +737,12 @@ class DOCDB(MyDB):
|
|||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
ORDER BY d.title, d.version_index
|
ORDER BY d.title, d.version_index
|
||||||
"""
|
"""
|
||||||
document_results = tx.run(cypher,
|
document_results = tx.run(
|
||||||
selection_session=str(selection_session),
|
cypher, selection_session=str(selection_session), project_id=str(project_model.project_id)
|
||||||
project_id=str(project_model.project_id))
|
)
|
||||||
|
|
||||||
for document_result in document_results:
|
for document_result in document_results:
|
||||||
document_node = document_result.get('document')
|
document_node = document_result.get("document")
|
||||||
document_model = self.document_node_to_model(document_node)
|
document_model = self.document_node_to_model(document_node)
|
||||||
project_model.documents.append(document_model)
|
project_model.documents.append(document_model)
|
||||||
|
|
||||||
@@ -758,8 +759,7 @@ class DOCDB(MyDB):
|
|||||||
u AS user
|
u AS user
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, selection_session=str(selection_session))
|
||||||
selection_session=str(selection_session))
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
@@ -769,26 +769,28 @@ class DOCDB(MyDB):
|
|||||||
user_dict = self.node_to_json(user_node)
|
user_dict = self.node_to_json(user_node)
|
||||||
|
|
||||||
for_document_selection_dict = dict()
|
for_document_selection_dict = dict()
|
||||||
for_document_selection_dict['server_context'] = first.get('server_context')
|
for_document_selection_dict["server_context"] = first.get("server_context")
|
||||||
|
|
||||||
callback_link = dict()
|
callback_link = dict()
|
||||||
callback_link['url'] = first.get('callback')
|
callback_link["url"] = first.get("callback")
|
||||||
callback_link['expires_in'] = first.get('session_callback_timedelta')
|
callback_link["expires_in"] = first.get("session_callback_timedelta")
|
||||||
|
|
||||||
for_document_selection_dict['callback'] = callback_link
|
for_document_selection_dict["callback"] = callback_link
|
||||||
for_document_selection_dict['projects'] = project_list
|
for_document_selection_dict["projects"] = project_list
|
||||||
for_document_selection_dict['current_user'] = user_dict
|
for_document_selection_dict["current_user"] = user_dict
|
||||||
|
|
||||||
for_document_selection_model = DataForDocumentSelection(**for_document_selection_dict)
|
for_document_selection_model = DataForDocumentSelection(**for_document_selection_dict)
|
||||||
|
|
||||||
print('Data for document selection: ', for_document_selection_dict)
|
print("Data for document selection: ", for_document_selection_dict)
|
||||||
|
|
||||||
return for_document_selection_model
|
return for_document_selection_model
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_read(get_data_for_document_selection_work)
|
return session.execute_read(get_data_for_document_selection_work)
|
||||||
|
|
||||||
def post_mark_documents_as_selected(self, all_documents: list, selection_session: UUID) -> DocumentsMarkedAsSelected:
|
def post_mark_documents_as_selected(
|
||||||
|
self, all_documents: list, selection_session: UUID
|
||||||
|
) -> DocumentsMarkedAsSelected:
|
||||||
|
|
||||||
def mark_documents_as_selected_work(tx) -> DocumentsMarkedAsSelected:
|
def mark_documents_as_selected_work(tx) -> DocumentsMarkedAsSelected:
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -798,12 +800,10 @@ class DOCDB(MyDB):
|
|||||||
MERGE (ss)-[r5:SELECTED]->(d)
|
MERGE (ss)-[r5:SELECTED]->(d)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
selected_documents_model = DocumentsMarkedAsSelected(**{'documents': list()})
|
selected_documents_model = DocumentsMarkedAsSelected(**{"documents": list()})
|
||||||
|
|
||||||
for document in all_documents:
|
for document in all_documents:
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, selection_session=str(selection_session), document_id=str(document))
|
||||||
selection_session=str(selection_session),
|
|
||||||
document_id=str(document))
|
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
|
|
||||||
@@ -817,16 +817,20 @@ class DOCDB(MyDB):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def document_version_links(document_json):
|
def document_version_links(document_json):
|
||||||
document_id = document_json['document_id']
|
document_id = document_json["document_id"]
|
||||||
version_index = document_json['version_index']
|
version_index = document_json["version_index"]
|
||||||
base = os.environ['KONTROLL_BASE_URL'] + "documents/1.0/document/" + document_id + "/version/" + str(version_index)
|
base = (
|
||||||
return DocumentVersionLinks(**{
|
os.environ["KONTROLL_BASE_URL"] + "documents/1.0/document/" + document_id + "/version/" + str(version_index)
|
||||||
'document_version': LinkData(**{'url': base}),
|
)
|
||||||
'document_version_metadata': LinkData(**{'url': base + "/metadata"}),
|
return DocumentVersionLinks(
|
||||||
'document_version_download': LinkData(**{'url': base + "/download"}),
|
**{
|
||||||
'document_versions': LinkData(**{'url': base + "/versions"}),
|
"document_version": LinkData(**{"url": base}),
|
||||||
'document_details': LinkData(**{'url': base + "/details"})
|
"document_version_metadata": LinkData(**{"url": base + "/metadata"}),
|
||||||
})
|
"document_version_download": LinkData(**{"url": base + "/download"}),
|
||||||
|
"document_versions": LinkData(**{"url": base + "/versions"}),
|
||||||
|
"document_details": LinkData(**{"url": base + "/details"}),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def get_download_instructions(self, session_id: UUID, server_context: str, current_user: User) -> SelectedDocuments:
|
def get_download_instructions(self, session_id: UUID, server_context: str, current_user: User) -> SelectedDocuments:
|
||||||
def get_download_instructions_work(tx) -> SelectedDocuments:
|
def get_download_instructions_work(tx) -> SelectedDocuments:
|
||||||
@@ -839,18 +843,16 @@ class DOCDB(MyDB):
|
|||||||
|
|
||||||
document_list = list()
|
document_list = list()
|
||||||
for result in results:
|
for result in results:
|
||||||
document_node = result.get('document')
|
document_node = result.get("document")
|
||||||
document_model = self.document_node_to_model(document_node)
|
document_model = self.document_node_to_model(document_node)
|
||||||
document_list.append(document_model)
|
document_list.append(document_model)
|
||||||
|
|
||||||
selected_documents = SelectedDocuments(**{'server_context': server_context,
|
selected_documents = SelectedDocuments(**{"server_context": server_context, "documents": document_list})
|
||||||
'documents': document_list})
|
|
||||||
return selected_documents
|
return selected_documents
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_read(get_download_instructions_work)
|
return session.execute_read(get_download_instructions_work)
|
||||||
|
|
||||||
|
|
||||||
def get_upload_documents(self, upload_session: UUID, current_user: User) -> UploadDocuments:
|
def get_upload_documents(self, upload_session: UUID, current_user: User) -> UploadDocuments:
|
||||||
def get_upload_documents_work(tx) -> UploadDocuments:
|
def get_upload_documents_work(tx) -> UploadDocuments:
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -860,12 +862,10 @@ class DOCDB(MyDB):
|
|||||||
AND us.upload_session = $upload_session
|
AND us.upload_session = $upload_session
|
||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
"""
|
"""
|
||||||
results = tx.run(cypher,
|
results = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session)
|
|
||||||
file_list = list()
|
file_list = list()
|
||||||
for result in results:
|
for result in results:
|
||||||
file_json = self.node_to_json(result.get('document'))
|
file_json = self.node_to_json(result.get("document"))
|
||||||
file_model = FileToUpload(**file_json)
|
file_model = FileToUpload(**file_json)
|
||||||
file_list.append(file_model)
|
file_list.append(file_model)
|
||||||
|
|
||||||
@@ -878,16 +878,14 @@ class DOCDB(MyDB):
|
|||||||
us.callback AS callback,
|
us.callback AS callback,
|
||||||
us.session_callback_timedelta
|
us.session_callback_timedelta
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||||
username=current_user.username,
|
|
||||||
upload_session=upload_session)
|
|
||||||
|
|
||||||
callback = result.get('callback')
|
callback = result.get("callback")
|
||||||
session_callback_timedelta = result.get('session_callback_timedelta')
|
session_callback_timedelta = result.get("session_callback_timedelta")
|
||||||
|
|
||||||
upload_documents = UploadDocuments()
|
upload_documents = UploadDocuments()
|
||||||
upload_documents.server_context = result.get('server_context')
|
upload_documents.server_context = result.get("server_context")
|
||||||
upload_documents.callback.url = result.get('callback')
|
upload_documents.callback.url = result.get("callback")
|
||||||
upload_documents.callback.expires_in = 3500 # difference between now and timedelta
|
upload_documents.callback.expires_in = 3500 # difference between now and timedelta
|
||||||
upload_documents.files = file_list
|
upload_documents.files = file_list
|
||||||
|
|
||||||
@@ -896,16 +894,18 @@ class DOCDB(MyDB):
|
|||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_read(get_upload_documents_work)
|
return session.execute_read(get_upload_documents_work)
|
||||||
|
|
||||||
def get_document_version(self, document_id: UUID, version_index: int,
|
def get_document_version(
|
||||||
current_user: User) -> Union[DocumentVersion, bool]:
|
self, document_id: UUID, version_index: int, current_user: User
|
||||||
|
) -> Union[DocumentVersion, bool]:
|
||||||
def get_document_version_work(tx) -> Union[DocumentVersion, bool]:
|
def get_document_version_work(tx) -> Union[DocumentVersion, bool]:
|
||||||
|
|
||||||
if version_index is None or version_index is False or not isinstance(version_index, int):
|
if version_index is None or version_index is False or not isinstance(version_index, int):
|
||||||
version_index_criteria = 'AND d.version_index = $version_index'
|
version_index_criteria = "AND d.version_index = $version_index"
|
||||||
else:
|
else:
|
||||||
version_index_criteria = ''
|
version_index_criteria = ""
|
||||||
|
|
||||||
cypher = """
|
cypher = (
|
||||||
|
"""
|
||||||
MATCH (u:User)-[r3:HAS_ACTIONS_ON]->(p:Project)-[r4:CONTAINS]->(d:Document)
|
MATCH (u:User)-[r3:HAS_ACTIONS_ON]->(p:Project)-[r4:CONTAINS]->(d:Document)
|
||||||
WHERE u.username = $username
|
WHERE u.username = $username
|
||||||
AND d.document_id = $document_id
|
AND d.document_id = $document_id
|
||||||
@@ -913,19 +913,20 @@ class DOCDB(MyDB):
|
|||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
ORDER by d.version_index DESC
|
ORDER by d.version_index DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""" % version_index_criteria
|
"""
|
||||||
|
% version_index_criteria
|
||||||
|
)
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=current_user.username,
|
cypher, username=current_user.username, document_id=document_id, version_index=version_index
|
||||||
document_id=document_id,
|
)
|
||||||
version_index=version_index)
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
print('There were no such document version.')
|
print("There were no such document version.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
document_node = first.get('document')
|
document_node = first.get("document")
|
||||||
return self.document_node_to_model(document_node)
|
return self.document_node_to_model(document_node)
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
@@ -935,11 +936,12 @@ class DOCDB(MyDB):
|
|||||||
def get_document_version_metadata_work(tx) -> DocumentMetadataEntries:
|
def get_document_version_metadata_work(tx) -> DocumentMetadataEntries:
|
||||||
|
|
||||||
if version_index is None or version_index is False or not isinstance(version_index, int):
|
if version_index is None or version_index is False or not isinstance(version_index, int):
|
||||||
version_index_criteria = 'AND d.version_index = $version_index'
|
version_index_criteria = "AND d.version_index = $version_index"
|
||||||
else:
|
else:
|
||||||
version_index_criteria = ''
|
version_index_criteria = ""
|
||||||
|
|
||||||
cypher = """
|
cypher = (
|
||||||
|
"""
|
||||||
MATCH (u:User)-[r3:HAS_ACTIONS_ON]->(p:Project)-[r4:CONTAINS]->(d:Document)
|
MATCH (u:User)-[r3:HAS_ACTIONS_ON]->(p:Project)-[r4:CONTAINS]->(d:Document)
|
||||||
WHERE u.username = $username
|
WHERE u.username = $username
|
||||||
AND d.document_id = $document_id
|
AND d.document_id = $document_id
|
||||||
@@ -947,32 +949,34 @@ class DOCDB(MyDB):
|
|||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
ORDER by d.version_index DESC
|
ORDER by d.version_index DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""" % version_index_criteria
|
"""
|
||||||
|
% version_index_criteria
|
||||||
|
)
|
||||||
|
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=current_user.username,
|
cypher, username=current_user.username, document_id=document_id, version_index=version_index
|
||||||
document_id=document_id,
|
)
|
||||||
version_index=version_index)
|
|
||||||
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
print('There were no such document version.')
|
print("There were no such document version.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
document_json = self.node_to_json(first.get('document'))
|
document_json = self.node_to_json(first.get("document"))
|
||||||
document_json['creation_date'] = self.bcf_time(document_json['creation_date'])
|
document_json["creation_date"] = self.bcf_time(document_json["creation_date"])
|
||||||
metadata = ['title', 'version_number', 'creation_date']
|
metadata = ["title", "version_number", "creation_date"]
|
||||||
entries = list()
|
entries = list()
|
||||||
for each_metadata in metadata:
|
for each_metadata in metadata:
|
||||||
each_metadata_text = each_metadata.replace('_', ' ')
|
each_metadata_text = each_metadata.replace("_", " ")
|
||||||
each_metadata_text = each_metadata_text.capitalize()
|
each_metadata_text = each_metadata_text.capitalize()
|
||||||
entry = {
|
entry = {
|
||||||
'name': each_metadata_text,
|
"name": each_metadata_text,
|
||||||
'value': [document_json[each_metadata]],
|
"value": [document_json[each_metadata]],
|
||||||
'data_type': DataType.string
|
"data_type": DataType.string,
|
||||||
}
|
}
|
||||||
entries.append(entry)
|
entries.append(entry)
|
||||||
return DocumentMetadataEntries(**{'metadata': entries})
|
return DocumentMetadataEntries(**{"metadata": entries})
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_read(get_document_version_metadata_work)
|
return session.execute_read(get_document_version_metadata_work)
|
||||||
|
|
||||||
@@ -984,15 +988,14 @@ class DOCDB(MyDB):
|
|||||||
AND d.document_id = $document_id
|
AND d.document_id = $document_id
|
||||||
RETURN d AS document
|
RETURN d AS document
|
||||||
"""
|
"""
|
||||||
results = tx.run(cypher,
|
results = tx.run(cypher, username=current_user.username, document_id=document_id)
|
||||||
username=current_user.username,
|
document_versions = DocumentVersions({"documents": list()})
|
||||||
document_id=document_id)
|
|
||||||
document_versions = DocumentVersions({'documents': list()})
|
|
||||||
for result in results:
|
for result in results:
|
||||||
document_json = self.node_to_json(result.get('document'))
|
document_json = self.node_to_json(result.get("document"))
|
||||||
document_version = self.get_document_version(document_id, document_json['version_index'], current_user)
|
document_version = self.get_document_version(document_id, document_json["version_index"], current_user)
|
||||||
document_versions.documents.append(document_version)
|
document_versions.documents.append(document_version)
|
||||||
return document_versions
|
return document_versions
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
return session.execute_read(get_document_versions_work)
|
return session.execute_read(get_document_versions_work)
|
||||||
|
|
||||||
|
|||||||
@@ -36,11 +36,13 @@ class FoundationDB(MyDB):
|
|||||||
CALL apoc.ttl.expireIn(ac, $time_delta, 's')
|
CALL apoc.ttl.expireIn(ac, $time_delta, 's')
|
||||||
RETURN ac AS authorization_code
|
RETURN ac AS authorization_code
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=username,
|
cypher,
|
||||||
authorization_code=authorization_code,
|
username=username,
|
||||||
scope=scope,
|
authorization_code=authorization_code,
|
||||||
time_delta=int(os.environ['SECURITY_AUTHORIZATION_CODE_EXPIRE_SECONDS']))
|
scope=scope,
|
||||||
|
time_delta=int(os.environ["SECURITY_AUTHORIZATION_CODE_EXPIRE_SECONDS"]),
|
||||||
|
)
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created < 1:
|
if summary.counters.nodes_created < 1:
|
||||||
raise HTTPException(status_code=400, detail="Authorization code was not created.")
|
raise HTTPException(status_code=400, detail="Authorization code was not created.")
|
||||||
@@ -58,14 +60,13 @@ class FoundationDB(MyDB):
|
|||||||
RETURN
|
RETURN
|
||||||
username, scope
|
username, scope
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(cypher, authorization_code=authorization_code)
|
||||||
authorization_code=authorization_code)
|
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
raise HTTPException(status_code=404, detail="Authorization code not found.")
|
raise HTTPException(status_code=404, detail="Authorization code not found.")
|
||||||
authorized_user = TokenData()
|
authorized_user = TokenData()
|
||||||
authorized_user.username = first.get("username")
|
authorized_user.username = first.get("username")
|
||||||
authorized_user.scopes = first.get("scope").split(' ')
|
authorized_user.scopes = first.get("scope").split(" ")
|
||||||
return authorized_user
|
return authorized_user
|
||||||
|
|
||||||
with self.driver.session() as session:
|
with self.driver.session() as session:
|
||||||
@@ -73,11 +74,11 @@ class FoundationDB(MyDB):
|
|||||||
|
|
||||||
token_info = TokenInfo()
|
token_info = TokenInfo()
|
||||||
token_info.access_token = create_access_token(
|
token_info.access_token = create_access_token(
|
||||||
user_info.dict(),
|
user_info.dict(), timedelta(seconds=int(os.environ["SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS"]))
|
||||||
timedelta(seconds=int(os.environ['SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS'])))
|
)
|
||||||
token_info.refresh_token = create_access_token(
|
token_info.refresh_token = create_access_token(
|
||||||
user_info.dict(),
|
user_info.dict(), timedelta(seconds=int(os.environ["SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS"]))
|
||||||
timedelta(seconds=int(os.environ['SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS'])))
|
)
|
||||||
|
|
||||||
def add_tokens_and_delete_code_work(tx) -> bool:
|
def add_tokens_and_delete_code_work(tx) -> bool:
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -92,13 +93,15 @@ class FoundationDB(MyDB):
|
|||||||
SET t3.value = $refresh_token
|
SET t3.value = $refresh_token
|
||||||
SET t3.hash = $refresh_token_hash
|
SET t3.hash = $refresh_token_hash
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
authorization_code=authorization_code,
|
cypher,
|
||||||
username=user_info.username,
|
authorization_code=authorization_code,
|
||||||
access_token=token_info.access_token,
|
username=user_info.username,
|
||||||
access_token_hash=hashlib.md5(token_info.access_token.encode('utf-8')).hexdigest(),
|
access_token=token_info.access_token,
|
||||||
refresh_token=token_info.refresh_token,
|
access_token_hash=hashlib.md5(token_info.access_token.encode("utf-8")).hexdigest(),
|
||||||
refresh_token_hash=hashlib.md5(token_info.refresh_token.encode('utf-8')).hexdigest())
|
refresh_token=token_info.refresh_token,
|
||||||
|
refresh_token_hash=hashlib.md5(token_info.refresh_token.encode("utf-8")).hexdigest(),
|
||||||
|
)
|
||||||
|
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created < 1 or summary.counters.nodes_deleted < 1:
|
if summary.counters.nodes_created < 1 or summary.counters.nodes_deleted < 1:
|
||||||
@@ -119,24 +122,25 @@ class FoundationDB(MyDB):
|
|||||||
RETURN
|
RETURN
|
||||||
at.value AS access_token
|
at.value AS access_token
|
||||||
"""
|
"""
|
||||||
refresh_token_payload = jwt.decode(refresh_token,
|
refresh_token_payload = jwt.decode(
|
||||||
secrets['security_secret_key'],
|
refresh_token, secrets["security_secret_key"], algorithms=[os.environ["SECURITY_ALGORITHM"]]
|
||||||
algorithms=[os.environ['SECURITY_ALGORITHM']])
|
)
|
||||||
username_from_refresh_token: str = refresh_token_payload.get("username")
|
username_from_refresh_token: str = refresh_token_payload.get("username")
|
||||||
print('refresh_token_username: ', username_from_refresh_token)
|
print("refresh_token_username: ", username_from_refresh_token)
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=username_from_refresh_token,
|
cypher,
|
||||||
refresh_token_hash=hashlib.md5(refresh_token.encode('utf-8')).hexdigest()
|
username=username_from_refresh_token,
|
||||||
)
|
refresh_token_hash=hashlib.md5(refresh_token.encode("utf-8")).hexdigest(),
|
||||||
|
)
|
||||||
first = result.single()
|
first = result.single()
|
||||||
if first is None:
|
if first is None:
|
||||||
raise HTTPException(status_code=404, detail="Access token not found.")
|
raise HTTPException(status_code=404, detail="Access token not found.")
|
||||||
token_info = TokenInfo()
|
token_info = TokenInfo()
|
||||||
token_info.access_token = first.get("access_token")
|
token_info.access_token = first.get("access_token")
|
||||||
token_info.refresh_token = refresh_token
|
token_info.refresh_token = refresh_token
|
||||||
access_token_payload = jwt.decode(token_info.access_token,
|
access_token_payload = jwt.decode(
|
||||||
secrets['security_secret_key'],
|
token_info.access_token, secrets["security_secret_key"], algorithms=[os.environ["SECURITY_ALGORITHM"]]
|
||||||
algorithms=[os.environ['SECURITY_ALGORITHM']])
|
)
|
||||||
username_from_access_token: str = access_token_payload.get("username")
|
username_from_access_token: str = access_token_payload.get("username")
|
||||||
if username_from_access_token is None:
|
if username_from_access_token is None:
|
||||||
raise credentials_exception
|
raise credentials_exception
|
||||||
@@ -148,11 +152,11 @@ class FoundationDB(MyDB):
|
|||||||
got_token_data, got_token_info = session.execute_read(use_refresh_to_get_access_work)
|
got_token_data, got_token_info = session.execute_read(use_refresh_to_get_access_work)
|
||||||
new_token_info = TokenInfo()
|
new_token_info = TokenInfo()
|
||||||
new_token_info.access_token = create_access_token(
|
new_token_info.access_token = create_access_token(
|
||||||
got_token_data.dict(),
|
got_token_data.dict(), timedelta(seconds=int(os.environ["SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS"]))
|
||||||
timedelta(seconds=int(os.environ['SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS'])))
|
)
|
||||||
new_token_info.refresh_token = create_access_token(
|
new_token_info.refresh_token = create_access_token(
|
||||||
got_token_data.dict(),
|
got_token_data.dict(), timedelta(seconds=int(os.environ["SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS"]))
|
||||||
timedelta(seconds=int(os.environ['SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS'])))
|
)
|
||||||
|
|
||||||
def update_tokens_work(tx) -> bool:
|
def update_tokens_work(tx) -> bool:
|
||||||
cypher = """
|
cypher = """
|
||||||
@@ -168,12 +172,14 @@ class FoundationDB(MyDB):
|
|||||||
rt.hash = $refresh_token_hash,
|
rt.hash = $refresh_token_hash,
|
||||||
at.hash = $access_token_hash
|
at.hash = $access_token_hash
|
||||||
"""
|
"""
|
||||||
result = tx.run(cypher,
|
result = tx.run(
|
||||||
username=got_token_data.username,
|
cypher,
|
||||||
access_token=new_token_info.access_token,
|
username=got_token_data.username,
|
||||||
refresh_token=new_token_info.refresh_token,
|
access_token=new_token_info.access_token,
|
||||||
access_token_hash=hashlib.md5(new_token_info.access_token.encode('utf-8')).hexdigest(),
|
refresh_token=new_token_info.refresh_token,
|
||||||
refresh_token_hash=hashlib.md5(new_token_info.refresh_token.encode('utf-8')).hexdigest())
|
access_token_hash=hashlib.md5(new_token_info.access_token.encode("utf-8")).hexdigest(),
|
||||||
|
refresh_token_hash=hashlib.md5(new_token_info.refresh_token.encode("utf-8")).hexdigest(),
|
||||||
|
)
|
||||||
summary = result.consume()
|
summary = result.consume()
|
||||||
if summary.counters.nodes_created < 2 or summary.counters.nodes_deleted < 2:
|
if summary.counters.nodes_created < 2 or summary.counters.nodes_deleted < 2:
|
||||||
raise HTTPException(status_code=400, detail="Tokens were not deleted and created.")
|
raise HTTPException(status_code=400, detail="Tokens were not deleted and created.")
|
||||||
@@ -183,4 +189,5 @@ class FoundationDB(MyDB):
|
|||||||
session.execute_write(update_tokens_work)
|
session.execute_write(update_tokens_work)
|
||||||
return new_token_info
|
return new_token_info
|
||||||
|
|
||||||
|
|
||||||
foundation_db = FoundationDB(driver)
|
foundation_db = FoundationDB(driver)
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from glob import glob
|
|||||||
|
|
||||||
def get_secrets():
|
def get_secrets():
|
||||||
secrets = dict()
|
secrets = dict()
|
||||||
for var in glob('/run/secrets/*'):
|
for var in glob("/run/secrets/*"):
|
||||||
k = var.split('/')[-1]
|
k = var.split("/")[-1]
|
||||||
v = open(var).read().rstrip('\n')
|
v = open(var).read().rstrip("\n")
|
||||||
secrets[k] = v
|
secrets[k] = v
|
||||||
return secrets
|
return secrets
|
||||||
|
|||||||
@@ -16,25 +16,20 @@ from security.secrets import get_secrets
|
|||||||
secrets = get_secrets()
|
secrets = get_secrets()
|
||||||
|
|
||||||
# password context
|
# password context
|
||||||
crypt_context = CryptContext(
|
crypt_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||||
schemes=["bcrypt"],
|
|
||||||
deprecated="auto")
|
|
||||||
|
|
||||||
oauth2_scheme = OAuth2AuthorizationCodeBearer(
|
oauth2_scheme = OAuth2AuthorizationCodeBearer(
|
||||||
authorizationUrl='foundation/oauth2/auth',
|
authorizationUrl="foundation/oauth2/auth",
|
||||||
tokenUrl='foundation/oauth2/token',
|
tokenUrl="foundation/oauth2/token",
|
||||||
scopes={
|
scopes={"test": "Full access, but only test data.", "user": "Normal user access.", "admin": "Full access to all."},
|
||||||
'test': 'Full access, but only test data.',
|
)
|
||||||
'user': 'Normal user access.',
|
|
||||||
'admin': 'Full access to all.'
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
credentials_exception = HTTPException(
|
credentials_exception = HTTPException(
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
detail="Could not validate credentials",
|
detail="Could not validate credentials",
|
||||||
headers={"WWW-Authenticate": "Bearer"},
|
headers={"WWW-Authenticate": "Bearer"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
||||||
@@ -44,7 +39,7 @@ def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
|||||||
else:
|
else:
|
||||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||||
payload.update({"expires": str(expire)})
|
payload.update({"expires": str(expire)})
|
||||||
encoded_jwt = jwt.encode(payload, secrets['security_secret_key'], algorithm=os.environ['SECURITY_ALGORITHM'])
|
encoded_jwt = jwt.encode(payload, secrets["security_secret_key"], algorithm=os.environ["SECURITY_ALGORITHM"])
|
||||||
return encoded_jwt
|
return encoded_jwt
|
||||||
|
|
||||||
|
|
||||||
@@ -79,20 +74,18 @@ async def get_current_user(security_scopes: SecurityScopes, token: str = Depends
|
|||||||
print(authenticate_value)
|
print(authenticate_value)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print('Token: ', token)
|
print("Token: ", token)
|
||||||
payload = jwt.decode(token,
|
payload = jwt.decode(token, secrets["security_secret_key"], algorithms=[os.environ["SECURITY_ALGORITHM"]])
|
||||||
secrets['security_secret_key'],
|
|
||||||
algorithms=[os.environ['SECURITY_ALGORITHM']])
|
|
||||||
username_from_token: str = payload.get("username")
|
username_from_token: str = payload.get("username")
|
||||||
print('Token username: ', username_from_token)
|
print("Token username: ", username_from_token)
|
||||||
if username_from_token is None:
|
if username_from_token is None:
|
||||||
raise credentials_exception
|
raise credentials_exception
|
||||||
token_scopes = payload.get("scopes", [])
|
token_scopes = payload.get("scopes", [])
|
||||||
print('Token scopes: ', token_scopes)
|
print("Token scopes: ", token_scopes)
|
||||||
token_data = TokenData(scopes=token_scopes, username=username_from_token)
|
token_data = TokenData(scopes=token_scopes, username=username_from_token)
|
||||||
|
|
||||||
except JWTError:
|
except JWTError:
|
||||||
print('JWTError')
|
print("JWTError")
|
||||||
raise credentials_exception
|
raise credentials_exception
|
||||||
|
|
||||||
user = db.get_user(username=token_data.username)
|
user = db.get_user(username=token_data.username)
|
||||||
|
|||||||
Reference in New Issue
Block a user