-
Notifications
You must be signed in to change notification settings - Fork 1k
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
[docs] First party import detection FAQ incorrect #5529
Comments
(Thanks, will clarify via updating the docs and see if it answers the above question...) |
Okay, a couple things from looking at this:
First, this is poorly worded. In this case, the stuff in Second, in the cases in which you see: from bar import alpha
from foo.sub import beta What's happening is that both modules are being classified as first-party (as opposed to both being classified as third-party). You can use One thing that isn't mentioned in the docs is that, apart from the I'll document all of this. |
Thanks for engaging here-- I think this is a really important part of the docs to get super-clear, since it's very easy to end up with confusing import-sorting behavior unless this is spelled out exactly.
I see-- maybe tricky to describe accurately, but if
I did, and I think it's the right behavior.
What I find most confusing is this statement in the docs "If the src field is omitted, Ruff will default to using the "project root" as the only first-party source". Basically it's unclear what it means to use a directory as a "first-party source". Currently in the docs, you have an example that sets So is the rule that python packages are recursively discovered from each first-party source directory? That seems likely, but there are two points of confusion:
Basically, I can imagine three meanings of "source root":
Pretty sure the meaning is (3), but it would help to have that spelled out explicitly and have the example reflect that. |
Yeah this is completely right. The way Separately from the |
If this is true, then how should I conceptualize a scenario in which
So is it fair to say that in this scheme, none of the packages are "contained by" (e.g. discoverable via) any source root? And instead that first/third-party determination is done purely by: "if it's the same package then first-party, else third-party"? |
Yes, this sounds right to me based on the layout above. Does it match the behavior you're seeing in practice? (Typically, I think you'd add |
Hmm-- that appears to be inconsistent with the behavior in the OP and with your explanation:
The OP matches this scenario once |
I think the explanation is that you have a (I'm not arguing that this is correct, but I believe that's what's happening.) |
(And then |
I guess arguably it should look for (As an aside, I've ported Pyright's module resolver to Rust, so we will likely be able to improve our resolution rules quite a bit in the future. E.g., we shouldn't need to rely on that kind of crude directory matching. Instead, we can just attempt to resolve |
Just confirmed that this is correct by changing the name of top-level
Exactly, unless bar is a namespace package.
That's good news! One thing to keep in mind is that Pyright's module resolver does not support monorepos well, so depending on your aims for ruff, you may want to modify it somewhat. The specific problem is that pyright runs with the assumption of a single python environment, which is an assumption that can easily be violated in monorepos. Dagster includes 70-80 python packages, and they can't all be installed in the same environment due to conflicting dependencies (certain examples are a problem). This means to run pyright on our entire repo requires multiple runs. The simplest way to do this would be to run pyright once per package, but this
The imperfect solution I came up with was to manually partition our packages into N sets that can be installed in the same environment. In CLI/CI we run once for each set and merge the results. In the editor, we just use the largest set's config for a single editor pyright/pylance instance. This works pretty well but it's fragile and overly complex-- you get false positive diagnostics in the editor once you stray outside the largest set. Ideally you should be able to run a single pyright/pylance instance capable of resolving each source file to one of multiple possible python environments. This would greatly simplify working the tool in a monorepo, and I'd suggest ruff should aim at this since you're just now getting into the import resolution game. I discussed with the pyright maintainer here: microsoft/pyright#4329 |
Awesome, thanks for mentioning this. I believe we should be able to support it (via something like the API you sketched out in that issue, allowing you to specify separate virtual environment paths for separate execution environments). |
Hijacking this thread for a second. Is the current sorting on |
Yes, with For example, the current docs text for
That "e.g." would give me pause when trying to set up first-vs-third party. |
Yup understood. Mostly trying to ensure that we have a solution that can support Dagster's requirements. Am I right that within (e.g.) |
yes |
Recently updated to
0.0.276
(though can't be sure when this behavior was introduced), and noticed the following. Here is a project layout with two packages,foo
andbar
:Here are the two
pyproject.toml
files:According to the Ruff FAQ:
This leads me to expect that the root directory here is the "project root". Because neither the
foo
norbar
packages reside directly in this directory, they should be treated the same. However, instead I find that inside ofexamples/foo/__init__.py
,foo
is first-party andbar
is third-party. I assessed this by looking at the import order that ruff targets:If I comment out
[tool.ruff]
inexamples/foo/pyproject.toml
, thenfoo
andbar
become "equal":If I then introduce a third
pyproject.toml
, but this time underexamples
, then it separatesfoo
andbar
again:From all this it looks like the current FAQ answer on third-party detection is incorrect. I also think it should be more detailed, since it doesn't mention the need for a
[tool.ruff]
section.FWIW I prefer the current behavior that clashes with the behavior described in the FAQ, but am scratching my head as to the actual resolution logic.
The text was updated successfully, but these errors were encountered: