lib-shopware6-api-base 6.0.0__tar.gz → 6.0.2__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 (58) hide show
  1. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.github/workflows/cicd_docker.yml +2 -2
  2. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/CHANGELOG.md +19 -0
  3. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/PKG-INFO +4 -4
  4. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/pyproject.toml +4 -4
  5. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/__init__conf__.py +1 -1
  6. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_api_base_cli.py +21 -12
  7. lib_shopware6_api_base-6.0.2/src/lib_shopware6_api_base/typed_click.py +34 -0
  8. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_cli.py +55 -0
  9. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.devcontainer/devcontainer.json +0 -0
  10. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.devcontainer/settings.json +0 -0
  11. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.github/actions/extract-metadata/action.yml +0 -0
  12. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.github/dependabot.yml +0 -0
  13. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.github/workflows/codeql-analysis.yml +0 -0
  14. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.github/workflows/default_release_public.yml +0 -0
  15. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/.gitignore +0 -0
  16. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/CODE_OF_CONDUCT.md +0 -0
  17. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/CONTRIBUTING.md +0 -0
  18. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/INSTALL.md +0 -0
  19. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/ISSUE_TEMPLATE.md +0 -0
  20. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/LICENSE +0 -0
  21. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/Makefile +0 -0
  22. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/PULL_REQUEST_TEMPLATE.md +0 -0
  23. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/README.md +0 -0
  24. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/example.env +0 -0
  25. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/notebooks/Quickstart.ipynb +0 -0
  26. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/.gitignore +0 -0
  27. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/__init__.py +0 -0
  28. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/__main__.py +0 -0
  29. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/_compat.py +0 -0
  30. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/_http_common.py +0 -0
  31. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/conf_shopware6_api_base_classes.py +0 -0
  32. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/config.py +0 -0
  33. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/defaultconfig.d/10-logging.toml +0 -0
  34. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/defaultconfig.d/20-shopware.toml +0 -0
  35. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/defaultconfig.toml +0 -0
  36. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/exit_codes.py +0 -0
  37. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_admin_client.py +0 -0
  38. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_api_base.py +0 -0
  39. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_api_base_criteria.py +0 -0
  40. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_api_base_criteria_aggregation.py +0 -0
  41. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_api_base_criteria_filter.py +0 -0
  42. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_api_base_criteria_sorting.py +0 -0
  43. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_api_base_helpers.py +0 -0
  44. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/lib_shopware6_storefront_client.py +0 -0
  45. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/logging_setup.py +0 -0
  46. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/src/lib_shopware6_api_base/py.typed +0 -0
  47. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/conf_test_docker.py +0 -0
  48. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/conftest.py +0 -0
  49. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_api_base.py +0 -0
  50. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_conf_classes.py +0 -0
  51. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_config.py +0 -0
  52. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_criteria.py +0 -0
  53. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_criteria_aggregation.py +0 -0
  54. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_criteria_filter.py +0 -0
  55. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_criteria_sorting.py +0 -0
  56. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_doctests.py +0 -0
  57. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_helpers.py +0 -0
  58. {lib_shopware6_api_base-6.0.0 → lib_shopware6_api_base-6.0.2}/tests/test_logging_config.py +0 -0
@@ -107,7 +107,7 @@ jobs:
107
107
  && steps.pytest.outcome == 'success'
108
108
  && matrix.os == 'ubuntu-latest'
109
109
  && matrix.python == '3.13'
110
- uses: codecov/codecov-action@v6
110
+ uses: codecov/codecov-action@v7
111
111
  with:
112
112
  files: ${{ env.COV_REPORT_FILE }}
113
113
  fail_ci_if_error: false
@@ -366,7 +366,7 @@ jobs:
366
366
 
367
367
  - name: Upload integration coverage to Codecov
368
368
  if: always()
369
- uses: codecov/codecov-action@v6
369
+ uses: codecov/codecov-action@v7
370
370
  with:
371
371
  files: coverage-integration.xml
372
372
  flags: integration
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [6.0.2] 2026-06-14
11
+
12
+ ### Changed
13
+ - Added a `typed_click.py` facade wrapping rich-click's `option` / `version_option` / `argument` decorators behind explicit, fully-known signatures, keeping the CLI strict-clean under pyright 1.1.410 (`reportUnknownMemberType`) without disabling the rule (ignore isolated to the facade).
14
+ - Bumped internal dependency floors: `lib_cli_exit_tools>=2.3.2`, `lib_log_rich>=6.3.5`, `lib_layered_config>=5.5.2`.
15
+
16
+ ## [6.0.1] - 2026-06-08
17
+
18
+ ### Fixed
19
+
20
+ - **CLI no longer swallows error messages.** `run_cli` was given a custom
21
+ `exception_handler` that returned an exit code but never printed, so every failure
22
+ (bad config, API error, invalid argument) exited non-zero with no diagnostic. The
23
+ handler now prints the message (terse, or a full traceback under `--traceback`)
24
+ for non-signal errors, while signals still exit cleanly and quietly.
25
+ - **`--traceback` no longer leaks across invocations.** `main()` snapshots and restores
26
+ the process-global `lib_cli_exit_tools.config.traceback`, so running the CLI once with
27
+ `--traceback` in a long-lived process no longer forces full tracebacks on later commands.
28
+
10
29
  ## [6.0.0] - 2026-06-08
11
30
 
12
31
  ### Breaking Changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lib_shopware6_api_base
3
- Version: 6.0.0
3
+ Version: 6.0.2
4
4
  Summary: python3 base API client for shopware6
5
5
  Project-URL: Homepage, https://github.com/bitranox/lib_shopware6_api_base
6
6
  Project-URL: Documentation, https://github.com/bitranox/lib_shopware6_api_base/blob/master/README.md
@@ -23,9 +23,9 @@ Classifier: Programming Language :: Python :: 3.14
23
23
  Classifier: Typing :: Typed
24
24
  Requires-Python: >=3.10
25
25
  Requires-Dist: httpx2>=2.3.0
26
- Requires-Dist: lib-cli-exit-tools>=2.3.1
27
- Requires-Dist: lib-layered-config>=5.5.1
28
- Requires-Dist: lib-log-rich>=6.3.4
26
+ Requires-Dist: lib-cli-exit-tools>=2.3.2
27
+ Requires-Dist: lib-layered-config>=5.5.2
28
+ Requires-Dist: lib-log-rich>=6.3.5
29
29
  Requires-Dist: orjson
30
30
  Requires-Dist: pydantic>=2.13.4
31
31
  Requires-Dist: rich-click
@@ -1,14 +1,14 @@
1
1
  [project]
2
2
  name = "lib_shopware6_api_base"
3
- version = "6.0.0"
3
+ version = "6.0.2"
4
4
  description = "python3 base API client for shopware6"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
7
7
  dependencies = [
8
8
  "pydantic>=2.13.4",
9
- "lib_layered_config>=5.5.1",
10
- "lib_log_rich>=6.3.4",
11
- "lib_cli_exit_tools>=2.3.1",
9
+ "lib_layered_config>=5.5.2",
10
+ "lib_log_rich>=6.3.5",
11
+ "lib_cli_exit_tools>=2.3.2",
12
12
  "rich-click",
13
13
  "orjson",
14
14
  "httpx2>=2.3.0",
@@ -26,7 +26,7 @@ name = "lib_shopware6_api_base"
26
26
  #: Human-readable summary shown in CLI help output.
27
27
  title = "python3 base API client for shopware6"
28
28
  #: Current release version pulled from ``pyproject.toml`` by automation.
29
- version = "6.0.0"
29
+ version = "6.0.2"
30
30
  #: Repository homepage presented to users.
31
31
  homepage = "https://github.com/bitranox/lib_shopware6_api_base"
32
32
  #: Author attribution surfaced in CLI output.
@@ -24,6 +24,7 @@ from .exit_codes import ExitCode
24
24
  from .lib_shopware6_admin_client import Shopware6AdminAPIClientBase
25
25
  from .lib_shopware6_storefront_client import Shopware6StoreFrontClientBase
26
26
  from .logging_setup import init_logging, shutdown_logging
27
+ from .typed_click import argument, option, version_option
27
28
 
28
29
  # CONSTANTS
29
30
  CLICK_CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
@@ -39,21 +40,25 @@ _EXTRA_SENSITIVE_KEYS = frozenset({"store_api_sw_access_key", "client_id"})
39
40
 
40
41
 
41
42
  def _get_exit_code(exc: BaseException) -> int:
42
- """Map exceptions to exit codes.
43
+ """Map exceptions to exit codes, printing the diagnostic the user needs to see.
43
44
 
44
- Custom exceptions get specific exit codes.
45
- Standard exceptions are delegated to lib_cli_exit_tools.
45
+ run_cli installs this in place of its default exception handler, so it must also
46
+ emit the message the default would have printed - otherwise every error exits with
47
+ a bare code and no output. Signals exit cleanly and quietly (no traceback); all
48
+ other errors print the message (terse, or a full traceback when --traceback is set)
49
+ before the mapped exit code is returned.
46
50
  """
47
- if isinstance(exc, ConfigurationError):
48
- return ExitCode.CONFIGURATION_ERROR
49
- if isinstance(exc, ShopwareAPIError):
50
- return ExitCode.API_ERROR
51
51
  if isinstance(exc, lib_cli_exit_tools.SigIntInterrupt):
52
52
  return ExitCode.SIGINT
53
53
  if isinstance(exc, lib_cli_exit_tools.SigTermInterrupt):
54
54
  return ExitCode.SIGTERM
55
55
  if isinstance(exc, BrokenPipeError):
56
56
  return ExitCode.SIGPIPE
57
+ lib_cli_exit_tools.print_exception_message()
58
+ if isinstance(exc, ConfigurationError):
59
+ return ExitCode.CONFIGURATION_ERROR
60
+ if isinstance(exc, ShopwareAPIError):
61
+ return ExitCode.API_ERROR
57
62
  if isinstance(exc, ValueError):
58
63
  return ExitCode.INVALID_ARGUMENT
59
64
  # Delegate to lib_cli_exit_tools for standard exceptions
@@ -107,12 +112,12 @@ def info() -> None:
107
112
 
108
113
 
109
114
  @click.group(help=__init__conf__.title, context_settings=CLICK_CONTEXT_SETTINGS) # type: ignore
110
- @click.version_option(
115
+ @version_option(
111
116
  version=__init__conf__.version,
112
117
  prog_name=__init__conf__.shell_command,
113
118
  message=f"{__init__conf__.shell_command} version {__init__conf__.version}",
114
119
  )
115
- @click.option("--traceback/--no-traceback", is_flag=True, type=bool, default=None, help="return traceback information on cli")
120
+ @option("--traceback/--no-traceback", is_flag=True, type=bool, default=None, help="return traceback information on cli")
116
121
  def cli_main(traceback: bool | None = None) -> None:
117
122
  """Main CLI entry point."""
118
123
  if traceback is not None:
@@ -126,7 +131,7 @@ def cli_info() -> None:
126
131
 
127
132
 
128
133
  @cli_main.command("test-connection", context_settings=CLICK_CONTEXT_SETTINGS) # type: ignore
129
- @click.option("--storefront/--no-storefront", default=True, help="also verify the Store API access key")
134
+ @option("--storefront/--no-storefront", default=True, help="also verify the Store API access key")
130
135
  def cli_test_connection(storefront: bool) -> None:
131
136
  """Check that the configured credentials can reach Shopware.
132
137
 
@@ -150,7 +155,7 @@ def cli_test_connection(storefront: bool) -> None:
150
155
 
151
156
 
152
157
  @cli_main.command("get", context_settings=CLICK_CONTEXT_SETTINGS) # type: ignore
153
- @click.argument("endpoint")
158
+ @argument("endpoint")
154
159
  def cli_get(endpoint: str) -> None:
155
160
  """Run a read-only Admin API GET and print the JSON response.
156
161
 
@@ -169,7 +174,7 @@ def cli_config() -> None:
169
174
 
170
175
 
171
176
  @cli_config.command("show", context_settings=CLICK_CONTEXT_SETTINGS) # type: ignore
172
- @click.option(
177
+ @option(
173
178
  "--section",
174
179
  type=click.Choice(["shopware", "lib_log_rich", "all"]),
175
180
  default="all",
@@ -203,6 +208,9 @@ def cli_config_paths() -> None:
203
208
  def main() -> int:
204
209
  """Entry point with logging setup and proper signal handling."""
205
210
  init_logging()
211
+ # cli_main sets the process-global lib_cli_exit_tools.config.traceback from --traceback;
212
+ # snapshot and restore it so the flag does not leak into later in-process invocations.
213
+ traceback_default = lib_cli_exit_tools.config.traceback
206
214
  try:
207
215
  return lib_cli_exit_tools.run_cli(
208
216
  cli_main,
@@ -210,6 +218,7 @@ def main() -> int:
210
218
  install_signals=True,
211
219
  )
212
220
  finally:
221
+ lib_cli_exit_tools.config.traceback = traceback_default
213
222
  shutdown_logging()
214
223
 
215
224
 
@@ -0,0 +1,34 @@
1
+ """Strictly-typed wrappers for rich_click decorators with partially-unknown types.
2
+
3
+ rich_click ships ``py.typed`` but re-exports click's decorators, whose
4
+ ``ParamType[Unknown]`` parameters make pyright (strict mode) report
5
+ ``reportUnknownMemberType`` at every call site. Wrapping the affected decorators
6
+ here behind explicit, fully-known signatures keeps the rest of the code
7
+ strict-clean without disabling the rule. This module is the single boundary that
8
+ touches the untyped surface, so the only ``# pyright: ignore`` for this gap lives here.
9
+ """
10
+
11
+ from collections.abc import Callable
12
+ from typing import Any
13
+
14
+ import rich_click as click
15
+
16
+ _CommandDecorator = Callable[[Callable[..., Any]], Callable[..., Any]]
17
+
18
+
19
+ def option(*param_decls: str, **attrs: Any) -> _CommandDecorator:
20
+ """Typed wrapper over :func:`rich_click.option`. See module docstring."""
21
+ return click.option(*param_decls, **attrs) # pyright: ignore[reportUnknownMemberType]
22
+
23
+
24
+ def version_option(*param_decls: str, **attrs: Any) -> _CommandDecorator:
25
+ """Typed wrapper over :func:`rich_click.version_option`. See module docstring."""
26
+ return click.version_option(*param_decls, **attrs) # pyright: ignore[reportUnknownMemberType]
27
+
28
+
29
+ def argument(*param_decls: str, **attrs: Any) -> _CommandDecorator:
30
+ """Typed wrapper over :func:`rich_click.argument`. See module docstring."""
31
+ return click.argument(*param_decls, **attrs) # pyright: ignore[reportUnknownMemberType]
32
+
33
+
34
+ __all__ = ["argument", "option", "version_option"]
@@ -246,6 +246,61 @@ class TestExitCodeMapping:
246
246
  # lib_cli_exit_tools returns 1 for generic exceptions
247
247
  assert exit_code == 1
248
248
 
249
+ @pytest.mark.os_agnostic
250
+ def test_error_prints_diagnostic_message(self, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
251
+ """A live error must print its message - run_cli's custom handler used to swallow it."""
252
+ import lib_cli_exit_tools
253
+
254
+ from lib_shopware6_api_base.exit_codes import ExitCode
255
+ from lib_shopware6_api_base.lib_shopware6_api_base_cli import _get_exit_code
256
+
257
+ # pin the terse format so the assertion does not depend on a leaked global --traceback state
258
+ monkeypatch.setattr(lib_cli_exit_tools.config, "traceback", False)
259
+ try:
260
+ raise ValueError("diagnostic_marker_42")
261
+ except ValueError as exc:
262
+ code = _get_exit_code(exc)
263
+ captured = capsys.readouterr()
264
+ assert code == ExitCode.INVALID_ARGUMENT
265
+ assert "diagnostic_marker_42" in (captured.out + captured.err)
266
+
267
+ @pytest.mark.os_agnostic
268
+ def test_configuration_error_prints_message(
269
+ self, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
270
+ ) -> None:
271
+ """A domain exception must also print its diagnostic, not just map an exit code."""
272
+ import lib_cli_exit_tools
273
+
274
+ from lib_shopware6_api_base.conf_shopware6_api_base_classes import ConfigurationError
275
+ from lib_shopware6_api_base.exit_codes import ExitCode
276
+ from lib_shopware6_api_base.lib_shopware6_api_base_cli import _get_exit_code
277
+
278
+ monkeypatch.setattr(lib_cli_exit_tools.config, "traceback", False)
279
+ try:
280
+ raise ConfigurationError("config_marker_99")
281
+ except ConfigurationError as exc:
282
+ code = _get_exit_code(exc)
283
+ captured = capsys.readouterr()
284
+ assert code == ExitCode.CONFIGURATION_ERROR
285
+ assert "config_marker_99" in (captured.out + captured.err)
286
+
287
+ @pytest.mark.os_agnostic
288
+ def test_signal_exit_is_quiet(self, capsys: pytest.CaptureFixture[str]) -> None:
289
+ """Signals exit cleanly with no printed traceback, even with an active exception."""
290
+ import lib_cli_exit_tools
291
+
292
+ from lib_shopware6_api_base.exit_codes import ExitCode
293
+ from lib_shopware6_api_base.lib_shopware6_api_base_cli import _get_exit_code
294
+
295
+ try:
296
+ raise lib_cli_exit_tools.SigIntInterrupt()
297
+ except lib_cli_exit_tools.SigIntInterrupt as exc:
298
+ code = _get_exit_code(exc)
299
+ captured = capsys.readouterr()
300
+ assert code == ExitCode.SIGINT
301
+ assert captured.out == ""
302
+ assert captured.err == ""
303
+
249
304
 
250
305
  # Keep the original test for backward compatibility
251
306
  def test_cli_commands() -> None: