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

Set the working dir and shadow file flag for mypy #9

Merged
merged 11 commits into from
Dec 19, 2022

Conversation

dmitrig
Copy link
Contributor

@dmitrig dmitrig commented Oct 28, 2022

Mypy requires some configuration in most cases, which it looks for in its working directory by default. You can check that flymake-collection-mypy won't work with projects like urllib3 at the moment. This updates flymake-collection-mypy to set default-directory to a parent dir containing a config file, if it exists. It also adds the mypy --shadow-file flag to make sure types are defined in the right module and caching works when processing temp files. Also includes minor tweaks to make flags customizable and parse out the diagnostic id.

Some things to consider:

  • Making setting the cwd opt-in, if it's important to preserve the current behavior
  • Adding a separate :working-dir keyword arg like flycheck instead of using :pre-let
  • I had to remove the leading dot from temp files, which appears to break relative imports. This will affect all checkers, but it could be made configurable per-checker

Copy link
Owner

@mohkale mohkale left a comment

Choose a reason for hiding this comment

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

Hi, thanks for this. Just a few things I think should be changed.

(make-temp-file ".flymake_" nil (concat "_" basename))))))
(make-temp-file "flymake_" nil (concat "_" basename))))))
Copy link
Owner

Choose a reason for hiding this comment

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

What is the significance of this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See:

I had to remove the leading dot from temp files, which appears to break relative imports. This will affect all checkers, but it could be made configurable per-checker

Python's module system can't handle file names with leading dots, so this causes some spurious errors when running mypy on temp files. I can provide an example, if you're interested. The --shadow-file flag avoids the issue but only works when the source file exists, so checking unsaved buffers would still be broken without this change.

Bit of an edge case, but making these short-lived temp files hidden didn't seem particularly important, either. Happy to revert or consider other options.

Copy link
Owner

Choose a reason for hiding this comment

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

Hmmm... the motivation is understandable but the end the result isn't ideal IMO 😞. Dot prefixed files are a standard for hidden files on UNIX (and more recently windows since it stopped restricting their creation). Most systems (example file browsers) will auto hide them. Admittedly that isn't a big concern for something so short lived but I'd still like to retain the intent that these are hidden files, especially when their in a project directory instead of /tmp/.

Could you instead make this a generic parameter that can be set by the linter itself and keep the default as .. Should be just a new parameter to the define macro here (and the helpers below as well).

Copy link
Contributor Author

@dmitrig dmitrig Dec 13, 2022

Choose a reason for hiding this comment

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

Added a temp-file-prefix parameter with a default. After working with flymake-collection-define a bit, I'd have to agree with the user in #2 re: reducing the use of macros. Seems like a lot of the logic could be moved into functions in flymake-collection.el, which all the checkers already require.

:type 'list
:group 'flymake-collection)

(defun flymake-collection-mypy--default-directory (buffer)
Copy link
Owner

Choose a reason for hiding this comment

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

Please add an option to enable or disable this functionality and use the project library to find the project root instead of locate-dominating-file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made it a bit more general: it can now try any of those options in order. Default is to look for config files, then try the project root, then fall back to the buffer default-directory. You can also use a directory path.

(warning bol (file-name) ":" line ":" column ": warning: " (message) eol)
(note bol (file-name) ":" line ":" column ": note: " (message) eol)))
((error bol (file-name) ":" line ":" column ": error: "
(message) " [" (id (one-or-more not-newline)) "]" eol)
Copy link
Owner

Choose a reason for hiding this comment

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

Some new tests ensuring id is parsed correctly would be great.

This appears to break relative imports in files checked by mypy. Maybe
make the temp file pattern configurable per checker?
Fall back to the buffer name when `buffer-file-name' is nil. Necessary
for checking temp files since python module names are based on the
file name.
(require 'flymake)
(require 'flymake-collection)

(eval-when-compile
(require 'flymake-collection-define))

(defcustom flymake-collection-mypy-args
'("--show-column-numbers"
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps --show-column-numbers and other args that the regexps depend upon shouldn't be customizable?

@jgarte
Copy link

jgarte commented Nov 27, 2022

Hi, what's the status on this? This PR would be so awesome to get merged in for me. I'll be using it.

Copy link
Owner

@mohkale mohkale left a comment

Choose a reason for hiding this comment

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

Hi, sorry for the late update. I'd been meaning to come back to this.

(make-temp-file ".flymake_" nil (concat "_" basename))))))
(make-temp-file "flymake_" nil (concat "_" basename))))))
Copy link
Owner

Choose a reason for hiding this comment

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

Hmmm... the motivation is understandable but the end the result isn't ideal IMO 😞. Dot prefixed files are a standard for hidden files on UNIX (and more recently windows since it stopped restricting their creation). Most systems (example file browsers) will auto hide them. Admittedly that isn't a big concern for something so short lived but I'd still like to retain the intent that these are hidden files, especially when their in a project directory instead of /tmp/.

Could you instead make this a generic parameter that can be set by the linter itself and keep the default as .. Should be just a new parameter to the define macro here (and the helpers below as well).

((res (cond
((eq spec 'default-directory)
(buffer-local-value 'default-directory buffer))
((eq spec 'project-root)
Copy link
Owner

Choose a reason for hiding this comment

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

Thanks for adding a project root check. I'm still not sure whether a recursive search up through the directory tree is the best (or at the very least a good default) choice here. Especially if this is something that's being edited across TRAMP or something else which adds a level of latency. That said I also can't think of a very good alternative either, this should really be something the tools themselves can pick up on IMO, not the packages that invoke those rules. That said they don't, so we should 🙃. I'm happy to approve this section. At some point it'd be nice if we could refactor it into something general purpose enough it could be used with the other python linters (they all have a habit of depending on this).

Copy link
Contributor Author

@dmitrig dmitrig Dec 13, 2022

Choose a reason for hiding this comment

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

Pretty sure sure this is how flycheck does it. I agree it'd be nice to, at the very least, avoid searching directories every time the checker is invoked. Actually, at first I only had this run only once per buffer, but initializing checkers and caching some state seemed like something that should also be done uniformly, rather than in an ad-hoc way per checker.

At some point it'd be nice if we could refactor it into something general purpose...

Don't think there's anything mypy or Python specific in either flymake-collection-mypy--locate-dominating-files or flymake-collection-mypy--default-directory if you want to make those available to other checkers.

@dmitrig dmitrig requested a review from mohkale December 14, 2022 18:31
@mohkale mohkale merged commit 74e2f3f into mohkale:release Dec 19, 2022
@mohkale
Copy link
Owner

mohkale commented Dec 19, 2022

LGTM. Thanks @dmitrig.

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.

4 participants