mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 10:11:46 +00:00
geom.settings - add a tooltip for available settings #4832
example - https://i.imgur.com/eTdqv5J.png added a test so we won't miss if some setting will be added/removed
This commit is contained in:
@@ -27,7 +27,7 @@ from ..entity_instance import entity_instance
|
|||||||
|
|
||||||
from . import has_occ
|
from . import has_occ
|
||||||
|
|
||||||
from typing import TypeVar, Union, Optional, Generator, Any
|
from typing import TypeVar, Union, Optional, Generator, Any, Literal
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
ShapeElementType = Union[
|
ShapeElementType = Union[
|
||||||
@@ -54,17 +54,62 @@ if has_occ:
|
|||||||
else:
|
else:
|
||||||
return shape
|
return shape
|
||||||
|
|
||||||
class missing_setting:
|
|
||||||
def __repr__(self): return '-'
|
|
||||||
|
|
||||||
class settings_mixin:
|
SETTING = Literal[
|
||||||
|
"mesher-linear-deflection",
|
||||||
|
"mesher-angular-deflection",
|
||||||
|
"reorient-shells",
|
||||||
|
"length-unit",
|
||||||
|
"angle-unit",
|
||||||
|
"precision",
|
||||||
|
"dimensionality",
|
||||||
|
"layerset-first",
|
||||||
|
"disable-boolean-result",
|
||||||
|
"no-wire-intersection-check",
|
||||||
|
"no-wire-intersection-tolerance",
|
||||||
|
"precision-factor",
|
||||||
|
"debug-boolean",
|
||||||
|
"boolean-attempt-2d",
|
||||||
|
"weld-vertices",
|
||||||
|
"use-world-coords",
|
||||||
|
"use-material-names",
|
||||||
|
"convert-back-units",
|
||||||
|
"context-ids",
|
||||||
|
"context-types",
|
||||||
|
"context-identifiers",
|
||||||
|
"iterator-output",
|
||||||
|
"disable-opening-subtractions",
|
||||||
|
"apply-default-materials",
|
||||||
|
"no-normals",
|
||||||
|
"generate-uvs",
|
||||||
|
"enable-layerset-slicing",
|
||||||
|
"element-hierarchy",
|
||||||
|
"validate",
|
||||||
|
"edge-arrows",
|
||||||
|
"building-local-placement",
|
||||||
|
"site-local-placement",
|
||||||
|
"force-space-transparency",
|
||||||
|
"circle-segments",
|
||||||
|
"keep-bounding-boxes",
|
||||||
|
"piecewise-step-type",
|
||||||
|
"piecewise-step-param",
|
||||||
|
"use-python-opencascade",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class missing_setting:
|
||||||
|
def __repr__(self):
|
||||||
|
return '-'
|
||||||
|
|
||||||
|
|
||||||
|
class settings_mixin:
|
||||||
"""
|
"""
|
||||||
Pythonic interface mixin to the settings modules and
|
Pythonic interface mixin to the settings modules and
|
||||||
to provide an additional setting to enable pythonOCC
|
to provide an additional setting to enable pythonOCC
|
||||||
when available
|
when available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
USE_PYTHON_OPENCASCADE = 'USE_PYTHON_OPENCASCADE'
|
use_python_opencascade = False
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(settings_mixin, self).__init__()
|
super(settings_mixin, self).__init__()
|
||||||
@@ -73,29 +118,33 @@ class settings_mixin:
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
def safe_get(x):
|
def safe_get(x):
|
||||||
try: return self.get_(x)
|
try:
|
||||||
except: return missing_setting()
|
return self.get(x)
|
||||||
|
except RuntimeError:
|
||||||
|
return missing_setting()
|
||||||
|
|
||||||
fmt_pair = lambda x: "%s = %r" % (self.rname(x), safe_get(x))
|
fmt_pair = lambda x: "%s = %r" % (self.rname(x), safe_get(x))
|
||||||
return "%s(%s)" % (
|
return "%s(%s)" % (
|
||||||
type(self).__name__,
|
type(self).__name__,
|
||||||
", ".join(map(fmt_pair, self.setting_names()))
|
", ".join(map(fmt_pair, self.setting_names()))
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def name(k):
|
def name(k: str) -> SETTING:
|
||||||
return k.lower().replace('_', '-')
|
return k.lower().replace("_", "-")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def rname(k):
|
def rname(k: SETTING) -> str:
|
||||||
return k.upper().replace('-', '_')
|
return k.upper().replace("-", "_")
|
||||||
|
|
||||||
def set(self, k: str, v: Any) -> None:
|
def set(self, k: SETTING, v: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Set value of the setting named `k` to `v`.
|
Set value of the setting named `k` to `v`.
|
||||||
|
|
||||||
:raises RuntimeError: If there is no setting with name `k`.
|
:raises RuntimeError: If there is no setting with name `k`.
|
||||||
"""
|
"""
|
||||||
if k == "USE_PYTHON_OPENCASCADE":
|
k = self.name(k)
|
||||||
|
if k == "use-python-opencascade":
|
||||||
if not has_occ:
|
if not has_occ:
|
||||||
raise AttributeError("Python OpenCASCADE is not installed")
|
raise AttributeError("Python OpenCASCADE is not installed")
|
||||||
if v:
|
if v:
|
||||||
@@ -104,17 +153,22 @@ class settings_mixin:
|
|||||||
self.use_python_opencascade = True
|
self.use_python_opencascade = True
|
||||||
else:
|
else:
|
||||||
self.set_(self.name(k), v)
|
self.set_(self.name(k), v)
|
||||||
|
|
||||||
def get(self, k: str) -> Any:
|
def get(self, k: SETTING) -> Any:
|
||||||
"""
|
"""
|
||||||
Return value of the setting named `k`.
|
Return value of the setting named `k`.
|
||||||
|
|
||||||
:raises RuntimeError: If there is no setting with name `k`.
|
:raises RuntimeError: If there is no setting with name `k`.
|
||||||
"""
|
"""
|
||||||
|
k = self.name(k)
|
||||||
return self.get_(self.name(k))
|
if k == "use-python-opencascade":
|
||||||
|
return self.use_python_opencascade
|
||||||
|
return self.get_(k)
|
||||||
|
|
||||||
def __getattr__(self, k):
|
def setting_names(self) -> tuple[SETTING, ...]:
|
||||||
|
return super().setting_names() + ("use-python-opencascade",)
|
||||||
|
|
||||||
|
def __getattr__(self, k: str) -> SETTING:
|
||||||
if k in map(self.rname, self.setting_names()):
|
if k in map(self.rname, self.setting_names()):
|
||||||
return k
|
return k
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,7 +1,32 @@
|
|||||||
|
import pytest
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.api
|
import ifcopenshell.api
|
||||||
import ifcopenshell.geom
|
import ifcopenshell.geom
|
||||||
import ifcopenshell.api.owner.settings
|
import ifcopenshell.api.owner.settings
|
||||||
|
from typing import get_args
|
||||||
|
|
||||||
|
|
||||||
|
class TestGeomSettings:
|
||||||
|
def test_run(self):
|
||||||
|
settings = ifcopenshell.geom.settings()
|
||||||
|
assert set(get_args(ifcopenshell.geom.SETTING)) == set(settings.setting_names())
|
||||||
|
|
||||||
|
assert settings.get(settings.USE_PYTHON_OPENCASCADE) is False
|
||||||
|
assert settings.get("use-python-opencascade") is False
|
||||||
|
assert "USE_PYTHON_OPENCASCADE = False" in repr(settings)
|
||||||
|
|
||||||
|
if ifcopenshell.geom.has_occ:
|
||||||
|
settings.set("use-python-opencascade", True)
|
||||||
|
settings.set(settings.USE_PYTHON_OPENCASCADE, True)
|
||||||
|
assert settings.get(settings.USE_PYTHON_OPENCASCADE) is True
|
||||||
|
assert "USE_PYTHON_OPENCASCADE = True" in repr(settings)
|
||||||
|
else:
|
||||||
|
with pytest.raises(AttributeError):
|
||||||
|
settings.set("use-python-opencascade", True)
|
||||||
|
with pytest.raises(AttributeError):
|
||||||
|
settings.set(settings.USE_PYTHON_OPENCASCADE, True)
|
||||||
|
assert "USE_PYTHON_OPENCASCADE = False" in repr(settings)
|
||||||
|
|
||||||
|
|
||||||
class TestAssignObject:
|
class TestAssignObject:
|
||||||
def test_no_welding_on_distinct_items(self):
|
def test_no_welding_on_distinct_items(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user