hafnia 0.1.26__tar.gz → 0.1.27__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 (56) hide show
  1. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/publish_docker.yaml +1 -1
  2. {hafnia-0.1.26 → hafnia-0.1.27}/PKG-INFO +1 -1
  3. {hafnia-0.1.26 → hafnia-0.1.27}/pyproject.toml +1 -1
  4. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/platform/builder.py +25 -19
  5. {hafnia-0.1.26 → hafnia-0.1.27}/uv.lock +1 -1
  6. {hafnia-0.1.26 → hafnia-0.1.27}/.devcontainer/devcontainer.json +0 -0
  7. {hafnia-0.1.26 → hafnia-0.1.27}/.devcontainer/hooks/post_create +0 -0
  8. {hafnia-0.1.26 → hafnia-0.1.27}/.github/dependabot.yaml +0 -0
  9. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/Dockerfile +0 -0
  10. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/build.yaml +0 -0
  11. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/check_release.yaml +0 -0
  12. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/ci_cd.yaml +0 -0
  13. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/lint.yaml +0 -0
  14. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/publish_pypi.yaml +0 -0
  15. {hafnia-0.1.26 → hafnia-0.1.27}/.github/workflows/tests.yaml +0 -0
  16. {hafnia-0.1.26 → hafnia-0.1.27}/.gitignore +0 -0
  17. {hafnia-0.1.26 → hafnia-0.1.27}/.pre-commit-config.yaml +0 -0
  18. {hafnia-0.1.26 → hafnia-0.1.27}/.python-version +0 -0
  19. {hafnia-0.1.26 → hafnia-0.1.27}/.vscode/extensions.json +0 -0
  20. {hafnia-0.1.26 → hafnia-0.1.27}/.vscode/launch.json +0 -0
  21. {hafnia-0.1.26 → hafnia-0.1.27}/.vscode/settings.json +0 -0
  22. {hafnia-0.1.26 → hafnia-0.1.27}/LICENSE +0 -0
  23. {hafnia-0.1.26 → hafnia-0.1.27}/README.md +0 -0
  24. {hafnia-0.1.26 → hafnia-0.1.27}/docs/cli.md +0 -0
  25. {hafnia-0.1.26 → hafnia-0.1.27}/docs/release.md +0 -0
  26. {hafnia-0.1.26 → hafnia-0.1.27}/examples/dataset_builder.py +0 -0
  27. {hafnia-0.1.26 → hafnia-0.1.27}/examples/example_load_dataset.py +0 -0
  28. {hafnia-0.1.26 → hafnia-0.1.27}/examples/example_logger.py +0 -0
  29. {hafnia-0.1.26 → hafnia-0.1.27}/examples/example_torchvision_dataloader.py +0 -0
  30. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/__init__.py +0 -0
  31. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/__main__.py +0 -0
  32. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/config.py +0 -0
  33. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/consts.py +0 -0
  34. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/data_cmds.py +0 -0
  35. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/experiment_cmds.py +0 -0
  36. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/profile_cmds.py +0 -0
  37. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/recipe_cmds.py +0 -0
  38. {hafnia-0.1.26 → hafnia-0.1.27}/src/cli/runc_cmds.py +0 -0
  39. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/__init__.py +0 -0
  40. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/data/__init__.py +0 -0
  41. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/data/factory.py +0 -0
  42. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/experiment/__init__.py +0 -0
  43. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/experiment/hafnia_logger.py +0 -0
  44. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/http.py +0 -0
  45. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/log.py +0 -0
  46. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/platform/__init__.py +0 -0
  47. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/platform/download.py +0 -0
  48. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/platform/experiment.py +0 -0
  49. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/torch_helpers.py +0 -0
  50. {hafnia-0.1.26 → hafnia-0.1.27}/src/hafnia/utils.py +0 -0
  51. {hafnia-0.1.26 → hafnia-0.1.27}/tests/test_builder.py +0 -0
  52. {hafnia-0.1.26 → hafnia-0.1.27}/tests/test_check_example_scripts.py +0 -0
  53. {hafnia-0.1.26 → hafnia-0.1.27}/tests/test_cli.py +0 -0
  54. {hafnia-0.1.26 → hafnia-0.1.27}/tests/test_hafnia_logger.py +0 -0
  55. {hafnia-0.1.26 → hafnia-0.1.27}/tests/test_samples.py +0 -0
  56. {hafnia-0.1.26 → hafnia-0.1.27}/tests/test_utils.py +0 -0
@@ -57,7 +57,7 @@ jobs:
57
57
  uses: aws-actions/amazon-ecr-login@v2.0.1
58
58
 
59
59
  - name: Set up Docker Buildx
60
- uses: docker/setup-buildx-action@v3.10.0
60
+ uses: docker/setup-buildx-action@v3.11.0
61
61
 
62
62
  - name: Build and push
63
63
  uses: docker/build-push-action@v6.18.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hafnia
3
- Version: 0.1.26
3
+ Version: 0.1.27
4
4
  Summary: Python SDK for communication with Hafnia platform.
5
5
  Author-email: Milestone Systems <hafniaplatform@milestone.dk>
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hafnia"
3
- version = "0.1.26"
3
+ version = "0.1.27"
4
4
  description = "Python SDK for communication with Hafnia platform."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1,7 +1,7 @@
1
1
  import json
2
2
  import os
3
+ import re
3
4
  import subprocess
4
- import tempfile
5
5
  import zipfile
6
6
  from hashlib import sha256
7
7
  from pathlib import Path
@@ -58,7 +58,7 @@ def buildx_available() -> bool:
58
58
  return False
59
59
 
60
60
 
61
- def build_dockerfile(dockerfile: str, docker_context: str, docker_tag: str, meta_file: str) -> None:
61
+ def build_dockerfile(dockerfile: str, docker_context: str, docker_tag: str) -> None:
62
62
  """
63
63
  Build a Docker image using the provided Dockerfile.
64
64
 
@@ -73,12 +73,12 @@ def build_dockerfile(dockerfile: str, docker_context: str, docker_tag: str, meta
73
73
 
74
74
  cmd = ["docker", "build", "--platform", "linux/amd64", "-t", docker_tag, "-f", dockerfile]
75
75
 
76
- remote_cache = os.getenv("REMOTE_CACHE_REPO")
76
+ remote_cache = os.getenv("EXPERIMENT_CACHE_ECR")
77
77
  cloud_mode = os.getenv("HAFNIA_CLOUD", "false").lower() in ["true", "1", "yes"]
78
78
 
79
79
  if buildx_available():
80
80
  cmd.insert(1, "buildx")
81
- cmd += ["--build-arg", "BUILDKIT_INLINE_CACHE=1", "--metadata-file", meta_file]
81
+ cmd += ["--build-arg", "BUILDKIT_INLINE_CACHE=1"]
82
82
  if cloud_mode:
83
83
  cmd += ["--push"]
84
84
  if remote_cache:
@@ -91,11 +91,27 @@ def build_dockerfile(dockerfile: str, docker_context: str, docker_tag: str, meta
91
91
  cmd.append(docker_context)
92
92
  sys_logger.debug("Build cmd: `{}`".format(" ".join(cmd)))
93
93
  sys_logger.info(f"Building and pushing Docker image with BuildKit (buildx); cache repo: {remote_cache or 'none'}")
94
+ result = None
95
+ output = ""
96
+ errors = []
94
97
  try:
95
- subprocess.run(cmd, check=True)
98
+ result = subprocess.run(cmd, check=True, capture_output=True, text=True)
99
+ output = (result.stdout or "") + (result.stderr or "")
96
100
  except subprocess.CalledProcessError as e:
97
- sys_logger.error(f"Docker build failed: {e}")
98
- raise RuntimeError(f"Docker build failed: {e}")
101
+ output = (e.stdout or "") + (e.stderr or "")
102
+ error_pattern = r"ERROR: (.+?)(?:\n|$)"
103
+ errors = re.findall(error_pattern, output)
104
+ if not errors:
105
+ raise RuntimeError(f"Docker build failed: {output}")
106
+ if re.search(r"image tag '([^']+)' already exists", errors[-1]):
107
+ sys_logger.warning("Image {} already exists in the registry.".format(docker_tag.rsplit("/")[-1]))
108
+ return
109
+ raise RuntimeError(f"Docker build failed: {output}")
110
+ finally:
111
+ stage_pattern = r"^.*\[\d+/\d+\][^\n]*"
112
+ stages = re.findall(stage_pattern, output, re.MULTILINE)
113
+ user_logger.info("\n".join(stages))
114
+ sys_logger.debug(output)
99
115
 
100
116
 
101
117
  def check_registry(docker_image: str) -> Optional[str]:
@@ -127,18 +143,8 @@ def build_image(metadata: Dict, registry_repo: str, state_file: str = "state.jso
127
143
  docker_image = f"{registry_repo}:{metadata['digest']}"
128
144
  image_exists = check_registry(docker_image) is not None
129
145
  if image_exists:
130
- sys_logger.info(f"Tag already in ECR – skipping build of {docker_image}.")
146
+ sys_logger.info("Image {} already exists in the registry.".format(docker_image.rsplit("/")[-1]))
131
147
  else:
132
- with tempfile.NamedTemporaryFile() as meta_tmp:
133
- meta_file = meta_tmp.name
134
- build_dockerfile(
135
- metadata["dockerfile"], Path(metadata["dockerfile"]).parent.as_posix(), docker_image, meta_file
136
- )
137
- with open(meta_file) as m:
138
- try:
139
- build_meta = json.load(m)
140
- metadata["local_digest"] = build_meta["containerimage.digest"]
141
- except Exception:
142
- metadata["local_digest"] = ""
148
+ build_dockerfile(metadata["dockerfile"], Path(metadata["dockerfile"]).parent.as_posix(), docker_image)
143
149
  metadata.update({"image_tag": docker_image, "image_exists": image_exists})
144
150
  Path(state_file).write_text(json.dumps(metadata, indent=2))
@@ -558,7 +558,7 @@ http = [
558
558
 
559
559
  [[package]]
560
560
  name = "hafnia"
561
- version = "0.1.26"
561
+ version = "0.1.27"
562
562
  source = { editable = "." }
563
563
  dependencies = [
564
564
  { name = "boto3" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes