xsoar-cli 1.3.2__tar.gz → 1.3.4__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 (101) hide show
  1. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/CLAUDE.md +4 -4
  2. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/CONTRIBUTING.md +16 -0
  3. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/PKG-INFO +1 -1
  4. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/_version.py +2 -2
  5. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/pyproject.toml +0 -1
  6. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/cli.py +1 -2
  7. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/configuration.py +20 -8
  8. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/connection_errors.py +9 -1
  9. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/graph/commands.py +10 -2
  10. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/manifest/commands.py +8 -2
  11. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/rbac/commands.py +2 -6
  12. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_config.py +1 -1
  13. xsoar_cli-1.3.2/src/xsoar_cli/__about__.py +0 -4
  14. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/.github/workflows/main.yml +0 -0
  15. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/.github/workflows/pull-request-open.yml +0 -0
  16. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/.github/workflows/release.yml +0 -0
  17. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/.gitignore +0 -0
  18. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/LICENSE.txt +0 -0
  19. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/README.md +0 -0
  20. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/__init__.py +0 -0
  21. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/case/README.md +0 -0
  22. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/case/__init__.py +0 -0
  23. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/case/commands.py +0 -0
  24. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/config/README.md +0 -0
  25. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/config/__init__.py +0 -0
  26. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/config/commands.py +0 -0
  27. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/graph/README.md +0 -0
  28. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/graph/__init__.py +0 -0
  29. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/integration/__init__.py +0 -0
  30. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/integration/commands.py +0 -0
  31. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/log.py +0 -0
  32. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/manifest/README.md +0 -0
  33. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/manifest/__init__.py +0 -0
  34. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/pack/README.md +0 -0
  35. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/pack/__init__.py +0 -0
  36. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/pack/commands.py +0 -0
  37. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/playbook/README.md +0 -0
  38. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/playbook/__init__.py +0 -0
  39. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/playbook/commands.py +0 -0
  40. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/plugins/README.md +0 -0
  41. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/plugins/__init__.py +0 -0
  42. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/plugins/commands.py +0 -0
  43. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/plugins/manager.py +0 -0
  44. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/rbac/__init__.py +0 -0
  45. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/src/xsoar_cli/utilities.py +0 -0
  46. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/__init__.py +0 -0
  47. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/conftest.py +0 -0
  48. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_base.py +0 -0
  49. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_case.py +0 -0
  50. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_connection_errors.py +0 -0
  51. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Download/playbook-empty.yml +0 -0
  52. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/.pack-ignore +0 -0
  53. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/.secrets-ignore +0 -0
  54. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/Author_image.png +0 -0
  55. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/Playbooks/GenericPlaybook.yml +0 -0
  56. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/README.md +0 -0
  57. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/pack_metadata.json +0 -0
  58. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/.pack-ignore +0 -0
  59. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/.secrets-ignore +0 -0
  60. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/Author_image.png +0 -0
  61. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/README.md +0 -0
  62. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.py +0 -0
  63. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.yml +0 -0
  64. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/Scripts/GenericScript/README.md +0 -0
  65. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_CommonScripts/pack_metadata.json +0 -0
  66. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/.pack-ignore +0 -0
  67. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/.secrets-ignore +0 -0
  68. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Author_image.png +0 -0
  69. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Playbooks/EDR_InitialTriage.yml +0 -0
  70. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/README.md +0 -0
  71. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.py +0 -0
  72. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.yml +0 -0
  73. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/README.md +0 -0
  74. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.py +0 -0
  75. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.yml +0 -0
  76. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/README.md +0 -0
  77. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.py +0 -0
  78. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.yml +0 -0
  79. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/README.md +0 -0
  80. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/test_data/basescript-dummy.json +0 -0
  81. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_EDR/pack_metadata.json +0 -0
  82. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_Layouts/.pack-ignore +0 -0
  83. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_Layouts/.secrets-ignore +0 -0
  84. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_Layouts/Author_image.png +0 -0
  85. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_Layouts/Layouts/layoutscontainer-GenericLayout.json +0 -0
  86. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_Layouts/README.md +0 -0
  87. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/MyOrg_Layouts/pack_metadata.json +0 -0
  88. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/Packs/Not_applicable/Playbooks/Empty.yml +0 -0
  89. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/manifest_base.json +0 -0
  90. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/manifest_invalid.json +0 -0
  91. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/manifest_with_pack_not_on_server.json +0 -0
  92. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/server_base_response.json +0 -0
  93. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/server_base_response_missing_one_pack.json +0 -0
  94. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/server_base_response_with_updates.json +0 -0
  95. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_data/server_base_response_with_updates_and_one_extra.json +0 -0
  96. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_graph.py +0 -0
  97. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_manifest.py +0 -0
  98. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_pack.py +0 -0
  99. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_playbook.py +0 -0
  100. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/tests/test_plugins.py +0 -0
  101. {xsoar_cli-1.3.2 → xsoar_cli-1.3.4}/uv.lock +0 -0
@@ -35,7 +35,6 @@ for confirmation before executing any terminal commands as they may have consequ
35
35
 
36
36
  ```
37
37
  src/xsoar_cli/ # Main package (src layout)
38
- __about__.py # Version (dynamic, read by hatch)
39
38
  cli.py # Entry point, Click group, plugin loading
40
39
  configuration.py # XSOARConfig class
41
40
  connection_errors.py # Error handling
@@ -90,9 +89,10 @@ uv run xsoar-cli --help
90
89
  - The `@load_config` decorator (in `utilities.py`) handles config loading and injects `XSOARConfig` into `ctx.obj`
91
90
  - Use `click.echo()` for user-facing output, `logging` for debug/file logs
92
91
  - Commands that iterate over both `custom_packs` and `marketplace_packs` must use a `pack_type` variable (`"Custom"` / `"Marketplace"`) and include it in all log messages so the pack origin is always explicit in debug output
93
- - Logging setup in `cli.py` is intentionally deferred to `main()`. Command and plugin registration happen at module level, but `_configure_logging()` must not be moved there -- see inline comments in `cli.py` for details
92
+ - Logging setup in `cli.py` is intentionally deferred to `main()`. Command and plugin registration happen at module level, but `_configure_logging()` must not be moved there. See inline comments in `cli.py` for details
94
93
  - Ruff noqa comments are used where rules are intentionally suppressed (e.g., `# noqa: PLR0913` for many parameters, `# noqa: ANN201` for fixture return types)
95
94
  - Type hints are used throughout; `str | None` union syntax (Python 3.10+)
95
+ - Heavy third-party imports (`xsoar_client`, `xsoar_dependency_graph`, `demisto_client`, etc.) must be deferred into the function or method bodies that use them, not imported at module level. This avoids loading slow transitive dependencies (boto3, azure-storage-blob, matplotlib, networkx, etc.) at CLI startup, keeping `--help` and `--version` fast. Use `from __future__ import annotations` together with a `TYPE_CHECKING` block so type hints remain clean and unquoted. Mark each deferred import with the comment `# Lazy import for performance reasons`. When patching deferred imports in tests, patch at the source (`xsoar_client.xsoar_client.Client`) rather than the importing module (`xsoar_cli.configuration.Client`)
96
96
  - Tests must not produce side effects on the real filesystem, such as writing to the log file. Tests invoke `cli()` directly via Click's `CliRunner`, bypassing `main()` and its logging setup
97
97
  - Tests use `unittest.mock.patch` to mock external dependencies (`xsoar_client`, config file I/O)
98
98
  - Test classes follow `class TestX` naming; test methods use `test_` prefix
@@ -108,11 +108,11 @@ uv run xsoar-cli --help
108
108
 
109
109
  ## Workflow
110
110
 
111
- - Prefer plain, natural language in comments and documentation. Avoid formal or academic wording where a simpler alternative exists
111
+ - Write comments and documentation in plain, natural language. Avoid formal or academic wording where a simpler alternative exists. Do not use em dashes ("--" or "—") as parenthetical separators; use periods, commas, or parentheses instead. Avoid filler phrases like "It is worth noting that" or "It should be noted that". Keep sentences short and direct.
112
112
  - Never start with code. Always plan changes properly before implementation. Ask for clarification in case of inconsistencies or missing information. Do not make assumptions. Confirm with user before generating code.
113
113
  - In case of larger modifications, do implementation in logically grouped steps. Complex modifications may be broken down further.
114
114
  - After completing each step, stop and wait for the user to review and confirm before proceeding to the next step.
115
- - Each step should be small enough to be comfortably reviewed -- as a rule of thumb, no more than one or two files modified per step.
115
+ - Each step should be small enough to be comfortably reviewed. As a rule of thumb, no more than one or two files modified per step.
116
116
 
117
117
  ## Plugin System
118
118
 
@@ -113,6 +113,22 @@ pip install -e /path/to/your/xsoar-dependency-graph
113
113
  - Add type hints where appropriate
114
114
  - Write docstrings for new functions and classes
115
115
 
116
+ #### Lazy imports
117
+
118
+ Heavy third-party packages like `xsoar_client`, `xsoar_dependency_graph` and `demisto_client` pull in large dependency trees (boto3, azure-storage-blob, matplotlib, networkx, etc.) that are expensive to load. To keep everyday invocations like `--help` and `--version` fast, these imports are placed inside the functions that need them rather than at the top of the file. Each lazy import is marked with the comment `# Lazy import for performance reasons`.
119
+
120
+ Type hints for the deferred types still appear in function signatures. To avoid quoting them as strings, modules that use this pattern include `from __future__ import annotations` and a `TYPE_CHECKING` block at the top:
121
+
122
+ ```python
123
+ from __future__ import annotations
124
+ from typing import TYPE_CHECKING
125
+
126
+ if TYPE_CHECKING:
127
+ from xsoar_client.xsoar_client import Client
128
+ ```
129
+
130
+ See `configuration.py` for a complete example.
131
+
116
132
  ### Testing
117
133
  - Add tests for new features
118
134
  - Ensure existing tests still pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xsoar-cli
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Project-URL: Documentation, https://github.com/tlium/xsoar-cli#readme
5
5
  Project-URL: Issues, https://github.com/tlium/xsoar-cli/issues
6
6
  Project-URL: Source, https://github.com/tlium/xsoar-cli
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.3.2'
32
- __version_tuple__ = version_tuple = (1, 3, 2)
31
+ __version__ = version = '1.3.4'
32
+ __version_tuple__ = version_tuple = (1, 3, 4)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -49,7 +49,6 @@ check = "mypy --install-types --non-interactive {args:src/xsoar_cli tests}"
49
49
  source_pkgs = ["xsoar_cli", "tests"]
50
50
  branch = true
51
51
  parallel = true
52
- omit = ["src/xsoar_cli/__about__.py"]
53
52
 
54
53
  [project.scripts]
55
54
  xsoar-cli = "xsoar_cli.cli:main"
@@ -12,7 +12,6 @@ import sys
12
12
 
13
13
  import click
14
14
 
15
- from .__about__ import __version__
16
15
  from .case import commands as case_commands
17
16
  from .config import commands as config_commands
18
17
  from .graph import commands as graph_commands
@@ -47,7 +46,7 @@ class XSOARCliGroup(click.Group):
47
46
 
48
47
  @click.group(cls=XSOARCliGroup)
49
48
  @click.pass_context
50
- @click.version_option(__version__)
49
+ @click.version_option(package_name="xsoar-cli")
51
50
  @click.option("--debug", is_flag=True, help="Enable debug logging")
52
51
  def cli(ctx: click.Context, debug: bool) -> None:
53
52
  """XSOAR CLI - Command line interface for XSOAR operations."""
@@ -1,12 +1,14 @@
1
1
  """Configuration management for XSOAR CLI."""
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import logging
4
- from typing import Optional
6
+ from typing import TYPE_CHECKING
5
7
 
6
- from xsoar_client.artifact_providers.azure import AzureArtifactProvider
7
- from xsoar_client.artifact_providers.s3 import S3ArtifactProvider
8
- from xsoar_client.config import ClientConfig
9
- from xsoar_client.xsoar_client import Client
8
+ if TYPE_CHECKING:
9
+ from xsoar_client.artifact_providers.azure import AzureArtifactProvider
10
+ from xsoar_client.artifact_providers.s3 import S3ArtifactProvider
11
+ from xsoar_client.xsoar_client import Client
10
12
 
11
13
  logger = logging.getLogger(__name__)
12
14
 
@@ -18,7 +20,7 @@ class EnvironmentConfig:
18
20
  self.env_name = env_name
19
21
  self._config = config
20
22
  self.custom_pack_authors = custom_pack_authors
21
- self._client: Optional[Client] = None
23
+ self._client: Client | None = None
22
24
 
23
25
  @property
24
26
  def client(self) -> Client:
@@ -30,6 +32,10 @@ class EnvironmentConfig:
30
32
 
31
33
  def _create_client(self) -> Client:
32
34
  """Create the XSOAR client with artifact provider."""
35
+ # Lazy import for performance reasons
36
+ from xsoar_client.config import ClientConfig
37
+ from xsoar_client.xsoar_client import Client
38
+
33
39
  logger.debug(
34
40
  "Client config for '%s': server_version=%s, base_url=%s, verify_ssl=%s",
35
41
  self.env_name,
@@ -55,10 +61,16 @@ class EnvironmentConfig:
55
61
  artifacts_location = self._config.get("artifacts_location")
56
62
 
57
63
  if artifacts_location == "S3":
64
+ # Lazy import for performance reasons
65
+ from xsoar_client.artifact_providers.s3 import S3ArtifactProvider
66
+
58
67
  bucket_name = self._config.get("s3_bucket_name", "")
59
68
  logger.debug("Creating S3 artifact provider for '%s' (bucket: %s)", self.env_name, bucket_name)
60
69
  return S3ArtifactProvider(bucket_name=bucket_name)
61
70
  elif artifacts_location == "Azure":
71
+ # Lazy import for performance reasons
72
+ from xsoar_client.artifact_providers.azure import AzureArtifactProvider
73
+
62
74
  logger.debug("Creating Azure artifact provider for '%s'", self.env_name)
63
75
  return AzureArtifactProvider(
64
76
  storage_account_url=self._config["azure_blobstore_url"],
@@ -92,7 +104,7 @@ class XSOARConfig:
92
104
  list(self._environments.keys()),
93
105
  )
94
106
 
95
- def get_client(self, environment: Optional[str] = None) -> Client:
107
+ def get_client(self, environment: str | None = None) -> Client:
96
108
  """Get the XSOAR client for the specified environment (or default)."""
97
109
  env = environment or self.default_environment
98
110
  if env not in self._environments:
@@ -110,7 +122,7 @@ class XSOARConfig:
110
122
  """Get list of all configured environment names."""
111
123
  return list(self._environments.keys())
112
124
 
113
- def environment_has_artifacts(self, environment: Optional[str] = None) -> bool:
125
+ def environment_has_artifacts(self, environment: str | None = None) -> bool:
114
126
  """Check if an environment has artifact provider configured."""
115
127
  env = environment or self.default_environment
116
128
  return self._environments[env].has_artifact_provider
@@ -1,4 +1,9 @@
1
- from urllib3.exceptions import NameResolutionError
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from urllib3.exceptions import NameResolutionError
2
7
 
3
8
 
4
9
  class ConnectionErrorHandler:
@@ -9,6 +14,9 @@ class ConnectionErrorHandler:
9
14
  if exception is None:
10
15
  return "Unknown error"
11
16
 
17
+ # Lazy import for performance reasons
18
+ from urllib3.exceptions import NameResolutionError
19
+
12
20
  # Walk through the exception chain to find known error types and the root cause
13
21
  current = exception
14
22
  hostname = None
@@ -1,9 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  from pathlib import Path
5
+ from typing import TYPE_CHECKING
3
6
 
4
7
  import click
5
- from xsoar_client.xsoar_client import Client
6
- from xsoar_dependency_graph.xsoar_dependency_graph import ContentGraph
7
8
 
8
9
  from xsoar_cli.utilities import (
9
10
  get_xsoar_config,
@@ -11,6 +12,10 @@ from xsoar_cli.utilities import (
11
12
  validate_xsoar_connectivity,
12
13
  )
13
14
 
15
+ if TYPE_CHECKING:
16
+ from xsoar_client.xsoar_client import Client
17
+ from xsoar_dependency_graph.xsoar_dependency_graph import ContentGraph
18
+
14
19
  logger = logging.getLogger(__name__)
15
20
 
16
21
 
@@ -37,6 +42,9 @@ def _build_content_graph(
37
42
  environment: str | None,
38
43
  ) -> ContentGraph:
39
44
  """Shared setup: load config, connect to XSOAR, build and return a ContentGraph."""
45
+ # Lazy import for performance reasons
46
+ from xsoar_dependency_graph.xsoar_dependency_graph import ContentGraph
47
+
40
48
  config = get_xsoar_config(ctx)
41
49
  xsoar_client: Client = config.get_client(environment)
42
50
  logger.info("Generating dependency graph (environment: '%s', repo: '%s')", environment or config.default_environment, repo_path)
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import json
2
4
  import logging
3
5
  import sys
@@ -5,8 +7,6 @@ from pathlib import Path
5
7
  from typing import TYPE_CHECKING, Any
6
8
 
7
9
  import click
8
- from demisto_client.demisto_api.rest import ApiException
9
- from packaging.version import Version
10
10
 
11
11
  from xsoar_cli.utilities import (
12
12
  find_installed_packs_not_in_manifest,
@@ -91,6 +91,9 @@ def generate(ctx: click.Context, environment: str | None, manifest_path: str) ->
91
91
  @validate_xsoar_connectivity()
92
92
  def update(ctx: click.Context, environment: str | None, manifest: str) -> None:
93
93
  """Update manifest on disk with latest available content pack versions."""
94
+ # Lazy import for performance reasons
95
+ from packaging.version import Version
96
+
94
97
  config = get_xsoar_config(ctx)
95
98
  xsoar_client: Client = config.get_client(environment)
96
99
  logger.info("Updating manifest '%s' (environment: '%s')", manifest, environment or config.default_environment)
@@ -362,6 +365,9 @@ def deploy(ctx: click.Context, environment: str | None, manifest: str, verbose:
362
365
  \b
363
366
  Prompts for confirmation prior to pack installation.
364
367
  """
368
+ # Lazy import for performance reasons
369
+ from demisto_client.demisto_api.rest import ApiException
370
+
365
371
  # Initialize client and determine target environment
366
372
  config = get_xsoar_config(ctx)
367
373
  xsoar_client: Client = config.get_client(environment)
@@ -4,7 +4,6 @@ from typing import TYPE_CHECKING
4
4
 
5
5
  import click
6
6
 
7
- import xsoar_cli
8
7
  from xsoar_cli.utilities import get_xsoar_config, load_config, validate_xsoar_connectivity
9
8
 
10
9
  if TYPE_CHECKING:
@@ -46,9 +45,6 @@ def getusers(ctx: click.Context, environment: str | None) -> None:
46
45
  users = json.loads(results)
47
46
  click.echo(json.dumps(users, sort_keys=True, indent=4) + "\n")
48
47
 
49
- config = get_xsoar_config(ctx)
50
- xsoar_client: Client = config.get_client(environment)
51
-
52
48
 
53
49
  @click.option("--environment", default=None, help="Default environment set in config file.")
54
50
  @click.command()
@@ -56,11 +52,11 @@ def getusers(ctx: click.Context, environment: str | None) -> None:
56
52
  @load_config
57
53
  @validate_xsoar_connectivity()
58
54
  def getusergroups(ctx: click.Context, environment: str | None) -> None:
59
- """Dump all roles in your environment."""
55
+ """Dump all user groups in your environment. XSOAR 8+ only."""
60
56
  config = get_xsoar_config(ctx)
61
57
  xsoar_client: Client = config.get_client(environment)
62
58
  if xsoar_client.config.server_version < 8:
63
- click.echo("Errot: Command not supported for XSOAR server versions less than 8")
59
+ click.echo("Error: Command not supported for XSOAR server versions less than 8")
64
60
  ctx.exit(1)
65
61
  results = xsoar_client.get_user_groups()
66
62
  user_groups = json.loads(results)
@@ -7,7 +7,7 @@ from xsoar_cli import cli
7
7
 
8
8
 
9
9
  class TestConfig:
10
- @patch("xsoar_cli.configuration.Client")
10
+ @patch("xsoar_client.xsoar_client.Client")
11
11
  @patch("pathlib.Path.is_file", MagicMock(return_value=True))
12
12
  @pytest.mark.parametrize(
13
13
  ("cli_args", "use_fixtures", "expected_return_value"),
@@ -1,4 +0,0 @@
1
- # SPDX-FileCopyrightText: 2025-present Torbjørn Lium <torben@lium.org>
2
- #
3
- # SPDX-License-Identifier: MIT
4
- __version__ = "0.0.0"
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
File without changes