ops 3.5.2__tar.gz → 3.7.0__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.
- {ops-3.5.2 → ops-3.7.0}/CHANGES.md +70 -0
- {ops-3.5.2 → ops-3.7.0}/HACKING.md +3 -0
- {ops-3.5.2 → ops-3.7.0}/PKG-INFO +4 -4
- {ops-3.5.2 → ops-3.7.0}/README.md +1 -1
- {ops-3.5.2 → ops-3.7.0}/STYLE.md +8 -0
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/_main.py +1 -1
- {ops-3.5.2 → ops-3.7.0}/ops/_private/harness.py +15 -11
- {ops-3.5.2 → ops-3.7.0}/ops/charm.py +2 -2
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/framework.py +2 -2
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/hookcmds/_types.py +1 -1
- {ops-3.5.2 → ops-3.7.0}/ops/log.py +2 -2
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/model.py +23 -15
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/pebble.py +27 -27
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/storage.py +2 -2
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/testing.py +2 -2
- {ops-3.5.2/test/charms/test_main/lib → ops-3.7.0}/ops/version.py +1 -1
- {ops-3.5.2 → ops-3.7.0}/ops.egg-info/PKG-INFO +4 -4
- {ops-3.5.2 → ops-3.7.0}/ops.egg-info/requires.txt +2 -2
- {ops-3.5.2 → ops-3.7.0}/pyproject.toml +42 -5
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/_main.py +1 -1
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/_private/harness.py +15 -11
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/charm.py +2 -2
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/framework.py +2 -2
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/hookcmds/_types.py +1 -1
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/log.py +2 -2
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/model.py +23 -15
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/pebble.py +27 -27
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/storage.py +2 -2
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/testing.py +2 -2
- {ops-3.5.2 → ops-3.7.0/test/charms/test_main/lib}/ops/version.py +1 -1
- {ops-3.5.2 → ops-3.7.0}/test/test_model.py +11 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_model_relation_data_class.py +53 -12
- {ops-3.5.2 → ops-3.7.0}/test/test_pebble.py +6 -8
- {ops-3.5.2 → ops-3.7.0}/tox.ini +3 -1
- {ops-3.5.2 → ops-3.7.0}/AGENTS.md +0 -0
- {ops-3.5.2 → ops-3.7.0}/CODE_OF_CONDUCT.md +0 -0
- {ops-3.5.2 → ops-3.7.0}/CONTRIBUTING.md +0 -0
- {ops-3.5.2 → ops-3.7.0}/LICENSE.txt +0 -0
- {ops-3.5.2 → ops-3.7.0}/MANIFEST.in +0 -0
- {ops-3.5.2 → ops-3.7.0}/SECURITY.md +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/_private/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/_private/timeconv.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/_private/yaml.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_action.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_other.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_port.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_relation.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_secret.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_state.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_status.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_storage.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/hookcmds/_utils.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/jujucontext.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/jujuversion.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/lib/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/main.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops/py.typed +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops.egg-info/SOURCES.txt +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops.egg-info/dependency_links.txt +0 -0
- {ops-3.5.2 → ops-3.7.0}/ops.egg-info/top_level.txt +0 -0
- {ops-3.5.2 → ops-3.7.0}/setup.cfg +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/benchmark/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/bin/relation-ids +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/bin/relation-list +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/actions.yaml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/config.yaml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/_private/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/_private/timeconv.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/_private/yaml.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_action.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_other.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_port.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_relation.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_secret.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_state.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_status.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_storage.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/hookcmds/_utils.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/jujucontext.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/jujuversion.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/lib/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/main.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/lib/ops/py.typed +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/metadata.yaml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_main/src/charm.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_relation/.gitignore +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_relation/charmcraft.yaml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_relation/pyproject.toml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_relation/src/charm.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_secrets/.gitignore +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_secrets/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_secrets/charmcraft.yaml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_secrets/pyproject.toml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_secrets/src/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_secrets/src/charm.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_smoke/.gitignore +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_smoke/README.md +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_smoke/metadata.yaml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_smoke/reference-pyproject.toml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_smoke/src/charm.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_tracing/.gitignore +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_tracing/charmcraft.yaml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_tracing/pyproject.toml +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/charms/test_tracing/src/charm.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/conftest.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/fake_pebble.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/integration/__init__.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/integration/conftest.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/integration/test_relation.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/integration/test_secrets.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/integration/test_tracing.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/pebble_cli.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/smoke/test_smoke.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_charm.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_framework.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_helpers.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_hookcmds.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_infra.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_jujucontext.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_jujuversion.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_lib.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_log.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_main.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_main_invocation.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_main_type_hint.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_real_pebble.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_storage.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_testing.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_timeconv.py +0 -0
- {ops-3.5.2 → ops-3.7.0}/test/test_yaml.py +0 -0
|
@@ -1,3 +1,73 @@
|
|
|
1
|
+
# 3.7.0 - 30 March 2026
|
|
2
|
+
|
|
3
|
+
## Features
|
|
4
|
+
|
|
5
|
+
* Enable interactive debugging via `breakpoint` in testing (#2363)
|
|
6
|
+
* ops.testing autoload support for charmcraft extensions (#2367)
|
|
7
|
+
* Allow testing.State.get_relation to accept relation objects (#2359)
|
|
8
|
+
* Support charmcraft.yaml format as meta for testing.Context (#2296)
|
|
9
|
+
|
|
10
|
+
## Fixes
|
|
11
|
+
|
|
12
|
+
* Correct type annotation for StorageMeta.properties (#2348)
|
|
13
|
+
* Move the testing.Container compatibility import so that mypy style checkers understand it (#2343)
|
|
14
|
+
* Hold only copies of user provided meta/config/actions in testing.Context (#2349)
|
|
15
|
+
* Deep-copy layer objects during testing.State plan rendering (#2380)
|
|
16
|
+
* Return copies from testing.State secret_get and action_get (#2379)
|
|
17
|
+
* Use timezone-aware datetimes in expiry calculation (#2378)
|
|
18
|
+
* Warn before clearing non-empty container in testing (#2365)
|
|
19
|
+
|
|
20
|
+
## Documentation
|
|
21
|
+
|
|
22
|
+
* Replace links to juju.is by canonical.com/juju (#2368)
|
|
23
|
+
* Refactor homepage to better put Ops in context (#2370)
|
|
24
|
+
* Add pytest-operator migration guide from Jubilant docs (#2381)
|
|
25
|
+
* Add a tip about AI help in the Jubilant migration guide (#2382)
|
|
26
|
+
* Mention jhack scenario snapshot (#2351)
|
|
27
|
+
* Update integration testing how-to guide (#2390)
|
|
28
|
+
* Explain K8s charms briefly at the start of the tutorial (#2392)
|
|
29
|
+
* Juju secrets identifier is now an opaque string (#2387)
|
|
30
|
+
|
|
31
|
+
## Tests
|
|
32
|
+
|
|
33
|
+
* Extend the type checking of the ops-scenario tests (#2230)
|
|
34
|
+
|
|
35
|
+
## CI
|
|
36
|
+
|
|
37
|
+
* Run ruff check --fix in tox -e format (#2369)
|
|
38
|
+
* Check example charms with mypy in CI (#2360)
|
|
39
|
+
* Update the list of published charms in the compatibility tests (#2384)
|
|
40
|
+
* Adjust minimum Python version in broad charm compatibility tests (#2317)
|
|
41
|
+
|
|
42
|
+
# 3.6.0 - 26 February 2026
|
|
43
|
+
|
|
44
|
+
## Features
|
|
45
|
+
|
|
46
|
+
* Bump default Juju version in `ops.testing.Context` to 3.6.14 (#2316)
|
|
47
|
+
|
|
48
|
+
## Fixes
|
|
49
|
+
|
|
50
|
+
* Correct the `Model.get_binding()` return type (#2329)
|
|
51
|
+
* Only show executable in `ExecError.__str__`, not full command line (#2336)
|
|
52
|
+
* Support Pydantic `MISSING` sentinel in `ops.Relation.save` (#2306)
|
|
53
|
+
|
|
54
|
+
## Documentation
|
|
55
|
+
|
|
56
|
+
* Add how-to subcategory for managing containers (#2309)
|
|
57
|
+
* Remove 2.19 version in docs, tweak ops.testing title (#2332)
|
|
58
|
+
* Use "true" and "false" consistently in the reference documentation (#2330)
|
|
59
|
+
* Add CLI args as another place to not put sensitive data (#2334)
|
|
60
|
+
* Fix remote unit kwarg in testing example (#2342)
|
|
61
|
+
* Clarify that secret labels are not names (#2337)
|
|
62
|
+
|
|
63
|
+
## Tests
|
|
64
|
+
|
|
65
|
+
* Set `SCENARIO_BARE_CHARM_ERRORS=true` in Ops tests that care (#2314)
|
|
66
|
+
|
|
67
|
+
## CI
|
|
68
|
+
|
|
69
|
+
* Fix releasing on branches with no `versions.md` doc (#2323)
|
|
70
|
+
|
|
1
71
|
# 3.5.2 - 11 February 2026
|
|
2
72
|
|
|
3
73
|
## Fixes
|
|
@@ -18,6 +18,9 @@ uv tool install tox --with tox-uv
|
|
|
18
18
|
uv tool update-shell
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
Optionally, to run checks automatically before each commit, install
|
|
22
|
+
[pre-commit](https://pre-commit.com/#install) and run `pre-commit install`.
|
|
23
|
+
|
|
21
24
|
You can validate that you have a working installation by running:
|
|
22
25
|
|
|
23
26
|
```sh
|
{ops-3.5.2 → ops-3.7.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ops
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.7.0
|
|
4
4
|
Summary: The Python library behind great charms
|
|
5
5
|
Author: The Charm Tech team at Canonical Ltd.
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -22,9 +22,9 @@ Requires-Dist: PyYAML==6.*
|
|
|
22
22
|
Requires-Dist: websocket-client==1.*
|
|
23
23
|
Requires-Dist: opentelemetry-api~=1.0
|
|
24
24
|
Provides-Extra: testing
|
|
25
|
-
Requires-Dist: ops-scenario==8.
|
|
25
|
+
Requires-Dist: ops-scenario==8.7.0; extra == "testing"
|
|
26
26
|
Provides-Extra: tracing
|
|
27
|
-
Requires-Dist: ops-tracing==3.
|
|
27
|
+
Requires-Dist: ops-tracing==3.7.0; extra == "tracing"
|
|
28
28
|
Provides-Extra: harness
|
|
29
29
|
Dynamic: license-file
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ Dynamic: license-file
|
|
|
32
32
|
|
|
33
33
|

|
|
34
34
|
|
|
35
|
-
The `ops` library is a Python framework for developing and testing Kubernetes and machine [charms](https://charmhub.io/). While charms can be written in any language, `ops` defines the latest standard, and charmers are encouraged to use Python with `ops` for all charms. The library is an official component of the Charm SDK, itself a part of [the Juju universe](https://
|
|
35
|
+
The `ops` library is a Python framework for developing and testing Kubernetes and machine [charms](https://charmhub.io/). While charms can be written in any language, `ops` defines the latest standard, and charmers are encouraged to use Python with `ops` for all charms. The library is an official component of the Charm SDK, itself a part of [the Juju universe](https://canonical.com/juju).
|
|
36
36
|
|
|
37
37
|
> - `ops` is [available on PyPI](https://pypi.org/project/ops/).
|
|
38
38
|
> - The latest version of `ops` requires Python 3.10 or above.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
The `ops` library is a Python framework for developing and testing Kubernetes and machine [charms](https://charmhub.io/). While charms can be written in any language, `ops` defines the latest standard, and charmers are encouraged to use Python with `ops` for all charms. The library is an official component of the Charm SDK, itself a part of [the Juju universe](https://
|
|
5
|
+
The `ops` library is a Python framework for developing and testing Kubernetes and machine [charms](https://charmhub.io/). While charms can be written in any language, `ops` defines the latest standard, and charmers are encouraged to use Python with `ops` for all charms. The library is an official component of the Charm SDK, itself a part of [the Juju universe](https://canonical.com/juju).
|
|
6
6
|
|
|
7
7
|
> - `ops` is [available on PyPI](https://pypi.org/project/ops/).
|
|
8
8
|
> - The latest version of `ops` requires Python 3.10 or above.
|
{ops-3.5.2 → ops-3.7.0}/STYLE.md
RENAMED
|
@@ -261,6 +261,14 @@ However, it's okay to use acronyms that are very well known in our domain, like
|
|
|
261
261
|
|
|
262
262
|
Choice of words: For example, if the whole document uses "mandatory", you probably shouldn't use "required" in a newly added paragraph. For another example, if the whole document uses "list foo" when adding new content, don't use "get a list of bar".
|
|
263
263
|
|
|
264
|
+
### Use "true"/"false" consistently in docstrings
|
|
265
|
+
|
|
266
|
+
When describing boolean parameters in docstrings:
|
|
267
|
+
|
|
268
|
+
- Use lowercase "true"/"false" (no backticks) for truth-y/falsy concepts: "if true, create parent directories".
|
|
269
|
+
- Use double-backtick-quoted `` ``True`` ``/`` ``False`` `` when referring to the Python objects themselves: "pass ``True`` to enable".
|
|
270
|
+
- Do not use bare "True"/"False" (capitalised without backticks).
|
|
271
|
+
|
|
264
272
|
### Be precise
|
|
265
273
|
|
|
266
274
|
Be precise in names and verbs. Use precise verbs to describe the behaviour. For example, the appropriate description of `/v1/services` is "list services", while "get a service" is probably a better fit for `/v1/services/{name}`.
|
|
@@ -212,7 +212,7 @@ class _Dispatcher:
|
|
|
212
212
|
self.event_name = name
|
|
213
213
|
|
|
214
214
|
def is_restricted_context(self):
|
|
215
|
-
"""Return True if we are running in a restricted Juju context.
|
|
215
|
+
"""Return ``True`` if we are running in a restricted Juju context.
|
|
216
216
|
|
|
217
217
|
When in a restricted context, most commands (relation-get, config-get,
|
|
218
218
|
state-get) are not available. As such, we change how we interact with
|
|
@@ -184,7 +184,7 @@ class ActionFailed(Exception): # noqa: N818 (name doesn't end with "Error")
|
|
|
184
184
|
state: State | None
|
|
185
185
|
"""The Juju state after the action has been run.
|
|
186
186
|
|
|
187
|
-
When using Harness.run_action, this will be None
|
|
187
|
+
When using Harness.run_action, this will be ``None``.
|
|
188
188
|
"""
|
|
189
189
|
|
|
190
190
|
def __init__(
|
|
@@ -450,7 +450,7 @@ class Harness(Generic[CharmType]):
|
|
|
450
450
|
should be active when the charm starts, and then call this method. This method will
|
|
451
451
|
automatically create and add peer relations that are specified in metadata.yaml.
|
|
452
452
|
|
|
453
|
-
If the charm metadata specifies containers, this sets can_connect to True for all
|
|
453
|
+
If the charm metadata specifies containers, this sets can_connect to ``True`` for all
|
|
454
454
|
containers (in addition to triggering pebble-ready for each).
|
|
455
455
|
|
|
456
456
|
Example::
|
|
@@ -801,8 +801,8 @@ class Harness(Generic[CharmType]):
|
|
|
801
801
|
Args:
|
|
802
802
|
storage_name: The storage backend name on the Charm
|
|
803
803
|
count: Number of disks being added
|
|
804
|
-
attach:
|
|
805
|
-
has been called a
|
|
804
|
+
attach: If true, also attach the storage mount; if :meth:`begin`
|
|
805
|
+
has been called a true value will also emit storage-attached
|
|
806
806
|
|
|
807
807
|
Return:
|
|
808
808
|
A list of storage IDs, e.g. ["my-storage/1", "my-storage/2"].
|
|
@@ -1646,7 +1646,7 @@ class Harness(Generic[CharmType]):
|
|
|
1646
1646
|
do/don't trigger extra calls.
|
|
1647
1647
|
|
|
1648
1648
|
Args:
|
|
1649
|
-
reset: If
|
|
1649
|
+
reset: If true, reset the calls list back to empty, if false, the call list is
|
|
1650
1650
|
preserved.
|
|
1651
1651
|
|
|
1652
1652
|
Return:
|
|
@@ -1859,7 +1859,7 @@ class Harness(Generic[CharmType]):
|
|
|
1859
1859
|
|
|
1860
1860
|
Args:
|
|
1861
1861
|
secret_id: The ID of the secret associated with the event.
|
|
1862
|
-
label: Label value to send to the event. If None
|
|
1862
|
+
label: Label value to send to the event. If ``None``, the secret's
|
|
1863
1863
|
label is used.
|
|
1864
1864
|
"""
|
|
1865
1865
|
secret = self._ensure_secret(secret_id)
|
|
@@ -1880,7 +1880,7 @@ class Harness(Generic[CharmType]):
|
|
|
1880
1880
|
secret_id: The ID of the secret associated with the event.
|
|
1881
1881
|
revision: Revision number to provide to the event. This should be
|
|
1882
1882
|
an item from the list returned by :meth:`get_secret_revisions`.
|
|
1883
|
-
label: Label value to send to the event. If None
|
|
1883
|
+
label: Label value to send to the event. If ``None``, the secret's
|
|
1884
1884
|
label is used.
|
|
1885
1885
|
"""
|
|
1886
1886
|
secret = self._ensure_secret(secret_id)
|
|
@@ -1901,7 +1901,7 @@ class Harness(Generic[CharmType]):
|
|
|
1901
1901
|
secret_id: The ID of the secret associated with the event.
|
|
1902
1902
|
revision: Revision number to provide to the event. This should be
|
|
1903
1903
|
an item from the list returned by :meth:`get_secret_revisions`.
|
|
1904
|
-
label: Label value to send to the event. If None
|
|
1904
|
+
label: Label value to send to the event. If ``None``, the secret's
|
|
1905
1905
|
label is used.
|
|
1906
1906
|
"""
|
|
1907
1907
|
secret = self._ensure_secret(secret_id)
|
|
@@ -2545,7 +2545,7 @@ class _TestingModelBackend:
|
|
|
2545
2545
|
|
|
2546
2546
|
Args:
|
|
2547
2547
|
name: name (i.e. from metadata.yaml).
|
|
2548
|
-
include_detached:
|
|
2548
|
+
include_detached: If true, include unattached storage mounts as well.
|
|
2549
2549
|
"""
|
|
2550
2550
|
return [
|
|
2551
2551
|
index
|
|
@@ -2599,7 +2599,11 @@ class _TestingModelBackend:
|
|
|
2599
2599
|
self._storage_attached[name].remove(index)
|
|
2600
2600
|
|
|
2601
2601
|
def _storage_attach(self, storage_id: str):
|
|
2602
|
-
"""Mark the named storage_id as attached
|
|
2602
|
+
"""Mark the named storage_id as attached.
|
|
2603
|
+
|
|
2604
|
+
Returns:
|
|
2605
|
+
``True`` if it was previously detached.
|
|
2606
|
+
"""
|
|
2603
2607
|
# NOTE: This is an extra function for _TestingModelBackend to simulate
|
|
2604
2608
|
# re-attachment of a storage unit. This is not present in
|
|
2605
2609
|
# ops.model._ModelBackend.
|
|
@@ -2910,7 +2914,7 @@ class _TestingModelBackend:
|
|
|
2910
2914
|
|
|
2911
2915
|
@classmethod
|
|
2912
2916
|
def _generate_secret_id(cls) -> str:
|
|
2913
|
-
# Not a proper Juju secrets
|
|
2917
|
+
# Not a proper Juju secrets identifier, but that's okay
|
|
2914
2918
|
return f'secret:{uuid.uuid4()}'
|
|
2915
2919
|
|
|
2916
2920
|
def secret_add(
|
|
@@ -2019,7 +2019,7 @@ class RelationMeta:
|
|
|
2019
2019
|
"""
|
|
2020
2020
|
|
|
2021
2021
|
optional: bool
|
|
2022
|
-
"""If
|
|
2022
|
+
"""If true, the relation is considered optional.
|
|
2023
2023
|
|
|
2024
2024
|
This value is informational only and is not used by Juju itself (all
|
|
2025
2025
|
relations are optional from Juju's perspective), but it may be set in
|
|
@@ -2079,7 +2079,7 @@ class StorageMeta:
|
|
|
2079
2079
|
multiple_range: tuple[int, int | None] | None
|
|
2080
2080
|
"""Range of numeric qualifiers when multiple storage units are used."""
|
|
2081
2081
|
|
|
2082
|
-
properties
|
|
2082
|
+
properties: list[str]
|
|
2083
2083
|
"""List of additional characteristics of the storage."""
|
|
2084
2084
|
|
|
2085
2085
|
def __init__(self, name: str, raw: _StorageMetaDict):
|
|
@@ -78,7 +78,7 @@ class Handle:
|
|
|
78
78
|
"""Handle defines a name for an object in the form of a hierarchical path.
|
|
79
79
|
|
|
80
80
|
The provided parent is the object (or that object's handle) that this handle
|
|
81
|
-
sits under, or None if the object identified by this handle stands by itself
|
|
81
|
+
sits under, or ``None`` if the object identified by this handle stands by itself
|
|
82
82
|
as the root of its own hierarchy.
|
|
83
83
|
|
|
84
84
|
The handle kind is a string that defines a namespace so objects with the
|
|
@@ -1231,7 +1231,7 @@ class StoredState:
|
|
|
1231
1231
|
Data is stored alongside the charm (in the charm container for Kubernetes
|
|
1232
1232
|
sidecar charms, and on the machine for machine charms). The exceptions are
|
|
1233
1233
|
two deprecated cases: Kubernetes podspec charms, and charms explicitly
|
|
1234
|
-
passing
|
|
1234
|
+
passing ``True`` for ``use_juju_for_storage`` when running :meth:`ops.main`.
|
|
1235
1235
|
|
|
1236
1236
|
For machine charms, charms are upgraded in-place on the machine, so the data
|
|
1237
1237
|
is preserved. For Kubernetes sidecar charms, when the charm is upgraded, the
|
|
@@ -154,7 +154,7 @@ class CloudSpec:
|
|
|
154
154
|
"""Whether to skip TLS verification."""
|
|
155
155
|
|
|
156
156
|
is_controller_cloud: bool = False
|
|
157
|
-
"""If this is the cloud used by the controller, defaults to False
|
|
157
|
+
"""If this is the cloud used by the controller, defaults to ``False``."""
|
|
158
158
|
|
|
159
159
|
@classmethod
|
|
160
160
|
def _from_dict(cls, d: dict[str, Any]) -> CloudSpec:
|
|
@@ -61,8 +61,8 @@ def setup_root_logging(
|
|
|
61
61
|
|
|
62
62
|
Args:
|
|
63
63
|
model_backend: a ModelBackend to use for juju-log
|
|
64
|
-
debug: if
|
|
65
|
-
exc_stderr: if
|
|
64
|
+
debug: if true, write logs to stderr as well as to juju-log.
|
|
65
|
+
exc_stderr: if true, write uncaught exceptions to stderr as well as to juju-log.
|
|
66
66
|
"""
|
|
67
67
|
logger = logging.getLogger()
|
|
68
68
|
logger.setLevel(logging.DEBUG)
|
|
@@ -259,7 +259,7 @@ class Model:
|
|
|
259
259
|
"""
|
|
260
260
|
return self.relations._get_unique(relation_name, relation_id)
|
|
261
261
|
|
|
262
|
-
def get_binding(self, binding_key: str | Relation) -> Binding
|
|
262
|
+
def get_binding(self, binding_key: str | Relation) -> Binding:
|
|
263
263
|
"""Get a network space binding.
|
|
264
264
|
|
|
265
265
|
Args:
|
|
@@ -536,7 +536,7 @@ def _calculate_expiry(
|
|
|
536
536
|
if isinstance(expire, datetime.datetime):
|
|
537
537
|
return expire
|
|
538
538
|
elif isinstance(expire, datetime.timedelta):
|
|
539
|
-
return datetime.datetime.now() + expire
|
|
539
|
+
return datetime.datetime.now(tz=datetime.timezone.utc) + expire
|
|
540
540
|
else:
|
|
541
541
|
raise TypeError(
|
|
542
542
|
'Expiration time must be a datetime or timedelta from now, '
|
|
@@ -1382,7 +1382,7 @@ class Secret:
|
|
|
1382
1382
|
identifier for identifying one secret in a set of secrets of arbitrary
|
|
1383
1383
|
size, use :attr:`unique_identifier` -- this should be rare.)
|
|
1384
1384
|
|
|
1385
|
-
This will be None if the secret was obtained using
|
|
1385
|
+
This will be ``None`` if the secret was obtained using
|
|
1386
1386
|
:meth:`Model.get_secret` with a label but no ID.
|
|
1387
1387
|
"""
|
|
1388
1388
|
return self._id
|
|
@@ -1391,8 +1391,7 @@ class Secret:
|
|
|
1391
1391
|
def unique_identifier(self) -> str | None:
|
|
1392
1392
|
"""Unique identifier of this secret.
|
|
1393
1393
|
|
|
1394
|
-
This is the secret's globally-unique identifier (
|
|
1395
|
-
20-character Xid, for example "9m4e2mr0ui3e8a215n4g").
|
|
1394
|
+
This is the secret's globally-unique identifier (alphanumeric).
|
|
1396
1395
|
|
|
1397
1396
|
Charms should use :attr:`id` (the secret's locator ID) to send
|
|
1398
1397
|
the secret's ID across relation data, and labels (:attr:`label`) to
|
|
@@ -1401,7 +1400,7 @@ class Secret:
|
|
|
1401
1400
|
cases where the charm has a set of secrets of arbitrary size, for
|
|
1402
1401
|
example, a group of 10 or 20 TLS certificates.
|
|
1403
1402
|
|
|
1404
|
-
This will be None if the secret was obtained using
|
|
1403
|
+
This will be ``None`` if the secret was obtained using
|
|
1405
1404
|
:meth:`Model.get_secret` with a label but no ID.
|
|
1406
1405
|
"""
|
|
1407
1406
|
if self._id is None:
|
|
@@ -1445,7 +1444,7 @@ class Secret:
|
|
|
1445
1444
|
Juju will ensure that the entity (the owner or observer) only has one
|
|
1446
1445
|
secret with this label at once.
|
|
1447
1446
|
|
|
1448
|
-
This will be None if the secret was obtained using
|
|
1447
|
+
This will be ``None`` if the secret was obtained using
|
|
1449
1448
|
:meth:`Model.get_secret` with an ID but no label.
|
|
1450
1449
|
"""
|
|
1451
1450
|
return self._label
|
|
@@ -1873,6 +1872,10 @@ class Relation:
|
|
|
1873
1872
|
# data.destination will be stored under the Juju relation key 'to'
|
|
1874
1873
|
relation.save(data, self.unit)
|
|
1875
1874
|
|
|
1875
|
+
If a Pydantic model's ``model_dump`` method omits any field (e.g. if its
|
|
1876
|
+
value is Pydantic's ``MISSING`` sentinel) the field will be erased from
|
|
1877
|
+
the relation data.
|
|
1878
|
+
|
|
1876
1879
|
Args:
|
|
1877
1880
|
obj: an object with attributes to save to the relation data, typically
|
|
1878
1881
|
a Pydantic ``BaseModel`` subclass or dataclass.
|
|
@@ -1915,7 +1918,11 @@ class Relation:
|
|
|
1915
1918
|
values = {field: getattr(obj, field) for field in fields}
|
|
1916
1919
|
|
|
1917
1920
|
# Encode each value, and then pass it over to Juju.
|
|
1918
|
-
|
|
1921
|
+
# Missing values are erased from the databag using empty string values.
|
|
1922
|
+
data = {
|
|
1923
|
+
field: encoder(values[attr]) if attr in values else ''
|
|
1924
|
+
for attr, field in sorted(fields.items())
|
|
1925
|
+
}
|
|
1919
1926
|
self.data[dst].update(data)
|
|
1920
1927
|
|
|
1921
1928
|
|
|
@@ -2643,9 +2650,9 @@ class Container:
|
|
|
2643
2650
|
combining).
|
|
2644
2651
|
layer: A YAML string, configuration layer dict, or pebble.Layer
|
|
2645
2652
|
object containing the Pebble layer to add.
|
|
2646
|
-
combine: If combine is
|
|
2653
|
+
combine: If combine is false (the default), append the new layer
|
|
2647
2654
|
as the top layer with the given label (must be unique). If
|
|
2648
|
-
combine is
|
|
2655
|
+
combine is true and the label already exists, the two layers
|
|
2649
2656
|
are combined into a single one considering the layer override
|
|
2650
2657
|
rules; if the layer doesn't exist, it is added as usual.
|
|
2651
2658
|
"""
|
|
@@ -2798,7 +2805,7 @@ class Container:
|
|
|
2798
2805
|
encoding: Encoding to use for encoding source str to bytes, or
|
|
2799
2806
|
strings read from source if it is a TextIO type. Ignored if
|
|
2800
2807
|
source is bytes or BinaryIO.
|
|
2801
|
-
make_dirs: If
|
|
2808
|
+
make_dirs: If true, create parent directories if they don't exist.
|
|
2802
2809
|
permissions: Permissions (mode) to create file with (Pebble default
|
|
2803
2810
|
is 0o644).
|
|
2804
2811
|
user_id: User ID (UID) for file. If neither ``group_id`` nor ``group`` is provided,
|
|
@@ -3036,6 +3043,7 @@ class Container:
|
|
|
3036
3043
|
type=ftype,
|
|
3037
3044
|
size=info.st_size,
|
|
3038
3045
|
permissions=stat.S_IMODE(info.st_mode),
|
|
3046
|
+
# This is unused, but a required FileInfo field.
|
|
3039
3047
|
last_modified=datetime.datetime.fromtimestamp(info.st_mtime),
|
|
3040
3048
|
user_id=info.st_uid,
|
|
3041
3049
|
user=pw_name,
|
|
@@ -3130,7 +3138,7 @@ class Container:
|
|
|
3130
3138
|
|
|
3131
3139
|
Args:
|
|
3132
3140
|
path: Path of the directory to create on the remote system.
|
|
3133
|
-
make_parents: If
|
|
3141
|
+
make_parents: If true, create parent directories if they don't exist.
|
|
3134
3142
|
permissions: Permissions (mode) to create directory with (Pebble
|
|
3135
3143
|
default is 0o755).
|
|
3136
3144
|
user_id: User ID (UID) for directory. If neither ``group_id`` nor ``group``
|
|
@@ -3158,13 +3166,13 @@ class Container:
|
|
|
3158
3166
|
|
|
3159
3167
|
Args:
|
|
3160
3168
|
path: Path of the file or directory to delete from the remote system.
|
|
3161
|
-
recursive: If
|
|
3169
|
+
recursive: If true, and path is a directory, recursively delete it and
|
|
3162
3170
|
everything under it. If path is a file, delete the file. In
|
|
3163
3171
|
either case, do nothing if the file or directory does not
|
|
3164
3172
|
exist. Behaviourally similar to ``rm -rf <file|dir>``.
|
|
3165
3173
|
|
|
3166
3174
|
Raises:
|
|
3167
|
-
pebble.PathError: If a relative path is provided, or if
|
|
3175
|
+
pebble.PathError: If a relative path is provided, or if ``recursive`` is ``False``
|
|
3168
3176
|
and the file or directory cannot be removed (it does not exist or is not empty).
|
|
3169
3177
|
"""
|
|
3170
3178
|
self._pebble.remove_path(path, recursive=recursive)
|
|
@@ -4277,7 +4285,7 @@ class CloudSpec:
|
|
|
4277
4285
|
"""Whether to skip TLS verification."""
|
|
4278
4286
|
|
|
4279
4287
|
is_controller_cloud: bool = False
|
|
4280
|
-
"""If this is the cloud used by the controller, defaults to False
|
|
4288
|
+
"""If this is the cloud used by the controller, defaults to ``False``."""
|
|
4281
4289
|
|
|
4282
4290
|
@classmethod
|
|
4283
4291
|
def from_dict(cls, d: dict[str, Any]) -> CloudSpec:
|
|
@@ -540,9 +540,9 @@ class ExecError(Error, Generic[AnyStr]):
|
|
|
540
540
|
"""Standard error from the process.
|
|
541
541
|
|
|
542
542
|
If :meth:`ExecProcess.wait_output` was being called and ``combine_stderr``
|
|
543
|
-
was False
|
|
543
|
+
was ``False``, this is the captured stderr as a str (or bytes if encoding was
|
|
544
544
|
None). If :meth:`ExecProcess.wait` was being called or ``combine_stderr``
|
|
545
|
-
was True
|
|
545
|
+
was ``True``, this is None.
|
|
546
546
|
"""
|
|
547
547
|
|
|
548
548
|
def __init__(
|
|
@@ -558,7 +558,7 @@ class ExecError(Error, Generic[AnyStr]):
|
|
|
558
558
|
self.stderr = stderr
|
|
559
559
|
|
|
560
560
|
def __str__(self):
|
|
561
|
-
message = f'non-zero exit code {self.exit_code} executing {self.command!r}'
|
|
561
|
+
message = f'non-zero exit code {self.exit_code} executing {self.command[0]!r}'
|
|
562
562
|
|
|
563
563
|
for name, out in [('stdout', self.stdout), ('stderr', self.stderr)]:
|
|
564
564
|
if out is None:
|
|
@@ -1069,7 +1069,7 @@ class ServiceInfo:
|
|
|
1069
1069
|
self.current = current
|
|
1070
1070
|
|
|
1071
1071
|
def is_running(self) -> bool:
|
|
1072
|
-
"""Return True if this service is running (in the active state)."""
|
|
1072
|
+
"""Return ``True`` if this service is running (in the active state)."""
|
|
1073
1073
|
return self.current == ServiceStatus.ACTIVE
|
|
1074
1074
|
|
|
1075
1075
|
@classmethod
|
|
@@ -1425,7 +1425,7 @@ class CheckInfo:
|
|
|
1425
1425
|
level: CheckLevel | str | None
|
|
1426
1426
|
"""Check level.
|
|
1427
1427
|
|
|
1428
|
-
This can be :attr:`CheckLevel.ALIVE`, :attr:`CheckLevel.READY`, or None (level not set).
|
|
1428
|
+
This can be :attr:`CheckLevel.ALIVE`, :attr:`CheckLevel.READY`, or ``None`` (level not set).
|
|
1429
1429
|
"""
|
|
1430
1430
|
|
|
1431
1431
|
startup: CheckStartup
|
|
@@ -1453,7 +1453,7 @@ class CheckInfo:
|
|
|
1453
1453
|
:meth:`Client.start_checks`. It is reset to one when the check
|
|
1454
1454
|
succeeds after the check's failure threshold was reached.
|
|
1455
1455
|
|
|
1456
|
-
This will be None if the version of Pebble being queried doesn't return
|
|
1456
|
+
This will be ``None`` if the version of Pebble being queried doesn't return
|
|
1457
1457
|
the ``successes`` field (introduced in Pebble v1.23.0).
|
|
1458
1458
|
"""
|
|
1459
1459
|
|
|
@@ -1472,7 +1472,7 @@ class CheckInfo:
|
|
|
1472
1472
|
change_id: ChangeID | None
|
|
1473
1473
|
"""Change ID of ``perform-check`` or ``recover-check`` change driving this check.
|
|
1474
1474
|
|
|
1475
|
-
This will be None on older versions of Pebble, which did not use changes
|
|
1475
|
+
This will be ``None`` on older versions of Pebble, which did not use changes
|
|
1476
1476
|
to drive health checks.
|
|
1477
1477
|
"""
|
|
1478
1478
|
|
|
@@ -1708,7 +1708,7 @@ class ExecProcess(Generic[AnyStr]):
|
|
|
1708
1708
|
|
|
1709
1709
|
If the stdin argument was not passed to :meth:`Client.exec`, this is a
|
|
1710
1710
|
writable file-like object the caller can use to stream input to the
|
|
1711
|
-
process. It is None if stdin was passed to :meth:`Client.exec`.
|
|
1711
|
+
process. It is ``None`` if stdin was passed to :meth:`Client.exec`.
|
|
1712
1712
|
"""
|
|
1713
1713
|
|
|
1714
1714
|
stdout: IO[AnyStr] | None
|
|
@@ -1716,16 +1716,16 @@ class ExecProcess(Generic[AnyStr]):
|
|
|
1716
1716
|
|
|
1717
1717
|
If the stdout argument was not passed to :meth:`Client.exec`, this is a
|
|
1718
1718
|
readable file-like object the caller can use to stream output from the
|
|
1719
|
-
process. It is None if stdout was passed to :meth:`Client.exec`.
|
|
1719
|
+
process. It is ``None`` if stdout was passed to :meth:`Client.exec`.
|
|
1720
1720
|
"""
|
|
1721
1721
|
|
|
1722
1722
|
stderr: IO[AnyStr] | None
|
|
1723
1723
|
"""Standard error from the process.
|
|
1724
1724
|
|
|
1725
1725
|
If the stderr argument was not passed to :meth:`Client.exec` and
|
|
1726
|
-
``combine_stderr`` was False
|
|
1727
|
-
caller can use to stream error output from the process. It is None if
|
|
1728
|
-
stderr was passed to :meth:`Client.exec` or ``combine_stderr`` was True
|
|
1726
|
+
``combine_stderr`` was ``False``, this is a readable file-like object the
|
|
1727
|
+
caller can use to stream error output from the process. It is ``None`` if
|
|
1728
|
+
stderr was passed to :meth:`Client.exec` or ``combine_stderr`` was ``True``.
|
|
1729
1729
|
"""
|
|
1730
1730
|
|
|
1731
1731
|
def __init__(
|
|
@@ -1820,8 +1820,8 @@ class ExecProcess(Generic[AnyStr]):
|
|
|
1820
1820
|
"""Wait for the process to finish and return tuple of (stdout, stderr).
|
|
1821
1821
|
|
|
1822
1822
|
If a timeout was specified to the :meth:`Client.exec` call, this waits
|
|
1823
|
-
at most that duration. If combine_stderr was True
|
|
1824
|
-
the process's standard error, and stderr will be None
|
|
1823
|
+
at most that duration. If combine_stderr was ``True``, stdout will include
|
|
1824
|
+
the process's standard error, and stderr will be ``None``.
|
|
1825
1825
|
|
|
1826
1826
|
Raises:
|
|
1827
1827
|
ChangeError: if there was an error starting or running the process.
|
|
@@ -1878,7 +1878,7 @@ class ExecProcess(Generic[AnyStr]):
|
|
|
1878
1878
|
|
|
1879
1879
|
|
|
1880
1880
|
def _has_fileno(f: Any) -> bool:
|
|
1881
|
-
"""Return True if the file-like object has a valid fileno() method."""
|
|
1881
|
+
"""Return ``True`` if the file-like object has a valid fileno() method."""
|
|
1882
1882
|
try:
|
|
1883
1883
|
f.fileno()
|
|
1884
1884
|
return True
|
|
@@ -2443,7 +2443,7 @@ class Client:
|
|
|
2443
2443
|
Args:
|
|
2444
2444
|
change_id: Change ID of change to wait for.
|
|
2445
2445
|
timeout: Maximum time in seconds to wait for the change to be
|
|
2446
|
-
ready. It may be None
|
|
2446
|
+
ready. It may be ``None``, in which case wait_change never times out.
|
|
2447
2447
|
delay: If polling, this is the delay in seconds between attempts.
|
|
2448
2448
|
|
|
2449
2449
|
Returns:
|
|
@@ -2539,8 +2539,8 @@ class Client:
|
|
|
2539
2539
|
def add_layer(self, label: str, layer: str | LayerDict | Layer, *, combine: bool = False):
|
|
2540
2540
|
"""Dynamically add a new layer onto the Pebble configuration layers.
|
|
2541
2541
|
|
|
2542
|
-
If combine is
|
|
2543
|
-
layer with the given label. If combine is
|
|
2542
|
+
If combine is false (the default), append the new layer as the top
|
|
2543
|
+
layer with the given label. If combine is true and the label already
|
|
2544
2544
|
exists, the two layers are combined into a single one considering the
|
|
2545
2545
|
layer override rules; if the layer doesn't exist, it is added as usual.
|
|
2546
2546
|
"""
|
|
@@ -2605,12 +2605,12 @@ class Client:
|
|
|
2605
2605
|
Args:
|
|
2606
2606
|
path: Path of the file to read from the remote system.
|
|
2607
2607
|
encoding: Encoding to use for decoding the file's bytes to str,
|
|
2608
|
-
or None to specify no decoding.
|
|
2608
|
+
or ``None`` to specify no decoding.
|
|
2609
2609
|
|
|
2610
2610
|
Returns:
|
|
2611
2611
|
A readable file-like object, whose read() method will return str
|
|
2612
2612
|
objects decoded according to the specified encoding, or bytes if
|
|
2613
|
-
encoding is None
|
|
2613
|
+
encoding is ``None``.
|
|
2614
2614
|
|
|
2615
2615
|
Raises:
|
|
2616
2616
|
PathError: If there was an error reading the file at path, for
|
|
@@ -2689,7 +2689,7 @@ class Client:
|
|
|
2689
2689
|
encoding: Encoding to use for encoding source str to bytes, or
|
|
2690
2690
|
strings read from source if it is a TextIO type. Ignored if
|
|
2691
2691
|
source is bytes or BinaryIO.
|
|
2692
|
-
make_dirs: If
|
|
2692
|
+
make_dirs: If true, create parent directories if they don't exist.
|
|
2693
2693
|
permissions: Permissions (mode) to create file with (Pebble default
|
|
2694
2694
|
is 0o644).
|
|
2695
2695
|
user_id: User ID (UID) for file. If neither ``group_id`` nor ``group`` is provided,
|
|
@@ -2849,7 +2849,7 @@ class Client:
|
|
|
2849
2849
|
|
|
2850
2850
|
Args:
|
|
2851
2851
|
path: Path of the directory to create on the remote system.
|
|
2852
|
-
make_parents: If
|
|
2852
|
+
make_parents: If true, create parent directories if they don't exist.
|
|
2853
2853
|
permissions: Permissions (mode) to create directory with (Pebble
|
|
2854
2854
|
default is 0o755).
|
|
2855
2855
|
user_id: User ID (UID) for directory. If neither ``group_id`` nor ``group``
|
|
@@ -2885,13 +2885,13 @@ class Client:
|
|
|
2885
2885
|
|
|
2886
2886
|
Args:
|
|
2887
2887
|
path: Path of the file or directory to delete from the remote system.
|
|
2888
|
-
recursive: If
|
|
2888
|
+
recursive: If true, and path is a directory, recursively delete it and
|
|
2889
2889
|
everything under it. If path is a file, delete the file. In
|
|
2890
2890
|
either case, do nothing if the file or directory does not
|
|
2891
2891
|
exist. Behaviourally similar to ``rm -rf <file|dir>``.
|
|
2892
2892
|
|
|
2893
2893
|
Raises:
|
|
2894
|
-
pebble.PathError: If a relative path is provided, or if
|
|
2894
|
+
pebble.PathError: If a relative path is provided, or if ``recursive`` is ``False``
|
|
2895
2895
|
and the file or directory cannot be removed (it does not exist or is not empty).
|
|
2896
2896
|
"""
|
|
2897
2897
|
path = str(path)
|
|
@@ -3074,13 +3074,13 @@ class Client:
|
|
|
3074
3074
|
:meth:`ExecProcess.wait_output` to capture error output as a
|
|
3075
3075
|
string, or read from :meth:`ExecProcess.stderr` to stream
|
|
3076
3076
|
error output from the process. Must be None if combine_stderr
|
|
3077
|
-
is True
|
|
3077
|
+
is ``True``.
|
|
3078
3078
|
encoding: If encoding is set (the default is UTF-8), the types
|
|
3079
3079
|
read or written to stdin/stdout/stderr are str, and encoding
|
|
3080
3080
|
is used to encode them to bytes. If encoding is None, the
|
|
3081
3081
|
types read or written are raw bytes.
|
|
3082
|
-
combine_stderr: If
|
|
3083
|
-
its stdout (the stderr argument must be None). If
|
|
3082
|
+
combine_stderr: If true, process's stderr output is combined into
|
|
3083
|
+
its stdout (the stderr argument must be None). If false,
|
|
3084
3084
|
separate streams are used for stdout and stderr.
|
|
3085
3085
|
|
|
3086
3086
|
Returns:
|
|
@@ -192,7 +192,7 @@ class SQLiteStorage:
|
|
|
192
192
|
|
|
193
193
|
Args:
|
|
194
194
|
event_path: If supplied, will only yield events that match event_path. If not
|
|
195
|
-
supplied (or None
|
|
195
|
+
supplied (or ``None``/``''``) will return all events.
|
|
196
196
|
|
|
197
197
|
Returns:
|
|
198
198
|
Iterable of (event_path, observer_path, method_name) tuples
|
|
@@ -294,7 +294,7 @@ class JujuStorage:
|
|
|
294
294
|
|
|
295
295
|
Args:
|
|
296
296
|
event_path: If supplied, will only yield events that match event_path. If not
|
|
297
|
-
supplied (or None
|
|
297
|
+
supplied (or ``None``/``''``) will return all events.
|
|
298
298
|
|
|
299
299
|
Returns:
|
|
300
300
|
Iterable of (event_path, observer_path, method_name) tuples
|