www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Keyword "package" prevents from importing a package module "package.d"

reply BoQsc <vaidas.boqsc gmail.com> writes:
![](https://i.imgur.com/829CzOS.png)

Source File **package.d** is a [package module][1] which contains 
import statements to import other modules.

How would one import a **package.d** module when [**keyword 
"package"**][2] is preventing that?



[1]: https://dlang.org/spec/module.html#package-module
[2]: https://dlang.org/spec/attribute.html#visibility_attributes

Example:
```
import package;
```
Error:

```
datatypes.d(1): Error: identifier expected following `import`
datatypes.d(1): Error: `;` expected
```
---

example](https://run.dlang.io/is/f3jURn)

Expected correct result if `package.d` was possible to import:

```
waffles/program.d(6): Error: `num` matches conflicting symbols:
waffles/testing1.d(1):        variable `testing1.num`
waffles/testing2.d(1):        variable `testing2.num`
```
Nov 02 2023
parent reply BoQsc <vaidas.boqsc gmail.com> writes:
Edit incorrect link to example:

 example](https://run.dlang.io/is/f3jURn)
Correct link: https://run.dlang.io/is/Zbrn75
Nov 02 2023
parent reply Arafel <er.krali gmail.com> writes:
On 02.11.23 11:45, BoQsc wrote:
 Edit incorrect link to example:
https://run.dlang.io/is/f3jURn)
Correct link: https://run.dlang.io/is/Zbrn75
``` --- waffles/program.d import waffles; ``` See https://dlang.org/spec/module.html#package-module
Nov 02 2023
parent reply BoQsc <vaidas.boqsc gmail.com> writes:
On Thursday, 2 November 2023 at 10:53:12 UTC, Arafel wrote:
 On 02.11.23 11:45, BoQsc wrote:
 Edit incorrect link to example:

 example](https://run.dlang.io/is/f3jURn)
Correct link: https://run.dlang.io/is/Zbrn75
``` --- waffles/program.d import waffles; ``` See https://dlang.org/spec/module.html#package-module
Weirdly enough it does not work on Windows operating system. ![](https://i.imgur.com/x47fcNF.png) ``` program.d(1): Error: unable to read module `waffles` program.d(1): Expected 'waffles.d' or 'waffles\package.d' in one of the following import paths: import path[0] = . import path[1] = C:\D\dmd2\windows\bin\..\..\src\phobos import path[2] = C:\D\dmd2\windows\bin\..\..\src\druntime\import Failed: ["C:\\D\\dmd2\\windows\\bin\\dmd.exe", "-v", "-o-", "program.d", "-I."] C:\waffles>dmd -i -run program.d program.d(1): Error: unable to read module `waffles` program.d(1): Expected 'waffles.d' or 'waffles\package.d' in one of the following import paths: import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos import path[1] = C:\D\dmd2\windows\bin64\..\..\src\druntime\import ```
Nov 02 2023
next sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 2 November 2023 at 11:12:58 UTC, BoQsc wrote:
 On Thursday, 2 November 2023 at 10:53:12 UTC, Arafel wrote:
 On 02.11.23 11:45, BoQsc wrote:
 Edit incorrect link to example:

 example](https://run.dlang.io/is/f3jURn)
Correct link: https://run.dlang.io/is/Zbrn75
```d --- waffles/program.d import waffles; void main() { import std; writeln(num); } --- waffles/package.d module waffles; public import waffles.testing1; public import waffles.testing2; --- waffles/testing1.d int num = 5; --- waffles/testing2.d int num2 = 9; ```
Nov 02 2023
parent reply BoQsc <vaidas.boqsc gmail.com> writes:
On Thursday, 2 November 2023 at 11:32:40 UTC, Imperatorn wrote:
 On Thursday, 2 November 2023 at 11:12:58 UTC, BoQsc wrote:
 On Thursday, 2 November 2023 at 10:53:12 UTC, Arafel wrote:
 On 02.11.23 11:45, BoQsc wrote:
 Edit incorrect link to example:

 example](https://run.dlang.io/is/f3jURn)
Correct link: https://run.dlang.io/is/Zbrn75
```d --- waffles/program.d import waffles; void main() { import std; writeln(num); } --- waffles/package.d module waffles; public import waffles.testing1; public import waffles.testing2; --- waffles/testing1.d int num = 5; --- waffles/testing2.d int num2 = 9; ```
`num` and `num2` was never a problem. The current major problem is that it does not work on Windows operating system with either `rdmd` or `dmd`. While it does work on run.dlang.io.
Nov 02 2023
next sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 2 November 2023 at 11:57:57 UTC, BoQsc wrote:
 On Thursday, 2 November 2023 at 11:32:40 UTC, Imperatorn wrote:
 On Thursday, 2 November 2023 at 11:12:58 UTC, BoQsc wrote:
 On Thursday, 2 November 2023 at 10:53:12 UTC, Arafel wrote:
 On 02.11.23 11:45, BoQsc wrote:
 [...]
```d --- waffles/program.d import waffles; void main() { import std; writeln(num); } --- waffles/package.d module waffles; public import waffles.testing1; public import waffles.testing2; --- waffles/testing1.d int num = 5; --- waffles/testing2.d int num2 = 9; ```
`num` and `num2` was never a problem. The current major problem is that it does not work on Windows operating system with either `rdmd` or `dmd`. While it does work on run.dlang.io.
That's not all I changed. It works for me on Windows.
Nov 02 2023
prev sibling parent reply Arafel <er.krali gmail.com> writes:
On 02.11.23 12:57, BoQsc wrote:
 The current major problem is that it does not work on Windows operating 
 system with either `rdmd` or `dmd`. While it does work on run.dlang.io.
The problem is with your import path. If you say: ```d import waffles; ``` The compiler would search for either `waffles.d` or `waffles/package.d` **in your current working directory**. So you have three options: 1. You can compile from the parent directory, most likely what run.dlang.io does: `dmd -i -run waffles/program.d` 2. You can explicitly add all the files to the dmd invocation (I think this is what dub does), although that likely defeats the purpose of `rdmd` and `dmd -i`. 3. You can add `..` (the parent directory) to your search path: `dmd -I.. [......]` Actually, the cleanest (and in my view proper) solution would be to create a new `waffles` directory with the "package" itself, and take the main function out of it, so you'd have: ``` waffles | +-- program.d | +-- waffles | +-- package.d | +-- testing1.d | +-- testing2.d ```
Nov 02 2023
parent reply BoQsc <vaidas.boqsc gmail.com> writes:
Well the whole thread is about importing `package.d` while being 
inside package to provide runnable working example which contains 
debug information of the package.

Sidenote:
This is essentially useful when distributing over many 
machines/platforms via `dub` package manager.

You would want to have a source file inside the project that 
imports package.d and is runnable with well tested example 
behaviour.

Therefore the need to import `package.d` is needed and I can't 
see a solution, which means
  that D Language might have to introduce a way to import 
`package.d` from inside the package, if there is a need to 
further improve experience of having a self-testing packages in 
both `dub` and `package modules`.
Nov 02 2023
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 2 November 2023 at 12:52:35 UTC, BoQsc wrote:
 Therefore the need to import `package.d` is needed and I can't 
 see a solution, which means
tbh package.d should never be used. It is a poorly designed, buggy misfeature of the language with plenty of better working alternatives (it is no different than making a `module yourthing.all;` people can import execpt with more limitations and bugs.)
Nov 02 2023
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Thursday, November 2, 2023 7:04:37 AM MDT Adam D Ruppe via Digitalmars-d-
learn wrote:
 On Thursday, 2 November 2023 at 12:52:35 UTC, BoQsc wrote:
 Therefore the need to import `package.d` is needed and I can't
 see a solution, which means
tbh package.d should never be used. It is a poorly designed, buggy misfeature of the language with plenty of better working alternatives (it is no different than making a `module yourthing.all;` people can import execpt with more limitations and bugs.)
The entire reason that it was added to the language was to be able to split up existing modules without breaking code. And it does that well. It was never intended to be used for anything else, but of course, some people always find ways to misuse a feature. package.d is indeed completely unnecessary for creating a module that publicly imports other modules in order to be able to import a single module and get several modules. Either way, personally, I don't think that that's something that should typically be done (with package.d or with any module name), but for whatever reason, some folks seem to love the idea. - Jonathan M Davis
Nov 02 2023
parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 2 November 2023 at 19:30:58 UTC, Jonathan M Davis 
wrote:
 The entire reason that it was added to the language was to be 
 able to split up existing modules without breaking code. And it 
 does that well.
No, it doesn't do that well at all. In fact, it does that so extremely poorly that (as you might recall) there were a very large number of support requests shortly after Phobos started using it about broken builds, since it would keep the old file and the new file when you updated and this stupid, idiotic design can't handle that situation. This only subsided because enough time has passed that nobody tries using it to break up existing modules anymore. It is just a *terrible* design that never should have passed review. It is randomly inconsistent with the rest of the language and this manifests as several bugs. (including but not limited to: https://issues.dlang.org/show_bug.cgi?id=14687 doesn't work with .di https://issues.dlang.org/show_bug.cgi?id=17699 breaks if you try to use it for its intended purpose https://issues.dlang.org/show_bug.cgi?id=20563 error messages hit random problems <can't find the link> all-at-once vs separate compilation of package leads to inconsistent reflection results im sure the list went on if i spent a few more minutes looking for my archives)
 package.d is indeed completely unnecessary for creating a 
 module that publicly imports other modules in order to be able 
 to import a single module and get several modules.
Yeah, it is a terrible feature that is poorly designed, hackily implemented, and serves no legitimate use case.
Nov 02 2023
parent reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Thursday, 2 November 2023 at 19:43:01 UTC, Adam D Ruppe wrote:
 On Thursday, 2 November 2023 at 19:30:58 UTC, Jonathan M Davis 
 wrote:
 The entire reason that it was added to the language was to be 
 able to split up existing modules without breaking code. And 
 it does that well.
No, it doesn't do that well at all. In fact, it does that so extremely poorly that (as you might recall) there were a very large number of support requests shortly after Phobos started using it about broken builds, since it would keep the old file and the new file when you updated and this stupid, idiotic design can't handle that situation. This only subsided because enough time has passed that nobody tries using it to break up existing modules anymore. It is just a *terrible* design that never should have passed review. It is randomly inconsistent with the rest of the language and this manifests as several bugs. (including but not limited to: https://issues.dlang.org/show_bug.cgi?id=14687 doesn't work with .di https://issues.dlang.org/show_bug.cgi?id=17699 breaks if you try to use it for its intended purpose https://issues.dlang.org/show_bug.cgi?id=20563 error messages hit random problems <can't find the link> all-at-once vs separate compilation of package leads to inconsistent reflection results im sure the list went on if i spent a few more minutes looking for my archives)
 package.d is indeed completely unnecessary for creating a 
 module that publicly imports other modules in order to be able 
 to import a single module and get several modules.
Yeah, it is a terrible feature that is poorly designed, hackily implemented, and serves no legitimate use case.
Is there any guide how one can refactor single-module package into multi-module package with distinction between public and private modules?
Nov 02 2023
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Fri, Nov 03, 2023 at 12:19:48AM +0000, Andrey Zherikov via
Digitalmars-d-learn wrote:
 On Thursday, 2 November 2023 at 19:43:01 UTC, Adam D Ruppe wrote:
 On Thursday, 2 November 2023 at 19:30:58 UTC, Jonathan M Davis wrote:
 The entire reason that it was added to the language was to be able
 to split up existing modules without breaking code. And it does that
 well.
No, it doesn't do that well at all. In fact, it does that so extremely poorly that (as you might recall) there were a very large number of support requests shortly after Phobos started using it about broken builds, since it would keep the old file and the new file when you updated and this stupid, idiotic design can't handle that situation. This only subsided because enough time has passed that nobody tries using it to break up existing modules anymore. It is just a *terrible* design that never should have passed review. It is randomly inconsistent with the rest of the language and this manifests as several bugs. (including but not limited to: https://issues.dlang.org/show_bug.cgi?id=14687 doesn't work with .di https://issues.dlang.org/show_bug.cgi?id=17699 breaks if you try to use it for its intended purpose https://issues.dlang.org/show_bug.cgi?id=20563 error messages hit random problems <can't find the link> all-at-once vs separate compilation of package leads to inconsistent reflection results im sure the list went on if i spent a few more minutes looking for my archives)
 package.d is indeed completely unnecessary for creating a module
 that publicly imports other modules in order to be able to import a
 single module and get several modules.
Yeah, it is a terrible feature that is poorly designed, hackily implemented, and serves no legitimate use case.
Is there any guide how one can refactor single-module package into multi-module package with distinction between public and private modules?
Supposedly you can do this: /* Original: */ // pkg/mymodule.d module mymodule; ... // code here // main.d import mymodule; void main() { ... } /* Split */ // pkg/mymodule/pub_submod.d module mymodule.pub_submod; ... // code here // pkg/mymodule/priv_submod.d module mymodule.priv_submod; ... // code here // pkg/mymodule/package.d module mymodule; public import priv_submod; // main.d import mymodule; void main() { ... } Barring the issues listed above, of course. T -- "The number you have dialed is imaginary. Please rotate your phone 90 degrees and try again."
Nov 02 2023
parent reply Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Friday, 3 November 2023 at 00:52:18 UTC, H. S. Teoh wrote:
 Supposedly you can do this:

 	/* Original: */

 	// pkg/mymodule.d
 	module mymodule;
 	... // code here

 	// main.d
 	import mymodule;
 	void main() { ... }

 	/* Split */

 	// pkg/mymodule/pub_submod.d
 	module mymodule.pub_submod;
 	... // code here

 	// pkg/mymodule/priv_submod.d
 	module mymodule.priv_submod;
 	... // code here

 	// pkg/mymodule/package.d
 	module mymodule;
 	public import priv_submod;

 	// main.d
 	import mymodule;
 	void main() { ... }

 Barring the issues listed above, of course.
I know how to do this with package.d but my question was about "package.d is bad design decision" - How would I do this refactoring without dedicated "main package file"? Python, for example, has __init__.py as well
Nov 03 2023
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, November 3, 2023 5:20:56 AM MDT Andrey Zherikov via Digitalmars-d-
learn wrote:
 On Friday, 3 November 2023 at 00:52:18 UTC, H. S. Teoh wrote:
 Supposedly you can do this:
     /* Original: */

     // pkg/mymodule.d
     module mymodule;
     ... // code here

     // main.d
     import mymodule;
     void main() { ... }

     /* Split */

     // pkg/mymodule/pub_submod.d
     module mymodule.pub_submod;
     ... // code here

     // pkg/mymodule/priv_submod.d
     module mymodule.priv_submod;
     ... // code here

     // pkg/mymodule/package.d
     module mymodule;
     public import priv_submod;

     // main.d
     import mymodule;
     void main() { ... }

 Barring the issues listed above, of course.
I know how to do this with package.d but my question was about "package.d is bad design decision" - How would I do this refactoring without dedicated "main package file"? Python, for example, has __init__.py as well
You don't. package.d is the only solution that the language provides to split up a module in place without breaking code, and in general, it works just fine. The issues that Adam was complaining about relate to bad installs where you end up with both the old mymodule.d file and mymodule/package.d on someone's system. The language does not handle that well (and that should be fixed), but as long as the new files are installed properly (which would include removing all of the old ones first), there isn't a problem. The issue came up with Phobos because of folks who assumed that they could just unzip a dmd install on top of another one without removing the old one first, which will always be risky business if the set of modules changes (which could also include module removals without introducing a corresponding package.d, though that only happens after an appropriate deprecation period). However, because the list of modules usually only grows, some folks had been getting away with it before and weren't expecting issues when either modules were removed or when they ended up with both std/datetime.d and std/datetime/package.d on their system, because they didn't actually remove the old install first. But since they hadn't been removing their old install first, they ran into issues when modules were split up in-place. Whatever the pros and cons are for package.d overall, the entire reason that it exists is to allow you to replace a module with a package, and Walter went with that solution, because it required minimal changes to the language. All of the semantics with public imports are what you get normally. It's just that the compiler now will import foo/package.d when you say import foo; and foo/package.d exists instead of requiring that it be foo.d. If you don't want to use package.d as a solution for breaking up a module, then your only option is to do so by changing your modules in manner which will involve the new modules being named something completely different. E.G. mymodule.d becomes foo/a.d and foo/b.d, with public imports in mymodule.d like you would have done in mymodule/package.d. You then either deprecate everything in mymodule.d so that folks will eventually change their code to use foo/a.d and foo/b.d directly, or you leave the code in the weird situation of everything being in the foo package, but existing code continues to import mymodule potentially forever. - Jonathan M Davis
Nov 03 2023
parent Andrey Zherikov <andrey.zherikov gmail.com> writes:
On Friday, 3 November 2023 at 18:04:58 UTC, Jonathan M Davis 
wrote:
 - Jonathan M Davis
Thanks a lot for detailed explanation!
Nov 03 2023
prev sibling parent Adam D Ruppe <destructionator gmail.com> writes:
On Friday, 3 November 2023 at 00:19:48 UTC, Andrey Zherikov wrote:
 Is there any guide how one can refactor single-module package 
 into multi-module package with distinction between public and 
 private modules?
Call the modules literally anything else and it works better. So say you have module foo.bar. You could keep that and put your multiple modules in a different thing like foo.bar_parts.part and foo.bar_parts.part2. This maintains compatibility on the user side; if they were previously using foo.bar, things keep working for them. Or, you could keep everything under foo.bar, but add a foo.bar.all that provides the old api. Users would have to adjust their imports to say `import foo.bar.all;` instead. This has more potential for transition breakage, but it keeps the new modules under the old namespace. I recommend option 1: having the new foo.bar_parts where the implementation actually goes. (Or you could call it whatever you want.) This avoids the whole package.d thing while still letting you and your user arrange modules how you like. You might also have a thing like `foo.bar_implementation` which is not intended for public use.
Nov 03 2023
prev sibling next sibling parent reply Arafel <er.krali gmail.com> writes:
On 02.11.23 13:52, BoQsc wrote:
 Well the whole thread is about importing `package.d` while being inside 
 package to provide runnable working example which contains debug 
 information of the package.
Sorry, but I have never seen a package that includes examples within the package directory itself, nor am I able to imagine why anybody would want that. It would just be polluting the package folder with unnecessary files. Examples are usually distributed in a separate directory, usually at the highest level of the distributable. As for tests, there are `unittest` blocks, and if necessary, they are placed in yet another separate directory. Anyway, your point is moot, because even if you were able to import `package.d`, it would still fail at: ``` public import waffle.testing1; public import waffle.testing2; ``` and for exactly the same reason: the compiler would look for `waffle/testing1.d` and it wouldn't find it withing `waffle/`. You simply can't expect to do `import waffle.foo` from within `waffle/` itself (unless you have another `waffle` folder in it, which is often the case). You always invoke the compiler from the outside the package structure, that's also how it works in java.
Nov 02 2023
parent Arafel <er.krali gmail.com> writes:
On 02.11.23 14:15, Arafel wrote:
 
 You simply can't expect to do `import waffle.foo` from within `waffle/` 
 itself (unless you have another `waffle` folder in it, which is often 
 the case).
Sorry, this is wrong. It should read: You simply can't expect to do `import waffle.foo` **when invoking the compiler** within `waffle/` itself (unless you have another `waffle` folder in it, which is often the case). You are actually perfectly fine to import other parts of the same package, as long as you run the compiler from right outside the package, or adjust the import paths accordingly.
Nov 02 2023
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 2 November 2023 at 12:52:35 UTC, BoQsc wrote:
 Therefore the need to import `package.d` is needed and I can't 
 see a solution, which means
  that D Language might have to introduce a way to import 
 `package.d` from inside the package, if there is a need to 
 further improve experience of having a self-testing packages in 
 both `dub` and `package modules`.
It's perfectly legal to write `import packagename;` in a file that's inside the `packagename/` directory. You just have to make sure that *the current directory in your terminal window* is outside the `packagename/` directory when you run the compiler. The D compiler *always* looks up files *relative to your terminal's current directory*. It does not care at all where the files are relative to each other.
Nov 02 2023
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 2 November 2023 at 11:12:58 UTC, BoQsc wrote:
 Weirdly enough it does not work on Windows operating system.
 [...]
 ```
 program.d(1): Error: unable to read module `waffles`
 program.d(1):        Expected 'waffles.d' or 
 'waffles\package.d' in one of the following import paths:
 import path[0] = .
 import path[1] = C:\D\dmd2\windows\bin\..\..\src\phobos
 import path[2] = C:\D\dmd2\windows\bin\..\..\src\druntime\import
 Failed: ["C:\\D\\dmd2\\windows\\bin\\dmd.exe", "-v", "-o-", 
 "program.d", "-I."]

 C:\waffles>dmd -i -run program.d
 program.d(1): Error: unable to read module `waffles`
 program.d(1):        Expected 'waffles.d' or 
 'waffles\package.d' in one of the following import paths:
 import path[0] = C:\D\dmd2\windows\bin64\..\..\src\phobos
 import path[1] = 
 C:\D\dmd2\windows\bin64\..\..\src\druntime\import

 ```
The problem is the directory you're running the command from. You need to run `dmd` from the parent directory of `waffles`.
Nov 02 2023