Skip to content

Commit 2cce17a

Browse files
Sort listed attributes (#47)
* sort attributes when being returned * add checks for proper attribute creation for longer names * add 4.5 to test versions * ruff check --fix * re-use proper list_attributes in bob * better tests * Update tests.yml * test also bob.list_attributes90 * Update tests.yml
1 parent ae7de09 commit 2cce17a

7 files changed

Lines changed: 309 additions & 31 deletions

File tree

.github/workflows/test-in-blender.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
max-parallel: 4
1414
fail-fast: false
1515
matrix:
16-
version: ["4.2", "4.3", "4.4", "daily"]
16+
version: ["4.2", "4.3", "4.4", "4.5", "daily"]
1717
os: [macos-14, ubuntu-latest, windows-latest]
1818
steps:
1919
- uses: actions/checkout@v4

.github/workflows/tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ jobs:
1313
max-parallel: 4
1414
fail-fast: false
1515
matrix:
16-
version: ["4.4"]
17-
os: [macos-14]
16+
version: [4.2, 4.3, 4.4, 4.5]
17+
os: [macos-latest, windows-latest, ubuntu-latest]
1818
steps:
1919
- uses: actions/checkout@v4
2020

@@ -26,7 +26,7 @@ jobs:
2626
- name: Install
2727
run: |
2828
uv sync --all-extras --dev
29-
uv pip install bpy==${{ matrix.version }}
29+
uv pip install bpy~=${{ matrix.version }}
3030
3131
- name: Run tests
3232
run: |

databpy/attribute.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,19 @@ def _check_is_mesh(obj: Object) -> None:
3131
def list_attributes(
3232
obj: Object, evaluate: bool = False, drop_hidden: bool = False
3333
) -> list[str]:
34-
_check_obj_attributes(obj)
35-
return list([name for name in obj.data.attributes.keys()])
34+
if evaluate:
35+
strings = list(evaluate_object(obj).data.attributes.keys())
36+
else:
37+
strings = list(obj.data.attributes.keys())
38+
39+
# return a sorted list of attribute names because there is inconsistency
40+
# between blender versions for the order of attributes being iterated over
41+
strings.sort()
42+
43+
if not drop_hidden:
44+
return strings
45+
46+
return [x for x in strings if not x.startswith(".")]
3647

3748

3849
@dataclass
@@ -454,10 +465,25 @@ def store_named_attribute(
454465
if atype is None:
455466
atype = guess_atype_from_array(data)
456467

468+
if name == "":
469+
raise NamedAttributeError("Attribute name cannot be an empty string.")
470+
457471
attribute = obj.data.attributes.get(name) # type: ignore
458472
if not attribute or not overwrite:
473+
current_names = obj.data.attributes.keys()
459474
attribute = obj.data.attributes.new(name, atype.value.type_name, domain.name)
460475

476+
if attribute is None:
477+
[
478+
obj.data.attributes.remove(obj.data.attributes[name])
479+
for name in obj.data.attributes.keys()
480+
if name not in current_names
481+
] # type: ignore
482+
raise NamedAttributeError(
483+
f"Could not create attribute `{name}` of type `{atype.value.type_name}` on domain `{domain.name}`. "
484+
"Potentially the attribute name is too long or there is no geometry on the object for the given domain."
485+
)
486+
461487
target_atype = AttributeTypes[attribute.data_type]
462488
if len(data) != len(attribute.data):
463489
raise NamedAttributeError(

databpy/object.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
AttributeDomain,
1414
AttributeDomains,
1515
AttributeTypes,
16+
list_attributes,
1617
_check_obj_attributes,
1718
evaluate_object,
1819
)
@@ -556,15 +557,7 @@ def list_attributes(
556557
list[str] | None
557558
A list of attribute names if the molecule object exists, None otherwise.
558559
"""
559-
if evaluate:
560-
strings = list(self.evaluate().data.attributes.keys())
561-
else:
562-
strings = list(self.object.data.attributes.keys())
563-
564-
if not drop_hidden:
565-
return strings
566-
else:
567-
return [x for x in strings if not x.startswith(".")]
560+
return list_attributes(self.object, evaluate=evaluate, drop_hidden=drop_hidden)
568561

569562
def __len__(self) -> int:
570563
"""
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# serializer version: 1
2+
# name: test_list_attributes[False-False]
3+
list([
4+
'.corner_edge',
5+
'.corner_vert',
6+
'.edge_verts',
7+
'.select_edge',
8+
'.select_poly',
9+
'.select_vert',
10+
'UVMap',
11+
'position',
12+
'sharp_face',
13+
])
14+
# ---
15+
# name: test_list_attributes[False-False].1
16+
list([
17+
'.corner_edge',
18+
'.corner_vert',
19+
'.edge_verts',
20+
'.select_edge',
21+
'.select_poly',
22+
'.select_vert',
23+
'UVMap',
24+
'a',
25+
'attr1',
26+
'attr_with_special_chars!@#$%^&*()',
27+
'longer_attribute_name',
28+
'medium_length',
29+
'position',
30+
'sharp_face',
31+
'short',
32+
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
33+
'数字属性',
34+
])
35+
# ---
36+
# name: test_list_attributes[False-True]
37+
list([
38+
'UVMap',
39+
'position',
40+
'sharp_face',
41+
])
42+
# ---
43+
# name: test_list_attributes[False-True].1
44+
list([
45+
'UVMap',
46+
'a',
47+
'attr1',
48+
'attr_with_special_chars!@#$%^&*()',
49+
'longer_attribute_name',
50+
'medium_length',
51+
'position',
52+
'sharp_face',
53+
'short',
54+
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
55+
'数字属性',
56+
])
57+
# ---
58+
# name: test_list_attributes[True-False]
59+
list([
60+
'.corner_edge',
61+
'.corner_vert',
62+
'.edge_verts',
63+
'.select_edge',
64+
'.select_poly',
65+
'.select_vert',
66+
'UVMap',
67+
'position',
68+
'sharp_face',
69+
])
70+
# ---
71+
# name: test_list_attributes[True-False].1
72+
list([
73+
'.corner_edge',
74+
'.corner_vert',
75+
'.edge_verts',
76+
'.select_edge',
77+
'.select_poly',
78+
'.select_vert',
79+
'UVMap',
80+
'a',
81+
'attr1',
82+
'attr_with_special_chars!@#$%^&*()',
83+
'longer_attribute_name',
84+
'medium_length',
85+
'position',
86+
'sharp_face',
87+
'short',
88+
'testing',
89+
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
90+
'数字属性',
91+
])
92+
# ---
93+
# name: test_list_attributes[True-True]
94+
list([
95+
'UVMap',
96+
'position',
97+
'sharp_face',
98+
])
99+
# ---
100+
# name: test_list_attributes[True-True].1
101+
list([
102+
'UVMap',
103+
'a',
104+
'attr1',
105+
'attr_with_special_chars!@#$%^&*()',
106+
'longer_attribute_name',
107+
'medium_length',
108+
'position',
109+
'sharp_face',
110+
'short',
111+
'testing',
112+
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
113+
'数字属性',
114+
])
115+
# ---
116+
# name: test_named_attribute_name
117+
list([
118+
'.corner_edge',
119+
'.corner_vert',
120+
'.edge_verts',
121+
'.select_edge',
122+
'.select_poly',
123+
'.select_vert',
124+
'UVMap',
125+
'a',
126+
'aa',
127+
'aaa',
128+
'aaaa',
129+
'aaaaa',
130+
'aaaaaa',
131+
'aaaaaaa',
132+
'aaaaaaaa',
133+
'aaaaaaaaa',
134+
'aaaaaaaaaa',
135+
'aaaaaaaaaaa',
136+
'aaaaaaaaaaaa',
137+
'aaaaaaaaaaaaa',
138+
'aaaaaaaaaaaaaa',
139+
'aaaaaaaaaaaaaaa',
140+
'aaaaaaaaaaaaaaaa',
141+
'aaaaaaaaaaaaaaaaa',
142+
'aaaaaaaaaaaaaaaaaa',
143+
'aaaaaaaaaaaaaaaaaaa',
144+
'aaaaaaaaaaaaaaaaaaaa',
145+
'aaaaaaaaaaaaaaaaaaaaa',
146+
'aaaaaaaaaaaaaaaaaaaaaa',
147+
'aaaaaaaaaaaaaaaaaaaaaaa',
148+
'aaaaaaaaaaaaaaaaaaaaaaaa',
149+
'aaaaaaaaaaaaaaaaaaaaaaaaa',
150+
'aaaaaaaaaaaaaaaaaaaaaaaaaa',
151+
'aaaaaaaaaaaaaaaaaaaaaaaaaaa',
152+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaa',
153+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
154+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
155+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
156+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
157+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
158+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
159+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
160+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
161+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
162+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
163+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
164+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
165+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
166+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
167+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
168+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
169+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
170+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
171+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
172+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
173+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
174+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
175+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
176+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
177+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
178+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
179+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
180+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
181+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
182+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
183+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
184+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
185+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
186+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
187+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
188+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
189+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
190+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
191+
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
192+
'position',
193+
'sharp_face',
194+
])
195+
# ---

tests/__snapshots__/test_bob.ambr

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
[-1., -1., -1.]])
1111
# ---
1212
# name: test_bob.1
13-
array([[-2.09603808e-03, -7.21023381e-01, -3.13093483e-01],
14-
[-4.39550936e-01, 5.03712118e-01, -1.86135709e+00],
15-
[-4.63244051e-01, 2.39126134e+00, -1.82179594e+00],
16-
[ 4.85980362e-01, -4.29094620e-02, 4.90632623e-01],
17-
[ 6.21735692e-01, -8.12329054e-01, -1.34520829e+00],
18-
[ 3.07357401e-01, 1.04044306e+00, -7.40214944e-01],
19-
[-1.11003029e+00, -5.92947364e-01, -1.00629151e+00],
20-
[ 4.81173426e-01, 7.55761325e-01, -1.12122655e+00]])
13+
array([[-1.40899801, -0.18262184, 0.88149434],
14+
[-2.42265749, -0.23832594, 0.53461844],
15+
[-0.81013453, 0.63205671, -0.12227035],
16+
[ 1.19240117, -1.59743011, -0.14498399],
17+
[ 0.73371911, -1.68970978, 0.35846812],
18+
[-1.06024873, -0.74044144, 1.20874739],
19+
[-1.69430518, 0.18745072, -2.24974346],
20+
[ 1.03262544, 0.02491132, -0.78184235]])
2121
# ---
2222
# name: test_get_position
2323
array([[ 1., 1., 1.],
@@ -40,12 +40,12 @@
4040
[-1., -1., -1.]])
4141
# ---
4242
# name: test_set_position.1
43-
array([[-0.18365459, 0.01642842, 1.66635835],
44-
[-1.79058218, -0.02525068, -0.37478185],
45-
[ 0.55500984, 0.89381772, -1.92875016],
46-
[-1.38086367, -2.55187011, -1.20552325],
47-
[-0.53758895, -1.00673819, -0.15946345],
48-
[-0.45155352, -0.01002919, -0.71784383],
49-
[ 0.01022454, -0.24301523, 2.18313527],
50-
[ 0.09924167, 0.41291735, 1.48610508]])
43+
array([[-1.02909052, -2.71057391, -0.04768289],
44+
[-0.67746568, -0.9472087 , -0.2236253 ],
45+
[-1.51190758, -1.18197215, -0.80486822],
46+
[-1.15094042, -0.64001381, 1.20405948],
47+
[-0.69383913, -1.56348133, 0.91123009],
48+
[-0.6464026 , -1.16587627, -0.93160886],
49+
[ 0.99367285, -0.8332808 , 0.61058164],
50+
[ 0.25490105, -0.72285438, 0.19398543]])
5151
# ---

0 commit comments

Comments
 (0)