Thread overview
Re: import from subdir
Dec 23, 2010
Jonathan M Davis
Dec 23, 2010
spir
Dec 23, 2010
Jonathan M Davis
Dec 24, 2010
spir
Dec 24, 2010
Jonathan M Davis
December 23, 2010
On Thursday 23 December 2010 04:38:56 spir wrote:
> Hello,
> 
> Say I have a project with the following tree structure:
> 
> [app]
> 	app.d
> 	util.d
> 	[test]
> 		test.d
> 	[data]
> 		data.d
> 
> Is there a way to import util & data from test?

Use the -I flag when compiling. Presumably, you'd do something like -I../ so that it would also search for files starting at the parent directory.

- Jonathan M Davis
December 23, 2010
On Thu, 23 Dec 2010 05:26:57 -0800
Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> On Thursday 23 December 2010 04:38:56 spir wrote:
> > Hello,
> > 
> > Say I have a project with the following tree structure:
> > 
> > [app]
> > 	app.d
> > 	util.d
> > 	[test]
> > 		test.d
> > 	[data]
> > 		data.d
> > 
> > Is there a way to import util & data from test?
> 
> Use the -I flag when compiling. Presumably, you'd do something like -I../ so that it would also search for files starting at the parent directory.
> 
> - Jonathan M Davis

Thank you, I'll try this solution. So, there is no syntax? (I tried "import ..util;" and import "..data.data;" without any success ;-)

What about proposing that each _single_ leading dot moves up one dir? In my case, this would give "import .util;" and "import .data.data;". I find this simple, practical and very useful.


Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com

December 23, 2010
On Thursday 23 December 2010 05:59:37 spir wrote:
> On Thu, 23 Dec 2010 05:26:57 -0800
> 
> Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> > On Thursday 23 December 2010 04:38:56 spir wrote:
> > > Hello,
> > > 
> > > Say I have a project with the following tree structure:
> > > 
> > > [app]
> > > 
> > > 	app.d
> > > 	util.d
> > > 	[test]
> > > 
> > > 		test.d
> > > 
> > > 	[data]
> > > 
> > > 		data.d
> > > 
> > > Is there a way to import util & data from test?
> > 
> > Use the -I flag when compiling. Presumably, you'd do something like -I../ so that it would also search for files starting at the parent directory.
> > 
> > - Jonathan M Davis
> 
> Thank you, I'll try this solution. So, there is no syntax? (I tried "import ..util;" and import "..data.data;" without any success ;-)
> 
> What about proposing that each _single_ leading dot moves up one dir? In my case, this would give "import .util;" and "import .data.data;". I find this simple, practical and very useful.

Packages and modules follow the file system's structure, but they're _not_ intended to be traversing the file system. So, if you have the module a.b.c, then it will be the file a/b/c.d where a is either in the base directory of compilation or in a directory given to dmd with the -I flag. But from the module's perspective, it doesn't care that packages equate to directories on disk or that module equate to files on disk. It's giving the compiler a module name, and the compiler finds it with the assumption that packages equate to directories and modules equate to files. But there's nothing stopping D from changing things so that having a file name a.b.c.d would be the module a.b.c. That change definitely won't be made, but the point is that in D, module names are effectively divorced from the file system as far as the language is concerned. It's just that the language specifies that packages equate to directories and modules equate to files in order to simplify the compilation process and simplify the job of any D-related tools.

What you're trying to do is pretty abnormal really, as far as your average module goes. I assume that you're writing a test app which needs access to the main body of code and are trying to find a way to point it to that code without mixing the two. The normal way to deal with that would be -I. The same goes for C++ actually. Not to mention, you probably don't want your tests to rely on where they are on disk in comparison to the rest of your code. If you later want to change where you put your test code, it could be a big hassle to have to go change all of your imports. Just use -I. It makes your test code properly portable and is really the intended way to do the sort of thing that you're trying to do.

- Jonathan M Davis
December 24, 2010
On Thu, 23 Dec 2010 12:54:42 -0800
Jonathan M Davis <jmdavisProg@gmx.com> wrote:

> What you're trying to do is pretty abnormal really, as far as your average module goes. I assume that you're writing a test app which needs access to the main body of code and are trying to find a way to point it to that code without mixing the two.

What is then abnormal in having test modules in their own dir? And indeed they need to import the module(s) they're supposed to test (and possibly ordinary and test data from another dir). AFAIK, this is very ordinary lib structuration for the sake of clarity. Dunno.

> The normal way to deal with that would be -I. The same goes for C++ actually. Not to mention, you probably don't want your tests to rely on where they are on disk in comparison to the rest of your code. If you later want to change where you put your test code, it could be a big hassle to have to go change all of your imports. Just use -I. It makes your test code properly portable and is really the intended way to do the sort of thing that you're trying to do.

Hem, I do not find a hassle to change one a few import once if ever I move a test module in the dir tree. But I find very unconvenient to have different compile/link command lines for every module just because of the lack of an importing syntax, requiring the use of -I. Instead of a command-line option, I would prefere to write it down once and for in the module itself. Maybe we could have something like
	pathlevel 2;
saying that (when an imported module is not found) the indicated path is to be understood as relative to 2 dir levels higher (which would probably be the root of the lib).

By the way, when I write "import data.foo", the language actually searches and inside /data (relative to the current module's dir) and find foo.d there. (Even if the module is not explicitely named at all.) So, there is still an implicite or default relationship between dir tree structure and module denomination. Or do I misinterpret your words?

Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com

December 24, 2010
On Thursday 23 December 2010 16:42:15 spir wrote:
> On Thu, 23 Dec 2010 12:54:42 -0800
> 
> Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> > What you're trying to do is pretty abnormal really, as far as your average module goes. I assume that you're writing a test app which needs access to the main body of code and are trying to find a way to point it to that code without mixing the two.
> 
> What is then abnormal in having test modules in their own dir? And indeed they need to import the module(s) they're supposed to test (and possibly ordinary and test data from another dir). AFAIK, this is very ordinary lib structuration for the sake of clarity. Dunno.

What is abnormal is having your test code rely where your normal code is on disk. Also, depending on what you're doing for testing, normally you'd just have the unit tests alongside your normal code and do a unittest build to test your code. So, you wouldn't even need separate test code unless you're doing something more exotic that you don't want in your unit tests.

> > The normal way to deal with that would be -I. The same goes for
> > C++ actually. Not to mention, you probably don't want your tests to rely
> > on where they are on disk in comparison to the rest of your code. If you
> > later want to change where you put your test code, it could be a big
> > hassle to have to go change all of your imports. Just use -I. It makes
> > your test code properly portable and is really the intended way to do
> > the sort of thing that you're trying to do.
> 
> Hem, I do not find a hassle to change one a few import once if ever I move
> a test module in the dir tree. But I find very unconvenient to have
> different compile/link command lines for every module just because of the
> lack of an importing syntax, requiring the use of -I. Instead of a
> command-line option, I would prefere to write it down once and for in the
> module itself. Maybe we could have something like pathlevel 2;
> saying that (when an imported module is not found) the indicated path is to
> be understood as relative to 2 dir levels higher (which would probably be
> the root of the lib).
> 
> By the way, when I write "import data.foo", the language actually searches and inside /data (relative to the current module's dir) and find foo.d there. (Even if the module is not explicitely named at all.) So, there is still an implicite or default relationship between dir tree structure and module denomination. Or do I misinterpret your words?

You misunderstand. From the module's perspective, import foo.bar; imports a module with the name foo.bar. It knows that bar is in the foo package, so unless the module doing the importing is in the foo package, it can't access the package-restricted functions and types from foo.bar or any other module in foo. It knows that bar is the module. But it doesn't care at all about what that means for files on disk. Consider the fact that you can have this directory structure:

dir/dir1/foo/bar.d
dir/dir2/dir3/hello/world.d
dir/dir2/dir3/foo/silly.d

where you're compiling from dir/dir2/dir3 and have -I../../dir1/. bar.d and silly.d are considered to be in the same package in spite of the fact that the fact that they're in different directories. When hello.world imports foo.bar, it doesn't care that it's not in the same directory as foo.silly. If foo.silly calls a package-restricted function in foo.bar, it's allowed to because they're in the same package, but it doesn't care that they're not in the same directory.

The directory structure relates to the package hierarchy. The compiler finds files using that structure/hierarchy. It knows that if a module is importing foo.bar, that there is a directory foo either in  the directory where compilation is taking place or in one of the directories given by the -I flag, and it knows that bar.d (or bar.di) will be in the foo directory. If there are multiple such directories (because of the -I flag being used), then it knows that bar.d is in one of them (if it were in more than one, then there would be an ambiguity error). The package hiercharcy tells the compiler where the source files are.

However, the imports themselves don't care at all about the directory structure. As shown in the example above, you could have each module in a package in a different directory as long as it was in the appropriate place in the directory structure given all of the -I flags being used. So, importing has no concept of directories or files - only packages and modules. The compiler is able to translate that to directories and files, but the imports don't care about it. From the language's perspective, it would be perfectly possible to change it so that all files were always in the same directory but used dots to separate packages and modules:

dir/dir1/foo.bar.d
dir/dir2/dir3/hello.world.d
dir/dir2/dir3/foo.silly.d

Now, no compiler is going to function that way, but conceptually, it could. So, trying to use .. and the like in an import statement to walk directory structure doesn't really make sense.

- Jonathan M Davis