zscaler-sdk-python 2.0.0b1__tar.gz → 2.0.0b2__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 (105) hide show
  1. {zscaler_sdk_python-2.0.0b1/zscaler_sdk_python.egg-info → zscaler_sdk_python-2.0.0b2}/PKG-INFO +15 -20
  2. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/README.md +10 -19
  3. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/pyproject.toml +7 -2
  4. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2/zscaler_sdk_python.egg-info}/PKG-INFO +15 -20
  5. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zscaler_sdk_python.egg-info/SOURCES.txt +3 -0
  6. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zscaler_sdk_python.egg-info/requires.txt +5 -0
  7. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/__version__.py +1 -1
  8. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/session.py +22 -6
  9. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/auth.py +21 -0
  10. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/client.py +190 -13
  11. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/config.py +10 -3
  12. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/credentials.py +15 -6
  13. zscaler_sdk_python-2.0.0b2/zssdk/zscore/data/_errors.json +14 -0
  14. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/_retry.json +10 -0
  15. zscaler_sdk_python-2.0.0b2/zssdk/zscore/data/zia/v1/errors-1.json +40 -0
  16. zscaler_sdk_python-2.0.0b2/zssdk/zscore/data/ztw/v1/errors-1.json +40 -0
  17. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/ztw/v1/service-1.json +553 -42
  18. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/endpoint.py +4 -0
  19. zscaler_sdk_python-2.0.0b2/zssdk/zscore/errorfactory.py +210 -0
  20. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/errorutils.py +48 -7
  21. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/exceptions.py +158 -0
  22. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/httpsession.py +36 -3
  23. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/parsers.py +48 -12
  24. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/useragent.py +1 -1
  25. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/ztw_client.pyi +21 -1
  26. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/data/ztw/v1/resources-1.json +958 -199
  27. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/ztw_resources.pyi +186 -14
  28. zscaler_sdk_python-2.0.0b1/zssdk/zscore/errorfactory.py +0 -96
  29. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/LICENSE.md +0 -0
  30. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/setup.cfg +0 -0
  31. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zscaler_sdk_python.egg-info/dependency_links.txt +0 -0
  32. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zscaler_sdk_python.egg-info/top_level.txt +0 -0
  33. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/__init__.py +0 -0
  34. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/py.typed +0 -0
  35. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/session.pyi +0 -0
  36. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/__init__.py +0 -0
  37. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/args.py +0 -0
  38. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/case.py +0 -0
  39. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/configloader.py +0 -0
  40. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/configprovider.py +0 -0
  41. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/csv_utils.py +0 -0
  42. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/endpoints.json +0 -0
  43. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/exception.json +0 -0
  44. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zcc/v1/paginators-1.json +0 -0
  45. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zcc/v1/service-1.json +0 -0
  46. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zdx/v1/paginators-1.json +0 -0
  47. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zdx/v1/service-1.json +0 -0
  48. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zia/v1/paginators-1.json +0 -0
  49. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zia/v1/service-1.json +0 -0
  50. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zid/v1/paginators-1.json +0 -0
  51. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zid/v1/service-1.json +0 -0
  52. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zpa/v1/paginators-1.json +0 -0
  53. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/zpa/v1/service-1.json +0 -0
  54. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/data/ztw/v1/paginators-1.json +0 -0
  55. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/handlers.py +0 -0
  56. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/hooks.py +0 -0
  57. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/loaders.py +0 -0
  58. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/logger.py +0 -0
  59. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/model.py +0 -0
  60. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/paginate.py +0 -0
  61. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/regions.py +0 -0
  62. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/request.py +0 -0
  63. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/response.py +0 -0
  64. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/retry.py +0 -0
  65. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/serialize.py +0 -0
  66. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/session.py +0 -0
  67. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/session.pyi +0 -0
  68. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/stub.py +0 -0
  69. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/tokenprovider.py +0 -0
  70. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/utils.py +0 -0
  71. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/validate.py +0 -0
  72. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/zcc_client.pyi +0 -0
  73. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/zdx_client.pyi +0 -0
  74. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/zia_client.pyi +0 -0
  75. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/zid_client.pyi +0 -0
  76. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zscore/zpa_client.pyi +0 -0
  77. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/__init__.py +0 -0
  78. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/action.py +0 -0
  79. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/base.py +0 -0
  80. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/base.pyi +0 -0
  81. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/collection.py +0 -0
  82. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/collection.pyi +0 -0
  83. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/data/zcc/v1/resources-1.json +0 -0
  84. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/data/zdx/v1/resources-1.json +0 -0
  85. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/data/zia/v1/resources-1.json +0 -0
  86. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/data/zid/v1/resources-1.json +0 -0
  87. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/data/zpa/v1/resources-1.json +0 -0
  88. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/dictionary.py +0 -0
  89. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/dictionary.pyi +0 -0
  90. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/exception_factory.py +0 -0
  91. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/exceptions.py +0 -0
  92. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/exceptions.pyi +0 -0
  93. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/factory.py +0 -0
  94. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/params.py +0 -0
  95. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/response.py +0 -0
  96. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/service.py +0 -0
  97. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/service.pyi +0 -0
  98. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/subresource.py +0 -0
  99. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/utils.py +0 -0
  100. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/validation.py +0 -0
  101. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/zcc_resources.pyi +0 -0
  102. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/zdx_resources.pyi +0 -0
  103. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/zia_resources.pyi +0 -0
  104. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/zid_resources.pyi +0 -0
  105. {zscaler_sdk_python-2.0.0b1 → zscaler_sdk_python-2.0.0b2}/zssdk/zsresource/zpa_resources.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zscaler-sdk-python
3
- Version: 2.0.0b1
3
+ Version: 2.0.0b2
4
4
  Summary: Zscaler SDK for Python
5
5
  Author-email: "Zscaler Inc." <devrel@zscaler.com>
6
6
  License-Expression: MIT
@@ -23,7 +23,11 @@ License-File: LICENSE.md
23
23
  Requires-Dist: cryptography>=46.0.0
24
24
  Requires-Dist: httpx<2.0.0,>=0.28.0
25
25
  Requires-Dist: jmespath>=1.0.0
26
+ Requires-Dist: pydantic<3.0.0,>=2.0.0
26
27
  Requires-Dist: PyJWT<3.0.0,>=2.8.0
28
+ Requires-Dist: truststore>=0.9.0
29
+ Provides-Extra: examples
30
+ Requires-Dist: prettytable>=3.0.0; extra == "examples"
27
31
  Provides-Extra: dev
28
32
  Requires-Dist: black==25.12.0; extra == "dev"
29
33
  Requires-Dist: faker>=30.0.0; extra == "dev"
@@ -130,7 +134,7 @@ This SDK uses a resource-oriented design with the following characteristics:
130
134
 
131
135
  If you are currently using [`zscaler-sdk-python`](https://github.com/zscaler/zscaler-sdk-python), here is why you should switch to `zscaler-sdk-python`:
132
136
 
133
- | Capability | `zscaler-sdk-python` (previous) | `zscaler-sdk-python` (this SDK) |
137
+ | Capability | `zscaler-sdk-python` v1 | `zscaler-sdk-python` v2 |
134
138
  |---|---|---|
135
139
  | **Data access** | Raw `dict` — `user["name"]` | Resource objects — `user.name` |
136
140
  | **CRUD pattern** | Service methods returning `(result, resp, error)` tuples | Active Record — `resource.create()`, `.load()`, `.update()`, `.delete()` |
@@ -297,6 +301,8 @@ client_id = your_beta_client_id
297
301
  client_secret = your_beta_client_secret
298
302
  ```
299
303
 
304
+ > **Note:** Profile names (e.g., `[default]`, `[beta]`) are arbitrary labels you choose. The `cloud` key within a profile is what selects the non-production Zscaler environment. Omit `cloud` entirely for production.
305
+
300
306
  Use a profile by name:
301
307
 
302
308
  ```python
@@ -392,7 +398,7 @@ The resource layer provides a Pythonic, object-oriented interface. Access servic
392
398
  ```python
393
399
  import zssdk
394
400
 
395
- session = zssdk.Session(profile_name="beta")
401
+ session = zssdk.Session(profile_name="default")
396
402
  zia = session.zia
397
403
 
398
404
  # Create a new VPN credential
@@ -512,7 +518,7 @@ When you use the `with` statement with `session.zia` or `session.ztw`:
512
518
  ```python
513
519
  import zssdk
514
520
 
515
- session = zssdk.Session(profile_name="beta")
521
+ session = zssdk.Session(profile_name="default")
516
522
 
517
523
  # ZIA: context manager activates changes on exit
518
524
  with session.zia as zia:
@@ -705,7 +711,7 @@ config = Config(
705
711
  log_file_path="/var/log/zssdk.log",
706
712
  )
707
713
  )
708
- session = Session(config=config, profile_name="beta")
714
+ session = Session(config=config, profile_name="default")
709
715
  ```
710
716
 
711
717
  **Custom format (programmatic only):**
@@ -722,7 +728,7 @@ config = Config(
722
728
  custom_formatter=custom_formatter,
723
729
  )
724
730
  )
725
- session = Session(config=config, profile_name="beta")
731
+ session = Session(config=config, profile_name="default")
726
732
  ```
727
733
 
728
734
  Sensitive fields (tokens, secrets, passwords) are redacted in log output.
@@ -760,20 +766,9 @@ When you type `session.zia.` in VS Code or PyCharm, you will see completions for
760
766
 
761
767
  ## Examples
762
768
 
763
- The repository includes runnable examples under `python/examples/`:
764
-
765
- **Zscaler Identity (ZID):**
766
-
767
- - `user_management/` — User profile CRUD
768
- - `group_management/` — Group management
769
- - `api_client_management/` — API client CRUD
770
- - `resource_server_management/` — Resource server viewing
771
-
772
- **Zscaler Internet Access (ZIA):**
773
-
774
- - `vpn_credentials_management/` — VPN credential management
769
+ The repository includes runnable CLI scripts and inline examples under `examples/`, organized by product. Prerequisites and configuration are covered in the [Configuration](#configuration) section above.
775
770
 
776
- Each example directory contains a `README.md` with usage details. Run any script with `--help` for options:
771
+ All CLI scripts are self-documenting. Run any script with no arguments for a usage hint, or `--help` for the full reference:
777
772
 
778
773
  ```sh
779
774
  python examples/zid/user_management/user_management.py --help
@@ -905,7 +900,7 @@ client_secret = ...
905
900
 
906
901
  ### Quick reference
907
902
 
908
- | What | `zscaler-sdk-python` | `zscaler-sdk-python` |
903
+ | What | `zscaler-sdk-python` v1 | `zscaler-sdk-python` v2 |
909
904
  |---|---|---|
910
905
  | Import | `from zscaler import ZscalerClient` | `from zssdk import Session` |
911
906
  | Access field | `user["name"]` | `user.name` |
@@ -87,7 +87,7 @@ This SDK uses a resource-oriented design with the following characteristics:
87
87
 
88
88
  If you are currently using [`zscaler-sdk-python`](https://github.com/zscaler/zscaler-sdk-python), here is why you should switch to `zscaler-sdk-python`:
89
89
 
90
- | Capability | `zscaler-sdk-python` (previous) | `zscaler-sdk-python` (this SDK) |
90
+ | Capability | `zscaler-sdk-python` v1 | `zscaler-sdk-python` v2 |
91
91
  |---|---|---|
92
92
  | **Data access** | Raw `dict` — `user["name"]` | Resource objects — `user.name` |
93
93
  | **CRUD pattern** | Service methods returning `(result, resp, error)` tuples | Active Record — `resource.create()`, `.load()`, `.update()`, `.delete()` |
@@ -254,6 +254,8 @@ client_id = your_beta_client_id
254
254
  client_secret = your_beta_client_secret
255
255
  ```
256
256
 
257
+ > **Note:** Profile names (e.g., `[default]`, `[beta]`) are arbitrary labels you choose. The `cloud` key within a profile is what selects the non-production Zscaler environment. Omit `cloud` entirely for production.
258
+
257
259
  Use a profile by name:
258
260
 
259
261
  ```python
@@ -349,7 +351,7 @@ The resource layer provides a Pythonic, object-oriented interface. Access servic
349
351
  ```python
350
352
  import zssdk
351
353
 
352
- session = zssdk.Session(profile_name="beta")
354
+ session = zssdk.Session(profile_name="default")
353
355
  zia = session.zia
354
356
 
355
357
  # Create a new VPN credential
@@ -469,7 +471,7 @@ When you use the `with` statement with `session.zia` or `session.ztw`:
469
471
  ```python
470
472
  import zssdk
471
473
 
472
- session = zssdk.Session(profile_name="beta")
474
+ session = zssdk.Session(profile_name="default")
473
475
 
474
476
  # ZIA: context manager activates changes on exit
475
477
  with session.zia as zia:
@@ -662,7 +664,7 @@ config = Config(
662
664
  log_file_path="/var/log/zssdk.log",
663
665
  )
664
666
  )
665
- session = Session(config=config, profile_name="beta")
667
+ session = Session(config=config, profile_name="default")
666
668
  ```
667
669
 
668
670
  **Custom format (programmatic only):**
@@ -679,7 +681,7 @@ config = Config(
679
681
  custom_formatter=custom_formatter,
680
682
  )
681
683
  )
682
- session = Session(config=config, profile_name="beta")
684
+ session = Session(config=config, profile_name="default")
683
685
  ```
684
686
 
685
687
  Sensitive fields (tokens, secrets, passwords) are redacted in log output.
@@ -717,20 +719,9 @@ When you type `session.zia.` in VS Code or PyCharm, you will see completions for
717
719
 
718
720
  ## Examples
719
721
 
720
- The repository includes runnable examples under `python/examples/`:
721
-
722
- **Zscaler Identity (ZID):**
723
-
724
- - `user_management/` — User profile CRUD
725
- - `group_management/` — Group management
726
- - `api_client_management/` — API client CRUD
727
- - `resource_server_management/` — Resource server viewing
728
-
729
- **Zscaler Internet Access (ZIA):**
730
-
731
- - `vpn_credentials_management/` — VPN credential management
722
+ The repository includes runnable CLI scripts and inline examples under `examples/`, organized by product. Prerequisites and configuration are covered in the [Configuration](#configuration) section above.
732
723
 
733
- Each example directory contains a `README.md` with usage details. Run any script with `--help` for options:
724
+ All CLI scripts are self-documenting. Run any script with no arguments for a usage hint, or `--help` for the full reference:
734
725
 
735
726
  ```sh
736
727
  python examples/zid/user_management/user_management.py --help
@@ -862,7 +853,7 @@ client_secret = ...
862
853
 
863
854
  ### Quick reference
864
855
 
865
- | What | `zscaler-sdk-python` | `zscaler-sdk-python` |
856
+ | What | `zscaler-sdk-python` v1 | `zscaler-sdk-python` v2 |
866
857
  |---|---|---|
867
858
  | Import | `from zscaler import ZscalerClient` | `from zssdk import Session` |
868
859
  | Access field | `user["name"]` | `user.name` |
@@ -2,8 +2,8 @@
2
2
  # jmespath is required here because it's imported by the SDK,
3
3
  # and the SDK is imported during the build process to determine
4
4
  # the dynamic version number.
5
- # PyJWT and httpx are also required for the same reason.
6
- requires = ["setuptools>=61.0", "jmespath", "PyJWT>=2.8.0,<3.0.0", "httpx>=0.28.0"]
5
+ # PyJWT, httpx, and truststore are also required for the same reason.
6
+ requires = ["setuptools>=61.0", "jmespath", "PyJWT>=2.8.0,<3.0.0", "httpx>=0.28.0", "pydantic>=2.0.0", "truststore>=0.9.0"]
7
7
  build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
@@ -29,7 +29,9 @@ dependencies = [
29
29
  "cryptography>=46.0.0",
30
30
  "httpx>=0.28.0,<2.0.0",
31
31
  "jmespath>=1.0.0",
32
+ "pydantic>=2.0.0,<3.0.0",
32
33
  "PyJWT>=2.8.0,<3.0.0",
34
+ "truststore>=0.9.0",
33
35
  ]
34
36
 
35
37
  [project.urls]
@@ -39,6 +41,9 @@ Documentation = "http://automation.zsapidocs.net/docs/"
39
41
  "Bug Tracker" = "https://github.com/zscaler/zscaler-sdk-python/issues"
40
42
 
41
43
  [project.optional-dependencies]
44
+ examples = [
45
+ "prettytable>=3.0.0",
46
+ ]
42
47
  dev = [
43
48
  "black==25.12.0",
44
49
  "faker>=30.0.0",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zscaler-sdk-python
3
- Version: 2.0.0b1
3
+ Version: 2.0.0b2
4
4
  Summary: Zscaler SDK for Python
5
5
  Author-email: "Zscaler Inc." <devrel@zscaler.com>
6
6
  License-Expression: MIT
@@ -23,7 +23,11 @@ License-File: LICENSE.md
23
23
  Requires-Dist: cryptography>=46.0.0
24
24
  Requires-Dist: httpx<2.0.0,>=0.28.0
25
25
  Requires-Dist: jmespath>=1.0.0
26
+ Requires-Dist: pydantic<3.0.0,>=2.0.0
26
27
  Requires-Dist: PyJWT<3.0.0,>=2.8.0
28
+ Requires-Dist: truststore>=0.9.0
29
+ Provides-Extra: examples
30
+ Requires-Dist: prettytable>=3.0.0; extra == "examples"
27
31
  Provides-Extra: dev
28
32
  Requires-Dist: black==25.12.0; extra == "dev"
29
33
  Requires-Dist: faker>=30.0.0; extra == "dev"
@@ -130,7 +134,7 @@ This SDK uses a resource-oriented design with the following characteristics:
130
134
 
131
135
  If you are currently using [`zscaler-sdk-python`](https://github.com/zscaler/zscaler-sdk-python), here is why you should switch to `zscaler-sdk-python`:
132
136
 
133
- | Capability | `zscaler-sdk-python` (previous) | `zscaler-sdk-python` (this SDK) |
137
+ | Capability | `zscaler-sdk-python` v1 | `zscaler-sdk-python` v2 |
134
138
  |---|---|---|
135
139
  | **Data access** | Raw `dict` — `user["name"]` | Resource objects — `user.name` |
136
140
  | **CRUD pattern** | Service methods returning `(result, resp, error)` tuples | Active Record — `resource.create()`, `.load()`, `.update()`, `.delete()` |
@@ -297,6 +301,8 @@ client_id = your_beta_client_id
297
301
  client_secret = your_beta_client_secret
298
302
  ```
299
303
 
304
+ > **Note:** Profile names (e.g., `[default]`, `[beta]`) are arbitrary labels you choose. The `cloud` key within a profile is what selects the non-production Zscaler environment. Omit `cloud` entirely for production.
305
+
300
306
  Use a profile by name:
301
307
 
302
308
  ```python
@@ -392,7 +398,7 @@ The resource layer provides a Pythonic, object-oriented interface. Access servic
392
398
  ```python
393
399
  import zssdk
394
400
 
395
- session = zssdk.Session(profile_name="beta")
401
+ session = zssdk.Session(profile_name="default")
396
402
  zia = session.zia
397
403
 
398
404
  # Create a new VPN credential
@@ -512,7 +518,7 @@ When you use the `with` statement with `session.zia` or `session.ztw`:
512
518
  ```python
513
519
  import zssdk
514
520
 
515
- session = zssdk.Session(profile_name="beta")
521
+ session = zssdk.Session(profile_name="default")
516
522
 
517
523
  # ZIA: context manager activates changes on exit
518
524
  with session.zia as zia:
@@ -705,7 +711,7 @@ config = Config(
705
711
  log_file_path="/var/log/zssdk.log",
706
712
  )
707
713
  )
708
- session = Session(config=config, profile_name="beta")
714
+ session = Session(config=config, profile_name="default")
709
715
  ```
710
716
 
711
717
  **Custom format (programmatic only):**
@@ -722,7 +728,7 @@ config = Config(
722
728
  custom_formatter=custom_formatter,
723
729
  )
724
730
  )
725
- session = Session(config=config, profile_name="beta")
731
+ session = Session(config=config, profile_name="default")
726
732
  ```
727
733
 
728
734
  Sensitive fields (tokens, secrets, passwords) are redacted in log output.
@@ -760,20 +766,9 @@ When you type `session.zia.` in VS Code or PyCharm, you will see completions for
760
766
 
761
767
  ## Examples
762
768
 
763
- The repository includes runnable examples under `python/examples/`:
764
-
765
- **Zscaler Identity (ZID):**
766
-
767
- - `user_management/` — User profile CRUD
768
- - `group_management/` — Group management
769
- - `api_client_management/` — API client CRUD
770
- - `resource_server_management/` — Resource server viewing
771
-
772
- **Zscaler Internet Access (ZIA):**
773
-
774
- - `vpn_credentials_management/` — VPN credential management
769
+ The repository includes runnable CLI scripts and inline examples under `examples/`, organized by product. Prerequisites and configuration are covered in the [Configuration](#configuration) section above.
775
770
 
776
- Each example directory contains a `README.md` with usage details. Run any script with `--help` for options:
771
+ All CLI scripts are self-documenting. Run any script with no arguments for a usage hint, or `--help` for the full reference:
777
772
 
778
773
  ```sh
779
774
  python examples/zid/user_management/user_management.py --help
@@ -905,7 +900,7 @@ client_secret = ...
905
900
 
906
901
  ### Quick reference
907
902
 
908
- | What | `zscaler-sdk-python` | `zscaler-sdk-python` |
903
+ | What | `zscaler-sdk-python` v1 | `zscaler-sdk-python` v2 |
909
904
  |---|---|---|
910
905
  | Import | `from zscaler import ZscalerClient` | `from zssdk import Session` |
911
906
  | Access field | `user["name"]` | `user.name` |
@@ -51,6 +51,7 @@ zssdk/zscore/zia_client.pyi
51
51
  zssdk/zscore/zid_client.pyi
52
52
  zssdk/zscore/zpa_client.pyi
53
53
  zssdk/zscore/ztw_client.pyi
54
+ zssdk/zscore/data/_errors.json
54
55
  zssdk/zscore/data/_retry.json
55
56
  zssdk/zscore/data/endpoints.json
56
57
  zssdk/zscore/data/exception.json
@@ -58,12 +59,14 @@ zssdk/zscore/data/zcc/v1/paginators-1.json
58
59
  zssdk/zscore/data/zcc/v1/service-1.json
59
60
  zssdk/zscore/data/zdx/v1/paginators-1.json
60
61
  zssdk/zscore/data/zdx/v1/service-1.json
62
+ zssdk/zscore/data/zia/v1/errors-1.json
61
63
  zssdk/zscore/data/zia/v1/paginators-1.json
62
64
  zssdk/zscore/data/zia/v1/service-1.json
63
65
  zssdk/zscore/data/zid/v1/paginators-1.json
64
66
  zssdk/zscore/data/zid/v1/service-1.json
65
67
  zssdk/zscore/data/zpa/v1/paginators-1.json
66
68
  zssdk/zscore/data/zpa/v1/service-1.json
69
+ zssdk/zscore/data/ztw/v1/errors-1.json
67
70
  zssdk/zscore/data/ztw/v1/paginators-1.json
68
71
  zssdk/zscore/data/ztw/v1/service-1.json
69
72
  zssdk/zsresource/__init__.py
@@ -1,7 +1,9 @@
1
1
  cryptography>=46.0.0
2
2
  httpx<2.0.0,>=0.28.0
3
3
  jmespath>=1.0.0
4
+ pydantic<3.0.0,>=2.0.0
4
5
  PyJWT<3.0.0,>=2.8.0
6
+ truststore>=0.9.0
5
7
 
6
8
  [dev]
7
9
  black==25.12.0
@@ -18,3 +20,6 @@ anyio==4.12.0
18
20
  autopep8==2.3.2
19
21
  tomlkit==0.13.3
20
22
  uv==0.9.21
23
+
24
+ [examples]
25
+ prettytable>=3.0.0
@@ -14,4 +14,4 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
14
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
15
  """
16
16
 
17
- __version__ = "2.0.0b1"
17
+ __version__ = "2.0.0b2"
@@ -16,8 +16,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
16
  # /Users/kakella/gitlab/oneapi/oneapi-sdk/python/zssdk/session.py
17
17
 
18
18
  import threading
19
- from dataclasses import asdict, dataclass, field
20
- from typing import Optional
19
+ from dataclasses import dataclass, fields
20
+ from typing import Optional, Union
21
+
22
+ from pydantic import SecretStr
21
23
 
22
24
  import zssdk.zscore.session
23
25
 
@@ -37,17 +39,31 @@ class ClientParams:
37
39
  cloud: Optional[str] = None
38
40
  vanity_domain: Optional[str] = None
39
41
  client_id: Optional[str] = None
40
- client_secret: Optional[str] = field(default=None, repr=False)
41
- private_key: Optional[str] = field(default=None, repr=False)
42
+ client_secret: Optional[Union[str, SecretStr]] = None
43
+ private_key: Optional[Union[str, SecretStr]] = None
42
44
  cert_file_path: Optional[str] = None
43
45
  token_provider: Optional[TokenProvider] = None
44
46
  api_version: Optional[str] = None
45
47
  customer_id: Optional[str] = None
46
48
  config: Optional[object] = None # zssdk.zscore.config.Config
47
49
 
50
+ def __post_init__(self):
51
+ if self.client_secret is not None and not isinstance(self.client_secret, SecretStr):
52
+ self.client_secret = SecretStr(self.client_secret)
53
+ if self.private_key is not None and not isinstance(self.private_key, SecretStr):
54
+ self.private_key = SecretStr(self.private_key)
55
+
48
56
  def to_dict(self):
49
- """Convert to dict, excluding None values."""
50
- return {k: v for k, v in asdict(self).items() if v is not None}
57
+ """Convert to dict, excluding None values. SecretStr values are unwrapped."""
58
+ result = {}
59
+ for f in fields(self):
60
+ value = getattr(self, f.name)
61
+ if value is not None:
62
+ if isinstance(value, SecretStr):
63
+ result[f.name] = value.get_secret_value()
64
+ else:
65
+ result[f.name] = value
66
+ return result
51
67
 
52
68
 
53
69
  class Session:
@@ -66,6 +66,27 @@ class _HttpxAuthProvider(httpx.Auth):
66
66
  else:
67
67
  raise
68
68
 
69
+ def force_refresh(self):
70
+ """
71
+ Invalidate the cached token so the next outbound request triggers a
72
+ fresh fetch via :meth:`auth_flow`.
73
+
74
+ Used by the body-aware reactive retry loop in
75
+ :meth:`BaseZsClient._execute_with_reactive_retry` when the API signals
76
+ ``SESSION_NOT_VALID`` / "Session already invalidated" — the in-memory
77
+ token has been revoked server-side, so the safest recovery is to throw
78
+ it away and let the next request trigger ``_refresh_token()`` under
79
+ the existing lock.
80
+
81
+ Thread-safe: uses the same lock as :meth:`_refresh_token`. If multiple
82
+ threads observe a 401 and all call this method, the worst case is a
83
+ small number of redundant refreshes — never a stale-token loop.
84
+ """
85
+ with self._lock:
86
+ self.sdk_logger.logger.info("Token recycle: invalidating cached token (reactive refresh)")
87
+ self._token = None
88
+ self._expiry_time = 0
89
+
69
90
  def auth_flow(self, request: httpx.Request):
70
91
  """The entry point for httpx's authentication mechanism."""
71
92
  if self._is_expired():