albert 1.14.0__tar.gz → 1.16.0__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 (306) hide show
  1. albert-1.16.0/.github/workflows/release-please.yml +19 -0
  2. albert-1.16.0/.release-please-manifest.json +1 -0
  3. albert-1.16.0/AGENTS.md +163 -0
  4. {albert-1.14.0 → albert-1.16.0}/CHANGELOG.md +19 -0
  5. {albert-1.14.0 → albert-1.16.0}/PKG-INFO +1 -1
  6. albert-1.16.0/docs/assets/Albert_Wordmark_Mono_RGB_White.svg +15 -0
  7. albert-1.16.0/docs/assets/Albert_Wordmark_RGB_Colour.svg +15 -0
  8. albert-1.16.0/docs/assets/favicon_bw.svg +4 -0
  9. {albert-1.14.0 → albert-1.16.0}/docs/index.md +2 -2
  10. {albert-1.14.0 → albert-1.16.0}/docs/styles/extra.css +9 -2
  11. {albert-1.14.0 → albert-1.16.0}/mkdocs.yml +2 -2
  12. albert-1.16.0/release-please-config.json +10 -0
  13. {albert-1.14.0 → albert-1.16.0}/src/albert/__init__.py +1 -1
  14. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/attachments.py +45 -1
  15. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/btinsight.py +9 -8
  16. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/cas.py +1 -1
  17. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/companies.py +3 -3
  18. albert-1.16.0/src/albert/collections/custom_templates.py +414 -0
  19. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/data_columns.py +4 -3
  20. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/data_templates.py +1 -1
  21. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/entity_types.py +2 -2
  22. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/inventory.py +8 -8
  23. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/lists.py +1 -1
  24. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/locations.py +3 -3
  25. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/lots.py +11 -28
  26. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/notes.py +1 -1
  27. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/parameter_groups.py +3 -2
  28. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/parameters.py +4 -4
  29. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/projects.py +44 -3
  30. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/property_data.py +4 -7
  31. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/storage_locations.py +3 -3
  32. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/tags.py +3 -2
  33. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/tasks.py +6 -3
  34. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/units.py +4 -3
  35. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/users.py +2 -2
  36. albert-1.16.0/src/albert/core/utils.py +20 -0
  37. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/custom_templates.py +32 -10
  38. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/projects.py +16 -1
  39. albert-1.16.0/src/albert/resources/tags.py +61 -0
  40. albert-1.16.0/tests/collections/test_custom_templates.py +99 -0
  41. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_inventory.py +7 -25
  42. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_projects.py +22 -1
  43. {albert-1.14.0 → albert-1.16.0}/tests/conftest.py +47 -0
  44. albert-1.14.0/docs/assets/Vector_Favicon_Blue.svg +0 -4
  45. albert-1.14.0/docs/assets/Wordmark_Black.png +0 -0
  46. albert-1.14.0/docs/assets/Wordmark_White.png +0 -0
  47. albert-1.14.0/src/albert/collections/custom_templates.py +0 -125
  48. albert-1.14.0/src/albert/resources/tags.py +0 -101
  49. albert-1.14.0/tests/collections/test_custom_templates.py +0 -60
  50. {albert-1.14.0 → albert-1.16.0}/.circleci/config.yml +0 -0
  51. {albert-1.14.0 → albert-1.16.0}/.gitignore +0 -0
  52. {albert-1.14.0 → albert-1.16.0}/.pre-commit-config.yaml +0 -0
  53. {albert-1.14.0 → albert-1.16.0}/.vscode/settings.json +0 -0
  54. {albert-1.14.0 → albert-1.16.0}/CONTRIBUTING.md +0 -0
  55. {albert-1.14.0 → albert-1.16.0}/LICENSE +0 -0
  56. {albert-1.14.0 → albert-1.16.0}/README.md +0 -0
  57. {albert-1.14.0 → albert-1.16.0}/docs/CONTRIBUTING.md +0 -0
  58. {albert-1.14.0 → albert-1.16.0}/docs/albert.md +0 -0
  59. {albert-1.14.0 → albert-1.16.0}/docs/authentication.md +0 -0
  60. {albert-1.14.0 → albert-1.16.0}/docs/collections/activities.md +0 -0
  61. {albert-1.14.0 → albert-1.16.0}/docs/collections/attachments.md +0 -0
  62. {albert-1.14.0 → albert-1.16.0}/docs/collections/base.md +0 -0
  63. {albert-1.14.0 → albert-1.16.0}/docs/collections/batch_data.md +0 -0
  64. {albert-1.14.0 → albert-1.16.0}/docs/collections/btdataset.md +0 -0
  65. {albert-1.14.0 → albert-1.16.0}/docs/collections/btinsight.md +0 -0
  66. {albert-1.14.0 → albert-1.16.0}/docs/collections/btmodel.md +0 -0
  67. {albert-1.14.0 → albert-1.16.0}/docs/collections/cas.md +0 -0
  68. {albert-1.14.0 → albert-1.16.0}/docs/collections/companies.md +0 -0
  69. {albert-1.14.0 → albert-1.16.0}/docs/collections/custom_fields.md +0 -0
  70. {albert-1.14.0 → albert-1.16.0}/docs/collections/custom_templates.md +0 -0
  71. {albert-1.14.0 → albert-1.16.0}/docs/collections/data_columns.md +0 -0
  72. {albert-1.14.0 → albert-1.16.0}/docs/collections/data_templates.md +0 -0
  73. {albert-1.14.0 → albert-1.16.0}/docs/collections/entity_types.md +0 -0
  74. {albert-1.14.0 → albert-1.16.0}/docs/collections/files.md +0 -0
  75. {albert-1.14.0 → albert-1.16.0}/docs/collections/hazards.md +0 -0
  76. {albert-1.14.0 → albert-1.16.0}/docs/collections/inventory.md +0 -0
  77. {albert-1.14.0 → albert-1.16.0}/docs/collections/links.md +0 -0
  78. {albert-1.14.0 → albert-1.16.0}/docs/collections/lists.md +0 -0
  79. {albert-1.14.0 → albert-1.16.0}/docs/collections/locations.md +0 -0
  80. {albert-1.14.0 → albert-1.16.0}/docs/collections/lots.md +0 -0
  81. {albert-1.14.0 → albert-1.16.0}/docs/collections/notebooks.md +0 -0
  82. {albert-1.14.0 → albert-1.16.0}/docs/collections/notes.md +0 -0
  83. {albert-1.14.0 → albert-1.16.0}/docs/collections/parameter_groups.md +0 -0
  84. {albert-1.14.0 → albert-1.16.0}/docs/collections/parameters.md +0 -0
  85. {albert-1.14.0 → albert-1.16.0}/docs/collections/pricings.md +0 -0
  86. {albert-1.14.0 → albert-1.16.0}/docs/collections/product_design.md +0 -0
  87. {albert-1.14.0 → albert-1.16.0}/docs/collections/projects.md +0 -0
  88. {albert-1.14.0 → albert-1.16.0}/docs/collections/property_data.md +0 -0
  89. {albert-1.14.0 → albert-1.16.0}/docs/collections/reports.md +0 -0
  90. {albert-1.14.0 → albert-1.16.0}/docs/collections/roles.md +0 -0
  91. {albert-1.14.0 → albert-1.16.0}/docs/collections/storage_classes.md +0 -0
  92. {albert-1.14.0 → albert-1.16.0}/docs/collections/storage_locations.md +0 -0
  93. {albert-1.14.0 → albert-1.16.0}/docs/collections/substances.md +0 -0
  94. {albert-1.14.0 → albert-1.16.0}/docs/collections/synthesis.md +0 -0
  95. {albert-1.14.0 → albert-1.16.0}/docs/collections/tags.md +0 -0
  96. {albert-1.14.0 → albert-1.16.0}/docs/collections/tasks.md +0 -0
  97. {albert-1.14.0 → albert-1.16.0}/docs/collections/un_numbers.md +0 -0
  98. {albert-1.14.0 → albert-1.16.0}/docs/collections/units.md +0 -0
  99. {albert-1.14.0 → albert-1.16.0}/docs/collections/users.md +0 -0
  100. {albert-1.14.0 → albert-1.16.0}/docs/collections/workflows.md +0 -0
  101. {albert-1.14.0 → albert-1.16.0}/docs/collections/worksheets.md +0 -0
  102. {albert-1.14.0 → albert-1.16.0}/docs/concepts.md +0 -0
  103. {albert-1.14.0 → albert-1.16.0}/docs/configuration.md +0 -0
  104. {albert-1.14.0 → albert-1.16.0}/docs/credentials.md +0 -0
  105. {albert-1.14.0 → albert-1.16.0}/docs/examples/inventory.md +0 -0
  106. {albert-1.14.0 → albert-1.16.0}/docs/examples/notebook.md +0 -0
  107. {albert-1.14.0 → albert-1.16.0}/docs/examples/property_data.md +0 -0
  108. {albert-1.14.0 → albert-1.16.0}/docs/examples/tasks.md +0 -0
  109. {albert-1.14.0 → albert-1.16.0}/docs/installation.md +0 -0
  110. {albert-1.14.0 → albert-1.16.0}/docs/migration.md +0 -0
  111. {albert-1.14.0 → albert-1.16.0}/docs/resources/acls.md +0 -0
  112. {albert-1.14.0 → albert-1.16.0}/docs/resources/activities.md +0 -0
  113. {albert-1.14.0 → albert-1.16.0}/docs/resources/attachments.md +0 -0
  114. {albert-1.14.0 → albert-1.16.0}/docs/resources/batch_data.md +0 -0
  115. {albert-1.14.0 → albert-1.16.0}/docs/resources/btdataset.md +0 -0
  116. {albert-1.14.0 → albert-1.16.0}/docs/resources/btinsight.md +0 -0
  117. {albert-1.14.0 → albert-1.16.0}/docs/resources/btmodel.md +0 -0
  118. {albert-1.14.0 → albert-1.16.0}/docs/resources/cas.md +0 -0
  119. {albert-1.14.0 → albert-1.16.0}/docs/resources/companies.md +0 -0
  120. {albert-1.14.0 → albert-1.16.0}/docs/resources/custom_fields.md +0 -0
  121. {albert-1.14.0 → albert-1.16.0}/docs/resources/custom_templates.md +0 -0
  122. {albert-1.14.0 → albert-1.16.0}/docs/resources/data_columns.md +0 -0
  123. {albert-1.14.0 → albert-1.16.0}/docs/resources/data_templates.md +0 -0
  124. {albert-1.14.0 → albert-1.16.0}/docs/resources/entity_types.md +0 -0
  125. {albert-1.14.0 → albert-1.16.0}/docs/resources/files.md +0 -0
  126. {albert-1.14.0 → albert-1.16.0}/docs/resources/hazards.md +0 -0
  127. {albert-1.14.0 → albert-1.16.0}/docs/resources/identifiers.md +0 -0
  128. {albert-1.14.0 → albert-1.16.0}/docs/resources/inventory.md +0 -0
  129. {albert-1.14.0 → albert-1.16.0}/docs/resources/links.md +0 -0
  130. {albert-1.14.0 → albert-1.16.0}/docs/resources/lists.md +0 -0
  131. {albert-1.14.0 → albert-1.16.0}/docs/resources/locations.md +0 -0
  132. {albert-1.14.0 → albert-1.16.0}/docs/resources/lots.md +0 -0
  133. {albert-1.14.0 → albert-1.16.0}/docs/resources/notebooks.md +0 -0
  134. {albert-1.14.0 → albert-1.16.0}/docs/resources/notes.md +0 -0
  135. {albert-1.14.0 → albert-1.16.0}/docs/resources/parameter_groups.md +0 -0
  136. {albert-1.14.0 → albert-1.16.0}/docs/resources/parameters.md +0 -0
  137. {albert-1.14.0 → albert-1.16.0}/docs/resources/pricings.md +0 -0
  138. {albert-1.14.0 → albert-1.16.0}/docs/resources/product_design.md +0 -0
  139. {albert-1.14.0 → albert-1.16.0}/docs/resources/projects.md +0 -0
  140. {albert-1.14.0 → albert-1.16.0}/docs/resources/property_data.md +0 -0
  141. {albert-1.14.0 → albert-1.16.0}/docs/resources/reports.md +0 -0
  142. {albert-1.14.0 → albert-1.16.0}/docs/resources/roles.md +0 -0
  143. {albert-1.14.0 → albert-1.16.0}/docs/resources/sheets.md +0 -0
  144. {albert-1.14.0 → albert-1.16.0}/docs/resources/storage_classes.md +0 -0
  145. {albert-1.14.0 → albert-1.16.0}/docs/resources/storage_locations.md +0 -0
  146. {albert-1.14.0 → albert-1.16.0}/docs/resources/substances.md +0 -0
  147. {albert-1.14.0 → albert-1.16.0}/docs/resources/synthesis.md +0 -0
  148. {albert-1.14.0 → albert-1.16.0}/docs/resources/tags.md +0 -0
  149. {albert-1.14.0 → albert-1.16.0}/docs/resources/tasks.md +0 -0
  150. {albert-1.14.0 → albert-1.16.0}/docs/resources/un_numbers.md +0 -0
  151. {albert-1.14.0 → albert-1.16.0}/docs/resources/units.md +0 -0
  152. {albert-1.14.0 → albert-1.16.0}/docs/resources/users.md +0 -0
  153. {albert-1.14.0 → albert-1.16.0}/docs/resources/workflows.md +0 -0
  154. {albert-1.14.0 → albert-1.16.0}/docs/resources/worksheets.md +0 -0
  155. {albert-1.14.0 → albert-1.16.0}/docs/sso.md +0 -0
  156. {albert-1.14.0 → albert-1.16.0}/pyproject.toml +0 -0
  157. {albert-1.14.0 → albert-1.16.0}/scripts/validate_release_tag.py +0 -0
  158. {albert-1.14.0 → albert-1.16.0}/scripts/validate_version_bump.py +0 -0
  159. {albert-1.14.0 → albert-1.16.0}/setup.sh +0 -0
  160. {albert-1.14.0 → albert-1.16.0}/src/albert/client.py +0 -0
  161. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/__init__.py +0 -0
  162. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/activities.py +0 -0
  163. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/base.py +0 -0
  164. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/batch_data.py +0 -0
  165. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/btdataset.py +0 -0
  166. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/btmodel.py +0 -0
  167. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/custom_fields.py +0 -0
  168. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/files.py +0 -0
  169. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/hazards.py +0 -0
  170. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/links.py +0 -0
  171. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/notebooks.py +0 -0
  172. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/pricings.py +0 -0
  173. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/product_design.py +0 -0
  174. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/report_templates.py +0 -0
  175. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/reports.py +0 -0
  176. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/roles.py +0 -0
  177. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/storage_classes.py +0 -0
  178. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/substance.py +0 -0
  179. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/synthesis.py +0 -0
  180. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/un_numbers.py +0 -0
  181. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/workflows.py +0 -0
  182. {albert-1.14.0 → albert-1.16.0}/src/albert/collections/worksheets.py +0 -0
  183. {albert-1.14.0 → albert-1.16.0}/src/albert/core/__init__.py +0 -0
  184. {albert-1.14.0 → albert-1.16.0}/src/albert/core/auth/__init__.py +0 -0
  185. {albert-1.14.0 → albert-1.16.0}/src/albert/core/auth/_listener.py +0 -0
  186. {albert-1.14.0 → albert-1.16.0}/src/albert/core/auth/_manager.py +0 -0
  187. {albert-1.14.0 → albert-1.16.0}/src/albert/core/auth/credentials.py +0 -0
  188. {albert-1.14.0 → albert-1.16.0}/src/albert/core/auth/sso.py +0 -0
  189. {albert-1.14.0 → albert-1.16.0}/src/albert/core/base.py +0 -0
  190. {albert-1.14.0 → albert-1.16.0}/src/albert/core/logging.py +0 -0
  191. {albert-1.14.0 → albert-1.16.0}/src/albert/core/pagination.py +0 -0
  192. {albert-1.14.0 → albert-1.16.0}/src/albert/core/session.py +0 -0
  193. {albert-1.14.0 → albert-1.16.0}/src/albert/core/shared/__init__.py +0 -0
  194. {albert-1.14.0 → albert-1.16.0}/src/albert/core/shared/enums.py +0 -0
  195. {albert-1.14.0 → albert-1.16.0}/src/albert/core/shared/identifiers.py +0 -0
  196. {albert-1.14.0 → albert-1.16.0}/src/albert/core/shared/models/base.py +0 -0
  197. {albert-1.14.0 → albert-1.16.0}/src/albert/core/shared/models/patch.py +0 -0
  198. {albert-1.14.0 → albert-1.16.0}/src/albert/core/shared/types.py +0 -0
  199. {albert-1.14.0 → albert-1.16.0}/src/albert/exceptions.py +0 -0
  200. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/__init__.py +0 -0
  201. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/_mixins.py +0 -0
  202. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/acls.py +0 -0
  203. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/activities.py +0 -0
  204. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/attachments.py +0 -0
  205. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/batch_data.py +0 -0
  206. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/btdataset.py +0 -0
  207. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/btinsight.py +0 -0
  208. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/btmodel.py +0 -0
  209. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/cas.py +0 -0
  210. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/companies.py +0 -0
  211. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/custom_fields.py +0 -0
  212. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/data_columns.py +0 -0
  213. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/data_templates.py +0 -0
  214. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/entity_types.py +0 -0
  215. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/facet.py +0 -0
  216. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/files.py +0 -0
  217. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/hazards.py +0 -0
  218. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/inventory.py +0 -0
  219. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/links.py +0 -0
  220. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/lists.py +0 -0
  221. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/locations.py +0 -0
  222. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/lots.py +0 -0
  223. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/notebooks.py +0 -0
  224. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/notes.py +0 -0
  225. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/parameter_groups.py +0 -0
  226. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/parameters.py +0 -0
  227. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/pricings.py +0 -0
  228. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/product_design.py +0 -0
  229. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/property_data.py +0 -0
  230. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/report_templates.py +0 -0
  231. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/reports.py +0 -0
  232. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/roles.py +0 -0
  233. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/sheets.py +0 -0
  234. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/storage_classes.py +0 -0
  235. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/storage_locations.py +0 -0
  236. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/substance.py +0 -0
  237. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/synthesis.py +0 -0
  238. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/tagged_base.py +0 -0
  239. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/tasks.py +0 -0
  240. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/un_numbers.py +0 -0
  241. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/units.py +0 -0
  242. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/users.py +0 -0
  243. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/worker_jobs.py +0 -0
  244. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/workflows.py +0 -0
  245. {albert-1.14.0 → albert-1.16.0}/src/albert/resources/worksheets.py +0 -0
  246. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/__init__.py +0 -0
  247. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/_auth.py +0 -0
  248. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/_patch.py +0 -0
  249. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/data_template.py +0 -0
  250. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/inventory.py +0 -0
  251. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/property_data.py +0 -0
  252. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/tasks.py +0 -0
  253. {albert-1.14.0 → albert-1.16.0}/src/albert/utils/worksheets.py +0 -0
  254. {albert-1.14.0 → albert-1.16.0}/tests/__init__.py +0 -0
  255. {albert-1.14.0 → albert-1.16.0}/tests/collections/__init__.py +0 -0
  256. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_activities.py +0 -0
  257. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_attachments.py +0 -0
  258. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_batch_data.py +0 -0
  259. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_btdataset.py +0 -0
  260. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_btinsight.py +0 -0
  261. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_btmodel.py +0 -0
  262. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_cas.py +0 -0
  263. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_company.py +0 -0
  264. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_custom_fields.py +0 -0
  265. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_data_columns.py +0 -0
  266. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_data_templates.py +0 -0
  267. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_entity_types.py +0 -0
  268. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_files.py +0 -0
  269. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_hazards.py +0 -0
  270. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_links.py +0 -0
  271. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_lists.py +0 -0
  272. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_locations.py +0 -0
  273. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_lots.py +0 -0
  274. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_notebooks.py +0 -0
  275. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_notes.py +0 -0
  276. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_parameter_groups.py +0 -0
  277. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_parameters.py +0 -0
  278. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_pricings.py +0 -0
  279. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_product_design.py +0 -0
  280. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_property_data.py +0 -0
  281. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_report_templates.py +0 -0
  282. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_reports.py +0 -0
  283. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_roles.py +0 -0
  284. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_storage_classes.py +0 -0
  285. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_storage_locations.py +0 -0
  286. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_substance.py +0 -0
  287. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_tags.py +0 -0
  288. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_tasks.py +0 -0
  289. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_un_number.py +0 -0
  290. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_units.py +0 -0
  291. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_users.py +0 -0
  292. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_workflows.py +0 -0
  293. {albert-1.14.0 → albert-1.16.0}/tests/collections/test_worksheet.py +0 -0
  294. {albert-1.14.0 → albert-1.16.0}/tests/core/shared/__init__.py +0 -0
  295. {albert-1.14.0 → albert-1.16.0}/tests/core/shared/test_identifiers.py +0 -0
  296. {albert-1.14.0 → albert-1.16.0}/tests/core/shared/test_types.py +0 -0
  297. {albert-1.14.0 → albert-1.16.0}/tests/core/test_auth.py +0 -0
  298. {albert-1.14.0 → albert-1.16.0}/tests/data/SDS_HCL.pdf +0 -0
  299. {albert-1.14.0 → albert-1.16.0}/tests/data/dontpanic.jpg +0 -0
  300. {albert-1.14.0 → albert-1.16.0}/tests/resources/test_inventory.py +0 -0
  301. {albert-1.14.0 → albert-1.16.0}/tests/resources/test_lots.py +0 -0
  302. {albert-1.14.0 → albert-1.16.0}/tests/resources/test_notebooks.py +0 -0
  303. {albert-1.14.0 → albert-1.16.0}/tests/resources/test_sheets.py +0 -0
  304. {albert-1.14.0 → albert-1.16.0}/tests/seeding.py +0 -0
  305. {albert-1.14.0 → albert-1.16.0}/tests/utils/fake_session.py +0 -0
  306. {albert-1.14.0 → albert-1.16.0}/tests/utils/test_patches.py +0 -0
@@ -0,0 +1,19 @@
1
+ name: release-please-poc
2
+
3
+ on:
4
+ workflow_dispatch: {}
5
+
6
+ permissions:
7
+ contents: write
8
+ pull-requests: write
9
+
10
+ jobs:
11
+ release-please:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: googleapis/release-please-action@v4
15
+ with:
16
+ token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
17
+ release-type: python
18
+ package-name: albert
19
+ target-branch: main
@@ -0,0 +1 @@
1
+ { ".": "1.14.1" }
@@ -0,0 +1,163 @@
1
+ # AGENTS
2
+
3
+ This file is the single source of truth for coding-agent guidance in this repo.
4
+ Follow these rules and patterns when making changes.
5
+
6
+ ## Rules
7
+
8
+ ### Changelog
9
+
10
+ Any change that impacts SDK users must be added to the changelog under the
11
+ appropriate release version, following Keep a Changelog 1.1.0.
12
+
13
+ This includes breaking and non-breaking changes, such as API or naming changes,
14
+ payload/behavior changes, deprecations, or internal refactors that affect
15
+ user-visible behavior.
16
+
17
+ When in doubt, add a changelog entry.
18
+
19
+ ### Using Numpy-Style Docstrings
20
+
21
+ Any new public methods and classes in this repository should follow the
22
+ Numpy-style docstring format. This ensures consistency and compatibility with
23
+ mkdocstrings for automated documentation generation.
24
+
25
+ Example:
26
+
27
+ ```python
28
+ class Cas:
29
+ """
30
+ Represents a CAS entity.
31
+
32
+ Attributes
33
+ ----------
34
+ number : str
35
+ The CAS number.
36
+ name : str, optional
37
+ The name of the CAS.
38
+ """
39
+
40
+ def from_string(cls, *, number: str) -> "Cas":
41
+ """
42
+ Creates a Cas object from a string.
43
+
44
+ Parameters
45
+ ----------
46
+ number : str
47
+ The CAS number.
48
+
49
+ Returns
50
+ -------
51
+ Cas
52
+ The Cas object created from the string.
53
+ """
54
+ return cls(number=number)
55
+ ```
56
+
57
+ When contributing new classes or methods, ensure all public members have
58
+ properly formatted Numpy-style docstrings.
59
+
60
+ ## Design Principles
61
+
62
+ 1. **Keep it simple** - Avoid over-engineering. Make minimal changes. Don't create massive file diffs or edit unnecessary files. Validate at boundaries, trust internal code based on type hints.
63
+
64
+ 2. **Follow existing code patterns** - Check similar code in the codebase before writing new code. Match existing patterns rather than creating new ones.
65
+
66
+ 3. **YAGNI** - Only edit files absolutely necessary for the task. Don't add extra configuration unless explicitly needed. Prefer sensible defaults over configurable complexity.
67
+
68
+ 4. **Verify by running code** - When guessing about how something works, run the code and verify rather than assuming.
69
+
70
+ 5. Verify you haven't over-engineered the solution
71
+
72
+ ## Project Basics
73
+
74
+ - Python: >=3.10 (type hints use modern syntax like list[str]).
75
+ - Formatting and linting: Ruff (line length 99). CI and pre-commit enforce this.
76
+ - Commit style: Conventional Commits (type(scope): summary), enforced by hooks.
77
+
78
+ Useful commands:
79
+
80
+ ```bash
81
+ ./setup.sh
82
+ uv run ruff format .
83
+ uv run ruff check . --fix
84
+ uv run pytest
85
+ ```
86
+
87
+ ## Repo Layout
88
+
89
+ - src/albert/collections: API-facing collection classes that call endpoints.
90
+ - src/albert/resources: Pydantic models representing API resources.
91
+ - src/albert/core: Session, pagination, shared enums, and base classes.
92
+ - src/albert/utils: Reusable helper utilities used by collections/resources.
93
+ - docs/: mkdocs content (autogenerated from docstrings via mkdocstrings).
94
+ - tests/: pytest suites, fixtures, and seed helpers.
95
+
96
+ ## API and Modeling Conventions
97
+
98
+ - Collections inherit from BaseCollection and accept an AlbertSession.
99
+ - Public collection methods should use @validate_call for runtime validation.
100
+ - Resources use BaseAlbertModel/BaseResource with Pydantic Fields and aliases.
101
+ - Keep API payloads in the wire format (camelCase) via Field(alias=...) and
102
+ model_dump(by_alias=True, mode="json", exclude_none=True).
103
+ - Prefer narrow, explicit payload construction instead of dumping entire models.
104
+
105
+ ## Pagination
106
+
107
+ Many list/search methods use AlbertPaginator (src/albert/core/pagination.py).
108
+ Two modes exist:
109
+
110
+ - Offset pagination (PaginationMode.OFFSET)
111
+ - Uses the offset query parameter.
112
+ - Defaults to limit=1000.
113
+ - Continues until Items is empty.
114
+
115
+ - Key pagination (PaginationMode.KEY)
116
+ - Uses startKey and expects lastKey in the response.
117
+ - Page size defaults to backend behavior.
118
+
119
+ Guidelines:
120
+
121
+ - Expose a max_items parameter on public list/search methods where appropriate.
122
+ It is used to stop iteration early regardless of mode.
123
+ - If a method returns an iterator, ensure the paginator is used consistently and
124
+ that the last_key can be inspected for resuming.
125
+ - Use clear docstrings about offset/startKey behavior and max_items semantics.
126
+
127
+ ## Testing
128
+
129
+ - Tests use pytest (see tests/).
130
+ - Integration-style tests require environment variables:
131
+ - ALBERT_CLIENT_ID_SDK
132
+ - ALBERT_CLIENT_SECRET_SDK
133
+ - ALBERT_BASE_URL
134
+ - The FakeAlbertSession in tests/utils supports unit-style tests without hitting
135
+ the network. Prefer it for pure behavior/unit tests.
136
+ - Seed helpers live in tests/seeding.py and are reused across fixtures.
137
+
138
+ ## Documentation
139
+
140
+ - Docs are built with mkdocs + mkdocstrings.
141
+ - When adding a new resource/collection, add a docs page in docs/ and link it in
142
+ mkdocs.yml (alphabetical in nav).
143
+ - Prefer docstrings for API reference content and keep them Numpy-style.
144
+
145
+ ## Release and Versioning
146
+
147
+ - Version is defined in src/albert/**init**.py and read dynamically by Hatch.
148
+ - Releases are created by tagging a version and drafting a GitHub release.
149
+
150
+ ## Do/Don’t Summary
151
+
152
+ Do:
153
+
154
+ - Add changelog entries for user-visible changes.
155
+ - Keep docstrings Numpy-style for public APIs.
156
+ - Use ruff for formatting/linting and respect line length 99.
157
+ - Follow existing collection/resource patterns and naming.
158
+
159
+ Don’t:
160
+
161
+ - Add new public APIs without docstrings and tests.
162
+ - Bypass Conventional Commits in commit messages.
163
+ - Introduce new dependencies without strong justification.
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.15.0] - 2026-02-04
9
+
10
+ ### Added
11
+
12
+ - Added `CustomTemplatesCollection.create` to support creating custom templates.
13
+ - Added `CustomTemplatesCollection.update_acl` to support updating custom template ACLs.
14
+ - Added `CustomTemplatesCollection.delete` to support deleting custom templates.
15
+
16
+ ### Changed
17
+
18
+ - Standardized list-parameter normalization across collection filters so scalars and
19
+ iterables are handled consistently.
20
+
21
+ ### Fixed
22
+
23
+ - Resolved custom-template ACL handling and schema parsing issues.
24
+ - Defaulted missing custom-template workflow names to a sensible value.
25
+ - Fixed enum parameter resolution to use session-level enum definitions.
26
+
8
27
  ## [1.14.0] - 2025-01-29
9
28
 
10
29
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: albert
3
- Version: 1.14.0
3
+ Version: 1.16.0
4
4
  Summary: The official Python SDK for the Albert Invent platform.
5
5
  Project-URL: Homepage, https://www.albertinvent.com/
6
6
  Project-URL: Documentation, https://docs.developer.albertinvent.com/albert-python
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 450.4 124.83">
3
+ <defs>
4
+ <style>
5
+ .cls-1 {
6
+ fill: #fff;
7
+ }
8
+ </style>
9
+ </defs>
10
+ <path class="cls-1" d="M155.73,0v114.36h-18.95V0h18.95Z"/>
11
+ <path class="cls-1" d="M172.72,114.36V0h18.79v45.75c5.88-8.17,16.01-13.4,27.12-13.4,22.06,0,39.05,18.13,39.05,41.98s-16.99,41.99-39.05,41.99c-11.11,0-21.24-4.74-27.12-12.91v10.95h-18.79ZM214.7,49.5c-13.56,0-24.01,10.95-24.01,24.83s10.45,24.83,24.01,24.83,24.01-10.95,24.01-24.83-10.45-24.83-24.01-24.83Z"/>
12
+ <path class="cls-1" d="M342.63,95.57c-6.7,12.58-19.28,20.75-36.11,20.75-24.34,0-41.66-17.32-41.66-41.99s17.48-41.98,40.68-41.98,39.86,18.14,39.86,41.98c0,3.11-.17,5.23-.17,5.72h-61.59c.82,11.6,11.11,20.26,23.03,20.26,10.46,0,15.85-5.06,20.42-12.09l15.52,7.35h0ZM326.61,66.33c-1.14-10.62-9.96-18.46-21.4-18.46s-20.26,9.31-21.4,18.46h42.8Z"/>
13
+ <path class="cls-1" d="M394.25,49.8c-13.88,0-22.38,8.32-22.38,24.82v39.73h-18.79V34.31h18.62v13.72c3.92-9.31,14.12-15.55,28.02-15.55v17.32h-5.47M407.08,6.84h20.33v25.64h22.98v17.33h-22.98v34.14c0,9.55,4.24,13.79,13.43,13.79,3.18,0,6.9-.89,9.55-2.65v18.21c-3.36,1.77-8.49,3.18-15.56,3.18-17.33,0-27.76-10.78-27.76-28.82V6.84h0Z"/>
14
+ <path class="cls-1" d="M119.79,66.31V0h-17.74L0,114.36h24L102.29,26.62v39.7h-18.67c-8.94,0-16.92,5.34-20.34,13.59-3.42,8.25-1.55,17.68,4.77,24l14.47,14.47c6.32,6.32,15.74,8.19,23.99,4.77,8.26-3.42,13.27-11.41,13.27-20.34v-19.49h9.63v-17h-9.63,0ZM102.29,102.8c0,2.13-1.13,3.82-3.1,4.64-.67.28-1.34.42-2,.42-1.27,0-2.47-.51-3.46-1.5l-14.47-14.47c-1.5-1.5-1.9-3.5-1.09-5.47.81-1.97,2.5-3.1,4.64-3.1h19.49v19.49h0Z"/>
15
+ </svg>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 450.4 124.83">
3
+ <defs>
4
+ <style>
5
+ .cls-1 {
6
+ fill: #7d19fe;
7
+ }
8
+ </style>
9
+ </defs>
10
+ <path class="cls-1" d="M155.73,0v114.36h-18.95V0h18.95Z"/>
11
+ <path class="cls-1" d="M172.72,114.36V0h18.79v45.75c5.88-8.17,16.01-13.4,27.12-13.4,22.06,0,39.05,18.13,39.05,41.98s-16.99,41.99-39.05,41.99c-11.11,0-21.24-4.74-27.12-12.91v10.95h-18.79ZM214.7,49.5c-13.56,0-24.01,10.95-24.01,24.83s10.45,24.83,24.01,24.83,24.01-10.95,24.01-24.83-10.45-24.83-24.01-24.83Z"/>
12
+ <path class="cls-1" d="M342.63,95.57c-6.7,12.58-19.28,20.75-36.11,20.75-24.34,0-41.66-17.32-41.66-41.99s17.48-41.98,40.68-41.98,39.86,18.14,39.86,41.98c0,3.11-.17,5.23-.17,5.72h-61.59c.82,11.6,11.11,20.26,23.03,20.26,10.46,0,15.85-5.06,20.42-12.09l15.52,7.35h0ZM326.61,66.33c-1.14-10.62-9.96-18.46-21.4-18.46s-20.26,9.31-21.4,18.46h42.8Z"/>
13
+ <path class="cls-1" d="M394.25,49.8c-13.88,0-22.38,8.32-22.38,24.82v39.73h-18.79V34.31h18.62v13.72c3.92-9.31,14.12-15.55,28.02-15.55v17.32h-5.47M407.08,6.84h20.33v25.64h22.98v17.33h-22.98v34.14c0,9.55,4.24,13.79,13.43,13.79,3.18,0,6.9-.89,9.55-2.65v18.21c-3.36,1.77-8.49,3.18-15.56,3.18-17.33,0-27.76-10.78-27.76-28.82V6.84h0Z"/>
14
+ <path class="cls-1" d="M119.79,66.31V0h-17.74L0,114.36h24L102.29,26.62v39.7h-18.67c-8.94,0-16.92,5.34-20.34,13.59-3.42,8.25-1.55,17.68,4.77,24l14.47,14.47c6.32,6.32,15.74,8.19,23.99,4.77,8.26-3.42,13.27-11.41,13.27-20.34v-19.49h9.63v-17h-9.63,0ZM102.29,102.8c0,2.13-1.13,3.82-3.1,4.64-.67.28-1.34.42-2,.42-1.27,0-2.47-.51-3.46-1.5l-14.47-14.47c-1.5-1.5-1.9-3.5-1.09-5.47.81-1.97,2.5-3.1,4.64-3.1h19.49v19.49h0Z"/>
15
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="2" y="2" width="28" height="28" rx="14" fill="black"/>
3
+ <path d="M22.2329 15.4998V7H19.9031L6.5 21.6587H9.65181L19.9358 10.4118V15.4998H17.4838C16.31 15.4998 15.2613 16.1836 14.8125 17.2417C14.3637 18.2997 14.6091 19.5071 15.4395 20.3175L17.3401 22.1722C18.1705 22.9817 19.4077 23.2221 20.4919 22.7841C21.577 22.3452 22.2348 21.3218 22.2348 20.1772V17.6796H23.5V15.5007H22.2348L22.2329 15.4998ZM19.9348 20.1763C19.9348 20.4495 19.7865 20.6662 19.528 20.7709C19.4403 20.8064 19.3517 20.8246 19.2649 20.8246C19.0988 20.8246 18.9402 20.7591 18.8105 20.6316L16.9099 18.7768C16.7121 18.5838 16.6599 18.3289 16.7672 18.0757C16.8745 17.8235 17.0956 17.6787 17.3765 17.6787H19.9358V20.1763H19.9348Z" fill="white"/>
4
+ </svg>
@@ -1,8 +1,8 @@
1
1
  # Albert Python
2
2
 
3
3
  <div class="logo-wrapper">
4
- <img src="assets/Wordmark_White.png" class="logo only-dark" alt="Albert Logo">
5
- <img src="assets/Wordmark_Black.png" class="logo only-light" alt="Albert Logo">
4
+ <img src="assets/Albert_Wordmark_Mono_RGB_White.svg" class="logo only-dark" alt="Albert Logo">
5
+ <img src="assets/Albert_Wordmark_RGB_Colour.svg" class="logo only-light" alt="Albert Logo">
6
6
  </div>
7
7
 
8
8
  [![CI](https://img.shields.io/circleci/build/github/albert-labs/albert-python/main?label=CI)](https://app.circleci.com/pipelines/github/albert-labs/albert-python?branch=main)
@@ -1,6 +1,13 @@
1
1
  :root {
2
- --md-primary-fg-color: #0149ff;
3
- --md-accent-fg-color: #0149ff;
2
+ --md-primary-fg-color: #7D19FE;
3
+ --md-accent-fg-color: #7D19FE;
4
+ }
5
+
6
+ .md-typeset a:hover,
7
+ .md-nav__link:hover,
8
+ .md-nav--primary .md-nav__link:hover,
9
+ .md-nav--secondary .md-nav__link:hover {
10
+ color: #0b62fe;
4
11
  }
5
12
 
6
13
  .logo-wrapper {
@@ -24,8 +24,8 @@ theme:
24
24
  name: "material"
25
25
  font:
26
26
  text: Aeonik Regular
27
- logo: assets/Wordmark_White.png
28
- favicon: assets/Vector_Favicon_Blue.svg
27
+ logo: assets/Albert_Wordmark_Mono_RGB_White.svg
28
+ favicon: assets/favicon_bw.svg
29
29
  features:
30
30
  - content.tabs.link # Tabs can contain links
31
31
  - content.code.annotate # Annotated code blocks (tooltips)
@@ -0,0 +1,10 @@
1
+ {
2
+ "release-type": "python",
3
+ "packages": {
4
+ ".": {
5
+ "package-name": "albert",
6
+ "version-file": "src/albert/__init__.py",
7
+ "include-v-in-tag": true
8
+ }
9
+ }
10
+ }
@@ -4,4 +4,4 @@ from albert.core.auth.sso import AlbertSSOClient
4
4
 
5
5
  __all__ = ["Albert", "AlbertClientCredentials", "AlbertSSOClient"]
6
6
 
7
- __version__ = "1.14.0"
7
+ __version__ = "1.16.0"
@@ -9,7 +9,7 @@ from pydantic import validate_call
9
9
  from albert.collections.base import BaseCollection
10
10
  from albert.collections.files import FileCollection
11
11
  from albert.collections.notes import NotesCollection
12
- from albert.core.shared.identifiers import AttachmentId, DataColumnId, InventoryId
12
+ from albert.core.shared.identifiers import AttachmentId, DataColumnId, InventoryId, ProjectId
13
13
  from albert.core.shared.types import MetadataItem
14
14
  from albert.resources.attachments import Attachment, AttachmentCategory
15
15
  from albert.resources.files import FileCategory, FileNamespace
@@ -288,3 +288,47 @@ class AttachmentCollection(BaseCollection):
288
288
 
289
289
  response = self.session.post(self.base_path, json=payload)
290
290
  return Attachment(**response.json())
291
+
292
+ @validate_call
293
+ def upload_and_attach_document_to_project(
294
+ self,
295
+ *,
296
+ project_id: ProjectId,
297
+ file_path: Path,
298
+ ) -> Attachment:
299
+ """Upload a file and attach it as a document to a project.
300
+
301
+ Args:
302
+ project_id: The Albert ID of the project (e.g. "PRO770").
303
+ file_path: Local path to the file to upload.
304
+
305
+ Returns:
306
+ The created Attachment record.
307
+ """
308
+ resolved_path = file_path.expanduser()
309
+ if not resolved_path.is_file():
310
+ raise FileNotFoundError(f"File not found at '{resolved_path}'")
311
+
312
+ content_type = mimetypes.guess_type(resolved_path.name)[0] or "application/octet-stream"
313
+ encoded_file_name = quote(resolved_path.name)
314
+ file_key = f"{project_id}/documents/original/{encoded_file_name}"
315
+
316
+ file_collection = self._get_file_collection()
317
+ with resolved_path.open("rb") as file_handle:
318
+ file_collection.sign_and_upload_file(
319
+ data=file_handle,
320
+ name=file_key,
321
+ namespace=FileNamespace.RESULT,
322
+ content_type=content_type,
323
+ )
324
+
325
+ payload = {
326
+ "parentId": project_id,
327
+ "category": AttachmentCategory.OTHER.value,
328
+ "name": encoded_file_name,
329
+ "key": file_key,
330
+ "nameSpace": FileNamespace.RESULT.value,
331
+ }
332
+
333
+ response = self.session.post(self.base_path, json=payload)
334
+ return Attachment(**response.json())
@@ -7,6 +7,7 @@ from albert.core.pagination import AlbertPaginator
7
7
  from albert.core.session import AlbertSession
8
8
  from albert.core.shared.enums import OrderBy, PaginationMode
9
9
  from albert.core.shared.identifiers import BTInsightId
10
+ from albert.core.utils import ensure_list
10
11
  from albert.resources.btinsight import BTInsight, BTInsightCategory, BTInsightState
11
12
 
12
13
 
@@ -132,17 +133,17 @@ class BTInsightCollection(BaseCollection):
132
133
  """
133
134
  params = {
134
135
  "offset": offset,
135
- "order": OrderBy(order_by).value if order_by else None,
136
+ "order": order_by,
136
137
  "sortBy": sort_by,
137
138
  "text": text,
138
- "name": name,
139
+ "name": ensure_list(name),
139
140
  }
140
- if state:
141
- state = state if isinstance(state, list) else [state]
142
- params["state"] = [BTInsightState(x).value for x in state]
143
- if category:
144
- category = category if isinstance(category, list) else [category]
145
- params["category"] = [BTInsightCategory(x).value for x in category]
141
+
142
+ state_values = ensure_list(state)
143
+ params["state"] = state_values if state_values else None
144
+
145
+ category_values = ensure_list(category)
146
+ params["category"] = category_values if category_values else None
146
147
 
147
148
  return AlbertPaginator(
148
149
  mode=PaginationMode.OFFSET,
@@ -106,7 +106,7 @@ class CasCollection(BaseCollection):
106
106
  An iterator over Cas entities.
107
107
  """
108
108
 
109
- params: dict[str, Any] = {"orderBy": order_by.value}
109
+ params: dict[str, Any] = {"orderBy": order_by}
110
110
  if id is not None:
111
111
  yield self.get_by_id(id=id)
112
112
  return
@@ -7,6 +7,7 @@ from albert.core.logging import logger
7
7
  from albert.core.pagination import AlbertPaginator, PaginationMode
8
8
  from albert.core.session import AlbertSession
9
9
  from albert.core.shared.identifiers import CompanyId
10
+ from albert.core.utils import ensure_list
10
11
  from albert.exceptions import AlbertException
11
12
  from albert.resources.companies import Company
12
13
 
@@ -62,9 +63,8 @@ class CompanyCollection(BaseCollection):
62
63
  "dupDetection": "false",
63
64
  "startKey": start_key,
64
65
  }
65
- if name:
66
- params["name"] = name if isinstance(name, list) else [name]
67
- params["exactMatch"] = str(exact_match).lower()
66
+ params["name"] = ensure_list(name)
67
+ params["exactMatch"] = str(exact_match).lower()
68
68
 
69
69
  return AlbertPaginator(
70
70
  mode=PaginationMode.KEY,