Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error related end-user experience #333

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

ftsell
Copy link
Member

@ftsell ftsell commented Mar 24, 2022

In my opinion, an end-user who uses an application that was built using django-configurations should in most cases not see an unwieldy traceback, but instead a nicely formatted error detailing what went wrong and what they should do to rectify it.
In this regard, the PR is not aimed at application developers, but instead aims to improve the user experience of those end-users.

As an example, instead of a traceback, the user now receives something like this:

Couldn't setup values of configuration Debug
    * DEBUG was given an invalid value
        - DEBUG is taken from the environment variable DJANGO_DEBUG as a BooleanValue
        - '5' was received but that is invalid
    * Value of DEBUG2 could not be retrieved from environment
        - DEBUG2 is taken from the environment variable DJANGO_DEBUG2 as a BooleanValue

Additionally, this PR closes #332 because I was getting annoyed at the failing tests


This feature is implemented by introducing our own custom exception type that is raised during Value setup and processing and caught by our importer. When caught, an error handler pretty-prints the information that is included in the exception. This information is, in turn, automatically retrieved from the relevant Value.


THIS IS STILL A WORK IN PROGRESS because I still want to include more actionable information in the error message. Nonetheless, the PR gives others the opportunity to chime in about the feature.

TODOs:

  • Add more information to error messages (e.g. which possible values are accepted in the environment or help texts)
  • Add automatic generation of example values where that makes sense (e.g. for django secret keys)
  • Update documentation to explain how application developers can raise their own ConfigurationErrors to display well-formatted errors to end-users, how help_text, help_reference and example_generator can be used
  • Get Code Quality up to standards (flake8 + test coverage)

This makes it easier to determine what exactly went wrong and thus build
better error handling in a later commit.
Tests were adapted accordingly to assert that only those specific errors
are raised instead of the plain ValueErrors.
Previously and ImproperlyConfigured error was always raised when an invalid
default configured for the BooleanValue class.
This behavior is unnecessary if the default is never used because the
value is marked as environ_required.
The check has thus been adapted to ignore invalid defaults in that case.
This introduces a function that wraps django entry points with an error
handler so that our own exception can be pretty-printed to an end-user
without a large stack-trace.
The defined error handler has also been applied to the existing
management, wsgi, asgi and fastcgi entry point definitions.
This way, multiple ConfigurationErrors are caught during setup, accumulated and printed all at once
Now Value classes accept a 'help_text' keyword which will get printed when a
ValueRetrievalError or ValueProcessingError occurs
Now Value classes accept a 'help_reference' keyword which will get printed when a
ValueRetrievalError or ValueProcessingError occurs
The test failed for two reasons. One was me changing the error string in a previous commit which
I have adapted the test for now.
The other was that django-cache-url changed its behavior. See #332
@codecov
Copy link

codecov bot commented Mar 24, 2022

Codecov Report

Merging #333 (b21f207) into master (141d8ef) will increase coverage by 0.12%.
The diff coverage is 90.26%.

@@            Coverage Diff             @@
##           master     #333      +/-   ##
==========================================
+ Coverage   89.94%   90.07%   +0.12%     
==========================================
  Files          25       29       +4     
  Lines        1194     1360     +166     
  Branches      235      265      +30     
==========================================
+ Hits         1074     1225     +151     
- Misses         89      102      +13     
- Partials       31       33       +2     
Impacted Files Coverage Δ
configurations/asgi.py 0.00% <0.00%> (ø)
configurations/fastcgi.py 0.00% <0.00%> (ø)
configurations/wsgi.py 0.00% <0.00%> (ø)
configurations/importer.py 82.35% <20.00%> (-2.74%) ⬇️
configurations/base.py 79.45% <50.00%> (-3.89%) ⬇️
configurations/values.py 94.46% <90.47%> (+0.13%) ⬆️
configurations/example_generators.py 96.29% <96.29%> (ø)
configurations/errors.py 100.00% <100.00%> (ø)
configurations/management.py 100.00% <100.00%> (ø)
tests/test_error_handling.py 100.00% <100.00%> (ø)
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 141d8ef...b21f207. Read the comment docs.

Example generators are an addition to the 'Value' classes that allow the error handler to display
example values for the failed value.
For example if no django secret key is found to be defined in the environment, an example (secure)
value for such a secret key can now be generated on the fly and be suggested to the user
@ftsell ftsell force-pushed the feature/better_end_user_experience branch from fdfa41c to e57a9b8 Compare March 24, 2022 13:44
@ftsell ftsell force-pushed the feature/better_end_user_experience branch from e57a9b8 to 3b96d16 Compare March 24, 2022 13:57
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.

Update tests for redis and email urls
1 participant