mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-09 21:53:40 +00:00
get_uri, resolve_uri - refactor #6605
1) Use pathlib for consistency 2) Ensure consistent output - always use posix format and resolve paths (but keep the symlinks)
This commit is contained in:
@@ -263,31 +263,46 @@ class Ifc(bonsai.core.tool.Ifc):
|
|||||||
IfcStore.history_edit_object(obj, finish_editing=True)
|
IfcStore.history_edit_object(obj, finish_editing=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def resolve_uri(cls, uri: str) -> str:
|
def normalize_path(cls, path: Union[Path, str]) -> str:
|
||||||
"""Get absolute path based on the active IFC file."""
|
# Do not use `Path.resolve` as it will resolve symlinks too.
|
||||||
if os.path.isabs(uri):
|
return Path(os.path.normpath(path)).as_posix()
|
||||||
return uri
|
|
||||||
ifc_path = cls.get_path()
|
|
||||||
if os.path.isfile(ifc_path):
|
|
||||||
ifc_path = os.path.dirname(ifc_path)
|
|
||||||
return (uri if not uri else os.path.join(ifc_path, uri)).replace("\\", "/")
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_uri(cls, uri: str | Path, use_relative_path: bool = False) -> str:
|
def resolve_uri(cls, uri: str | Path) -> str:
|
||||||
"""Get path relative to the active IFC file, if `use_relative_path` is `True`.
|
"""Get absolute path based on the active IFC file."""
|
||||||
|
|
||||||
If `use_relative_path` is `False` - get absolute filepath from uri.
|
|
||||||
"""
|
|
||||||
if not use_relative_path:
|
|
||||||
return Path(uri).absolute().resolve().as_posix()
|
|
||||||
uri = Path(uri)
|
uri = Path(uri)
|
||||||
if not os.path.isabs(uri) or not (ifc_path := cls.get_path()):
|
if uri.is_absolute():
|
||||||
return uri.as_posix().replace("\\", "/")
|
return cls.normalize_path(uri)
|
||||||
if Path(uri).drive != Path(ifc_path).drive:
|
ifc_path = Path(cls.get_path())
|
||||||
return uri.as_posix().replace("\\", "/")
|
if ifc_path.is_file():
|
||||||
if os.path.isfile(ifc_path):
|
ifc_path = ifc_path.parent
|
||||||
ifc_path = os.path.dirname(ifc_path)
|
if not str(uri):
|
||||||
return Path(os.path.relpath(uri, ifc_path)).as_posix().replace("\\", "/")
|
# TODO: When does it occur and why we return empty path in this case?
|
||||||
|
return str(uri)
|
||||||
|
return cls.normalize_path(ifc_path / uri)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_uri(cls, uri: str | Path, use_relative_path: bool) -> str:
|
||||||
|
"""Get path relative to the active IFC file, if ``use_relative_path`` is ``True``.
|
||||||
|
|
||||||
|
``use_relative_path`` is ``False``:
|
||||||
|
- return ``uri`` as-is if it's absolute
|
||||||
|
- raise ``ValueError`` if ``uri`` is relative (this condition indicates deeper code error)
|
||||||
|
"""
|
||||||
|
uri = Path(uri)
|
||||||
|
if not use_relative_path:
|
||||||
|
if not uri.is_absolute():
|
||||||
|
raise ValueError(f"Unexpected relative path in get_uri: '{uri}'.")
|
||||||
|
return cls.normalize_path(uri)
|
||||||
|
if not uri.is_absolute() or not (ifc_path := cls.get_path()):
|
||||||
|
return cls.normalize_path(uri)
|
||||||
|
ifc_path = Path(ifc_path)
|
||||||
|
if uri.drive != ifc_path.drive:
|
||||||
|
return cls.normalize_path(uri)
|
||||||
|
if ifc_path.is_file():
|
||||||
|
ifc_path = ifc_path.parent
|
||||||
|
# Use `os.path.relpath` as it does support creating '..' paths.
|
||||||
|
return cls.normalize_path(Path(os.path.relpath(uri, ifc_path)))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unlink(
|
def unlink(
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import test.bim.bootstrap
|
|||||||
import bonsai.core.tool
|
import bonsai.core.tool
|
||||||
import bonsai.tool as tool
|
import bonsai.tool as tool
|
||||||
import pytest
|
import pytest
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
from bonsai.tool.ifc import Ifc as subject
|
from bonsai.tool.ifc import Ifc as subject
|
||||||
|
|
||||||
|
|
||||||
@@ -237,3 +239,102 @@ class TestUnlink(test.bim.bootstrap.NewFile):
|
|||||||
subject.unlink(element=element, obj=obj)
|
subject.unlink(element=element, obj=obj)
|
||||||
assert subject.get_entity(obj) == element
|
assert subject.get_entity(obj) == element
|
||||||
assert subject.get_object(element) == obj
|
assert subject.get_object(element) == obj
|
||||||
|
|
||||||
|
|
||||||
|
class TestUri(test.bim.bootstrap.NewFile):
|
||||||
|
def test_get_uri(self):
|
||||||
|
ifc = ifcopenshell.file()
|
||||||
|
subject.set(ifc)
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
|
base_path = Path(tmp_dir)
|
||||||
|
project_dir = base_path / "project"
|
||||||
|
project_dir.mkdir()
|
||||||
|
path = project_dir / "project.ifc"
|
||||||
|
test_name = "test.xml"
|
||||||
|
test_filepath = project_dir / test_name
|
||||||
|
test_filepath.touch()
|
||||||
|
path.touch()
|
||||||
|
subject.set_path(subject.normalize_path(path))
|
||||||
|
|
||||||
|
# Test absolute filepaths.
|
||||||
|
abs_filepath = str(test_filepath)
|
||||||
|
assert subject.get_uri(abs_filepath, False) == subject.normalize_path(abs_filepath)
|
||||||
|
assert subject.get_uri(abs_filepath, True) == test_name
|
||||||
|
|
||||||
|
# Test relative filepaths.
|
||||||
|
rel_filepath = test_name
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
subject.get_uri(rel_filepath, False)
|
||||||
|
|
||||||
|
assert subject.get_uri(rel_filepath, True) == test_name
|
||||||
|
|
||||||
|
# Test that paths are resolved, but keeping symlinks.
|
||||||
|
link_name = "link.xml"
|
||||||
|
link_path = base_path / link_name
|
||||||
|
link_path.symlink_to(test_filepath)
|
||||||
|
|
||||||
|
# Test absolute paths.
|
||||||
|
abs_filepath = test_filepath.parent / ".." / link_name
|
||||||
|
assert subject.get_uri(abs_filepath, False) == subject.normalize_path(abs_filepath)
|
||||||
|
assert subject.get_uri(abs_filepath, True) == "../" + link_name
|
||||||
|
|
||||||
|
# Test relative paths.
|
||||||
|
rel_filepath = "../" + link_name
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
subject.get_uri(rel_filepath, False)
|
||||||
|
assert subject.get_uri(rel_filepath, True) == rel_filepath
|
||||||
|
|
||||||
|
def test_resolve_uri(self):
|
||||||
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
|
base_path = Path(tmp_dir)
|
||||||
|
project_dir = base_path / "project"
|
||||||
|
project_dir.mkdir()
|
||||||
|
path = project_dir / "project.ifc"
|
||||||
|
path.touch()
|
||||||
|
subject.set_path(subject.normalize_path(path))
|
||||||
|
test_name = "test.xml"
|
||||||
|
test_filepath = project_dir / test_name
|
||||||
|
test_filepath.touch()
|
||||||
|
|
||||||
|
# Test absolute filepaths.
|
||||||
|
abs_filepath = str(test_filepath)
|
||||||
|
assert subject.resolve_uri(abs_filepath) == subject.normalize_path(abs_filepath)
|
||||||
|
rel_filepath = test_name
|
||||||
|
assert subject.resolve_uri(rel_filepath) == subject.normalize_path(abs_filepath)
|
||||||
|
|
||||||
|
# Test that paths are resolved, but keeping symlinks.
|
||||||
|
link_name = "link.xml"
|
||||||
|
link_path = base_path / link_name
|
||||||
|
link_path.symlink_to(test_filepath)
|
||||||
|
|
||||||
|
# Test absolute path.
|
||||||
|
abs_filepath = test_filepath.parent / ".." / link_name
|
||||||
|
assert subject.resolve_uri(abs_filepath) == subject.normalize_path(abs_filepath)
|
||||||
|
|
||||||
|
# Test relative path.
|
||||||
|
rel_filepath = "../" + link_name
|
||||||
|
assert subject.resolve_uri(rel_filepath) == subject.normalize_path(abs_filepath)
|
||||||
|
|
||||||
|
def test_normalize_path(self):
|
||||||
|
# Posix format.
|
||||||
|
path = r"test\test.txt"
|
||||||
|
assert subject.normalize_path(path) == "test/test.txt"
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
|
base_path = Path(tmp_dir)
|
||||||
|
project_path = base_path / "project"
|
||||||
|
project_path.mkdir()
|
||||||
|
original_file = project_path / "test.xml"
|
||||||
|
original_file.touch()
|
||||||
|
|
||||||
|
link_name = "link.xml"
|
||||||
|
link_path = project_path / link_name
|
||||||
|
link_path.symlink_to(original_file)
|
||||||
|
|
||||||
|
# Absolute path.
|
||||||
|
abs_path = project_path / ".." / link_name
|
||||||
|
assert subject.normalize_path(abs_path) == (base_path / link_name).as_posix()
|
||||||
|
|
||||||
|
rel_path = "../" + link_name
|
||||||
|
assert subject.normalize_path(rel_path) == rel_path
|
||||||
|
|||||||
Reference in New Issue
Block a user