ops 2.22.0__tar.gz → 2.23.0.dev0__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-2.23.0.dev0/CONTRIBUTING.md +130 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/HACKING.md +43 -150
- {ops-2.22.0 → ops-2.23.0.dev0}/PKG-INFO +40 -52
- {ops-2.22.0 → ops-2.23.0.dev0}/README.md +37 -35
- {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/_main.py +28 -7
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/harness.py +0 -7
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/charm.py +218 -10
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/jujucontext.py +5 -1
- {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/model.py +215 -18
- {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/pebble.py +47 -11
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/testing.py +2 -0
- {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/version.py +1 -1
- {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/PKG-INFO +40 -52
- {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/SOURCES.txt +6 -0
- ops-2.23.0.dev0/ops.egg-info/requires.txt +12 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/pyproject.toml +62 -10
- {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/_main.py +28 -7
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/harness.py +0 -7
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/charm.py +218 -10
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/jujucontext.py +5 -1
- {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/model.py +215 -18
- {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/pebble.py +47 -11
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/testing.py +2 -0
- {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/version.py +1 -1
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/src/charm.py +9 -0
- ops-2.23.0.dev0/test/charms/test_relation/charmcraft.yaml +32 -0
- ops-2.23.0.dev0/test/charms/test_relation/src/charm.py +54 -0
- ops-2.23.0.dev0/test/charms/test_tracing/.gitignore +3 -0
- ops-2.23.0.dev0/test/integration/conftest.py +246 -0
- ops-2.23.0.dev0/test/integration/test_relation.py +72 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/integration/test_tracing.py +16 -16
- {ops-2.22.0 → ops-2.23.0.dev0}/test/pebble_cli.py +14 -8
- {ops-2.22.0 → ops-2.23.0.dev0}/test/smoke/test_smoke.py +2 -14
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_charm.py +846 -2
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_infra.py +5 -3
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_jujucontext.py +6 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_main.py +53 -7
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_model.py +236 -145
- ops-2.23.0.dev0/test/test_model_relation_data_class.py +951 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_pebble.py +43 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_real_pebble.py +3 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_testing.py +4 -3
- {ops-2.22.0 → ops-2.23.0.dev0}/tox.ini +33 -118
- ops-2.22.0/ops.egg-info/requires.txt +0 -27
- ops-2.22.0/test/integration/conftest.py +0 -205
- {ops-2.22.0 → ops-2.23.0.dev0}/CHANGES.md +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/CODE_OF_CONDUCT.md +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/LICENSE.txt +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/MANIFEST.in +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/SECURITY.md +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/STYLE.md +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/timeconv.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/yaml.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/framework.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/jujuversion.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/lib/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/log.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/main.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/py.typed +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops/storage.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/dependency_links.txt +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/top_level.txt +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/setup.cfg +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/benchmark/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-ids +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-ids.bat +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-list +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-list.bat +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/actions.yaml +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/config.yaml +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/timeconv.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/yaml.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/framework.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/jujuversion.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/lib/__init__.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/log.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/main.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/py.typed +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/storage.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/metadata.yaml +0 -0
- {ops-2.22.0/test/charms/test_tracing → ops-2.23.0.dev0/test/charms/test_relation}/.gitignore +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_smoke/README.md +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_smoke/metadata.yaml +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_smoke/src/charm.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_tracing/charmcraft.yaml +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_tracing/src/charm.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/conftest.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/fake_pebble.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_framework.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_helpers.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_jujuversion.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_lib.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_log.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_main_invocation.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_main_type_hint.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_storage.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_timeconv.py +0 -0
- {ops-2.22.0 → ops-2.23.0.dev0}/test/test_yaml.py +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
We welcome contributions to Ops!
|
|
2
|
+
|
|
3
|
+
Before working on changes, please consider [opening an issue](https://github.com/canonical/operator/issues) explaining your use case. If you would like to chat with us about your use cases or proposed implementation, you can reach us at [Matrix](https://matrix.to/#/#charmhub-charmdev:ubuntu.com) or [Discourse](https://discourse.charmhub.io/).
|
|
4
|
+
|
|
5
|
+
For detailed technical information about the development of Ops, see [HACKING.md](./HACKING.md).
|
|
6
|
+
|
|
7
|
+
# Pull requests
|
|
8
|
+
|
|
9
|
+
Changes are proposed as [pull requests on GitHub](https://github.com/canonical/operator/pulls).
|
|
10
|
+
|
|
11
|
+
Pull requests should have a short title that follows the [conventional commit style](https://www.conventionalcommits.org/en/) using one of these types:
|
|
12
|
+
|
|
13
|
+
- chore
|
|
14
|
+
- ci
|
|
15
|
+
- docs
|
|
16
|
+
- feat
|
|
17
|
+
- fix
|
|
18
|
+
- perf
|
|
19
|
+
- refactor
|
|
20
|
+
- revert
|
|
21
|
+
- test
|
|
22
|
+
|
|
23
|
+
Some examples:
|
|
24
|
+
|
|
25
|
+
- feat: add the ability to observe change-updated events
|
|
26
|
+
- fix!: correct the type hinting for config data
|
|
27
|
+
- docs: clarify how to use mounts in ops.testing.Container
|
|
28
|
+
- ci: adjust the workflow that publishes ops-scenario
|
|
29
|
+
|
|
30
|
+
We consider Ops too small a project to use scopes, so we don't use them.
|
|
31
|
+
|
|
32
|
+
Note that the commit messages to the PR's branch do not need to follow the conventional commit format, as these will be squashed into a single commit to `main` using the PR title as the commit message.
|
|
33
|
+
|
|
34
|
+
To help us review your changes, please rebase your pull request onto the `main` branch before you request a review. If you need to bring in the latest changes from `main` after the review has started, please use a merge commit.
|
|
35
|
+
|
|
36
|
+
# Tests
|
|
37
|
+
|
|
38
|
+
Changes should include tests. Where reasonable, prefer to write 'Scenario' tests using [ops.testing](https://ops.readthedocs.io/en/latest/reference/ops-testing.html) instead of legacy [ops.testing.Harness](https://ops.readthedocs.io/en/latest/reference/ops-testing-harness.html) tests.
|
|
39
|
+
|
|
40
|
+
Tests for Ops should go in the test module corresponding to the code. For example, a feature added in `ops/main.py` would go in `test/test_main.py`. However, when adding a large number of logically related tests, consider putting these in their own file, named accordingly. For example, if adding a feature `foo` in `ops/main.py`, the tests might go in `test/test_main_foo.py`.
|
|
41
|
+
|
|
42
|
+
Tests for [`ops-scenario`](https://github.com/canonical/operator/tree/main/testing/tests) and [`ops-tracing`](https://github.com/canonical/operator/tree/main/tracing/test) are arranged differently in places. Try to find the most logical place to add tests, based on the code that is tested.
|
|
43
|
+
|
|
44
|
+
# Coding style
|
|
45
|
+
|
|
46
|
+
We have a team [Python style guide](./STYLE.md), most of which is enforced by CI checks. Please be complete with docstrings and keep them informative for _users_, as the [Ops library reference](https://ops.readthedocs.io/en/latest/reference/index.html) is automatically generated from Python docstrings.
|
|
47
|
+
|
|
48
|
+
# Documentation
|
|
49
|
+
|
|
50
|
+
The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html) are built automatically from [the top-level `docs` directory](./docs). We use [MyST Markdown](https://mystmd.org/) for most pages and arrange the pages according to [Diátaxis](https://diataxis.fr/).
|
|
51
|
+
|
|
52
|
+
To contribute docs:
|
|
53
|
+
|
|
54
|
+
1. Fork this repo and edit the relevant source files:
|
|
55
|
+
- Tutorials - [`/docs/tutorial`](./docs/tutorial)
|
|
56
|
+
- How-to guides - [`/docs/howto`](./docs/howto)
|
|
57
|
+
- Reference - Automatically generated from Python docstrings
|
|
58
|
+
- Explanation - [`/docs/explanation`](./docs/explanation)
|
|
59
|
+
2. [Build the documentation locally](#how-to-build-the-documentation-locally), to check that everything looks right
|
|
60
|
+
3. [Propose your changes using a pull request](#pull-requests)
|
|
61
|
+
|
|
62
|
+
When you create the pull request, GitHub automatically builds a preview of the docs. To find the preview, look for the "docs/readthedocs.org:ops" check near the bottom of the pull request page, then click **Details**. You can use the preview to double check that everything looks right.
|
|
63
|
+
|
|
64
|
+
## How to write great documentation
|
|
65
|
+
|
|
66
|
+
- Use short sentences, ideally with one or two clauses.
|
|
67
|
+
- Use headings to split the doc into sections. Make sure that the purpose of each section is clear from its heading.
|
|
68
|
+
- Avoid a long introduction. Assume that the reader is only going to scan the first paragraph and the headings.
|
|
69
|
+
- Avoid background context unless it's essential for the reader to understand.
|
|
70
|
+
|
|
71
|
+
Recommended tone:
|
|
72
|
+
|
|
73
|
+
- Use a casual tone, but avoid idioms. Common contractions such as "it's" and "doesn't" are great.
|
|
74
|
+
- Use "we" to include the reader in what you're explaining.
|
|
75
|
+
- Avoid passive descriptions. If you expect the reader to do something, give a direct instruction.
|
|
76
|
+
|
|
77
|
+
## How to build the documentation locally
|
|
78
|
+
|
|
79
|
+
To build the docs and open them in your browser:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
tox -e docs
|
|
83
|
+
open docs/_build/html/index.html
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Alternatively, to serve the docs locally and automatically refresh them whenever you edit a file:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
tox -e docs-live
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## How to document version dependencies
|
|
93
|
+
|
|
94
|
+
We don't publish separate documentation for separate versions of Ops. The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html) are always for the in-development (main branch) of Ops, and do not include any notes indicating changes or additions across Ops versions. We encourage all charmers to promptly upgrade to the latest version of Ops, and to refer to the release notes and changelog for learning about changes.
|
|
95
|
+
|
|
96
|
+
We do note when features behave differently when using different versions of Juju.
|
|
97
|
+
|
|
98
|
+
In docstrings:
|
|
99
|
+
|
|
100
|
+
- Use `.. jujuadded:: x.y` to indicate that the feature is only available when using version x.y (or higher) of Juju.
|
|
101
|
+
- Use `.. jujuchanged:: x.y` when the feature's behaviour _in Ops_ changes.
|
|
102
|
+
- Use `.. jujuremoved:: x.y` when the feature will be available in Ops but not in that version (or later) of Juju.
|
|
103
|
+
|
|
104
|
+
Similar directives also work in MyST Markdown. For example:
|
|
105
|
+
|
|
106
|
+
````markdown
|
|
107
|
+
```{jujuadded} x.y
|
|
108
|
+
Summary
|
|
109
|
+
```
|
|
110
|
+
````
|
|
111
|
+
|
|
112
|
+
Unmarked features are assumed to work and be available in the current LTS version of Juju.
|
|
113
|
+
|
|
114
|
+
# Copyright
|
|
115
|
+
|
|
116
|
+
The format for copyright notices is documented in the [LICENSE.txt](LICENSE.txt). New files should begin with a copyright line with the current year (e.g. Copyright 2024 Canonical Ltd.) and include the full boilerplate (see APPENDIX of [LICENSE.txt](LICENSE.txt)). The copyright information in existing files does not need to be updated when those files are modified -- only the initial creation year is required.
|
|
117
|
+
|
|
118
|
+
# Reviews
|
|
119
|
+
|
|
120
|
+
All changes require review before being merged. Code review typically examines:
|
|
121
|
+
|
|
122
|
+
- Code quality
|
|
123
|
+
- Test coverage
|
|
124
|
+
- User experience
|
|
125
|
+
|
|
126
|
+
When evaluating design decisions, we give priority to the following personas:
|
|
127
|
+
|
|
128
|
+
- Charm authors and maintainers (highest priority)
|
|
129
|
+
- Contributors to the Ops codebase
|
|
130
|
+
- Juju developers
|
|
@@ -1,14 +1,38 @@
|
|
|
1
|
+
We welcome contributions to Ops! Before you start work on a contribution, please also read [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
2
|
+
|
|
1
3
|
# Setting up a Dev Environment
|
|
2
4
|
|
|
3
5
|
To work in the framework itself you will need Python >= 3.8. Linting, testing,
|
|
4
6
|
and docs automation is performed using
|
|
5
|
-
[`tox`](https://tox.readthedocs.io/en/latest/)
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
[`tox`](https://tox.readthedocs.io/en/latest/).
|
|
8
|
+
|
|
9
|
+
First, make sure to install [uv](https://docs.astral.sh/uv/), for example:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
sudo snap install astral-uv --classic
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then install `tox` with extensions, as well as a range of Python versions:
|
|
8
16
|
|
|
9
17
|
```sh
|
|
10
|
-
|
|
11
|
-
|
|
18
|
+
uv tool install tox --with tox-uv
|
|
19
|
+
uv tool update-shell
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
You can validate that you have a working installation by running:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
tox --version
|
|
26
|
+
4.26.0 from /home/<your-user>/.local/share/uv/tools/tox/lib/python3.13/site-packages/tox/__init__.py
|
|
27
|
+
registered plugins:
|
|
28
|
+
tox-uv-1.26.0 at /home/<your-user>/.local/share/uv/tools/tox/lib/python3.13/site-packages/tox_uv/plugin.py with uv==0.7.12
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For improved performance on the tests, install the library that allows
|
|
32
|
+
PyYAML to use C speedups:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
sudo apt-get install libyaml-dev
|
|
12
36
|
```
|
|
13
37
|
|
|
14
38
|
# Testing
|
|
@@ -26,9 +50,6 @@ tox -e unit -- test/test_charm.py
|
|
|
26
50
|
# Format the code using Ruff
|
|
27
51
|
tox -e format
|
|
28
52
|
|
|
29
|
-
# Compile the requirements.txt file for docs
|
|
30
|
-
tox -e docs-deps
|
|
31
|
-
|
|
32
53
|
# Generate a local copy of the Sphinx docs in docs/_build
|
|
33
54
|
tox -e docs
|
|
34
55
|
|
|
@@ -36,23 +57,18 @@ tox -e docs
|
|
|
36
57
|
tox -e unit -- -k <pattern>
|
|
37
58
|
```
|
|
38
59
|
|
|
39
|
-
For more in depth debugging, you can enter
|
|
40
|
-
|
|
41
|
-
`pytest` directly:
|
|
60
|
+
For more in depth debugging, you can enter the virtualenv so that you can run
|
|
61
|
+
`pytest` or other tools directly:
|
|
42
62
|
|
|
43
63
|
```sh
|
|
44
|
-
|
|
45
|
-
source .
|
|
46
|
-
|
|
47
|
-
...
|
|
48
|
-
|
|
49
|
-
# Enter the unit testing virtualenv and run tests
|
|
50
|
-
source .tox/unit/bin/activate
|
|
64
|
+
uv sync --all-groups
|
|
65
|
+
source .venv/bin/activate
|
|
51
66
|
pytest
|
|
52
|
-
...
|
|
53
|
-
|
|
54
67
|
```
|
|
55
68
|
|
|
69
|
+
Likewise, use this virtualenv to enable Python type hints and language server if
|
|
70
|
+
you use an editor from the console or specify it as interpreter path in an IDE.
|
|
71
|
+
|
|
56
72
|
## Pebble Tests
|
|
57
73
|
|
|
58
74
|
The framework has some tests that interact with a real/live Pebble server. To
|
|
@@ -160,126 +176,6 @@ your charm to a controller using that version of Juju. For example, with microk8
|
|
|
160
176
|
We rely on automation to [update charm pins](.github/actions/update-charm-pins/) of
|
|
161
177
|
a bunch of charms that use the operator framework. The script can be run locally too.
|
|
162
178
|
|
|
163
|
-
# Contributing
|
|
164
|
-
|
|
165
|
-
Changes are proposed as [pull requests on GitHub](https://github.com/canonical/operator/pulls).
|
|
166
|
-
|
|
167
|
-
For coding style, we follow [PEP 8](https://peps.python.org/pep-0008/) as well as a team [Python style guide](./STYLE.md). Please be complete with docstrings and keep them informative for _users_,
|
|
168
|
-
as the [ops library reference](https://ops.readthedocs.io/en/latest/reference/index.html)
|
|
169
|
-
is automatically generated from Python docstrings.
|
|
170
|
-
|
|
171
|
-
For more advice about contributing documentation, see [Contributing documentation](#contributing-documentation).
|
|
172
|
-
|
|
173
|
-
Pull requests should have a short title that follows the
|
|
174
|
-
[conventional commit style](https://www.conventionalcommits.org/en/) using one of these types:
|
|
175
|
-
|
|
176
|
-
* chore
|
|
177
|
-
* ci
|
|
178
|
-
* docs
|
|
179
|
-
* feat
|
|
180
|
-
* fix
|
|
181
|
-
* perf
|
|
182
|
-
* refactor
|
|
183
|
-
* revert
|
|
184
|
-
* test
|
|
185
|
-
|
|
186
|
-
Some examples:
|
|
187
|
-
|
|
188
|
-
* feat: add the ability to observe change-updated events
|
|
189
|
-
* fix!: correct the type hinting for config data
|
|
190
|
-
* docs: clarify how to use mounts in ops.testing.Container
|
|
191
|
-
* ci: adjust the workflow that publishes ops-scenario
|
|
192
|
-
|
|
193
|
-
Note that the commit messages to the PR's branch do not need to follow the
|
|
194
|
-
conventional commit format, as these will be squashed into a single commit to `main`
|
|
195
|
-
using the PR title as the commit message.
|
|
196
|
-
|
|
197
|
-
We consider Ops too small a project to use scopes, so we don't use them.
|
|
198
|
-
|
|
199
|
-
## Copyright
|
|
200
|
-
|
|
201
|
-
The format for copyright notices is documented in the [LICENSE.txt](LICENSE.txt).
|
|
202
|
-
New files should begin with a copyright line with the current year (e.g. Copyright 2024 Canonical Ltd.) and include the full boilerplate (see APPENDIX of [LICENSE.txt](LICENSE.txt)).
|
|
203
|
-
The copyright information in existing files does not need to be updated when those files are modified -- only the initial creation year is required.
|
|
204
|
-
|
|
205
|
-
# Contributing documentation
|
|
206
|
-
|
|
207
|
-
The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html)
|
|
208
|
-
are built automatically from [the top-level `docs` directory](./docs). We use [MyST Markdown](https://mystmd.org/)
|
|
209
|
-
for most pages and arrange the pages according to [Diátaxis](https://diataxis.fr/).
|
|
210
|
-
|
|
211
|
-
To contribute docs:
|
|
212
|
-
|
|
213
|
-
1. Fork this repo and edit the relevant source files:
|
|
214
|
-
* Tutorials - [`/docs/tutorial`](./docs/tutorial)
|
|
215
|
-
* How-to guides - [`/docs/howto`](./docs/howto)
|
|
216
|
-
* Reference - Automatically generated from Python docstrings
|
|
217
|
-
* Explanation - [`/docs/explanation`](./docs/explanation)
|
|
218
|
-
2. [Build the documentation locally](#how-to-build-the-documentation-locally),
|
|
219
|
-
to check that everything looks right
|
|
220
|
-
3. [Propose your changes using a pull request](#contributing)
|
|
221
|
-
|
|
222
|
-
When you create the pull request, GitHub automatically builds a preview of the docs.
|
|
223
|
-
To find the preview, look for the "docs/readthedocs.org:ops" check near the bottom of
|
|
224
|
-
the pull request page, then click **Details**. You can use the preview to double check
|
|
225
|
-
that everything looks right.
|
|
226
|
-
|
|
227
|
-
## How to write great documentation
|
|
228
|
-
|
|
229
|
-
- Use short sentences, ideally with one or two clauses.
|
|
230
|
-
- Use headings to split the doc into sections. Make sure that the purpose of each section is clear from its heading.
|
|
231
|
-
- Avoid a long introduction. Assume that the reader is only going to scan the first paragraph and the headings.
|
|
232
|
-
- Avoid background context unless it's essential for the reader to understand.
|
|
233
|
-
|
|
234
|
-
Recommended tone:
|
|
235
|
-
- Use a casual tone, but avoid idioms. Common contractions such as "it's" and "doesn't" are great.
|
|
236
|
-
- Use "we" to include the reader in what you're explaining.
|
|
237
|
-
- Avoid passive descriptions. If you expect the reader to do something, give a direct instruction.
|
|
238
|
-
|
|
239
|
-
## How to build the documentation locally
|
|
240
|
-
|
|
241
|
-
To build the docs and open them in your browser:
|
|
242
|
-
|
|
243
|
-
```sh
|
|
244
|
-
tox -e docs
|
|
245
|
-
open docs/_build/html/index.html
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
Alternatively, to serve the docs locally and automatically refresh them whenever you edit a file:
|
|
249
|
-
|
|
250
|
-
```sh
|
|
251
|
-
tox -e docs-live
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
## How to document version dependencies
|
|
255
|
-
|
|
256
|
-
We don't publish separate documentation for separate versions of ops.
|
|
257
|
-
The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html)
|
|
258
|
-
are always for the in-development (main branch) of ops, and do not include
|
|
259
|
-
any notes indicating changes or additions across ops versions.
|
|
260
|
-
We encourage all charmers to promptly upgrade to the latest version of ops,
|
|
261
|
-
and to refer to the release notes and changelog for learning about changes.
|
|
262
|
-
|
|
263
|
-
We do note when features behave differently when using different versions of Juju.
|
|
264
|
-
|
|
265
|
-
In docstrings:
|
|
266
|
-
|
|
267
|
-
* Use `.. jujuadded:: x.y` to indicate that the feature is only available
|
|
268
|
-
when using version x.y (or higher) of Juju.
|
|
269
|
-
* Use `..jujuchanged:: x.y` when the feature's behaviour _in ops_ changes.
|
|
270
|
-
* Use `..jujuremoved:: x.y` when the feature will be available in ops
|
|
271
|
-
but not in that version (or later) of Juju.
|
|
272
|
-
|
|
273
|
-
Similar directives also work in MyST Markdown. For example:
|
|
274
|
-
|
|
275
|
-
````markdown
|
|
276
|
-
```{jujuadded} x.y
|
|
277
|
-
Summary
|
|
278
|
-
```
|
|
279
|
-
````
|
|
280
|
-
|
|
281
|
-
Unmarked features are assumed to work and be available in the current LTS version of Juju.
|
|
282
|
-
|
|
283
179
|
# Maintaining the documentation
|
|
284
180
|
|
|
285
181
|
## How to Pull in Style Changes
|
|
@@ -307,7 +203,7 @@ To pull in new dependency changes from the starter pack, change to the starter p
|
|
|
307
203
|
make html
|
|
308
204
|
```
|
|
309
205
|
|
|
310
|
-
Then, compare the generated file `.sphinx/requirements.txt`and the `
|
|
206
|
+
Then, compare the generated file `.sphinx/requirements.txt` and the `docs` declaration in the `dependency-groups` section of [`pyproject.toml`](./pyproject.toml) and adjust the `pyproject.toml` file accordingly.
|
|
311
207
|
|
|
312
208
|
# Dependencies
|
|
313
209
|
|
|
@@ -368,14 +264,11 @@ To make a release of the `ops` and/or `ops-scenario` packages, do the following:
|
|
|
368
264
|
- in [pyroject.toml for `ops`](pyproject.toml), the required versions for `ops-scenario` and `ops-tracing`
|
|
369
265
|
- in [pyproject.toml for `ops-scenario`](testing/pyproject.toml), the `version` attribute and the required version for `ops`
|
|
370
266
|
- in [pyproject.toml for `ops-tracing`](tracing/pyproject.toml), the `version` attribute and the required version for `ops`
|
|
371
|
-
11.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
12. Add, commit, and push, and open a PR to get the `CHANGES.md` update, version bumps,
|
|
375
|
-
and doc requirement bumps into main (and get it merged).
|
|
376
|
-
13. Wait until the tests pass after the PR is merged. It takes around 10 minutes.
|
|
267
|
+
11. Add, commit, and push, and open a PR to get the `CHANGES.md` update and version
|
|
268
|
+
bumps into main (and get it merged).
|
|
269
|
+
12. Wait until the tests pass after the PR is merged. It takes around 10 minutes.
|
|
377
270
|
If the tests don't pass at the tip of the main branch, do not release.
|
|
378
|
-
|
|
271
|
+
13. When you are ready, click "Publish". GitHub will create the additional tag.
|
|
379
272
|
|
|
380
273
|
Pushing the tags will trigger automatic builds for the Python packages and
|
|
381
274
|
publish them to PyPI ([ops](https://pypi.org/project/ops/) and
|
|
@@ -388,9 +281,9 @@ To make a release of the `ops` and/or `ops-scenario` packages, do the following:
|
|
|
388
281
|
(Note that the versions in the YAML refer to versions of the GitHub actions, not the versions of the ops library.)
|
|
389
282
|
|
|
390
283
|
You can troubleshoot errors on the [Actions Tab](https://github.com/canonical/operator/actions).
|
|
391
|
-
|
|
284
|
+
14. Announce the release on [Discourse](https://discourse.charmhub.io/c/framework/42)
|
|
392
285
|
and [Matrix](https://matrix.to/#/#charmhub-charmdev:ubuntu.com).
|
|
393
|
-
|
|
286
|
+
15. Open a PR to change the version strings to the expected next version, with ".dev0" appended.
|
|
394
287
|
For example, if 2.90.0 is the next expected `ops` version, use
|
|
395
288
|
`ops==2.90.0.dev0 ops-tracing==2.90.0.dev0 ops-scenario==7.90.0.dev0`.
|
|
396
289
|
There will be a total of seven changes:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ops
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.23.0.dev0
|
|
4
4
|
Summary: The Python library behind great charms
|
|
5
5
|
Author: The Charm Tech team at Canonical Ltd.
|
|
6
6
|
Project-URL: Homepage, https://ops.readthedocs.io/en/latest/
|
|
@@ -22,24 +22,10 @@ Requires-Dist: PyYAML==6.*
|
|
|
22
22
|
Requires-Dist: websocket-client==1.*
|
|
23
23
|
Requires-Dist: opentelemetry-api~=1.0
|
|
24
24
|
Requires-Dist: importlib-metadata
|
|
25
|
-
Provides-Extra: docs
|
|
26
|
-
Requires-Dist: canonical-sphinx-extensions; extra == "docs"
|
|
27
|
-
Requires-Dist: furo; extra == "docs"
|
|
28
|
-
Requires-Dist: linkify-it-py; extra == "docs"
|
|
29
|
-
Requires-Dist: myst-parser; extra == "docs"
|
|
30
|
-
Requires-Dist: pyspelling; extra == "docs"
|
|
31
|
-
Requires-Dist: sphinx~=8.0.0; extra == "docs"
|
|
32
|
-
Requires-Dist: sphinx-autobuild; extra == "docs"
|
|
33
|
-
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
34
|
-
Requires-Dist: sphinx-design; extra == "docs"
|
|
35
|
-
Requires-Dist: sphinx-notfound-page; extra == "docs"
|
|
36
|
-
Requires-Dist: sphinx-tabs; extra == "docs"
|
|
37
|
-
Requires-Dist: sphinxcontrib-jquery; extra == "docs"
|
|
38
|
-
Requires-Dist: sphinxext-opengraph; extra == "docs"
|
|
39
25
|
Provides-Extra: testing
|
|
40
|
-
Requires-Dist: ops-scenario==7.
|
|
26
|
+
Requires-Dist: ops-scenario==7.23.0.dev0; extra == "testing"
|
|
41
27
|
Provides-Extra: tracing
|
|
42
|
-
Requires-Dist: ops-tracing==2.
|
|
28
|
+
Requires-Dist: ops-tracing==2.23.0.dev0; extra == "tracing"
|
|
43
29
|
Provides-Extra: harness
|
|
44
30
|
Dynamic: license-file
|
|
45
31
|
|
|
@@ -131,46 +117,48 @@ class OpsExampleCharm(ops.CharmBase):
|
|
|
131
117
|
self.unit.status = ops.ActiveStatus()
|
|
132
118
|
```
|
|
133
119
|
|
|
134
|
-
> See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/
|
|
120
|
+
> See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/reference/ops.html#ops.PebbleReadyEvent)
|
|
135
121
|
|
|
136
|
-
- The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a
|
|
122
|
+
- The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a unit test:
|
|
137
123
|
|
|
138
124
|
```python
|
|
139
|
-
import ops
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
125
|
+
import ops
|
|
126
|
+
from ops import testing
|
|
127
|
+
|
|
128
|
+
from charm import OpsExampleCharm
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_httpbin_pebble_ready():
|
|
132
|
+
# Arrange:
|
|
133
|
+
ctx = testing.Context(OpsExampleCharm)
|
|
134
|
+
container = testing.Container("httpbin", can_connect=True)
|
|
135
|
+
state_in = testing.State(containers={container})
|
|
136
|
+
|
|
137
|
+
# Act:
|
|
138
|
+
state_out = ctx.run(ctx.on.pebble_ready(container), state_in)
|
|
139
|
+
|
|
140
|
+
# Assert:
|
|
141
|
+
updated_plan = state_out.get_container(container.name).plan
|
|
142
|
+
expected_plan = {
|
|
143
|
+
"services": {
|
|
144
|
+
"httpbin": {
|
|
145
|
+
"override": "replace",
|
|
146
|
+
"summary": "httpbin",
|
|
147
|
+
"command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent",
|
|
148
|
+
"startup": "enabled",
|
|
149
|
+
"environment": {"GUNICORN_CMD_ARGS": "--log-level info"},
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
assert expected_plan == updated_plan
|
|
154
|
+
assert (
|
|
155
|
+
state_out.get_container(container.name).service_statuses["httpbin"]
|
|
156
|
+
== ops.pebble.ServiceStatus.ACTIVE
|
|
157
|
+
)
|
|
158
|
+
assert state_out.unit_status == testing.ActiveStatus()
|
|
171
159
|
```
|
|
172
160
|
|
|
173
|
-
> See more: [`ops.testing
|
|
161
|
+
> See more: [`ops.testing`](https://ops.readthedocs.io/en/latest/reference/ops-testing.html)
|
|
174
162
|
|
|
175
163
|
|
|
176
164
|
Explore further, start editing the files, or skip ahead and pack the charm:
|
|
@@ -86,46 +86,48 @@ class OpsExampleCharm(ops.CharmBase):
|
|
|
86
86
|
self.unit.status = ops.ActiveStatus()
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
> See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/
|
|
89
|
+
> See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/reference/ops.html#ops.PebbleReadyEvent)
|
|
90
90
|
|
|
91
|
-
- The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a
|
|
91
|
+
- The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a unit test:
|
|
92
92
|
|
|
93
93
|
```python
|
|
94
|
-
import ops
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
94
|
+
import ops
|
|
95
|
+
from ops import testing
|
|
96
|
+
|
|
97
|
+
from charm import OpsExampleCharm
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_httpbin_pebble_ready():
|
|
101
|
+
# Arrange:
|
|
102
|
+
ctx = testing.Context(OpsExampleCharm)
|
|
103
|
+
container = testing.Container("httpbin", can_connect=True)
|
|
104
|
+
state_in = testing.State(containers={container})
|
|
105
|
+
|
|
106
|
+
# Act:
|
|
107
|
+
state_out = ctx.run(ctx.on.pebble_ready(container), state_in)
|
|
108
|
+
|
|
109
|
+
# Assert:
|
|
110
|
+
updated_plan = state_out.get_container(container.name).plan
|
|
111
|
+
expected_plan = {
|
|
112
|
+
"services": {
|
|
113
|
+
"httpbin": {
|
|
114
|
+
"override": "replace",
|
|
115
|
+
"summary": "httpbin",
|
|
116
|
+
"command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent",
|
|
117
|
+
"startup": "enabled",
|
|
118
|
+
"environment": {"GUNICORN_CMD_ARGS": "--log-level info"},
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
assert expected_plan == updated_plan
|
|
123
|
+
assert (
|
|
124
|
+
state_out.get_container(container.name).service_statuses["httpbin"]
|
|
125
|
+
== ops.pebble.ServiceStatus.ACTIVE
|
|
126
|
+
)
|
|
127
|
+
assert state_out.unit_status == testing.ActiveStatus()
|
|
126
128
|
```
|
|
127
129
|
|
|
128
|
-
> See more: [`ops.testing
|
|
130
|
+
> See more: [`ops.testing`](https://ops.readthedocs.io/en/latest/reference/ops-testing.html)
|
|
129
131
|
|
|
130
132
|
|
|
131
133
|
Explore further, start editing the files, or skip ahead and pack the charm:
|