-
-
Notifications
You must be signed in to change notification settings - Fork 484
Output a more clear configuration error #421
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot! Great work!
Two things:
- Let's change how we work with constants here
- Let's test the new output!
👍
return django_settings_module | ||
parser.read(cast(str, config_file_path)) | ||
|
||
section = 'mypy.plugins.django-stubs' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reuse this const from somewhere else? Looks like we should already have it somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mypy_django_plugin/main.py
Outdated
"\t(required) django_settings_module: str"]) | ||
|
||
def raise_error(handler: ErrorHandler, error_type: int) -> NoReturn: | ||
messages = {1: "'django_settings_module' is not set: no mypy config file specified", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make an enum
from keys here. Like @unique class ErrorType(enum.IntEnum)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good idea! I think enums access time is faster than dicts.
Considering that they shouldn't get evaluated until needed for an error, where should they live?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just had a look into this and I have mixed feelings. Enums can take the following form:
class ErrorType(enum.Enum):
SOME_ERROR: "some error because bad bad something"
BAD_ERROR: "bad error because something"
# or, say
class ErrorType(enum.IntEnum):
SOME_ERROR: 1
BAD_ERROR: 2
As far as I understand, the IntEnum
just allows the enum to be referenced like ErrorType(1)
. The reason I used an int as the key initially was that it's the smallest type that would allow to reference errors without having to add those definitions to the scope before needed.
If an enum is used, this would require a call like error(ErrorType.MISSING_SECTION
) or similar, i.e. they'd be in the scope before they are needed, which isn't great considering the startup time which is already rather slow and that errors won't get thrown often.
Also, currently these messages aren't used anywhere else or have any operations done to them. If we, say, had to do any comparison operations, then attaching types to them with enums would make sense; but now they're rather limited, so I'd probably leave it as it is for now, mostly due to performance reasons though.
Let me know if I'm missing out on something or you have something planned where having them as enums would make more sense. For now I've moved the error handler import to the local scope having done some python -X importtime
runs - the startup is at least double as sluggish as mypy's 🐌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also added a try/except for the file read, and using ConfigParser.read_file
instead of read
, since the latter is made for multiple files and does some extras that aren't required here.
Thanks! In terms of testing, would you expect it to be written in the same language as the type checks? I struggled to find any examples. If I try removing the configuration from one of the tests now, that's what I get: platform linux -- Python 3.6.11, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 -- /home/sarunas/.pyenv/versions/3.6.11/envs/django-stubs-3.6.11/bin/python3.6
cachedir: .pytest_cache
rootdir: /home/sarunas/Documents/misc/django-stubs, inifile: pytest.ini, testpaths: ./test-data/typecheck/test_config.yml
plugins: cov-2.10.0, mypy-plugins-1.3.0
collected 3 items
test-data/typecheck/test_config.yml::django_settings_module_missing usage: (config)
[mypy.plugins.django_stubs]
(required) django_settings_module: str
(django-stubs) mypy: error: 'django_settings_module' is not set: setting is not provided
FAILED
test-data/typecheck/test_config.yml::pyproject_toml_config PASSED
test-data/typecheck/test_config.yml::generate_pyproject_toml_and_settings_file_from_installed_apps_key PASSED
========================================================================================================================================= FAILURES =========================================================================================================================================
______________________________________________________________________________________________________________________________ django_settings_module_missing ______________________________________________________________________________________________________________________________
/home/sarunas/Documents/misc/django-stubs/test-data/typecheck/test_config.yml:2:
E pytest_mypy_plugins.utils.TypecheckAssertionError: Critical error occurred Or should this be a standard python test? |
Also, I didn't find any note in the readme which mentions that some features aren't supported by |
@snejus yes, we must be clear about the minimal requirements. |
Perfect! Sorry to distract though, what do you reckon about the above? Just realised the second comment ended up being an essay. Skip it - the main idea: at least the way I see it, using enums would add to the already slow startup time, and I struggled to find good reasons to use it - though that's just a shallow look and I can't read your mind so I'd be happy to hear a bit more about this :) |
@snejus seems ok! Let's skip it then! |
Hey, sorry for disappearing - been a bit too busy with work.
Do you have a comment about this by any chance? As far as I understand the type checks testing lang (actually, what is it officially called? :) ) cannot handle hard failures/exits - could you confirm this? If that's the case I'll add a usual python test for it. |
@snejus you can try https://github.com/typeddjango/django-stubs/tree/master/test-data/typecheck It probably should work. If not, then we can create |
Had a deeper look into it - it doesn't seem like it can be done with ============================================================ test session starts =============================================================
platform linux -- Python 3.6.11, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 -- /home/sarunas/.pyenv/versions/3.6.11/envs/django-stubs-3.6.11/bin/python3.6
cachedir: .pytest_cache
rootdir: /home/sarunas/Documents/misc/django-stubs, inifile: pytest.ini, testpaths: ./test-data/typecheck/test_config.yml
plugins: cov-2.10.0, mypy-plugins-1.3.0
collected 3 items
test-data/typecheck/test_config.yml::config_missing_django_settings_module usage: (config)
[mypy.plugins.django_stubs]
(required) django_settings_module: str
(django-stubs) mypy: error: 'django_settings_module' is not set: setting is not provided
FAILED
test-data/typecheck/test_config.yml::pyproject_toml_config PASSED
test-data/typecheck/test_config.yml::generate_pyproject_toml_and_settings_file_from_installed_apps_key PASSED
================================================================== FAILURES ==================================================================
___________________________________________________ config_missing_django_settings_module ____________________________________________________
/home/sarunas/Documents/misc/django-stubs/test-data/typecheck/test_config.yml:2:
E pytest_mypy_plugins.utils.TypecheckAssertionError: Critical error occurred where the test case looks like this: - case: config_missing_django_settings_module
main: |
pass
mypy_config: |
[mypy.plugins.django-stubs] This kinda makes sense - the language is suited to test type checking specifically, whereas this is sort of a test case setup level error. I guess I'll go ahead with a |
I've seen you mentioned this PR in #428 - I'll cover django setup validation too. |
@snejus thanks a lot! |
Ah, didn't see your message until now and got it done meanwhile. Though would it not be a bit of an overkill to use For the input validation, the template stays the same and can take 3 error messages (see the tests) - and that's basically it. If new vars get added in the future then it just needs that field name adding there - though that won't happen often I imagine. Considering the rest of error handling, the output will look even more boring - the way I see it (do correct me if I'm wrong) is that we're simply gonna catch the exceptions and reraise it with our generic message, like |
Looks like the output is telling me what's next 😅 |
mypy_django_plugin/main.py
Outdated
|
||
usage = '\n'.join(['(config)', | ||
'...', | ||
'[mypy.plugins.django_stubs]', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just realised that this entire nonsense is a constant, and that the tests already define a string for it:
TEMPLATE = """usage: (config)
...
[mypy.plugins.django_stubs]
django_settings_module: str (required)
...
(django-stubs) mypy: error: 'django_settings_module' is not set: {}
"""
Assuming that we follow DRY, and considering that error handling is about to get extended in general, I feel like most of this exit
function should move somewhere else, say, a module called errors
? It could live in mypy_django_plugin/lib/
like helpers
and fullnames
. I thought of adding it to the helpers, but it somehow seems wrong to from helpers import exit
which kills the app.
Additionally, that'd be a good start considering the rest of error handling plans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@mkurnikov ?
@kszmigiel ?
Cool. Let's finish this PR here, (unless there are any further action points that relate to input validation). In terms of further error handling, #428 is very much related to my #417 which has some work done already, so I believe it may make more sense to continue with it there. I found that #224 also experience similar issues. Are you by any chance aware of any other affected tickets? Would be good to source as many as possible in order to build a clear picture and to know which parts people struggle the most with/need to get most attention. |
Nope, I guess that you have found everything we had. |
Nope, not yet! Though I'm on it currently, together with #417 to handle Thanks, by the way! Next step - colours ;) |
Hey - just checking whether there's anything that is blocking this getting merged in? The further error handling improvements partly depend on this (finally found time to work on it), so it'd be good know what's the status. |
Thanks a lot! |
I have made things!
This tackles #420; missing configuration is now reported like this:
The function got refactored a little bit and made a little less verbose. I thought this way it will be easier to add new configuration options (a solution to #417 which is on the way for example).
Related issues