bcf-api-xml 0.4.15__tar.gz → 0.4.16__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.
Files changed (28) hide show
  1. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/PKG-INFO +4 -1
  2. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/README.md +2 -0
  3. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/__init__.py +2 -2
  4. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/export/excel.py +69 -32
  5. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/pyproject.toml +1 -1
  6. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/Schemas/bcf.version +0 -0
  7. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/Schemas/markup.xsd +0 -0
  8. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/Schemas/project.xsd +0 -0
  9. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/Schemas/version.xsd +0 -0
  10. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/Schemas/visinfo.xsd +0 -0
  11. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/errors.py +0 -0
  12. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/export/__init__.py +0 -0
  13. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/export/zip.py +0 -0
  14. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/import_zip.py +0 -0
  15. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/ClippingPlane.py +0 -0
  16. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/Color.py +0 -0
  17. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/Comment.py +0 -0
  18. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/Component.py +0 -0
  19. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/Line.py +0 -0
  20. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/OrthogonalCamera.py +0 -0
  21. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/PerspectiveCamera.py +0 -0
  22. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/Topic.py +0 -0
  23. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/ViewSetupHints.py +0 -0
  24. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/Viewpoint.py +0 -0
  25. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/Visibility.py +0 -0
  26. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/VisualizationInfo.py +0 -0
  27. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/bcf_api_xml/models/XYZ.py +0 -0
  28. {bcf_api_xml-0.4.15 → bcf_api_xml-0.4.16}/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.15
3
+ Version: 0.4.16
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
  ```
@@ -27,6 +27,8 @@ pre-commit install
27
27
  ```
28
28
 
29
29
  # Publish new version
30
+ Update version number in `pyproject.toml` and `bcf_api_xml/__init__.py` then
31
+
30
32
  ```bash
31
33
  poetry publish --build --username= --password=
32
34
  ```
@@ -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.15"
7
+ __version__ = "0.4.16"
@@ -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,14 +20,15 @@ HEADER_TRANSLATIONS = {
15
20
  "author": "Author",
16
21
  "assigned_to": "Assigned to",
17
22
  "title": "Title",
18
- "description": "Description of the problem",
23
+ "description": "Description",
19
24
  "due_date": "Due date",
25
+ "stage": "Stage",
20
26
  "status": "Status",
21
27
  "priority": "Priority",
22
- "tags": "Tags",
28
+ "tags": "Labels",
23
29
  "comments": "Comments",
24
30
  "viewpoint": "Image",
25
- "models": "Name of model",
31
+ "models": "Models",
26
32
  "space": "Organisation",
27
33
  "project": "Project",
28
34
  },
@@ -32,14 +38,15 @@ HEADER_TRANSLATIONS = {
32
38
  "author": "Auteur",
33
39
  "assigned_to": "Assigné à",
34
40
  "title": "Titre",
35
- "description": "Description du problème",
41
+ "description": "Description",
36
42
  "due_date": "Date d'échéance",
43
+ "stage": "Phase",
37
44
  "status": "Statut",
38
45
  "priority": "Priorité",
39
46
  "tags": "Tags",
40
- "comments": "Commentaire du problème",
47
+ "comments": "Commentaires",
41
48
  "viewpoint": "Image",
42
- "models": "Nom du modèle",
49
+ "models": "Maquettes",
43
50
  "space": "Organisation",
44
51
  "project": "Project",
45
52
  },
@@ -53,14 +60,27 @@ TITLE_COL_INDEX = 4
53
60
  VIEWPOINT_COL_INDEX = 5
54
61
  DESCRIPTION_COL_INDEX = 6
55
62
  DUE_DATE_COL_INDEX = 7
56
- STATUS_COL_INDEX = 8
57
- PRIORITY_COL_INDEX = 9
58
- TAGS_COL_INDEX = 10
59
- COMMENTS_COL_INDEX = 11
63
+ STAGE_COL_INDEX = 8
64
+ STATUS_COL_INDEX = 9
65
+ PRIORITY_COL_INDEX = 10
66
+ LABELS_COL_INDEX = 11
67
+ COMMENTS_COL_INDEX = 12
68
+ MODELS_COL_INDEX = 13
69
+
70
+ LAST_USED_COL_INDEX = MODELS_COL_INDEX
71
+ LAST_USED_COL_LETTER = col_to_letter(LAST_USED_COL_INDEX)
60
72
 
61
73
 
62
74
  def to_xlsx(
63
- space, project, models, topics, comments, viewpoints, company_logo_content, lang="en"
75
+ space,
76
+ project,
77
+ models,
78
+ topics,
79
+ comments,
80
+ viewpoints,
81
+ company_logo_content,
82
+ lang="en",
83
+ sheetname=None,
64
84
  ):
65
85
  """
66
86
  topics: list of topics (dict parsed from BCF-API json)
@@ -69,7 +89,10 @@ def to_xlsx(
69
89
  """
70
90
  xls_file = io.BytesIO()
71
91
  with xlsxwriter.Workbook(xls_file, options={"remove_timezone": True}) as workbook:
72
- worksheet = workbook.add_worksheet()
92
+ if sheetname:
93
+ worksheet = workbook.add_worksheet(sheetname)
94
+ else:
95
+ worksheet = workbook.add_worksheet()
73
96
 
74
97
  # Set default height for tables
75
98
  DEFAULT_CELL_HEIGHT = 220
@@ -86,22 +109,30 @@ def to_xlsx(
86
109
 
87
110
  # Set image cell width
88
111
  IMAGE_COLUMN_WIDTH = 220
89
- worksheet.set_column_pixels(VIEWPOINT_COL_INDEX, VIEWPOINT_COL_INDEX, IMAGE_COLUMN_WIDTH)
112
+ worksheet.set_column_pixels(
113
+ VIEWPOINT_COL_INDEX, VIEWPOINT_COL_INDEX, IMAGE_COLUMN_WIDTH
114
+ )
90
115
 
91
116
  header_fmt = workbook.add_format(
92
- {"align": "center", "bold": True, "bg_color": "#C0C0C0", "border": 1}
117
+ {
118
+ "valign": "vcenter",
119
+ "align": "center",
120
+ "bold": True,
121
+ "bg_color": "#C0C0C0",
122
+ "border": 1,
123
+ }
93
124
  )
94
125
  base_fmt = workbook.add_format({"valign": "top", "border": 1})
95
126
  if lang == "fr":
96
127
  date_fmt = workbook.add_format(
97
- {"valign": "top", "num_format": "dd/mm/yyyy", "border": 1}
128
+ {"align": "left", "valign": "top", "num_format": "dd/mm/yyyy", "border": 1}
98
129
  )
99
130
  else:
100
131
  date_fmt = workbook.add_format(
101
- {"valign": "top", "num_format": "yyyy-mm-dd", "border": 1}
132
+ {"align": "left", "valign": "top", "num_format": "yyyy-mm-dd", "border": 1}
102
133
  )
103
134
 
104
- comments_fmt = workbook.add_format({"valign": "top", "text_wrap": True, "border": 1})
135
+ text_wrap_fmt = workbook.add_format({"valign": "top", "text_wrap": True, "border": 1})
105
136
  header_fmt2 = workbook.add_format({"border": 1})
106
137
  base_fm_align = workbook.add_format({"align": "center", "valign": "top"})
107
138
 
@@ -152,31 +183,29 @@ def to_xlsx(
152
183
  },
153
184
  )
154
185
 
155
- worksheet.merge_range("D1:Z1", "", merge_format_gray)
186
+ worksheet.merge_range(f"D1:{LAST_USED_COL_LETTER}1", "", merge_format_gray)
156
187
  row += 1
157
188
  worksheet.set_row(row, 20)
158
- worksheet.merge_range("A2:Z2", "", merge_format_default)
189
+ worksheet.merge_range(f"A2:{LAST_USED_COL_LETTER}2", "", merge_format_default)
159
190
  row += 1
160
191
  worksheet.set_row_pixels(row, ROW_HEIGHT)
161
192
  worksheet.merge_range("A3:B3", "", merge_format_default)
162
193
  worksheet.write(row, 0, headers["project"], header_fmt)
163
- worksheet.merge_range("C3:Z3", "", merge_format_default)
194
+ worksheet.merge_range(f"C3:{LAST_USED_COL_LETTER}3", "", merge_format_default)
164
195
  worksheet.write(row, 2, project["name"], header_fmt2)
165
196
 
166
- # TODO: add spreadsheet metadata for models
167
-
168
197
  row += 1
169
198
  worksheet.set_row_pixels(row, ROW_HEIGHT)
170
199
  worksheet.merge_range("A4:B4", "", merge_format_default)
171
200
  worksheet.write(row, 0, headers["space"], header_fmt)
172
- worksheet.merge_range("C4:Z4", "", merge_format_default)
201
+ worksheet.merge_range(f"C4:{LAST_USED_COL_LETTER}4", "", merge_format_default)
173
202
  worksheet.write(row, 2, space["name"], header_fmt2)
174
203
 
175
204
  row += 1
176
205
  worksheet.set_row_pixels(row, ROW_HEIGHT)
177
206
  worksheet.merge_range("A5:B5", "", merge_format_default)
178
207
  worksheet.write(row, 0, "Date", header_fmt)
179
- worksheet.merge_range("C5:Z5", "", merge_format_default)
208
+ worksheet.merge_range(f"C5:{LAST_USED_COL_LETTER}5", "", merge_format_default)
180
209
  if lang == "fr":
181
210
  current_time = datetime.now().strftime("%d/%m/%Y, %H:%M:%S")
182
211
  else:
@@ -185,7 +214,7 @@ def to_xlsx(
185
214
 
186
215
  row += 1
187
216
  worksheet.set_row(row, 20)
188
- worksheet.merge_range("A6:Z6", "", merge_format_default)
217
+ worksheet.merge_range(f"A6:{LAST_USED_COL_LETTER}6", "", merge_format_default)
189
218
  row += 1
190
219
 
191
220
  # Set topic row height
@@ -194,18 +223,21 @@ def to_xlsx(
194
223
  # Create table header
195
224
  worksheet.write(row, INDEX_COL_INDEX, headers["index"], header_fmt)
196
225
  worksheet.write(row, CREATION_DATE_COL_INDEX, headers["creation_date"], header_fmt)
226
+ worksheet.set_column_pixels(CREATION_DATE_COL_INDEX, CREATION_DATE_COL_INDEX, 100)
197
227
  worksheet.write(row, AUTHOR_COL_INDEX, headers["author"], header_fmt)
198
228
  worksheet.write(row, ASSIGNED_TO_COL_INDEX, headers["assigned_to"], header_fmt)
199
229
  worksheet.write(row, TITLE_COL_INDEX, headers["title"], header_fmt)
200
230
  worksheet.write(row, VIEWPOINT_COL_INDEX, headers["viewpoint"], header_fmt)
201
231
  worksheet.write(row, DESCRIPTION_COL_INDEX, headers["description"], header_fmt)
202
232
  worksheet.write(row, DUE_DATE_COL_INDEX, headers["due_date"], header_fmt)
233
+ worksheet.write(row, STAGE_COL_INDEX, headers["stage"], header_fmt)
203
234
  worksheet.write(row, STATUS_COL_INDEX, headers["status"], header_fmt)
204
235
  worksheet.write(row, PRIORITY_COL_INDEX, headers["priority"], header_fmt)
205
- worksheet.write(row, TAGS_COL_INDEX, headers["tags"], header_fmt)
236
+ worksheet.write(row, LABELS_COL_INDEX, headers["tags"], header_fmt)
206
237
  worksheet.write(row, COMMENTS_COL_INDEX, headers["comments"], header_fmt)
207
- worksheet.set_column_pixels(10, 10, 100)
208
- worksheet.set_column_pixels(11, 11, 200)
238
+ worksheet.set_column_pixels(LABELS_COL_INDEX, LABELS_COL_INDEX, 100)
239
+ worksheet.set_column_pixels(COMMENTS_COL_INDEX, COMMENTS_COL_INDEX, 200)
240
+ worksheet.write(row, MODELS_COL_INDEX, headers["models"], header_fmt)
209
241
  row += 1
210
242
 
211
243
  # Sort topic by index
@@ -232,12 +264,13 @@ def to_xlsx(
232
264
  worksheet.write_datetime(row, DUE_DATE_COL_INDEX, due_date, date_fmt)
233
265
  else:
234
266
  worksheet.write(row, DUE_DATE_COL_INDEX, "", base_fmt)
267
+ worksheet.write(row, STAGE_COL_INDEX, topic.get("stage"), base_fmt)
235
268
  worksheet.write(row, STATUS_COL_INDEX, topic.get("topic_status"), base_fmt)
236
269
  worksheet.write(row, PRIORITY_COL_INDEX, topic.get("priority"), base_fmt)
237
270
 
238
- concatenated_tags = ", ".join(topic.get("labels", []))
271
+ concatenated_labels = ", ".join(topic.get("labels", []))
239
272
 
240
- worksheet.write(row, TAGS_COL_INDEX, concatenated_tags, base_fmt)
273
+ worksheet.write(row, LABELS_COL_INDEX, concatenated_labels, base_fmt)
241
274
 
242
275
  concatenated_comments = ""
243
276
 
@@ -250,7 +283,11 @@ def to_xlsx(
250
283
  concatenated_comments += (
251
284
  f"[{comment_date}] {comment['author']}: {comment['comment']}\n"
252
285
  )
253
- worksheet.write(row, COMMENTS_COL_INDEX, concatenated_comments, comments_fmt)
286
+ worksheet.write(row, COMMENTS_COL_INDEX, concatenated_comments, text_wrap_fmt)
287
+
288
+ concatenated_models = "\n".join(topic.get("models", []))
289
+
290
+ worksheet.write(row, MODELS_COL_INDEX, concatenated_models, text_wrap_fmt)
254
291
 
255
292
  if len(topic_viewpoints):
256
293
  viewpoint = topic_viewpoints[0]
@@ -287,7 +324,7 @@ def to_xlsx(
287
324
  worksheet.write(row, VIEWPOINT_COL_INDEX, "", base_fmt)
288
325
 
289
326
  row += 1
290
- worksheet.set_column("M:Z", None, None, {"hidden": True})
327
+
291
328
  worksheet.set_default_row(hide_unused_rows=True)
292
329
 
293
330
  worksheet.autofit()
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "bcf-api-xml"
3
- version = "0.4.15"
3
+ version = "0.4.16"
4
4
  description = "Convert BCF-API to BCF-XML"
5
5
  authors = ["Hugo Duroux <hugo@bimdata.io>"]
6
6
  license = "MIT"