bcf-api-xml 0.4.15__tar.gz → 0.4.17__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/PKG-INFO +4 -1
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/README.md +2 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/__init__.py +2 -2
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/export/excel.py +73 -34
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/pyproject.toml +1 -1
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/Schemas/bcf.version +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/Schemas/markup.xsd +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/Schemas/project.xsd +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/Schemas/version.xsd +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/Schemas/visinfo.xsd +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/errors.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/export/__init__.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/export/zip.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/import_zip.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/ClippingPlane.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/Color.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/Comment.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/Component.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/Line.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/OrthogonalCamera.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/PerspectiveCamera.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/Topic.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/ViewSetupHints.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/Viewpoint.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/Visibility.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/VisualizationInfo.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/XYZ.py +0 -0
- {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.17}/bcf_api_xml/models/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: bcf-api-xml
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.17
|
4
4
|
Summary: Convert BCF-API to BCF-XML
|
5
5
|
Home-page: https://github.com/bimdata/BCF-API-XML-translator
|
6
6
|
License: MIT
|
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
15
16
|
Requires-Dist: generateDS (>=2.35.13,<3.0.0)
|
16
17
|
Requires-Dist: lxml (>=5.3.1,<6.0.0)
|
17
18
|
Requires-Dist: pillow (>=11.1.0,<12.0.0)
|
@@ -49,6 +50,8 @@ pre-commit install
|
|
49
50
|
```
|
50
51
|
|
51
52
|
# Publish new version
|
53
|
+
Update version number in `pyproject.toml` and `bcf_api_xml/__init__.py` then
|
54
|
+
|
52
55
|
```bash
|
53
56
|
poetry publish --build --username= --password=
|
54
57
|
```
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from bcf_api_xml.errors import InvalidBCF # noqa: F401
|
2
2
|
from bcf_api_xml.errors import UnsupportedBCFVersion # noqa: F401
|
3
|
-
from bcf_api_xml.export import to_zip # noqa: F401
|
4
3
|
from bcf_api_xml.export import to_xlsx # noqa: F401
|
4
|
+
from bcf_api_xml.export import to_zip # noqa: F401
|
5
5
|
from bcf_api_xml.import_zip import to_json # noqa: F401
|
6
6
|
|
7
|
-
__version__ = "0.4.
|
7
|
+
__version__ = "0.4.17"
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import base64
|
2
2
|
import io
|
3
|
+
import string
|
3
4
|
from datetime import datetime
|
4
5
|
|
5
6
|
import requests
|
@@ -8,6 +9,10 @@ from dateutil import parser
|
|
8
9
|
from PIL import Image
|
9
10
|
|
10
11
|
|
12
|
+
def col_to_letter(index):
|
13
|
+
return string.ascii_uppercase[index]
|
14
|
+
|
15
|
+
|
11
16
|
HEADER_TRANSLATIONS = {
|
12
17
|
"en": {
|
13
18
|
"index": "Index",
|
@@ -15,16 +20,18 @@ HEADER_TRANSLATIONS = {
|
|
15
20
|
"author": "Author",
|
16
21
|
"assigned_to": "Assigned to",
|
17
22
|
"title": "Title",
|
18
|
-
"description": "Description
|
23
|
+
"description": "Description",
|
19
24
|
"due_date": "Due date",
|
25
|
+
"stage": "Stage",
|
20
26
|
"status": "Status",
|
21
27
|
"priority": "Priority",
|
22
|
-
"tags": "
|
28
|
+
"tags": "Labels",
|
23
29
|
"comments": "Comments",
|
24
30
|
"viewpoint": "Image",
|
25
|
-
"models": "
|
31
|
+
"models": "Models",
|
26
32
|
"space": "Organisation",
|
27
33
|
"project": "Project",
|
34
|
+
"sheetname": "BCF list",
|
28
35
|
},
|
29
36
|
"fr": {
|
30
37
|
"index": "N°",
|
@@ -32,16 +39,18 @@ HEADER_TRANSLATIONS = {
|
|
32
39
|
"author": "Auteur",
|
33
40
|
"assigned_to": "Assigné à",
|
34
41
|
"title": "Titre",
|
35
|
-
"description": "Description
|
42
|
+
"description": "Description",
|
36
43
|
"due_date": "Date d'échéance",
|
44
|
+
"stage": "Phase",
|
37
45
|
"status": "Statut",
|
38
46
|
"priority": "Priorité",
|
39
47
|
"tags": "Tags",
|
40
|
-
"comments": "
|
48
|
+
"comments": "Commentaires",
|
41
49
|
"viewpoint": "Image",
|
42
|
-
"models": "
|
50
|
+
"models": "Maquettes",
|
43
51
|
"space": "Organisation",
|
44
52
|
"project": "Project",
|
53
|
+
"sheetname": "Liste des BCF",
|
45
54
|
},
|
46
55
|
}
|
47
56
|
|
@@ -53,23 +62,41 @@ TITLE_COL_INDEX = 4
|
|
53
62
|
VIEWPOINT_COL_INDEX = 5
|
54
63
|
DESCRIPTION_COL_INDEX = 6
|
55
64
|
DUE_DATE_COL_INDEX = 7
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
65
|
+
STAGE_COL_INDEX = 8
|
66
|
+
STATUS_COL_INDEX = 9
|
67
|
+
PRIORITY_COL_INDEX = 10
|
68
|
+
LABELS_COL_INDEX = 11
|
69
|
+
COMMENTS_COL_INDEX = 12
|
70
|
+
MODELS_COL_INDEX = 13
|
71
|
+
|
72
|
+
LAST_USED_COL_INDEX = MODELS_COL_INDEX
|
73
|
+
LAST_USED_COL_LETTER = col_to_letter(LAST_USED_COL_INDEX)
|
60
74
|
|
61
75
|
|
62
76
|
def to_xlsx(
|
63
|
-
space,
|
77
|
+
space,
|
78
|
+
project,
|
79
|
+
models,
|
80
|
+
topics,
|
81
|
+
comments,
|
82
|
+
viewpoints,
|
83
|
+
company_logo_content,
|
84
|
+
lang="en",
|
85
|
+
sheetname=None,
|
64
86
|
):
|
65
87
|
"""
|
66
88
|
topics: list of topics (dict parsed from BCF-API json)
|
67
89
|
comments: dict(topics_guid=[comment])
|
68
90
|
viewpoints: dict(topics_guid=[viewpoint])
|
69
91
|
"""
|
92
|
+
headers = HEADER_TRANSLATIONS[lang]
|
93
|
+
|
70
94
|
xls_file = io.BytesIO()
|
71
95
|
with xlsxwriter.Workbook(xls_file, options={"remove_timezone": True}) as workbook:
|
72
|
-
|
96
|
+
if sheetname:
|
97
|
+
worksheet = workbook.add_worksheet(sheetname)
|
98
|
+
else:
|
99
|
+
worksheet = workbook.add_worksheet(headers["sheetname"])
|
73
100
|
|
74
101
|
# Set default height for tables
|
75
102
|
DEFAULT_CELL_HEIGHT = 220
|
@@ -86,27 +113,33 @@ def to_xlsx(
|
|
86
113
|
|
87
114
|
# Set image cell width
|
88
115
|
IMAGE_COLUMN_WIDTH = 220
|
89
|
-
worksheet.set_column_pixels(
|
116
|
+
worksheet.set_column_pixels(
|
117
|
+
VIEWPOINT_COL_INDEX, VIEWPOINT_COL_INDEX, IMAGE_COLUMN_WIDTH
|
118
|
+
)
|
90
119
|
|
91
120
|
header_fmt = workbook.add_format(
|
92
|
-
{
|
121
|
+
{
|
122
|
+
"valign": "vcenter",
|
123
|
+
"align": "center",
|
124
|
+
"bold": True,
|
125
|
+
"bg_color": "#C0C0C0",
|
126
|
+
"border": 1,
|
127
|
+
}
|
93
128
|
)
|
94
129
|
base_fmt = workbook.add_format({"valign": "top", "border": 1})
|
95
130
|
if lang == "fr":
|
96
131
|
date_fmt = workbook.add_format(
|
97
|
-
{"valign": "top", "num_format": "dd/mm/yyyy", "border": 1}
|
132
|
+
{"align": "left", "valign": "top", "num_format": "dd/mm/yyyy", "border": 1}
|
98
133
|
)
|
99
134
|
else:
|
100
135
|
date_fmt = workbook.add_format(
|
101
|
-
{"valign": "top", "num_format": "yyyy-mm-dd", "border": 1}
|
136
|
+
{"align": "left", "valign": "top", "num_format": "yyyy-mm-dd", "border": 1}
|
102
137
|
)
|
103
138
|
|
104
|
-
|
139
|
+
text_wrap_fmt = workbook.add_format({"valign": "top", "text_wrap": True, "border": 1})
|
105
140
|
header_fmt2 = workbook.add_format({"border": 1})
|
106
141
|
base_fm_align = workbook.add_format({"align": "center", "valign": "top"})
|
107
142
|
|
108
|
-
headers = HEADER_TRANSLATIONS[lang]
|
109
|
-
|
110
143
|
# Company Logo followed by date, espace, space, models
|
111
144
|
row = 0
|
112
145
|
|
@@ -152,31 +185,29 @@ def to_xlsx(
|
|
152
185
|
},
|
153
186
|
)
|
154
187
|
|
155
|
-
worksheet.merge_range("D1:
|
188
|
+
worksheet.merge_range(f"D1:{LAST_USED_COL_LETTER}1", "", merge_format_gray)
|
156
189
|
row += 1
|
157
190
|
worksheet.set_row(row, 20)
|
158
|
-
worksheet.merge_range("A2:
|
191
|
+
worksheet.merge_range(f"A2:{LAST_USED_COL_LETTER}2", "", merge_format_default)
|
159
192
|
row += 1
|
160
193
|
worksheet.set_row_pixels(row, ROW_HEIGHT)
|
161
194
|
worksheet.merge_range("A3:B3", "", merge_format_default)
|
162
195
|
worksheet.write(row, 0, headers["project"], header_fmt)
|
163
|
-
worksheet.merge_range("C3:
|
196
|
+
worksheet.merge_range(f"C3:{LAST_USED_COL_LETTER}3", "", merge_format_default)
|
164
197
|
worksheet.write(row, 2, project["name"], header_fmt2)
|
165
198
|
|
166
|
-
# TODO: add spreadsheet metadata for models
|
167
|
-
|
168
199
|
row += 1
|
169
200
|
worksheet.set_row_pixels(row, ROW_HEIGHT)
|
170
201
|
worksheet.merge_range("A4:B4", "", merge_format_default)
|
171
202
|
worksheet.write(row, 0, headers["space"], header_fmt)
|
172
|
-
worksheet.merge_range("C4:
|
203
|
+
worksheet.merge_range(f"C4:{LAST_USED_COL_LETTER}4", "", merge_format_default)
|
173
204
|
worksheet.write(row, 2, space["name"], header_fmt2)
|
174
205
|
|
175
206
|
row += 1
|
176
207
|
worksheet.set_row_pixels(row, ROW_HEIGHT)
|
177
208
|
worksheet.merge_range("A5:B5", "", merge_format_default)
|
178
209
|
worksheet.write(row, 0, "Date", header_fmt)
|
179
|
-
worksheet.merge_range("C5:
|
210
|
+
worksheet.merge_range(f"C5:{LAST_USED_COL_LETTER}5", "", merge_format_default)
|
180
211
|
if lang == "fr":
|
181
212
|
current_time = datetime.now().strftime("%d/%m/%Y, %H:%M:%S")
|
182
213
|
else:
|
@@ -185,7 +216,7 @@ def to_xlsx(
|
|
185
216
|
|
186
217
|
row += 1
|
187
218
|
worksheet.set_row(row, 20)
|
188
|
-
worksheet.merge_range("A6:
|
219
|
+
worksheet.merge_range(f"A6:{LAST_USED_COL_LETTER}6", "", merge_format_default)
|
189
220
|
row += 1
|
190
221
|
|
191
222
|
# Set topic row height
|
@@ -194,18 +225,21 @@ def to_xlsx(
|
|
194
225
|
# Create table header
|
195
226
|
worksheet.write(row, INDEX_COL_INDEX, headers["index"], header_fmt)
|
196
227
|
worksheet.write(row, CREATION_DATE_COL_INDEX, headers["creation_date"], header_fmt)
|
228
|
+
worksheet.set_column_pixels(CREATION_DATE_COL_INDEX, CREATION_DATE_COL_INDEX, 100)
|
197
229
|
worksheet.write(row, AUTHOR_COL_INDEX, headers["author"], header_fmt)
|
198
230
|
worksheet.write(row, ASSIGNED_TO_COL_INDEX, headers["assigned_to"], header_fmt)
|
199
231
|
worksheet.write(row, TITLE_COL_INDEX, headers["title"], header_fmt)
|
200
232
|
worksheet.write(row, VIEWPOINT_COL_INDEX, headers["viewpoint"], header_fmt)
|
201
233
|
worksheet.write(row, DESCRIPTION_COL_INDEX, headers["description"], header_fmt)
|
202
234
|
worksheet.write(row, DUE_DATE_COL_INDEX, headers["due_date"], header_fmt)
|
235
|
+
worksheet.write(row, STAGE_COL_INDEX, headers["stage"], header_fmt)
|
203
236
|
worksheet.write(row, STATUS_COL_INDEX, headers["status"], header_fmt)
|
204
237
|
worksheet.write(row, PRIORITY_COL_INDEX, headers["priority"], header_fmt)
|
205
|
-
worksheet.write(row,
|
238
|
+
worksheet.write(row, LABELS_COL_INDEX, headers["tags"], header_fmt)
|
206
239
|
worksheet.write(row, COMMENTS_COL_INDEX, headers["comments"], header_fmt)
|
207
|
-
worksheet.set_column_pixels(
|
208
|
-
worksheet.set_column_pixels(
|
240
|
+
worksheet.set_column_pixels(LABELS_COL_INDEX, LABELS_COL_INDEX, 100)
|
241
|
+
worksheet.set_column_pixels(COMMENTS_COL_INDEX, COMMENTS_COL_INDEX, 200)
|
242
|
+
worksheet.write(row, MODELS_COL_INDEX, headers["models"], header_fmt)
|
209
243
|
row += 1
|
210
244
|
|
211
245
|
# Sort topic by index
|
@@ -232,12 +266,13 @@ def to_xlsx(
|
|
232
266
|
worksheet.write_datetime(row, DUE_DATE_COL_INDEX, due_date, date_fmt)
|
233
267
|
else:
|
234
268
|
worksheet.write(row, DUE_DATE_COL_INDEX, "", base_fmt)
|
269
|
+
worksheet.write(row, STAGE_COL_INDEX, topic.get("stage"), base_fmt)
|
235
270
|
worksheet.write(row, STATUS_COL_INDEX, topic.get("topic_status"), base_fmt)
|
236
271
|
worksheet.write(row, PRIORITY_COL_INDEX, topic.get("priority"), base_fmt)
|
237
272
|
|
238
|
-
|
273
|
+
concatenated_labels = ", ".join(topic.get("labels", []))
|
239
274
|
|
240
|
-
worksheet.write(row,
|
275
|
+
worksheet.write(row, LABELS_COL_INDEX, concatenated_labels, base_fmt)
|
241
276
|
|
242
277
|
concatenated_comments = ""
|
243
278
|
|
@@ -250,7 +285,11 @@ def to_xlsx(
|
|
250
285
|
concatenated_comments += (
|
251
286
|
f"[{comment_date}] {comment['author']}: {comment['comment']}\n"
|
252
287
|
)
|
253
|
-
worksheet.write(row, COMMENTS_COL_INDEX, concatenated_comments,
|
288
|
+
worksheet.write(row, COMMENTS_COL_INDEX, concatenated_comments, text_wrap_fmt)
|
289
|
+
|
290
|
+
concatenated_models = "\n".join(topic.get("models", []))
|
291
|
+
|
292
|
+
worksheet.write(row, MODELS_COL_INDEX, concatenated_models, text_wrap_fmt)
|
254
293
|
|
255
294
|
if len(topic_viewpoints):
|
256
295
|
viewpoint = topic_viewpoints[0]
|
@@ -287,7 +326,7 @@ def to_xlsx(
|
|
287
326
|
worksheet.write(row, VIEWPOINT_COL_INDEX, "", base_fmt)
|
288
327
|
|
289
328
|
row += 1
|
290
|
-
|
329
|
+
|
291
330
|
worksheet.set_default_row(hide_unused_rows=True)
|
292
331
|
|
293
332
|
worksheet.autofit()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|