hafnia 0.4.0__tar.gz → 0.4.2__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.
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/Dockerfile +4 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/build.yaml +7 -3
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/check_release.yaml +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/ci_cd.yaml +7 -6
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/publish_docker.yaml +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/publish_pypi.yaml +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/tests.yaml +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/PKG-INFO +4 -4
- {hafnia-0.4.0 → hafnia-0.4.2}/README.md +3 -3
- {hafnia-0.4.0 → hafnia-0.4.2}/examples/example_dataset_recipe.py +8 -6
- {hafnia-0.4.0 → hafnia-0.4.2}/examples/example_hafnia_dataset.py +15 -5
- {hafnia-0.4.0 → hafnia-0.4.2}/pyproject.toml +3 -3
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/__init__.py +1 -1
- hafnia-0.4.2/src/hafnia/dataset/dataset_names.py +190 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/dataset_recipe/dataset_recipe.py +3 -3
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/dataset_upload_helper.py +31 -26
- hafnia-0.4.0/src/hafnia/dataset/format_conversions/image_classification_from_directory.py → hafnia-0.4.2/src/hafnia/dataset/format_conversions/format_image_classification_folder.py +14 -10
- hafnia-0.4.2/src/hafnia/dataset/format_conversions/format_yolo.py +164 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/format_conversions/torchvision_datasets.py +10 -4
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/hafnia_dataset.py +246 -72
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/operations/dataset_stats.py +82 -70
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/operations/dataset_transformations.py +102 -37
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/operations/table_transformations.py +132 -15
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/bbox.py +3 -5
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/bitmask.py +2 -7
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/classification.py +3 -3
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/polygon.py +2 -4
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/primitive.py +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/segmentation.py +2 -2
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/platform/datasets.py +4 -8
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/platform/download.py +1 -72
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/torch_helpers.py +12 -12
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/utils.py +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/visualizations/image_visualizations.py +2 -0
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/__main__.py +2 -2
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/config.py +2 -2
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/dataset_cmds.py +2 -2
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/dataset_recipe_cmds.py +1 -1
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/experiment_cmds.py +1 -1
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/profile_cmds.py +2 -2
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/runc_cmds.py +1 -1
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/trainer_package_cmds.py +2 -2
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/conftest.py +3 -7
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/data/000000000139.jpg +0 -0
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/data/000000000139.txt +20 -0
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/data/000000000285.jpg +0 -0
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/data/000000000285.txt +1 -0
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/data/000000000632.jpg +0 -0
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/data/000000000632.txt +18 -0
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/images.txt +3 -0
- hafnia-0.4.2/tests/data/dataset_formats/format_yolo/obj.names +80 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/dataset_image_metadata_schema.yaml +16 -24
- hafnia-0.4.2/tests/data/expected_images/test_dataset_transformations/test_video_storage_format_read_image.png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_format_yolo/test_format_yolo_import_export_tiny_dataset.png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_format_yolo/test_import_yolo_format_visualized.png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_check_dataset[caltech-256].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_samples/test_check_dataset[midwest-vehicle-detection].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_check_dataset[tiny-dataset].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[caltech-256].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[midwest-vehicle-detection].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[tiny-dataset].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_visualizations/test_blur_anonymization[micro-coco-2017].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_visualizations/test_blur_anonymization[micro-tiny-dataset].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_visualizations/test_draw_annotations[micro-coco-2017].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_visualizations/test_draw_annotations[micro-tiny-dataset].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_visualizations/test_mask_region[micro-coco-2017].png +0 -0
- hafnia-0.4.2/tests/data/expected_images/test_visualizations/test_mask_region[micro-tiny-dataset].png +0 -0
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-coco-2017/annotations.jsonl +3 -0
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-coco-2017/annotations.parquet +0 -0
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-coco-2017/data/657/657dff54d5175e2ae9f4b9629cf57646.jpg +0 -0
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-coco-2017/data/825/825fa2d2d9416694b8e81a47ca38f580.jpg +0 -0
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-coco-2017/data/aa3/aa3cc40b5cde88e5bd189c0b3e6c223c.jpg +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/micro_test_datasets/micro-coco-2017/dataset_info.json +6 -8
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-tiny-dataset/annotations.jsonl +3 -0
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-tiny-dataset/annotations.parquet +0 -0
- hafnia-0.4.2/tests/data/micro_test_datasets/micro-tiny-dataset/data/2da/2da1d8dbf2b60bdab8dff1d7f5c2dfb5.png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/micro_test_datasets/micro-tiny-dataset/dataset_info.json +5 -42
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/helper_testing.py +101 -4
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/integration/test_cli_integration.py +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/integration/test_dataset_merges.py +11 -8
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/integration/test_dataset_recipes_with_platform.py +1 -1
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/integration/test_samples.py +2 -9
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/dataset_recipe/test_recipe_transformations.py +7 -7
- hafnia-0.4.2/tests/unit/dataset/format_conversions/test_format_yolo.py +85 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/format_conversions/test_image_classification_directory.py +7 -7
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/operations/test_dataset_stats.py +8 -8
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/operations/test_dataset_transformations.py +89 -9
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/operations/test_table_transformations.py +9 -3
- hafnia-0.4.2/tests/unit/dataset/test_dataset_names.py +13 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/test_hafnia_dataset.py +3 -3
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/test_shape_primitives.py +5 -5
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/test_cli.py +9 -9
- {hafnia-0.4.0 → hafnia-0.4.2}/uv.lock +51 -295
- hafnia-0.4.0/src/hafnia/dataset/dataset_names.py +0 -77
- hafnia-0.4.0/tests/data/expected_images/test_samples/test_check_dataset[midwest-vehicle-detection].png +0 -0
- hafnia-0.4.0/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[midwest-vehicle-detection].png +0 -0
- hafnia-0.4.0/tests/data/expected_images/test_visualizations/test_blur_anonymization[micro-coco-2017].png +0 -0
- hafnia-0.4.0/tests/data/expected_images/test_visualizations/test_blur_anonymization[micro-tiny-dataset].png +0 -0
- hafnia-0.4.0/tests/data/expected_images/test_visualizations/test_draw_annotations[micro-coco-2017].png +0 -0
- hafnia-0.4.0/tests/data/expected_images/test_visualizations/test_draw_annotations[micro-tiny-dataset].png +0 -0
- hafnia-0.4.0/tests/data/expected_images/test_visualizations/test_mask_region[micro-coco-2017].png +0 -0
- hafnia-0.4.0/tests/data/expected_images/test_visualizations/test_mask_region[micro-tiny-dataset].png +0 -0
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-coco-2017/annotations.jsonl +0 -3
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-coco-2017/annotations.parquet +0 -0
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-coco-2017/data/3b4/3b4165c8c4f830be4e95c6eb6209880a.jpg +0 -0
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-coco-2017/data/837/837b642d8a7b3b8dcf86c7a23edb55ce.jpg +0 -0
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-coco-2017/data/dc8/dc8efc98ce6304fe182a2c0a3ce312cf.jpg +0 -0
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-tiny-dataset/annotations.jsonl +0 -3
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-tiny-dataset/annotations.parquet +0 -0
- hafnia-0.4.0/tests/data/micro_test_datasets/micro-tiny-dataset/data/907/907f182da7bcedb8222bbd5721a8a86e.png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.devcontainer/devcontainer.json +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.devcontainer/hooks/post_create +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/dependabot.yaml +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.github/workflows/lint.yaml +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.gitignore +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.pre-commit-config.yaml +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.python-version +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.trivyignore +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.vscode/extensions.json +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.vscode/launch.json +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/.vscode/settings.json +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/LICENSE +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/docs/cli.md +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/docs/release.md +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/examples/example_logger.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/examples/example_torchvision_dataloader.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/data/__init__.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/data/factory.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/dataset_helpers.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/dataset_recipe/recipe_transforms.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/dataset_recipe/recipe_types.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/license_types.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/__init__.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/point.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/dataset/primitives/utils.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/experiment/__init__.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/experiment/hafnia_logger.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/http.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/log.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/platform/__init__.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/platform/builder.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/platform/dataset_recipe.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/platform/experiment.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/platform/trainer_package.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/src/hafnia/visualizations/colors.py +0 -0
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/__init__.py +0 -0
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/consts.py +0 -0
- {hafnia-0.4.0/src/cli → hafnia-0.4.2/src/hafnia_cli}/keychain.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/__init__.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_check_dataset[caltech-101].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_check_dataset[cifar100].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_check_dataset[cifar10].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_check_dataset[coco-2017].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_check_dataset[mnist].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[caltech-101].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[cifar100].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[cifar10].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[coco-2017].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/expected_images/test_samples/test_dataset_draw_image_and_target[mnist].png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/micro_test_datasets/micro-tiny-dataset/data/3dd/3ddec2275a02e79e3251d85443622e4c.png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/data/micro_test_datasets/micro-tiny-dataset/data/4d8/4d8450b045e60e8f3657ababa44af9b6.png +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/integration/test_check_example_scripts.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/integration/test_torchvision_datasets.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/dataset_recipe/test_dataset_recipe_helpers.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/dataset_recipe/test_dataset_recipes.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/test_colors.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/dataset/test_dataset_helpers.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/test_builder.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/test_hafnia_logger.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/test_utils.py +0 -0
- {hafnia-0.4.0 → hafnia-0.4.2}/tests/unit/test_visualizations.py +0 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
ARG PYTHON_VERSION
|
|
2
2
|
FROM python:${PYTHON_VERSION}-slim
|
|
3
|
+
|
|
4
|
+
RUN apt-get update && apt-get install -y pigz && rm -rf /var/lib/apt/lists/*
|
|
5
|
+
|
|
3
6
|
WORKDIR /opt/ml/processing
|
|
4
7
|
|
|
5
8
|
COPY dist/*.whl .
|
|
@@ -8,4 +11,4 @@ RUN pip install --no-cache-dir *.whl && \
|
|
|
8
11
|
|
|
9
12
|
RUN mkdir -p /opt/ml/processing/input \
|
|
10
13
|
/opt/ml/processing/output \
|
|
11
|
-
/opt/ml/processing/tmp
|
|
14
|
+
/opt/ml/processing/tmp
|
|
@@ -6,6 +6,10 @@ on:
|
|
|
6
6
|
python-version-file:
|
|
7
7
|
required: true
|
|
8
8
|
type: string
|
|
9
|
+
pyproject-toml-file:
|
|
10
|
+
required: false
|
|
11
|
+
type: string
|
|
12
|
+
default: "pyproject.toml"
|
|
9
13
|
outputs:
|
|
10
14
|
package-version:
|
|
11
15
|
description: "The extracted package version"
|
|
@@ -25,11 +29,11 @@ jobs:
|
|
|
25
29
|
- name: Extract package version
|
|
26
30
|
id: extract-version
|
|
27
31
|
run: |
|
|
28
|
-
VERSION=$(grep -m 1 'version = ' ${{ inputs.
|
|
32
|
+
VERSION=$(grep -m 1 'version = ' ${{ inputs.pyproject-toml-file }} | sed -e 's/version = "\(.*\)"/\1/')
|
|
29
33
|
echo "package_version=$VERSION" >> $GITHUB_OUTPUT
|
|
30
34
|
|
|
31
35
|
- name: Install uv
|
|
32
|
-
uses: astral-sh/setup-uv@
|
|
36
|
+
uses: astral-sh/setup-uv@v7
|
|
33
37
|
with:
|
|
34
38
|
version: 0.6.8
|
|
35
39
|
|
|
@@ -45,7 +49,7 @@ jobs:
|
|
|
45
49
|
run: uv build
|
|
46
50
|
|
|
47
51
|
- name: Upload package artifact
|
|
48
|
-
uses: actions/upload-artifact@
|
|
52
|
+
uses: actions/upload-artifact@v5.0.0
|
|
49
53
|
with:
|
|
50
54
|
name: python-package
|
|
51
55
|
path: dist/
|
|
@@ -5,14 +5,14 @@ on:
|
|
|
5
5
|
branches: [main]
|
|
6
6
|
pull_request:
|
|
7
7
|
branches: [main]
|
|
8
|
-
paths: ["src/**", "tests/**", "pyproject.toml"]
|
|
8
|
+
paths: ["src/**", "tests/**", "pyproject.toml", ".python-version", "uv.lock", ".github/workflows/**"]
|
|
9
9
|
|
|
10
10
|
jobs:
|
|
11
11
|
lint:
|
|
12
12
|
name: Lint Code
|
|
13
13
|
uses: ./.github/workflows/lint.yaml
|
|
14
14
|
with:
|
|
15
|
-
python-version-file: "
|
|
15
|
+
python-version-file: ".python-version"
|
|
16
16
|
|
|
17
17
|
security-scan:
|
|
18
18
|
name: Security Scan
|
|
@@ -36,14 +36,15 @@ jobs:
|
|
|
36
36
|
secrets: inherit
|
|
37
37
|
uses: ./.github/workflows/tests.yaml
|
|
38
38
|
with:
|
|
39
|
-
python-version-file: "
|
|
39
|
+
python-version-file: ".python-version"
|
|
40
40
|
|
|
41
41
|
build:
|
|
42
42
|
name: Build Package
|
|
43
43
|
needs: [test, security-scan]
|
|
44
44
|
uses: ./.github/workflows/build.yaml
|
|
45
45
|
with:
|
|
46
|
-
python-version-file: "
|
|
46
|
+
python-version-file: ".python-version"
|
|
47
|
+
pyproject-toml-file: "pyproject.toml"
|
|
47
48
|
|
|
48
49
|
publish-docker-staging:
|
|
49
50
|
name: Publish Docker Image to Staging
|
|
@@ -52,7 +53,7 @@ jobs:
|
|
|
52
53
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
53
54
|
uses: ./.github/workflows/publish_docker.yaml
|
|
54
55
|
with:
|
|
55
|
-
python-version-file: "
|
|
56
|
+
python-version-file: ".python-version"
|
|
56
57
|
package-version: ${{ needs.build.outputs.package-version }}
|
|
57
58
|
environment: "staging"
|
|
58
59
|
|
|
@@ -80,7 +81,7 @@ jobs:
|
|
|
80
81
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
81
82
|
uses: ./.github/workflows/publish_docker.yaml
|
|
82
83
|
with:
|
|
83
|
-
python-version-file: "
|
|
84
|
+
python-version-file: ".python-version"
|
|
84
85
|
package-version: ${{ needs.build.outputs.package-version }}
|
|
85
86
|
environment: "production"
|
|
86
87
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hafnia
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Python SDK for communication with Hafnia platform.
|
|
5
5
|
Author-email: Milestone Systems <hafniaplatform@milestone.dk>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -158,7 +158,7 @@ and `dataset.samples` with annotations as a polars DataFrame
|
|
|
158
158
|
print(dataset.samples.head(2))
|
|
159
159
|
shape: (2, 14)
|
|
160
160
|
┌──────────────┬─────────────────────────────────┬────────┬───────┬───┬─────────────────────────────────┬──────────┬──────────┬─────────────────────────────────┐
|
|
161
|
-
│ sample_index ┆ file_name ┆ height ┆ width ┆ … ┆
|
|
161
|
+
│ sample_index ┆ file_name ┆ height ┆ width ┆ … ┆ bboxes ┆ bitmasks ┆ polygons ┆ meta │
|
|
162
162
|
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
163
163
|
│ u32 ┆ str ┆ i64 ┆ i64 ┆ ┆ list[struct[11]] ┆ null ┆ null ┆ struct[5] │
|
|
164
164
|
╞══════════════╪═════════════════════════════════╪════════╪═══════╪═══╪═════════════════════════════════╪══════════╪══════════╪═════════════════════════════════╡
|
|
@@ -218,7 +218,7 @@ sample_dict = dataset[0]
|
|
|
218
218
|
|
|
219
219
|
for sample_dict in dataset:
|
|
220
220
|
sample = Sample(**sample_dict)
|
|
221
|
-
print(sample.sample_id, sample.
|
|
221
|
+
print(sample.sample_id, sample.bboxes)
|
|
222
222
|
break
|
|
223
223
|
```
|
|
224
224
|
Not that it is possible to create a `Sample` object from the sample dictionary.
|
|
@@ -421,7 +421,7 @@ pil_image.save("visualized_labels.png")
|
|
|
421
421
|
|
|
422
422
|
# Create DataLoaders - using TorchVisionCollateFn
|
|
423
423
|
collate_fn = torch_helpers.TorchVisionCollateFn(
|
|
424
|
-
skip_stacking=["
|
|
424
|
+
skip_stacking=["bboxes.bbox", "bboxes.class_idx"]
|
|
425
425
|
)
|
|
426
426
|
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True, collate_fn=collate_fn)
|
|
427
427
|
```
|
|
@@ -129,7 +129,7 @@ and `dataset.samples` with annotations as a polars DataFrame
|
|
|
129
129
|
print(dataset.samples.head(2))
|
|
130
130
|
shape: (2, 14)
|
|
131
131
|
┌──────────────┬─────────────────────────────────┬────────┬───────┬───┬─────────────────────────────────┬──────────┬──────────┬─────────────────────────────────┐
|
|
132
|
-
│ sample_index ┆ file_name ┆ height ┆ width ┆ … ┆
|
|
132
|
+
│ sample_index ┆ file_name ┆ height ┆ width ┆ … ┆ bboxes ┆ bitmasks ┆ polygons ┆ meta │
|
|
133
133
|
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
134
134
|
│ u32 ┆ str ┆ i64 ┆ i64 ┆ ┆ list[struct[11]] ┆ null ┆ null ┆ struct[5] │
|
|
135
135
|
╞══════════════╪═════════════════════════════════╪════════╪═══════╪═══╪═════════════════════════════════╪══════════╪══════════╪═════════════════════════════════╡
|
|
@@ -189,7 +189,7 @@ sample_dict = dataset[0]
|
|
|
189
189
|
|
|
190
190
|
for sample_dict in dataset:
|
|
191
191
|
sample = Sample(**sample_dict)
|
|
192
|
-
print(sample.sample_id, sample.
|
|
192
|
+
print(sample.sample_id, sample.bboxes)
|
|
193
193
|
break
|
|
194
194
|
```
|
|
195
195
|
Not that it is possible to create a `Sample` object from the sample dictionary.
|
|
@@ -392,7 +392,7 @@ pil_image.save("visualized_labels.png")
|
|
|
392
392
|
|
|
393
393
|
# Create DataLoaders - using TorchVisionCollateFn
|
|
394
394
|
collate_fn = torch_helpers.TorchVisionCollateFn(
|
|
395
|
-
skip_stacking=["
|
|
395
|
+
skip_stacking=["bboxes.bbox", "bboxes.class_idx"]
|
|
396
396
|
)
|
|
397
397
|
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True, collate_fn=collate_fn)
|
|
398
398
|
```
|
|
@@ -129,26 +129,28 @@ mapping_midwest = {
|
|
|
129
129
|
"Vehicle*": "Vehicle", # Wildcard mapping. Selects class names starting with 'Vehicle.' e.g. 'Vehicle.Bicycle', "Vehicle.Car', etc.
|
|
130
130
|
"Vehicle.Trailer": OPS_REMOVE_CLASS, # Use this to remove a class
|
|
131
131
|
}
|
|
132
|
-
coco_remapped = coco.class_mapper(class_mapping=mappings_coco, method="remove_undefined", task_name="
|
|
133
|
-
midwest_remapped = midwest.class_mapper(class_mapping=mapping_midwest, task_name="
|
|
132
|
+
coco_remapped = coco.class_mapper(class_mapping=mappings_coco, method="remove_undefined", task_name="object_detection")
|
|
133
|
+
midwest_remapped = midwest.class_mapper(class_mapping=mapping_midwest, task_name="object_detection")
|
|
134
134
|
|
|
135
135
|
# 2b) Merge datasets
|
|
136
136
|
merged_dataset_all_images = HafniaDataset.from_merge(dataset0=coco_remapped, dataset1=midwest_remapped)
|
|
137
137
|
|
|
138
138
|
# 2c) Remove images without 'Person' or 'Vehicle' annotations
|
|
139
|
-
merged_dataset = merged_dataset_all_images.select_samples_by_class_name(
|
|
139
|
+
merged_dataset = merged_dataset_all_images.select_samples_by_class_name(
|
|
140
|
+
name=["Person", "Vehicle"], task_name="object_detection"
|
|
141
|
+
)
|
|
140
142
|
merged_dataset.print_stats()
|
|
141
143
|
|
|
142
144
|
# 3) Once you have verified operations using the 'HafniaDataset' interface, you can convert
|
|
143
145
|
# the operations to a single 'DatasetRecipe'
|
|
144
146
|
merged_recipe = DatasetRecipe.from_merge(
|
|
145
147
|
recipe0=DatasetRecipe.from_name("coco-2017").class_mapper(
|
|
146
|
-
class_mapping=mappings_coco, method="remove_undefined", task_name="
|
|
148
|
+
class_mapping=mappings_coco, method="remove_undefined", task_name="object_detection"
|
|
147
149
|
),
|
|
148
150
|
recipe1=DatasetRecipe.from_name("midwest-vehicle-detection").class_mapper(
|
|
149
|
-
class_mapping=mapping_midwest, task_name="
|
|
151
|
+
class_mapping=mapping_midwest, task_name="object_detection"
|
|
150
152
|
),
|
|
151
|
-
).select_samples_by_class_name(name=["Person", "Vehicle"], task_name="
|
|
153
|
+
).select_samples_by_class_name(name=["Person", "Vehicle"], task_name="object_detection")
|
|
152
154
|
|
|
153
155
|
# 3a) Verify again on the sample datasets, that the recipe works and can build as a dataset
|
|
154
156
|
merged_dataset = merged_recipe.build()
|
|
@@ -33,8 +33,8 @@ dataset.print_class_distribution()
|
|
|
33
33
|
dataset.print_stats() # Print verbose dataset statistics
|
|
34
34
|
|
|
35
35
|
# Get dataset stats
|
|
36
|
-
dataset.
|
|
37
|
-
dataset.
|
|
36
|
+
dataset.calculate_class_counts() # Get class counts for all tasks
|
|
37
|
+
dataset.calculate_task_class_counts(primitive=Classification) # Get class counts for a specific task
|
|
38
38
|
|
|
39
39
|
# Create a dataset split for training
|
|
40
40
|
dataset_train = dataset.create_split_dataset("train")
|
|
@@ -86,9 +86,19 @@ dataset.write(path_dataset)
|
|
|
86
86
|
# Load dataset from disk
|
|
87
87
|
dataset_again = HafniaDataset.from_path(path_dataset)
|
|
88
88
|
|
|
89
|
+
## Dataset importers and exporters ##
|
|
90
|
+
dataset_coco = HafniaDataset.from_name("coco-2017").select_samples(n_samples=5, seed=42)
|
|
91
|
+
path_yolo_format = Path(".data/tmp/yolo_dataset")
|
|
89
92
|
|
|
93
|
+
# Export dataset to YOLO format
|
|
94
|
+
dataset_coco.to_yolo_format(path_export_yolo_dataset=path_yolo_format)
|
|
95
|
+
|
|
96
|
+
# Import dataset from YOLO format
|
|
97
|
+
dataset_coco_imported = HafniaDataset.from_yolo_format(path_yolo_format)
|
|
98
|
+
|
|
99
|
+
## Custom dataset operations and statistics ##
|
|
90
100
|
# Want custom dataset transformations or statistics? Use the polars table (dataset.samples) directly
|
|
91
|
-
n_objects = dataset.samples["
|
|
101
|
+
n_objects = dataset.samples["bboxes"].list.len().sum()
|
|
92
102
|
n_objects = dataset.samples[Bbox.column_name()].list.len().sum() # Use Bbox.column_name() to avoid magic variables
|
|
93
103
|
n_classifications = dataset.samples[Classification.column_name()].list.len().sum()
|
|
94
104
|
|
|
@@ -106,7 +116,7 @@ for sample_dict in dataset_train:
|
|
|
106
116
|
# Unpack dict into a Sample-object! Important for data validation, useability, IDE completion and mypy hints
|
|
107
117
|
sample: Sample = Sample(**sample_dict)
|
|
108
118
|
|
|
109
|
-
|
|
119
|
+
bboxes: List[Bbox] = sample.bboxes # Use 'sample.bboxes' access bounding boxes as a list of Bbox objects
|
|
110
120
|
bitmasks: List[Bitmask] = sample.bitmasks # Use 'sample.bitmasks' to access bitmasks as a list of Bitmask objects
|
|
111
121
|
polygons: List[Polygon] = sample.polygons # Use 'sample.polygons' to access polygons as a list of Polygon objects
|
|
112
122
|
classifications: List[Classification] = sample.classifications # As a list of Classification objects
|
|
@@ -134,7 +144,7 @@ for i_fake_sample in range(5):
|
|
|
134
144
|
width=640,
|
|
135
145
|
split="train",
|
|
136
146
|
tags=["sample"],
|
|
137
|
-
|
|
147
|
+
bboxes=bboxes,
|
|
138
148
|
classifications=classifications,
|
|
139
149
|
)
|
|
140
150
|
fake_samples.append(sample)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "hafnia"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.2"
|
|
4
4
|
description = "Python SDK for communication with Hafnia platform."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -44,14 +44,14 @@ dev = [
|
|
|
44
44
|
test = ["pytest>=8.3.4", "pre-commit>=4.2.0", "ruff>=0.9.1"]
|
|
45
45
|
|
|
46
46
|
[project.scripts]
|
|
47
|
-
hafnia = '
|
|
47
|
+
hafnia = 'hafnia_cli.__main__:main'
|
|
48
48
|
|
|
49
49
|
[build-system]
|
|
50
50
|
requires = ["hatchling"]
|
|
51
51
|
build-backend = "hatchling.build"
|
|
52
52
|
|
|
53
53
|
[tool.hatch.build.targets.wheel]
|
|
54
|
-
packages = ["src/
|
|
54
|
+
packages = ["src/hafnia_cli", "src/hafnia"]
|
|
55
55
|
|
|
56
56
|
[tool.uv]
|
|
57
57
|
default-groups = ["test"]
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
import boto3
|
|
5
|
+
from pydantic import BaseModel, field_validator
|
|
6
|
+
|
|
7
|
+
FILENAME_RECIPE_JSON = "recipe.json"
|
|
8
|
+
FILENAME_DATASET_INFO = "dataset_info.json"
|
|
9
|
+
FILENAME_ANNOTATIONS_JSONL = "annotations.jsonl"
|
|
10
|
+
FILENAME_ANNOTATIONS_PARQUET = "annotations.parquet"
|
|
11
|
+
|
|
12
|
+
DATASET_FILENAMES_REQUIRED = [
|
|
13
|
+
FILENAME_DATASET_INFO,
|
|
14
|
+
FILENAME_ANNOTATIONS_JSONL,
|
|
15
|
+
FILENAME_ANNOTATIONS_PARQUET,
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DeploymentStage(Enum):
|
|
20
|
+
STAGING = "staging"
|
|
21
|
+
PRODUCTION = "production"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
TAG_IS_SAMPLE = "sample"
|
|
25
|
+
|
|
26
|
+
OPS_REMOVE_CLASS = "__REMOVE__"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PrimitiveField:
|
|
30
|
+
CLASS_NAME: str = "class_name" # Name of the class this primitive is associated with, e.g. "car" for Bbox
|
|
31
|
+
CLASS_IDX: str = "class_idx" # Index of the class this primitive is associated with, e.g. 0 for "car" if it is the first class # noqa: E501
|
|
32
|
+
OBJECT_ID: str = "object_id" # Unique identifier for the object, e.g. "12345123"
|
|
33
|
+
CONFIDENCE: str = "confidence" # Confidence score (0-1.0) for the primitive, e.g. 0.95 for Bbox
|
|
34
|
+
|
|
35
|
+
META: str = "meta" # Contains metadata about each primitive, e.g. attributes color, occluded, iscrowd, etc.
|
|
36
|
+
TASK_NAME: str = "task_name" # Name of the task this primitive is associated with, e.g. "bboxes" for Bbox
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def fields() -> List[str]:
|
|
40
|
+
"""
|
|
41
|
+
Returns a list of expected field names for primitives.
|
|
42
|
+
"""
|
|
43
|
+
return [
|
|
44
|
+
PrimitiveField.CLASS_NAME,
|
|
45
|
+
PrimitiveField.CLASS_IDX,
|
|
46
|
+
PrimitiveField.OBJECT_ID,
|
|
47
|
+
PrimitiveField.CONFIDENCE,
|
|
48
|
+
PrimitiveField.META,
|
|
49
|
+
PrimitiveField.TASK_NAME,
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class SampleField:
|
|
54
|
+
FILE_PATH: str = "file_path"
|
|
55
|
+
HEIGHT: str = "height"
|
|
56
|
+
WIDTH: str = "width"
|
|
57
|
+
SPLIT: str = "split"
|
|
58
|
+
TAGS: str = "tags"
|
|
59
|
+
|
|
60
|
+
CLASSIFICATIONS: str = "classifications"
|
|
61
|
+
BBOXES: str = "bboxes"
|
|
62
|
+
BITMASKS: str = "bitmasks"
|
|
63
|
+
POLYGONS: str = "polygons"
|
|
64
|
+
|
|
65
|
+
STORAGE_FORMAT: str = "storage_format" # E.g. "image", "video", "zip"
|
|
66
|
+
COLLECTION_INDEX: str = "collection_index"
|
|
67
|
+
COLLECTION_ID: str = "collection_id"
|
|
68
|
+
REMOTE_PATH: str = "remote_path" # Path to the file in remote storage, e.g. S3
|
|
69
|
+
SAMPLE_INDEX: str = "sample_index"
|
|
70
|
+
|
|
71
|
+
ATTRIBUTION: str = "attribution" # Attribution for the sample (image/video), e.g. creator, license, source, etc.
|
|
72
|
+
META: str = "meta"
|
|
73
|
+
DATASET_NAME: str = "dataset_name"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class StorageFormat:
|
|
77
|
+
IMAGE: str = "image"
|
|
78
|
+
VIDEO: str = "video"
|
|
79
|
+
ZIP: str = "zip"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class SplitName:
|
|
83
|
+
TRAIN: str = "train"
|
|
84
|
+
VAL: str = "validation"
|
|
85
|
+
TEST: str = "test"
|
|
86
|
+
UNDEFINED: str = "UNDEFINED"
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
def valid_splits() -> List[str]:
|
|
90
|
+
return [SplitName.TRAIN, SplitName.VAL, SplitName.TEST]
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def all_split_names() -> List[str]:
|
|
94
|
+
return [*SplitName.valid_splits(), SplitName.UNDEFINED]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class DatasetVariant(Enum):
|
|
98
|
+
DUMP = "dump"
|
|
99
|
+
SAMPLE = "sample"
|
|
100
|
+
HIDDEN = "hidden"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class AwsCredentials(BaseModel):
|
|
104
|
+
access_key: str
|
|
105
|
+
secret_key: str
|
|
106
|
+
session_token: str
|
|
107
|
+
region: Optional[str]
|
|
108
|
+
|
|
109
|
+
def aws_credentials(self) -> Dict[str, str]:
|
|
110
|
+
"""
|
|
111
|
+
Returns the AWS credentials as a dictionary.
|
|
112
|
+
"""
|
|
113
|
+
environment_vars = {
|
|
114
|
+
"AWS_ACCESS_KEY_ID": self.access_key,
|
|
115
|
+
"AWS_SECRET_ACCESS_KEY": self.secret_key,
|
|
116
|
+
"AWS_SESSION_TOKEN": self.session_token,
|
|
117
|
+
}
|
|
118
|
+
if self.region:
|
|
119
|
+
environment_vars["AWS_REGION"] = self.region
|
|
120
|
+
|
|
121
|
+
return environment_vars
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def from_session(session: boto3.Session) -> "AwsCredentials":
|
|
125
|
+
"""
|
|
126
|
+
Creates AwsCredentials from a Boto3 session.
|
|
127
|
+
"""
|
|
128
|
+
frozen_credentials = session.get_credentials().get_frozen_credentials()
|
|
129
|
+
return AwsCredentials(
|
|
130
|
+
access_key=frozen_credentials.access_key,
|
|
131
|
+
secret_key=frozen_credentials.secret_key,
|
|
132
|
+
session_token=frozen_credentials.token,
|
|
133
|
+
region=session.region_name,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
ARN_PREFIX = "arn:aws:s3:::"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class ResourceCredentials(AwsCredentials):
|
|
141
|
+
s3_arn: str
|
|
142
|
+
|
|
143
|
+
@staticmethod
|
|
144
|
+
def fix_naming(payload: Dict[str, str]) -> "ResourceCredentials":
|
|
145
|
+
"""
|
|
146
|
+
The endpoint returns a payload with a key called 's3_path', but it
|
|
147
|
+
is actually an ARN path (starts with arn:aws:s3::). This method renames it to 's3_arn' for consistency.
|
|
148
|
+
"""
|
|
149
|
+
if "s3_path" in payload and payload["s3_path"].startswith(ARN_PREFIX):
|
|
150
|
+
payload["s3_arn"] = payload.pop("s3_path")
|
|
151
|
+
|
|
152
|
+
if "region" not in payload:
|
|
153
|
+
payload["region"] = "eu-west-1"
|
|
154
|
+
return ResourceCredentials(**payload)
|
|
155
|
+
|
|
156
|
+
@field_validator("s3_arn")
|
|
157
|
+
@classmethod
|
|
158
|
+
def validate_s3_arn(cls, value: str) -> str:
|
|
159
|
+
"""Validate s3_arn to ensure it starts with 'arn:aws:s3:::'"""
|
|
160
|
+
if not value.startswith("arn:aws:s3:::"):
|
|
161
|
+
raise ValueError(f"Invalid S3 ARN: {value}. It should start with 'arn:aws:s3:::'")
|
|
162
|
+
return value
|
|
163
|
+
|
|
164
|
+
def s3_path(self) -> str:
|
|
165
|
+
"""
|
|
166
|
+
Extracts the S3 path from the ARN.
|
|
167
|
+
Example: arn:aws:s3:::my-bucket/my-prefix -> my-bucket/my-prefix
|
|
168
|
+
"""
|
|
169
|
+
return self.s3_arn[len(ARN_PREFIX) :]
|
|
170
|
+
|
|
171
|
+
def s3_uri(self) -> str:
|
|
172
|
+
"""
|
|
173
|
+
Converts the S3 ARN to a URI format.
|
|
174
|
+
Example: arn:aws:s3:::my-bucket/my-prefix -> s3://my-bucket/my-prefix
|
|
175
|
+
"""
|
|
176
|
+
return f"s3://{self.s3_path()}"
|
|
177
|
+
|
|
178
|
+
def bucket_name(self) -> str:
|
|
179
|
+
"""
|
|
180
|
+
Extracts the bucket name from the S3 ARN.
|
|
181
|
+
Example: arn:aws:s3:::my-bucket/my-prefix -> my-bucket
|
|
182
|
+
"""
|
|
183
|
+
return self.s3_path().split("/")[0]
|
|
184
|
+
|
|
185
|
+
def object_key(self) -> str:
|
|
186
|
+
"""
|
|
187
|
+
Extracts the object key from the S3 ARN.
|
|
188
|
+
Example: arn:aws:s3:::my-bucket/my-prefix -> my-prefix
|
|
189
|
+
"""
|
|
190
|
+
return "/".join(self.s3_path().split("/")[1:])
|
|
@@ -98,8 +98,8 @@ class DatasetRecipe(Serializable):
|
|
|
98
98
|
@staticmethod
|
|
99
99
|
def from_recipe_id(recipe_id: str) -> "DatasetRecipe":
|
|
100
100
|
"""Loads a dataset recipe by id from the hafnia platform."""
|
|
101
|
-
from cli.config import Config
|
|
102
101
|
from hafnia.platform.dataset_recipe import get_dataset_recipe_by_id
|
|
102
|
+
from hafnia_cli.config import Config
|
|
103
103
|
|
|
104
104
|
cfg = Config()
|
|
105
105
|
endpoint_dataset = cfg.get_platform_endpoint("dataset_recipes")
|
|
@@ -114,8 +114,8 @@ class DatasetRecipe(Serializable):
|
|
|
114
114
|
@staticmethod
|
|
115
115
|
def from_recipe_name(name: str) -> "DatasetRecipe":
|
|
116
116
|
"""Loads a dataset recipe by name from the hafnia platform"""
|
|
117
|
-
from cli.config import Config
|
|
118
117
|
from hafnia.platform.dataset_recipe import get_dataset_recipe_by_name
|
|
118
|
+
from hafnia_cli.config import Config
|
|
119
119
|
|
|
120
120
|
cfg = Config()
|
|
121
121
|
endpoint_dataset = cfg.get_platform_endpoint("dataset_recipes")
|
|
@@ -239,8 +239,8 @@ class DatasetRecipe(Serializable):
|
|
|
239
239
|
|
|
240
240
|
def as_platform_recipe(self, recipe_name: Optional[str], overwrite: bool = False) -> Dict:
|
|
241
241
|
"""Uploads dataset recipe to the hafnia platform."""
|
|
242
|
-
from cli.config import Config
|
|
243
242
|
from hafnia.platform.dataset_recipe import get_or_create_dataset_recipe
|
|
243
|
+
from hafnia_cli.config import Config
|
|
244
244
|
|
|
245
245
|
recipe = self.as_dict()
|
|
246
246
|
cfg = Config()
|