
Hello Many people are asking for an uninstall command. While there are possible side-effects when removing all installed files, I think it worths it... I would like to introduce an uninstall command in distutils, using Marc-André Lemburg's mxSetup tool (see http://www.egenix.com/products/python/mxBase/) and turning it into a uninstall command. It's quite straighforward since it uses the install command in dry-run mode to get the files to remove. It requires of course to keep the source. Next, (in a second step) I was wondering if a uninstall registery could not be a good thing to have, to store a record of the installed files so there's no need to keep the source for uninstallation. This would required a new command, (and a detailed specification of course) There's an open ticket here about that (#4673) Any thoughts ? Regards Tarek -- Tarek Ziadé | Association AfPy | www.afpy.org Blog FR | http://programmation-python.org Blog EN | http://tarekziade.wordpress.com/

Enthought has a package called Enstaller which includes a modified version of setuptools + an enstaller package that adds some different functionality. One of the modifications to setuptools adds an uninstall command which works well with our .egg's. Dealing with eggs allows us to do some dependency checking to warn the user if the package they are trying to remove is required by another package. Another feature we added is similar to the uninstall registry you mentioned. Whenever someone invokes easy_install and a change is made(i.e. a package(s) was removed, added, or modified), we create an entry in a rollback cache file that stores the package-version of everything installed in site-packages at that time. There is a rollback menu that displays the changes between the different known rollback points and you can restore your state to a previous working state in this way. A lot of this stuff is specific to setuptools/eggs but the fundamentals of it could be helpful when determining how to implement these kinds of things into distutils itself, if that is the desired path. Here is the trunk for Enstaller: https://svn.enthought.com/svn/enthought/Enstaller/trunk/ -- Chris Galvan Tarek Ziadé wrote:
Hello
Many people are asking for an uninstall command. While there are possible side-effects when removing all installed files, I think it worths it...
I would like to introduce an uninstall command in distutils, using Marc-André Lemburg's mxSetup tool (see http://www.egenix.com/products/python/mxBase/) and turning it into a uninstall command.
It's quite straighforward since it uses the install command in dry-run mode to get the files to remove. It requires of course to keep the source.
Next, (in a second step) I was wondering if a uninstall registery could not be a good thing to have, to store a record of the installed files so there's no need to keep the source for uninstallation. This would required a new command, (and a detailed specification of course)
There's an open ticket here about that (#4673)
Any thoughts ?
Regards Tarek

On Thu, Jan 29, 2009 at 6:49 PM, Tarek Ziadé <ziade.tarek@gmail.com> wrote:
Next, (in a second step) I was wondering if a uninstall registery could not be a good thing to have, to store a record of the installed files so there's no need to keep the source for uninstallation. This would required a new command, (and a detailed specification of course)
pip writes an installation record in Package.egg-info/installed-files.txt (based on the setuptools --record option, with filenames made relative). So... that's similar to it. Of course, to be accurate you have to make sure you don't install over those files. So pip should really be uninstalling before installing something new, and probably be fancy about the whole thing (maybe like Enstaller is doing). But if tools do respect the integrity of those files, it's a reasonably simple record. Well, that and they should be careful about one package overwriting another packages file (which I haven't really seen happen, but of course it *could* happen). -- Ian Bicking | http://blog.ianbicking.org

Ian Bicking schrieb:
On Thu, Jan 29, 2009 at 6:49 PM, Tarek Ziadé <ziade.tarek@gmail.com> wrote:
Next, (in a second step) I was wondering if a uninstall registery could not be a good thing to have, to store a record of the installed files so there's no need to keep the source for uninstallation. This would required a new command, (and a detailed specification of course)
pip writes an installation record in Package.egg-info/installed-files.txt (based on the setuptools --record option, with filenames made relative). So... that's similar to it. Of course, to be accurate you have to make sure you don't install over those files. So pip should really be uninstalling before installing something new, and probably be fancy about the whole thing (maybe like Enstaller is doing).
But if tools do respect the integrity of those files, it's a reasonably simple record. Well, that and they should be careful about one package overwriting another packages file (which I haven't really seen happen, but of course it *could* happen).
You could also take a look into the log-file that bdist_wininst installers create (for deinstallation). It contains information about directories and registry entries created, files copied, and some more information about what the installer has done. Reinstalling a package simply appends to the log file. -- Thanks, Thomas

Reading your answer and Chris's, I am now wondering, if we have a global uninstall command, why we wouldn't have a global install command.... How hard would it be, from your projects, to have the install/uninstall feature, on the top of today's distutils ? (since the record feature is in distutils) In other words, is the current "record" feature of distutils would be sufficient ? On Fri, Jan 30, 2009 at 6:24 AM, Ian Bicking <ianb@colorstudy.com> wrote:
On Thu, Jan 29, 2009 at 6:49 PM, Tarek Ziadé <ziade.tarek@gmail.com> wrote:
Next, (in a second step) I was wondering if a uninstall registery could not be a good thing to have, to store a record of the installed files so there's no need to keep the source for uninstallation. This would required a new command, (and a detailed specification of course)
pip writes an installation record in Package.egg-info/installed-files.txt (based on the setuptools --record option, with filenames made relative). So... that's similar to it. Of course, to be accurate you have to make sure you don't install over those files. So pip should really be uninstalling before installing something new, and probably be fancy about the whole thing (maybe like Enstaller is doing).
But if tools do respect the integrity of those files, it's a reasonably simple record. Well, that and they should be careful about one package overwriting another packages file (which I haven't really seen happen, but of course it *could* happen).
-- Ian Bicking | http://blog.ianbicking.org
-- Tarek Ziadé | Association AfPy | www.afpy.org Blog FR | http://programmation-python.org Blog EN | http://tarekziade.wordpress.com/

Tarek Ziadé wrote:
Reading your answer and Chris's, I am now wondering, if we have a global uninstall command, why we wouldn't have a global install command....
How hard would it be, from your projects, to have the install/uninstall feature, on the top of today's distutils ? (since the record feature is in distutils)
In other words, is the current "record" feature of distutils would be sufficient ?
I can see several things which have a big impact on an uninstall feature design: - how to handle multiple versions of one package ? - should it handle dependencies ? - should it work for packages installed anywhere, or only for a few reserved places ? Only the last point is worth considering at the distutils level - the two others are specific to setuptools (or more exactly any system on top of distutils). Once those decisions are made, we can make decision on how to deal with uninstall. For example, if uninstalling only packages installed in some blessed locations is acceptable, the problem of a global registry of some kind becomes much easier to deal with. If it is not, I don't see much choice but to put the packages-specific uninstall data in the package itself. Some people do not like setuptools stubborness about installing things in some places - I am one of them. But not being able to uninstall automatically would not bother me too much (actually, I install things manually so that I can use stow, which provides me an uninstall feature). I also wonder whether we should add uninstall feature to distutils itself from a UI POV. Of course, distutils should have some support of some kind, but the high level stuff could be done by another program, no ? After all, uninstall is NOT the opposite of install - many platforms let you install things on a per program basis, but then uninstalling is done in a centralized manner. I noticed that the ruby gems system, which I don't claim to know, use this system: http://www.rubygems.org/read/chapter/10#page38 Having a separate program would enable asking questions and co - which is not something I would be pleased to see in the python setup.py dance, cheers, David

On Fri, Jan 30, 2009 at 10:28 AM, David Cournapeau <david@ar.media.kyoto-u.ac.jp> wrote:
I can see several things which have a big impact on an uninstall feature design: - how to handle multiple versions of one package ? - should it handle dependencies ?
from a distutils point of view, none of these features exist. My opinion is that the multiple version and the dependencies matters should be treated separately, because the atomic part is the package. And if you know how to uninstall a package, it's the basis of a meta-uninstaller.
- should it work for packages installed anywhere, or only for a few reserved places ?
It should work for any package installed. Wherever it's installed. If it's in the path and usable in Python, it should be removable.
Only the last point is worth considering at the distutils level - the two others are specific to setuptools (or more exactly any system on top of distutils). Once those decisions are made, we can make decision on how to deal with uninstall.
For example, if uninstalling only packages installed in some blessed locations is acceptable, the problem of a global registry of some kind becomes much easier to deal with.
the "blessed locations" are already known. For instance, if you take a look at the patch I am working on here (http://bugs.python.org/issue4908) we are able to find the packages and their egg-link file/folders (so any record of installation if it's kept in the egg-info) this code is still incomplete, I am waiting for PJE feedback to add the support for zip files that contains several .egg folders or zip files. But the current version is able to find a package and its metadata. notice that there are probably some edge cases we need to address I believe (setuptools too) like sys.meta_path and sys.path_hooks support.
I also wonder whether we should add uninstall feature to distutils itself from a UI POV. [cut] Having a separate program would enable asking questions and co - which is not something I would be pleased to see in the python setup.py dance,
My opinion is that distutils and pkgutil should provide a set of apis to: - locate a package (see http://bugs.python.org/issue4908) - install / uninstall a package Then two simple basics commands could be offered in Python executable scripts.
From there any third party app could have fun adding a better UI
But my point is that the logic behind install/uninstall should be unique and clearly defined and in one and only one place (e.g. Python) to avoid having many different ways to deal with those problems. I think this is why we have several kinds of tools to answer to these problems slighlty differenlty at the moment. But if we can reach a consensus on the install/uninstall part and have something for it in Python, it's a good step forward imho. I have added a question in the survey about uninstallation. and this thread could be a good starting point for providing more infos to the people to answer that question (eg what could be possible.?) Cheers Tarek -- Tarek Ziadé | Association AfPy | www.afpy.org Blog FR | http://programmation-python.org Blog EN | http://tarekziade.wordpress.com/

Tarek Ziadé wrote:
On Fri, Jan 30, 2009 at 10:28 AM, David Cournapeau <david@ar.media.kyoto-u.ac.jp> wrote:
I can see several things which have a big impact on an uninstall feature design: - how to handle multiple versions of one package ? - should it handle dependencies ?
from a distutils point of view, none of these features exist. My opinion is that the multiple version and the dependencies matters should be treated separately, because the atomic part is the package.
agreed
And if you know how to uninstall a package, it's the basis of a meta-uninstaller.
Not necessarily: many package systems simply do not deal at all with multiple versions. This really complicates the matter a lot right away whether that's something which needs to be supported, even if it is not supported by the tool itself. IOW, ignoring the problem in distutils may well render any multiple version handling impossible for tools build on top of distutils.
- should it work for packages installed anywhere, or only for a few reserved places ?
It should work for any package installed. Wherever it's installed. If it's in the path and usable in Python, it should be removable.
Again, that's a major complication - so if it is required, it should really be weight against the implementation and reliability cost. For example, I am somewhat familiar with the following systems used for deployment: autoconf-based, .deb based, .net based, stow-based, windows Side by side, globac assembly cache (GAC, the .net stuff). AFAIK, not a single one supports both multiple versions deployment and arbitrary installation location. That should at least be an indication this is not a trivial matter.
My opinion is that distutils and pkgutil should provide a set of apis to:
- locate a package (see http://bugs.python.org/issue4908) - install / uninstall a package
Then two simple basics commands could be offered in Python executable scripts.
From there any third party app could have fun adding a better UI
But my point is that the logic behind install/uninstall should be unique and clearly defined and in one and only one place (e.g. Python) to avoid having many different ways to deal with those problems.
100 % agreed. My remark was just that uninstalling may require asking some questions to the user depending on the system state, so a distutils uninstall command at the UI level may not be advisable . Of course, the actual implementation for uninstalling should be done in distutils itself, with a *documented* API so that other tools can be built on top of it. David

On Jan 29, 2009, at 17:49 PM, Tarek Ziadé wrote:
Many people are asking for an uninstall command.
This is true. Many other people, however, are unwilling to let the Python packaging tool nor the packages that it is installing write into their system directories. For these people, the system directories are never allowed to be written into by any tool other than their operating system packaging tool e.g. apt. For these people, offering a new feature so that, in addition to the Python packaging tool scribbling into their system directory at install time, it will *also* later scribble into it again attempting to undo the changes that it earlier did is only compounding the problem. :-) For those people, there are several potential solutions. One is the path from Python package through Python packaging tool (e.g. stdeb) to operating system package (e.g. .deb) to operating system tool (e.g. apt) to system directories. Another is GNU stow. For me, and for some hackers that I've talked to, making setuptools compatible with GNU stow would satisfy their need to have a way to cleanly uninstall. So, please consider this a reminder in the distutils development process that you are undergoing that GNU stow compatibility has many benefits. Regards, Zooko --- Tahoe, the Least-Authority Filesystem -- http://allmydata.org store your data: $10/month -- http://allmydata.com/?tracking=zsig

On Sat, Jan 31, 2009 at 23:21, zooko <zooko@zooko.com> wrote:
Many other people, however, are unwilling to let the Python packaging tool nor the packages that it is installing write into their system directories. For these people, the system directories are never allowed to be written into by any tool other than their operating system packaging tool e.g. apt. For these people, offering a new feature so that, in addition to the Python packaging tool scribbling into their system directory at install time, it will *also* later scribble into it again attempting to undo the changes that it earlier did is only compounding the problem. :-)
For those people, there are several potential solutions. One is the path from Python package through Python packaging tool (e.g. stdeb) to operating system package (e.g. .deb) to operating system tool (e.g. apt) to system directories. Another is GNU stow.
For me, and for some hackers that I've talked to, making setuptools compatible with GNU stow would satisfy their need to have a way to cleanly uninstall.
So, please consider this a reminder in the distutils development process that you are undergoing that GNU stow compatibility has many benefits.
As far as I can figure out, that's just a matter of installing things with a prefix, like /usr/local/stow/yoursoftware instead of /usr/local and then using stow to symlink everything into /usr/local/bin and /usr/local/lib, etc. I may have misunderstood, though, but if not it should already be compatible... -- Lennart Regebro: Zope and Plone consulting. http://www.colliberty.com/ +33 661 58 14 64

Lennart Regebro wrote:
On Sat, Jan 31, 2009 at 23:21, zooko <zooko@zooko.com> wrote:
Many other people, however, are unwilling to let the Python packaging tool nor the packages that it is installing write into their system directories. For these people, the system directories are never allowed to be written into by any tool other than their operating system packaging tool e.g. apt. For these people, offering a new feature so that, in addition to the Python packaging tool scribbling into their system directory at install time, it will *also* later scribble into it again attempting to undo the changes that it earlier did is only compounding the problem. :-)
For those people, there are several potential solutions. One is the path from Python package through Python packaging tool (e.g. stdeb) to operating system package (e.g. .deb) to operating system tool (e.g. apt) to system directories. Another is GNU stow.
For me, and for some hackers that I've talked to, making setuptools compatible with GNU stow would satisfy their need to have a way to cleanly uninstall.
So, please consider this a reminder in the distutils development process that you are undergoing that GNU stow compatibility has many benefits.
As far as I can figure out, that's just a matter of installing things with a prefix, like /usr/local/stow/yoursoftware instead of /usr/local and then using stow to symlink everything into /usr/local/bin and /usr/local/lib, etc. I may have misunderstood, though, but if not it should already be compatible...
There are two problems with stow and setuptools: - setuptools refuses to install in a directory not in PYTHONPATH, so python setup.py install --prefix=/usr/local/stow/my-package does not work when setup.py uses setuptools. You have to use --single-version-externally-managed (plus another option required by this one). That's the most annoying point, since it depends on whether setup.py uses setuptools or plain distutils. From a user POV, setuptools broke standard python behavior. - namespace packages: the fact that namespace/__init__ are 'owned' by several packages is a fundamental problem (not only for stow, but almost any package system). But unless python itself supports namespace packages, I don't see any solution to this one. cheers, Davod

On Jan 31, 2009, at 23:17 PM, David Cournapeau wrote:
There are two problems with stow and setuptools: - setuptools refuses to install in a directory not in PYTHONPATH, so python setup.py install --prefix=/usr/local/stow/my- package does not work when setup.py uses setuptools. You have to use --single-version-externally-managed (plus another option required by this one). That's the most annoying point, since it depends on whether setup.py uses setuptools or plain distutils. From a user POV, setuptools broke standard python behavior. - namespace packages: the fact that namespace/__init__ are 'owned' by several packages is a fundamental problem (not only for stow, but almost any package system). But unless python itself supports namespace packages, I don't see any solution to this one.
also: - easy-install.pth; When you install two different packages under GNU stow, then stow can install both of those packages (by creating symlinks pointing to each file from each package) *unless* both packages created a file in the same location. Two different Python packages both installed by setuptools (without --single- version-externally-managed) will create a file in the same location -- the easy-install.pth file. If setuptools didn't need to create this file (and if it accepted installation into a directory not currently on the PYTHONPATH, per http://bugs.python.org/setuptools/ issue54 (be more like distutils with regard to --prefix=)), then it would be GNU stow-compatible. Regards, Zooko --- Tahoe, the Least-Authority Filesystem -- http://allmydata.org store your data: $10/month -- http://allmydata.com/?tracking=zsig
participants (7)
-
Chris Galvan
-
David Cournapeau
-
Ian Bicking
-
Lennart Regebro
-
Tarek Ziadé
-
Thomas Heller
-
zooko