Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b19b85c9d1 | |||
| db4b2b7f87 | |||
| 77916995bc | |||
| 3dd56dc38e | |||
| ae42bec1c3 | |||
| ea7baf8eb5 | |||
| 8352bb5c9a | |||
| fc34b876fd | |||
| 183993cfc5 | |||
| 9be3b4b93d | |||
| 0b14660115 | |||
| 68c4c682a0 | |||
| 4f93ddcaf3 | |||
| e842f651b9 | |||
| 7e1bec1aba | |||
| 1fb9a4f5fe | |||
| 1668c80bed | |||
| ac6ba87c68 | |||
| 3db8565f57 | |||
| a32822f4e3 | |||
| 40956927c8 | |||
| 4628f111ba | |||
| 9c952b432d | |||
| f075988e4b |
@@ -6,72 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
update_issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get project data
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GHPROJECT_TOKEN}}
|
||||
ORGANIZATION: specklesystems
|
||||
PROJECT_NUMBER: 9
|
||||
run: |
|
||||
gh api graphql --header 'GraphQL-Features: projects_next_graphql' -f query='
|
||||
query($org: String!, $number: Int!) {
|
||||
organization(login: $org){
|
||||
projectNext(number: $number) {
|
||||
id
|
||||
fields(first:20) {
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
settings
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json
|
||||
|
||||
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
|
||||
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
|
||||
|
||||
echo "$PROJECT_ID"
|
||||
echo "$STATUS_FIELD_ID"
|
||||
|
||||
echo 'DONE_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .settings | fromjson | .options[] | select(.name== "Done") | .id' project_data.json) >> $GITHUB_ENV
|
||||
echo "$DONE_ID"
|
||||
|
||||
- name: Add Issue to project #it's already in the project, but we do this to get its node id!
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GHPROJECT_TOKEN}}
|
||||
ISSUE_ID: ${{ github.event.issue.node_id }}
|
||||
run: |
|
||||
item_id="$( gh api graphql --header 'GraphQL-Features: projects_next_graphql' -f query='
|
||||
mutation($project:ID!, $id:ID!) {
|
||||
addProjectNextItem(input: {projectId: $project, contentId: $id}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}' -f project=$PROJECT_ID -f id=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
|
||||
|
||||
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
|
||||
|
||||
- name: Update Status
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GHPROJECT_TOKEN}}
|
||||
ISSUE_ID: ${{ github.event.issue.node_id }}
|
||||
run: |
|
||||
gh api graphql --header 'GraphQL-Features: projects_next_graphql' -f query='
|
||||
mutation($project:ID!, $status:ID!, $id:ID!, $value:String!) {
|
||||
set_status: updateProjectNextItemField(
|
||||
input: {
|
||||
projectId: $project
|
||||
itemId: $id
|
||||
fieldId: $status
|
||||
value: $value
|
||||
}
|
||||
) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}' -f project=$PROJECT_ID -f status=$STATUS_FIELD_ID -f id=$ITEM_ID -f value=${{ env.DONE_ID }}
|
||||
uses: specklesystems/github-actions/.github/workflows/project-add-issue.yml@main
|
||||
secrets: inherit
|
||||
with:
|
||||
issue-id: ${{ github.event.issue.node_id }}
|
||||
@@ -6,45 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
track_issue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get project data
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GHPROJECT_TOKEN}}
|
||||
ORGANIZATION: specklesystems
|
||||
PROJECT_NUMBER: 9
|
||||
run: |
|
||||
gh api graphql --header 'GraphQL-Features: projects_next_graphql' -f query='
|
||||
query($org: String!, $number: Int!) {
|
||||
organization(login: $org){
|
||||
projectNext(number: $number) {
|
||||
id
|
||||
fields(first:20) {
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
settings
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json
|
||||
|
||||
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
|
||||
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
|
||||
|
||||
- name: Add Issue to project
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GHPROJECT_TOKEN}}
|
||||
ISSUE_ID: ${{ github.event.issue.node_id }}
|
||||
run: |
|
||||
item_id="$( gh api graphql --header 'GraphQL-Features: projects_next_graphql' -f query='
|
||||
mutation($project:ID!, $id:ID!) {
|
||||
addProjectNextItem(input: {projectId: $project, contentId: $id}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}' -f project=$PROJECT_ID -f id=$ISSUE_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
|
||||
|
||||
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
|
||||
uses: specklesystems/github-actions/.github/workflows/project-add-issue.yml@main
|
||||
secrets: inherit
|
||||
with:
|
||||
issue-id: ${{ github.event.issue.node_id }}
|
||||
@@ -5,6 +5,7 @@ from typing import (
|
||||
Any,
|
||||
ClassVar,
|
||||
Dict,
|
||||
ForwardRef,
|
||||
List,
|
||||
Optional,
|
||||
Set,
|
||||
@@ -217,25 +218,37 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
return True, t(value)
|
||||
|
||||
if getattr(t, "__module__", None) == "typing":
|
||||
if isinstance(t, ForwardRef):
|
||||
return True, value
|
||||
|
||||
origin = getattr(t, "__origin__")
|
||||
# below is what in nicer for >= py38
|
||||
# origin = get_origin(t)
|
||||
|
||||
# recursive validation for Unions on both types preferring the fist type
|
||||
if origin is Union:
|
||||
t_1, t_2 = t.__args__ # type: ignore
|
||||
# below is what in nicer for >= py38
|
||||
# t_1, t_2 = get_args(t)
|
||||
t_1_success, t_1_value = _validate_type(t_1, value)
|
||||
if t_1_success:
|
||||
return True, t_1_value
|
||||
return _validate_type(t_2, value)
|
||||
args = t.__args__ # type: ignore
|
||||
for arg_t in args:
|
||||
t_success, t_value = _validate_type(arg_t, value)
|
||||
if t_success:
|
||||
return True, t_value
|
||||
return False, value
|
||||
if origin is dict:
|
||||
if not isinstance(value, dict):
|
||||
return False, value
|
||||
if value == {}:
|
||||
return True, value
|
||||
if not getattr(t, "__args__", None):
|
||||
return True, value
|
||||
t_key, t_value = t.__args__ # type: ignore
|
||||
|
||||
if (
|
||||
getattr(t_key, "__name__", None),
|
||||
getattr(t_value, "__name__", None),
|
||||
) == ("KT", "VT"):
|
||||
return True, value
|
||||
# we're only checking the first item, but the for loop and return after
|
||||
# evaluating the first item is the fastest way
|
||||
for dict_key, dict_value in value.items():
|
||||
@@ -251,7 +264,11 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
return False, value
|
||||
if value == []:
|
||||
return True, value
|
||||
if not hasattr(t, "__args__"):
|
||||
return True, value
|
||||
t_items = t.__args__[0] # type: ignore
|
||||
if getattr(t_items, "__name__", None) == "T":
|
||||
return True, value
|
||||
first_item_valid, _ = _validate_type(t_items, value[0])
|
||||
if first_item_valid:
|
||||
return True, value
|
||||
@@ -260,7 +277,11 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
if origin is tuple:
|
||||
if not isinstance(value, tuple):
|
||||
return False, value
|
||||
if not hasattr(t, "__args__"):
|
||||
return True, value
|
||||
args = t.__args__ # type: ignore
|
||||
if args == tuple():
|
||||
return True, value
|
||||
# we're not checking for empty tuple, cause tuple lengths must match
|
||||
if len(args) != len(value):
|
||||
return False, value
|
||||
@@ -272,6 +293,17 @@ def _validate_type(t: Optional[type], value: Any) -> Tuple[bool, Any]:
|
||||
values.append(item_value)
|
||||
return True, tuple(values)
|
||||
|
||||
if origin is set:
|
||||
if not isinstance(value, set):
|
||||
return False, value
|
||||
if not hasattr(t, "__args__"):
|
||||
return True, value
|
||||
t_items = t.__args__[0] # type: ignore
|
||||
first_item_valid, _ = _validate_type(t_items, next(iter(value)))
|
||||
if first_item_valid:
|
||||
return True, value
|
||||
return False, value
|
||||
|
||||
if isinstance(value, t):
|
||||
return True, value
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
from typing import Any, List, Optional
|
||||
from deprecated import deprecated
|
||||
|
||||
from specklepy.objects.geometry import Point, Vector
|
||||
|
||||
from .base import Base
|
||||
|
||||
OTHER = "Objects.Other."
|
||||
OTHER_REVIT = OTHER + "Revit."
|
||||
|
||||
IDENTITY_TRANSFORM = [
|
||||
1.0,
|
||||
@@ -72,7 +74,7 @@ class DisplayStyle(Base, speckle_type=OTHER + "DisplayStyle"):
|
||||
class Transform(
|
||||
Base,
|
||||
speckle_type=OTHER + "Transform",
|
||||
serialize_ignore={"translation", "scaling", "is_identity"},
|
||||
serialize_ignore={"translation", "scaling", "is_identity", "value"},
|
||||
):
|
||||
"""The 4x4 transformation matrix
|
||||
|
||||
@@ -84,12 +86,21 @@ class Transform(
|
||||
_value: Optional[List[float]] = None
|
||||
|
||||
@property
|
||||
@deprecated(version="2.12", reason="Use matrix")
|
||||
def value(self) -> List[float]:
|
||||
"""The transform matrix represented as a flat list of 16 floats"""
|
||||
return self._value
|
||||
|
||||
@value.setter
|
||||
def value(self, value: List[float]) -> None:
|
||||
self.matrix = value
|
||||
|
||||
@property
|
||||
def matrix(self) -> List[float]:
|
||||
"""The transform matrix represented as a flat list of 16 floats"""
|
||||
return self._value
|
||||
|
||||
@matrix.setter
|
||||
def matrix(self, value: List[float]) -> None:
|
||||
try:
|
||||
value = [float(x) for x in value]
|
||||
except (ValueError, TypeError) as error:
|
||||
@@ -118,7 +129,7 @@ class Transform(
|
||||
|
||||
@property
|
||||
def is_identity(self) -> bool:
|
||||
return self.value == IDENTITY_TRANSFORM
|
||||
return self._value == IDENTITY_TRANSFORM
|
||||
|
||||
def apply_to_point(self, point: Point) -> Point:
|
||||
"""Transform a single speckle Point
|
||||
@@ -236,15 +247,38 @@ class BlockDefinition(
|
||||
geometry: Optional[List[Base]] = None
|
||||
|
||||
|
||||
class BlockInstance(
|
||||
Base, speckle_type=OTHER + "BlockInstance", detachable={"blockDefinition"}
|
||||
class Instance(
|
||||
Base, speckle_type=OTHER + "Instance", detachable={"definition"}
|
||||
):
|
||||
blockDefinition: Optional[BlockDefinition] = None
|
||||
transform: Optional[Transform] = None
|
||||
definition: Optional[Base] = None
|
||||
|
||||
|
||||
class BlockInstance(
|
||||
Instance, speckle_type=OTHER + "BlockInstance", serialize_ignore={"blockDefinition"}
|
||||
):
|
||||
@property
|
||||
@deprecated(version="2.13", reason="Use definition")
|
||||
def blockDefinition(self) -> Optional[BlockDefinition]:
|
||||
if isinstance(self.definition, BlockDefinition):
|
||||
return self.definition
|
||||
return None
|
||||
|
||||
@blockDefinition.setter
|
||||
def blockDefinition(self, value: Optional[BlockDefinition]) -> None:
|
||||
self.definition = value
|
||||
|
||||
class RevitInstance(Instance, speckle_type=OTHER_REVIT + "RevitInstance"):
|
||||
level: Optional[Base] = None
|
||||
facingFlipped: bool
|
||||
handFlipped: bool
|
||||
parameters: Optional[Base] = None
|
||||
elementId: Optional[str]
|
||||
|
||||
# TODO: prob move this into a built elements module, but just trialling this for now
|
||||
class RevitParameter(Base, speckle_type="Objects.BuiltElements.Revit.Parameter"):
|
||||
class RevitParameter(
|
||||
Base, speckle_type="Objects.BuiltElements.Revit.Parameter"
|
||||
):
|
||||
name: Optional[str] = None
|
||||
value: Any = None
|
||||
applicationUnitType: Optional[str] = None # eg UnitType UT_Length
|
||||
@@ -254,4 +288,4 @@ class RevitParameter(Base, speckle_type="Objects.BuiltElements.Revit.Parameter")
|
||||
] = None # BuiltInParameterName or GUID for shared parameter
|
||||
isShared: bool = False
|
||||
isReadOnly: bool = False
|
||||
isTypeParameter: bool = False
|
||||
isTypeParameter: bool = False
|
||||
@@ -6,7 +6,10 @@ from specklepy.objects.structural.analysis import (
|
||||
ModelSettings,
|
||||
ModelUnits,
|
||||
)
|
||||
from specklepy.objects.structural.axis import Axis
|
||||
from specklepy.objects.structural.axis import (
|
||||
AxisType,
|
||||
Axis
|
||||
)
|
||||
from specklepy.objects.structural.geometry import (
|
||||
Element1D,
|
||||
Element2D,
|
||||
@@ -82,6 +85,7 @@ __all__ = [
|
||||
"ElementType1D",
|
||||
"ElementType2D",
|
||||
"ElementType3D",
|
||||
"AxisType",
|
||||
"Axis",
|
||||
"Node",
|
||||
"Restraint",
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
from typing import Optional
|
||||
from enum import Enum
|
||||
|
||||
from specklepy.objects.base import Base
|
||||
from specklepy.objects.geometry import Plane
|
||||
|
||||
|
||||
class AxisType(int, Enum):
|
||||
Cartesian = 0
|
||||
Cylindrical = 1
|
||||
Spherical = 2
|
||||
|
||||
|
||||
class Axis(Base, speckle_type="Objects.Structural.Geometry.Axis"):
|
||||
name: Optional[str] = None
|
||||
axisType: Optional[str] = None
|
||||
axisType: Optional[AxisType] = None
|
||||
plane: Optional[Plane] = None
|
||||
|
||||
@@ -5,7 +5,7 @@ from specklepy.objects.base import Base
|
||||
from specklepy.objects.structural.axis import Axis
|
||||
from specklepy.objects.structural.materials import StructuralMaterial
|
||||
|
||||
STRUCTURAL_PROPERTY = "Objectives.Structural.Properties"
|
||||
STRUCTURAL_PROPERTY = "Objects.Structural.Properties"
|
||||
|
||||
|
||||
class MemberType(int, Enum):
|
||||
@@ -90,7 +90,7 @@ class Property(Base, speckle_type=STRUCTURAL_PROPERTY):
|
||||
name: Optional[str] = None
|
||||
|
||||
|
||||
class SectionProfile(Base, speckle_type=STRUCTURAL_PROPERTY + ".SectionProfile"):
|
||||
class SectionProfile(Base, speckle_type=STRUCTURAL_PROPERTY + ".Profiles.SectionProfile"):
|
||||
name: Optional[str] = None
|
||||
shapeType: Optional[ShapeType] = None
|
||||
area: float = 0.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from enum import Enum, IntEnum
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -18,6 +18,16 @@ class FakeIntEnum(IntEnum):
|
||||
one = 1
|
||||
|
||||
|
||||
class FakeBase(Base):
|
||||
foo: Optional[str]
|
||||
|
||||
def __init__(self, foo: str) -> None:
|
||||
self.foo = foo
|
||||
|
||||
|
||||
fake_bases = [FakeBase("foo"), FakeBase("bar")]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"input_type, value, is_valid, return_value",
|
||||
[
|
||||
@@ -64,7 +74,9 @@ class FakeIntEnum(IntEnum):
|
||||
# same as the dict typing below...
|
||||
(List[int], [None, 2], True, [None, 2]),
|
||||
(List[Optional[int]], [None, 2], True, [None, 2]),
|
||||
(List, ["foo", 2, "bar"], True, ["foo", 2, "bar"]),
|
||||
(Dict[str, int], {"foo": 1}, True, {"foo": 1}),
|
||||
(Dict, {"foo": 1}, True, {"foo": 1}),
|
||||
(Dict[str, Optional[int]], {"foo": None}, True, {"foo": None}),
|
||||
# this case should be
|
||||
# (Dict[int, Base], {1: None}, False, {1: None}),
|
||||
@@ -72,9 +84,29 @@ class FakeIntEnum(IntEnum):
|
||||
(Dict[int, Base], {1: None}, True, {1: None}),
|
||||
(Dict[int, Base], {1: test_base}, True, {1: test_base}),
|
||||
(Tuple[int, str, str], (1, "foo", "bar"), True, (1, "foo", "bar")),
|
||||
(Tuple, (1, "foo", "bar"), True, (1, "foo", "bar")),
|
||||
# given our current rules, this is the reality. Its just sad...
|
||||
(Tuple[str, str, str], (1, "foo", "bar"), True, ("1", "foo", "bar")),
|
||||
(Tuple[str, Optional[str], str], (1, None, "bar"), True, ("1", None, "bar")),
|
||||
(Set[bool], set([1, 2]), False, set([1, 2])),
|
||||
(Set[int], set([1, 2]), True, set([1, 2])),
|
||||
(Set[int], set([None, 2]), True, set([None, 2])),
|
||||
# not testing this, since order of input iterables in sets are not preserved
|
||||
# easily produces false reports since we're only checking the type of the
|
||||
# first item
|
||||
# (Set[int], set(["None", 2]), False, set(["None", 2])),
|
||||
(Set[Optional[int]], set([None, 2]), True, set([None, 2])),
|
||||
(Optional[Union[List[int], List[FakeBase]]], None, True, None),
|
||||
(Optional[Union[List[int], List[FakeBase]]], "foo", False, "foo"),
|
||||
(Union[List[int], List[FakeBase], None], "foo", False, "foo"),
|
||||
(Optional[Union[List[int], List[FakeBase]]], [1, 2, 3], True, [1, 2, 3]),
|
||||
(
|
||||
Optional[Union[List[int], List[FakeBase]]],
|
||||
fake_bases,
|
||||
True,
|
||||
fake_bases,
|
||||
),
|
||||
(List["int"], [2, 3, 4], True, [2, 3, 4]),
|
||||
],
|
||||
)
|
||||
def test_validate_type(
|
||||
|
||||
Reference in New Issue
Block a user