pyc8y 4.0.0a1__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 (168) hide show
  1. pyc8y-4.0.0a1/.gitattributes +1 -0
  2. pyc8y-4.0.0a1/.github/workflows/codeql-analysis.yml +70 -0
  3. pyc8y-4.0.0a1/.github/workflows/lint.yml +16 -0
  4. pyc8y-4.0.0a1/.github/workflows/publish.yml +39 -0
  5. pyc8y-4.0.0a1/.gitignore +14 -0
  6. pyc8y-4.0.0a1/.readthedocs.yaml +23 -0
  7. pyc8y-4.0.0a1/CHANGELOG.md +473 -0
  8. pyc8y-4.0.0a1/LICENSE +201 -0
  9. pyc8y-4.0.0a1/PKG-INFO +313 -0
  10. pyc8y-4.0.0a1/README.md +78 -0
  11. pyc8y-4.0.0a1/bookworm311.dockerfile +6 -0
  12. pyc8y-4.0.0a1/buster37.dockerfile +10 -0
  13. pyc8y-4.0.0a1/docs/conf.py +45 -0
  14. pyc8y-4.0.0a1/docs/docs-app.md +16 -0
  15. pyc8y-4.0.0a1/docs/docs-base.md +15 -0
  16. pyc8y-4.0.0a1/docs/docs-main.md +28 -0
  17. pyc8y-4.0.0a1/docs/docs-measurements.md +34 -0
  18. pyc8y-4.0.0a1/docs/docs-model.md +42 -0
  19. pyc8y-4.0.0a1/docs/getting-started.md +395 -0
  20. pyc8y-4.0.0a1/docs/griffe_ext.py +10 -0
  21. pyc8y-4.0.0a1/docs/index.md +86 -0
  22. pyc8y-4.0.0a1/docs/intro-app.md +20 -0
  23. pyc8y-4.0.0a1/docs/intro-base.md +17 -0
  24. pyc8y-4.0.0a1/docs/intro-main.md +6 -0
  25. pyc8y-4.0.0a1/docs/intro-measurements.md +26 -0
  26. pyc8y-4.0.0a1/docs/intro-model.md +6 -0
  27. pyc8y-4.0.0a1/docs/requirements.txt +5 -0
  28. pyc8y-4.0.0a1/integration_tests/__init__.py +1 -0
  29. pyc8y-4.0.0a1/integration_tests/conftest.py +300 -0
  30. pyc8y-4.0.0a1/integration_tests/test_alarms.py +216 -0
  31. pyc8y-4.0.0a1/integration_tests/test_applications.py +114 -0
  32. pyc8y-4.0.0a1/integration_tests/test_apps.py +186 -0
  33. pyc8y-4.0.0a1/integration_tests/test_audits.py +67 -0
  34. pyc8y-4.0.0a1/integration_tests/test_base_aiohttp.py +27 -0
  35. pyc8y-4.0.0a1/integration_tests/test_binaries.py +103 -0
  36. pyc8y-4.0.0a1/integration_tests/test_bulk_operations.py +74 -0
  37. pyc8y-4.0.0a1/integration_tests/test_device_registry.py +109 -0
  38. pyc8y-4.0.0a1/integration_tests/test_devicegroups.py +116 -0
  39. pyc8y-4.0.0a1/integration_tests/test_events.py +231 -0
  40. pyc8y-4.0.0a1/integration_tests/test_global_roles.py +99 -0
  41. pyc8y-4.0.0a1/integration_tests/test_identity.py +64 -0
  42. pyc8y-4.0.0a1/integration_tests/test_inventory.py +461 -0
  43. pyc8y-4.0.0a1/integration_tests/test_inventoryroles.py +122 -0
  44. pyc8y-4.0.0a1/integration_tests/test_measurements.py +402 -0
  45. pyc8y-4.0.0a1/integration_tests/test_notification2.py +483 -0
  46. pyc8y-4.0.0a1/integration_tests/test_operations.py +106 -0
  47. pyc8y-4.0.0a1/integration_tests/test_tenant_options.py +110 -0
  48. pyc8y-4.0.0a1/integration_tests/test_users.py +190 -0
  49. pyc8y-4.0.0a1/justfile +26 -0
  50. pyc8y-4.0.0a1/mkdocs.yaml +40 -0
  51. pyc8y-4.0.0a1/pyproject.toml +71 -0
  52. pyc8y-4.0.0a1/pytest.ini +7 -0
  53. pyc8y-4.0.0a1/samples/Dockerfile +16 -0
  54. pyc8y-4.0.0a1/samples/Sample.ipynb +332 -0
  55. pyc8y-4.0.0a1/samples/client_side_filtering.py +122 -0
  56. pyc8y-4.0.0a1/samples/cumulocity-notification2_synchronous.json +7 -0
  57. pyc8y-4.0.0a1/samples/cumulocity-tenant_options.json +7 -0
  58. pyc8y-4.0.0a1/samples/cumulocity.json +17 -0
  59. pyc8y-4.0.0a1/samples/dealing_with_measurements.py +102 -0
  60. pyc8y-4.0.0a1/samples/device_registry.py +88 -0
  61. pyc8y-4.0.0a1/samples/handling_events.py +54 -0
  62. pyc8y-4.0.0a1/samples/multi_tenant_app.py +108 -0
  63. pyc8y-4.0.0a1/samples/notification2_asynchronous.py +68 -0
  64. pyc8y-4.0.0a1/samples/notification2_synchronous.py +69 -0
  65. pyc8y-4.0.0a1/samples/processing_modes.py +85 -0
  66. pyc8y-4.0.0a1/samples/simple_agent.py +92 -0
  67. pyc8y-4.0.0a1/samples/simple_tenant_app.py +80 -0
  68. pyc8y-4.0.0a1/samples/tenant_options.py +23 -0
  69. pyc8y-4.0.0a1/samples/user_sessions.py +51 -0
  70. pyc8y-4.0.0a1/src/pyc8y/__init__.py +10 -0
  71. pyc8y-4.0.0a1/src/pyc8y/app.py +823 -0
  72. pyc8y-4.0.0a1/src/pyc8y/auth.py +152 -0
  73. pyc8y-4.0.0a1/src/pyc8y/base_util.py +102 -0
  74. pyc8y-4.0.0a1/src/pyc8y/client.py +61 -0
  75. pyc8y-4.0.0a1/src/pyc8y/model/__init__.py +100 -0
  76. pyc8y-4.0.0a1/src/pyc8y/model/alarm.py +775 -0
  77. pyc8y-4.0.0a1/src/pyc8y/model/application.py +451 -0
  78. pyc8y-4.0.0a1/src/pyc8y/model/audit.py +369 -0
  79. pyc8y-4.0.0a1/src/pyc8y/model/binary.py +347 -0
  80. pyc8y-4.0.0a1/src/pyc8y/model/event.py +674 -0
  81. pyc8y-4.0.0a1/src/pyc8y/model/identity.py +235 -0
  82. pyc8y-4.0.0a1/src/pyc8y/model/inventory.py +777 -0
  83. pyc8y-4.0.0a1/src/pyc8y/model/managed_object.py +584 -0
  84. pyc8y-4.0.0a1/src/pyc8y/model/matcher/__init__.py +36 -0
  85. pyc8y-4.0.0a1/src/pyc8y/model/matcher/_jmespath.py +22 -0
  86. pyc8y-4.0.0a1/src/pyc8y/model/matcher/_jsonpath.py +22 -0
  87. pyc8y-4.0.0a1/src/pyc8y/model/matcher/_matcher.py +174 -0
  88. pyc8y-4.0.0a1/src/pyc8y/model/matcher/_pydf.py +25 -0
  89. pyc8y-4.0.0a1/src/pyc8y/model/measurement.py +1209 -0
  90. pyc8y-4.0.0a1/src/pyc8y/model/model_base.py +877 -0
  91. pyc8y-4.0.0a1/src/pyc8y/model/model_util.py +219 -0
  92. pyc8y-4.0.0a1/src/pyc8y/model/notification2.py +387 -0
  93. pyc8y-4.0.0a1/src/pyc8y/model/operation.py +666 -0
  94. pyc8y-4.0.0a1/src/pyc8y/model/tenant_option.py +367 -0
  95. pyc8y-4.0.0a1/src/pyc8y/model/tenants.py +265 -0
  96. pyc8y-4.0.0a1/src/pyc8y/model/user.py +1374 -0
  97. pyc8y-4.0.0a1/src/pyc8y/notification2/__init__.py +11 -0
  98. pyc8y-4.0.0a1/src/pyc8y/notification2/listener.py +378 -0
  99. pyc8y-4.0.0a1/src/pyc8y/registry/__init__.py +77 -0
  100. pyc8y-4.0.0a1/src/pyc8y/rest.py +495 -0
  101. pyc8y-4.0.0a1/src/pyc8y/types.py +187 -0
  102. pyc8y-4.0.0a1/tasks.py +168 -0
  103. pyc8y-4.0.0a1/test_interactive.ipynb +386 -0
  104. pyc8y-4.0.0a1/tests/__init__.py +1 -0
  105. pyc8y-4.0.0a1/tests/basics/test_aiohttp.py +40 -0
  106. pyc8y-4.0.0a1/tests/benchmark/__init__.py +0 -0
  107. pyc8y-4.0.0a1/tests/benchmark/mo100.json +8790 -0
  108. pyc8y-4.0.0a1/tests/benchmark/test_json.py +31 -0
  109. pyc8y-4.0.0a1/tests/model/__init__.py +1 -0
  110. pyc8y-4.0.0a1/tests/model/alarm.json +31 -0
  111. pyc8y-4.0.0a1/tests/model/application.json +66 -0
  112. pyc8y-4.0.0a1/tests/model/audit_records.json +89 -0
  113. pyc8y-4.0.0a1/tests/model/availability.json +8 -0
  114. pyc8y-4.0.0a1/tests/model/bulk_operations.json +60 -0
  115. pyc8y-4.0.0a1/tests/model/conftest.py +9 -0
  116. pyc8y-4.0.0a1/tests/model/current_user.json +25 -0
  117. pyc8y-4.0.0a1/tests/model/device.json +57 -0
  118. pyc8y-4.0.0a1/tests/model/event.json +23 -0
  119. pyc8y-4.0.0a1/tests/model/global_role.json +63 -0
  120. pyc8y-4.0.0a1/tests/model/inventoryrole.json +26 -0
  121. pyc8y-4.0.0a1/tests/model/managed_object.json +113 -0
  122. pyc8y-4.0.0a1/tests/model/operation.json +12 -0
  123. pyc8y-4.0.0a1/tests/model/series.json +65 -0
  124. pyc8y-4.0.0a1/tests/model/subscriptions.json +66 -0
  125. pyc8y-4.0.0a1/tests/model/tenant_option.json +14 -0
  126. pyc8y-4.0.0a1/tests/model/tenants.json +308 -0
  127. pyc8y-4.0.0a1/tests/model/test_administration.py +90 -0
  128. pyc8y-4.0.0a1/tests/model/test_alarm.py +116 -0
  129. pyc8y-4.0.0a1/tests/model/test_alarms.py +246 -0
  130. pyc8y-4.0.0a1/tests/model/test_application.py +23 -0
  131. pyc8y-4.0.0a1/tests/model/test_applications.py +90 -0
  132. pyc8y-4.0.0a1/tests/model/test_audit.py +124 -0
  133. pyc8y-4.0.0a1/tests/model/test_audits.py +134 -0
  134. pyc8y-4.0.0a1/tests/model/test_base.py +323 -0
  135. pyc8y-4.0.0a1/tests/model/test_bulk_operation.py +80 -0
  136. pyc8y-4.0.0a1/tests/model/test_device.py +128 -0
  137. pyc8y-4.0.0a1/tests/model/test_device_registry.py +68 -0
  138. pyc8y-4.0.0a1/tests/model/test_event.py +83 -0
  139. pyc8y-4.0.0a1/tests/model/test_events.py +182 -0
  140. pyc8y-4.0.0a1/tests/model/test_filtering.py +63 -0
  141. pyc8y-4.0.0a1/tests/model/test_global_role.py +48 -0
  142. pyc8y-4.0.0a1/tests/model/test_inventory.py +111 -0
  143. pyc8y-4.0.0a1/tests/model/test_inventoryrole.py +64 -0
  144. pyc8y-4.0.0a1/tests/model/test_managedobject.py +148 -0
  145. pyc8y-4.0.0a1/tests/model/test_matchers.py +241 -0
  146. pyc8y-4.0.0a1/tests/model/test_measurements.py +524 -0
  147. pyc8y-4.0.0a1/tests/model/test_notification2_token.py +66 -0
  148. pyc8y-4.0.0a1/tests/model/test_operation.py +70 -0
  149. pyc8y-4.0.0a1/tests/model/test_operations.py +125 -0
  150. pyc8y-4.0.0a1/tests/model/test_resource.py +228 -0
  151. pyc8y-4.0.0a1/tests/model/test_subscription.py +67 -0
  152. pyc8y-4.0.0a1/tests/model/test_subscriptions.py +70 -0
  153. pyc8y-4.0.0a1/tests/model/test_tenant.py +80 -0
  154. pyc8y-4.0.0a1/tests/model/test_tenant_option.py +118 -0
  155. pyc8y-4.0.0a1/tests/model/test_tenants.py +67 -0
  156. pyc8y-4.0.0a1/tests/model/test_user.py +91 -0
  157. pyc8y-4.0.0a1/tests/model/user.json +925 -0
  158. pyc8y-4.0.0a1/tests/smoke_test.py +27 -0
  159. pyc8y-4.0.0a1/tests/test_app.py +480 -0
  160. pyc8y-4.0.0a1/tests/test_auth.py +69 -0
  161. pyc8y-4.0.0a1/tests/test_get_client.py +218 -0
  162. pyc8y-4.0.0a1/tests/test_subscription_listener.py +212 -0
  163. pyc8y-4.0.0a1/tests/test_util.py +136 -0
  164. pyc8y-4.0.0a1/tests/utils.py +169 -0
  165. pyc8y-4.0.0a1/util/__init__.py +1 -0
  166. pyc8y-4.0.0a1/util/microservice_util.py +130 -0
  167. pyc8y-4.0.0a1/util/testing_util.py +47 -0
  168. pyc8y-4.0.0a1/uv.lock +1880 -0
@@ -0,0 +1 @@
1
+ CHANGELOG.md merge=union
@@ -0,0 +1,70 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ #
7
+ # ******** NOTE ********
8
+ # We have attempted to detect the languages in your repository. Please check
9
+ # the `language` matrix defined below to confirm you have the correct set of
10
+ # supported CodeQL languages.
11
+ #
12
+ name: "CodeQL"
13
+
14
+ on:
15
+ push:
16
+ branches: [ main ]
17
+ pull_request:
18
+ # The branches below must be a subset of the branches above
19
+ branches: [ main ]
20
+ schedule:
21
+ - cron: '36 22 * * 2'
22
+
23
+ jobs:
24
+ analyze:
25
+ name: Analyze
26
+ runs-on: ubuntu-latest
27
+ permissions:
28
+ actions: read
29
+ contents: read
30
+ security-events: write
31
+
32
+ strategy:
33
+ fail-fast: false
34
+ matrix:
35
+ language: [ 'python' ]
36
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
38
+
39
+ steps:
40
+ - name: Checkout repository
41
+ uses: actions/checkout@v2
42
+
43
+ # Initializes the CodeQL tools for scanning.
44
+ - name: Initialize CodeQL
45
+ uses: github/codeql-action/init@v1
46
+ with:
47
+ languages: ${{ matrix.language }}
48
+ # If you wish to specify custom queries, you can do so here or in a config file.
49
+ # By default, queries listed here will override any specified in a config file.
50
+ # Prefix the list here with "+" to use these queries and those in the config file.
51
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
52
+
53
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54
+ # If this step fails, then you should remove it and run the build manually (see below)
55
+ - name: Autobuild
56
+ uses: github/codeql-action/autobuild@v1
57
+
58
+ # ℹ️ Command-line programs to run using the OS shell.
59
+ # 📚 https://git.io/JvXDl
60
+
61
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62
+ # and modify them (or add more) to build your code if your project
63
+ # uses a compiled language
64
+
65
+ #- run: |
66
+ # make bootstrap
67
+ # make release
68
+
69
+ - name: Perform CodeQL Analysis
70
+ uses: github/codeql-action/analyze@v1
@@ -0,0 +1,16 @@
1
+ name: Lint
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ lint:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v6.0.2
11
+ - name: Install uv
12
+ uses: astral-sh/setup-uv@v8.1.0
13
+ with:
14
+ python-version: '3.11'
15
+ - name: Run ruff
16
+ run: uv run ruff check src/pyc8y tests integration_tests samples
@@ -0,0 +1,39 @@
1
+ # Publishes pyc8y to PyPI via Trusted Publishing (OIDC) when a v* tag is pushed.
2
+ # Setup:
3
+ # - PyPI: https://pypi.org/manage/account/publishing/ -> Add a pending publisher
4
+ # (project=pyc8y, repo=this repo, workflow=publish.yml, environment=pypi)
5
+ # - GitHub: Settings -> Environments -> create "pypi"
6
+
7
+ name: Release
8
+
9
+ on:
10
+ push:
11
+ tags:
12
+ - v*
13
+
14
+ jobs:
15
+ pypi:
16
+ name: Publish to PyPI
17
+ runs-on: ubuntu-latest
18
+ environment:
19
+ name: pypi
20
+ permissions:
21
+ id-token: write
22
+ contents: read
23
+ steps:
24
+ - name: Checkout
25
+ uses: actions/checkout@v6.0.2
26
+ with:
27
+ fetch-depth: 0 # hatch-vcs derives the version from the tag
28
+ - name: Install uv
29
+ uses: astral-sh/setup-uv@v8.1.0
30
+ - name: Install Python 3.13
31
+ run: uv python install 3.13
32
+ - name: Build
33
+ run: uv build
34
+ - name: Smoke test (wheel)
35
+ run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
36
+ - name: Smoke test (source distribution)
37
+ run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
38
+ - name: Publish
39
+ run: uv publish
@@ -0,0 +1,14 @@
1
+ .idea*
2
+ .vscode*
3
+ .pytest*
4
+ __pycache__
5
+ dist*
6
+ build*
7
+ *venv*
8
+ *.egg-info
9
+ .env*
10
+ _version.py
11
+ wordlist.txt
12
+ .ipynb_checkpoints
13
+ .coverage
14
+ /site/
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2025 Cumulocity GmbH
2
+
3
+ # Read the Docs configuration file
4
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
5
+
6
+ version: 2
7
+
8
+ build:
9
+ os: ubuntu-22.04
10
+ tools:
11
+ python: "3.11"
12
+
13
+ python:
14
+ install:
15
+ - method: pip
16
+ path: .
17
+ extra_requirements:
18
+ - filters
19
+ - pandas
20
+ - requirements: docs/requirements.txt
21
+
22
+ mkdocs:
23
+ configuration: mkdocs.yaml
@@ -0,0 +1,473 @@
1
+ # Changelog
2
+
3
+ ### Features
4
+
5
+ * Migrated the entire library to `asyncio` using highly optimized `httpio` and `orjson` libraries under the hood.
6
+
7
+ * All model objects are now fully based on and compatible to the actual JSON data. The pure JSON representation is
8
+ available via the commonly available `json` property. Key fields (like `id`, or `creation_date` are still promoted
9
+ as class attributes, all other fragments can be read using the universal `get` function and `[]` operator.
10
+
11
+ * Added `workers` parameter to most query-like functions (`select`, `get_all`, `delete_by`, ...) and bulk operations
12
+ (`create`, `update`, `apply_to`, `delete`, ...) to automatically perform the activities unordered and in parallel.
13
+
14
+ * Added the `expression` parameter to all query-like functions (`select`, `get_all`, `delete_by`, ...) for consistency.
15
+
16
+ * Added `send_to` function to Operations API to send an operation to a collection of devices.
17
+
18
+ * Added functions `get_tenant_options` and `get_current_tenant_options` to Applications API.
19
+
20
+
21
+ ### Breaking changes
22
+
23
+ #### Major changes
24
+
25
+ * The `c8y_api` and `c8y_tk` modules have been merged into a single `pyc8y` module which integrates pure API calls
26
+ with auxiliary functionality in a single, sound SDK design. The project name was changed to _Cumulocity Python SDK_
27
+ accordingly. The PyPI entry was changed to `pyc8y`.
28
+
29
+ * The somewhat magic _dot notation_ access (`object.fragment.field`) has been removed to reduce complexity and increase
30
+ transparency. Custom fields and fragments can only be addressed using the index operator `[]` or the `get` function.
31
+ Both support dot/path notation within (`object.get("fragment.field")` or `object["fragment.field"]`). The `get`
32
+ functions allows the definition of a proper default value whereas the `[]` index operator will raise a `KeyError`
33
+ if any part of the specified path is not available.
34
+
35
+ * Immutable lists. In any object read from Cumulocity lists/arrays are _considered_ immutable. To extend a list it
36
+ needs to be overwritten. This is in conformance with Cumulocity's data model in which an attribute cannot be altered
37
+ but only overwritten with the new value resp. structure.
38
+
39
+ * The module now being exclusively async, the `AsyncListener` and `AsyncQueueListener` have been renamed to `Listener`
40
+ and `QueueListener`. The synchronous variants have been dropped.
41
+
42
+ * The `GlobalRole` class has been renamed to `UserGroup` to match the REST API naming. TODO: global_roles API alias?
43
+ Likewise, the `permission_ids` property has been renamed to `role_ids`. `add_permissions` to `assign_roles` etc.
44
+
45
+ * The `level` attribute in the `Permission` class has been renamed to `permission` to match the JSON structure.
46
+
47
+ * Inventory role assignments are not part of the `Users` class, moved from `InventoryRoles` because the API logically
48
+ belongs to users and role assignments cannot be created without a user reference.
49
+
50
+ * The `SubscriptionListener` listener implementation has been promoted to a standard component. It has been simplified
51
+ and converted to run async callbacks. It can be created from `MultiTenantCumulocityApp` using the `create_listener`
52
+ function.
53
+
54
+ Percentage -> Percent
55
+
56
+
57
+ #### Minor changes
58
+
59
+ * All ID are now required to be `string`s. Integers are no longer supported.
60
+
61
+ * Default page size is now a reasonable 100 throughout the SDK. Also, a default limit of 5 is applied to ease use in
62
+ interactive ("quick grab") scenarios. Be sure to define proper limits and page sizes in production use.
63
+
64
+ * Object-oriented `update` and `reload` now automatically update the `self` object as well. They feature a new `copy`
65
+ parameter to return a new instance and leave self as-is if needed.
66
+
67
+ * Cumulocity objects featuring a last updated date: The Python attributes were renamed to
68
+ `update_time`/`update_datetime` (previously `updated_time`/`updated_datetime`).
69
+
70
+ * Throughout the SDK additional parameters to the constructors (`__init__`) and query-like functions (`select`,
71
+ `get_all`, `count`, etc.) now need to be named to enforce a better coding style and forward compatibility.
72
+
73
+ * The Identity classes' `create` and `delete` functions now also allow bulk creation/deletion to stay conform to the
74
+ rest of the model classes. Direct creation and deletion of an individual external ID therefor now requires named
75
+ parameters.
76
+
77
+ * Auxiliary enumerations have been moved to be top-level classes and have been renamed accordingly:
78
+ - `Operation.Status` to `OperationStatus`
79
+ - `BulkOperation.Status` to `BulkStatus`, `BulkOperation.GeneralStatus` to `GeneralBulkStatus`
80
+
81
+ * In the tenant options API, functions `TenantOptions.delete_by` and `TenantOptions.update_by` are discontinued. Use
82
+ functions `delete` and `update_values` instead. The `get_all_mapped` function was optimized and replaced by function
83
+ `get_values`.
84
+
85
+
86
+ * The `UserG`
87
+
88
+ * In the Binary API, the
89
+
90
+
91
+
92
+
93
+ ## Version 3.7.2
94
+
95
+ * Switched to MkDocs for documentation.
96
+ * Fixed [Issue #91](https://github.com/Cumulocity-IoT/cumulocity-python-api/issues/91)
97
+ * Fixed [issue #92](https://github.com/Cumulocity-IoT/cumulocity-python-api/issues/92)
98
+
99
+ ## Version 3.7.1
100
+
101
+ * Adding `clear_tenant_cache` function to `MultiTenantCumulocityApp` to explicitly wipe unsubscribed tenants.
102
+ * Fixed [Issue #87](https://github.com/Cumulocity-IoT/cumulocity-python-api/issues/87)
103
+
104
+ ## Version 3.7.0
105
+
106
+ * Adding `aggregation_function` and `aggregation_interval` parameters to the `Measurements.get_series` function
107
+ to support the latest series aggregation features as described in the
108
+ [Cumulocity OpenAPI Documentation](https://cumulocity.com/api/core/#operation/getMeasurementSeriesResource).
109
+
110
+ ## Version 3.6.0
111
+
112
+ * Fixed a bug in `get_count` for when _no_ additional filter parameter was provided.
113
+ * Switching to `withTotalElements` instead of `withTotalPages` in `get_count` implementations.
114
+ * Adding `select`, `get_all` and `get_count` functions to Binaries API and Operations API.
115
+ * Adding `c8y_tk.analytics.parallel` module and `ParallelExecutor` class which can be used to reduce I/O wait
116
+ time through concurrent API requests and asynchronous result collection.
117
+
118
+ ## Version 3.5.1
119
+
120
+ * Fixing imports for situations where client-side filtering libraries are not imported. The library supports
121
+ optional dependncy definitions: `c8y_api[filters]` to support all available filters, `c8y_api[pydf]`,
122
+ `c8y_api[jmespath]`, and `c8y_api[jsonpath]` to support PyDF, JMESPath or JSONPath accordingly.
123
+ * Harmonizing page size and limit - the page size of a query should never exceed a given limit (as this would
124
+ be pointless). This feature also allows just specifying the limit for a query, the page size will
125
+ automatically be adjusted.
126
+
127
+ ## Version 3.5.0
128
+
129
+ * Added client-side filtering to many of the standard API (wherever sensibly applicable); These APIs `select`
130
+ and `get_all` functions now feature optional `include` and `exclude` parameters which can be used to filter
131
+ the results before being wrapped into Python objects; Added multiple matchers including a JSONPath matcher
132
+ a JMESPath matcher and a PyDF (Python Display Filter) matcher with PyDF as default.
133
+
134
+ ## Version 3.4.0
135
+
136
+ * Added `QueueListener` and `AsyncQueueListener` classes to the Notification 2.0 toolkit. These pre-defined
137
+ listener implementation append new notifications to standard queues that can be monitored/listened to which
138
+ makes Notification 2.0 solutions even simpler to implement.
139
+ * Updated and rewrote Notification 2.0 listener implementation. Added additional parameters for more control:
140
+ `consumer_name`, `shared`, `auto_ack` and `auto_unsubscribe`. Added `unsubscribe` function for removing
141
+ subscribers on demand. Both `AsyncListener` and `Listener` now provide consistent `start`/`stop` functions
142
+ which take care of coroutine and thread creation. The `listen ` function can still be invoked directly if
143
+ necessary.
144
+
145
+ ## Version 3.3.0
146
+
147
+ * Added `get_by` function to inventory API to return a single object by query.
148
+ * Added `CumulocityApp` class to module `c8y_tk.app` which allows working with Cumulocity interactively, e.g. in a
149
+ Jupyther notebook. It will deal with environment variables just like the other connection helpers but will also
150
+ ask interactively for missing info, e.g. a second factor with 2FA. It also integrates well with the
151
+ [c8y-go-cli](https://goc8ycli.netlify.app/) tool.
152
+ * Added `c8y_tk.app` packages with `SubscriptionListener` class to ease development of multi_tenant microservices
153
+ which need to act on all subscribed tenants or on added/removed subscriptions alike.
154
+ * Adding debug logs to base API as default urllib3 logs are not helpful for our purpose.
155
+ * Single and multi tenant applications now automatically set the `application_key` property from the standard
156
+ `APPLICATION_KEY` environment variable.
157
+ * Added `get_count` function to `Operations` API.
158
+ * Added `as_values` parameter to `get_all` and `select` functions of the Inventory, DeviceInventory,
159
+ DeviceGroupInventory, Events, Alarms, Users, Operations, and AuditRecords API.
160
+ * Added code coverage reporting to `test` target for _invoke_.
161
+ * Updated `as_tuple` for complex objects as well as the `as_values` parameter for `select`
162
+ and `get_all` functions to work with strings or 2-tuples. The use of a dictionary
163
+ was removed as dictionaries don't define an order.
164
+ * Added `as_values` parameter to the Measurements API `select` and `get_all` functions.
165
+ * Adding `c8y_tk.analytics` package with `to_numpy`, `to_series` and `to_data_frame` functions to
166
+ ease incorporating Cumulocity data into standard analytics pipelines.
167
+
168
+ ## Version 3.2.1
169
+
170
+ * Some essential fixes and improvements for dealing with measurements and series.
171
+
172
+ ## Version 3.2
173
+
174
+ * Added a `as_tuple` function to all complex objects which can be used to extract multiple nested values
175
+ as a tuple using path-like expressions (complementing the generic `get` function).
176
+ * Added `as_tuples` parameter to `select` and `get_all` functions in all inventory API as well
177
+ as Events and Alarms API. This parameter can be used to directly extract specific values from
178
+ the results instead of parsing the JSON.
179
+ * Added `reload` function to inventory object classes
180
+ * Added `delete_tree` function to inventory object classes, implicitly using `cascade` or
181
+ `forceCascade` parameters depending on the use case.
182
+ * Added `__repr__` function to relevant object classes.
183
+ * Removed redundant `util.py` file which impeded importing.
184
+
185
+ ## Version 3.1.1
186
+
187
+ * Fixing project dependencies for older Python versions.
188
+
189
+ ## Version 3.1
190
+
191
+ * Adding support for Python 3.7 as this is still widely used in the industry. New code can now safely used with
192
+ Python 3.7 throughout Python 3.13. Added `invoke` task for docker-based tests with different Python versions.
193
+ * Greatly improved _dot notation_ access to all complex Cumulocity objects (Managed Objects, Events, Alarms,
194
+ Operations, etc.) This now also supports mixed access, e.g. `obj.fragment[3].sub["name"]`.
195
+ * Publicly releasing a generic `get` function to complex objects which allows accessing a nested value without
196
+ the need to check for null values, e.g. `obj.get('fragment.sub.name', default='N/A')`.
197
+
198
+ ## Version 3
199
+
200
+ * Unified query behaviour of all API classes (introducing potentially breaking changes as the order of parameters needed to change).
201
+ * Added support for arbitrary expressions and kwargs on almost all select functions defined at the API classes, e.g. for Measurements, Events, Alarms, Inventory, etc. Using the expression parameter (always the first in all select-like functions that support it), an arbitrary query expression can be defined which will be forwarded to the REST API as-is. Using kwargs, additional maybe undocumented or deprecated parameters can be defined.
202
+ * Additional, undocumented select parameters will automatically be converted to Pascal case (e.g. my_undocumented_arg will be translated to myUndocumentedArg).
203
+ * Incorporated pull request to remove dependency on deprecated pkg_resources package (thanks @reubenmiller).
204
+ * Incorporated pull request to support context handlers.
205
+ * Many additional unit tests and integration tests.
206
+ * Fixed issue [#63](https://github.com/Cumulocity-IoT/cumulocity-python-api/issues/63) (tenant option select function did not filter categories correctly).
207
+
208
+
209
+ ## Version 2.1
210
+
211
+ * Added support for processing mode on all API base classes
212
+ * Added support for Cookie-based auth on OAI-only tenants
213
+ * Added latest extensions for Notification 2.0 API including `count` function.
214
+ * Switch to Python version 3.10
215
+
216
+
217
+ ## Version 2.0
218
+
219
+ * Added Changes support to the Audit API.
220
+ * Fixed Issue #53 "KeyError when retrieving 'bulkOperation'"; bulk operations JSON is somewhat _non-standard_ as
221
+ the root element is not named like the corresponding REST resource.
222
+ * Added proper support for the CurrentUser API; this is a breaking change as some functions moved from the User API
223
+ to the CurrentUser API (the correct place).
224
+ * Added support for 2FA at user level; TFA/TOTP can be enabled for individual users. Parts of this functionality,
225
+ e.g. getting the TOTP secret are only available at the CurrentUser level
226
+ * Adding traditional date filter parameter names (date_from and date_to in addition to before/after) to Events
227
+ and Alarms API.
228
+
229
+
230
+ ## Version 1.10
231
+
232
+ * The `select` and `get_all` functions now feature an `expression` parameter which allows to directly specify the entire REST API filtering expression.
233
+ * Fixed, unified and streamlined the behavior or the `query` parameter within all `select` and `get_all` functions.
234
+ * The `apply_to` functions now allow to specify the to-be-applied changes directly in JSON.
235
+ * Various tiny code and documentation improvements.
236
+ * Updated GitHub Actions to latest Node versions.
237
+ * Fixed build dependencies.
238
+
239
+
240
+ ## Version 1.9.2
241
+
242
+ * Testing code improvements.
243
+ * Added support for signed, shared and non-persistent Notification 2.0 subscriptions and tokens (Thanks @wilbersl!)
244
+ * Fixed audit record parsing.
245
+ * Various code and documentation improvements.
246
+ * Added support for token-based authentication for interactive sessions.
247
+ * Added page_number parameter to inventory queries to be able to pull a specific page.
248
+ * Added get_count functions to inventory to estimate expected number of results.
249
+ * Added get_subscribers function MultiTenantCumulocityApp.
250
+
251
+
252
+ ## Version 1.9.1
253
+
254
+ * Minor improvements and fixes.
255
+ * Added possibility to pull a specific result page to all `select` and `get_all` functions.
256
+
257
+
258
+ ## Version 1.9.0
259
+
260
+ * Added support for inventory endpoints `/availability`, `/supportedMeasurements` and `/supportedSeries`.
261
+
262
+ * Added `Units` class to support explicit modelling of measurement fragments.
263
+
264
+ * Added support for the Current Application API (current application settings, current application subscriptions).
265
+
266
+ * Added test fixture (`app_factory`)to `conftest.py` to register (and automatically unregister) a dedicated
267
+ microservice application for advanced integration testing.
268
+
269
+ * Making websocket ping interval explicit and updating it to 60 seconds by default.
270
+
271
+
272
+ ## Version 1.8.2
273
+
274
+ * Bumped flask from 2.2.2 to 2.3.2 (vulnerability)
275
+
276
+ Bumped python-dateutil from 2.8.1 to 2.8.2 (pandas requirement)
277
+
278
+ * Added `is_tls` property to `CumulocityRestApi` class;
279
+
280
+ fixed secure protocol handling for Notification2 websocket connections.
281
+
282
+ * Microservice build support improvements.
283
+
284
+
285
+ ## Version 1.8.1
286
+
287
+ * Fixed series value collection for incomplete series.
288
+
289
+
290
+ ## Version 1.8
291
+
292
+ * Adding support for measurement series queries.
293
+
294
+ ## Version 1.7
295
+
296
+ * Adding support for the Audit API.
297
+
298
+ * Added support for event attachment handling.
299
+
300
+ * Adding support for bulk operations.
301
+
302
+ ## Version 1.6.1
303
+
304
+ * Adding `c8y_tk` namespace to distribution.
305
+
306
+ ## Version 1.6
307
+
308
+ * Added API support for Notification 2.0 subscriptions and tokens.
309
+
310
+ * Added new package c8y_tk for additional features.
311
+
312
+ * Added synchronous and asynchronous Notification 2.0 websocket listener,
313
+ Added two (async/sync) Notification 2.0 samples.
314
+
315
+ ## Version 1.5
316
+
317
+ * Improved Applications API.
318
+
319
+ * Added microservice utilities for easier testing of provided samples.
320
+
321
+ * Added Tenant Options API support.
322
+
323
+ ## Version 1.4
324
+
325
+ * Fixed https://github.com/SoftwareAG/cumulocity-python-api/issues/25
326
+ The SimpleTenantApp did not include the tenant ID into the username which is not supported
327
+ by all Cumulocity instances.
328
+
329
+ * Adding class _QueryUtil, bundling query encoding related functionality.
330
+
331
+ * Added tests for special character parsing.
332
+
333
+ * Fixed handling and documentation of inventory API for querying by name.
334
+ Added query parameter for specification of custom queries.
335
+
336
+ * Reverted changes in ComplexObject - a ComplexObject is not a dictionary-like class, it only
337
+ supports some dictionary-like access functions. But, for instance, updating a ComplexObject
338
+ is very different from updating a dictionary. Hence, it no longer inherits MutableMapping.
339
+
340
+ ## Version 1.3.2
341
+
342
+ ### Changed
343
+
344
+ * Obfuscated internal properties in _DictWrapper which blocked standard dictionary behavior.
345
+ Code cleanup.
346
+
347
+ * ComplexObject & _DictMapping now both inherit MutableMapping (Thanks Sam!).
348
+
349
+ * The base API now ignores trailing slashes gracefully.
350
+
351
+
352
+ ## Version 1.3.1
353
+
354
+ ### Changed
355
+
356
+ * Switched to version 2.4.0 of PyJWT as recommended by https://nvd.nist.gov/vuln/detail/CVE-2022-29217
357
+
358
+
359
+ ## Version 1.3
360
+
361
+ ### Changed
362
+
363
+ * All objects with fragments can now be converted to Pandas Series (Thanks Sam!).
364
+
365
+ ### Added
366
+
367
+ * Added support for operations (Thanks Alex!).
368
+
369
+ * Added support for lastUpdated field in alarms and events.
370
+
371
+
372
+ ## Version 1.2
373
+
374
+ ### Changed
375
+
376
+ * Changed behavior of Events and Alarms API. Previously, an undefined event/alarm time was set to the current datetime
377
+ when invoking the `.create` function on the object. This was handy but inconsistent to the REST API behavior and
378
+ therefore removed. Instead, the constructor can now be invoked with `time='now'` as a shorthand. The `time` field
379
+ is never set to a default value automatically.
380
+
381
+ * Added `samples` folder to linting task.
382
+
383
+ * Added device agent registration sample (Thanks Nick!).
384
+
385
+
386
+ ## Version 1.1.1
387
+
388
+ ### Added
389
+
390
+ * Added Multi-Tenant sample script (`samples/multi_tenant_app.py`).
391
+
392
+ * Added task `build-ms` task and corresponding script files to generate Cumulocity microservices from sample scripts.
393
+
394
+ ### Fixes
395
+
396
+ * Fixed authentication (username must include tenant ID) for subscribed tenants in multi-tenant scenarios.
397
+
398
+ * Fixed pylint dependency in `requirements.txt`.
399
+
400
+ * Added `cachetools` to library dependencies in `setup.cfg`.
401
+
402
+
403
+ ## Version 1.1
404
+
405
+ ### Notes
406
+
407
+ * _Warning_, this release is a breaking change as it introduces an `auth` parameter to the API base classes,
408
+ `CumulocityRestAPI` and `CumulocityAPI`. This parameter should be the new standard to use (instead of just
409
+ username and password).
410
+
411
+ * _Warning_, this release replaces the 'all-purpose' class `CumulocityApp` with specialized versions for multi-tenant
412
+ (`MultiTenantCumulocityApp`) and single tenant (`SimpleCumulocityApp`) environments.
413
+
414
+ ### Added
415
+
416
+ * Added `_util.py` file to hold all cross-class auxiliary functionality.
417
+
418
+ * Added `_auth.py` file to hold all cross-class authentication functionality. Moved corresponding code from file
419
+ `app.__init__.py` to the `AuthUtil` class.
420
+
421
+ * Added `_jwt.py` with `JWT` class which encapsulates JWT handling for the libraries purpose. This is _not_ a full
422
+ JWT implementation.
423
+
424
+ * Added `HTMLBearerAuth` class which encapsulates Cumulocity's JWT token-based authentication mechanism.
425
+
426
+ * Added token-based authentication support. All API classes now can be initialized with an AuthBase parameter which
427
+ would allow all kinds of authentication mechanisms. As of now, `HTTPbasicAuth` and `HTTPBearerAuth` is supported.
428
+
429
+ * Added caching with TTL/Max Size strategies to `MultiTenantCumulocityApp` and `SimpleCumulocityApp`.
430
+
431
+ * Added samples: `user_sessions.py` illustrating how user sessions can be obtained and `simple_tenant_app.py`
432
+ illustrating how the `SimpleCumulocityApp` class is used.
433
+
434
+ * Added requirements: `cachetools` (for caching), `inputtimeout` and `flask` (for samples).
435
+
436
+ ### Changed
437
+
438
+ * Fixed file opening in `post_file` function in `_base_api.py` to avoid files already being closed when posting.
439
+
440
+ * Removed class `CumulocityApp` as it was too generic and hard to use. Replaces with classes `SimpleCumulocityApp`
441
+ which behaves pretty much identical and `MultiTenantCumulocityApp` which behances more like a factory.
442
+
443
+
444
+ ## Version 1.0.2
445
+
446
+ ### Changed
447
+
448
+ * Added this changelog :-)
449
+
450
+ * Fixed [Issue #7](https://github.com/SoftwareAG/cumulocity-python-api/issues/7):
451
+ Improved caching and user experience when creating CumulocityApp instances. Added unit tests.
452
+
453
+ * Added possibility to resolve the tenant ID from authorization headers (both `Basic` and `Bearer`).
454
+
455
+
456
+ ## Version 1.0.1
457
+
458
+ ### Changed
459
+
460
+ * The cumulocity-pyton-api library is now available on [PyPI](https://pypi.org) under the name `c8y_api` (see https://pypi.org/project/c8y-api/)
461
+ * Updated README to reflect installation from PyPI
462
+
463
+
464
+ ## Version 1.0
465
+
466
+ Major refactoring of beta version:
467
+ * Unified user experience
468
+ * Complete documentation
469
+ * Performance improvements
470
+ * Introduced `CumulocityApp` to avoid mix-up with `CumulocityApi`
471
+ * Complete unit tests
472
+ * Structured integration tests
473
+ * Removed samples (sorry, need to be re-organized)