hatch icon indicating copy to clipboard operation
hatch copied to clipboard

ModuleNotFoundError

Open LIghtJUNction opened this issue 6 months ago • 16 comments

Bug Report: Inconsistent behavior between packages = ["src/astrbot"] and packages = ["astrbot"] in editable installs

Background

I'm experiencing an issue that was initially reported to the uv project, but the maintainers correctly identified this as a hatch/hatchling behavior rather than a uv issue. I'm now reporting it here as suggested.

Original discussion: [link to uv issue if applicable]

Description

When using hatch/hatchling as a build backend, there's inconsistent behavior between packages = ["src/astrbot"] and packages = ["astrbot"] configurations. Regular builds work for both, but editable installations behave differently.

Environment

  • OS: Windows
  • hatch/hatchling version: [please specify]
  • Python version: [please specify]
  • Build frontend: uv (but likely reproducible with other PEP 517 frontends)

Expected Behavior

Both package path configurations should work consistently across regular builds and editable installs, or provide clear guidance on when to use each format.

Actual Behavior

  • Regular builds (uv build) work fine with both configurations
  • Editable installs show different behavior depending on the package path format
  • One configuration works while the other fails with ModuleNotFoundError

Reproduction Steps

Configuration A (Works with editable installs):

[tool.hatch.build.targets.wheel]
packages = ["src/astrbot"]

Configuration B (Fails with editable installs):

[tool.hatch.build.targets.wheel]
packages = ["astrbot"]
  1. Set up project with either configuration above
  2. Run uv tool install -e . (or other editable install method)
  3. Execute the script-defined executable
  4. ✅ Configuration A works
  5. ❌ Configuration B fails with ModuleNotFoundError

Project Structure

project/
├── src/
│   └── astrbot/
│       ├── __init__.py
│       └── [other modules]
├── astrbot/  # or direct package location
│   ├── __init__.py
│   └── [other modules]
└── pyproject.toml

Questions

  1. What's the expected behavior difference between packages = ["src/astrbot"] and packages = ["astrbot"]?
  2. Why do both work for regular builds but behave differently for editable installs?
  3. Is there documentation clarifying when to use each package path format?
  4. Should hatch provide better error messages to help users choose the correct configuration?

Additional Context

This inconsistency makes it confusing for users to configure their projects correctly, especially when migrating between different project layouts or when testing only covers regular builds but not editable installs.

LIghtJUNction avatar Jun 18 '25 22:06 LIghtJUNction

Please show the contents of pyproject.toml.

ofek avatar Jun 18 '25 23:06 ofek

[project] name = "AstrBot" version = "3.5.15" description = "易上手的多平台 LLM 聊天机器人及开发框架" readme = "README.md" requires-python = ">=3.10" dependencies = [ "aiocqhttp>=1.4.4", "aiodocker>=0.24.0", "aiohttp>=3.11.18", "aiosqlite>=0.21.0", "anthropic>=0.51.0", "anyio>=4.9.0", "apscheduler>=3.11.0", "beautifulsoup4>=4.13.4", "certifi>=2025.4.26", "chardet~=5.2.0", "colorlog>=6.9.0", "cryptography>=44.0.3", "dashscope>=1.23.2", "defusedxml>=0.7.1", "dingtalk-stream>=0.22.1", "docstring-parser>=0.16", "faiss-cpu>=1.10.0", "filelock>=3.18.0", "google-genai>=1.14.0", "googlesearch-python>=1.3.0", "lark-oapi>=1.4.15", "lxml-html-clean>=0.4.2", "mcp>=1.8.0", "nh3>=0.2.21", "openai>=1.78.0", "ormsgpack>=1.9.1", "pillow>=11.2.1", "pip>=25.1.1", "psutil>=5.8.0", "pydantic~=2.11.7", "pydub>=0.25.1", "pyjwt>=2.10.1", "python-telegram-bot>=22.0", "qq-botpy>=1.2.1", "quart>=0.20.0", "readability-lxml>=0.8.4.1", "silk-python", "telegramify-markdown>=0.5.1", "toml>=0.10.2", "watchfiles>=1.0.5", "websockets>=15.0.1", "wechatpy>=1.8.18", ]

[project.scripts] astrbot = "astrbot.cli:cli"

[build-system] requires = ["hatchling", "uv-dynamic-versioning"] build-backend = "hatchling.build"

[tool.ruff] exclude = [ "astrbot/core/utils/t2i/local_strategy.py", "astrbot/api/all.py", ] line-length = 88

target-version = "py310"

[tool.uv.sources] silk-python = { git = "https://github.com/synodriver/pysilk.git" }

[tool.hatch.build.targets.wheel] packages = ["src/astrbot"]

This is my corrected version. Previously, the astrbot project had: [tool.hatch.build.targets.wheel] packages = ["astrbot"]

I could use uv build normally, but I couldn't use uv tool install -e . properly.

I spent a lot of time researching this issue. Finally, I discovered that I only needed to move the folder to src/astrbot, and all problems were solved.

This is the corrected branch: https://github.com/LIghtJUNction/AstrBot

This is the branch before correction: https://github.com/LIghtJUNction/AstrBot/tree/test

LIghtJUNction avatar Jun 18 '25 23:06 LIghtJUNction

I can't reproduce so far, what command are you running?

Image

ofek avatar Jun 18 '25 23:06 ofek

uv tool install -e .

astrbot

LIghtJUNction avatar Jun 18 '25 23:06 LIghtJUNction

I can't reproduce so far, what command are you running?

Image

I can't reproduce so far, what command are you running?

Image

Thank you for your response!

[project.scripts] astrbot = "astrbot.cli:cli"

run: uv tool install -e . and astrbot

output:

Image

LIghtJUNction avatar Jun 19 '25 00:06 LIghtJUNction

That's strange. The issue above occurs when I use astrbot layout:

  • Execute uv tool install -e .
  • Run astrbot
  • It fails

But when I change to src/astrbot layout:

  • Execute uv tool install -e .
  • Run astrbot
  • It works successfully

I made sure to change the folder structure accordingly, and uv build runs normally in both cases.

When I changed src/astrbot back to astrbot and moved the files, I got the same error again.

The strange thing is that the astrbot layout sometimes works normally too - I have no idea why.

Anyway, src/astrbot layout always works without any issues.

LIghtJUNction avatar Jun 19 '25 00:06 LIghtJUNction

Sorry, I have something to attend to and will be offline for a while. I might not be back to check for several hours.

So I may miss your reply and won't be able to respond promptly.

(I'm in UTC+8 timezone, by the way)

LIghtJUNction avatar Jun 19 '25 00:06 LIghtJUNction

Works for me, perhaps try checking out the old branch in a completely new directory after a fresh clone:

Image

ofek avatar Jun 19 '25 01:06 ofek

Thank you for your patient response. I will also build it successfully like you did. I am now working hard to reproduce this bug.

I have created a new empty project and am trying to reproduce it.

I will notify you once I successfully reproduce it and tell you how to reproduce it.

LIghtJUNction avatar Jun 19 '25 03:06 LIghtJUNction

Image PS C:\Users\light\Documents\GitHub\TestRepo> uv tool install -e .
Resolved 2 packages in 947ms Installed 2 packages in 32ms

  • silk-python==0.2.7 (from git+https://github.com/synodriver/pysilk.git@6666723883dd597da3a14bb694e10d2dd47c2581)
  • testrepo==0.1.0 (from file:///C:/Users/light/Documents/GitHub/TestRepo) Installed 1 executable: hi.exe PS C:\Users\light\Documents\GitHub\TestRepo> hi Traceback (most recent call last): File "", line 198, in _run_module_as_main File "", line 88, in run_code File "C:\Users\light.local\bin\hi.exe_main.py", line 4, in from testrepo import hello ModuleNotFoundError: No module named 'testrepo' PS C:\Users\light\Documents\GitHub\TestRepo>

!!!! "I successfully reproduced it!"

Reproduction Steps: Any repository with project.scripts Follow my steps strictly, and you should see the same situation as I do For example, the test project I sent you

Step 1 (Normal situation test) uv tool install -e . Run hi Output: Hello from testrepo! Everything works normally

But if at this point: Win + X, A (Windows, open system terminal) pip install path/to/testrepo/ and pip uninstall path/to/testrepo

Then:

Then go back to the previous repository

Find that the hi command is no longer effective

Output:

Just like this

I'll try to reproduce this on a Linux system later!

LIghtJUNction avatar Jun 19 '25 03:06 LIghtJUNction

testrepo.zip

testrepo

LIghtJUNction avatar Jun 19 '25 03:06 LIghtJUNction

WSL: ARCH

[moss@LIGHTJUNcPC TestRepo]$ uv tool install -e . Resolved 1 package in 17ms Built testrepo @ file:///mnt/c/Users/light/Documents/Gi Prepared 1 package in 3.43s Installed 1 package in 0.55ms

  • testrepo==0.1.0 (from file:///mnt/c/Users/light/Documents/GitHub/TestRepo) Installed 1 executable: hi [moss@LIGHTJUNcPC TestRepo]$ hi Traceback (most recent call last): File "/home/moss/.local/bin/hi", line 4, in from testrepo import hello ModuleNotFoundError: No module named 'testrepo' [moss@LIGHTJUNcPC TestRepo]$

LIghtJUNction avatar Jun 19 '25 03:06 LIghtJUNction

Now I'm trying to create another empty project and attempt to fully reproduce it once on Linux.

LIghtJUNction avatar Jun 19 '25 03:06 LIghtJUNction

Image

Image

Linux blocked pip install to protect the environment. both pip install and uv pip install

Image Thank you, Linux😭, for implementing these security measures to protect system stability. Although it may cause some inconvenience at times, this truly reflects its responsibility as a reliable operating system.

LIghtJUNction avatar Jun 19 '25 04:06 LIghtJUNction

Image

LIghtJUNction avatar Jun 19 '25 04:06 LIghtJUNction

Once this bug is triggered, it becomes very difficult to recover from. I've tried restarting the computer, running uv cache clean, deleting pycache, deleting dist, deleting .venv and recreating it, re-running the activation script, changing the default Python version, and changing the project Python version - none of these methods successfully fixed the issue.

The most effective solution was to change the project structure, and then it worked. However, it became very difficult to reproduce the issue again afterwards. It took me quite a while to figure this out through trial and error.

LIghtJUNction avatar Jun 19 '25 04:06 LIghtJUNction