polyswarm-api 4.7.0__tar.gz → 4.8.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 (21) hide show
  1. {polyswarm_api-4.7.0/src/polyswarm_api.egg-info → polyswarm_api-4.8.0}/PKG-INFO +1 -1
  2. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/pyproject.toml +2 -2
  3. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/__init__.py +1 -1
  4. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/aio/api.py +50 -2
  5. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/api.py +48 -1
  6. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/resources.py +21 -0
  7. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0/src/polyswarm_api.egg-info}/PKG-INFO +1 -1
  8. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/LICENSE +0 -0
  9. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/README.md +0 -0
  10. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/setup.cfg +0 -0
  11. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/aio/__init__.py +0 -0
  12. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/aio/session.py +0 -0
  13. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/core.py +0 -0
  14. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/exceptions.py +0 -0
  15. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/refang.py +0 -0
  16. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/session.py +0 -0
  17. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api/settings.py +0 -0
  18. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api.egg-info/SOURCES.txt +0 -0
  19. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api.egg-info/dependency_links.txt +0 -0
  20. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api.egg-info/requires.txt +0 -0
  21. {polyswarm_api-4.7.0 → polyswarm_api-4.8.0}/src/polyswarm_api.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polyswarm_api
3
- Version: 4.7.0
3
+ Version: 4.8.0
4
4
  Summary: Client library to simplify interacting with the PolySwarm consumer API
5
5
  Author-email: PolySwarm Developers <info@polyswarm.io>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "polyswarm_api"
7
- version = "4.7.0"
7
+ version = "4.8.0"
8
8
  description = "Client library to simplify interacting with the PolySwarm consumer API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10,<4"
@@ -55,7 +55,7 @@ package-dir = { "" = "src" }
55
55
  where = ["src"]
56
56
 
57
57
  [tool.bumpversion]
58
- current_version = "4.7.0"
58
+ current_version = "4.8.0"
59
59
  commit = true
60
60
  tag = false
61
61
  sign_tags = true
@@ -1,5 +1,5 @@
1
1
  # https://www.python.org/dev/peps/pep-0008/#module-level-dunder-names
2
- __version__ = '4.7.0'
2
+ __version__ = '4.8.0'
3
3
  __release_url__ = 'https://api.github.com/repos/polyswarm/polyswarm-api/releases/latest'
4
4
 
5
5
  from . import api
@@ -288,6 +288,51 @@ class PolySwarmAsyncAPI:
288
288
  result_parser=resources.MetadataMapping,
289
289
  )
290
290
 
291
+ async def metadata_raw_search(self, body, community=None):
292
+ """Run a raw OpenSearch query body against the metadata corpus.
293
+
294
+ The server overlays the community filter itself and caps the work, so
295
+ ``body`` is a plain ``_search`` body and the community travels in the
296
+ query string rather than in it. The accepted grammar is closed: a
297
+ construct the server does not recognise is refused rather than passed
298
+ through, and so is a top-level ``community``/``communities`` key.
299
+
300
+ Entitlement-gated and metered per query, including a query the server
301
+ refuses after running it.
302
+
303
+ :param body: An OpenSearch ``_search`` body (``query``, ``aggs``,
304
+ ``size``, ``sort``, ``_source``, ...). Omitting ``size`` returns
305
+ **no documents**: the server defaults it to 0 so an aggregation
306
+ caller does not pay for hits they did not ask for. Ask for hits
307
+ by setting it.
308
+ :param community: Community to search; defaults to the client's.
309
+ :return: A ``MetadataRawSearch`` whose ``json`` carries the engine's
310
+ ``hits`` and ``aggregations``, plus ``partial`` when the server
311
+ could not establish that the answer is complete.
312
+
313
+ ``partial`` is a **list to inspect, not a flag**. Its entries are
314
+ ``{'code': ..., 'message': ...}`` and they make different claims,
315
+ so branch on ``code`` - ``message`` is for a human and may be
316
+ reworded. The codes are a closed set:
317
+
318
+ * ``timed_out`` / ``terminated_early`` - the search stopped early.
319
+ * ``shards_failed`` - a shard was lost; also carries ``failed``.
320
+ * ``buckets_clamped`` - a ``terms`` list dropped terms.
321
+ * ``composite_paged`` - a ``composite`` may have more pages; page
322
+ it with its ``after_key``.
323
+ * ``bucket_count_approximate`` - a ``terms`` count is approximate
324
+ rather than truncated.
325
+ * ``hit_total_capped`` - the hit counter stopped at
326
+ ``track_total_hits``. This is what *every* large query that asks
327
+ for hits returns, so on its own it says nothing about the
328
+ aggregations; the server omits it when the body asked for no
329
+ documents. ``hits.total.relation`` carries the same fact as the
330
+ engine's own field, ``eq`` exact and ``gte`` capped.
331
+ """
332
+ logger.info('Running a raw metadata search')
333
+ return await self._single(
334
+ resources.MetadataRawSearch.search(self, body, community))
335
+
291
336
  async def metadata_field_properties_write(self, field_path, description,
292
337
  example=None, category=None, aliases=None):
293
338
  """Upsert a metadata field properties entry (the single write path).
@@ -597,18 +642,21 @@ class PolySwarmAsyncAPI:
597
642
  """
598
643
  return await self._single(resources.LiveHuntResult.get(self, id=result_id))
599
644
 
600
- async def historical_create(self, rule=None, ruleset_name=None):
645
+ async def historical_create(self, rule=None, ruleset_name=None, window_days=None):
601
646
  """
602
647
  Run a new historical hunt.
603
648
 
604
649
  :param rule: YaraRuleset object or string containing YARA rules to install
605
650
  :param ruleset_name: Name of the ruleset.
651
+ :param window_days: Days back the hunt reaches: 30, 60, 90 or 180. Omit it for the
652
+ platform maximum. The server validates the value; the SDK does not.
606
653
  :return: The created Hunt resource
607
654
  """
608
655
  logger.info('Create historical hunt %s', rule)
609
656
  rule, rule_id = self._parse_rule(rule)
610
657
  return await self._single(resources.HistoricalHunt.create(self, yara=rule.yara if rule else None, rule_id=rule_id,
611
- ruleset_name=ruleset_name, community=self.community))
658
+ ruleset_name=ruleset_name, window_days=window_days,
659
+ community=self.community))
612
660
 
613
661
  async def historical_get(self, hunt=None):
614
662
  """
@@ -303,6 +303,50 @@ class PolyswarmAPI:
303
303
  result_parser=resources.MetadataMapping,
304
304
  )
305
305
 
306
+ def metadata_raw_search(self, body, community=None):
307
+ """Run a raw OpenSearch query body against the metadata corpus.
308
+
309
+ The server overlays the community filter itself and caps the work, so
310
+ ``body`` is a plain ``_search`` body and the community travels in the
311
+ query string rather than in it. The accepted grammar is closed: a
312
+ construct the server does not recognise is refused rather than passed
313
+ through, and so is a top-level ``community``/``communities`` key.
314
+
315
+ Entitlement-gated and metered per query, including a query the server
316
+ refuses after running it.
317
+
318
+ :param body: An OpenSearch ``_search`` body (``query``, ``aggs``,
319
+ ``size``, ``sort``, ``_source``, ...). Omitting ``size`` returns
320
+ **no documents**: the server defaults it to 0 so an aggregation
321
+ caller does not pay for hits they did not ask for. Ask for hits
322
+ by setting it.
323
+ :param community: Community to search; defaults to the client's.
324
+ :return: A ``MetadataRawSearch`` whose ``json`` carries the engine's
325
+ ``hits`` and ``aggregations``, plus ``partial`` when the server
326
+ could not establish that the answer is complete.
327
+
328
+ ``partial`` is a **list to inspect, not a flag**. Its entries are
329
+ ``{'code': ..., 'message': ...}`` and they make different claims,
330
+ so branch on ``code`` - ``message`` is for a human and may be
331
+ reworded. The codes are a closed set:
332
+
333
+ * ``timed_out`` / ``terminated_early`` - the search stopped early.
334
+ * ``shards_failed`` - a shard was lost; also carries ``failed``.
335
+ * ``buckets_clamped`` - a ``terms`` list dropped terms.
336
+ * ``composite_paged`` - a ``composite`` may have more pages; page
337
+ it with its ``after_key``.
338
+ * ``bucket_count_approximate`` - a ``terms`` count is approximate
339
+ rather than truncated.
340
+ * ``hit_total_capped`` - the hit counter stopped at
341
+ ``track_total_hits``. This is what *every* large query that asks
342
+ for hits returns, so on its own it says nothing about the
343
+ aggregations; the server omits it when the body asked for no
344
+ documents. ``hits.total.relation`` carries the same fact as the
345
+ engine's own field, ``eq`` exact and ``gte`` capped.
346
+ """
347
+ logger.info("Running a raw metadata search")
348
+ return self._single(resources.MetadataRawSearch.search(self, body, community))
349
+
306
350
  def metadata_field_properties_write(
307
351
  self, field_path, description, example=None, category=None, aliases=None
308
352
  ):
@@ -691,12 +735,14 @@ class PolyswarmAPI:
691
735
  """
692
736
  return self._single(resources.LiveHuntResult.get(self, id=result_id))
693
737
 
694
- def historical_create(self, rule=None, ruleset_name=None):
738
+ def historical_create(self, rule=None, ruleset_name=None, window_days=None):
695
739
  """
696
740
  Run a new historical hunt.
697
741
 
698
742
  :param rule: YaraRuleset object or string containing YARA rules to install
699
743
  :param ruleset_name: Name of the ruleset.
744
+ :param window_days: Days back the hunt reaches: 30, 60, 90 or 180. Omit it for the
745
+ platform maximum. The server validates the value; the SDK does not.
700
746
  :return: The created Hunt resource
701
747
  """
702
748
  logger.info("Create historical hunt %s", rule)
@@ -707,6 +753,7 @@ class PolyswarmAPI:
707
753
  yara=rule.yara if rule else None,
708
754
  rule_id=rule_id,
709
755
  ruleset_name=ruleset_name,
756
+ window_days=window_days,
710
757
  community=self.community,
711
758
  )
712
759
  )
@@ -77,6 +77,25 @@ class MetadataMapping(core.BaseJsonResource):
77
77
  RESOURCE_ENDPOINT = '/search/metadata/mappings'
78
78
 
79
79
 
80
+ class MetadataRawSearch(core.BaseJsonResource):
81
+ RESOURCE_ENDPOINT = '/search/metadata/raw'
82
+
83
+ @classmethod
84
+ def search(cls, api, body, community=None):
85
+ """``body`` is the caller's whole query and travels untouched. The
86
+ community is scope, not query, and the server reads it from the query
87
+ string - folding it into the body would pick scope with a key the
88
+ server's grammar then rejects."""
89
+ return core.PolyswarmRequest(
90
+ api=api,
91
+ method='POST',
92
+ url=f'{api.uri}{cls.RESOURCE_ENDPOINT}',
93
+ params={'community': community or api.community},
94
+ json=body,
95
+ result_parser=cls,
96
+ )
97
+
98
+
80
99
  class MetadataFieldProperties(core.BaseJsonResource):
81
100
  RESOURCE_ENDPOINT = '/search/metadata/properties'
82
101
  RESOURCE_ID_KEYS = ['field_path']
@@ -853,6 +872,8 @@ class HistoricalHunt(core.BaseJsonResource):
853
872
  # unknown (no source rule, or nothing to compare against) — not
854
873
  # "unchanged".
855
874
  self.source_rule_changed = content.get('source_rule_changed')
875
+ # None: no window requested (platform maximum), or a server predating the field.
876
+ self.window_days = content.get('window_days')
856
877
 
857
878
 
858
879
  class HistoricalHuntList(HistoricalHunt):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polyswarm_api
3
- Version: 4.7.0
3
+ Version: 4.8.0
4
4
  Summary: Client library to simplify interacting with the PolySwarm consumer API
5
5
  Author-email: PolySwarm Developers <info@polyswarm.io>
6
6
  License: MIT
File without changes
File without changes
File without changes