psengine 2.0.7__tar.gz → 2.1.1__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 (140) hide show
  1. {psengine-2.0.7 → psengine-2.1.1}/PKG-INFO +25 -18
  2. {psengine-2.0.7 → psengine-2.1.1}/psengine/_version.py +1 -1
  3. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/helpers.py +13 -22
  4. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/models.py +1 -1
  5. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/note.py +43 -46
  6. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/note_mgr.py +111 -154
  7. {psengine-2.0.7 → psengine-2.1.1}/psengine/base_http_client.py +48 -71
  8. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/classic_alert.py +99 -114
  9. psengine-2.1.1/psengine/classic_alerts/classic_alert_mgr.py +503 -0
  10. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/helpers.py +25 -28
  11. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/markdown/markdown.py +4 -4
  12. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/models.py +1 -1
  13. {psengine-2.0.7 → psengine-2.1.1}/psengine/collective_insights/collective_insights.py +35 -37
  14. {psengine-2.0.7 → psengine-2.1.1}/psengine/collective_insights/insight.py +20 -16
  15. {psengine-2.0.7 → psengine-2.1.1}/psengine/common_models.py +39 -23
  16. {psengine-2.0.7 → psengine-2.1.1}/psengine/config/config.py +84 -92
  17. {psengine-2.0.7 → psengine-2.1.1}/psengine/detection/detection_mgr.py +47 -47
  18. {psengine-2.0.7 → psengine-2.1.1}/psengine/detection/detection_rule.py +21 -20
  19. {psengine-2.0.7 → psengine-2.1.1}/psengine/detection/helpers.py +15 -10
  20. {psengine-2.0.7 → psengine-2.1.1}/psengine/endpoints.py +13 -0
  21. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/lookup.py +50 -56
  22. psengine-2.1.1/psengine/enrich/lookup_mgr.py +314 -0
  23. psengine-2.1.1/psengine/enrich/models/__init__.py +13 -0
  24. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/models/lookup.py +1 -4
  25. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/models/soar.py +45 -45
  26. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/soar.py +21 -19
  27. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/soar_mgr.py +50 -56
  28. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_lists/entity_list.py +119 -109
  29. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_lists/entity_list_mgr.py +37 -47
  30. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_lists/models.py +8 -8
  31. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_match/entity_match.py +24 -21
  32. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_match/entity_match_mgr.py +76 -93
  33. {psengine-2.0.7 → psengine-2.1.1}/psengine/helpers/__init__.py +1 -0
  34. {psengine-2.0.7 → psengine-2.1.1}/psengine/helpers/helpers.py +165 -140
  35. psengine-2.1.1/psengine/identity/__init__.py +31 -0
  36. psengine-2.1.1/psengine/identity/constants.py +15 -0
  37. psengine-2.1.1/psengine/identity/errors.py +34 -0
  38. psengine-2.1.1/psengine/identity/identity.py +392 -0
  39. psengine-2.1.1/psengine/identity/identity_mgr.py +836 -0
  40. psengine-2.1.1/psengine/identity/models/common_models.py +227 -0
  41. psengine-2.1.1/psengine/identity/models/detections.py +54 -0
  42. psengine-2.1.1/psengine/identity/models/incident_report.py +38 -0
  43. psengine-2.1.1/psengine/identity/models/lookup.py +55 -0
  44. {psengine-2.0.7 → psengine-2.1.1}/psengine/logger/rf_logger.py +20 -10
  45. {psengine-2.0.7 → psengine-2.1.1}/psengine/markdown/markdown.py +48 -16
  46. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/helpers.py +13 -15
  47. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/panel_log.py +7 -7
  48. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/pa_category.py +6 -7
  49. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/playbook_alert_mgr.py +192 -180
  50. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/playbook_alerts.py +121 -110
  51. psengine-2.1.1/psengine/py.typed +0 -0
  52. {psengine-2.0.7 → psengine-2.1.1}/psengine/rf_client.py +93 -124
  53. {psengine-2.0.7 → psengine-2.1.1}/psengine/risklists/models.py +14 -3
  54. {psengine-2.0.7 → psengine-2.1.1}/psengine/risklists/risklist_mgr.py +42 -48
  55. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/base_stix_entity.py +10 -13
  56. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/complex_entity.py +56 -76
  57. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/enriched_indicator.py +19 -32
  58. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/helpers.py +20 -16
  59. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/rf_bundle.py +25 -41
  60. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/simple_entity.py +17 -17
  61. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/util.py +8 -13
  62. {psengine-2.0.7 → psengine-2.1.1}/psengine.egg-info/PKG-INFO +25 -18
  63. {psengine-2.0.7 → psengine-2.1.1}/psengine.egg-info/SOURCES.txt +11 -0
  64. psengine-2.1.1/psengine.egg-info/requires.txt +28 -0
  65. {psengine-2.0.7 → psengine-2.1.1}/pyproject.toml +32 -32
  66. psengine-2.0.7/psengine/classic_alerts/classic_alert_mgr.py +0 -504
  67. psengine-2.0.7/psengine/enrich/lookup_mgr.py +0 -341
  68. psengine-2.0.7/psengine.egg-info/requires.txt +0 -30
  69. {psengine-2.0.7 → psengine-2.1.1}/LICENSE +0 -0
  70. {psengine-2.0.7 → psengine-2.1.1}/README.rst +0 -0
  71. {psengine-2.0.7 → psengine-2.1.1}/psengine/__init__.py +0 -0
  72. {psengine-2.0.7 → psengine-2.1.1}/psengine/_sdk_id.py +0 -0
  73. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/__init__.py +0 -0
  74. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/constants.py +0 -0
  75. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/errors.py +0 -0
  76. {psengine-2.0.7 → psengine-2.1.1}/psengine/analyst_notes/markdown.py +0 -0
  77. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/__init__.py +0 -0
  78. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/constants.py +0 -0
  79. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/errors.py +0 -0
  80. {psengine-2.0.7 → psengine-2.1.1}/psengine/classic_alerts/markdown/__init__.py +0 -0
  81. {psengine-2.0.7 → psengine-2.1.1}/psengine/collective_insights/__init__.py +0 -0
  82. {psengine-2.0.7 → psengine-2.1.1}/psengine/collective_insights/constants.py +0 -0
  83. {psengine-2.0.7 → psengine-2.1.1}/psengine/collective_insights/errors.py +0 -0
  84. {psengine-2.0.7 → psengine-2.1.1}/psengine/collective_insights/models.py +0 -0
  85. {psengine-2.0.7 → psengine-2.1.1}/psengine/config/__init__.py +0 -0
  86. {psengine-2.0.7 → psengine-2.1.1}/psengine/config/errors.py +0 -0
  87. {psengine-2.0.7 → psengine-2.1.1}/psengine/constants.py +0 -0
  88. {psengine-2.0.7 → psengine-2.1.1}/psengine/detection/__init__.py +0 -0
  89. {psengine-2.0.7 → psengine-2.1.1}/psengine/detection/errors.py +0 -0
  90. {psengine-2.0.7 → psengine-2.1.1}/psengine/detection/models.py +0 -0
  91. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/__init__.py +0 -0
  92. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/constants.py +0 -0
  93. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/errors.py +0 -0
  94. {psengine-2.0.7 → psengine-2.1.1}/psengine/enrich/models/base_enriched_entity.py +0 -0
  95. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_lists/__init__.py +0 -0
  96. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_lists/constants.py +0 -0
  97. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_lists/errors.py +0 -0
  98. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_match/__init__.py +0 -0
  99. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_match/errors.py +0 -0
  100. {psengine-2.0.7 → psengine-2.1.1}/psengine/entity_match/models.py +0 -0
  101. {psengine-2.0.7 → psengine-2.1.1}/psengine/errors.py +0 -0
  102. {psengine-2.0.7/psengine/enrich → psengine-2.1.1/psengine/identity}/models/__init__.py +0 -0
  103. {psengine-2.0.7 → psengine-2.1.1}/psengine/logger/__init__.py +0 -0
  104. {psengine-2.0.7 → psengine-2.1.1}/psengine/logger/constants.py +0 -0
  105. {psengine-2.0.7 → psengine-2.1.1}/psengine/logger/errors.py +0 -0
  106. {psengine-2.0.7 → psengine-2.1.1}/psengine/markdown/__init__.py +0 -0
  107. {psengine-2.0.7 → psengine-2.1.1}/psengine/markdown/models.py +0 -0
  108. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/__init__.py +0 -0
  109. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/constants.py +0 -0
  110. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/errors.py +0 -0
  111. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/mappings.py +0 -0
  112. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/__init__.py +0 -0
  113. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown.py +0 -0
  114. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown_code_repo.py +0 -0
  115. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown_cyber_vulnerability.py +0 -0
  116. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown_domain_abuse.py +0 -0
  117. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown_geopolitics_facility.py +0 -0
  118. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown_identity_exposure.py +0 -0
  119. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown_malware_report.py +0 -0
  120. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/markdown/markdown_third_party_risk.py +0 -0
  121. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/__init__.py +0 -0
  122. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/common_models.py +0 -0
  123. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/panel_status.py +0 -0
  124. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/pba_code_repo_leak.py +0 -0
  125. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/pba_cyber_vulnerability.py +0 -0
  126. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/pba_domain_abuse.py +0 -0
  127. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/pba_geopolitics_facility.py +0 -0
  128. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/pba_identity_exposures.py +0 -0
  129. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/pba_malware_report.py +0 -0
  130. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/pba_third_party_risk.py +0 -0
  131. {psengine-2.0.7 → psengine-2.1.1}/psengine/playbook_alerts/models/search_endpoint.py +0 -0
  132. {psengine-2.0.7 → psengine-2.1.1}/psengine/risklists/__init__.py +0 -0
  133. {psengine-2.0.7 → psengine-2.1.1}/psengine/risklists/constants.py +0 -0
  134. {psengine-2.0.7 → psengine-2.1.1}/psengine/risklists/errors.py +0 -0
  135. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/__init__.py +0 -0
  136. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/constants.py +0 -0
  137. {psengine-2.0.7 → psengine-2.1.1}/psengine/stix2/errors.py +0 -0
  138. {psengine-2.0.7 → psengine-2.1.1}/psengine.egg-info/dependency_links.txt +0 -0
  139. {psengine-2.0.7 → psengine-2.1.1}/psengine.egg-info/top_level.txt +0 -0
  140. {psengine-2.0.7 → psengine-2.1.1}/setup.cfg +0 -0
@@ -1,12 +1,22 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: psengine
3
- Version: 2.0.7
3
+ Version: 2.1.1
4
4
  Summary: psengine is a simple, yet elegant, library for rapid development of integrations with Recorded Future.
5
5
  Author-email: Moise Medici <moise.medici@recordedfuture.com>, Patrick Kinsella <patrick.kinsella@recordedfuture.com>, Ernest Bartosevic <ernest.bartosevic@recordedfuture.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/RecordedFuture-ProfessionalServices/psengine
8
- Project-URL: Changelog, https://github.com/RecordedFuture-ProfessionalServices/psengine/blob/main/CHANGELOG.rst
8
+ Project-URL: Changelog, https://recordedfuture-professionalservices.github.io/psengine/CHANGELOG/
9
9
  Keywords: API,Recorded Future,Cyber Security Engineering,Threat Intelligence
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Security
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
10
20
  Requires-Python: <3.14,>=3.9
11
21
  Description-Content-Type: text/x-rst
12
22
  License-File: LICENSE
@@ -16,29 +26,26 @@ Requires-Dist: stix2~=3.0.1
16
26
  Requires-Dist: python-dateutil>=2.7.0
17
27
  Requires-Dist: more-itertools<=10.2.0,>=9.0.0
18
28
  Requires-Dist: pydantic<3.0.0,>=2.7
19
- Requires-Dist: pydantic-settings[toml]~=2.5.2
29
+ Requires-Dist: pydantic-settings[toml]<2.11.0,>=2.5.2
20
30
  Requires-Dist: markdown-strings==3.4.0
21
31
  Provides-Extra: dev
22
- Requires-Dist: tox==4.12.1; extra == "dev"
23
- Requires-Dist: build==1.0.3; extra == "dev"
24
32
  Requires-Dist: pytest==8.3.4; extra == "dev"
25
33
  Requires-Dist: pytest-cov==6.0.0; extra == "dev"
26
34
  Requires-Dist: pytest-mock==3.14.0; extra == "dev"
35
+ Requires-Dist: pytest-md==0.2.0; extra == "dev"
27
36
  Requires-Dist: pytest-random-order==1.1.1; extra == "dev"
28
- Requires-Dist: pytest-vcr==1.0.2; extra == "dev"
29
- Requires-Dist: pytest-watch==4.2.0; extra == "dev"
30
- Requires-Dist: requests==2.29.0; extra == "dev"
37
+ Requires-Dist: pytest-httpdbg==0.9.0; extra == "dev"
31
38
  Requires-Dist: ruff~=0.11.0; extra == "dev"
32
- Requires-Dist: wheel==0.37.1; extra == "dev"
33
- Requires-Dist: setuptools==61.0.0; extra == "dev"
34
- Requires-Dist: Sphinx==7.1.2; extra == "dev"
35
- Requires-Dist: sphinxcontrib-confluencebuilder==2.3.0; extra == "dev"
36
- Requires-Dist: atlassian-python-api==3.41.4; extra == "dev"
37
- Requires-Dist: sphinx_autodoc_typehints==1.25.2; extra == "dev"
38
- Requires-Dist: sphinxcontrib-napoleon; extra == "dev"
39
- Requires-Dist: typer==0.12.5; extra == "dev"
40
- Requires-Dist: cookiecutter==2.6.0; extra == "dev"
41
- Requires-Dist: tomlkit>=0.13.2; extra == "dev"
39
+ Requires-Dist: mimesis>=12.1.0; extra == "dev"
40
+ Requires-Dist: build==1.3.0; extra == "dev"
41
+ Requires-Dist: wheel==0.45.1; extra == "dev"
42
+ Requires-Dist: setuptools==80.9.0; extra == "dev"
43
+ Provides-Extra: docs
44
+ Requires-Dist: ruff~=0.11.0; extra == "docs"
45
+ Requires-Dist: mkdocs; extra == "docs"
46
+ Requires-Dist: mkdocs-material; extra == "docs"
47
+ Requires-Dist: mkdocstrings[python]; extra == "docs"
48
+ Requires-Dist: griffe-typingdoc; extra == "docs"
42
49
  Dynamic: license-file
43
50
 
44
51
  ==================================================
@@ -11,4 +11,4 @@
11
11
  # accessed from any third party API. #
12
12
  ##############################################################################################
13
13
 
14
- __version__ = '2.0.7'
14
+ __version__ = '2.1.1'
@@ -14,9 +14,10 @@
14
14
  import json
15
15
  import logging
16
16
  from pathlib import Path
17
- from typing import Union
17
+ from typing import Annotated, Union
18
18
 
19
19
  from pydantic import validate_call
20
+ from typing_extensions import Doc
20
21
 
21
22
  from ..errors import WriteFileError
22
23
  from ..helpers import OSHelpers, debug_call
@@ -28,16 +29,14 @@ LOG = logging.getLogger('psengine.analyst_notes.helpers')
28
29
  @debug_call
29
30
  @validate_call
30
31
  def save_attachment(
31
- note_id: str, data: Union[bytes, str], ext: str, output_directory: Union[str, Path]
32
+ note_id: Annotated[str, Doc('The ID of the AnalystNote.')],
33
+ data: Annotated[Union[bytes, str], Doc('The data returned from `fetch_attachment`.')],
34
+ ext: Annotated[str, Doc('The extension of the attachment, returned by `fetch_attachment`.')],
35
+ output_directory: Annotated[Union[str, Path], Doc('The directory to save the file into.')],
32
36
  ) -> None:
33
- """Save yara, sigma, snort or pdf to file. The file will use the extension provided and the
34
- ``note_id`` to create the filename.
37
+ """Save a YARA, Sigma, Snort, or PDF attachment to a file.
35
38
 
36
- Args:
37
- note_id (str): ``AnalystNote`` id
38
- data (Union[bytes, str]): data, returned from ``fetch_attachment``
39
- ext (str): extension of the attachment, returned by ``fetch_attachment``
40
- output_directory (str, Path): the directory to save the file into
39
+ The file will use the provided extension and the `note_id` to create the filename.
41
40
  """
42
41
  output_directory = (
43
42
  output_directory if isinstance(output_directory, str) else output_directory.as_posix()
@@ -47,13 +46,11 @@ def save_attachment(
47
46
 
48
47
  @debug_call
49
48
  @validate_call
50
- def save_note(note: AnalystNote, output_directory: Union[str, Path]) -> None:
51
- """Save AnalystNote object on file. The file will have the name of the note id.
52
-
53
- Args:
54
- note (AnalystNote): note to save.
55
- output_directory (str, Path): the directory to save the file into
56
- """
49
+ def save_note(
50
+ note: Annotated[AnalystNote, Doc('The note to save.')],
51
+ output_directory: Annotated[Union[str, Path], Doc('The directory to save the file into.')],
52
+ ) -> None:
53
+ """Save an `AnalystNote` object to a file named with the note ID."""
57
54
  output_directory = (
58
55
  output_directory if isinstance(output_directory, str) else output_directory.as_posix()
59
56
  )
@@ -70,12 +67,6 @@ def _save_attachment(
70
67
  ) -> None:
71
68
  """Save attachment from bytes or note itself from json.
72
69
 
73
- Args:
74
- note_id (str): id of the note, will be the filename
75
- data (bytes | str): content to save
76
- ext (str): extension of the file.
77
- output_directory (str): the directory to save the file into
78
-
79
70
  Raises:
80
71
  WriteFileError: if saving to file fails
81
72
  """
@@ -189,7 +189,7 @@ class Attributes(RFBaseModel):
189
189
  @field_validator('events', mode='after')
190
190
  @classmethod
191
191
  def remove_empty_events(cls, values):
192
- """Remove empty events when ``NoteEvent`` skip the validation."""
192
+ """Remove empty events when `NoteEvent` skip the validation."""
193
193
  return [v for v in values if v.type_ and v.attributes]
194
194
 
195
195
 
@@ -12,9 +12,10 @@
12
12
  ##############################################################################################
13
13
 
14
14
  from functools import total_ordering
15
- from typing import Optional, Union
15
+ from typing import Annotated, Optional, Union
16
16
 
17
17
  from pydantic import Field
18
+ from typing_extensions import Doc
18
19
 
19
20
  from ..common_models import IdNameTypeDescription, RFBaseModel
20
21
  from ..constants import TIMESTAMP_STR
@@ -26,32 +27,34 @@ from .models import Attributes, PreviewAttributesIn, PreviewAttributesOut, Reque
26
27
  # AnalystNote also used by BaseEnrichedEntity
27
28
  @total_ordering
28
29
  class AnalystNote(RFBaseModel):
29
- """Validate data received from ``/search``, ``/analystnote/{note}`` endpoints.
30
+ """Validate data received from the `/search` and `/analystnote/{note}` endpoints.
30
31
 
31
- Methods:
32
- __hash__:
33
- Returns a hash value based on note ``id_``.
32
+ This class supports hashing, equality comparison, string representation, and total ordering
33
+ of `AnalystNote` instances.
34
34
 
35
- __eq__:
36
- Checks equality between two AnalystNote instances based on ``id_`` and published time.
35
+ Hashing:
36
+ Returns a hash value based on the note `id_`.
37
37
 
38
- __gt__:
39
- Defines a greater-than comparison between two AnalystNote instances based published time
40
- and the ``id_``
38
+ Equality:
39
+ Checks equality between two `AnalystNote` instances based on the `id_` and published time.
41
40
 
42
- __str__:
43
- Returns a string representation of the AnalystNote instance with:
44
- ``id_``, ``title``, and published timestamp.
41
+ Greater-than Comparison:
42
+ Defines a greater-than comparison between two `AnalystNote` instances based on the published
43
+ time and the `id_`.
45
44
 
46
- .. code-block:: python
45
+ String Representation:
46
+ Returns a string representation of the `AnalystNote` instance including the `id_`, `title`,
47
+ and published timestamp.
47
48
 
48
- >>> print(analyst_note)
49
- Analyst Note ID: 12345, Title: Cyber Vuln, Published: 2024-05-21 10:42:30AM
49
+ ```python
50
+ >>> print(analyst_note)
51
+ Analyst Note ID: 12345, Title: Cyber Vuln, Published: 2024-05-21 10:42:30AM
52
+ ```
50
53
 
51
- Total Ordering:
52
- The ordering of AnalystNote instances is determined primarily by the published timestamp in
53
- the attributes. If two instances have the same published timestamp, the note id is used as
54
- a secondary criterion for ordering.
54
+ Ordering:
55
+ The ordering of `AnalystNote` instances is determined primarily by the published timestamp.
56
+ If two instances have the same published timestamp, the note `id_` is used as a secondary
57
+ criterion.
55
58
  """
56
59
 
57
60
  external_id: Optional[str] = None
@@ -77,7 +80,7 @@ class AnalystNote(RFBaseModel):
77
80
  @property
78
81
  def detection_rule_type(self) -> Optional[str]:
79
82
  """Returns the attachment type if present, else None. It checks for specific types like
80
- 'sigma rule', 'yara rule', and 'snort rule' in the topics of the note.
83
+ `sigma rule`, `yara rule`, and `snort rule` in the topics of the note.
81
84
  """
82
85
  topics_type = ('sigma rule', 'yara rule', 'snort rule')
83
86
 
@@ -101,26 +104,20 @@ class AnalystNote(RFBaseModel):
101
104
 
102
105
  def markdown(
103
106
  self,
104
- extract_entities: bool = True,
105
- diamond_model: bool = True,
106
- html_tags: bool = False,
107
- defang_malicious_infrastructure: bool = False,
108
- character_limit: int = None,
109
- ) -> str:
110
- """Return the markdown representation of the Note.
111
-
112
- Args:
113
- extract_entities (bool): Extract and include entities in the markdown. Defaults to True.
114
- diamond_model (bool): Include a diamond model visualization. Defaults to True.
115
- html_tags (bool): Include HTML tags in the output. Defaults to False.
116
- defang_malicious_infrastructure (bool): Defang URLs or other malicious indicators.
117
- Defaults to False.
118
- character_limit (int, optional): Limit the output to a specified number of characters.
119
- Defaults to None.
120
-
121
- Returns:
122
- str: The generated markdown string.
123
- """
107
+ extract_entities: Annotated[
108
+ bool, Doc('Extract and include entities in the markdown.')
109
+ ] = True,
110
+ diamond_model: Annotated[bool, Doc('Include a diamond model visualization.')] = True,
111
+ html_tags: Annotated[bool, Doc('Include HTML tags in the output.')] = False,
112
+ defang_malicious_infrastructure: Annotated[
113
+ bool, Doc('Defang URLs or other malicious indicators.')
114
+ ] = False,
115
+ character_limit: Annotated[
116
+ Optional[int],
117
+ Doc('Limit the output to a specified number of characters.'),
118
+ ] = None,
119
+ ) -> Annotated[str, Doc('The generated markdown string.')]:
120
+ """Return the markdown representation of the note."""
124
121
  return _markdown(
125
122
  self,
126
123
  extract_entities=extract_entities,
@@ -132,7 +129,7 @@ class AnalystNote(RFBaseModel):
132
129
 
133
130
 
134
131
  class AnalystNotePreviewIn(RFBaseModel):
135
- """Validate data sent to ``/preview`` endpoint."""
132
+ """Validate data sent to `/preview` endpoint."""
136
133
 
137
134
  attributes: PreviewAttributesIn
138
135
  source: Optional[str]
@@ -141,14 +138,14 @@ class AnalystNotePreviewIn(RFBaseModel):
141
138
 
142
139
 
143
140
  class AnalystNotePreviewOut(RFBaseModel):
144
- """Validate data received from ``/preview`` endpoint."""
141
+ """Validate data received from `/preview` endpoint."""
145
142
 
146
143
  attributes: PreviewAttributesOut
147
144
  source: IdNameTypeDescription
148
145
 
149
146
 
150
147
  class AnalystNotePublishIn(AnalystNotePreviewIn):
151
- """Validate data sent to ``/publish`` endpoint."""
148
+ """Validate data sent to `/publish` endpoint."""
152
149
 
153
150
  attributes: PreviewAttributesIn
154
151
  source: Optional[str] = None
@@ -160,13 +157,13 @@ class AnalystNotePublishIn(AnalystNotePreviewIn):
160
157
 
161
158
 
162
159
  class AnalystNotePublishOut(RFBaseModel):
163
- """Validate data received from ``/publish`` endpoint."""
160
+ """Validate data received from `/publish` endpoint."""
164
161
 
165
162
  note_id: str
166
163
 
167
164
 
168
165
  class AnalystNoteSearchIn(RFBaseModel):
169
- """Validate data sent to ``/search`` endpoint."""
166
+ """Validate data sent to `/search` endpoint."""
170
167
 
171
168
  published: Optional[str] = None
172
169
  entity: Optional[str] = None