Skip to content

Conversation

@tonyandrewmeyer
Copy link
Collaborator

In #1975, we'd like to include a couple of docstrings. This PR clears the way for that, as well as any other doctests we wish to use in the future.

The PR tweaks some docstrings that are in private methods, so not in in our reference documentation. In addition:

  • ActionEvent.set_results changes from a block of >>> text to a set of bullet points. If this was doctest'ed then it'd actually call the method, but doing that with set_results itself would be complicated. This seems just as clear to me.
  • pebble.Client.exec has a couple of lines to disable doctest. This could be a doctest, but that would require a real Pebble, which we currently split off into a different set of tests. This is a bit ugly, but putting doctest: +SKIP on most of the lines is uglier (in my opinion), and I don't think there's a cleaner way to skip a single docstring.

Example usage:
# this is how we test that attempting to write a remote app's
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is private, so only someone developing Harness would see the change.

is completed.
Usage:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is private, so only someone developing Ops would see it.

Comment on lines -113 to +117
--branch -m pytest --ignore={[vars]tst_path}smoke \
--branch -m pytest \
--ignore={[vars]tst_path}smoke \
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had the doctests running for coverage and then changed my mind on that. However, I think it is nicer to keep the ignores on separate lines.

Comment on lines -953 to +963
>>> from lib.charms.tempo_coordinator_k8s.v0.charm_tracing import trace_charm
>>> from lib.charms.tempo_coordinator_k8s.v0.tracing import charm_tracing_config
>>> @trace_charm(tracing_endpoint="my_endpoint", cert_path="cert_path")
>>> class MyCharm(...):
>>> _cert_path = "/path/to/cert/on/charm/container.crt"
>>> def __init__(self, ...):
>>> self.tracing = TracingEndpointRequirer(...)
>>> self.my_endpoint, self.cert_path = charm_tracing_config(
... self.tracing, self._cert_path)
from lib.charms.tempo_coordinator_k8s.v0.charm_tracing import trace_charm
from lib.charms.tempo_coordinator_k8s.v0.tracing import charm_tracing_config
@trace_charm(tracing_endpoint="my_endpoint", cert_path="cert_path")
class MyCharm(...):
_cert_path = "/path/to/cert/on/charm/container.crt"
def __init__(self, ...):
self.tracing = TracingEndpointRequirer(...)
self.my_endpoint, self.cert_path = charm_tracing_config(
self.tracing, self._cert_path
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, I should provide a clean for this upstream, but we're considering reimplementing this library rather than vendoring it, and there's the "move all the interface libraries" project as well, so it doesn't seem worth doing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My 2c:

  • let's not run doctests on vendored code
  • testing charm libs is outside of ops scope (albeit great for community)
  • doc-testing charm libs is even more so (albeit helps to keep charm lib doc strings in sync with charm lib code: chore: fix charm lib doc string haproxy-operator#163)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The challenge here is that pytest's doctest integration doesn't provide much in the way of configuration (pytest-doctestplus is better, but still doesn't have exactly what we want). There's no "ignore" option so to do this we'd have to have a lot of glob statements that match the files to be tested and don't match the files to not be tested.

Copy link
Collaborator

@benhoyt benhoyt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks. Can you show what a failing doctest looks like?

@tonyandrewmeyer
Copy link
Collaborator Author

Can you show what a failing doctest looks like?

In the summary:

FAILED test/charms/test_main/lib/ops/pebble.py::lib.ops.pebble.Client.exec

And in the details:

/home/tameyer/w/config-schema/test/charms/test_main/lib/ops/framework.py:946: UnexpectedException
__________________________________________________________ [doctest] lib.ops.pebble.Client.exec ___________________________________________________________
[gw0] linux -- Python 3.13.0 /home/tameyer/w/config-schema/.tox/unit/bin/python3
2974 :class:`ExecProcess` that deals with strings if ``encoding`` is
2975 specified (the default ), or one that deals with bytes if ``encoding``
2976 is set to ``None``.l
2977 
2978 Most of the parameters are explained in the "Parameters" section
2979 below, however, input/output handling is a bit more complex. Some
2980 examples are shown below::
2981 
2982     # Simple command with no output; just check exit code
2983     >>> process = client.exec(['send-emails'])
UNEXPECTED EXCEPTION: NameError("name 'client' is not defined")
Traceback (most recent call last):
  File "/home/tameyer/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu/lib/python3.13/doctest.py", line 1395, in __run
    exec(compile(example.source, filename, "single",
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                 compileflags, True), test.globs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<doctest lib.ops.pebble.Client.exec[0]>", line 1, in <module>
NameError: name 'client' is not defined. Did you mean: 'Client'?

tonyandrewmeyer and others added 2 commits August 19, 2025 11:51
Co-authored-by: Dave Wilding <tech@dpw.me>
Co-authored-by: Dave Wilding <tech@dpw.me>
@tonyandrewmeyer tonyandrewmeyer merged commit a8169e3 into canonical:main Aug 18, 2025
43 checks passed
@tonyandrewmeyer tonyandrewmeyer deleted the add-doctests branch August 18, 2025 23:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants