Templated docstrings for Python classes.
Project description
documented
Templated docstrings for Python classes.
Features
- Describe your business logic in docstrings of your classes and exceptions;
- When printing an object or an exception, the library will substitute the placeholders in the docstring text with runtime values,
- And you (or your user) will see a human readable text.
Installation
pip install documented
Example
from dataclasses import dataclass
from documented import DocumentedError
@dataclass
class InsufficientWizardryLevel(DocumentedError):
"""
🧙 Your level of wizardry is insufficient ☹
Spell: {self.spell}
Minimum level required: {self.required_level}
Actual level: {self.actual_level} {self.comment}
Unseen University will be happy to assist in your training! 🎓
"""
spell: str
required_level: int
actual_level: int
@property
def comment(self) -> str:
if self.actual_level <= 0:
return '(You are Rincewind, right? Hi!)'
else:
return ''
raise InsufficientWizardryLevel(
spell='Animal transformation',
required_level=8,
actual_level=0,
)
which prints:
---------------------------------------------------------------------
InsufficientWizardryLevel Traceback (most recent call last)
<ipython-input-1-d8ccdb953cf6> in <module>
27
28
---> 29 raise InsufficientWizardryLevel(
30 spell='Animal transformation',
31 required_level=8,
InsufficientWizardryLevel:
🧙 Your level of wizardry is insufficient ☹
Spell: Animal transformation
Minimum level required: 8
Actual level: 0 (You are Rincewind, right? Hi!)
Unseen University will be happy to assist in your training! 🎓
Usage
- Template rendering is done using
str.format()
. - That function receives the object instance as
self
keyword argument. - From template, you can't call methods of the object, but you can access its fields and properties.
textwrap.dedent()
is applied to the result, thus Python indentation rules do not corrupt the resulting message.
Dynamically computed pieces of content may be introduced using:
@property
- or,
@cached_property
for performance.
You can also access elements of lists and dicts by index, for example: {self.countries[US]}
.
Making your exceptions sane
-
Create your own exception classes in terms of your domain, to play a part in your business logic.
-
Do not use the word
Exception
orError
in their names. Your code shouldraise
things like:BalanceInsufficient
PlanetNotFound
TetOffline
OrderDeclined
And should not:
ValueError
Exception
CatastrophicalError
-
Store meaningful properties of your errors in fields of the exception classes.
-
Use
dataclasses
,attrs
orpydantic
to save yourself from boilerplate in__init__()
— and to get IDE support. -
Maintain docstrings of your exceptions to contain up-to-date, human readable descriptions of what they mean.
-
You will be stimulated to do this by
documented
: when an exception happens, the docstring becomes actually useful.
Links
- About naming and abstracting things: Kevlin Henney. Seven Ineffective Coding Habits of Many Programmers
- Python: Better Typed Than You Think summarizes a number of ways to handle errors in Python programs
- dry-python/returns proposes to replace exceptions with monadic
Result
container, which works great in Scala, Haskell, and Rust, — but arguably not everyone would want to adopt this approach in their Python codebase.
Which actually explains the meaning of this little helper: if we're stuck with exceptions in Python, why not at least make them friendlier?
This project was generated with wemake-python-package
. Current template version is: 5840464a31423422d7523897d854e92408eee6b8. See what is updated since then.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for documented-0.1.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f55daee8476ca89eacfddf7cf6467cab663e12e0726aec7424d9980ed5d1167b |
|
MD5 | c8133dc6af969e3da836a2c031d5d1c8 |
|
BLAKE2b-256 | 5f4d24e0d335c7da6a426b6622d4c357429d0c7ba02a8b8520bde0625bdd0d7d |