cpg-utils 5.2.1__tar.gz → 5.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/PKG-INFO +22 -2
  2. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/cloud.py +54 -2
  3. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/config.py +32 -12
  4. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils.egg-info/PKG-INFO +22 -2
  5. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils.egg-info/requires.txt +1 -0
  6. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/setup.py +2 -1
  7. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/LICENSE +0 -0
  8. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/README.md +0 -0
  9. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/__init__.py +0 -0
  10. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/cloudpath_hail_az.py +0 -0
  11. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/constants.py +0 -0
  12. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/cromwell.py +0 -0
  13. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/cromwell_model.py +0 -0
  14. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/dataproc.py +0 -0
  15. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/git.py +0 -0
  16. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/hail_batch.py +0 -0
  17. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/membership.py +0 -0
  18. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/py.typed +0 -0
  19. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils/slack.py +0 -0
  20. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils.egg-info/SOURCES.txt +0 -0
  21. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils.egg-info/dependency_links.txt +0 -0
  22. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/cpg_utils.egg-info/top_level.txt +0 -0
  23. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/pyproject.toml +0 -0
  24. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/setup.cfg +0 -0
  25. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/test/__init__.py +0 -0
  26. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/test/test_config.py +0 -0
  27. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/test/test_cromwell.py +0 -0
  28. {cpg-utils-5.2.1 → cpg_utils-5.3.0}/test/test_doctests.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: cpg-utils
3
- Version: 5.2.1
3
+ Version: 5.3.0
4
4
  Summary: Library of convenience functions specific to the CPG
5
5
  Home-page: https://github.com/populationgenomics/cpg-utils
6
6
  License: MIT
@@ -17,6 +17,26 @@ Classifier: Topic :: Scientific/Engineering
17
17
  Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
+ Requires-Dist: boto3>=1.28.56
21
+ Requires-Dist: botocore>=1.31.56
22
+ Requires-Dist: cloudpathlib[all]
23
+ Requires-Dist: frozendict
24
+ Requires-Dist: google-auth>=1.27.0
25
+ Requires-Dist: google-cloud-artifact-registry
26
+ Requires-Dist: google-cloud-secret-manager
27
+ Requires-Dist: requests
28
+ Requires-Dist: tabulate
29
+ Requires-Dist: toml
30
+ Requires-Dist: deprecated
31
+ Dynamic: classifier
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: home-page
35
+ Dynamic: keywords
36
+ Dynamic: license
37
+ Dynamic: license-file
38
+ Dynamic: requires-dist
39
+ Dynamic: summary
20
40
 
21
41
  # cpg-utils
22
42
 
@@ -5,7 +5,9 @@ import os
5
5
  import re
6
6
  import subprocess
7
7
  import traceback
8
- from typing import Any
8
+ import urllib.parse
9
+ from collections import defaultdict
10
+ from typing import Any, NamedTuple
9
11
 
10
12
  # pylint: disable=no-name-in-module
11
13
  import google.api_core.exceptions
@@ -26,7 +28,7 @@ from google.auth._default import (
26
28
  _SERVICE_ACCOUNT_TYPE,
27
29
  )
28
30
  from google.auth.transport import requests
29
- from google.cloud import secretmanager
31
+ from google.cloud import artifactregistry, secretmanager
30
32
  from google.oauth2 import credentials as oauth2_credentials
31
33
  from google.oauth2 import service_account
32
34
 
@@ -123,6 +125,56 @@ def write_secret(project_id: str, secret_name: str, secret_value: str) -> None:
123
125
  secret_manager.disable_secret_version(request={'name': version.name})
124
126
 
125
127
 
128
+ class DockerImage(NamedTuple):
129
+ name: str
130
+ uri: str
131
+ tag_uri: str
132
+ size: str
133
+ build_time: str
134
+
135
+
136
+ _repo_image_tags: dict[str, defaultdict[str, dict[str, DockerImage]]] = {}
137
+
138
+
139
+ def _ensure_image_tags_loaded(project: str, location: str, repository: str) -> None:
140
+ """Populate _repo_image_tags as a map-of-map-of-maps of 'repository' -> 'imagename' -> 'tag' -> image."""
141
+ if repository in _repo_image_tags:
142
+ return
143
+
144
+ image_tags: defaultdict[str, dict[str, DockerImage]] = defaultdict(dict)
145
+
146
+ request = artifactregistry.ListDockerImagesRequest(
147
+ parent=f'projects/{project}/locations/{location}/repositories/{repository}',
148
+ page_size=500, # Increase efficiency by making fewer requests
149
+ )
150
+ for image in artifactregistry.ArtifactRegistryClient().list_docker_images(request):
151
+ name_and_checksum = image.name.rpartition('/dockerImages/')[2]
152
+ name = urllib.parse.unquote(name_and_checksum).rpartition('@')[0]
153
+ base_uri = image.uri.rpartition('@')[0]
154
+ for tag in image.tags:
155
+ image_tags[name][tag] = DockerImage(
156
+ image.name,
157
+ image.uri,
158
+ f'{base_uri}@{tag}',
159
+ image.image_size_bytes,
160
+ image.build_time,
161
+ )
162
+
163
+ image_tags.default_factory = None
164
+ _repo_image_tags[repository] = image_tags
165
+
166
+
167
+ def find_image(repository: str | None, name: str, version: str) -> DockerImage:
168
+ """Returns image details or raises ValueError if the image or tag does not exist."""
169
+ repository = f'images-{repository}' if repository is not None else 'images'
170
+ _ensure_image_tags_loaded('cpg-common', 'australia-southeast1', repository)
171
+ try:
172
+ return _repo_image_tags[repository][name][version]
173
+ except KeyError as e:
174
+ message = f'Image {name}:{version} not found in {repository} repository ({e} not found)'
175
+ raise ValueError(message) from None
176
+
177
+
126
178
  def get_google_identity_token(
127
179
  target_audience: str | None,
128
180
  request: google.auth.transport.Request | None = None,
@@ -9,6 +9,7 @@ import toml
9
9
  from frozendict import frozendict
10
10
 
11
11
  from cpg_utils import Path, to_path
12
+ from cpg_utils.cloud import find_image
12
13
 
13
14
  AR_GUID_NAME = 'ar-guid'
14
15
 
@@ -474,33 +475,52 @@ def output_path(
474
475
  )
475
476
 
476
477
 
477
- def image_path(key: str) -> str:
478
+ def image_path(
479
+ key: str,
480
+ version: str | list[str] | None = None,
481
+ repository: str | None = None,
482
+ ) -> str:
478
483
  """
479
- Returns a path to a container image using key in config's "images" section.
484
+ Returns a path to a container image for the given key (i.e., image name)
485
+ and version.
480
486
 
481
487
  Examples
482
488
  --------
483
- >> image_path('bcftools')
484
- 'australia-southeast1-docker.pkg.dev/cpg-common/images/bcftools:1.10.2'
485
-
486
- Assuming config structure as follows:
487
-
488
- ```toml
489
- [images]
490
- bcftools = 'australia-southeast1-docker.pkg.dev/cpg-common/images/bcftools:1.10.2'
491
- ```
489
+ >> image_path('bcftools', '1.16-1')
490
+ 'australia-southeast1-docker.pkg.dev/cpg-common/images/bcftools:1.16-1'
492
491
 
493
492
  Parameters
494
493
  ----------
495
494
  key : str
495
+ Specifies the image name.
496
+ When `version` is not specified:
496
497
  Describes the key within the `images` config section. Can list sections
497
498
  separated with '/'.
498
499
 
500
+ version : str or list[str], optional
501
+ Specifies the desired image version, e.g., '1.18-1', either directly as
502
+ a version number string or indirectly via a config key list which will
503
+ be used to retrieve a version number string via `config_retrieve`.
504
+
505
+ repository : str, optional
506
+ The suffix (e.g., 'dev' for images-dev) of an artifact registry repository
507
+ to be used instead of the default production images repository.
508
+
509
+ Using `image_path(key)` without giving `version` is deprecated. In future,
510
+ specifying it will be required.
511
+
499
512
  Returns
500
513
  -------
501
514
  str
502
515
  """
503
- return config_retrieve(['images', *key.strip('/').split('/')])
516
+ if version is None:
517
+ return config_retrieve(['images', *key.strip('/').split('/')])
518
+
519
+ if isinstance(version, list):
520
+ version = config_retrieve(version)
521
+
522
+ assert isinstance(version, str)
523
+ return find_image(repository, key, version).tag_uri
504
524
 
505
525
 
506
526
  def reference_path(key: str) -> str:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: cpg-utils
3
- Version: 5.2.1
3
+ Version: 5.3.0
4
4
  Summary: Library of convenience functions specific to the CPG
5
5
  Home-page: https://github.com/populationgenomics/cpg-utils
6
6
  License: MIT
@@ -17,6 +17,26 @@ Classifier: Topic :: Scientific/Engineering
17
17
  Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
+ Requires-Dist: boto3>=1.28.56
21
+ Requires-Dist: botocore>=1.31.56
22
+ Requires-Dist: cloudpathlib[all]
23
+ Requires-Dist: frozendict
24
+ Requires-Dist: google-auth>=1.27.0
25
+ Requires-Dist: google-cloud-artifact-registry
26
+ Requires-Dist: google-cloud-secret-manager
27
+ Requires-Dist: requests
28
+ Requires-Dist: tabulate
29
+ Requires-Dist: toml
30
+ Requires-Dist: deprecated
31
+ Dynamic: classifier
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: home-page
35
+ Dynamic: keywords
36
+ Dynamic: license
37
+ Dynamic: license-file
38
+ Dynamic: requires-dist
39
+ Dynamic: summary
20
40
 
21
41
  # cpg-utils
22
42
 
@@ -3,6 +3,7 @@ botocore>=1.31.56
3
3
  cloudpathlib[all]
4
4
  frozendict
5
5
  google-auth>=1.27.0
6
+ google-cloud-artifact-registry
6
7
  google-cloud-secret-manager
7
8
  requests
8
9
  tabulate
@@ -8,7 +8,7 @@ with open('README.md') as f:
8
8
  setup(
9
9
  name='cpg-utils',
10
10
  # This tag is automatically updated by bumpversion
11
- version='5.2.1',
11
+ version='5.3.0',
12
12
  description='Library of convenience functions specific to the CPG',
13
13
  long_description=long_description,
14
14
  long_description_content_type='text/markdown',
@@ -24,6 +24,7 @@ setup(
24
24
  'cloudpathlib[all]',
25
25
  'frozendict',
26
26
  'google-auth>=1.27.0',
27
+ 'google-cloud-artifact-registry',
27
28
  'google-cloud-secret-manager',
28
29
  'requests',
29
30
  'tabulate',
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