splunk-soar-sdk 3.6.0__py3-none-any.whl → 3.6.1__py3-none-any.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.
@@ -27,35 +27,51 @@ package = typer.Typer()
27
27
  console = Console() # For printing lots of pretty colors and stuff
28
28
 
29
29
 
30
- async def collect_all_wheels(wheels: set[DependencyWheel]) -> list[tuple[str, bytes]]:
31
- """Asynchronously collect all wheels from the given set of DependencyWheel objects."""
32
- # Create progress bar for tracking wheel collection
30
+ async def collect_all_wheels(wheels: list[DependencyWheel]) -> list[tuple[str, bytes]]:
31
+ """Asynchronously collect all wheels from the given list of DependencyWheel objects.
32
+
33
+ Downloads/builds each unique wheel once while updating every DependencyWheel instance
34
+ so the manifest records the final wheel filenames.
35
+ """
36
+ dedupe_map: dict[int, list[DependencyWheel]] = {}
37
+ for wheel in wheels:
38
+ key = hash(wheel)
39
+ dedupe_map.setdefault(key, []).append(wheel)
40
+
33
41
  progress = tqdm(
34
- total=len(wheels),
42
+ total=len(dedupe_map),
35
43
  desc="Downloading wheels",
36
44
  unit="wheel",
37
45
  colour="green",
38
46
  ncols=80,
39
47
  )
40
48
 
41
- async def collect_from_wheel(wheel: DependencyWheel) -> list[tuple[str, bytes]]:
42
- result = []
43
- # This actually is covered, but pytest-cov branch coverage
44
- # has a bug with the end of async for loops
49
+ async def collect_from_wheel(
50
+ cache_key: int, wheel: DependencyWheel
51
+ ) -> tuple[int, list[tuple[str, bytes]]]:
52
+ result: list[tuple[str, bytes]] = []
45
53
  async for path, data in wheel.collect_wheels(): # pragma: no cover
46
54
  result.append((path, data))
47
- # Update progress bar after each wheel is processed
48
55
  progress.update(1)
49
- return result
56
+ return cache_key, result
50
57
 
51
- # Use asyncio.gather to truly run all wheel collections concurrently
52
58
  with contextlib.closing(progress):
53
- wheel_data_lists = await asyncio.gather(
54
- *(collect_from_wheel(wheel) for wheel in wheels)
59
+ gathered_results = await asyncio.gather(
60
+ *(
61
+ collect_from_wheel(key, wheel_group[0])
62
+ for key, wheel_group in dedupe_map.items()
63
+ )
55
64
  )
56
65
 
57
- # Use itertools.chain to flatten the list of lists
58
- return list(chain.from_iterable(wheel_data_lists))
66
+ cache = dict(gathered_results)
67
+
68
+ for key, wheel_group in dedupe_map.items():
69
+ for path, _ in cache[key]:
70
+ wheel_name = Path(path).name
71
+ for wheel in wheel_group:
72
+ wheel._record_built_wheel(wheel_name)
73
+
74
+ return list(chain.from_iterable(cache.values()))
59
75
 
60
76
 
61
77
  @package.command()
@@ -124,13 +140,13 @@ def build(
124
140
 
125
141
  with tarfile.open(output_file, "w:gz") as app_tarball:
126
142
  # Collect all wheels from both Python versions
127
- all_wheels = set(
143
+ all_wheels = (
128
144
  app_meta.pip313_dependencies.wheel + app_meta.pip314_dependencies.wheel
129
145
  )
130
146
 
131
147
  # Run the async collection function within an event loop
132
148
  console.print(
133
- f"[yellow]Collecting [bold]{len(all_wheels)}[/bold] wheel{'' if len(all_wheels) == 1 else 's'} for package[/]"
149
+ f"[yellow]Collecting [bold]{len(all_wheels)}[/bold] wheel{'' if len(set(all_wheels)) == 1 else 's'} for package[/]"
134
150
  )
135
151
  wheel_data = asyncio.run(collect_all_wheels(all_wheels))
136
152
 
@@ -219,18 +219,41 @@ class DependencyWheel(BaseModel):
219
219
  sdist: UvSourceDistribution | None = Field(exclude=True, default=None)
220
220
  source_dir: UvSourceDirectory | None = Field(exclude=True, default=None)
221
221
 
222
+ def _set_wheel_paths(self, wheel_name: str) -> str:
223
+ """Assign the final wheel path (with any existing prefix) to both arches."""
224
+ base_path = Path(self.input_file or "wheels/shared")
225
+ # If there's already a filename component, replace it instead of nesting it
226
+ if base_path.suffix == ".whl":
227
+ base_path = base_path.parent
228
+ wheel_path = (base_path / wheel_name).as_posix()
229
+ self.input_file = wheel_path
230
+ self.input_file_aarch64 = wheel_path
231
+ return wheel_path
232
+
233
+ def set_placeholder_wheel_name(self, version: str) -> None:
234
+ """Populate a clearly placeholder wheel path when we expect to build from source."""
235
+ # Use only a filename here; platform-specific prefixes are added later.
236
+ self.input_file = "<to_be_built>.whl"
237
+ self.input_file_aarch64 = "<to_be_built>.whl"
238
+
239
+ def _record_built_wheel(self, wheel_name: str) -> str:
240
+ """Fill in missing wheel paths once a wheel has been built from source."""
241
+ return self._set_wheel_paths(wheel_name)
242
+
222
243
  async def collect_wheels(self) -> AsyncGenerator[tuple[str, bytes]]:
223
244
  """Collect a list of wheel files to fetch for this dependency across all platforms."""
224
245
  if self.wheel is None and self.sdist is not None:
225
246
  logger.info(f"Building sdist for {self.input_file}")
226
247
  wheel_name, wheel_bytes = await self.sdist.fetch_and_build()
227
- yield (f"wheels/shared/{wheel_name}", wheel_bytes)
248
+ wheel_path = self._record_built_wheel(wheel_name)
249
+ yield (wheel_path, wheel_bytes)
228
250
  return
229
251
 
230
252
  if self.wheel is None and self.source_dir is not None:
231
253
  logger.info(f"Building local sources for {self.input_file}")
232
254
  wheel_name, wheel_bytes = self.source_dir.build()
233
- yield (f"wheels/shared/{wheel_name}", wheel_bytes)
255
+ wheel_path = self._record_built_wheel(wheel_name)
256
+ yield (wheel_path, wheel_bytes)
234
257
  return
235
258
 
236
259
  if self.wheel is None:
@@ -398,12 +421,14 @@ class UvPackage(BaseModel):
398
421
  and UvLock.normalize_package_name(self.name) in DEPENDENCIES_TO_BUILD
399
422
  ):
400
423
  wheel.sdist = self.sdist
424
+ wheel.set_placeholder_wheel_name(self.version)
401
425
 
402
426
  if (
403
427
  self.source.directory is not None
404
428
  and UvLock.normalize_package_name(self.name) in DEPENDENCIES_TO_BUILD
405
429
  ):
406
430
  wheel.source_dir = UvSourceDirectory(directory=self.source.directory)
431
+ wheel.set_placeholder_wheel_name(self.version)
407
432
 
408
433
  try:
409
434
  wheel_x86_64 = self._find_wheel(
@@ -429,7 +454,7 @@ class UvPackage(BaseModel):
429
454
  wheel.input_file_aarch64 = f"{wheel_aarch64.basename}.whl"
430
455
  wheel.wheel_aarch64 = wheel_aarch64
431
456
  except FileNotFoundError:
432
- if wheel.sdist is None:
457
+ if wheel.sdist is None and wheel.source_dir is None:
433
458
  logger.warning(
434
459
  f"Could not find a suitable aarch64 wheel for {self.name=}, {self.version=}, {abi_precedence=}, {python_precedence=} -- the built package might not work on ARM systems"
435
460
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: splunk-soar-sdk
3
- Version: 3.6.0
3
+ Version: 3.6.1
4
4
  Summary: The official framework for developing and testing Splunk SOAR Apps
5
5
  Project-URL: Homepage, https://github.com/phantomcyber/splunk-soar-sdk
6
6
  Project-URL: Documentation, https://github.com/phantomcyber/splunk-soar-sdk
@@ -43,7 +43,7 @@ soar_sdk/cli/manifests/cli.py,sha256=cly5xVdj4bBIdZVMQPIWTXRgUfd1ON3qKO-76Fwql18
43
43
  soar_sdk/cli/manifests/deserializers.py,sha256=kwgPAMgUEXtIn4AuQOh1nkLfWFqe4qnYPZ1czB-FQTU,16516
44
44
  soar_sdk/cli/manifests/processors.py,sha256=soiRTbfLQuetstt1Xk7vKmWzOUhgVON5JxjWMvnGN7w,5141
45
45
  soar_sdk/cli/manifests/serializers.py,sha256=ulpq3nS8g1YrIP371XoQC3_kpz-9v2Ln_mqPyMtpWn8,3632
46
- soar_sdk/cli/package/cli.py,sha256=Vb6vdDszWLEOuBrAe4BLoxzdmr8luwA0_FbsvjjYhhM,9578
46
+ soar_sdk/cli/package/cli.py,sha256=_SlMNfqEyjAAWQy8AU4KhDpqxbV0jnjTQX1c3uULAtk,9945
47
47
  soar_sdk/cli/package/utils.py,sha256=fl6PMcrdC2zA7A16byQuxxPyAI2Z-BqBLfLlF2ZNnQ4,1712
48
48
  soar_sdk/cli/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  soar_sdk/cli/test/cli.py,sha256=iDrthN8L7B1RplLhq0EI69MndaOhvAXn7bqv3XzlfpM,7655
@@ -72,7 +72,7 @@ soar_sdk/meta/actions.py,sha256=qOXFChYxOVTt1d0gBffyw8ahJ3E4w7GsVoD4yzJN8Vc,2189
72
72
  soar_sdk/meta/adapters.py,sha256=KjSYIUtkCz2eesA_vhsNCjfi5C-Uz71tbSuDIjhuB8U,1112
73
73
  soar_sdk/meta/app.py,sha256=KbDiq1JgRiH4hudyKr95wMfcPN7YLyOkRjf4JIoFihs,2815
74
74
  soar_sdk/meta/datatypes.py,sha256=piR-oBVAATiRciXSdVE7XaqjUZTgSaOvTEqcOcNvCS0,795
75
- soar_sdk/meta/dependencies.py,sha256=1Jsdurc77zCMVSA_dePQfdNi2tpplnhuEnSnMs87Ibo,21949
75
+ soar_sdk/meta/dependencies.py,sha256=SXWOoUJRmyW9RE3CrgF2sQLQhfyPcXAg7KO0ONf3h_g,23244
76
76
  soar_sdk/meta/webhooks.py,sha256=ILKP9pNalKG9DLdNQNoDlu5KUnm0m7PyA2O0fbkqVrA,1217
77
77
  soar_sdk/models/__init__.py,sha256=YZVAcBguAlUsxAnBBL6jSguJEzf5PYCtdvbNyU1XfEU,380
78
78
  soar_sdk/models/artifact.py,sha256=G8hv9wPPoRgrAQzIf-YlCSjAlkHEcIPF389T1bo4yHw,1087
@@ -110,8 +110,8 @@ soar_sdk/views/components/pie_chart.py,sha256=LVTeHVJN6nf2vjUs9y7PDBhS0U1fKW750l
110
110
  soar_sdk/webhooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
111
  soar_sdk/webhooks/models.py,sha256=j3kbvYmcOlcj3gQYKtrv7iS-lDavMKYNLdCNMy_I2Hc,4542
112
112
  soar_sdk/webhooks/routing.py,sha256=OjezhuAb8wzW0MnbGSnIWeAH3uJcu-Sb7s3w9zoiPVM,6873
113
- splunk_soar_sdk-3.6.0.dist-info/METADATA,sha256=B68IqabYE-9dIw_KGpE_UETtUF-W0rmTWt-gjYbHM7M,7478
114
- splunk_soar_sdk-3.6.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
115
- splunk_soar_sdk-3.6.0.dist-info/entry_points.txt,sha256=CgBjo2ZWpYNkt9TgvToL26h2Tg1yt8FbvYTb5NVgNuc,51
116
- splunk_soar_sdk-3.6.0.dist-info/licenses/LICENSE,sha256=gNCGrGhrSQb1PUzBOByVUN1tvaliwLZfna-QU2r2hQ8,11345
117
- splunk_soar_sdk-3.6.0.dist-info/RECORD,,
113
+ splunk_soar_sdk-3.6.1.dist-info/METADATA,sha256=1Y4gKBFsYMfCL1vPPxCCLCDvz16iQ9EmjhdjY0prJg0,7478
114
+ splunk_soar_sdk-3.6.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
115
+ splunk_soar_sdk-3.6.1.dist-info/entry_points.txt,sha256=CgBjo2ZWpYNkt9TgvToL26h2Tg1yt8FbvYTb5NVgNuc,51
116
+ splunk_soar_sdk-3.6.1.dist-info/licenses/LICENSE,sha256=gNCGrGhrSQb1PUzBOByVUN1tvaliwLZfna-QU2r2hQ8,11345
117
+ splunk_soar_sdk-3.6.1.dist-info/RECORD,,