-
Notifications
You must be signed in to change notification settings - Fork 23
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
import this/foo
which resolves this
to <current nimble root>
#267
Comments
You can already refer to the root of a Nimble package from itself just by using the package name, or am I mistaken? |
Import hygiene mandates using relative paths. Using package name would could resolve to a different path depending on what's in your nimble path, and in fact is a frequent source of gotchas for nimble test. As another example, See also nim-lang/fusion#25 (comment) for yet another example (for fusion bundled in stdlib) |
We already have too many ways to express this, and this change muddies the waters even further. It remains an option for the future; perhaps when it's a problem that many users share? |
This would require Nim knowing even more about Nimble than it already does. I don't think this is the direction we want to go in. |
When debugging users' Arraymancer issues I've already naively copy pasted their "import arraymancer" and used the one installed from "nimble install" instead if the one from the package.
I have mixed feelings. One thing for sure is that I don't like how Python package import works as they require manipulating PYTHON_PATH before using any git cloned repo. |
If this is a common problem for you (or anyone else) then you may prefer to disable Nim reading these packages by removing https://github.com/nim-lang/Nim/blob/devel/config/nim.cfg#L52 |
I don't see how this can work in practice, unless I'm missing your point; it's an all or nothing. If arraymancer depends on other nimble packages (which it does), you'd have to specify the
nim already knows about all of this, and needs this information already, see compiler/packagehandling.nim ( The fact is that currently
there's no way to tell how This is error prone (as is the other gotcha mentioned with nimble path overriding local path), and also not self documenting in terms of what imports are external vs internal. This proposal solves all those issues:
|
this keeps happening, see latest CI important_packages breakage c-blake/cligen#170 This RFC would fix this issue cleanly and avoid any possible ambiguities: # before RFC
import cligen/prefetch # bad, caused https://github.com/c-blake/cligen/issues/170
import prefetch # bad for reasons I gave above, everything is in same scope (internal vs external);
# plus requires computing relative paths eg subdir/prefetch or ../prefetch
# and these would look different from an external package importing it
# with RFC
import this/prefetch # 0 ambiguity, and external imports would be identical modulo s/this/pkgname/ |
I consider this an artifact of bad You would have to Anyway, I've said all this before. This is maybe just yet another case where unnecessary complexities cause trouble. |
I don't see how removing
not sure i agree with that statement |
I continue to be dumbfounded about this src/-scope conflation. The whole package is already "scoped" in its git checkout dir, easily arranged to be the same as the package name. Under my idea, to "be installed" is simply to have that dir in the path. Most deps are library deps. Why complicate life? (EDIT: also "src/" scopes exactly nothing. It's the same name in every package. "cligen/cligen/" might do scoping work, but "src/" only separates "tests/", "bin/", "docs/" and the like from source which could all just be at the top-level - or whatever.) |
Agree; there are better places to spend the complexity budget, like making sure that versions parse correctly or that requirements result in the proper versions being installed. |
plenty of packages are in a git repo not named identical to the package name, eg: so that can't work; and the reason why you'd want to allow the git repo not be named identical to the nimble package name are obvious, eg if you already have so you sill have to duplicate the package dir, and without src it looks more confusing without src, eg:
it does. The fact that you didn't follow best practice in cligen by prefixing via src means that everything in your cligen git repo is in import scope without even being prefixed by cligen, eg:
I suggest you patch cligen to follow the |
Sure it can. You just
No it doesn't. We are arguing at cross purposes. You seem to have accepted nimble or nimble develop or whatever as a valid constraint for "best practices" to be contingent upon. I'm arguing against it independently as if we were in a world without nimble-induced complexity. I really think you should step back and imagine such a world. There is a very simple manual solution for most packages in that world with no package manager at all. "src/" pushes people away from that world by requiring either file motion or symlinks at "install" time or having "src/" in your Were I to change Your Anyway, I've said about as much on this topic as I care to, including writing an entire almost fully functional program demonstrating the ideas (which I use literally every day just as |
your suggestion is to use With your approach, everything cloned under git_clones is available for import, you can't be granular about it. With the existing approach (what nimble uses), you can simply select which packages are importable explicitly eg: # without mypkg1, mypkg2
nim --path:/patho/git_clones/mypkg1/src --path:/patho/git_clones/mypkg2/src main1.nim
# without mypkg2
nim --path:/patho/git_clones/mypkg1/src main1.nim furthermore you can have several clones of the same package and select (via --path) which one you want, without global effects on the filesystem, all living under the same root /patho/git_clones/. And finally,
it's not specific to nimble. The fact that you have no
# main.nim
import cligen # ok, works
import examples/cols # bug: this is exposed to everyone that can `import cligen` I don't know how to explain this any better than what I already did but maybe @dom96 can? |
@timotheecour what exactly are you afraid of? That someone will manage to position a file near yours and then manipulate your source to import it? That your source will accidentally import a file that it shouldn't have access to? Making files more accessible in the project isn't a bug; it's a feature. If you want to change Nimble, there's a repository for that. This repository is for changes to the compiler. From that perspective, this change is counter to the approach @genotrance invented and which @c-blake and I support; that the package managers can determine the environment whole-cloth, build tools can optionally use this input from the package manager to invoke the compiler, and the compiler can optionally use input from the build tools to compile software. The unidirectional flow of information makes it much easier for each participant to reason about the environment, and narrowing each scope is similarly useful -- the package manager just manages packages, the build tool just builds the project, and the compiler just compiles code. Simple. If you want several clones of the same package (why?) then you can easily do that by changing your package manager to clone the same package several times. But please don't hoist more complexity on literally every single future user of the language -- just add a directory to your file system and point to it with your pm, build tool, or compiler. Thanks. |
For starters, I'm not for Meanwhile, some people don't use nimble and I'm also for removing all nimble / pkg manager specific code from Nim eventually. We have Lastly, there can be 500 ways to do package management and Nim should and can already support that. If nimble does not work well enough and anyone has found a better way, feel free to innovate and succeed on those merits. With hindsight, from scratch solutions can conveniently avoid nimble's legacy but do nothing to solve its issues. |
I will just say that as far as I understand, and I've discussed this matter with @genotrance at length, the package directory structure enforcement made by Nimble will remain. I've even tried to push for a way to resolve it because of the amount of passionate push back from the likes of @c-blake, but we couldn't come up with a better alternative. The reason I'm saying this is because I feel like there is an implicit blame that rests on me when it comes to this feature and that is completely unfair. |
@dom96 - I meant/mean nothing personal or unfair, though my tone may become strident the more sure I am that I am right or the more off track counter arguments seem. I am indeed passionately against src/ (and unnecessary hierarchy/complexity in general) and think it should never have existed and I did complain the moment I was pushed into it by someone due to scary sounding If you really care about qualification, then push To me, every single time someone uses
@timotheecour, to all of these I say, much like @disrpuptek, so what? I think I agree with both his statements and reasoning 100%, especially the information flow/separation of concerns. To follow up on complaints you may feel unaddressed, if client code imports something under In general, this Super diverse repo/branch scenarios should not complicate the life of 99% user when there is a simple solution already using directories and search paths in the natural way (analogizing For complex version scenarios, I could have one top-level dir switch In terms of this RFC more specifically, I agree with @genotrance about just using "." (possibly with a quotes requirement) is better than a new keyword "this/foo". It's probably what most people think "." should do already anyway. That's sort of how $PATH search in Unix works. C preprocessors have a similar distinction between I already think module import should allow stropping |
If it can be interpreted as "./foo.nim" that is the interpreation that is picked up. I try to avoid "--path" as far as reasonable. The fact that it's "import strutils" and not "import std / strutils" is a legacy and you can view these modules as keywords. New standard modules are always under "std", so it's a fixed set of keyword-like imports. Having said that, I agree with @c-blake's and @disruptek's views. Nimble created a set of problems (and not only solutions) and we're getting a better Nimble thanks to @genotrance's superb work. As for "nimp" and "nimph", I don't mind package manager experiements, heck I did my own with "nawabs" (now dead) but we're well served with a single standard tool. Heretical thought: Rename "nimp" to "nimble" (version 2.0) and make it reasonably command line compatible. I know it's not realistic, but even such a radical solution would cause far fewer disruptions than multiple competing packager managers. |
Also, to give Nimble some credit: The "namespacing" design predated our |
Confirmed, still seems like a good idea. :-) |
Regardless of how all these things work or should work, what is the benefit of "this" over the existing and widely used "."? Let's please close this RFC. The discussion is interesting but has been done elsewhere already. |
@Araq I think we should seriously consider this RFC, it removes ambiguities; with this RFC:
in nim-lang/Nim#17426 (comment) you mention:
however this guideline doesn't work, nor should it IMO: for eg in and writing with this RFC, this would simply be: import this/enumutils with 0 possible chances of clashing with something you're not expecting, and this works from anywhere inside the same package (stdlib in this case), without having to compute relative paths (../std/enumutils), nor with any hacks. to re-iterate: import this/os
import this/tables
import this/enumutils
import this/private/since # not this/since |
Won't they be able to tell this naturally? If they're importing using a relative import, it can be assumed that they're importing within the package. Otherwise, they're using an absolute import, which will indicate the same thing.
How often does this actually happen? The compiler produces output on what modules are used, and if, by some rare chance, you do have a module with the same name, you'll get compile-time errors regardless. |
@timotheecour , besides @Varriount's fine questions, you still are not motivating why |
But relative paths are the best solution in my opinion -- clear, independent of the --path state, not machine specific. We should discourage --path and --path-like solutions and encourage relative paths. They work and are the simplest design that works. Also... the "lib/pure" setup is a hack and standard modules should be in "std" anyway. However -- we still need a way to get os2.nim and json2.nim modules into the standard, somehow. Different topic. |
it's not possible without having to do detective work, eg look at https://github.com/yglukhov/nimx/blob/master/nimx/view.nim
which of those are local vs external imports? add to the mix the fact that
there's no way to tell whether a path like
as mentioned above, there's no way to tell whether |
But I don't think package-anything should have to connect with this. The less we intertwine the compiler import system and the packaging system the better, IMO. Partly because the packaging system seems like a mess, but partly just on foundational separation of concerns terms. I don't see cut & paste & translate imports from a defining package to a client package as a very common use case to optimize for (or in your words "looking the same"). If many-module-in-deep-folder-hierarchy package authors want that property, they can get it by importing with |
I've suggested that before, see nim-lang/Nim#8608, but it was closed. see also @Araq's remark in nim-lang/Nim#7250 (comment)
IMO relative imports SHOULD start with ./ or ../, and this should become the prefered style; we can develop tooling to help in this migration, but that would require changing the above stance regarding EDIT: |
Orthogonal questions: Taking the example from #267 (comment)
Is the below the most restrictive way to write it? Should we consider it the most readable/idiomatic? import std/[typetraits, tables]
import pkg/kiwi
import "."/[types, context, animation_runner, layout_vars]
import "."/property_visitor
import "."/class_registry
import "."/serializers
import "."/notification_center Somewhat similar to the
But maybe disabled by default, given that I believe we can't add it to |
I still think it's ugly, but more importantly, what else should |
so this gives (currently) a false sense of hygiene, but if this were fixed, i would agree with requiring/encouraging this new syntax (but with
the problem is that it can mean different things depending on context (maybe x is a nimble package, eg regex:
that would be clear progress, but it's not enough. These should hold: # this must resolve to a local import, ie `currentSourcePath.parentDir/foo.nim`:
import ./foo
# ditto
import ./bar/foo
# ditto
import ./[foo, bar]
# this is fine:
import std/tables
import pkg/regex
import pkg/regex/foo this should give a deprecation warnings eventually (maybe after tooling is developped to help fix those automatically):
as @yglukhov mentioned here: nim-lang/Nim#8608 (comment)
|
Why not like this: import std / tables # sure, what else.
import tables # deprecated, but allowed for old std modules.
import ast # local, relative import
import "." / ast # same as 'import ast' but discouraged because longer
import ".." / [ast] # local, relative import
import compiler / ast # local, relative import
import pkg / compiler / [ast] # 'pkg' means take --path and --nimblePath into account
This way only EDIT: I do not recommend the |
Another unmentioned aspect in play here is at odds with the entire general notion of "precise import", but takes a bit of elaboration to explain. A client package (in nimble or not, just client code really) being able to replace just one module file from something it depends upon. I have a few things in It's not always easy to know when to disallow, though. So, you kind of want to lean toward allowing it almost all the time. E.g., someone might want to replace So, if the whole stdlib (or something else beyond your control that has a lot of cross internal dependency) is doing precise, enforced relative imports everywhere then you need to put a clone of the whole thing, or at least all modules that transitively import anything you wanted to change into your source tree. Yuck. Hygiene in the small has now led to a mess in the large (not unlike nimble's src/ shenanigans which actually impact this use case, too, but that is a longer story.). And, honestly, that is a far more tricky computation than the ".." thing @timotheecour was complaining about. You may object to this "surgical substitution" example as an ill-advised, obscure uncommon use case, but it was actually one of the things that made Symbolics Lisp Machines of the 1980s so popular among people I've spoken to who used them. The power of simple tweaks should not be underestimated, especially among developers whose tastes and priorities can differ dramatically. It's obviously a kind of "expert mode", and it can cut both ways, of course, by breaking things, but Nim is also a kind of a great power/great responsibility language in most of its philosophy. I think of it a lot like defining some new variant of a TL;DR - getting a different module than what "looks obvious" can be a feature, not a bug, and the more intricate the web of dependencies, the more likely it can be a feature, actually, because that's when it's hardest to replace other ways. So, there are some real conflicting concerns here. Maybe the resolution is "screw the expert mode people wanting to hot patch/hack patch the stdlib/other stuff". Maybe that's already written in stone and just "assumed", but I didn't think it should go without mention. Or maybe I'm missing some logical step making such substitution easy in these New World Orders underway/being proposed. Apologies if so. |
Maybe a better TL;DR - proc names are (usually) unqualified not |
Looks good to me. Especially if: import ./tables # is an error/warning if there is no local, relative `tables`
import "."/tables # is an error/warning if there is no local, relative `tables`
import ./[foo, bar] # no longer produces an error if `foo` and `bar` are local, relative imports
import "."/[foo, bar] # works like `./[foo, bar]`, which we could encourage instead @c-blake Do you think the Some related forum threads: |
Ok. I was just reading the docs for |
Well, I just tested it and I still think package/module name management should be as close to regular module/symbol as possible and not interact much with the package manager, and I think we're off that road. As a strawman analogy, nimscript shenanigans to define a new local scope |
Are the current import semantics documented anywhere? |
@Araq So, this would mean that non-stdlib "external" modules (like say, NPeg) would be referenced through "pkg"? |
proposal
turn
this
into a reserved keyword (likestd
andpkg
) when resolving imports, and resolves to the enclosing nimble package root directoryexample
file layout:
rationale
..
, which are common especially in projects with multiple directories:One additional advantage is that external use matches internal use, with
s/this/arraymancer/
, as shown above.it's immediately clear which imports refer to current nimble package vs external packages, unlike with relative paths that don't start with
..
(and even those don't guarantee that)note
import this/foo
would've previously resolved to./this/foo.nim
(ie a directory ./this exists), then it would resolve to thatThe text was updated successfully, but these errors were encountered: