albert 1.13.0b1__tar.gz → 1.14.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.
- {albert-1.13.0b1 → albert-1.14.0}/CHANGELOG.md +8 -1
- {albert-1.13.0b1 → albert-1.14.0}/PKG-INFO +1 -1
- albert-1.14.0/docs/examples/inventory.md +37 -0
- albert-1.14.0/docs/resources/acls.md +1 -0
- {albert-1.13.0b1 → albert-1.14.0}/mkdocs.yml +2 -0
- {albert-1.13.0b1 → albert-1.14.0}/scripts/validate_version_bump.py +11 -3
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/__init__.py +1 -1
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/attachments.py +17 -11
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/projects.py +9 -9
- albert-1.14.0/src/albert/collections/worksheets.py +283 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/auth/_listener.py +4 -2
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/shared/enums.py +1 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/acls.py +26 -2
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/notebooks.py +26 -2
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/utils/property_data.py +61 -1
- albert-1.14.0/src/albert/utils/worksheets.py +90 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_inventory.py +3 -2
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_property_data.py +152 -1
- albert-1.13.0b1/src/albert/collections/worksheets.py +0 -118
- {albert-1.13.0b1 → albert-1.14.0}/.circleci/config.yml +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/.gitignore +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/.pre-commit-config.yaml +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/.vscode/settings.json +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/CONTRIBUTING.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/LICENSE +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/README.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/CONTRIBUTING.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/albert.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/assets/Vector_Favicon_Blue.svg +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/assets/Wordmark_Black.png +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/assets/Wordmark_White.png +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/authentication.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/activities.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/attachments.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/base.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/batch_data.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/btdataset.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/btinsight.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/btmodel.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/cas.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/companies.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/custom_fields.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/custom_templates.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/data_columns.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/data_templates.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/entity_types.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/files.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/hazards.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/inventory.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/links.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/lists.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/locations.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/lots.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/notebooks.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/notes.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/parameter_groups.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/parameters.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/pricings.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/product_design.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/projects.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/property_data.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/reports.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/roles.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/storage_classes.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/storage_locations.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/substances.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/synthesis.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/tags.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/tasks.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/un_numbers.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/units.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/users.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/workflows.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/collections/worksheets.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/concepts.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/configuration.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/credentials.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/examples/notebook.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/examples/property_data.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/examples/tasks.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/index.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/installation.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/migration.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/activities.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/attachments.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/batch_data.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/btdataset.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/btinsight.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/btmodel.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/cas.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/companies.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/custom_fields.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/custom_templates.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/data_columns.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/data_templates.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/entity_types.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/files.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/hazards.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/identifiers.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/inventory.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/links.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/lists.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/locations.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/lots.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/notebooks.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/notes.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/parameter_groups.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/parameters.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/pricings.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/product_design.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/projects.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/property_data.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/reports.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/roles.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/sheets.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/storage_classes.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/storage_locations.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/substances.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/synthesis.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/tags.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/tasks.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/un_numbers.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/units.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/users.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/workflows.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/resources/worksheets.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/sso.md +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/docs/styles/extra.css +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/pyproject.toml +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/scripts/validate_release_tag.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/setup.sh +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/client.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/activities.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/base.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/batch_data.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/btdataset.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/btinsight.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/btmodel.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/cas.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/companies.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/custom_fields.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/custom_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/data_columns.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/data_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/entity_types.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/files.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/hazards.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/inventory.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/links.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/lists.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/locations.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/lots.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/notebooks.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/notes.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/parameter_groups.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/parameters.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/pricings.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/product_design.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/property_data.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/report_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/reports.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/roles.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/storage_classes.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/storage_locations.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/substance.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/synthesis.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/tags.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/tasks.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/un_numbers.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/units.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/users.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/collections/workflows.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/auth/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/auth/_manager.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/auth/credentials.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/auth/sso.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/base.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/logging.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/pagination.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/session.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/shared/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/shared/identifiers.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/shared/models/base.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/shared/models/patch.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/core/shared/types.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/exceptions.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/_mixins.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/activities.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/attachments.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/batch_data.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/btdataset.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/btinsight.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/btmodel.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/cas.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/companies.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/custom_fields.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/custom_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/data_columns.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/data_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/entity_types.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/facet.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/files.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/hazards.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/inventory.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/links.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/lists.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/locations.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/lots.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/notes.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/parameter_groups.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/parameters.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/pricings.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/product_design.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/projects.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/property_data.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/report_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/reports.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/roles.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/sheets.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/storage_classes.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/storage_locations.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/substance.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/synthesis.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/tagged_base.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/tags.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/tasks.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/un_numbers.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/units.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/users.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/worker_jobs.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/workflows.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/resources/worksheets.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/utils/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/utils/_auth.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/utils/_patch.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/utils/data_template.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/utils/inventory.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/src/albert/utils/tasks.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_activities.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_attachments.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_batch_data.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_btdataset.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_btinsight.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_btmodel.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_cas.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_company.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_custom_fields.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_custom_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_data_columns.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_data_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_entity_types.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_files.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_hazards.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_links.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_lists.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_locations.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_lots.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_notebooks.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_notes.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_parameter_groups.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_parameters.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_pricings.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_product_design.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_projects.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_report_templates.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_reports.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_roles.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_storage_classes.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_storage_locations.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_substance.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_tags.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_tasks.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_un_number.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_units.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_users.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_workflows.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/collections/test_worksheet.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/conftest.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/core/shared/__init__.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/core/shared/test_identifiers.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/core/shared/test_types.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/core/test_auth.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/data/SDS_HCL.pdf +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/data/dontpanic.jpg +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/resources/test_inventory.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/resources/test_lots.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/resources/test_notebooks.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/resources/test_sheets.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/seeding.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/utils/fake_session.py +0 -0
- {albert-1.13.0b1 → albert-1.14.0}/tests/utils/test_patches.py +0 -0
|
@@ -5,7 +5,14 @@ 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
|
-
## [
|
|
8
|
+
## [1.14.0] - 2025-01-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Added `ACLContainer` model for `{class, fgclist}` ACL payloads.
|
|
13
|
+
- Added `WorksheetCollection.duplicate_sheet` functionality.
|
|
14
|
+
- Added `WorksheetCollection.create_sheet_template` functionality.
|
|
15
|
+
- Added a deprecation warning for `NotebookCopyACL`; formal deprecation planned for 2.0 (use `ACLContainer`).
|
|
9
16
|
|
|
10
17
|
## [1.2.0] - 2025-07-25
|
|
11
18
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: albert
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.14.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,37 @@
|
|
|
1
|
+
# Inventory
|
|
2
|
+
|
|
3
|
+
Albert Inventory serves as a digital manifestation of your physical inventory. It enables you to sort, filter, trace, and manage all types of inventory.
|
|
4
|
+
|
|
5
|
+
## Inventory function on CAS
|
|
6
|
+
|
|
7
|
+
Inventory function is a business-controlled, multi-select list on the Inventory ↔ CAS relationship.
|
|
8
|
+
Use it by updating an existing inventory item.
|
|
9
|
+
|
|
10
|
+
!!! example "Add inventory function values to a CAS entry"
|
|
11
|
+
```python
|
|
12
|
+
from albert import Albert
|
|
13
|
+
from albert.resources.lists import ListItem, ListItemCategory
|
|
14
|
+
|
|
15
|
+
client = Albert.from_client_credentials()
|
|
16
|
+
|
|
17
|
+
inventory_id = "INV123"
|
|
18
|
+
cas_id = "CAS123"
|
|
19
|
+
|
|
20
|
+
# Optional: create a new inventoryFunction list item first.
|
|
21
|
+
list_item = ListItem(
|
|
22
|
+
name="Primary Function",
|
|
23
|
+
category=ListItemCategory.INVENTORY,
|
|
24
|
+
list_type="inventoryFunction",
|
|
25
|
+
)
|
|
26
|
+
list_item = client.lists.create(list_item=list_item)
|
|
27
|
+
|
|
28
|
+
inventory_item = client.inventory.get_by_id(id=inventory_id)
|
|
29
|
+
if inventory_item.cas:
|
|
30
|
+
for cas_amount in inventory_item.cas:
|
|
31
|
+
if cas_amount.id == cas_id:
|
|
32
|
+
cas_amount.inventory_function = [list_item]
|
|
33
|
+
break
|
|
34
|
+
|
|
35
|
+
updated_item = client.inventory.update(inventory_item=inventory_item)
|
|
36
|
+
print(updated_item.id)
|
|
37
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
::: albert.resources.acls
|
|
@@ -177,6 +177,7 @@ nav:
|
|
|
177
177
|
- Resources:
|
|
178
178
|
- Activities: resources/activities.md
|
|
179
179
|
- Attachments: resources/attachments.md
|
|
180
|
+
- ACL: resources/acls.md
|
|
180
181
|
- Batch Data: resources/batch_data.md
|
|
181
182
|
- Breakthrough:
|
|
182
183
|
- Breakthrough Datasets: resources/btdataset.md
|
|
@@ -221,6 +222,7 @@ nav:
|
|
|
221
222
|
- Worksheets: resources/worksheets.md
|
|
222
223
|
- Sheets: resources/sheets.md
|
|
223
224
|
- Examples:
|
|
225
|
+
- Inventory: examples/inventory.md
|
|
224
226
|
- Property Data: examples/property_data.md
|
|
225
227
|
- Tasks: examples/tasks.md
|
|
226
228
|
- Notebooks: examples/notebook.md
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import argparse
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
2
4
|
import sys
|
|
3
|
-
from os import popen
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
from packaging import version
|
|
@@ -19,8 +20,15 @@ def main(base_branch: str):
|
|
|
19
20
|
local_path = Path(__file__).parents[1] / version_file
|
|
20
21
|
local_version = extract_version(local_path.read_text())
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
if not re.fullmatch(r"[A-Za-z0-9._/-]+", base_branch) or base_branch.startswith("-"):
|
|
24
|
+
raise ValueError(f"Invalid base branch ref: {base_branch!r}")
|
|
25
|
+
|
|
26
|
+
subprocess.run(["git", "fetch", "origin"], check=True)
|
|
27
|
+
base_contents = subprocess.check_output(
|
|
28
|
+
["git", "show", f"{base_branch}:{version_file}"],
|
|
29
|
+
text=True,
|
|
30
|
+
)
|
|
31
|
+
base_version = extract_version(base_contents)
|
|
24
32
|
|
|
25
33
|
if is_version_bump(local_version, base_version):
|
|
26
34
|
print(f"Version bump detected: {base_version} -> {local_version}")
|
|
@@ -152,20 +152,30 @@ class AttachmentCollection(BaseCollection):
|
|
|
152
152
|
The name of the file, by default ""
|
|
153
153
|
upload_key : str | None, optional
|
|
154
154
|
Override the storage key used when signing and uploading the file.
|
|
155
|
-
Defaults to
|
|
155
|
+
Defaults to ``{parent_id}/{note_id}/{file_name}``.
|
|
156
156
|
|
|
157
157
|
Returns
|
|
158
158
|
-------
|
|
159
159
|
Note
|
|
160
160
|
The created note.
|
|
161
161
|
"""
|
|
162
|
-
|
|
163
|
-
if not upload_name:
|
|
162
|
+
if not (upload_key or file_name):
|
|
164
163
|
raise ValueError("A file name or upload key must be provided for attachment upload.")
|
|
165
164
|
|
|
166
|
-
file_type = mimetypes.guess_type(file_name or upload_name)[0]
|
|
167
|
-
file_collection = self._get_file_collection()
|
|
168
165
|
note_collection = self._get_note_collection()
|
|
166
|
+
note = Note(
|
|
167
|
+
parent_id=parent_id,
|
|
168
|
+
note=note_text,
|
|
169
|
+
)
|
|
170
|
+
registered_note = note_collection.create(note=note)
|
|
171
|
+
if upload_key:
|
|
172
|
+
attachment_name = file_name or Path(upload_key).name
|
|
173
|
+
upload_name = upload_key
|
|
174
|
+
else:
|
|
175
|
+
attachment_name = file_name
|
|
176
|
+
upload_name = f"{parent_id}/{registered_note.id}/{file_name}"
|
|
177
|
+
file_type = mimetypes.guess_type(attachment_name or upload_name)[0]
|
|
178
|
+
file_collection = self._get_file_collection()
|
|
169
179
|
|
|
170
180
|
file_collection.sign_and_upload_file(
|
|
171
181
|
data=file_data,
|
|
@@ -176,16 +186,12 @@ class AttachmentCollection(BaseCollection):
|
|
|
176
186
|
file_info = file_collection.get_by_name(
|
|
177
187
|
name=upload_name, namespace=FileNamespace.RESULT.value
|
|
178
188
|
)
|
|
179
|
-
note = Note(
|
|
180
|
-
parent_id=parent_id,
|
|
181
|
-
note=note_text,
|
|
182
|
-
)
|
|
183
|
-
registered_note = note_collection.create(note=note)
|
|
184
189
|
self.attach_file_to_note(
|
|
185
190
|
note_id=registered_note.id,
|
|
186
|
-
file_name=
|
|
191
|
+
file_name=attachment_name,
|
|
187
192
|
file_key=file_info.name,
|
|
188
193
|
)
|
|
194
|
+
|
|
189
195
|
return note_collection.get_by_id(id=registered_note.id)
|
|
190
196
|
|
|
191
197
|
@validate_call
|
|
@@ -142,17 +142,17 @@ class ProjectCollection(BaseCollection):
|
|
|
142
142
|
----------
|
|
143
143
|
text : str, optional
|
|
144
144
|
Full-text search query.
|
|
145
|
-
status : list
|
|
145
|
+
status : list[str], optional
|
|
146
146
|
Filter by project statuses.
|
|
147
|
-
market_segment : list
|
|
147
|
+
market_segment : list[str], optional
|
|
148
148
|
Filter by market segment.
|
|
149
|
-
application : list
|
|
149
|
+
application : list[str], optional
|
|
150
150
|
Filter by application.
|
|
151
|
-
technology : list
|
|
151
|
+
technology : list[str], optional
|
|
152
152
|
Filter by technology tags.
|
|
153
|
-
created_by : list
|
|
153
|
+
created_by : list[str], optional
|
|
154
154
|
Filter by user names who created the project.
|
|
155
|
-
location : list
|
|
155
|
+
location : list[str], optional
|
|
156
156
|
Filter by location(s).
|
|
157
157
|
from_created_at : str, optional
|
|
158
158
|
Earliest creation date in 'YYYY-MM-DD' format.
|
|
@@ -162,15 +162,15 @@ class ProjectCollection(BaseCollection):
|
|
|
162
162
|
Facet field to filter on.
|
|
163
163
|
facet_text : str, optional
|
|
164
164
|
Facet text to search for.
|
|
165
|
-
contains_field : list
|
|
165
|
+
contains_field : list[str], optional
|
|
166
166
|
Fields to search inside.
|
|
167
|
-
contains_text : list
|
|
167
|
+
contains_text : list[str], optional
|
|
168
168
|
Values to search for within the `contains_field`.
|
|
169
169
|
linked_to : str, optional
|
|
170
170
|
Entity ID the project is linked to.
|
|
171
171
|
my_project : bool, optional
|
|
172
172
|
If True, return only projects owned by current user.
|
|
173
|
-
my_role : list
|
|
173
|
+
my_role : list[str], optional
|
|
174
174
|
User roles to filter by.
|
|
175
175
|
order_by : OrderBy, optional
|
|
176
176
|
Sort order. Default is DESCENDING.
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
from pydantic import validate_call
|
|
2
|
+
|
|
3
|
+
from albert.collections.base import BaseCollection
|
|
4
|
+
from albert.collections.custom_templates import CustomTemplatesCollection
|
|
5
|
+
from albert.core.session import AlbertSession
|
|
6
|
+
from albert.core.shared.identifiers import ProjectId
|
|
7
|
+
from albert.resources.acls import ACLContainer
|
|
8
|
+
from albert.resources.custom_templates import CustomTemplate
|
|
9
|
+
from albert.resources.worksheets import Worksheet
|
|
10
|
+
from albert.utils.worksheets import (
|
|
11
|
+
get_columns_to_copy,
|
|
12
|
+
get_prg_rows_to_copy,
|
|
13
|
+
get_sheet_from_worksheet,
|
|
14
|
+
get_task_rows_to_copy,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class WorksheetCollection(BaseCollection):
|
|
19
|
+
"""WorksheetCollection is a collection class for managing Worksheet entities in the Albert platform."""
|
|
20
|
+
|
|
21
|
+
_api_version = "v3"
|
|
22
|
+
|
|
23
|
+
def __init__(self, *, session: AlbertSession):
|
|
24
|
+
super().__init__(session=session)
|
|
25
|
+
self.base_path = f"/api/{WorksheetCollection._api_version}/worksheet"
|
|
26
|
+
|
|
27
|
+
def _add_session_to_sheets(self, response_json: dict):
|
|
28
|
+
sheets = response_json.get("Sheets")
|
|
29
|
+
if sheets:
|
|
30
|
+
for s in sheets:
|
|
31
|
+
s["session"] = self.session
|
|
32
|
+
s["project_id"] = response_json["projectId"]
|
|
33
|
+
response_json["session"] = self.session
|
|
34
|
+
return response_json
|
|
35
|
+
|
|
36
|
+
@validate_call
|
|
37
|
+
def get_by_project_id(self, *, project_id: ProjectId) -> Worksheet:
|
|
38
|
+
"""Retrieve a worksheet by its project ID. Projects and Worksheets are 1:1 in the Albert platform.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
project_id : str
|
|
43
|
+
The project ID to retrieve the worksheet for.
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
Worksheet
|
|
48
|
+
The Worksheet object for that project.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
params = {"type": "project", "id": project_id}
|
|
52
|
+
response = self.session.get(self.base_path, params=params)
|
|
53
|
+
|
|
54
|
+
response_json = response.json()
|
|
55
|
+
|
|
56
|
+
# Sheets are themselves collections, and therefore need access to the session
|
|
57
|
+
response_json = self._add_session_to_sheets(response_json)
|
|
58
|
+
return Worksheet(**response_json)
|
|
59
|
+
|
|
60
|
+
@validate_call
|
|
61
|
+
def setup_worksheet(self, *, project_id: ProjectId, add_sheet=False) -> Worksheet:
|
|
62
|
+
"""Setup a new worksheet for a project.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
project_id : str
|
|
67
|
+
The project ID to setup the worksheet for.
|
|
68
|
+
add_sheet : bool, optional
|
|
69
|
+
Whether to add a blank sheet to the worksheet, by default False
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
Worksheet
|
|
74
|
+
The Worksheet object for the project.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
params = {"sheets": str(add_sheet).lower()}
|
|
78
|
+
path = f"{self.base_path}/{project_id}/setup"
|
|
79
|
+
self.session.post(path, json=params)
|
|
80
|
+
return self.get_by_project_id(project_id=project_id)
|
|
81
|
+
|
|
82
|
+
@validate_call
|
|
83
|
+
def setup_new_sheet_from_template(
|
|
84
|
+
self, *, project_id: ProjectId, sheet_template_id: str, sheet_name: str
|
|
85
|
+
) -> Worksheet:
|
|
86
|
+
"""Create a new sheet in the Worksheet related to the specified Project from a template.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
project_id : str
|
|
91
|
+
_description_
|
|
92
|
+
sheet_template_id : str
|
|
93
|
+
_description_
|
|
94
|
+
sheet_name : str
|
|
95
|
+
_description_
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
Worksheet
|
|
100
|
+
The Worksheet object for the project.
|
|
101
|
+
"""
|
|
102
|
+
payload = {"name": sheet_name}
|
|
103
|
+
params = {"templateId": sheet_template_id}
|
|
104
|
+
path = f"{self.base_path}/project/{project_id}/sheets"
|
|
105
|
+
self.session.post(path, json=payload, params=params)
|
|
106
|
+
return self.get_by_project_id(project_id=project_id)
|
|
107
|
+
|
|
108
|
+
@validate_call
|
|
109
|
+
def add_sheet(self, *, project_id: ProjectId, sheet_name: str) -> Worksheet:
|
|
110
|
+
"""Create a new blank sheet in the Worksheet with the specified name.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
project_id : str
|
|
115
|
+
The project ID for the Worksheet to add the sheet to.
|
|
116
|
+
sheet_name : str
|
|
117
|
+
The name of the new sheet.
|
|
118
|
+
|
|
119
|
+
Returns
|
|
120
|
+
-------
|
|
121
|
+
Worksheet
|
|
122
|
+
The Worksheet object for the project.
|
|
123
|
+
"""
|
|
124
|
+
payload = {"name": sheet_name}
|
|
125
|
+
url = f"{self.base_path}/project/{project_id}/sheets"
|
|
126
|
+
self.session.put(url=url, json=payload)
|
|
127
|
+
return self.get_by_project_id(project_id=project_id)
|
|
128
|
+
|
|
129
|
+
@validate_call
|
|
130
|
+
def duplicate_sheet(
|
|
131
|
+
self,
|
|
132
|
+
*,
|
|
133
|
+
project_id: ProjectId,
|
|
134
|
+
source_sheet_name: str,
|
|
135
|
+
new_sheet_name: str,
|
|
136
|
+
copy_all_pd_rows: bool = True,
|
|
137
|
+
copy_all_pinned_columns: bool = True,
|
|
138
|
+
copy_all_unpinned_columns: bool = True,
|
|
139
|
+
column_names: list[str] | None = None,
|
|
140
|
+
task_row_names: list[str] | None = None,
|
|
141
|
+
) -> Worksheet:
|
|
142
|
+
"""Duplicate an existing sheet within the same project.
|
|
143
|
+
|
|
144
|
+
This creates a new sheet based on the specified source sheet. You can control
|
|
145
|
+
which Product Design (PD) & Results rows and columns are copied using the available options.
|
|
146
|
+
The final list of columns copied is the union of:
|
|
147
|
+
- all pinned columns (if copy_all_pinned_columns is True)
|
|
148
|
+
- all unpinned columns (if copy_all_unpinned_columns is True)
|
|
149
|
+
- explicitly listed column names (column_names)
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
project_id : str
|
|
154
|
+
The project ID under which the sheet exists.
|
|
155
|
+
source_sheet_name : str
|
|
156
|
+
The name of the existing sheet to duplicate.
|
|
157
|
+
new_sheet_name : str
|
|
158
|
+
The name of the new sheet to create.
|
|
159
|
+
copy_all_pd_rows : bool, optional
|
|
160
|
+
When True, all PD (Product Design) rows from the source sheet are copied.
|
|
161
|
+
When False, only rows corresponding to the selected columns will be copied.
|
|
162
|
+
Default is True.
|
|
163
|
+
copy_all_pinned_columns : bool, optional
|
|
164
|
+
If True, includes all pinned columns from the source sheet. Default is True.
|
|
165
|
+
copy_all_unpinned_columns : bool, optional
|
|
166
|
+
If True, includes all unpinned columns from the source sheet. Default is True.
|
|
167
|
+
column_names : list[str], optional
|
|
168
|
+
A list of column names to explicitly copy. These are resolved internally
|
|
169
|
+
to column IDs using the sheet's product design grid.
|
|
170
|
+
task_row_names : list[str], optional
|
|
171
|
+
List of task row names to include from the tasks.
|
|
172
|
+
|
|
173
|
+
Returns
|
|
174
|
+
-------
|
|
175
|
+
Worksheet
|
|
176
|
+
The Worksheet entity containing newly created sheet.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
worksheet = self.get_by_project_id(project_id=project_id)
|
|
180
|
+
sheet = get_sheet_from_worksheet(sheet_name=source_sheet_name, worksheet=worksheet)
|
|
181
|
+
columns = get_columns_to_copy(
|
|
182
|
+
sheet=sheet,
|
|
183
|
+
copy_all_pinned_columns=copy_all_pinned_columns,
|
|
184
|
+
copy_all_unpinned_columns=copy_all_unpinned_columns,
|
|
185
|
+
input_column_names=column_names,
|
|
186
|
+
)
|
|
187
|
+
task_rows = get_task_rows_to_copy(sheet=sheet, input_row_names=task_row_names)
|
|
188
|
+
|
|
189
|
+
payload = {
|
|
190
|
+
"name": new_sheet_name,
|
|
191
|
+
"sourceData": {
|
|
192
|
+
"projectId": project_id,
|
|
193
|
+
"sheetId": sheet.id,
|
|
194
|
+
"Columns": [{"id": col_id} for col_id in columns],
|
|
195
|
+
"copyAllPDRows": copy_all_pd_rows,
|
|
196
|
+
"TaskRows": [{"id": row_id} for row_id in task_rows],
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
path = f"{self.base_path}/project/{project_id}/sheets"
|
|
201
|
+
self.session.put(path, json=payload)
|
|
202
|
+
return self.get_by_project_id(project_id=project_id)
|
|
203
|
+
|
|
204
|
+
@validate_call
|
|
205
|
+
def create_sheet_template(
|
|
206
|
+
self,
|
|
207
|
+
*,
|
|
208
|
+
project_id: ProjectId,
|
|
209
|
+
source_sheet_name: str,
|
|
210
|
+
template_name: str,
|
|
211
|
+
copy_all_pd_rows: bool = True,
|
|
212
|
+
copy_all_pinned_columns: bool = True,
|
|
213
|
+
copy_all_unpinned_columns: bool = True,
|
|
214
|
+
column_names: list[str] | None = None,
|
|
215
|
+
task_row_names: list[str] | None = None,
|
|
216
|
+
prg_row_names: list[str] | None = None,
|
|
217
|
+
acl: ACLContainer | None = None,
|
|
218
|
+
) -> CustomTemplate:
|
|
219
|
+
"""Create a new sheet template from an existing sheet.
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
project_id : str
|
|
224
|
+
The project ID under which the sheet exists.
|
|
225
|
+
source_sheet_name : str
|
|
226
|
+
The name of the existing sheet to use as the template source.
|
|
227
|
+
template_name : str
|
|
228
|
+
The name of the new template.
|
|
229
|
+
copy_all_pd_rows : bool, optional
|
|
230
|
+
When True, all PD (Product Design) rows from the source sheet are copied.
|
|
231
|
+
When False, only rows corresponding to the selected columns will be copied.
|
|
232
|
+
copy_all_pinned_columns : bool, optional
|
|
233
|
+
If True, includes all pinned columns from the source sheet. Default is True.
|
|
234
|
+
copy_all_unpinned_columns : bool, optional
|
|
235
|
+
If True, includes all unpinned columns from the source sheet. Default is True.
|
|
236
|
+
column_names : list[str], optional
|
|
237
|
+
A list of column names to explicitly copy. These are resolved internally
|
|
238
|
+
to column IDs using the sheet's product design grid.
|
|
239
|
+
task_row_names : list[str], optional
|
|
240
|
+
List of task row names to include from the tasks.
|
|
241
|
+
prg_row_names : list[str], optional
|
|
242
|
+
List of parameter group row names to include.
|
|
243
|
+
acl : ACLContainer, optional
|
|
244
|
+
ACL for the template.
|
|
245
|
+
|
|
246
|
+
Returns
|
|
247
|
+
-------
|
|
248
|
+
CustomTemplate
|
|
249
|
+
The CustomTemplate for the created sheet template.
|
|
250
|
+
"""
|
|
251
|
+
worksheet = self.get_by_project_id(project_id=project_id)
|
|
252
|
+
sheet = get_sheet_from_worksheet(sheet_name=source_sheet_name, worksheet=worksheet)
|
|
253
|
+
columns = get_columns_to_copy(
|
|
254
|
+
sheet=sheet,
|
|
255
|
+
copy_all_pinned_columns=copy_all_pinned_columns,
|
|
256
|
+
copy_all_unpinned_columns=copy_all_unpinned_columns,
|
|
257
|
+
input_column_names=column_names,
|
|
258
|
+
)
|
|
259
|
+
if not columns:
|
|
260
|
+
raise ValueError("At least one column must be selected to create a template.")
|
|
261
|
+
task_rows = get_task_rows_to_copy(sheet=sheet, input_row_names=task_row_names)
|
|
262
|
+
prg_rows = get_prg_rows_to_copy(sheet=sheet, input_row_names=prg_row_names)
|
|
263
|
+
|
|
264
|
+
payload = {
|
|
265
|
+
"name": template_name,
|
|
266
|
+
"sourceData": {
|
|
267
|
+
"projectId": project_id,
|
|
268
|
+
"sheetId": sheet.id,
|
|
269
|
+
"Columns": [{"id": col_id} for col_id in columns],
|
|
270
|
+
"copyAllPDRows": copy_all_pd_rows,
|
|
271
|
+
"TaskRows": [{"id": row_id} for row_id in task_rows],
|
|
272
|
+
"PRGRows": [{"id": row_id} for row_id in prg_rows],
|
|
273
|
+
},
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if acl is not None:
|
|
277
|
+
payload["ACL"] = acl.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
278
|
+
|
|
279
|
+
path = f"{self.base_path}/sheet/template"
|
|
280
|
+
response = self.session.post(path, json=payload)
|
|
281
|
+
response_json = response.json()
|
|
282
|
+
ctp_id = response_json.get("ctpId")
|
|
283
|
+
return CustomTemplatesCollection(session=self.session).get_by_id(id=ctp_id)
|
|
@@ -31,6 +31,10 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|
|
31
31
|
status = "successful" if self.server.token else "failed (no token found)"
|
|
32
32
|
self.send_response(200)
|
|
33
33
|
self.send_header("Content-Type", "text/html")
|
|
34
|
+
self.send_header(
|
|
35
|
+
"Content-Security-Policy",
|
|
36
|
+
"default-src 'none'; frame-ancestors 'none'; base-uri 'none';",
|
|
37
|
+
)
|
|
34
38
|
self.end_headers()
|
|
35
39
|
self.wfile.write(
|
|
36
40
|
f"""
|
|
@@ -38,8 +42,6 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|
|
38
42
|
<body>
|
|
39
43
|
<h1>Authentication {status}</h1>
|
|
40
44
|
<p>You can close this window now.</p>
|
|
41
|
-
<script>window.close()</script>
|
|
42
|
-
<button onclick="window.close()">Close Window</button>
|
|
43
45
|
</body>
|
|
44
46
|
</html>
|
|
45
47
|
""".encode()
|
|
@@ -3,10 +3,11 @@ from enum import Enum
|
|
|
3
3
|
from pydantic import Field
|
|
4
4
|
|
|
5
5
|
from albert.core.base import BaseAlbertModel
|
|
6
|
+
from albert.core.shared.models.base import BaseResource
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class AccessControlLevel(str, Enum):
|
|
9
|
-
"""
|
|
10
|
+
"""Access control levels you can grant users."""
|
|
10
11
|
|
|
11
12
|
PROJECT_OWNER = "ProjectOwner"
|
|
12
13
|
PROJECT_EDITOR = "ProjectEditor"
|
|
@@ -22,9 +23,32 @@ class AccessControlLevel(str, Enum):
|
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class ACL(BaseAlbertModel):
|
|
25
|
-
"""
|
|
26
|
+
"""A single access rule for a user.
|
|
27
|
+
|
|
28
|
+
Attributes
|
|
29
|
+
----------
|
|
30
|
+
id : str
|
|
31
|
+
The user or team this rule applies to.
|
|
32
|
+
fgc : AccessControlLevel | None
|
|
33
|
+
The access level for that user or team.
|
|
34
|
+
"""
|
|
26
35
|
|
|
27
36
|
id: str = Field(description="The id of the user for which this ACL applies")
|
|
28
37
|
fgc: AccessControlLevel | None = Field(
|
|
29
38
|
default=None, description="The Fine-Grain Control Level"
|
|
30
39
|
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ACLContainer(BaseResource):
|
|
43
|
+
"""Access settings with a default class and a list of rules.
|
|
44
|
+
|
|
45
|
+
Attributes
|
|
46
|
+
----------
|
|
47
|
+
acl_class : str | None
|
|
48
|
+
The default access class (for example, "restricted" or "confidential").
|
|
49
|
+
fgclist : list[ACL] | None
|
|
50
|
+
Specific access rules for users or teams.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
acl_class: str | None = Field(default=None, alias="class")
|
|
54
|
+
fgclist: list[ACL] | None = Field(default=None, alias="fgclist")
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
import uuid
|
|
5
|
+
import warnings
|
|
5
6
|
from datetime import datetime
|
|
6
7
|
from enum import Enum
|
|
7
8
|
from pathlib import Path
|
|
@@ -14,7 +15,7 @@ from albert.core.base import BaseAlbertModel
|
|
|
14
15
|
from albert.core.shared.identifiers import LinkId, NotebookId, ProjectId, SynthesisId, TaskId
|
|
15
16
|
from albert.core.shared.models.base import BaseResource, EntityLink
|
|
16
17
|
from albert.exceptions import AlbertException
|
|
17
|
-
from albert.resources.acls import ACL
|
|
18
|
+
from albert.resources.acls import ACL, ACLContainer
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class ListBlockStyle(str, Enum):
|
|
@@ -297,13 +298,36 @@ class PutBlockPayload(BaseAlbertModel):
|
|
|
297
298
|
|
|
298
299
|
|
|
299
300
|
class NotebookCopyACL(BaseResource):
|
|
301
|
+
"""
|
|
302
|
+
Access settings applied to a copied notebook.
|
|
303
|
+
|
|
304
|
+
Warning
|
|
305
|
+
-----
|
|
306
|
+
Deprecated and will be removed in 2.0. Use ``ACLContainer`` instead.
|
|
307
|
+
|
|
308
|
+
Attributes
|
|
309
|
+
----------
|
|
310
|
+
fgclist : list[ACL]
|
|
311
|
+
Specific access rules for users or teams.
|
|
312
|
+
acl_class : str
|
|
313
|
+
Default access class (for example, "restricted" or "confidential").
|
|
314
|
+
"""
|
|
315
|
+
|
|
300
316
|
fgclist: list[ACL] = Field(default=None)
|
|
301
317
|
acl_class: str = Field(alias="class")
|
|
302
318
|
|
|
319
|
+
def __init__(self, **data):
|
|
320
|
+
warnings.warn(
|
|
321
|
+
"NotebookCopyACL is deprecated and will be removed in 2.0; use ACLContainer instead.",
|
|
322
|
+
DeprecationWarning,
|
|
323
|
+
stacklevel=2,
|
|
324
|
+
)
|
|
325
|
+
super().__init__(**data)
|
|
326
|
+
|
|
303
327
|
|
|
304
328
|
class NotebookCopyInfo(BaseAlbertModel):
|
|
305
329
|
id: NotebookId
|
|
306
330
|
parent_id: str = Field(alias="parentId")
|
|
307
331
|
notebook_name: str | None = Field(default=None, alias="notebookName")
|
|
308
332
|
name: str | None = Field(default=None)
|
|
309
|
-
acl: NotebookCopyACL | None = Field(default=None)
|
|
333
|
+
acl: ACLContainer | NotebookCopyACL | None = Field(default=None)
|