-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Editable installs are broken after __editable__
and __path_hook__
changes
#3548
Comments
This is likely because setuptools released a new mechanism for implementing editable installs, as part of their PEP600 support. The pdoc3 project is probably not yet aware of the new mechanism, and will need updating. There isn’t really anything for pip to do here, so I’m closing this issue. If it turns out that there is a pip problem here, feel free to reopen it. |
@pfmoore This is likely going to create a lot of havoc. Editable install is how people operate in Python community. And if all of a sudden, entire tooling around editable install is going to break, then likely we must be planning better around it. My 2 cents. May be, instead of enforcing the new mechanism as default, this could have been an opt in to start with. Instead of fighting this out, we decided to simply pin setuptools |
Please reach out to the setuptools maintainers. While various Python packaging tools do interoperate, the behaviour changes you’re seeing come from setuptools. The maintainers of pip don’t control / maintain setuptools, which is where I recommend you reach out. |
I can actually transfer the issue, so… here you go. :) |
Setuptools 64.0.0 introduced change that broke paths of editable cli packages. This change makes CLIs installed via editable packages to miss paths required to import code from the editable packages themselves. Related to: pypa/setuptools#3548
Setuptools 64.0.0 introduced change that broke paths of editable cli packages. This change makes CLIs installed via editable packages to miss paths required to import code from the editable packages themselves. Related to: pypa/setuptools#3548
It looks like we started to have the same problem in Airflow.
This started to happen few days ago and adding Airlfow's source to I did some bisecting and pin-pointed it to version 64.0.0 of setuptools. Version 63.4.3 worked perfectly fine, 64.0.0 breaks it. The reason seems to be as described in the issue. I've added those lines to our pyproject.toml and they solved the problem:
See: apache/airflow#25848 It is super-easy to reproduce now:
This works perfectly well (because of the 63.4.3 limit)
You see the stack-trace above |
(The error is also present in all other 64.* and 65* versions BTW). |
Hi @abhinavsingh, Could you provide a minimal reproducer explaining more in details the issues you are having? (Maybe it is worthy to split multiple issues in multiple reproducers). I tried to investigate what you are describing with the following reproducer, but I was not able to find the problematic behaviour you are referring to... (Maybe I understood something wrong? Or maybe the reproducer is missing something? Or -- best case scenario -- the problem might have already gotten solved in the latest release?). # docker run --rm -it python:3.10.6 bash
cd /tmp && rm -rf /tmp/proj_root
mkdir -p /tmp/proj_root
mkdir -p /tmp/proj_root/namespace/cli
echo "def run(): print('hello world')" > /tmp/proj_root/namespace/cli/__init__.py
cat <<EOF > /tmp/proj_root/pyproject.toml
[build-system]
requires = ["setuptools>=65.1.0"]
build-backend = "setuptools.build_meta"
[project]
name = "namespace.cli"
version = "42"
[project.scripts]
namespace-cli = "namespace.cli:run"
EOF
cd /tmp/proj_root
python3.10 -m venv .venv
.venv/bin/python -m pip install -U pip
.venv/bin/python -m pip install -e .
cd /var
/tmp/proj_root/.venv/bin/python -c 'import namespace; print(f"{namespace.__path__=}")'
# ==> namespace.__path__=_NamespacePath(['/tmp/proj_root/namespace'])
/tmp/proj_root/.venv/bin/namespace-cli
# ==> hello world As you can see above, the reproducer show that whenever possible There are a few other remarks I would like to make:
|
@potiuk I suspect airflow's use case is different. By having a look on the Setuptools's implementation of PEP 660 does not use the By running: # docker run --rm -it python:3.10.6 bash
apt update && apt install -y git build-essential
cd /tmp
git clone https://github.com/apache/airflow
cd /tmp/airflow
sed -i 's/==63.4.3/>=65.1.0/g' pyproject.toml
python -m venv .venv
.venv/bin/python -m pip install -U pip
.venv/bin/python -m pip install -e .
cd /var
/tmp/airflow/.venv/bin/python -c 'import airflow.settings; print(dir(airflow.settings))'
# ==> ['AIRFLOW_HOME', 'AIRFLOW_MOVED_TABLE_PREFIX', 'ALLOW_FUTURE_EXEC_DATES', 'CAN_FORK', 'CHECK_SLAS', 'COMPRESS_SERIALIZED_DAGS', 'Callable', 'DAEMON_UMASK', 'DAGS_FOLDER', 'DASHBOARD_UIALERTS', 'DEFAULT_ENGINE_ARGS', 'DONOT_MODIFY_HANDLERS', 'EXECUTE_TASKS_NEW_PYTHON_INTERPRETER', 'Engine', 'GUNICORN_WORKER_READY_PREFIX', 'HEADER', 'HIDE_SENSITIVE_VAR_CONN_FIELDS', 'IS_K8S_OR_K8SCELERY_EXECUTOR', 'KILOBYTE', 'LAZY_LOAD_PLUGINS', 'LAZY_LOAD_PROVIDERS', 'LOGGING_CLASS_PATH', 'LOGGING_LEVEL', 'LOG_FORMAT', 'List', 'MASK_SECRETS_IN_LOGS', 'MEGABYTE', 'MIN_SERIALIZED_DAG_FETCH_INTERVAL', 'MIN_SERIALIZED_DAG_UPDATE_INTERVAL', 'NullPool', 'Optional', 'PLUGINS_FOLDER', 'SASession', 'SIMPLE_LOG_FORMAT', 'SQL_ALCHEMY_CONN', 'STATE_COLORS', 'TIMEZONE', 'TYPE_CHECKING', 'USE_JOB_SCHEDULE', 'Union', 'WEBSERVER_CONFIG', 'WEB_COLORS', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_get_rich_console', 'atexit', 'conf', 'configure_action_logging', 'configure_adapters', 'configure_logging', 'configure_orm', 'configure_vars', 'create_engine', 'custom_show_warning', 'dag_policy', 'dispose_orm', 'exc', 'executor_constants', 'functools', 'get_airflow_context_vars', 'get_dagbag_import_timeout', 'get_session_lifetime_config', 'import_local_settings', 'initialize', 'json', 'log', 'logging', 'original_show_warning', 'os', 'pendulum', 'pod_mutation_hook', 'prepare_engine_args', 'prepare_syspath', 'reconfigure_orm', 'replace_showwarning', 'scoped_session', 'sessionmaker', 'setup_event_handlers', 'sqlalchemy', 'sys', 'task_instance_mutation_hook', 'task_policy', 'tz', 'validate_session', 'warnings'] I can see that the package is indeed installed in the editable mode, however the Footnotes
|
Thanks for the pointer @abravalheri . I will take a closer look and see if I can work it out. I was kinda suspecting that we could have been doing something that PEP 660 does not really like :). I will keep you posted. |
Time to do some more deep PEP reading |
@potiuk Hey! Airflow's |
(Copying some opinion from the PyPA discord for eventual readers of this thread).
|
@ofek Airlfow is an ASF project and community makes decisions not me personally. If you want to make a POC and have some good arguments, you will have to start dicsussion at the airflow devlist https://airflow.apache.org/community/ . But you have to - in general - have a good reasoning and justification for such a change in build system. just fixing an error that we can fix without switching to another build mechanism is not good enough reason. |
This comment was marked as resolved.
This comment was marked as resolved.
Hi @lonetwin, Based on this comment I would say that (so far) the stdlib developers have no intention the increase the scope or add features to If you absolutely need to use |
In the spirit of over-communicating: I'm unsubscribing from this since I don't think there's anything for me to do here. To the maintainers, please feel free to @-mention me in case there's something here that's on pip's end. |
@abravalheri Apologies, haven't checked back on GitHub in weeks. Missed your message altogether. A point to note in our case is that, we have all our packages under a namespace. As others have figured, v64 is an issue. At our end, I had to pin setup tools to v62 to let our company workflows pass. In our setup, we simply go by paths returned by I am not on my work system today. But, I'll give you a reproducible scenario as soon as I get to my system. We surely don't want to pin ourself to v62 forever. |
* this allows `pip install -e .` to produce a working editable install locally * the basis for the `setuptools` pin here is based on reading through pypa/setuptools#3548; in short, looks like a behavior change in `setuptools` so let's just pin it for now * since this only affects Python developers for our project I've not added any "regression test"/"CI test" for it, but feel free to add one editable job to the CI if you want
- Fixes issues with editable builds, [broken by new versions of setuptools](pypa/setuptools#3548) - Migrates project to `pyproject.toml`, [as recommended](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/)
- Fixes issues with editable builds, [broken by new versions of setuptools](pypa/setuptools#3548) - Migrates project to `pyproject.toml`, [as recommended](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/)
* Migrate from setuptools to hatch - Fixes issues with editable builds, [broken by new versions of setuptools](pypa/setuptools#3548) - Migrates project to `pyproject.toml`, [as recommended](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/) * Move some configuration from setup.cfg to pyproject.toml * Don't install setuptools on CI - Not required anymore * Move configuration to pyproject.toml * Move more configuration to pyproject.toml * Rename some minor fields * Use Python 3.12 to publish the package --------- Co-authored-by: Uxio Fuentefria <[email protected]>
For what it's worth, installing packages using |
@rachtsingh performance degradation using editable mode can be caused by a myriad of elements many of them not under the control of setuptools (e.g. depending on how the particular package you are installing is implemented, which is the layout of that package, how many items you have in the Setuptools follows the implementation options described in https://peps.python.org/pep-0660/#what-to-put-in-the-wheel, and in general the performance hits associated with these implementation options are considered acceptable (the purpose of the editable mode is to help in development time and not meant to be used in production). If you manage to investigate more and isolate a specific behaviour in setuptools that you think can be optimised, PRs would be very welcome. |
I'm seeing an issue that might be related to this, for reproduction I've created this Dockerfile Relevant output: #21 0.513 _NamespacePath(['/home/zope/venv/lib/python3.12/site-packages/Products', 'Products', '__editable__.ZMS-5.2.0.finder.__path_hook__', '/home/zope/venv/src/products-zms-skins/Products', '/home/zope/venv/src/zms/Products'])
## [...] output from iter_modules which is missing `Products.zms`
#21 0.513 _NamespacePath(['/home/zope/venv/lib/python3.12/site-packages/Products', 'Products', '__editable__.ZMS-5.2.0.finder.__path_hook__'])
#21 0.513 __REGISTRY__['confdict'] None
#21 0.513 ['/home/zope/venv/src/zms/Products/zms'] To me this shows that after installation the namespace Package So, the package Further if I install Zope (as of yet a package that still does not have a Still this smells fishy enough that I would like some advice if this is a problem in setuptools, or python - or just in my code (still the most likely scenario I think). |
@abravalheri How do you read that notice in the docs? At first I read this as: "the module That leaves behind the question: How am I supposed to iterate over submodules of a namespace package if they are installed with setuptools in the new mode? |
My interpretation of that passage in the Python docs is:
This might be a good question for CPython? If you would like to propose a PR in setuptools to implement this non standard Another possibility is to always use The good part ("glass half-full" point of view) is that editable installs are not really meant to be used in production, only for development. So in production you should not reach these code paths as packages are installed regularly. |
I assumed that |
Uhm... shouldn't the question be to setuptools? I mean, the documented way is right there, linked above? If not, where would I ask this? Also, it may be way stronger a question if you or one of the setuptools contributors asks this, as I may just be ignored.
I would like to help review this, but I feel unable to judge wether that is the best way forward?
I thought that my project does have the source layout. How would I check this?
While that is true, they are also essential to (my) development workflow, either local or in docker containers, to install the module under development into a virtualenv and work on it there. |
Setuptools itself also does not expose any APIs (or at least not that have not been deprecated) for iterating over namespaces. So maybe you are looking for a feature that does not exist. If The best discovery mechanism known to work with third-party packages is entry-points, although even that has its limitations with editable installs (i.e. newly added entry-point need a full re-install).
This is setuptools' description of what a src-layout entails: https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#src-layout. Note that if you "remap" or "customise" package directories via the When installed in editable mode, a
That is a fair comment, but it is also fair to recognise that editable installations are not a silver bullet and have many problems and limitations. This is made explicit in the setuptools docs.
In my option, the best way forward if you would like support for Please note however that this territory is "muddy" and that there are not many answers out there for the problems of editable installs and namespace packages:
Note that it was also very difficult to reach a general agreement in terms of standards for editable installs (to be honest, I don't think the community never reached one), and one of the main issues is that there is no solution that solves all problems:
In general, the understanding is that editable installs are inherently "flawed", because it is currently impossible to have something to behave at the same time as if it was installed and in development at the same time, without constantly reinstalling it. |
That... sounds like a lot of work. I was hoping that we could agree that this is a backwards incompatibility issue. I.e. in the past editable installs did work even for namespace packages with setuptools, and thus this should continue to work. If I understand you correctly, adding pull request here for Just so I'm not seeing things: In this case, I cannot choose a different way to install, as the Zope-Maintainers (in their infinite wisdom) have decided that they require namespace packages for extensions. :-/ |
I don't think we can apply the concept of backwards incompatibility in this scenario because the brutal change in behaviour is motivated by a PEP, which basically made the exact previous implementation no longer viable. Also the previous behaviour and API still exists in setuptools, unchanged and bug-by-bug backwards compatible (although deprecated). Installers no longer call that API by default, though.
I don't think there is a standard about iterating over submodules. The
If you are writing a package, you can still chose its directory structure right? So you can use a |
To be completely clear here, it is 100% possible to implement the "legacy" mechanism that setuptools used in the past for editable installs. I believe this mechanism is now available in setuptools via the The difficulties I have seen raised with editable mode have typically been either limitations of alternative implementation methods, bugs that were also present in the legacy mechanism, or feature requests for capabilities that were mot present in the legacy mode. While it would be nice to have these improvements, I don't believe the community has ever managed to come up with a consistent, clearly specified, and implementable of what such an "improved editable mode" would look like. If the problems reported here are ones that did not exist before setuptools added PEP 660 support, and they can't be fixed by specifying The current state of the art is that all editable install mechanisms have limitations, as @abravalheri says. Setuptools gives you a choice of which limitations you prefer (most other build backends just pick one implementation technique and accept its limitations) but that's about the best you can hope for as things stand. @dwt does |
Hi @pfmoore, to be frank I think that |
OK, I wasn't aware of that. I'm disappointed that it was never raised in the PEP 660 discussions - we repeatedly characterised the existing mechanism as "just add a I'll retract the statement that |
With the risk of sounding exaustive, I also would like to point out another thing that may have remained unsaid in this recent discussion, but is covered in the docs: Legacy namespaces are not guaranteed to work in the current implementation of editable installs in setuptools. This change is intentional, may be backwards incompatible, but I don't think there is much to do about it due to the reasons listed in the previous comment. Support for namespace packages has been deprecated by a couple of years now and users are prompted to switch to native namespaces (and for better compatibility users are advised to use the src-layout with them). |
@pfmoore, that is also something that I learned/guessed after trying to "reverse engineer" the old installation when implementing PEP 660. To be honest, probably only the person first coming up with the We may revisit editable in the future based on the new knowledge that was gained via feedback, but that should be done in a "let's look forward" way. We should probably wait for input from core devs on namespaces (and other issues open in the cpython repo) first, though. |
+1. My personal view is that what we need to do in order to improve editable support is:
When I accepted PEP 660, my view was that for (1) "what you get creating a |
Setuptools 64.0.0 introduced change that broke paths of editable cli packages. This change makes CLIs installed via editable packages to miss paths required to import code from the editable packages themselves. Related to: pypa/setuptools#3548 GitOrigin-RevId: 98a7701942c683f3126f9c4f450c352b510a2734
This discussion about what to do in the wider python ecosystem is probably necessary, but I would like to come back to my initial observation once more to make sure we are not missing a simple bug. What I see there is that it seems that However, after calling This seems to be part of the problem and something I might be able to contribute a fix towards. But to do that, I need to understand: Is that actually a problem? Is there a reason why it would be 'correct' to remove these extra entries? If so, why? |
ping? Could any of the setuptools maintainer give me a heads here please? |
@dwt is there any PR you would like to propose/implement? As previously noted we don't control the implementation of Otherwise please consider using a different installation mode (e.g. |
Setuptools 64.0.0 introduced change that broke paths of editable cli packages. This change makes CLIs installed via editable packages to miss paths required to import code from the editable packages themselves. Related to: pypa/setuptools#3548 GitOrigin-RevId: 98a7701942c683f3126f9c4f450c352b510a2734
Description
I am starting to observe broken editable installs since past week.
Specifically, editable install now creates a
__editable__.<pkg>.pth
and__editable___<pkg>_finder.py
files. These paths are returned as part ofnamespace.__path__
, which has broken a lot of tooling.pdoc3
went broke. Skipping__editable__
package seems to fix (hack) it.__editable__
paths duringiter_modules
pdoc3/pdoc#408.venv/bin
, it is unable to import the modules since it was installed using-e
.PYTHONPATH
is the only option."python.analysis.extraPaths"
to.vscode/settings.json
is the way outI was unable to find any search result on Google for
__editable__
and__path_hook__
. So, I am unsure what I am up against here.Expected behavior
PYTHONPATH
namespace.__path__
must return actual path instead of__editable__.*
which seems to break a lot of existing toolingpip version
22.2.2
Python version
3.10.5
OS
MacOS 12.5
How to Reproduce
-e
PYTHONPATH
Our projects are using
pyproject.toml
andsetup.cfg
.Output
`ImportError: cannot import name 'entry_point' from 'namespace.cli' (unknown location)`
Code of Conduct
The text was updated successfully, but these errors were encountered: