holoscan 2.6.0__cp312-cp312-manylinux_2_35_x86_64.whl

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 (126) hide show
  1. holoscan-2.6.0.data/purelib/holoscan/__init__.py +133 -0
  2. holoscan-2.6.0.data/purelib/holoscan/cli/__init__.py +32 -0
  3. holoscan-2.6.0.data/purelib/holoscan/cli/__main__.py +159 -0
  4. holoscan-2.6.0.data/purelib/holoscan/cli/common/argparse_types.py +153 -0
  5. holoscan-2.6.0.data/purelib/holoscan/cli/common/artifact_sources.py +149 -0
  6. holoscan-2.6.0.data/purelib/holoscan/cli/common/constants.py +119 -0
  7. holoscan-2.6.0.data/purelib/holoscan/cli/common/dockerutils.py +509 -0
  8. holoscan-2.6.0.data/purelib/holoscan/cli/common/enum_types.py +52 -0
  9. holoscan-2.6.0.data/purelib/holoscan/cli/common/exceptions.py +130 -0
  10. holoscan-2.6.0.data/purelib/holoscan/cli/common/sdk_utils.py +180 -0
  11. holoscan-2.6.0.data/purelib/holoscan/cli/common/utils.py +130 -0
  12. holoscan-2.6.0.data/purelib/holoscan/cli/logging.json +37 -0
  13. holoscan-2.6.0.data/purelib/holoscan/cli/nics/__init__.py +18 -0
  14. holoscan-2.6.0.data/purelib/holoscan/cli/nics/nics.py +34 -0
  15. holoscan-2.6.0.data/purelib/holoscan/cli/packager/__init__.py +18 -0
  16. holoscan-2.6.0.data/purelib/holoscan/cli/packager/arguments.py +137 -0
  17. holoscan-2.6.0.data/purelib/holoscan/cli/packager/config_reader.py +181 -0
  18. holoscan-2.6.0.data/purelib/holoscan/cli/packager/container_builder.py +368 -0
  19. holoscan-2.6.0.data/purelib/holoscan/cli/packager/manifest_files.py +220 -0
  20. holoscan-2.6.0.data/purelib/holoscan/cli/packager/models.py +93 -0
  21. holoscan-2.6.0.data/purelib/holoscan/cli/packager/package_command.py +189 -0
  22. holoscan-2.6.0.data/purelib/holoscan/cli/packager/packager.py +122 -0
  23. holoscan-2.6.0.data/purelib/holoscan/cli/packager/parameters.py +558 -0
  24. holoscan-2.6.0.data/purelib/holoscan/cli/packager/platforms.py +402 -0
  25. holoscan-2.6.0.data/purelib/holoscan/cli/packager/templates/Dockerfile.jinja2 +470 -0
  26. holoscan-2.6.0.data/purelib/holoscan/cli/packager/templates/dockerignore +93 -0
  27. holoscan-2.6.0.data/purelib/holoscan/cli/packager/templates/tools.sh +416 -0
  28. holoscan-2.6.0.data/purelib/holoscan/cli/py.typed +0 -0
  29. holoscan-2.6.0.data/purelib/holoscan/cli/runner/__init__.py +18 -0
  30. holoscan-2.6.0.data/purelib/holoscan/cli/runner/resources.py +174 -0
  31. holoscan-2.6.0.data/purelib/holoscan/cli/runner/run_command.py +203 -0
  32. holoscan-2.6.0.data/purelib/holoscan/cli/runner/runner.py +306 -0
  33. holoscan-2.6.0.data/purelib/holoscan/cli/version/__init__.py +18 -0
  34. holoscan-2.6.0.data/purelib/holoscan/cli/version/version.py +50 -0
  35. holoscan-2.6.0.data/purelib/holoscan/conditions/__init__.py +57 -0
  36. holoscan-2.6.0.data/purelib/holoscan/core/__init__.py +430 -0
  37. holoscan-2.6.0.data/purelib/holoscan/decorator.py +592 -0
  38. holoscan-2.6.0.data/purelib/holoscan/executors/__init__.py +26 -0
  39. holoscan-2.6.0.data/purelib/holoscan/graphs/__init__.py +32 -0
  40. holoscan-2.6.0.data/purelib/holoscan/gxf/__init__.py +57 -0
  41. holoscan-2.6.0.data/purelib/holoscan/lib/gxf_extensions/libgxf_holoscan_wrapper.so +0 -0
  42. holoscan-2.6.0.data/purelib/holoscan/lib/gxf_extensions/libgxf_holoscan_wrapper_lib.so +0 -0
  43. holoscan-2.6.0.data/purelib/holoscan/lib/gxf_extensions/libgxf_ucx_holoscan.so +0 -0
  44. holoscan-2.6.0.data/purelib/holoscan/lib/gxf_extensions/libgxf_ucx_holoscan_lib.so +0 -0
  45. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_app.so +0 -0
  46. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_core.so +0 -0
  47. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_cuda.so +0 -0
  48. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_logger.so +0 -0
  49. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_multimedia.so +0 -0
  50. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_rmm.so +0 -0
  51. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_sample.so +0 -0
  52. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_serialization.so +0 -0
  53. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_std.so +0 -0
  54. holoscan-2.6.0.data/purelib/holoscan/lib/libgxf_ucx.so +0 -0
  55. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_core.so.2.6.0 +0 -0
  56. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_infer.so.2.6.0 +0 -0
  57. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_infer_onnx_runtime.so.2.6.0 +0 -0
  58. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_infer_torch.so.2.6.0 +0 -0
  59. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_infer_utils.so.2.6.0 +0 -0
  60. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_logger.so.2.6.0 +0 -0
  61. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_aja.so.2.6.0 +0 -0
  62. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_async_ping_rx.so.2.6.0 +0 -0
  63. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_async_ping_tx.so.2.6.0 +0 -0
  64. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_bayer_demosaic.so.2.6.0 +0 -0
  65. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_format_converter.so.2.6.0 +0 -0
  66. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_gxf_codelet.so.2.6.0 +0 -0
  67. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_holoviz.so.2.6.0 +0 -0
  68. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_inference.so.2.6.0 +0 -0
  69. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_inference_processor.so.2.6.0 +0 -0
  70. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_ping_rx.so.2.6.0 +0 -0
  71. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_ping_tensor_rx.so.2.6.0 +0 -0
  72. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_ping_tensor_tx.so.2.6.0 +0 -0
  73. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_ping_tx.so.2.6.0 +0 -0
  74. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_segmentation_postprocessor.so.2.6.0 +0 -0
  75. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_v4l2.so.2.6.0 +0 -0
  76. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_video_stream_recorder.so.2.6.0 +0 -0
  77. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_op_video_stream_replayer.so.2.6.0 +0 -0
  78. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_profiler.so.2.6.0 +0 -0
  79. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_spdlog_logger.so.2.6.0 +0 -0
  80. holoscan-2.6.0.data/purelib/holoscan/lib/libholoscan_viz.so.2.6.0 +0 -0
  81. holoscan-2.6.0.data/purelib/holoscan/lib/libucm.so.0.0.0 +0 -0
  82. holoscan-2.6.0.data/purelib/holoscan/lib/libucp.so.0.0.0 +0 -0
  83. holoscan-2.6.0.data/purelib/holoscan/lib/libucs.so.0.0.0 +0 -0
  84. holoscan-2.6.0.data/purelib/holoscan/lib/libucs_signal.so.0.0.0 +0 -0
  85. holoscan-2.6.0.data/purelib/holoscan/lib/libuct.so.0.0.0 +0 -0
  86. holoscan-2.6.0.data/purelib/holoscan/lib/libyaml-cpp.so.0.7.0 +0 -0
  87. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libucm_cuda.so.0.0.0 +0 -0
  88. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libucs_fuse.so.0.0.0 +0 -0
  89. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libuct_cma.so.0.0.0 +0 -0
  90. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libuct_cuda.so.0.0.0 +0 -0
  91. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libuct_cuda_gdrcopy.so.0.0.0 +0 -0
  92. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libuct_ib.so.0.0.0 +0 -0
  93. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libuct_rdmacm.so.0.0.0 +0 -0
  94. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libuct_xpmem.so.0.0.0 +0 -0
  95. holoscan-2.6.0.data/purelib/holoscan/lib/ucx/libucx_perftest_cuda.so.0.0.0 +0 -0
  96. holoscan-2.6.0.data/purelib/holoscan/logger/__init__.py +37 -0
  97. holoscan-2.6.0.data/purelib/holoscan/network_contexts/__init__.py +28 -0
  98. holoscan-2.6.0.data/purelib/holoscan/operators/__init__.py +97 -0
  99. holoscan-2.6.0.data/purelib/holoscan/operators/aja_source/__init__.py +22 -0
  100. holoscan-2.6.0.data/purelib/holoscan/operators/bayer_demosaic/__init__.py +24 -0
  101. holoscan-2.6.0.data/purelib/holoscan/operators/format_converter/__init__.py +23 -0
  102. holoscan-2.6.0.data/purelib/holoscan/operators/gxf_codelet/__init__.py +67 -0
  103. holoscan-2.6.0.data/purelib/holoscan/operators/holoviz/__init__.py +424 -0
  104. holoscan-2.6.0.data/purelib/holoscan/operators/inference/__init__.py +23 -0
  105. holoscan-2.6.0.data/purelib/holoscan/operators/inference_processor/__init__.py +23 -0
  106. holoscan-2.6.0.data/purelib/holoscan/operators/ping_rx/__init__.py +45 -0
  107. holoscan-2.6.0.data/purelib/holoscan/operators/ping_tensor_rx/__init__.py +22 -0
  108. holoscan-2.6.0.data/purelib/holoscan/operators/ping_tensor_tx/__init__.py +22 -0
  109. holoscan-2.6.0.data/purelib/holoscan/operators/ping_tx/__init__.py +46 -0
  110. holoscan-2.6.0.data/purelib/holoscan/operators/segmentation_postprocessor/__init__.py +23 -0
  111. holoscan-2.6.0.data/purelib/holoscan/operators/v4l2_video_capture/__init__.py +23 -0
  112. holoscan-2.6.0.data/purelib/holoscan/operators/video_stream_recorder/__init__.py +22 -0
  113. holoscan-2.6.0.data/purelib/holoscan/operators/video_stream_replayer/__init__.py +22 -0
  114. holoscan-2.6.0.data/purelib/holoscan/resources/__init__.py +147 -0
  115. holoscan-2.6.0.data/purelib/holoscan/schedulers/__init__.py +32 -0
  116. holoscan-2.6.0.data/purelib/holoscan-2.6.0.pth +1 -0
  117. holoscan-2.6.0.dist-info/LICENSE.txt +202 -0
  118. holoscan-2.6.0.dist-info/METADATA +125 -0
  119. holoscan-2.6.0.dist-info/NOTICE.txt +174 -0
  120. holoscan-2.6.0.dist-info/NVIDIA-AI-PRODUCT-EULA.txt +243 -0
  121. holoscan-2.6.0.dist-info/RECORD +126 -0
  122. holoscan-2.6.0.dist-info/WHEEL +5 -0
  123. holoscan-2.6.0.dist-info/axle.lck +0 -0
  124. holoscan-2.6.0.dist-info/entry_points.txt +3 -0
  125. holoscan-2.6.0.dist-info/symlinks.txt +82 -0
  126. holoscan-2.6.0.dist-info/top_level.txt +3 -0
@@ -0,0 +1,133 @@
1
+ """
2
+ SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ SPDX-License-Identifier: Apache-2.0
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ """ # noqa: E501
17
+
18
+ import importlib.metadata
19
+
20
+ # We import cli, core and gxf to make sure they're available before other modules that rely on them
21
+ from . import cli, core, gxf
22
+
23
+
24
+ def _set_version():
25
+ try:
26
+ return importlib.metadata.version("holoscan")
27
+ except ImportError:
28
+ return "unknown version"
29
+
30
+
31
+ __all__ = ["__version__", "as_tensor", "cli", "core", "gxf"]
32
+ __version__ = _set_version()
33
+
34
+
35
+ def as_tensor(obj):
36
+ if hasattr(obj, "__cuda_array_interface__") or hasattr(obj, "__array_interface__"):
37
+ # Workaround for bug in CuPy<13.0.0a1 where strides of ndarray with all but 1 dimension a
38
+ # singleton, could become order='F' strides instead of the expected order='C' strides.
39
+ # See:
40
+ # https://github.com/cupy/cupy/pull/7438
41
+ # https://github.com/cupy/cupy/pull/7457
42
+ # https://forums.developer.nvidia.com/t/known-issue-in-cupy-affecting-tensor-interop/244423
43
+ #
44
+ # Here we force any array that is both C and F contiguous to have C-ordered strides
45
+ # We do this for both NumPy and CuPy arrays for consistency.
46
+
47
+ # nd-array, but with only 1 non-singleton dimension
48
+ nd_singleton = (obj.ndim > 1) and (sum(tuple(s > 1 for s in obj.shape)) == 1)
49
+ if nd_singleton and obj.flags.forc:
50
+ # determine expected strides for a C-contiguous array
51
+ expected_strides = [
52
+ 1,
53
+ ] * obj.ndim
54
+ expected_strides[obj.ndim - 1] = obj.itemsize
55
+ for i in range(obj.ndim - 2, -1, -1):
56
+ expected_strides[i] = expected_strides[i + 1] * obj.shape[i + 1]
57
+ expected_strides = tuple(expected_strides)
58
+
59
+ # make a copy to force stride update if they do not match
60
+ if obj.strides != expected_strides:
61
+ if hasattr(obj, "__cuda_array_interface__"):
62
+ try:
63
+ import cupy as cp
64
+
65
+ if isinstance(obj, cp.ndarray):
66
+ # use as_strided to avoid a copy
67
+ obj = cp.lib.stride_tricks.as_strided(
68
+ obj, shape=obj.shape, strides=expected_strides
69
+ )
70
+ return core.Tensor.as_tensor(obj)
71
+ except ImportError:
72
+ pass
73
+ elif hasattr(obj, "__array_interface__"):
74
+ try:
75
+ import numpy as np
76
+
77
+ if isinstance(obj, np.ndarray):
78
+ # use as_strided to avoid a copy
79
+ obj = np.lib.stride_tricks.as_strided(
80
+ obj, shape=obj.shape, strides=expected_strides
81
+ )
82
+ return core.Tensor.as_tensor(obj)
83
+ except ImportError:
84
+ pass
85
+ # update strides by making an explicit copy
86
+ try:
87
+ obj = obj.copy(order="C")
88
+ except (AttributeError, TypeError):
89
+ import warnings
90
+
91
+ warnings.warn(
92
+ "Unexpected strides encountered during call to `as_tensor` and no copy "
93
+ "method was available. Leaving the strides unchanged.",
94
+ stacklevel=2,
95
+ )
96
+
97
+ return core.Tensor.as_tensor(obj)
98
+
99
+
100
+ as_tensor.__doc__ = core.Tensor.as_tensor.__doc__
101
+
102
+
103
+ # Other modules are exposed to the public API but will only be lazily loaded
104
+ _EXTRA_MODULES = [
105
+ "conditions",
106
+ "decorator",
107
+ "executors",
108
+ "graphs",
109
+ "logger",
110
+ "operators",
111
+ "resources",
112
+ "schedulers",
113
+ ]
114
+ __all__.extend(_EXTRA_MODULES)
115
+
116
+
117
+ # Autocomplete
118
+ def __dir__():
119
+ return __all__
120
+
121
+
122
+ # Lazily load extra modules
123
+ def __getattr__(name):
124
+ import importlib
125
+ import sys
126
+
127
+ if name in _EXTRA_MODULES:
128
+ module_name = f"{__name__}.{name}"
129
+ module = importlib.import_module(module_name) # import
130
+ sys.modules[module_name] = module # cache
131
+ return module
132
+ else:
133
+ raise AttributeError(f"module {__name__} has no attribute {name}")
@@ -0,0 +1,32 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations undwer the License.
15
+ """
16
+ .. autosummary::
17
+ :toctree: _autosummary
18
+
19
+ common
20
+ packager
21
+ runner
22
+ version
23
+ """
24
+
25
+ import os
26
+ import sys
27
+
28
+ __title__ = "holoscan.cli"
29
+ _current_dir = os.path.abspath(os.path.dirname(__file__))
30
+ if sys.path and os.path.abspath(sys.path[0]) != _current_dir:
31
+ sys.path.insert(0, _current_dir)
32
+ del _current_dir
@@ -0,0 +1,159 @@
1
+ """
2
+ SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ SPDX-License-Identifier: Apache-2.0
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ """ # noqa: E501
17
+
18
+ import argparse
19
+ import json
20
+ import logging
21
+ import logging.config
22
+ import os
23
+ from pathlib import Path
24
+ from typing import Optional, Union
25
+
26
+ from .common.enum_types import Platform, PlatformConfiguration
27
+
28
+ logging.getLogger("docker.api.build").setLevel(logging.WARNING)
29
+ logging.getLogger("docker.auth").setLevel(logging.WARNING)
30
+ logging.getLogger("docker.utils.config").setLevel(logging.WARNING)
31
+ logging.getLogger("urllib3.connectionpool").setLevel(logging.WARNING)
32
+ logging.getLogger("urllib3").setLevel(logging.WARNING)
33
+
34
+ LOG_CONFIG_FILENAME = "logging.json"
35
+
36
+
37
+ def parse_args(argv: Optional[list[str]] = None) -> argparse.Namespace:
38
+ from .packager.package_command import create_package_parser
39
+ from .runner.run_command import create_run_parser
40
+
41
+ if argv is None:
42
+ import sys
43
+
44
+ argv = sys.argv
45
+ argv = list(argv) # copy argv for manipulation to avoid side-effects
46
+
47
+ # We have intentionally not set the default using `default="INFO"` here so that the default
48
+ # value from here doesn't override the value in `LOG_CONFIG_FILENAME` unless the user indends
49
+ # to do so. If the user doesn't use this flag to set log level, this argument is set to "None"
50
+ # and the logging level specified in `LOG_CONFIG_FILENAME` is used.
51
+
52
+ command_name = os.path.basename(argv[0])
53
+ program_name = "holoscan" if command_name == "__main__.py" else command_name
54
+ parent_parser = argparse.ArgumentParser()
55
+
56
+ parent_parser.add_argument(
57
+ "-l",
58
+ "--log-level",
59
+ dest="log_level",
60
+ type=str.upper,
61
+ choices=["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL"],
62
+ help="set the logging level (default: INFO)",
63
+ )
64
+
65
+ parser = argparse.ArgumentParser(
66
+ parents=[parent_parser],
67
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
68
+ add_help=False,
69
+ prog=program_name,
70
+ )
71
+
72
+ subparser = parser.add_subparsers(dest="command")
73
+
74
+ # Parser for `package` command
75
+ create_package_parser(subparser, "package", parents=[parent_parser])
76
+
77
+ # Parser for `run` command
78
+ create_run_parser(subparser, "run", parents=[parent_parser])
79
+
80
+ # Parser for `version` command
81
+ subparser.add_parser(
82
+ "version", formatter_class=argparse.HelpFormatter, parents=[parent_parser], add_help=False
83
+ )
84
+
85
+ # Parser for `nics` command
86
+ subparser.add_parser(
87
+ "nics", formatter_class=argparse.HelpFormatter, parents=[parent_parser], add_help=False
88
+ )
89
+ args = parser.parse_args(argv[1:])
90
+ args.argv = argv # save argv for later use in runpy
91
+
92
+ # Print help if no command is specified
93
+ if args.command is None:
94
+ parser.print_help()
95
+ parser.exit()
96
+
97
+ if args.command == "package":
98
+ if args.platform[0] == Platform.X64Workstation:
99
+ args.platform_config = PlatformConfiguration.dGPU
100
+ elif args.platform_config is None:
101
+ parser.error(f"'--platform-config' is required for '{args.platform[0].value}'")
102
+
103
+ return args
104
+
105
+
106
+ def set_up_logging(level: Optional[str], config_path: Union[str, Path] = LOG_CONFIG_FILENAME):
107
+ """Initializes the logger and sets up logging level.
108
+
109
+ Args:
110
+ level (str): A logging level (DEBUG, INFO, WARN, ERROR, CRITICAL).
111
+ log_config_path (str): A path to logging config file.
112
+ """
113
+ # Default log config path
114
+ log_config_path = Path(__file__).absolute().parent / LOG_CONFIG_FILENAME
115
+
116
+ config_path = Path(config_path)
117
+
118
+ # If a logging config file that is specified by `log_config_path` exists in the current folder,
119
+ # it overrides the default one
120
+ if config_path.exists():
121
+ log_config_path = config_path
122
+
123
+ config_dict = json.loads(log_config_path.read_bytes())
124
+
125
+ if level is not None and "root" in config_dict:
126
+ config_dict["root"]["level"] = level
127
+ logging.config.dictConfig(config_dict)
128
+
129
+
130
+ def main(argv: Optional[list[str]] = None):
131
+ args = parse_args(argv)
132
+
133
+ set_up_logging(args.log_level)
134
+
135
+ if args.command == "package":
136
+ from .packager.packager import execute_package_command
137
+
138
+ execute_package_command(args)
139
+
140
+ elif args.command == "run":
141
+ from .runner.runner import execute_run_command
142
+
143
+ execute_run_command(args)
144
+
145
+ elif args.command == "version":
146
+ from .common.artifact_sources import ArtifactSources
147
+ from .version.version import execute_version_command
148
+
149
+ artifact_sources = ArtifactSources()
150
+ execute_version_command(args, artifact_sources)
151
+
152
+ elif args.command == "nics":
153
+ from .nics.nics import execute_nics_command
154
+
155
+ execute_nics_command(args)
156
+
157
+
158
+ if __name__ == "__main__":
159
+ main()
@@ -0,0 +1,153 @@
1
+ """
2
+ SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ SPDX-License-Identifier: Apache-2.0
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ """ # noqa: E501
17
+
18
+ import argparse
19
+ import os
20
+ from pathlib import Path
21
+
22
+ from .constants import SDK
23
+ from .enum_types import Platform, PlatformConfiguration, SdkType
24
+
25
+
26
+ def valid_dir_path(path: str, create_if_not_exists: bool = True) -> Path:
27
+ """Helper type checking and type converting method for ArgumentParser.add_argument
28
+ to convert string input to pathlib.Path if the given path exists and it is a directory path.
29
+ If directory does not exist, create the directory and convert string input to pathlib.Path.
30
+
31
+ Args:
32
+ path: string input path
33
+
34
+ Returns:
35
+ If path exists and is a directory, return absolute path as a pathlib.Path object.
36
+
37
+ If path exists and is not a directory, raises argparse.ArgumentTypeError.
38
+
39
+ If path doesn't exist, create the directory and return absolute path as a pathlib.Path
40
+ object.
41
+ """
42
+ path = os.path.expanduser(path)
43
+ dir_path = Path(path).absolute()
44
+ if dir_path.exists():
45
+ if dir_path.is_dir():
46
+ return dir_path
47
+ else:
48
+ raise argparse.ArgumentTypeError(
49
+ f"Expected directory path: '{dir_path}' is not a directory"
50
+ )
51
+
52
+ if create_if_not_exists:
53
+ # create directory
54
+ dir_path.mkdir(parents=True)
55
+ return dir_path
56
+
57
+ raise argparse.ArgumentTypeError(f"No such directory: '{dir_path}'")
58
+
59
+
60
+ def valid_existing_dir_path(path: str) -> Path:
61
+ """Helper type checking and type converting method for ArgumentParser.add_argument
62
+ to convert string input to pathlib.Path if the given path exists and it is a directory path.
63
+
64
+ Args:
65
+ path: string input path
66
+
67
+ Returns:
68
+ If path exists and is a directory, return absolute path as a pathlib.Path object.
69
+
70
+ If path doesn't exist or it is not a directory, raises argparse.ArgumentTypeError.
71
+ """
72
+ return valid_dir_path(path, False)
73
+
74
+
75
+ def valid_existing_path(path: str) -> Path:
76
+ """Helper type checking and type converting method for ArgumentParser.add_argument
77
+ to convert string input to pathlib.Path if the given file/folder path exists.
78
+
79
+ Args:
80
+ path: string input path
81
+
82
+ Returns:
83
+ If path exists, return absolute path as a pathlib.Path object.
84
+
85
+ If path doesn't exist, raises argparse.ArgumentTypeError.
86
+ """
87
+ path = os.path.expanduser(path)
88
+ file_path = Path(path).absolute()
89
+ if file_path.exists():
90
+ return file_path
91
+ raise argparse.ArgumentTypeError(f"No such file/folder: '{file_path}'")
92
+
93
+
94
+ def valid_platforms(platforms_str: str) -> list[Platform]:
95
+ """Helper type checking and type converting method for ArgumentParser.add_argument
96
+ to convert platform strings to Platform enum if values are valid.
97
+
98
+ Args:
99
+ platforms_str: string comma separated platforms values
100
+ Returns:
101
+ If all values are valid, convert all values to Platform enum.
102
+
103
+ Otherwise, raises argparse.ArgumentTypeError.
104
+ """
105
+
106
+ platforms = platforms_str.lower().split(",")
107
+ platform_enums = []
108
+ for platform in platforms:
109
+ if platform not in SDK.PLATFORMS:
110
+ raise argparse.ArgumentTypeError(f"{platform} is not a valid option for --platforms.")
111
+ platform_enums.append(Platform(platform))
112
+
113
+ return platform_enums
114
+
115
+
116
+ def valid_platform_config(platform_config_str: str) -> PlatformConfiguration:
117
+ """Helper type checking and type converting method for ArgumentParser.add_argument
118
+ to convert platform configuration string to PlatformConfigurations enum if value is valid.
119
+
120
+ Args:
121
+ platform_config_str: a platforms configuration value
122
+ Returns:
123
+ If the value is valid, convert the value to PlatformConfigurations enum.
124
+
125
+ Otherwise, raises argparse.ArgumentTypeError.
126
+ """
127
+
128
+ platform_config_str = platform_config_str.lower()
129
+ if platform_config_str not in SDK.PLATFORM_CONFIGS:
130
+ raise argparse.ArgumentTypeError(
131
+ f"{platform_config_str} is not a valid option for --platform-config."
132
+ )
133
+
134
+ return PlatformConfiguration(platform_config_str)
135
+
136
+
137
+ def valid_sdk_type(sdk_str: str) -> SdkType:
138
+ """Helper type checking and type converting method for ArgumentParser.add_argument
139
+ to convert sdk string to SdkType enum if value is valid.
140
+
141
+ Args:
142
+ sdk_str: sdk string
143
+ Returns:
144
+ If the value is valid, convert the value to SdkType enum.
145
+
146
+ Otherwise, raises argparse.ArgumentTypeError.
147
+ """
148
+
149
+ sdk_str = sdk_str.lower()
150
+ if sdk_str not in SDK.SDKS:
151
+ raise argparse.ArgumentTypeError(f"{sdk_str} is not a valid option for --sdk.")
152
+
153
+ return SdkType(sdk_str)
@@ -0,0 +1,149 @@
1
+ """
2
+ SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
+ SPDX-License-Identifier: Apache-2.0
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ """ # noqa: E501
17
+
18
+ import json
19
+ import logging
20
+ from typing import Any, Optional
21
+
22
+ import requests
23
+ from packaging.version import Version
24
+
25
+ from holoscan import __version__ as holoscan_version_string
26
+
27
+ from .enum_types import PlatformConfiguration, SdkType
28
+ from .exceptions import InvalidSourceFileError, ManifestDownloadError
29
+
30
+
31
+ class ArtifactSources:
32
+ """Provides default artifact source URLs with the ability to override."""
33
+
34
+ SectionWheelVersion = "wheel-version"
35
+ SectionDebianVersion = "debian-version"
36
+ SectionBaseImages = "base-images"
37
+ SectionBuildImages = "build-images"
38
+ SectionHealthProbe = "health-probes"
39
+ EdgeROToken = "eyJ2ZXIiOiIyIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYiLCJraWQiOiJLcXV1ZVdTTlRjSkhqTFhGLTJCSnctX0lkRnY0eVhqREJyNEdWMU5Gc2NJIn0.eyJzdWIiOiJqZnJ0QDAxZHRqNnF0ZWNmcnB6MXJrNmg2cjAwd2FkXC91c2Vyc1wvc3ZjLWhvbG9zY2FuLWNsaS1wdWJsaWMtcm8iLCJzY3AiOiJtZW1iZXItb2YtZ3JvdXBzOnN2Yy1ob2xvc2Nhbi1jbGktcHVibGljLWdyb3VwIiwiYXVkIjoiamZydEAwMWR0ajZxdGVjZnJwejFyazZoNnIwMHdhZCIsImlzcyI6ImpmcnRAMDFkdGo2cXRlY2ZycHoxcms2aDZyMDB3YWRcL3VzZXJzXC9ycGFsYW5pc3dhbXkiLCJpYXQiOjE3MDY1NzA1NjUsImp0aSI6IjlmNmEyMmM1LTk5ZTItNGRlMi1hMDhiLTQxZjg2NzIyYmJjNyJ9.Y0gfyW2F0kxiKnMhGzNCyRRE2DNrDW6CUj5ozrQiIvAbSbhohskFcFmP836PU4p3ZQTzbYk9-bBwrqoPDUaZf8p9AW9GZ3mvlU2BxK0EQ-F4oKxA1_Z7agZ0KKcmcrfWnE4Ffy53qAD8PTk5vdcznpYOBpJtF4i16j2QcXvhVGGEqUyGa7_sONdK0sevb3ZztiEoupi4gD2wPTRn30rjpGIiFSDKiswAQwoyF_SqMCQWOBEeXMISp8hkEggUpvPrESv2lbpjgaKuEJ1CikbivYTJCcoqpgH7E72FXr1sB9jfwrFD8pkjtRpGGDxN43waXy4f3Ctr8_rpbmCvwSa9iw" # noqa: E501
40
+ HoloscanVersion = None
41
+ ManifestFileUrl = None
42
+
43
+ def __init__(self) -> None:
44
+ ArtifactSources.HoloscanVersion = ".".join(
45
+ str(i) for i in Version(holoscan_version_string).release[0:3]
46
+ )
47
+ ArtifactSources.ManifestFileUrl = f"https://edge.urm.nvidia.com/artifactory/sw-holoscan-cli-generic/{ArtifactSources.HoloscanVersion}/artifacts.json"
48
+ self._logger = logging.getLogger("common")
49
+ self._supported_holoscan_versions = ["2.6.0"]
50
+
51
+ @property
52
+ def holoscan_versions(self) -> list[str]:
53
+ # logic to dynamically fetch the supported versions
54
+ return self._supported_holoscan_versions # for now, return the hardcoded value
55
+
56
+ def base_image(self, version) -> str:
57
+ return self._data[version][SdkType.Holoscan.value][ArtifactSources.SectionBaseImages]
58
+
59
+ def build_images(self, version) -> dict[Any, str]:
60
+ return self._data[version][SdkType.Holoscan.value][ArtifactSources.SectionBuildImages]
61
+
62
+ def health_probe(self, version) -> dict[Any, str]:
63
+ return self._data[version][ArtifactSources.SectionHealthProbe]
64
+
65
+ def load(self, uri: str):
66
+ """Overrides the default values from a given JSON file.
67
+ Validates top-level attributes to ensure the file is valid
68
+
69
+ Args:
70
+ file (Path): Path to JSON file
71
+ """
72
+ if uri.startswith("https"):
73
+ self._download_manifest_internal(uri)
74
+ elif uri.startswith("http"):
75
+ raise ManifestDownloadError(
76
+ "Downloading manifest files from non-HTTPS servers is not supported."
77
+ )
78
+ else:
79
+ self._logger.info(f"Using CLI manifest file from {uri}...")
80
+ with open(uri) as file:
81
+ temp = json.load(file)
82
+
83
+ try:
84
+ self.validate(temp)
85
+ self._data = temp
86
+ except Exception as ex:
87
+ raise InvalidSourceFileError(f"{uri} is missing required data: {ex}") from ex
88
+
89
+ def validate(self, data: Any):
90
+ self._logger.debug("Validating CLI manifest file...")
91
+
92
+ for key in data:
93
+ item = data[key]
94
+ assert SdkType.Holoscan.value in item
95
+ holoscan = item[SdkType.Holoscan.value]
96
+
97
+ assert ArtifactSources.SectionWheelVersion in holoscan
98
+ assert ArtifactSources.SectionDebianVersion in holoscan
99
+ assert ArtifactSources.SectionBaseImages in holoscan
100
+ assert ArtifactSources.SectionBuildImages in holoscan
101
+
102
+ for config in PlatformConfiguration:
103
+ assert config.value in holoscan[ArtifactSources.SectionBuildImages]
104
+
105
+ def download_manifest(self):
106
+ self._download_manifest_internal(
107
+ ArtifactSources.ManifestFileUrl,
108
+ {"Authorization": f"Bearer {ArtifactSources.EdgeROToken}"},
109
+ )
110
+
111
+ def _download_manifest_internal(self, url, headers=None):
112
+ self._logger.info("Downloading CLI manifest file...")
113
+ manifest = requests.get(url, headers=headers)
114
+
115
+ try:
116
+ manifest.raise_for_status()
117
+ except Exception as ex:
118
+ raise ManifestDownloadError(
119
+ f"Error downloading manifest file from {url}: {manifest.reason}"
120
+ ) from ex
121
+ else:
122
+ self._data = manifest.json()
123
+ self.validate(self._data)
124
+
125
+ def debian_package_version(self, version: str) -> Optional[str]:
126
+ """Gets the version of the Debian package based on the version of Holoscan.
127
+
128
+ Args:
129
+ version (str): version of Holoscan
130
+
131
+ Returns:
132
+ Optional[str]: Debian package version
133
+ """
134
+ return (
135
+ self._data[version][SdkType.Holoscan.value][ArtifactSources.SectionDebianVersion]
136
+ if version in self._data
137
+ else None
138
+ )
139
+
140
+ def wheel_package_version(self, version: str) -> Optional[str]:
141
+ """Gets the version of the PyPI package based on the version of Holoscan.
142
+
143
+ Args:
144
+ version (str): version of Holoscan
145
+
146
+ Returns:
147
+ Optional[str]: PyPI package version
148
+ """
149
+ return self._data[version][SdkType.Holoscan.value][ArtifactSources.SectionWheelVersion]