112 Commits

Author SHA1 Message Date
Kenneth Reitz a484f9b693 pythons 2012-02-26 13:20:33 -05:00
Kenneth Reitz 706d8b4327 yeah 2012-02-26 13:18:08 -05:00
Kenneth Reitz 17b811865c mission statement 2012-02-26 13:17:50 -05:00
utahta ea7cb63494 v1.1 2011-08-29 18:01:31 +09:00
utahta e7943488de release 1.0 2011-08-08 03:09:42 +09:00
utahta 630d525f6a 0.10 -> 1.0 2011-08-08 03:04:42 +09:00
utahta 770715b536 release 0.10 2011-08-08 02:51:43 +09:00
utahta 0112a39aff update 2011-08-08 02:45:29 +09:00
utahta df91a87b24 update 0.10 2011-08-08 02:44:08 +09:00
utahta 212460fd6d update 2011-08-07 15:56:04 +09:00
utahta bfdccb5051 improve venv 2011-08-07 15:36:46 +09:00
utahta bc219fcebe bug fix 2011-08-07 12:58:54 +09:00
utahta 4993f466e9 add systemwide install support 2011-08-07 03:48:38 +09:00
utahta 7b2fa2f0eb Improve symlink command 2011-08-07 00:39:13 +09:00
utahta 90face7065 bug fix 2011-08-07 00:11:23 +09:00
utahta 4ef2954bd6 bug fix 2011-08-07 00:08:37 +09:00
utahta 1025529528 update readme 2011-08-06 23:58:47 +09:00
utahta 04f4cd15b3 Improve venv command, log and bashrc 2011-08-06 23:56:31 +09:00
utahta 7bdb546fa4 merge develop 2011-07-23 18:00:04 +09:00
utahta 12b392a98c fixed #34 #35 2011-07-23 16:31:37 +09:00
utahta 2eb3b7509f merge #33 2011-07-23 12:19:41 +09:00
utahta b6abb47bc3 cleanup 2011-07-23 12:12:30 +09:00
Chris Ledet 483b49984c updated README with corrected rst syntax 2011-07-22 07:35:05 -07:00
Chris Ledet 704321f040 updated README 2011-07-22 10:34:00 -04:00
utahta e033edcda0 release 0.9 2011-07-22 19:09:59 +09:00
utahta 07828a266d update 2011-07-22 18:38:20 +09:00
utahta 9fbc3273cf update venv command 2011-07-22 01:56:01 +09:00
utahta 4aa62201c7 update venv command 2011-07-21 02:22:00 +09:00
utahta b4a6674fba Added venv command 2011-07-21 02:14:41 +09:00
utahta ef4ff75630 update 2011-07-20 00:08:01 +09:00
utahta 219ad17459 update 2011-07-19 23:17:29 +09:00
utahta b039caf384 Merge branch 'develop' of github.com:utahta/pythonbrew into develop 2011-07-18 22:31:34 +09:00
utahta 1db87055fd Added buildout command 2011-07-18 22:31:13 +09:00
utahta aec7d769b1 bug fix 2011-07-11 19:03:37 +09:00
utahta cfdd193ffe release 0.8 2011-07-11 00:22:48 +09:00
utahta f09e32372d update 2011-07-11 00:01:20 +09:00
utahta 2469c1a7af update 2011-07-10 21:17:05 +09:00
utahta f9bcb60638 update readme 2011-07-10 20:51:27 +09:00
utahta 6cb6cc6057 update 0.8 2011-07-10 20:49:00 +09:00
utahta f410b1d1d8 update 2011-07-08 19:25:18 +09:00
utahta 8a1032b08c #21 support ubuntu 11.04(Natty) 2011-07-07 20:39:19 +09:00
utahta 87d0d7b52f #21 support ubuntu 11.04(Natty) 2011-07-07 19:37:30 +09:00
utahta 7371bde921 update config.cfg 2011-06-29 18:57:09 +09:00
utahta 7e5d138150 #30 bug fix 2011-06-29 18:10:26 +09:00
Thomas Grenfell Smith 7e5f5c72e1 Describe the 'symlink' command better 2011-06-23 16:04:32 -04:00
utahta 4a1174811c bug fix 2011-05-30 03:08:34 +09:00
Yuta 0b7a67b430 Merge branch 'bugfix-python27-environ' of https://github.com/npinto/pythonbrew into npinto-bugfix-python27-environ 2011-05-29 21:30:00 +09:00
Yuta 7f7e1d30a1 added 2.5.6 2011-05-29 21:29:09 +09:00
Nicolas Pinto 01af855533 Cleaning up 2011-05-28 17:12:23 -04:00
Nicolas Pinto 92c48adfac Add patch to fix _environ symbol missing bug in python27, see http://bugs.python.org/issue1602133 2011-05-28 17:10:45 -04:00
Nicolas Pinto 5c5ff69474 Add patch to fix _environ symbol missing bug in python27, see http://bugs.python.org/issue1602133 2011-05-28 17:04:16 -04:00
Nicolas Pinto b4bda56e4b Add patch to fix _environ symbol missing bug in python27, see http://bugs.python.org/issue1602133 2011-05-28 16:35:56 -04:00
utahta 4c64902d1d update README.rst 2011-05-25 22:20:53 -07:00
utahta 5ceec61246 update ChangeLog 2011-05-25 17:36:11 -07:00
Yuta c265aa4b78 release 0.7.3 2011-05-25 20:16:52 +09:00
utahta aa0bc97bc8 update symlink,uninstall command 2011-05-25 13:30:46 +09:00
Yuta c92148805d update py command 2011-05-25 01:01:35 +09:00
Yuta 0dfc0d38f1 update pythonbrew-install 2011-05-24 22:38:40 +09:00
utahta c0f9d4ed57 update symlink command 2011-05-24 18:12:31 +09:00
utahta 91101100a7 update py command 2011-05-19 18:29:31 +09:00
utahta a1e3d240ef support python3 2011-05-17 18:39:49 +09:00
Yuta b5b77fb483 Merge branch 'master' of github.com:utahta/pythonbrew 2011-05-04 23:03:49 +09:00
utahta 3a3f6b00ae remove \r 2011-05-03 20:54:50 -07:00
Chris Rose 48dec674ea Clean off trailing whitespace in the stable version number 2011-05-02 10:00:02 -06:00
Yuta e0b794d2b3 0.7.2 2011-05-02 18:09:18 +09:00
Yuta 20027a4a36 added patch-python26 2011-05-02 17:30:59 +09:00
Yuta 3bc8c36aaa release 0.7.1 2011-04-17 22:35:48 +09:00
Yuta 9731bd3c5c readme 2011-04-17 20:59:42 +09:00
Yuta 9393b66448 modified install and uninstall command 2011-04-17 20:48:48 +09:00
Yuta c8779d0322 added -f option to update command 2011-04-17 10:48:26 +09:00
Yuta 3a220f342a Added -b option to symlink command 2011-04-17 10:43:54 +09:00
Yuta 358bb34395 bug fix 2011-04-13 23:26:01 +09:00
utahta 867ffcb054 refactoring 2011-04-13 18:11:37 +09:00
Yuta cdb92c3e2a pythonbrew-install script accept Python-2.7 2011-04-12 00:44:37 +09:00
Yuta bb24bd5fb4 enable parallel make 2011-04-01 01:28:17 +09:00
Yuta ff2af78672 0.7 release 2011-03-23 01:27:00 +09:00
Yuta eb49f121db Added symlink command. Added --as option. 2011-03-23 01:14:39 +09:00
Yuta 2f3fbeca53 fixed 2011-03-20 04:09:36 +09:00
Yuta 7d002f2429 0.6.9 release 2011-03-20 04:06:05 +09:00
Yuta 4b319dfb8c bug fixed 2011-03-20 04:00:42 +09:00
Yuta 3a9cfe074e update command 2011-03-20 03:45:58 +09:00
Yuta c7c4ab09c8 Added config.cfg 2011-03-20 01:30:20 +09:00
Yuta 459fdae35f Added pybrew to bashrc and Help command by default 2011-03-19 02:26:44 +09:00
Yuta 7e494c1c7e update 0.6.8 2011-03-17 20:29:02 +09:00
Yuta e7d3bc5f8a Added Python-3.2 to the list 2011-03-17 20:20:12 +09:00
utahta acd817860b remove test_dummy.py 2010-12-10 01:37:56 +09:00
utahta f7b0bb80f0 update 0.6.7 2010-12-10 01:29:10 +09:00
utahta 966fa577f7 Bug fixed. Added tests. 2010-12-10 01:26:11 +09:00
utahta 7b2ae023bf update 0.6.6 2010-12-07 16:16:19 +09:00
utahta 2b19c65dce Added py command. 2010-12-07 15:51:11 +09:00
utahta c0d749d7dc update 0.6.5 2010-12-01 01:55:12 +09:00
utahta 15a57b10dc supported file: URIs 2010-12-01 01:52:21 +09:00
utahta 01128aebfd update 0.6.4 2010-11-25 23:31:26 +09:00
utahta 16b465dd24 update ChangeLog 2010-11-25 23:20:40 +09:00
utahta 8e54618ff4 removed installed command. added some functions to bashrc. 2010-11-25 23:14:19 +09:00
utahta 5fadee8e92 update 0.6.3 2010-11-25 01:20:25 +09:00
utahta 611b71d635 added use command. added some functions to bashrc. 2010-11-25 01:12:24 +09:00
utahta 159d839803 update 0.6.2 2010-11-22 02:18:15 +09:00
utahta a7ef06f6ae fixed installed command. 2010-11-22 02:04:16 +09:00
utahta 88157a4a96 , added patch-gestaltmodule.c.diff 2010-11-21 18:23:42 +09:00
utahta c5f31138c1 use curl instead of urllib 2010-11-21 12:44:15 +09:00
utahta 0605c27c57 added some function to bashrc. fixed issue 2. 2010-11-20 07:38:22 +09:00
utahta 0bc17f56db update version 0.6.1 2010-11-18 01:29:24 +09:00
utahta 53236cc001 add managed version file 2010-11-18 00:51:51 +09:00
utahta 2c527f98e1 fixed 2010-11-17 01:26:14 +09:00
utahta 79278f78b3 add setup.py MANIFEST.in 2010-11-17 00:49:42 +09:00
utahta a696654e64 Refactoring: update command 2010-11-16 23:25:43 +09:00
utahta 828f488865 Bug fix. Added list option (--all-versions). 2010-11-15 02:40:31 +09:00
utahta c7aeaa9fcd update 0.6 2010-11-14 03:27:13 +09:00
utahta 97b101f33c bug fix. Added PythonInstaller class. 2010-11-13 21:24:37 +09:00
utahta b357cc13ff bug fix. 2010-11-13 04:01:14 +09:00
utahta 3f455e161b update 0.5 2010-11-13 03:25:56 +09:00
86 changed files with 5819 additions and 1456 deletions
+5
View File
@@ -5,3 +5,8 @@
.settings
.tmp_*
*.pyc
pythonbrew.egg-info
dist
__pycache__
*.swp
.idea
+98
View File
@@ -0,0 +1,98 @@
* 1.1
- Added --framework, --universal and --static options to install command.
* 1.0
- Added systemwide install support. (issue #31)
- Fixed issue #41 Handle venv binary with the symlink command.
- Improved `venv` command (without virtualenvwrapper)
* 0.9
- Added `buildout` command.
- Added `venv` command.
* 0.8
- Fixed issue #21 Added Ubuntu 11.04(Natty) support
- Fixed issue #24 non-framework python27 now defines environ properly. Thanks npinto.
- Fixed issue #27 Cleanup of OS X python build flags
- Fixed issue #28 Describe the 'symlink' command better. Thanks tgs.
- Fixed issue #30 py command does not accept arguments with a space
- Fixed bug: `pythonbrew off` need not have removed the symlink in bin directory
- Added --no-test option to the install command
- Added --verbose option to the install command
- `pythonbrew clean` has been removed. Added `pythonbrew cleanup` instead.
* 0.7.3
- Improved symlink command
- Added python3 support
* 0.7.2
- Bug fixed
* 0.7.1
- Enable parallel make option (--jobs).
- The pythonbrew-install script accept Python-2.7.
- Added -b option to symlink command.
* 0.7
- Added symlink command.
- Added --as option.
* 0.6.9
- Bug fixed.
- Added config.cfg
- Help command by default
* 0.6.8
- Added Python-3.2 to the installation list
* 0.6.7
- Bug fixed: Off command did not work.
- Added tests.
* 0.6.6
- Added py command
* 0.6.5
- Supported file: URIs
* 0.6.4
- Added some functions to bashrc
- Removed installed command
- Bug fix
* 0.6.3
- Added use command
- Added some functions to bashrc
- Bug fix
* 0.6.2
- Use curl instead of urllib
- Added patch-gestaltmodule.c.diff
- Added some functions to bashrc
* 0.6.1
- Add setup.py MANIFEST.in
- Added list option (--all-versions)
- Bug fix
* 0.6
- Compiling Python-2.5.5 and Python-2.4.6 on MacOSX SnowLeopard
- Bug fix
* 0.5
- This version is incompatible with the 0.4 or less.
- Split the file.
- Added pythonbrew-install script.
- Added pybrew script. This is a symbolic pythonbrew.
- Rename `search` to `list`.
- Removed `init`.
- Added syntax that `pythonbrew command <VERSION>`
- Change default PYTHONBREW_ROOT path as $HOME/.pythonbrew
* 0.4
* 0.3
* 0.2
- Bug fix
* 0.1
- First release
+3
View File
@@ -0,0 +1,3 @@
recursive-include pythonbrew/patches *
recursive-include pythonbrew/etc *
include pythonbrew_install.py
+211
View File
@@ -0,0 +1,211 @@
Overview
========
pythonbrew is a program to automate the building and installation of Python in the users $HOME.
pythonbrew is inspired by `perlbrew <http://github.com/gugod/App-perlbrew>`_ and `rvm <https://github.com/wayneeseguin/rvm>`_.
Installation
============
The recommended way to download and install pythonbrew is to run these statements in your shell::
curl -kL http://xrl.us/pythonbrewinstall | bash
After that, pythonbrew installs itself to ~/.pythonbrew.
Please add the following line to the end of your ~/.bashrc::
[[ -s $HOME/.pythonbrew/etc/bashrc ]] && source $HOME/.pythonbrew/etc/bashrc
If you need to install pythonbrew into somewhere else, you can do that by setting a PYTHONBREW_ROOT environment variable::
export PYTHONBREW_ROOT=/path/to/pythonbrew
curl -kLO http://xrl.us/pythonbrewinstall
chmod +x pythonbrewinstall
./pythonbrewinstall
For Systemwide(Multi-User) installation
---------------------------------------
If the install script is run as root, pythonbrew will automatically install into /usr/local/pythonbrew.
The pythonbrew will be automatically configured for every user on the system if you install as root.
After installation, where you would normally use `sudo`, non-root users will need to use `sudopybrew`::
sudopybrew install -n -v -j2 2.7.2
Usage
=====
pythonbrew command [options]
Install some pythons::
pythonbrew install 2.7.2
pythonbrew install --verbose 2.7.2
pythonbrew install --force 2.7.2
pythonbrew install --no-test 2.7.2
pythonbrew install --configure="CC=gcc_4.1" 2.7.2
pythonbrew install --no-setuptools 2.7.2
pythonbrew install http://www.python.org/ftp/python/2.7/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2
pythonbrew install 2.7.2 3.2
Permanently use the specified python::
pythonbrew switch 2.7.2
pythonbrew switch 3.2
Use the specified python in current shell::
pythonbrew use 2.7.2
Runs a named python file against specified and/or all pythons::
pythonbrew py test.py
pythonbrew py -v test.py # Show verbose output
pythonbrew py -p 2.7.2 -p 3.2 test.py # Use the specified pythons
List the installed pythons::
pythonbrew list
List the available installation pythons::
pythonbrew list -k
Uninstall the specified python::
pythonbrew uninstall 2.7.2
pythonbrew uninstall 2.7.2 3.2
Remove stale source folders and archives::
pythonbrew cleanup
Upgrades pythonbrew to the latest version::
pythonbrew update
pythonbrew update --master
pythonbrew update --develop
Disable pythonbrew::
pythonbrew off
Create/Remove a symbolic link to python (in a directory on your $PATH)::
pythonbrew symlink # Create a symbolic link, like "py2.7.2", for each installed version
pythonbrew symlink -p 2.7.2
pythonbrew symlink pip # Create a symbolic link to the specified script in bin directory
pythonbrew symlink -r # Remove a symbolic link
pythonbrew symlink -v foo # Create a symbolic link to the specified virtual environment python in bin directory
Runs the buildout with specified or current using python::
pythonbrew buildout
pythonbrew buildout -p 2.6.6
Create isolated python environments (uses virtualenv)::
pythonbrew venv init
pythonbrew venv create proj
pythonbrew venv list
pythonbrew venv use proj
pythonbrew venv delete proj
Show version::
pythonbrew version
COMMANDS
========
install <version>
Build and install the given version of python.
Install setuptools and pip automatically.
switch <version>
Permanently use the specified python as default.
use <version>
Use the specified python in current shell.
py <python file>
Runs a named python file against specified and/or all pythons.
list
List the installed all pythons.
list -k <version>
List the available install pythons.
uninstall <version>
Uninstall the given version of python.
cleanup
Remove stale source folders and archives.
update
Upgrades pythonbrew to the latest version.
off
Disable pythonbrew.
symlink
Create/Remove a symbolic link to python (in a directory on your $PATH)
buildout
Runs the buildout with specified or current using python.
venv
Create isolated python environments (uses virtualenv)
version
Show version.
See more details below
`pythonbrew help <command>`
Changelog
=========
1.1 (2011-08-29)
----------------
- Added --framework, --universal and --static options to install command.
1.0 (2011-08-08)
----------------
- Added systemwide install support. (issue #31)
- Fixed issue #41 Handle venv binary with the symlink command.
- Improved `venv` command (without virtualenvwrapper)
0.9 (2011-07-21)
----------------
- Added `venv` command (uses virtualenv and virtualenvwrapper)
- Added `buildout` command.
0.8 (2011-07-10)
----------------
- Fixed issue #21 Added Ubuntu 11.04(Natty) support
- Fixed issue #24 non-framework python27 now defines environ properly. Thanks npinto.
- Fixed issue #27 Cleanup of OS X python build flags
- Fixed issue #28 Describe the 'symlink' command better. Thanks tgs.
- Fixed issue #30 py command does not accept arguments with a space
- Fixed bug: `pythonbrew off` need not have removed the symlink in bin directory
- Added --no-test option to the install command
- Added --verbose option to the install command
- `pythonbrew clean` has been removed. Added `pythonbrew cleanup` instead.
More
----
see the `pythonbrew/Changelog <https://github.com/utahta/pythonbrew/blob/master/ChangeLog>`_
+138 -59
View File
@@ -1,73 +1,132 @@
Overview
========
pythonbrew is a program to automate the building and installation of Python in the users HOME.
Pythonbrew is anti-virtualenv. This isn't.
pythonbrew is based on `perlbrew <http://github.com/gugod/App-perlbrew>`_.
Differences:
- No `switch`. That's crazy.
- Bottles (pre-compiled Pythons)
----------------------------------
pythonbrew is a program to automate the building and installation of Python in the users $HOME.
pythonbrew is inspired by `perlbrew <http://github.com/gugod/App-perlbrew>`_ and `rvm <https://github.com/wayneeseguin/rvm>`_.
Installation
============
Following python version is required to use pythonbrew:
2.4 <= Python < 3
The recommended way to download and install pythonbrew is to run these statements in your shell::
The recommended way to download and install pythonbrew is to run these statements in your shell.::
curl -kL http://xrl.us/pythonbrewinstall | bash
curl -LO http://github.com/utahta/pythonbrew/raw/master/pythonbrew
chmod +x pythonbrew
./pythonbrew install
After that, pythonbrew installs itself to ~/.pythonbrew.
After that, pythonbrew installs itself to ~/python/pythonbrew/bin, and you should follow the instruction on screen to setup your .bashrc or .cshrc to put it in your PATH.
Please add the following line to the end of your ~/.bashrc::
If you need to install pythonbrew into somewhere else, you can do that by setting a PYTHONBREW_ROOT environment variable.::
[[ -s $HOME/.pythonbrew/etc/bashrc ]] && source $HOME/.pythonbrew/etc/bashrc
If you need to install pythonbrew into somewhere else, you can do that by setting a PYTHONBREW_ROOT environment variable::
export PYTHONBREW_ROOT=/path/to/pythonbrew
./pythonbrew install
curl -kLO http://xrl.us/pythonbrewinstall
chmod +x pythonbrewinstall
./pythonbrewinstall
For Systemwide(Multi-User) installation
---------------------------------------
If the install script is run as root, pythonbrew will automatically install into /usr/local/pythonbrew.
The pythonbrew will be automatically configured for every user on the system if you install as root.
After installation, where you would normally use `sudo`, non-root users will need to use `sudopybrew`::
sudopybrew install -n -v -j2 2.7.2
Usage
=====
pythonbrew command [options]
Initialize::
Install some pythons::
pythonbrew init
Install some Pythons::
pythonbrew install 2.7.2
pythonbrew install --verbose 2.7.2
pythonbrew install --force 2.7.2
pythonbrew install --no-test 2.7.2
pythonbrew install --configure="CC=gcc_4.1" 2.7.2
pythonbrew install --no-setuptools 2.7.2
pythonbrew install http://www.python.org/ftp/python/2.7/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2.tgz
pythonbrew install /path/to/Python-2.7.2
pythonbrew install 2.7.2 3.2
pythonbrew install Python-3.1.2
pythonbrew install Python-2.6.6
pythonbrew install --configure="CC=gcc_4.1" Python-2.6.6
pythonbrew install --no-setuptools Python-2.6.6
pythonbrew install http://www.python.org/ftp/python/2.6.6/Python-2.6.6.tgz
pythonbrew install /path/to/Python-2.6.6.tgz
Switch python in the $PATH::
Permanently use the specified python::
pythonbrew switch Python-2.6.6
pythonbrew switch /path/to/python
pythonbrew switch 2.7.2
pythonbrew switch 3.2
Search python packages::
Use the specified python in current shell::
pythonbrew search Python-2.6
pythonbrew search Python-3
pythonbrew use 2.7.2
Uninstall some Pythons::
Runs a named python file against specified and/or all pythons::
pythonbrew uninstall Python-2.6.6
pythonbrew py test.py
pythonbrew py -v test.py # Show verbose output
pythonbrew py -p 2.7.2 -p 3.2 test.py # Use the specified pythons
List the installed pythons::
pythonbrew list
List the available installation pythons::
pythonbrew list -k
Uninstall the specified python::
pythonbrew uninstall 2.7.2
pythonbrew uninstall 2.7.2 3.2
Remove stale source folders and archives::
pythonbrew clean
pythonbrew cleanup
Upgrades pythonbrew to the latest version::
pythonbrew update
pythonbrew update --master
pythonbrew update --develop
Disable pythonbrew::
pythonbrew off
Create/Remove a symbolic link to python (in a directory on your $PATH)::
pythonbrew symlink # Create a symbolic link, like "py2.7.2", for each installed version
pythonbrew symlink -p 2.7.2
pythonbrew symlink pip # Create a symbolic link to the specified script in bin directory
pythonbrew symlink -r # Remove a symbolic link
pythonbrew symlink -v foo # Create a symbolic link to the specified virtual environment python in bin directory
Runs the buildout with specified or current using python::
pythonbrew buildout
pythonbrew buildout -p 2.6.6
Create isolated python environments (uses virtualenv)::
pythonbrew venv init
pythonbrew venv create proj
pythonbrew venv list
pythonbrew venv use proj
pythonbrew venv delete proj
Show version::
pythonbrew version
@@ -75,34 +134,29 @@ Show version::
COMMANDS
========
init
Run this once to setup the pythonbrew directory ready for installing.
pythons into. Run it again if you decide to change PYTHONBREW_ROOT.
install <version>
Build and install the given version of python.
Install setuptools and pip automatically.
install Python-<version>
Build and install the given version of Python.
Setuptools and pip is automatically installed.
options: --force, --no-setuptools and --configure.
switch <version>
Permanently use the specified python as default.
installed
List the installed versions of python.
use <version>
Use the specified python in current shell.
switch Python-<version>
Switch to the given version.
py <python file>
Runs a named python file against specified and/or all pythons.
switch /path/to/python
Switch to the given version of python.
list
List the installed all pythons.
search Python-<version>
Search Python packages.
uninstall Python-<version>
list -k <version>
List the available install pythons.
uninstall <version>
Uninstall the given version of python.
clean
cleanup
Remove stale source folders and archives.
update
@@ -111,17 +165,42 @@ update
off
Disable pythonbrew.
symlink
Create/Remove a symbolic link to python (in a directory on your $PATH)
buildout
Runs the buildout with specified or current using python.
venv
Create isolated python environments (uses virtualenv)
version
Show version.
Options
See more details below
`pythonbrew help <command>`
LICENCE
=======
\-f | --force
Force installation of a Python.
The MIT License
\-C | --configure
Custom configure options.
Copyright (c) <2010-2011> <utahta>
\-n | --no-setuptools
Skip installation of setuptools.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-696
View File
@@ -1,696 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
import os
import sys
import urllib
import errno
import re
import shutil
import filecmp
import subprocess
import tempfile
from HTMLParser import HTMLParser
from optparse import OptionParser
VERSION = "0.4"
if os.environ.has_key("PYTHONBREW_ROOT"):
ROOT = os.environ["PYTHONBREW_ROOT"]
else:
ROOT = "%s/python/pythonbrew" % os.environ["HOME"]
PYTHONDLSITE = "http://www.python.org/ftp/python/%s/%s"
DISTRIBUTE_SETUP_DLSITE = "http://python-distribute.org/distribute_setup.py"
PYTHONBREW_DLSITE = "http://github.com/utahta/pythonbrew/raw/master/pythonbrew"
PATH_PYTHONS = "%s/pythons" % ROOT
PATH_BUILD = "%s/build" % ROOT
PATH_DISTS = "%s/dists" % ROOT
PATH_ETC = "%s/etc" % ROOT
PATH_BIN = "%s/bin" % ROOT
parser = OptionParser(usage="%prog COMMAND [OPTIONS]",
version=VERSION,
add_help_option=False)
parser.add_option(
'-h', '--help',
dest='help',
action='store_true',
help='Show help')
parser.disable_interspersed_args()
command_dict = {}
def add_command(command):
command_dict[command.name] = command
#----------------------------------------------------
# exception
#----------------------------------------------------
class BuildingException(Exception):
"""General exception during building"""
#----------------------------------------------------
# util
#----------------------------------------------------
def size_format(b):
kb = 1000
mb = kb*kb
b = float(b)
if b >= mb:
return "%.1fMb" % (b/mb)
if b >= kb:
return "%.1fKb" % (b/kb)
return "%.0fbytes" % (b)
def is_url(name):
if ':' not in name:
return False
scheme = name.split(':', 1)[0].lower()
return scheme in ['http', 'https', 'file', 'ftp']
def splitext(name):
base, ext = os.path.splitext(name)
if base.lower().endswith('.tar'):
ext = base[-4:] + ext
base = base[:-4]
return base, ext
def is_archive_file(name):
ext = splitext(name)[1].lower()
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar')
if ext in archives:
return True
return False
def makedirs(path):
try:
os.makedirs(path)
except OSError, (e, es):
if errno.EEXIST != e:
raise
def symlink(src, dst):
try:
os.symlink(src, dst)
except:
pass
def unlink(path):
try:
os.unlink(path)
except OSError, (e, es):
if errno.ENOENT != e:
raise
def rm_r(path):
"""like rm -r command."""
if os.path.isdir(path):
shutil.rmtree(path)
else:
unlink(path)
def off():
for root, dirs, files in os.walk(PATH_BIN):
for f in files:
if f == "pythonbrew":
continue
unlink("%s/%s" % (root, f))
unlink("%s/current" % PATH_PYTHONS)
def copy_myself(path):
(fd, src) = tempfile.mkstemp()
fp = file(path, "r")
line = fp.readline()
if line.startswith("#!"):
os.write(fd, "#!%s\n" % os.path.realpath(sys.executable))
else:
os.write(fd, line)
os.write(fd, fp.read())
os.close(fd)
fp.close()
dist = "%s/pythonbrew" % PATH_BIN
if os.path.isfile(src) and os.path.isfile(dist):
if filecmp.cmp(src, dist):
unlink(src)
return (False, dist)
makedirs(PATH_BIN)
shutil.copy(src, dist)
os.chmod(dist, 0755)
unlink(src)
return (True, dist)
#----------------------------------------------------
# classes
#----------------------------------------------------
class Downloader(object):
def __init__(self):
self._msg = ""
self._last_msg = ""
self._bytes = 0.0
def download(self, msg, url, path):
self._msg = msg
self._bytes = 0
urllib.urlretrieve(url, path, self._download_progress)
print " downloaded."
def _download_progress(self, block, blockbytes, maxbytes):
self._bytes += float(blockbytes)
if self._bytes >= maxbytes:
self._bytes = maxbytes
percent = (self._bytes / maxbytes) * 100
max_size = size_format(maxbytes)
now_size = size_format(self._bytes)
now_msg = "\rDownloading %s (%s): %3i%% %s" % (self._msg, max_size, percent, now_size)
padding = " " * (len(self._last_msg) - len(now_msg))
sys.stdout.write("%s%s" % (now_msg, padding))
sys.stdout.flush()
self._last_msg = now_msg
class Subprocess(object):
def __init__(self, log=None, shell=False, cwd=None, print_cmd=True):
self._log = log
self._shell = shell
self._cwd = cwd
self._print_cmd = print_cmd
def chdir(self, cwd):
self._cwd = cwd
def check_call(self, cmd, shell=None, cwd=None):
if shell:
self._shell = shell
if cwd:
self._cwd = cwd
if self._print_cmd:
print cmd
if self._log:
cmd = "(%s) >> '%s' 2>&1" % (cmd, self._log)
retcode = subprocess.call(cmd, shell=self._shell, cwd=self._cwd)
if retcode != 0:
raise BuildingException()
class PythonVersionParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self._versions = []
self._re = re.compile("^(\d+\.\d+(\..*)?)/$")
def handle_starttag(self, tag, attrs):
if tag == "a":
attrs = dict(attrs)
if "href" in attrs:
m = self._re.search(attrs["href"])
if m:
self._versions.append(m.group(1))
def get_sorted_versions(self):
return sorted(self._versions)
class PythonPackages(object):
def __init__(self):
parser = PythonVersionParser()
fp = urllib.urlopen("http://www.python.org/ftp/python/")
parser.feed(fp.read())
fp.close()
parser.close()
self._versions = parser.get_sorted_versions()
def has_version(self, version):
return version in self._versions
def get_packages(self):
return ["Python-%s" % v for v in self._versions]
#----------------------------------------------------
# commands
#----------------------------------------------------
class Command(object):
name = None
usage = None
summary = ""
def __init__(self):
self.parser = OptionParser(usage=self.usage,
prog='%s %s' % (os.path.basename(sys.argv[0]), self.name))
def run(self, args):
options, args = self.parser.parse_args(args)
self.run_command(options, args[1:])
class HelpCommand(Command):
name = "help"
usage = "%prog [COMMAND]"
summary = "Show available commands"
def run_command(self, options, args):
if args:
command = args[0]
if command not in command_dict:
parser.error("Unknown command: `%s`" % command)
return
command = command_dict[command]
command.parser.print_help()
return
parser.print_help()
print
print "Commands available:"
commands = [command_dict[key] for key in sorted(command_dict.keys())]
for command in commands:
print " %s: %s" % (command.name, command.summary)
print
print "Further Instructions:"
print " http://github.com/utahta/pythonbrew"
class InitCommand(Command):
name = "init"
usage = "%prog"
summary = "Run this once to setup the pythonbrew directory ready for installing pythons into"
def run_command(self, options, args):
makedirs(PATH_PYTHONS)
makedirs(PATH_BUILD)
makedirs(PATH_DISTS)
makedirs(PATH_ETC)
os.system("echo 'export PATH=%s/bin:%s/current/bin:${PATH}' > %s/bashrc" % (ROOT, PATH_PYTHONS, PATH_ETC))
os.system("echo 'setenv PATH %s/bin:%s/current/bin:$PATH' > %s/cshrc" % (ROOT, PATH_PYTHONS, PATH_ETC))
m = re.search("(t?csh)", os.environ.get("SHELL"))
if m:
shrc = "cshrc"
yourshrc = m.group(1)+"rc"
else:
shrc = yourshrc = "bashrc"
print """
Pythonbrew environment initiated, required directories are created under
"""+ROOT+"""
Well-done! Congratulations! Please add the following line to the end
of your ~/."""+yourshrc+"""
source """+PATH_ETC+"""/"""+shrc+"""
After that, exit this shell, start a new one, and install some fresh
pythons:
pythonbrew install Python-2.6.6
pythonbrew install Python-2.5.5
For further instructions, simply run:
pythonbrew
The default help messages will popup and tell you what to do!
Enjoy pythonbrew at $HOME!!
INSTRUCTION"""
class InstallCommand(Command):
name = "install"
usage = "%prog [OPTIONS] PACKAGE_NAMES"
summary = "Build and install the given version of python"
def __init__(self):
super(InstallCommand, self).__init__()
self.parser.add_option(
"-f", "--force",
dest="force",
action="store_true",
default=False,
help="Force installation of a Python."
)
self.parser.add_option(
"-C", "--configure",
dest="configure",
default="",
metavar="CONFIGURE_OPTIONS",
help="Custom configure options."
)
self.parser.add_option(
"-n", "--no-setuptools",
dest="no_setuptools",
action="store_true",
default=False,
help="Skip installation of setuptools."
)
self._logfile = "%s/build.log" % ROOT
def run_command(self, options, args):
if args:
# Install Python
self._install_python(args[0], options)
else:
# Install pythonbrew
self._install_myself()
def _install_myself(self):
executable = os.path.abspath(sys.argv[0])
(retval, dist) = copy_myself(executable)
if not retval:
print "You are already running the installed latest version of pythonbrew."
print "\n%s" % dist
sys.exit()
print """The pythonbrew is installed as:
"""+dist+"""
You may trash the downloaded """+executable+""" from now on.
Next, if this is the first time you've run pythonbrew installation, run:
"""+dist+""" init
And follow the instruction on screen."""
def _get_package(self, name):
if not os.path.isfile(name) and not os.path.isdir(name):
if is_url(name):
basename = os.path.basename(name)
download_url = name
download_path = "%s/%s" % (PATH_DISTS, basename)
else:
m = re.search("^Python-(\d+\.\d+(\..*)?)$", name)
if not m:
print "Unknown package: `%s`" % name
sys.exit(1)
if os.path.isdir("%s/%s" % (PATH_PYTHONS, name)):
print "You are already installed `%s`." % name
sys.exit()
dist_version = m.group(1)
pkgs = PythonPackages()
if not pkgs.has_version(dist_version):
print "Package not found: `%s`" % name
sys.exit(1)
basename = "%s.tgz" % name
download_url = PYTHONDLSITE % (dist_version, basename)
download_path = "%s/%s" % (PATH_DISTS, basename)
if os.path.isfile(download_path):
print "Use the previously fetched %s" % (download_path)
else:
try:
dl = Downloader()
dl.download(
basename,
download_url,
download_path
)
except:
unlink(download_path)
print "\nInterrupt to abort. `%s`" % (download_url)
sys.exit(1)
# iffy
if os.path.getsize(download_path) < 1000000:
print "Failed to download. (maybe not stable version of python) `%s`" % (download_url)
unlink(download_path)
sys.exit(1)
else:
if is_archive_file(name):
basename = os.path.basename(name)
print "Copy the archive file %s to %s/%s" % (name, PATH_DISTS, basename)
shutil.copy(name, "%s/%s" % (PATH_DISTS, basename))
else:
print "Invalid file. `%s`" % name
sys.exit(1)
return basename
def _get_uncompress_command(self, basename):
distpath = "%s/%s" % (PATH_DISTS, basename)
if os.path.isfile(distpath):
ext = splitext(basename)[1]
if ext == ".tar.gz" or ext == ".tgz":
return "tar zxf %s" % (distpath)
elif ext == ".tar.bz2":
return "tar jxf %s" % (distpath)
elif ext == ".tar":
return "tar xf %s" % (distpath)
elif ext == ".zip":
return "unzip %s" % (distpath)
elif os.path.isdir(distpath):
return "mv %s %s/%s" % (distpath, PATH_BUILD, basename)
else:
print "File not found. `%s`" % (basename)
return ""
def _install_python(self, dist, options):
basename = self._get_package(dist)
pkgname = splitext(basename)[0]
install_dir = "%s/%s" % (PATH_PYTHONS, pkgname)
configure = "--prefix=%s %s" % (install_dir, options.configure)
print "Installing %s into %s" % (pkgname, install_dir);
print """This could take a while. You can run the following command on another shell to track the status:
tail -f %s
""" % (self._logfile)
try:
s = Subprocess(log=self._logfile, shell=True, cwd=PATH_BUILD)
s.check_call(self._get_uncompress_command(basename))
s.chdir("%s/%s" % (PATH_BUILD, pkgname))
s.check_call("./configure %s" % (configure))
if options.force:
s.check_call("make")
s.check_call("make install")
else:
s.check_call("make")
s.check_call("make test")
s.check_call("make install")
except:
print """Installing %(pkgname)s failed. See %(ROOT)s/build.log to see why.
pythonbrew install --force %(pkgname)s""" % {"pkgname":pkgname, "ROOT":ROOT}
sys.exit(1)
# install setuptools
self._install_setuptools(pkgname, options.no_setuptools)
print """
Installed %(pkgname)s successfully. Run the following command to switch to it.
pythonbrew switch %(pkgname)s""" % {"pkgname":pkgname}
def _install_setuptools(self, pkgname, no_setuptools):
if no_setuptools:
print "Skip installation setuptools."
return
if re.match("^Python-3.*", pkgname):
is_python3 = True
else:
is_python3 = False
download_url = DISTRIBUTE_SETUP_DLSITE
basename = os.path.basename(download_url)
dl = Downloader()
dl.download(basename, download_url, "%s/%s" % (PATH_DISTS, basename))
if is_python3:
if os.path.isfile("%s/%s/bin/python3" % (PATH_PYTHONS, pkgname)):
pyexec = "%s/%s/bin/python3" % (PATH_PYTHONS, pkgname)
elif os.path.isfile("%s/%s/bin/python3.0" % (PATH_PYTHONS, pkgname)):
pyexec = "%s/%s/bin/python3.0" % (PATH_PYTHONS, pkgname)
else:
print "Python3 binary not found. `%s/%s`" % (PATH_PYTHONS, pkgname)
return
else:
pyexec = "%s/%s/bin/python" % (PATH_PYTHONS, pkgname)
try:
s = Subprocess(log=self._logfile, shell=True, cwd=PATH_DISTS)
s.check_call("%s %s" % (pyexec, basename))
if os.path.isfile("%s/%s/bin/easy_install" % (PATH_PYTHONS, pkgname)) and not is_python3:
s.check_call("%s/%s/bin/easy_install pip" % (PATH_PYTHONS, pkgname), cwd=None)
except:
print "Installing setuptools failed. See %s/build.log to see why." % (ROOT)
sys.exit(1)
class InstalledCommand(Command):
name = "installed"
usage = "%prog"
summary = "List the installed versions of python"
def run_command(self, options, args):
if not os.path.islink("%s/current" % PATH_PYTHONS):
cur = os.path.realpath("%s/bin/python" % ROOT)
print "%s (*)" % cur
elif os.path.islink("%s/current" % PATH_PYTHONS):
cur = os.path.basename(os.path.realpath("%s/current" % PATH_PYTHONS))
else:
cur = ""
for d in sorted(os.listdir("%s/" % PATH_PYTHONS)):
if d == "current":
continue
if cur == d:
print "%s (*)" % cur
else:
print "%s" % (d)
class SwitchCommand(Command):
name = "switch"
usage = "%prog PACKAGE"
summary = "Switch to the given version"
def run_command(self, options, args):
if args:
dist = args[0]
distdir = dist
if os.path.isfile( dist ) and os.access( dist, os.X_OK ):
if re.search( ".*python(\d(\.\d)?)?$", dist ):
self._switch_file(dist)
else:
print "`%s` is not python binary." % dist
return
elif not os.path.isdir( "%s/%s" % (PATH_PYTHONS, dist) ):
print "`%s` is not installed." % dist
return
self._switch_dir( distdir )
def _switch_file(self, dist):
off()
symlink(dist, "%s/python" % PATH_BIN)
print "Switched to "+dist
def _switch_dir(self, dist):
off()
symlink(dist, "%s/current" % PATH_PYTHONS)
for root, dirs, files in os.walk("%s/current/bin/" % PATH_PYTHONS):
for f in files:
symlink("%s%s" % (root, f), "%s/%s" % (PATH_BIN, f))
break
# I want better code
if not os.path.isfile("%s/python" % PATH_BIN):
if os.path.isfile("%s/python3" % PATH_BIN):
symlink(os.path.realpath("%s/python3" % PATH_BIN), "%s/python" % PATH_BIN)
elif os.path.isfile("%s/python3.0" % PATH_BIN):
symlink(os.path.realpath("%s/python3.0" % PATH_BIN), "%s/python" % PATH_BIN)
print "Switched to "+dist
class OffCommand(Command):
name = "off"
usage = "%prog"
summary = "Disable pythonbrew"
def run_command(self, options, args):
off()
class VersionCommand(Command):
name = "version"
usage = "%prog"
summary = "Show version"
def run_command(self, options, args):
print VERSION
class SearchCommand(Command):
name = "search"
usage = "%prog Python-<VERSION>"
summary = "Search Python packages"
def run_command(self, options, args):
pkgs = PythonPackages()
if args:
pattern = args[0]
_re = re.compile(r"%s" % pattern)
pkgnames = []
for pkgname in pkgs.get_packages():
if _re.match(pkgname):
pkgnames.append(pkgname)
if pkgnames:
for pkgname in pkgnames:
print pkgname
else:
print "Package not found. `%s`" % pattern
else:
for pkgname in pkgs.get_packages():
print pkgname
class UninstallCommand(Command):
name = "uninstall"
usage = "%prog Python-<VERSION>"
summary = "Uninstall the given version of python"
def run_command(self, options, args):
if args:
pkgname = args[0]
pkgpath = "%s/%s" % (PATH_PYTHONS, pkgname)
if not os.path.isdir(pkgpath):
print "%s is not installed." % pkgname
sys.exit(1)
if os.path.islink("%s/current" % PATH_PYTHONS):
curpath = os.path.realpath("%s/current" % PATH_PYTHONS)
if pkgpath == curpath:
off()
rm_r(pkgpath)
else:
self.parser.print_help()
class CleanCommand(Command):
name = "clean"
usage = "%prog"
summary = "Remove stale source folders and archives"
def run_command(self, options, args):
self._clean(PATH_BUILD)
self._clean(PATH_DISTS)
def _clean(self, root):
for dir in os.listdir(root):
rm_r("%s/%s" % (root, dir))
class UpdateCommand(Command):
name = "update"
usage = "%prog"
summary = "Upgrades pythonbrew to the latest version"
def run_command(self, options, args):
download_url = PYTHONBREW_DLSITE
basename = os.path.basename(download_url)
download_path = "%s/%s" % (PATH_DISTS, basename)
try:
d = Downloader()
d.download(basename, download_url, download_path)
except:
print "Failed to download. `%s`" % download_url
sys.exit(1)
(retval, dist) = copy_myself(download_path)
if not retval:
print "You are already running the installed latest version of pythonbrew."
print "\n%s" % dist
sys.exit()
print "The pythonbrew has been updated."
class Pythonbrew(object):
def run(self):
options, args = parser.parse_args(sys.argv[1:])
if options.help and not args:
args = ["help"]
if not args:
parser.error('You must give a command (use "pythonbrew help" to see a list of commands)')
return
add_command(HelpCommand())
add_command(InitCommand())
add_command(InstallCommand())
add_command(InstalledCommand())
add_command(SwitchCommand())
add_command(OffCommand())
add_command(VersionCommand())
add_command(SearchCommand())
add_command(UninstallCommand())
add_command(CleanCommand())
add_command(UpdateCommand())
command = args[0].lower()
if command not in command_dict:
parser.error("Unknown command: `%s`" % command)
return
command = command_dict[command]
command.run(args)
def main():
p = Pythonbrew()
p.run()
if __name__ == "__main__":
main()
+111
View File
@@ -0,0 +1,111 @@
#!/usr/bin/env bash
shopt -s extglob
PYTHONS="/usr/bin/python /usr/bin/python2 `command -v python`"
CURL=`command -v curl`
trim()
{
trimmed=$1
trimmed="${trimmed#"${trimmed%%[![:space:]]*}"}" # remove leading whitespace characters
trimmed="${trimmed%"${trimmed##*[![:space:]]}"}" # remove trailing whitespace characters
echo $trimmed
}
usage()
{
printf "
Usage:
${0} [options]
options:
--python : Python interpreter.
"
}
parse_arguments()
{
for arg do
val=`echo "$arg" | sed -e "s;--[^=]*=;;"`
case "$arg" in
--python=*) PYTHONS="$val $PYTHONS" ;;
--help) usage ;;
*) echo "Can't find the option. :$arg";;
esac
done
}
parse_arguments $@
if [[ ! -x $CURL ]] ; then
echo "pythonbrew required curl. curl was not found in your path."
exit
fi
for PYTHON in $PYTHONS ; do
if [[ ! -x $PYTHON ]] ; then
continue
fi
PYTHON_VERSION=`$PYTHON -V 2>&1`
PYTHON_VERSION=${PYTHON_VERSION/"Python "/""}
PYTHON_VERSION_S=`echo $PYTHON_VERSION | sed -e "s/\(^[[:digit:]]\{1,\}.[[:digit:]]\{1,\}\).*/\1/"`
if [[ $PYTHON_VERSION_S = "2.4" ]] || [[ $PYTHON_VERSION_S = "2.5" ]] || [[ $PYTHON_VERSION_S = "2.6" ]] || [[ $PYTHON_VERSION_S = "2.7" ]] || [[ ${PYTHON_VERSION_S:0:1} = "3" ]] ; then
PYTHON_FOUND='1'
break
fi
done
if [[ $PYTHON_FOUND != '1' ]] ; then
echo "pythonbrew required Python (2.4, 2.5, 2.6 or 2.7)."
#TODO Installing python.
exit
fi
systemwide_install=0
if [[ -n "$PYTHONBREW_ROOT" ]] ; then
ROOT="$PYTHONBREW_ROOT"
else
if (( UID == 0 )) ; then
systemwide_install=1
ROOT="/usr/local/pythonbrew"
else
ROOT="$HOME/.pythonbrew"
fi
fi
PATH_DISTS="$ROOT/dists"
STABLE_VERSION=`curl -skL https://github.com/utahta/pythonbrew/raw/master/stable-version.txt`
STABLE_VERSION=`trim $STABLE_VERSION`
if [[ -z "$STABLE_VERSION" ]] ; then
echo 'Can not get stable-version of pythonbrew.'
exit 1
fi
TEMP_FILE="pythonbrew-$STABLE_VERSION"
TEMP_TARBALL="$TEMP_FILE.tar.gz"
DOWNLOAD_URL="http://pypi.python.org/packages/source/p/pythonbrew/$TEMP_TARBALL"
mkdir -p "$PATH_DISTS"
rm -rf "$PATH_DISTS/$TEMP_TARBALL"
rm -rf "$PATH_DISTS/$TEMP_FILE"
echo "Downloading $DOWNLOAD_URL"
builtin cd $PATH_DISTS ; curl --progress-bar -kL $DOWNLOAD_URL -o "$TEMP_TARBALL"
echo "Extracting $PATH_DISTS/$TEMP_TARBALL"
builtin cd $PATH_DISTS ; tar zxf $TEMP_TARBALL
echo "Installing pythonbrew into $ROOT"
if (( systemwide_install == 1 )) ; then
PYTHONBREW_ROOT="$ROOT" $PYTHON $PATH_DISTS/$TEMP_FILE/pythonbrew_install.py --systemwide
else
$PYTHON $PATH_DISTS/$TEMP_FILE/pythonbrew_install.py
fi
if [[ $? == 1 ]] ; then
echo "Failed to install pythonbrew."
exit
fi
-696
View File
@@ -1,696 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
import os
import sys
import urllib
import errno
import re
import shutil
import filecmp
import subprocess
import tempfile
from HTMLParser import HTMLParser
from optparse import OptionParser
VERSION = "0.4"
if os.environ.has_key("PYTHONBREW_ROOT"):
ROOT = os.environ["PYTHONBREW_ROOT"]
else:
ROOT = "%s/python/pythonbrew" % os.environ["HOME"]
PYTHONDLSITE = "http://www.python.org/ftp/python/%s/%s"
DISTRIBUTE_SETUP_DLSITE = "http://python-distribute.org/distribute_setup.py"
PYTHONBREW_DLSITE = "http://github.com/utahta/pythonbrew/raw/master/pythonbrew"
PATH_PYTHONS = "%s/pythons" % ROOT
PATH_BUILD = "%s/build" % ROOT
PATH_DISTS = "%s/dists" % ROOT
PATH_ETC = "%s/etc" % ROOT
PATH_BIN = "%s/bin" % ROOT
parser = OptionParser(usage="%prog COMMAND [OPTIONS]",
version=VERSION,
add_help_option=False)
parser.add_option(
'-h', '--help',
dest='help',
action='store_true',
help='Show help')
parser.disable_interspersed_args()
command_dict = {}
def add_command(command):
command_dict[command.name] = command
#----------------------------------------------------
# exception
#----------------------------------------------------
class BuildingException(Exception):
"""General exception during building"""
#----------------------------------------------------
# util
#----------------------------------------------------
def size_format(b):
kb = 1000
mb = kb*kb
b = float(b)
if b >= mb:
return "%.1fMb" % (b/mb)
if b >= kb:
return "%.1fKb" % (b/kb)
return "%.0fbytes" % (b)
def is_url(name):
if ':' not in name:
return False
scheme = name.split(':', 1)[0].lower()
return scheme in ['http', 'https', 'file', 'ftp']
def splitext(name):
base, ext = os.path.splitext(name)
if base.lower().endswith('.tar'):
ext = base[-4:] + ext
base = base[:-4]
return base, ext
def is_archive_file(name):
ext = splitext(name)[1].lower()
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar')
if ext in archives:
return True
return False
def makedirs(path):
try:
os.makedirs(path)
except OSError, (e, es):
if errno.EEXIST != e:
raise
def symlink(src, dst):
try:
os.symlink(src, dst)
except:
pass
def unlink(path):
try:
os.unlink(path)
except OSError, (e, es):
if errno.ENOENT != e:
raise
def rm_r(path):
"""like rm -r command."""
if os.path.isdir(path):
shutil.rmtree(path)
else:
unlink(path)
def off():
for root, dirs, files in os.walk(PATH_BIN):
for f in files:
if f == "pythonbrew":
continue
unlink("%s/%s" % (root, f))
unlink("%s/current" % PATH_PYTHONS)
def copy_myself(path):
(fd, src) = tempfile.mkstemp()
fp = file(path, "r")
line = fp.readline()
if line.startswith("#!"):
os.write(fd, "#!%s\n" % os.path.realpath(sys.executable))
else:
os.write(fd, line)
os.write(fd, fp.read())
os.close(fd)
fp.close()
dist = "%s/pythonbrew" % PATH_BIN
if os.path.isfile(src) and os.path.isfile(dist):
if filecmp.cmp(src, dist):
unlink(src)
return (False, dist)
makedirs(PATH_BIN)
shutil.copy(src, dist)
os.chmod(dist, 0755)
unlink(src)
return (True, dist)
#----------------------------------------------------
# classes
#----------------------------------------------------
class Downloader(object):
def __init__(self):
self._msg = ""
self._last_msg = ""
self._bytes = 0.0
def download(self, msg, url, path):
self._msg = msg
self._bytes = 0
urllib.urlretrieve(url, path, self._download_progress)
print " downloaded."
def _download_progress(self, block, blockbytes, maxbytes):
self._bytes += float(blockbytes)
if self._bytes >= maxbytes:
self._bytes = maxbytes
percent = (self._bytes / maxbytes) * 100
max_size = size_format(maxbytes)
now_size = size_format(self._bytes)
now_msg = "\rDownloading %s (%s): %3i%% %s" % (self._msg, max_size, percent, now_size)
padding = " " * (len(self._last_msg) - len(now_msg))
sys.stdout.write("%s%s" % (now_msg, padding))
sys.stdout.flush()
self._last_msg = now_msg
class Subprocess(object):
def __init__(self, log=None, shell=False, cwd=None, print_cmd=True):
self._log = log
self._shell = shell
self._cwd = cwd
self._print_cmd = print_cmd
def chdir(self, cwd):
self._cwd = cwd
def check_call(self, cmd, shell=None, cwd=None):
if shell:
self._shell = shell
if cwd:
self._cwd = cwd
if self._print_cmd:
print cmd
if self._log:
cmd = "(%s) >> '%s' 2>&1" % (cmd, self._log)
retcode = subprocess.call(cmd, shell=self._shell, cwd=self._cwd)
if retcode != 0:
raise BuildingException()
class PythonVersionParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self._versions = []
self._re = re.compile("^(\d+\.\d+(\..*)?)/$")
def handle_starttag(self, tag, attrs):
if tag == "a":
attrs = dict(attrs)
if "href" in attrs:
m = self._re.search(attrs["href"])
if m:
self._versions.append(m.group(1))
def get_sorted_versions(self):
return sorted(self._versions)
class PythonPackages(object):
def __init__(self):
parser = PythonVersionParser()
fp = urllib.urlopen("http://www.python.org/ftp/python/")
parser.feed(fp.read())
fp.close()
parser.close()
self._versions = parser.get_sorted_versions()
def has_version(self, version):
return version in self._versions
def get_packages(self):
return ["Python-%s" % v for v in self._versions]
#----------------------------------------------------
# commands
#----------------------------------------------------
class Command(object):
name = None
usage = None
summary = ""
def __init__(self):
self.parser = OptionParser(usage=self.usage,
prog='%s %s' % (os.path.basename(sys.argv[0]), self.name))
def run(self, args):
options, args = self.parser.parse_args(args)
self.run_command(options, args[1:])
class HelpCommand(Command):
name = "help"
usage = "%prog [COMMAND]"
summary = "Show available commands"
def run_command(self, options, args):
if args:
command = args[0]
if command not in command_dict:
parser.error("Unknown command: `%s`" % command)
return
command = command_dict[command]
command.parser.print_help()
return
parser.print_help()
print
print "Commands available:"
commands = [command_dict[key] for key in sorted(command_dict.keys())]
for command in commands:
print " %s: %s" % (command.name, command.summary)
print
print "Further Instructions:"
print " http://github.com/utahta/pythonbrew"
class InitCommand(Command):
name = "init"
usage = "%prog"
summary = "Run this once to setup the pythonbrew directory ready for installing pythons into"
def run_command(self, options, args):
makedirs(PATH_PYTHONS)
makedirs(PATH_BUILD)
makedirs(PATH_DISTS)
makedirs(PATH_ETC)
os.system("echo 'export PATH=%s/bin:%s/current/bin:${PATH}' > %s/bashrc" % (ROOT, PATH_PYTHONS, PATH_ETC))
os.system("echo 'setenv PATH %s/bin:%s/current/bin:$PATH' > %s/cshrc" % (ROOT, PATH_PYTHONS, PATH_ETC))
m = re.search("(t?csh)", os.environ.get("SHELL"))
if m:
shrc = "cshrc"
yourshrc = m.group(1)+"rc"
else:
shrc = yourshrc = "bashrc"
print """
Pythonbrew environment initiated, required directories are created under
"""+ROOT+"""
Well-done! Congratulations! Please add the following line to the end
of your ~/."""+yourshrc+"""
source """+PATH_ETC+"""/"""+shrc+"""
After that, exit this shell, start a new one, and install some fresh
pythons:
pythonbrew install Python-2.6.6
pythonbrew install Python-2.5.5
For further instructions, simply run:
pythonbrew
The default help messages will popup and tell you what to do!
Enjoy pythonbrew at $HOME!!
INSTRUCTION"""
class InstallCommand(Command):
name = "install"
usage = "%prog [OPTIONS] PACKAGE_NAMES"
summary = "Build and install the given version of python"
def __init__(self):
super(InstallCommand, self).__init__()
self.parser.add_option(
"-f", "--force",
dest="force",
action="store_true",
default=False,
help="Force installation of a Python."
)
self.parser.add_option(
"-C", "--configure",
dest="configure",
default="",
metavar="CONFIGURE_OPTIONS",
help="Custom configure options."
)
self.parser.add_option(
"-n", "--no-setuptools",
dest="no_setuptools",
action="store_true",
default=False,
help="Skip installation of setuptools."
)
self._logfile = "%s/build.log" % ROOT
def run_command(self, options, args):
if args:
# Install Python
self._install_python(args[0], options)
else:
# Install pythonbrew
self._install_myself()
def _install_myself(self):
executable = os.path.abspath(sys.argv[0])
(retval, dist) = copy_myself(executable)
if not retval:
print "You are already running the installed latest version of pythonbrew."
print "\n%s" % dist
sys.exit()
print """The pythonbrew is installed as:
"""+dist+"""
You may trash the downloaded """+executable+""" from now on.
Next, if this is the first time you've run pythonbrew installation, run:
"""+dist+""" init
And follow the instruction on screen."""
def _get_package(self, name):
if not os.path.isfile(name) and not os.path.isdir(name):
if is_url(name):
basename = os.path.basename(name)
download_url = name
download_path = "%s/%s" % (PATH_DISTS, basename)
else:
m = re.search("^Python-(\d+\.\d+(\..*)?)$", name)
if not m:
print "Unknown package: `%s`" % name
sys.exit(1)
if os.path.isdir("%s/%s" % (PATH_PYTHONS, name)):
print "You are already installed `%s`." % name
sys.exit()
dist_version = m.group(1)
pkgs = PythonPackages()
if not pkgs.has_version(dist_version):
print "Package not found: `%s`" % name
sys.exit(1)
basename = "%s.tgz" % name
download_url = PYTHONDLSITE % (dist_version, basename)
download_path = "%s/%s" % (PATH_DISTS, basename)
if os.path.isfile(download_path):
print "Use the previously fetched %s" % (download_path)
else:
try:
dl = Downloader()
dl.download(
basename,
download_url,
download_path
)
except:
unlink(download_path)
print "\nInterrupt to abort. `%s`" % (download_url)
sys.exit(1)
# iffy
if os.path.getsize(download_path) < 1000000:
print "Failed to download. (maybe not stable version of python) `%s`" % (download_url)
unlink(download_path)
sys.exit(1)
else:
if is_archive_file(name):
basename = os.path.basename(name)
print "Copy the archive file %s to %s/%s" % (name, PATH_DISTS, basename)
shutil.copy(name, "%s/%s" % (PATH_DISTS, basename))
else:
print "Invalid file. `%s`" % name
sys.exit(1)
return basename
def _get_uncompress_command(self, basename):
distpath = "%s/%s" % (PATH_DISTS, basename)
if os.path.isfile(distpath):
ext = splitext(basename)[1]
if ext == ".tar.gz" or ext == ".tgz":
return "tar zxf %s" % (distpath)
elif ext == ".tar.bz2":
return "tar jxf %s" % (distpath)
elif ext == ".tar":
return "tar xf %s" % (distpath)
elif ext == ".zip":
return "unzip %s" % (distpath)
elif os.path.isdir(distpath):
return "mv %s %s/%s" % (distpath, PATH_BUILD, basename)
else:
print "File not found. `%s`" % (basename)
return ""
def _install_python(self, dist, options):
basename = self._get_package(dist)
pkgname = splitext(basename)[0]
install_dir = "%s/%s" % (PATH_PYTHONS, pkgname)
configure = "--prefix=%s %s" % (install_dir, options.configure)
print "Installing %s into %s" % (pkgname, install_dir);
print """This could take a while. You can run the following command on another shell to track the status:
tail -f %s
""" % (self._logfile)
try:
s = Subprocess(log=self._logfile, shell=True, cwd=PATH_BUILD)
s.check_call(self._get_uncompress_command(basename))
s.chdir("%s/%s" % (PATH_BUILD, pkgname))
s.check_call("./configure %s" % (configure))
if options.force:
s.check_call("make")
s.check_call("make install")
else:
s.check_call("make")
s.check_call("make test")
s.check_call("make install")
except:
print """Installing %(pkgname)s failed. See %(ROOT)s/build.log to see why.
pythonbrew install --force %(pkgname)s""" % {"pkgname":pkgname, "ROOT":ROOT}
sys.exit(1)
# install setuptools
self._install_setuptools(pkgname, options.no_setuptools)
print """
Installed %(pkgname)s successfully. Run the following command to switch to it.
pythonbrew switch %(pkgname)s""" % {"pkgname":pkgname}
def _install_setuptools(self, pkgname, no_setuptools):
if no_setuptools:
print "Skip installation setuptools."
return
if re.match("^Python-3.*", pkgname):
is_python3 = True
else:
is_python3 = False
download_url = DISTRIBUTE_SETUP_DLSITE
basename = os.path.basename(download_url)
dl = Downloader()
dl.download(basename, download_url, "%s/%s" % (PATH_DISTS, basename))
if is_python3:
if os.path.isfile("%s/%s/bin/python3" % (PATH_PYTHONS, pkgname)):
pyexec = "%s/%s/bin/python3" % (PATH_PYTHONS, pkgname)
elif os.path.isfile("%s/%s/bin/python3.0" % (PATH_PYTHONS, pkgname)):
pyexec = "%s/%s/bin/python3.0" % (PATH_PYTHONS, pkgname)
else:
print "Python3 binary not found. `%s/%s`" % (PATH_PYTHONS, pkgname)
return
else:
pyexec = "%s/%s/bin/python" % (PATH_PYTHONS, pkgname)
try:
s = Subprocess(log=self._logfile, shell=True, cwd=PATH_DISTS)
s.check_call("%s %s" % (pyexec, basename))
if os.path.isfile("%s/%s/bin/easy_install" % (PATH_PYTHONS, pkgname)) and not is_python3:
s.check_call("%s/%s/bin/easy_install pip" % (PATH_PYTHONS, pkgname), cwd=None)
except:
print "Installing setuptools failed. See %s/build.log to see why." % (ROOT)
sys.exit(1)
class InstalledCommand(Command):
name = "installed"
usage = "%prog"
summary = "List the installed versions of python"
def run_command(self, options, args):
if not os.path.islink("%s/current" % PATH_PYTHONS):
cur = os.path.realpath("%s/bin/python" % ROOT)
print "%s (*)" % cur
elif os.path.islink("%s/current" % PATH_PYTHONS):
cur = os.path.basename(os.path.realpath("%s/current" % PATH_PYTHONS))
else:
cur = ""
for d in sorted(os.listdir("%s/" % PATH_PYTHONS)):
if d == "current":
continue
if cur == d:
print "%s (*)" % cur
else:
print "%s" % (d)
class SwitchCommand(Command):
name = "switch"
usage = "%prog PACKAGE"
summary = "Switch to the given version"
def run_command(self, options, args):
if args:
dist = args[0]
distdir = dist
if os.path.isfile( dist ) and os.access( dist, os.X_OK ):
if re.search( ".*python(\d(\.\d)?)?$", dist ):
self._switch_file(dist)
else:
print "`%s` is not python binary." % dist
return
elif not os.path.isdir( "%s/%s" % (PATH_PYTHONS, dist) ):
print "`%s` is not installed." % dist
return
self._switch_dir( distdir )
def _switch_file(self, dist):
off()
symlink(dist, "%s/python" % PATH_BIN)
print "Switched to "+dist
def _switch_dir(self, dist):
off()
symlink(dist, "%s/current" % PATH_PYTHONS)
for root, dirs, files in os.walk("%s/current/bin/" % PATH_PYTHONS):
for f in files:
symlink("%s%s" % (root, f), "%s/%s" % (PATH_BIN, f))
break
# I want better code
if not os.path.isfile("%s/python" % PATH_BIN):
if os.path.isfile("%s/python3" % PATH_BIN):
symlink(os.path.realpath("%s/python3" % PATH_BIN), "%s/python" % PATH_BIN)
elif os.path.isfile("%s/python3.0" % PATH_BIN):
symlink(os.path.realpath("%s/python3.0" % PATH_BIN), "%s/python" % PATH_BIN)
print "Switched to "+dist
class OffCommand(Command):
name = "off"
usage = "%prog"
summary = "Disable pythonbrew"
def run_command(self, options, args):
off()
class VersionCommand(Command):
name = "version"
usage = "%prog"
summary = "Show version"
def run_command(self, options, args):
print VERSION
class SearchCommand(Command):
name = "search"
usage = "%prog Python-<VERSION>"
summary = "Search Python packages"
def run_command(self, options, args):
pkgs = PythonPackages()
if args:
pattern = args[0]
_re = re.compile(r"%s" % pattern)
pkgnames = []
for pkgname in pkgs.get_packages():
if _re.match(pkgname):
pkgnames.append(pkgname)
if pkgnames:
for pkgname in pkgnames:
print pkgname
else:
print "Package not found. `%s`" % pattern
else:
for pkgname in pkgs.get_packages():
print pkgname
class UninstallCommand(Command):
name = "uninstall"
usage = "%prog Python-<VERSION>"
summary = "Uninstall the given version of python"
def run_command(self, options, args):
if args:
pkgname = args[0]
pkgpath = "%s/%s" % (PATH_PYTHONS, pkgname)
if not os.path.isdir(pkgpath):
print "%s is not installed." % pkgname
sys.exit(1)
if os.path.islink("%s/current" % PATH_PYTHONS):
curpath = os.path.realpath("%s/current" % PATH_PYTHONS)
if pkgpath == curpath:
off()
rm_r(pkgpath)
else:
self.parser.print_help()
class CleanCommand(Command):
name = "clean"
usage = "%prog"
summary = "Remove stale source folders and archives"
def run_command(self, options, args):
self._clean(PATH_BUILD)
self._clean(PATH_DISTS)
def _clean(self, root):
for dir in os.listdir(root):
rm_r("%s/%s" % (root, dir))
class UpdateCommand(Command):
name = "update"
usage = "%prog"
summary = "Upgrades pythonbrew to the latest version"
def run_command(self, options, args):
download_url = PYTHONBREW_DLSITE
basename = os.path.basename(download_url)
download_path = "%s/%s" % (PATH_DISTS, basename)
try:
d = Downloader()
d.download(basename, download_url, download_path)
except:
print "Failed to download. `%s`" % download_url
sys.exit(1)
(retval, dist) = copy_myself(download_path)
if not retval:
print "You are already running the installed latest version of pythonbrew."
print "\n%s" % dist
sys.exit()
print "The pythonbrew has been updated."
class Pythonbrew(object):
def run(self):
options, args = parser.parse_args(sys.argv[1:])
if options.help and not args:
args = ["help"]
if not args:
parser.error('You must give a command (use "pythonbrew help" to see a list of commands)')
return
add_command(HelpCommand())
add_command(InitCommand())
add_command(InstallCommand())
add_command(InstalledCommand())
add_command(SwitchCommand())
add_command(OffCommand())
add_command(VersionCommand())
add_command(SearchCommand())
add_command(UninstallCommand())
add_command(CleanCommand())
add_command(UpdateCommand())
command = args[0].lower()
if command not in command_dict:
parser.error("Unknown command: `%s`" % command)
return
command = command_dict[command]
command.run(args)
def main():
p = Pythonbrew()
p.run()
if __name__ == "__main__":
main()
+27
View File
@@ -0,0 +1,27 @@
import sys
import os
from pythonbrew.basecommand import command_dict, load_all_commands
from pythonbrew.baseparser import parser
from pythonbrew.log import logger
from pythonbrew.define import PATH_HOME_ETC
from pythonbrew.util import makedirs
def init_home():
if not os.path.isdir(PATH_HOME_ETC):
makedirs(PATH_HOME_ETC)
def main():
options, args = parser.parse_args(sys.argv[1:])
if options.help and not args:
args = ['help']
if not args:
args = ['help'] # as default
init_home()
load_all_commands()
command = args[0].lower()
if command not in command_dict:
parser.error("Unknown command: `%s`" % command)
return
command = command_dict[command]
command.run(args[1:])
+37
View File
@@ -0,0 +1,37 @@
import os
import sys
import re
from optparse import OptionParser
from pythonbrew import commands
command_dict = {}
class Command(object):
name = None
usage = None
summary = ""
def __init__(self):
self.parser = OptionParser(usage=self.usage,
prog='%s %s' % ("pythonbrew", self.name))
command_dict[self.name] = self
def run(self, args):
options, args = self.parser.parse_args(args)
self.run_command(options, args)
def load_command(name):
full_name = 'pythonbrew.commands.%s' % name
if full_name in sys.modules:
return
try:
__import__(full_name)
except ImportError:
pass
def load_all_commands():
for name in command_names():
load_command(name)
def command_names():
return [path[:-3] for path in os.listdir(commands.__path__[0]) if not re.match("(__init__\.py$|.*\.pyc$)", path)]
+13
View File
@@ -0,0 +1,13 @@
from optparse import OptionParser
from pythonbrew.define import VERSION
parser = OptionParser(usage="%prog COMMAND [OPTIONS]",
prog="pythonbrew",
version=VERSION,
add_help_option=False)
parser.add_option(
'-h', '--help',
dest='help',
action='store_true',
help='Show help')
parser.disable_interspersed_args()
View File
+58
View File
@@ -0,0 +1,58 @@
import os
import sys
import subprocess
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS, BOOTSTRAP_DLSITE
from pythonbrew.util import Package, get_using_python_pkgname, Link, is_installed
from pythonbrew.log import logger
from pythonbrew.downloader import Downloader
class BuildoutCommand(Command):
name = "buildout"
usage = "%prog"
summary = "Runs the buildout with specified or current using python"
def __init__(self):
super(BuildoutCommand, self).__init__()
self.parser.add_option(
"-p", "--python",
dest="python",
default=None,
help="Use the specified version of python.",
metavar='VERSION'
)
def run_command(self, options, args):
if options.python:
pkgname = Package(options.python).name
else:
pkgname = get_using_python_pkgname()
if not is_installed(pkgname):
logger.error('`%s` is not installed.' % pkgname)
sys.exit(1)
logger.info('Using %s' % pkgname)
# build a path
python = os.path.join(PATH_PYTHONS, pkgname, 'bin', 'python')
# Download bootstrap.py
download_url = BOOTSTRAP_DLSITE
filename = Link(download_url).filename
bootstrap = os.path.join(os.getcwd(), filename) # fetching into current directory
try:
d = Downloader()
d.download(filename, download_url, bootstrap)
except:
e = sys.exc_info()[1]
logger.error("%s" % (e))
sys.exit(1)
# call bootstrap.py
if subprocess.call([python, bootstrap, '-d']):
logger.error('Failed to bootstrap.')
sys.exit(1)
# call buildout
subprocess.call(['./bin/buildout'])
BuildoutCommand()
+19
View File
@@ -0,0 +1,19 @@
import os
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_BUILD, PATH_DISTS
from pythonbrew.util import rm_r
class CleanupCommand(Command):
name = "cleanup"
usage = "%prog"
summary = "Remove stale source folders and archives"
def run_command(self, options, args):
self._cleanup(PATH_BUILD)
self._cleanup(PATH_DISTS)
def _cleanup(self, root):
for dir in os.listdir(root):
rm_r(os.path.join(root, dir))
CleanupCommand()
+27
View File
@@ -0,0 +1,27 @@
from pythonbrew.basecommand import Command, command_dict
from pythonbrew.baseparser import parser
from pythonbrew.log import logger
class HelpCommand(Command):
name = "help"
usage = "%prog [COMMAND]"
summary = "Show available commands"
def run_command(self, options, args):
if args:
command = args[0]
if command not in command_dict:
parser.error("Unknown command: `%s`" % command)
return
command = command_dict[command]
command.parser.print_help()
return
parser.print_help()
logger.log("\nCommands available:")
commands = [command_dict[key] for key in sorted(command_dict.keys())]
for command in commands:
logger.log(" %s: %s" % (command.name, command.summary))
logger.log("\nFurther Instructions:")
logger.log(" https://github.com/utahta/pythonbrew")
HelpCommand()
+99
View File
@@ -0,0 +1,99 @@
import sys
from pythonbrew.basecommand import Command
from pythonbrew.installer.pythoninstaller import PythonInstaller,\
PythonInstallerMacOSX
from pythonbrew.util import is_macosx
class InstallCommand(Command):
name = "install"
usage = "%prog [OPTIONS] VERSION"
summary = "Build and install the given version of python"
def __init__(self):
super(InstallCommand, self).__init__()
self.parser.add_option(
"-f", "--force",
dest="force",
action="store_true",
default=False,
help="Force installation of python."
)
self.parser.add_option(
"-n", "--no-test",
dest="no_test",
action="store_true",
default=False,
help="Skip `make test`."
)
self.parser.add_option(
"-v", "--verbose",
dest="verbose",
action="store_true",
default=False,
help="Display log information on the console."
)
self.parser.add_option(
"-C", "--configure",
dest="configure",
default="",
metavar="CONFIGURE_OPTIONS",
help="Options passed directly to configure."
)
self.parser.add_option(
"--no-setuptools",
dest="no_setuptools",
action="store_true",
default=False,
help="Skip installation of setuptools."
)
self.parser.add_option(
"--as",
dest="alias",
default=None,
help="Install a python under an alias."
)
self.parser.add_option(
'-j', "--jobs",
dest="jobs",
type='int',
default=0,
help="Enable parallel make."
)
self.parser.add_option(
"--framework",
dest="framework",
action="store_true",
default=False,
help="Build (MacOSX|Darwin) framework."
)
self.parser.add_option(
"--universal",
dest="universal",
action="store_true",
default=False,
help="Build for both 32 & 64 bit Intel."
)
self.parser.add_option(
"--static",
dest="static",
action="store_true",
default=False,
help="Build static libraries."
)
def run_command(self, options, args):
if not args:
self.parser.print_help()
sys.exit(1)
# installing python
for arg in args:
try:
if is_macosx():
p = PythonInstallerMacOSX(arg, options)
else:
p = PythonInstaller(arg, options)
p.install()
except:
continue
InstallCommand()
+68
View File
@@ -0,0 +1,68 @@
import os
import re
from pythonbrew.basecommand import Command
from pythonbrew.define import PYTHON_VERSION_URL, LATEST_VERSIONS_OF_PYTHON,\
PATH_PYTHONS
from pythonbrew.util import Package, get_using_python_pkgname
from pythonbrew.log import logger
class ListCommand(Command):
name = "list"
usage = "%prog [VERSION]"
summary = "List the installed all pythons"
def __init__(self):
super(ListCommand, self).__init__()
self.parser.add_option(
'-a', '--all-versions',
dest='all_versions',
action='store_true',
default=False,
help='Show the all python versions.'
)
self.parser.add_option(
'-k', '--known',
dest='known',
action='store_true',
default=False,
help='List the available latest python versions.'
)
def run_command(self, options, args):
if options.known:
self.available_install(options, args)
else:
self.installed(options, args)
def installed(self, options, args):
logger.log("# pythonbrew pythons")
cur = get_using_python_pkgname()
for d in sorted(os.listdir(PATH_PYTHONS)):
if cur and cur == d:
logger.log(' %s (*)' % d)
else:
logger.log(' %s' % d)
def available_install(self, options, args):
logger.log('# Pythons')
if args:
pkg = Package(args[0])
_re = re.compile(r"%s" % pkg.name)
pkgs = []
for pkgname in self._get_packages_name(options):
if _re.match(pkgname):
pkgs.append(pkgname)
if pkgs:
for pkgname in pkgs:
logger.log("%s" % pkgname)
else:
logger.error("`%s` was not found." % pkg.name)
else:
for pkgname in self._get_packages_name(options):
logger.log("%s" % pkgname)
def _get_packages_name(self, options):
return ["Python-%s" % version for version in sorted(PYTHON_VERSION_URL.keys())
if(options.all_versions or (not options.all_versions and version in LATEST_VERSIONS_OF_PYTHON))]
ListCommand()
+12
View File
@@ -0,0 +1,12 @@
from pythonbrew.basecommand import Command
from pythonbrew.util import off
class OffCommand(Command):
name = "off"
usage = "%prog"
summary = "Disable pythonbrew"
def run_command(self, options, args):
off()
OffCommand()
+56
View File
@@ -0,0 +1,56 @@
import os
import sys
import subprocess
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS
from pythonbrew.util import Package
from pythonbrew.log import logger
class PyCommand(Command):
name = "py"
usage = "%prog PYTHON_FILE"
summary = "Runs a named python file against specified and/or all pythons"
def __init__(self):
super(PyCommand, self).__init__()
self.parser.add_option(
"-p", "--python",
dest="pythons",
action="append",
default=[],
help="Use the specified python version.",
metavar='VERSION'
)
self.parser.add_option(
"-v", "--verbose",
dest="verbose",
action="store_true",
default=False,
help="Show the running python version."
)
self.parser.disable_interspersed_args()
def run_command(self, options, args):
if not args:
self.parser.print_help()
sys.exit(1)
pythons = self._get_pythons(options.pythons)
for d in pythons:
if options.verbose:
logger.info('`%s` running...' % d)
path = os.path.join(PATH_PYTHONS, d, 'bin', args[0])
if os.path.isfile(path) and os.access(path, os.X_OK):
subprocess.call([path] + args[1:])
else:
path = os.path.join(PATH_PYTHONS, d, 'bin', 'python')
if os.path.isfile(path) and os.access(path, os.X_OK):
subprocess.call([path] + args)
else:
logger.error('%s: No such file or directory.' % path)
def _get_pythons(self, _pythons):
pythons = [Package(p).name for p in _pythons]
return [d for d in sorted(os.listdir(PATH_PYTHONS))
if not pythons or d in pythons]
PyCommand()
+28
View File
@@ -0,0 +1,28 @@
import os
import sys
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS
from pythonbrew.util import Package, set_current_path, is_installed
from pythonbrew.log import logger
class SwitchCommand(Command):
name = "switch"
usage = "%prog VERSION"
summary = "Permanently use the specified python as default"
def run_command(self, options, args):
if not args:
self.parser.print_help()
sys.exit(1)
pkg = Package(args[0])
pkgname = pkg.name
if not is_installed(pkgname):
logger.error("`%s` is not installed." % pkgname)
sys.exit(1)
pkgbin = os.path.join(PATH_PYTHONS,pkgname,'bin')
set_current_path(pkgbin)
logger.info("Switched to %s" % pkgname)
SwitchCommand()
+117
View File
@@ -0,0 +1,117 @@
import os
import sys
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS, PATH_BIN, PATH_VENVS
from pythonbrew.util import Package, symlink, unlink, get_using_python_pkgname,\
is_installed
from pythonbrew.log import logger
class SymlinkCommand(Command):
name = "symlink"
usage = "%prog [OPTIONS] [SCRIPT]"
summary = "Create/Remove a symbolic link on your $PATH"
def __init__(self):
super(SymlinkCommand, self).__init__()
self.parser.add_option(
"-p", "--python",
dest="pythons",
action="append",
default=[],
help="Use the specified python version.",
metavar='VERSION'
)
self.parser.add_option(
"-r", "--remove",
dest="remove",
action="store_true",
default=False,
help="Remove the all symbolic link."
)
self.parser.add_option(
"-d", "--default",
dest="default",
default=None,
help="Use as default the specified python version."
)
self.parser.add_option(
"-v", "--venv",
dest="venv",
default=None,
help="Use the virtual environment python."
)
def run_command(self, options, args):
if options.default:
# create only one instance as default of an application.
pythons = self._get_pythons([options.default])
for pkgname in pythons:
if args:
bin = args[0]
self._symlink(bin, bin, pkgname)
else:
self._symlink('python', 'py', pkgname)
elif options.venv:
if options.pythons:
pkgname = Package(options.pythons[0]).name
else:
pkgname = get_using_python_pkgname()
if not is_installed(pkgname):
logger.error('`%s` is not installed.')
sys.exit(1)
venv_pkgdir = os.path.join(PATH_VENVS, pkgname)
venv_dir = os.path.join(venv_pkgdir, options.venv)
if not os.path.isdir(venv_dir):
logger.error("`%s` environment was not found in %s." % (options.venv, venv_pkgdir))
sys.exit(1)
pkg = Package(pkgname)
if args:
bin = args[0]
dstbin = '%s%s-%s' % (bin, pkg.version, options.venv)
self._symlink(bin, dstbin, pkgname)
else:
dstbin = 'py%s-%s' % (pkg.version, options.venv)
self._symlink('python', dstbin, pkgname)
else:
pythons = self._get_pythons(options.pythons)
for pkgname in pythons:
if options.remove:
# remove symlinks
for bin in os.listdir(PATH_BIN):
path = os.path.join(PATH_BIN, bin)
if os.path.islink(path):
unlink(path)
else:
# create symlinks
if args:
bin = args[0]
self._symlink_version_suffix(bin, bin, pkgname)
else:
self._symlink_version_suffix('python', 'py', pkgname)
def _symlink_version_suffix(self, srcbin, dstbin, pkgname):
"""Create a symlink. add version suffix.
"""
version = Package(pkgname).version
dstbin = '%s%s' % (dstbin, version)
self._symlink(srcbin, dstbin, pkgname)
def _symlink(self, srcbin, dstbin, pkgname):
"""Create a symlink.
"""
src = os.path.join(PATH_PYTHONS, pkgname, 'bin', srcbin)
dst = os.path.join(PATH_BIN, dstbin)
if os.path.isfile(src):
symlink(src, dst)
else:
logger.error("%s was not found in your path." % src)
def _get_pythons(self, _pythons):
"""Get the installed python versions list.
"""
pythons = [Package(p).name for p in _pythons]
return [d for d in sorted(os.listdir(PATH_PYTHONS))
if not pythons or d in pythons]
SymlinkCommand()
+39
View File
@@ -0,0 +1,39 @@
import os
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS, PATH_BIN, PATH_VENVS
from pythonbrew.util import off, rm_r, Package, get_using_python_pkgname, unlink,\
is_installed
from pythonbrew.log import logger
class UninstallCommand(Command):
name = "uninstall"
usage = "%prog VERSION"
summary = "Uninstall the given version of python"
def run_command(self, options, args):
if args:
# Uninstall pythons
for arg in args:
pkg = Package(arg)
pkgname = pkg.name
pkgpath = os.path.join(PATH_PYTHONS, pkgname)
venvpath = os.path.join(PATH_VENVS, pkgname)
if not is_installed(pkgname):
logger.error("`%s` is not installed." % pkgname)
continue
if get_using_python_pkgname() == pkgname:
off()
for d in os.listdir(PATH_BIN):
# remove symlink
path = os.path.join(PATH_BIN, d)
if os.path.islink(path):
basename = os.path.basename(os.path.realpath(path))
tgtpath = os.path.join(pkgpath, 'bin', basename)
if os.path.isfile(tgtpath) and os.path.samefile(path, tgtpath):
unlink(path)
rm_r(pkgpath)
rm_r(venvpath)
else:
self.parser.print_help()
UninstallCommand()
+117
View File
@@ -0,0 +1,117 @@
import os
import sys
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_DISTS, VERSION, ROOT,\
PATH_BUILD, PYTHONBREW_UPDATE_URL_CONFIG, PATH_ETC_CONFIG
from pythonbrew.log import logger
from pythonbrew.downloader import Downloader, get_pythonbrew_update_url,\
get_stable_version, get_headerinfo_from_url
from pythonbrew.util import rm_r, extract_downloadfile, Link, is_gzip, Subprocess, Version
class UpdateCommand(Command):
name = "update"
usage = "%prog"
summary = "Update the pythonbrew to the latest version"
def __init__(self):
super(UpdateCommand, self).__init__()
self.parser.add_option(
'--master',
dest='master',
action='store_true',
default=False,
help='Update the pythonbrew to the `master` branch on github.'
)
self.parser.add_option(
'--develop',
dest='develop',
action='store_true',
default=False,
help='Update the pythonbrew to the `develop` branch on github.'
)
self.parser.add_option(
'--config',
dest='config',
action='store_true',
default=False,
help='Update config.cfg.'
)
self.parser.add_option(
'-f', '--force',
dest='force',
action='store_true',
default=False,
help='Force update the pythonbrew.'
)
def run_command(self, options, args):
if options.config:
self._update_config(options, args)
else:
self._update_pythonbrew(options, args)
def _update_config(self, options, args):
# config.cfg update
# TODO: Automatically create for config.cfg
download_url = PYTHONBREW_UPDATE_URL_CONFIG
if not download_url:
logger.error("Invalid download url in config.cfg. `%s`" % download_url)
sys.exit(1)
distname = Link(PYTHONBREW_UPDATE_URL_CONFIG).filename
download_file = PATH_ETC_CONFIG
try:
d = Downloader()
d.download(distname, download_url, download_file)
except:
logger.error("Failed to download. `%s`" % download_url)
sys.exit(1)
logger.log("The config.cfg has been updated.")
def _update_pythonbrew(self, options, args):
if options.master:
version = 'master'
elif options.develop:
version = 'develop'
else:
version = get_stable_version()
# check for version
if not options.force and Version(version) <= VERSION:
logger.info("You are already running the installed latest version of pythonbrew.")
return
download_url = get_pythonbrew_update_url(version)
if not download_url:
logger.error("`pythonbrew-%s` was not found in pypi." % version)
sys.exit(1)
headinfo = get_headerinfo_from_url(download_url)
content_type = headinfo['content-type']
if not options.master and not options.develop:
if not is_gzip(content_type, Link(download_url).filename):
logger.error("content type should be gzip. content-type:`%s`" % content_type)
sys.exit(1)
filename = "pythonbrew-%s" % version
distname = "%s.tgz" % filename
download_file = os.path.join(PATH_DISTS, distname)
try:
d = Downloader()
d.download(distname, download_url, download_file)
except:
logger.error("Failed to download. `%s`" % download_url)
sys.exit(1)
extract_dir = os.path.join(PATH_BUILD, filename)
rm_r(extract_dir)
if not extract_downloadfile(content_type, download_file, extract_dir):
sys.exit(1)
try:
logger.info("Installing %s into %s" % (extract_dir, ROOT))
s = Subprocess()
s.check_call([sys.executable, os.path.join(extract_dir,'pythonbrew_install.py'), '--upgrade'])
except:
logger.error("Failed to update pythonbrew.")
sys.exit(1)
logger.info("The pythonbrew has been updated.")
UpdateCommand()
+34
View File
@@ -0,0 +1,34 @@
import os
import sys
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS, PATH_HOME_ETC_TEMP
from pythonbrew.util import Package
from pythonbrew.log import logger
class UseCommand(Command):
name = "use"
usage = "%prog VERSION"
summary = "Use the specified python in current shell"
def run_command(self, options, args):
if not args:
self.parser.print_help()
sys.exit(1)
pkg = Package(args[0])
pkgname = pkg.name
pkgdir = os.path.join(PATH_PYTHONS, pkgname)
if not os.path.isdir(pkgdir):
logger.error("`%s` is not installed." % pkgname)
sys.exit(1)
pkgbin = os.path.join(pkgdir,'bin')
self._set_temp(pkgbin)
logger.info("Using `%s`" % pkgname)
def _set_temp(self, path):
fp = open(PATH_HOME_ETC_TEMP, 'w')
fp.write('PATH_PYTHONBREW_TEMP="%s"\n' % (path))
fp.close()
UseCommand()
+164
View File
@@ -0,0 +1,164 @@
import os
import sys
from pythonbrew.basecommand import Command
from pythonbrew.define import PATH_PYTHONS, PATH_VENVS, PATH_HOME_ETC_VENV,\
PATH_ETC, VIRTUALENV_DLSITE, PATH_DISTS
from pythonbrew.util import Package, \
is_installed, get_installed_pythons_pkgname, get_using_python_pkgname,\
untar_file, Subprocess, rm_r
from pythonbrew.log import logger
from pythonbrew.downloader import Downloader
class VenvCommand(Command):
name = "venv"
usage = "%prog [create|use|delete|list] [project]"
summary = "Create isolated python environments"
def __init__(self):
super(VenvCommand, self).__init__()
self.parser.add_option(
"-p", "--python",
dest="python",
default=None,
help="Use the specified version of python.",
metavar='VERSION'
)
self.parser.add_option(
"-a", "--all",
dest="all",
action='store_true',
default=False,
help="Show the all python environments.",
)
self.parser.add_option(
"-n", "--no-site-packages",
dest="no_site_packages",
action='store_true',
default=False,
help="Don't give access to the global site-packages dir to the virtual environment.",
)
self._venv_dir = os.path.join(PATH_ETC, 'virtualenv')
self._venv = os.path.join(self._venv_dir, 'virtualenv.py')
def run_command(self, options, args):
if not args:
self.parser.print_help()
sys.exit(1)
cmd = args[0]
if not cmd in ('init', 'create', 'delete', 'use', 'list'):
self.parser.print_help()
sys.exit(1)
# initialize?
if cmd == 'init':
self.run_command_init()
return
# target python interpreter
if options.python:
pkgname = Package(options.python).name
if not is_installed(pkgname):
logger.error('%s is not installed.' % pkgname)
sys.exit(1)
else:
# check using python under pythonbrew
pkgname = get_using_python_pkgname()
if not pkgname:
logger.error('Can not use venv command before switching a python. Try \'pythonbrew switch <version of python>\'.')
sys.exit(1)
self._pkgname = pkgname
self._target_py = os.path.join(PATH_PYTHONS, pkgname, 'bin', 'python')
self._workon_home = os.path.join(PATH_VENVS, pkgname)
self._py = os.path.join(PATH_PYTHONS, pkgname, 'bin', 'python')
# is already installed virtualenv?
if not os.path.exists(self._venv):
self.run_command_init()
# Create a shell script
self.__getattribute__('run_command_%s' % cmd)(options, args)
def run_command_init(self):
if os.path.exists(self._venv):
logger.info('venv command is already initialized.')
return
if not os.access(PATH_DISTS, os.W_OK):
logger.error("Can not initialize venv command: Permission denied.")
sys.exit(1)
d = Downloader()
download_file = os.path.join(PATH_DISTS, 'virtualenv.tar.gz')
d.download('virtualenv.tar.gz', VIRTUALENV_DLSITE, download_file)
logger.info('Extracting virtualenv into %s' % self._venv_dir)
untar_file(download_file, self._venv_dir)
def run_command_create(self, options, args):
if not os.access(PATH_VENVS, os.W_OK):
logger.error("Can not create a virtuale environment in %s.\nPermission denied." % PATH_VENVS)
sys.exit(1)
virtualenv_options = []
if options.no_site_packages:
virtualenv_options.append('--no-site-packages')
for arg in args[1:]:
target_dir = os.path.join(self._workon_home, arg)
logger.info("Creating `%s` environment into %s" % (arg, self._workon_home))
# make command
cmd = [self._py, self._venv, '-p', self._target_py]
cmd.extend(virtualenv_options)
cmd.append(target_dir)
# create environment
s = Subprocess(verbose=True)
s.call(cmd)
def run_command_delete(self, options, args):
for arg in args[1:]:
target_dir = os.path.join(self._workon_home, arg)
if not os.path.isdir(target_dir):
logger.error('%s already does not exist.' % target_dir)
else:
if not os.access(target_dir, os.W_OK):
logger.error("Can not delete %s.\nPermission denied." % target_dir)
continue
logger.info('Deleting `%s` environment in %s' % (arg, self._workon_home))
# make command
rm_r(target_dir)
def run_command_use(self, options, args):
if len(args) < 2:
logger.error("Unrecognized command line argument: ( 'pythonbrew venv use <project>' )")
sys.exit(1)
activate = os.path.join(self._workon_home, args[1], 'bin', 'activate')
if not os.path.exists(activate):
logger.error('`%s` environment already does not exist. Try `pythonbrew venv create %s`.' % (args[1], args[1]))
sys.exit(1)
self._write("""\
echo '# Using `%(arg)s` environment (found in %(workon_home)s)'
echo '# To leave an environment, simply run `deactivate`'
source '%(activate)s'
""" % {'arg': args[1], 'workon_home': self._workon_home, 'activate': activate})
def run_command_list(self, options, args):
if options.all:
for pkgname in get_installed_pythons_pkgname():
workon_home = os.path.join(PATH_VENVS, pkgname)
logger.log("# virtualenv for %(pkgname)s (found in %(workon_home)s)" % {'pkgname': pkgname, 'workon_home': workon_home})
if os.path.isdir(workon_home):
for d in sorted(os.listdir(workon_home)):
if os.path.isdir(os.path.join(workon_home, d)):
logger.log(d)
else:
logger.log("# virtualenv for %(pkgname)s (found in %(workon_home)s)" % {'pkgname': self._pkgname, 'workon_home': self._workon_home})
if os.path.isdir(self._workon_home):
for d in sorted(os.listdir(self._workon_home)):
if os.path.isdir(os.path.join(self._workon_home, d)):
logger.log(d)
def _write(self, src):
fp = open(PATH_HOME_ETC_VENV, 'w')
fp.write(src)
fp.close()
VenvCommand()
+13
View File
@@ -0,0 +1,13 @@
from pythonbrew.basecommand import Command
from pythonbrew.define import VERSION
from pythonbrew.log import logger
class VersionCommand(Command):
name = "version"
usage = "%prog"
summary = "Show version"
def run_command(self, options, args):
logger.log(VERSION)
VersionCommand()
+43
View File
@@ -0,0 +1,43 @@
import sys
import re
import subprocess
from subprocess import Popen, PIPE
from pythonbrew.log import logger
from pythonbrew.util import to_str
from pythonbrew.exceptions import CurlFetchException
class Curl(object):
def __init__(self):
returncode = subprocess.call("command -v curl > /dev/null", shell=True)
if returncode:
logger.log("pythonbrew required curl. curl was not found in your path.")
sys.exit(1)
def read(self, url):
p = Popen("curl -skL %s" % url, stdout=PIPE, shell=True)
p.wait()
if p.returncode:
raise Exception('Failed to read.')
return p.stdout.read()
def readheader(self, url):
p = Popen("curl --head -skL %s" % url, stdout=PIPE, shell=True)
p.wait()
if p.returncode:
raise Exception('Failed to readheader.')
respinfo = {}
for line in p.stdout:
line = to_str(line.strip())
if re.match('^HTTP.*? 200 OK$', line):
break
for line in p.stdout:
line = to_str(line.strip()).split(":", 1)
if len(line) == 2:
respinfo[line[0].strip().lower()] = line[1].strip()
return respinfo
def fetch(self, url, filename):
p = Popen("curl -# -kL %s -o %s" % (url, filename), shell=True)
p.wait()
if p.returncode:
raise CurlFetchException('Failed to fetch.')
+96
View File
@@ -0,0 +1,96 @@
import os
import re
try:
import ConfigParser
except:
import configparser as ConfigParser
# pythonbrew version
VERSION = "1.1"
# pythonbrew installer root path
INSTALLER_ROOT = os.path.dirname(os.path.abspath(__file__))
# Root
# pythonbrew root path
ROOT = os.environ.get("PYTHONBREW_ROOT")
if not ROOT:
ROOT = os.path.join(os.environ["HOME"],".pythonbrew")
# directories
PATH_PYTHONS = os.path.join(ROOT,"pythons")
PATH_BUILD = os.path.join(ROOT,"build")
PATH_DISTS = os.path.join(ROOT,"dists")
PATH_ETC = os.path.join(ROOT,"etc")
PATH_BIN = os.path.join(ROOT,"bin")
PATH_LOG = os.path.join(ROOT,"log")
PATH_VENVS = os.path.join(ROOT, "venvs")
PATH_SCRIPTS = os.path.join(ROOT,"scripts")
PATH_SCRIPTS_PYTHONBREW = os.path.join(PATH_SCRIPTS,"pythonbrew")
PATH_SCRIPTS_PYTHONBREW_COMMANDS = os.path.join(PATH_SCRIPTS_PYTHONBREW,"commands")
PATH_SCRIPTS_PYTHONBREW_INSTALLER = os.path.join(PATH_SCRIPTS_PYTHONBREW,"installer")
PATH_PATCHES = os.path.join(ROOT,"patches")
PATH_PATCHES_ALL = os.path.join(PATH_PATCHES,"all")
PATH_PATCHES_MACOSX = os.path.join(PATH_PATCHES,"macosx")
PATH_PATCHES_MACOSX_PYTHON27 = os.path.join(PATH_PATCHES_MACOSX,"python27")
PATH_PATCHES_MACOSX_PYTHON26 = os.path.join(PATH_PATCHES_MACOSX,"python26")
PATH_PATCHES_MACOSX_PYTHON25 = os.path.join(PATH_PATCHES_MACOSX,"python25")
PATH_PATCHES_MACOSX_PYTHON24 = os.path.join(PATH_PATCHES_MACOSX,"python24")
# files
PATH_BIN_PYTHONBREW = os.path.join(PATH_BIN,'pythonbrew')
PATH_ETC_CONFIG = os.path.join(PATH_ETC,'config.cfg')
# Home
# pythonbrew home path
PATH_HOME = os.environ.get('PYTHONBREW_HOME')
if not PATH_HOME:
PATH_HOME = os.path.join(os.environ["HOME"],".pythonbrew")
# directories
PATH_HOME_ETC = os.path.join(PATH_HOME, 'etc')
# files
PATH_HOME_ETC_VENV = os.path.join(PATH_HOME_ETC, 'venv.run')
PATH_HOME_ETC_CURRENT = os.path.join(PATH_HOME_ETC,'current')
PATH_HOME_ETC_TEMP = os.path.join(PATH_HOME_ETC,'temp')
# read config.cfg
config = ConfigParser.SafeConfigParser()
config.read([PATH_ETC_CONFIG, os.path.join(INSTALLER_ROOT,'etc','config.cfg')])
def _get_or_default(section, option, default=''):
try:
return config.get(section, option)
except:
return default
# setuptools download
DISTRIBUTE_SETUP_DLSITE = _get_or_default('distribute', 'url')
# buildout bootstrap download
BOOTSTRAP_DLSITE = _get_or_default('bootstrap', 'url')
# virtualenv download
VIRTUALENV_DLSITE = _get_or_default('virtualenv', 'url')
# pythonbrew download
PYTHONBREW_UPDATE_URL_MASTER = _get_or_default('pythonbrew', 'master')
PYTHONBREW_UPDATE_URL_DEVELOP = _get_or_default('pythonbrew', 'develop')
PYTHONBREW_UPDATE_URL_PYPI = _get_or_default('pythonbrew', 'pypi')
PYTHONBREW_UPDATE_URL_CONFIG = _get_or_default('pythonbrew', 'config')
# stable version text
PYTHONBREW_STABLE_VERSION_URL = _get_or_default('pythonbrew', 'stable-version')
# python download
LATEST_VERSIONS_OF_PYTHON = []
PYTHON_VERSION_URL = {}
PYTHON_VERSION_URL["1.5.2"] = _get_or_default('Python-1.5.2', 'url')
PYTHON_VERSION_URL["1.6.1"] = _get_or_default('Python-1.6.1', 'url')
for section in sorted(config.sections()):
m = re.search("^Python-(.*)$", section)
if m:
version = m.group(1)
PYTHON_VERSION_URL[version] = config.get(section, 'url')
if config.has_option(section, 'latest') and config.getboolean(section, 'latest'):
LATEST_VERSIONS_OF_PYTHON.append(version)
+31
View File
@@ -0,0 +1,31 @@
from pythonbrew.define import PYTHON_VERSION_URL, PYTHONBREW_STABLE_VERSION_URL, \
PYTHONBREW_UPDATE_URL_PYPI, PYTHONBREW_UPDATE_URL_MASTER,\
PYTHONBREW_UPDATE_URL_DEVELOP
from pythonbrew.log import logger
from pythonbrew.curl import Curl
from pythonbrew.util import to_str
def get_headerinfo_from_url(url):
c = Curl()
return c.readheader(url)
def get_stable_version():
c = Curl()
return to_str(c.read(PYTHONBREW_STABLE_VERSION_URL).strip())
class Downloader(object):
def download(self, msg, url, path):
logger.info("Downloading %s as %s" % (msg, path))
c = Curl()
c.fetch(url, path)
def get_pythonbrew_update_url(version):
if version == "master":
return PYTHONBREW_UPDATE_URL_MASTER
elif version == 'develop':
return PYTHONBREW_UPDATE_URL_DEVELOP
else:
return PYTHONBREW_UPDATE_URL_PYPI % (version)
def get_python_version_url(version):
return PYTHON_VERSION_URL.get(version)
+138
View File
@@ -0,0 +1,138 @@
# settings
PATH_ROOT="$PYTHONBREW_ROOT"
if [ -z "${PATH_ROOT}" ] ; then
PATH_ROOT="$HOME/.pythonbrew"
fi
PATH_ETC="$PATH_ROOT/etc"
PATH_HOME="$PYTHONBREW_HOME"
if [ -z "${PATH_HOME}" ] ; then
PATH_HOME="$HOME/.pythonbrew"
fi
PATH_HOME_ETC="$PATH_HOME/etc"
# py file
PY_PYTHONBREW="$PATH_ROOT/bin/pythonbrew"
# functions
__pythonbrew_set_default()
{
PATH_PYTHONBREW="$PATH_ROOT/bin"
}
__pythonbrew_set_path()
{
PATH_WITHOUT_PYTHONBREW=$(printf $PATH | awk -v RS=: -v ORS=: "/${PATH_ROOT//\//\/}/ {next} {print}" | sed -e 's#:$##')
export PATH=$PATH_PYTHONBREW:$PATH_WITHOUT_PYTHONBREW
}
__pythonbrew_set_temp_path()
{
if [[ -s "$PATH_HOME_ETC/temp" ]] ; then
source "$PATH_HOME_ETC/temp"
PATH_PYTHONBREW="$PATH_ROOT/bin:$PATH_PYTHONBREW_TEMP"
else
__pythonbrew_set_default
fi
__pythonbrew_set_path
}
__pythonbrew_set_current_path()
{
if [[ -s "$PATH_HOME_ETC/current" ]] ; then
source "$PATH_HOME_ETC/current"
PATH_PYTHONBREW="$PATH_ROOT/bin:$PATH_PYTHONBREW_CURRENT"
else
__pythonbrew_set_default
fi
__pythonbrew_set_path
}
__pythonbrew_reload()
{
[[ -s "$PATH_ETC/bashrc" ]] && source "$PATH_ETC/bashrc"
}
__pythonbrew_use()
{
$pythonbrew "$@"
[[ $? == 0 ]] && __pythonbrew_set_temp_path
}
__pythonbrew_switch()
{
$pythonbrew "$@"
[[ $? == 0 ]] && __pythonbrew_set_current_path
}
__pythonbrew_off()
{
$pythonbrew "$@"
[[ $? == 0 ]] && __pythonbrew_set_current_path
}
__pythonbrew_update()
{
$pythonbrew "$@"
[[ $? == 0 ]] && __pythonbrew_reload
}
__pythonbrew_venv()
{
$pythonbrew "$@"
if [[ $? == 0 ]] ; then
if [[ -s "$PATH_HOME_ETC/venv.run" ]] ; then
source "$PATH_HOME_ETC/venv.run"
cat /dev/null > "$PATH_HOME_ETC/venv.run"
fi
fi
}
__pythonbrew_find_command()
{
command_name=""
for arg in "$@" ; do
case $arg in
--*) continue;;
-*) continue;;
*)
command_name=$arg
break
;;
esac
done
}
__pythonbrew_run()
{
__pythonbrew_find_command "$@"
case $command_name in
use) __pythonbrew_use "$@";;
switch) __pythonbrew_switch "$@" ;;
off) __pythonbrew_off "$@" ;;
update) __pythonbrew_update "$@" ;;
venv) __pythonbrew_venv "$@" ;;
*) $pythonbrew "$@" ;;
esac
builtin hash -r
}
pythonbrew()
{
pythonbrew=$PY_PYTHONBREW
__pythonbrew_run "$@"
}
pybrew()
{
pythonbrew "$@"
}
sudopybrew()
{
pythonbrew="sudo PYTHONBREW_ROOT=$PATH_ROOT PATH=$PATH_PYTHONBREW:$PATH_WITHOUT_PYTHONBREW $PY_PYTHONBREW"
__pythonbrew_run "$@"
}
# main
__pythonbrew_set_current_path
+187
View File
@@ -0,0 +1,187 @@
[distribute]
url = http://python-distribute.org/distribute_setup.py
[bootstrap]
url = http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py
[virtualenv]
url = http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.6.4.tar.gz
[pythonbrew]
master = https://github.com/utahta/pythonbrew/tarball/master
develop = https://github.com/utahta/pythonbrew/tarball/develop
pypi = http://pypi.python.org/packages/source/p/pythonbrew/pythonbrew-%%s.tar.gz
stable-version = https://github.com/utahta/pythonbrew/raw/master/stable-version.txt
config = https://github.com/utahta/pythonbrew/raw/master/pythonbrew/etc/config.cfg
[Python-1.5.2]
url = http://www.python.org/ftp/python/src/py152.tgz
latest = True
[Python-1.6.1]
url = http://www.python.org/download/releases/1.6.1/Python-1.6.1.tar.gz
latest = True
[Python-2.0]
url = http://www.python.org/ftp/python/2.0/Python-2.0.tgz
[Python-2.0.1]
url = http://www.python.org/ftp/python/2.0.1/Python-2.0.1.tgz
latest = True
[Python-2.1]
url = http://www.python.org/ftp/python/2.1/Python-2.1.tgz
[Python-2.1.1]
url = http://www.python.org/ftp/python/2.1.1/Python-2.1.1.tgz
[Python-2.1.2]
url = http://www.python.org/ftp/python/2.1.2/Python-2.1.2.tgz
[Python-2.1.3]
url = http://www.python.org/ftp/python/2.1.3/Python-2.1.3.tgz
latest = True
[Python-2.2]
url = http://www.python.org/ftp/python/2.2/Python-2.2.tgz
[Python-2.2.1]
url = http://www.python.org/ftp/python/2.2.1/Python-2.2.1.tgz
[Python-2.2.2]
url = http://www.python.org/ftp/python/2.2.2/Python-2.2.2.tgz
[Python-2.2.3]
url = http://www.python.org/ftp/python/2.2.3/Python-2.2.3.tgz
latest = True
[Python-2.3]
url = http://www.python.org/ftp/python/2.3/Python-2.3.tgz
[Python-2.3.1]
url = http://www.python.org/ftp/python/2.3.1/Python-2.3.1.tgz
[Python-2.3.2]
url = http://www.python.org/ftp/python/2.3.2/Python-2.3.2.tgz
[Python-2.3.4]
url = http://www.python.org/ftp/python/2.3.4/Python-2.3.4.tgz
[Python-2.3.5]
url = http://www.python.org/ftp/python/2.3.5/Python-2.3.5.tgz
[Python-2.3.6]
url = http://www.python.org/ftp/python/2.3.6/Python-2.3.6.tgz
[Python-2.3.7]
url = http://www.python.org/ftp/python/2.3.7/Python-2.3.7.tgz
latest = True
[Python-2.4]
url = http://www.python.org/ftp/python/2.4/Python-2.4.tgz
[Python-2.4.1]
url = http://www.python.org/ftp/python/2.4.1/Python-2.4.1.tgz
[Python-2.4.2]
url = http://www.python.org/ftp/python/2.4.2/Python-2.4.2.tgz
[Python-2.4.3]
url = http://www.python.org/ftp/python/2.4.3/Python-2.4.3.tgz
[Python-2.4.4]
url = http://www.python.org/ftp/python/2.4.4/Python-2.4.4.tgz
[Python-2.4.5]
url = http://www.python.org/ftp/python/2.4.5/Python-2.4.5.tgz
[Python-2.4.6]
url = http://www.python.org/ftp/python/2.4.6/Python-2.4.6.tgz
latest = True
[Python-2.5]
url = http://www.python.org/ftp/python/2.5/Python-2.5.tgz
[Python-2.5.1]
url = http://www.python.org/ftp/python/2.5.1/Python-2.5.1.tgz
[Python-2.5.2]
url = http://www.python.org/ftp/python/2.5.2/Python-2.5.2.tgz
[Python-2.5.3]
url = http://www.python.org/ftp/python/2.5.3/Python-2.5.3.tgz
[Python-2.5.4]
url = http://www.python.org/ftp/python/2.5.4/Python-2.5.4.tgz
[Python-2.5.5]
url = http://www.python.org/ftp/python/2.5.5/Python-2.5.5.tgz
[Python-2.5.6]
url = http://www.python.org/ftp/python/2.5.6/Python-2.5.6.tgz
latest = True
[Python-2.6]
url = http://www.python.org/ftp/python/2.6/Python-2.6.tgz
[Python-2.6.1]
url = http://www.python.org/ftp/python/2.6.1/Python-2.6.1.tgz
[Python-2.6.2]
url = http://www.python.org/ftp/python/2.6.2/Python-2.6.2.tgz
[Python-2.6.3]
url = http://www.python.org/ftp/python/2.6.3/Python-2.6.3.tgz
[Python-2.6.4]
url = http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tgz
[Python-2.6.5]
url = http://www.python.org/ftp/python/2.6.5/Python-2.6.5.tgz
[Python-2.6.6]
url = http://www.python.org/ftp/python/2.6.6/Python-2.6.6.tgz
[Python-2.6.7]
url = http://www.python.org/ftp/python/2.6.7/Python-2.6.7.tgz
latest = True
[Python-2.7]
url = http://www.python.org/ftp/python/2.7/Python-2.7.tgz
[Python-2.7.1]
url = http://www.python.org/ftp/python/2.7.1/Python-2.7.1.tgz
[Python-2.7.2]
url = http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tgz
latest = True
[Python-3.0]
url = http://www.python.org/ftp/python/3.0/Python-3.0.tgz
[Python-3.0.1]
url = http://www.python.org/ftp/python/3.0.1/Python-3.0.1.tgz
latest = True
[Python-3.1]
url = http://www.python.org/ftp/python/3.1/Python-3.1.tgz
[Python-3.1.1]
url = http://www.python.org/ftp/python/3.1.1/Python-3.1.1.tgz
[Python-3.1.2]
url = http://www.python.org/ftp/python/3.1.2/Python-3.1.2.tgz
[Python-3.1.3]
url = http://www.python.org/ftp/python/3.1.3/Python-3.1.3.tgz
[Python-3.1.4]
url = http://www.python.org/ftp/python/3.1.4/Python-3.1.4.tgz
latest = True
[Python-3.2]
url = http://www.python.org/ftp/python/3.2/Python-3.2.tgz
[Python-3.2.1]
url = http://www.python.org/ftp/python/3.2.1/Python-3.2.1.tgz
latest = True
+16
View File
@@ -0,0 +1,16 @@
class BuildingException(Exception):
"""General exception during building"""
class ShellCommandException(Exception):
"""General exception during shell command"""
class UnknownVersionException(Exception):
"""General exception during installing"""
class AlreadyInstalledException(Exception):
"""General exception during installing"""
class NotSupportedVersionException(Exception):
"""General exception during installing"""
class CurlFetchException(Exception):
"""Exception curl during fetching"""
+62
View File
@@ -0,0 +1,62 @@
from pythonbrew.installer.pythonbrewinstaller import PythonbrewInstaller
from pythonbrew.log import logger
from pythonbrew.define import INSTALLER_ROOT, ROOT, PATH_ETC
def install_pythonbrew():
PythonbrewInstaller.install(INSTALLER_ROOT)
# for bash
shrc = yourshrc = "bashrc"
logger.log("""
Well-done! Congratulations!
The pythonbrew is installed as:
%(ROOT)s
Please add the following line to the end of your ~/.%(yourshrc)s
source %(PATH_ETC)s/%(shrc)s
After that, exit this shell, start a new one, and install some fresh
pythons:
pythonbrew install 2.7.2
pythonbrew install 3.2
For further instructions, run:
pythonbrew help
The default help messages will popup and tell you what to do!
Enjoy pythonbrew at %(ROOT)s!!
""" % {'ROOT':ROOT, 'yourshrc':yourshrc, 'shrc':shrc, 'PATH_ETC':PATH_ETC})
def upgrade_pythonbrew():
PythonbrewInstaller.install(INSTALLER_ROOT)
def systemwide_pythonbrew():
PythonbrewInstaller.install(INSTALLER_ROOT)
PythonbrewInstaller.systemwide_install()
logger.log("""
Well-done! Congratulations!
The pythonbrew is installed as:
%(ROOT)s
After that, exit this shell, start a new one, and install some fresh
pythons:
pythonbrew install 2.7.2
pythonbrew install 3.2
For further instructions, run:
pythonbrew help
The default help messages will popup and tell you what to do!
Enjoy pythonbrew at %(ROOT)s!!
""" % {'ROOT':ROOT})
+109
View File
@@ -0,0 +1,109 @@
import os
import sys
import glob
import shutil
from pythonbrew.util import makedirs, rm_r
from pythonbrew.define import PATH_BUILD, PATH_BIN, PATH_DISTS, PATH_PYTHONS,\
PATH_ETC, PATH_SCRIPTS, PATH_SCRIPTS_PYTHONBREW,\
PATH_SCRIPTS_PYTHONBREW_COMMANDS, PATH_BIN_PYTHONBREW,\
PATH_LOG, PATH_PATCHES, PATH_ETC_CONFIG,\
PATH_SCRIPTS_PYTHONBREW_INSTALLER, PATH_VENVS, PATH_HOME_ETC, ROOT
import stat
import time
class PythonbrewInstaller(object):
"""pythonbrew installer:
"""
@staticmethod
def install(installer_root):
# create directories
makedirs(PATH_PYTHONS)
makedirs(PATH_BUILD)
makedirs(PATH_DISTS)
makedirs(PATH_ETC)
makedirs(PATH_BIN)
makedirs(PATH_LOG)
makedirs(PATH_VENVS)
makedirs(PATH_HOME_ETC)
# create script directories
rm_r(PATH_SCRIPTS)
makedirs(PATH_SCRIPTS)
makedirs(PATH_SCRIPTS_PYTHONBREW)
makedirs(PATH_SCRIPTS_PYTHONBREW_COMMANDS)
makedirs(PATH_SCRIPTS_PYTHONBREW_INSTALLER)
# copy all .py files
for path in glob.glob(os.path.join(installer_root,"*.py")):
shutil.copy(path, PATH_SCRIPTS_PYTHONBREW)
for path in glob.glob(os.path.join(installer_root,"commands","*.py")):
shutil.copy(path, PATH_SCRIPTS_PYTHONBREW_COMMANDS)
for path in glob.glob(os.path.join(installer_root,"installer","*.py")):
shutil.copy(path, PATH_SCRIPTS_PYTHONBREW_INSTALLER)
# create patches direcotry
rm_r(PATH_PATCHES)
shutil.copytree(os.path.join(installer_root,"patches"), PATH_PATCHES)
# create a main file
fp = open("%s/pythonbrew_main.py" % PATH_SCRIPTS, "w")
fp.write("""import pythonbrew
if __name__ == "__main__":
pythonbrew.main()
""")
fp.close()
# create entry point file
fp = open(PATH_BIN_PYTHONBREW, "w")
fp.write("""#!/usr/bin/env bash
%s %s/pythonbrew_main.py "$@"
""" % (sys.executable, PATH_SCRIPTS))
fp.close()
# mode 0755
os.chmod(PATH_BIN_PYTHONBREW, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH)
# create a bashrc for pythonbrew
shutil.copy(os.path.join(installer_root,'etc','bashrc'), os.path.join(PATH_ETC,'bashrc'))
# copy config.cfg
shutil.copy(os.path.join(installer_root,'etc','config.cfg'), PATH_ETC_CONFIG)
@staticmethod
def systemwide_install():
profile = """\
#begin-pythonbrew
if [ -n "${BASH_VERSION:-}" -o -n "${ZSH_VERSION:-}" ] ; then
export PYTHONBREW_ROOT=%(root)s
source "${PYTHONBREW_ROOT}/etc/bashrc"
fi
#end-pythonbrew
""" % {'root': ROOT}
if os.path.isdir('/etc/profile.d'):
fp = open('/etc/profile.d/pythonbrew.sh', 'w')
fp.write(profile)
fp.close()
elif os.path.isfile('/etc/profile'):
# create backup
shutil.copy('/etc/profile', '/tmp/profile.pythonbrew.%s' % int(time.time()))
output = []
is_copy = True
fp = open('/etc/profile', 'r')
for line in fp:
if line.startswith('#begin-pythonbrew'):
is_copy = False
continue
elif line.startswith('#end-pythonbrew'):
is_copy = True
continue
if is_copy:
output.append(line)
fp.close()
output.append(profile)
fp = open('/etc/profile', 'w')
fp.write(''.join(output))
fp.close()
+330
View File
@@ -0,0 +1,330 @@
import os
import sys
import shutil
import mimetypes
import re
from pythonbrew.util import makedirs, symlink, Package, is_url, Link,\
unlink, is_html, Subprocess, rm_r,\
is_python25, is_python24, is_python26, is_python27,\
extract_downloadfile, is_archive_file, path_to_fileurl, is_file,\
fileurl_to_path, is_python30, is_python31, is_python32,\
get_macosx_deployment_target, Version
from pythonbrew.define import PATH_BUILD, PATH_DISTS, PATH_PYTHONS,\
ROOT, PATH_LOG, DISTRIBUTE_SETUP_DLSITE,\
PATH_PATCHES_MACOSX_PYTHON25, PATH_PATCHES_MACOSX_PYTHON24,\
PATH_PATCHES_MACOSX_PYTHON26, PATH_PATCHES_MACOSX_PYTHON27, PATH_PATCHES_ALL
from pythonbrew.downloader import get_python_version_url, Downloader,\
get_headerinfo_from_url
from pythonbrew.log import logger
from pythonbrew.exceptions import UnknownVersionException,\
NotSupportedVersionException
class PythonInstaller(object):
"""Python installer
"""
def __init__(self, arg, options):
if is_archive_file(arg):
name = path_to_fileurl(arg)
elif os.path.isdir(arg):
name = path_to_fileurl(arg)
else:
name = arg
if is_url(name):
self.download_url = name
filename = Link(self.download_url).filename
pkg = Package(filename, options.alias)
else:
pkg = Package(name, options.alias)
self.download_url = get_python_version_url(pkg.version)
if not self.download_url:
logger.error("Unknown python version: `%s`" % pkg.name)
raise UnknownVersionException
filename = Link(self.download_url).filename
self.pkg = pkg
self.install_dir = os.path.join(PATH_PYTHONS, pkg.name)
self.build_dir = os.path.join(PATH_BUILD, pkg.name)
self.download_file = os.path.join(PATH_DISTS, filename)
self.options = options
self.logfile = os.path.join(PATH_LOG, 'build.log')
self.patches = []
if Version(self.pkg.version) >= '3.1':
self.configure_options = ['--with-computed-gotos']
else:
self.configure_options = []
def install(self):
# cleanup
if os.path.isdir(self.build_dir):
shutil.rmtree(self.build_dir)
# get content type.
if is_file(self.download_url):
path = fileurl_to_path(self.download_url)
self.content_type = mimetypes.guess_type(path)[0]
else:
headerinfo = get_headerinfo_from_url(self.download_url)
self.content_type = headerinfo['content-type']
if is_html(self.content_type):
# note: maybe got 404 or 503 http status code.
logger.error("Invalid content-type: `%s`" % self.content_type)
return
if os.path.isdir(self.install_dir):
logger.info("You are already installed `%s`" % self.pkg.name)
return
self.download_and_extract()
logger.info("\nThis could take a while. You can run the following command on another shell to track the status:")
logger.info(" tail -f %s\n" % self.logfile)
self.patch()
logger.info("Installing %s into %s" % (self.pkg.name, self.install_dir))
try:
self.configure()
self.make()
self.make_install()
except:
rm_r(self.install_dir)
logger.error("Failed to install %s. See %s to see why." % (self.pkg.name, self.logfile))
logger.log(" pythonbrew install --force %s" % self.pkg.version)
sys.exit(1)
self.symlink()
self.install_setuptools()
logger.info("\nInstalled %(pkgname)s successfully. Run the following command to switch to %(pkgname)s."
% {"pkgname":self.pkg.name})
logger.info(" pythonbrew switch %s" % self.pkg.alias)
def download_and_extract(self):
if is_file(self.download_url):
path = fileurl_to_path(self.download_url)
if os.path.isdir(path):
logger.info('Copying %s into %s' % (path, self.build_dir))
shutil.copytree(path, self.build_dir)
return
if os.path.isfile(self.download_file):
logger.info("Use the previously fetched %s" % (self.download_file))
else:
base_url = Link(self.download_url).base_url
try:
dl = Downloader()
dl.download(base_url, self.download_url, self.download_file)
except:
unlink(self.download_file)
logger.error("Failed to download.\n%s" % (sys.exc_info()[1]))
sys.exit(1)
# extracting
if not extract_downloadfile(self.content_type, self.download_file, self.build_dir):
sys.exit(1)
def patch(self):
version = Version(self.pkg.version)
# for ubuntu 11.04(Natty)
if is_python24(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "python24")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python25(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "python25")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python26(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "common")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python27(version):
if version < '2.7.2':
patch_dir = os.path.join(PATH_PATCHES_ALL, "common")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python30(version):
patch_dir = os.path.join(PATH_PATCHES_ALL, "python30")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python31(version):
if version < '3.1.4':
patch_dir = os.path.join(PATH_PATCHES_ALL, "common")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
elif is_python32(version):
if version == '3.2':
patch_dir = os.path.join(PATH_PATCHES_ALL, "python32")
self._add_patches_to_list(patch_dir, ['patch-setup.py.diff'])
self._do_patch()
def _do_patch(self):
try:
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
if self.patches:
logger.info("Patching %s" % self.pkg.name)
for patch in self.patches:
if type(patch) is dict:
for (ed, source) in patch.items():
s.shell('ed - %s < %s' % (source, ed))
else:
s.shell("patch -p0 < %s" % patch)
except:
logger.error("Failed to patch `%s`.\n%s" % (self.build_dir, sys.exc_info()[1]))
sys.exit(1)
def _add_patches_to_list(self, patch_dir, patch_files):
for patch in patch_files:
if type(patch) is dict:
tmp = patch
patch = {}
for key in tmp.keys():
patch[os.path.join(patch_dir, key)] = tmp[key]
self.patches.append(patch)
else:
self.patches.append(os.path.join(patch_dir, patch))
def configure(self):
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
cmd = "./configure --prefix=%s %s %s" % (self.install_dir, self.options.configure, ' '.join(self.configure_options))
if self.options.verbose:
logger.log(cmd)
s.check_call(cmd)
def make(self):
jobs = self.options.jobs
make = ((jobs > 0 and 'make -j%s' % jobs) or 'make')
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
s.check_call(make)
if not self.options.no_test:
if self.options.force:
# note: ignore tests failure error.
s.call("make test")
else:
s.check_call("make test")
def make_install(self):
version = Version(self.pkg.version)
if version == "1.5.2" or version == "1.6.1":
makedirs(self.install_dir)
s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose)
s.check_call("make install")
def symlink(self):
install_dir = os.path.realpath(self.install_dir)
if self.options.framework:
# create symlink bin -> /path/to/Frameworks/Python.framework/Versions/?.?/bin
bin_dir = os.path.join(install_dir, 'bin')
if os.path.exists(bin_dir):
rm_r(bin_dir)
m = re.match(r'\d\.\d', self.pkg.version)
if m:
version = m.group(0)
symlink(os.path.join(install_dir,'Frameworks','Python.framework','Versions',version,'bin'),
os.path.join(bin_dir))
path_python = os.path.join(install_dir,'bin','python')
if not os.path.isfile(path_python):
src = None
for d in os.listdir(os.path.join(install_dir,'bin')):
if re.match(r'python\d\.\d', d):
src = d
break
if src:
path_src = os.path.join(install_dir,'bin',src)
symlink(path_src, path_python)
def install_setuptools(self):
options = self.options
pkgname = self.pkg.name
if options.no_setuptools:
logger.log("Skip installation of setuptools.")
return
download_url = DISTRIBUTE_SETUP_DLSITE
filename = Link(download_url).filename
download_file = os.path.join(PATH_DISTS, filename)
dl = Downloader()
dl.download(filename, download_url, download_file)
install_dir = os.path.join(PATH_PYTHONS, pkgname)
path_python = os.path.join(install_dir,"bin","python")
try:
s = Subprocess(log=self.logfile, cwd=PATH_DISTS, verbose=self.options.verbose)
logger.info("Installing distribute into %s" % install_dir)
s.check_call([path_python, filename])
# installing pip
easy_install = os.path.join(install_dir, 'bin', 'easy_install')
if os.path.isfile(easy_install):
logger.info("Installing pip into %s" % install_dir)
s.check_call([easy_install, 'pip'])
except:
logger.error("Failed to install setuptools. See %s/build.log to see why." % (ROOT))
logger.log("Skip installation of setuptools.")
class PythonInstallerMacOSX(PythonInstaller):
"""Python installer for MacOSX
"""
def __init__(self, arg, options):
super(PythonInstallerMacOSX, self).__init__(arg, options)
# check for version
version = Version(self.pkg.version)
if version < '2.6' and (version != '2.4.6' and version < '2.5.5'):
logger.error("`%s` is not supported on MacOSX Snow Leopard" % self.pkg.name)
raise NotSupportedVersionException
# set configure options
target = get_macosx_deployment_target()
if target:
self.configure_options.append('MACOSX_DEPLOYMENT_TARGET=%s' % target)
# set build options
if options.framework and options.static:
logger.error("Can't specify both framework and static.")
raise Exception
if options.framework:
self.configure_options.append('--enable-framework=%s' % os.path.join(self.install_dir, 'Frameworks'))
elif not options.static:
self.configure_options.append('--enable-shared')
if options.universal:
self.configure_options.append('--enable-universalsdk=/')
self.configure_options.append('--with-universal-archs=intel')
# note: skip `make test` to avoid hanging test_threading.
if is_python25(version) or is_python24(version):
self.options.no_test = True
def patch(self):
# note: want an interface to the source patching functionality. like a patchperl.
version = Version(self.pkg.version)
if is_python24(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON24
self._add_patches_to_list(patch_dir, ['patch-configure', 'patch-Makefile.pre.in',
'patch-Lib-cgi.py.diff', 'patch-Lib-site.py.diff',
'patch-setup.py.diff', 'patch-Include-pyport.h',
'patch-Mac-OSX-Makefile.in', 'patch-Mac-OSX-IDLE-Makefile.in',
'patch-Mac-OSX-PythonLauncher-Makefile.in', 'patch-configure-badcflags.diff',
'patch-configure-arch_only.diff', 'patch-macosmodule.diff',
'patch-mactoolboxglue.diff', 'patch-pymactoolbox.diff',
'patch-gestaltmodule.c.diff'])
elif is_python25(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON25
self._add_patches_to_list(patch_dir, ['patch-Makefile.pre.in.diff',
'patch-Lib-cgi.py.diff',
'patch-Lib-distutils-dist.py.diff',
'patch-setup.py.diff',
'patch-configure-badcflags.diff',
'patch-configure-arch_only.diff',
'patch-64bit.diff',
'patch-pyconfig.h.in.diff',
'patch-gestaltmodule.c.diff',
{'_localemodule.c.ed': 'Modules/_localemodule.c'},
{'locale.py.ed': 'Lib/locale.py'}])
elif is_python26(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON26
self._add_patches_to_list(patch_dir, ['patch-Lib-cgi.py.diff',
'patch-Lib-distutils-dist.py.diff',
'patch-Mac-IDLE-Makefile.in.diff',
'patch-Mac-Makefile.in.diff',
'patch-Mac-PythonLauncher-Makefile.in.diff',
'patch-Mac-Tools-Doc-setup.py.diff',
'patch-setup.py-db46.diff',
'patch-Lib-ctypes-macholib-dyld.py.diff',
'patch-setup_no_tkinter.py.diff',
{'_localemodule.c.ed': 'Modules/_localemodule.c'},
{'locale.py.ed': 'Lib/locale.py'}])
elif is_python27(version):
patch_dir = PATH_PATCHES_MACOSX_PYTHON27
self._add_patches_to_list(patch_dir, ['patch-Modules-posixmodule.diff'])
self._do_patch()
+43
View File
@@ -0,0 +1,43 @@
import sys
class Color(object):
DEBUG = '\033[35m'
INFO = '\033[32m'
ERROR = '\033[31m'
ENDC = '\033[0m'
@classmethod
def _deco(cls, msg, color):
return '%s%s%s' % (color, msg, cls.ENDC)
@classmethod
def debug(cls, msg):
return cls._deco(msg, cls.DEBUG)
@classmethod
def info(cls, msg):
return cls._deco(msg, cls.INFO)
@classmethod
def error(cls, msg):
return cls._deco(msg, cls.ERROR)
class Logger(object):
def debug(self, msg):
self._stdout(Color.debug("DEBUG: %s\n" % msg))
def log(self, msg):
self._stdout("%s\n" % (msg))
def info(self, msg):
self._stdout(Color.info('%s\n' % msg))
def error(self, msg):
self._stderr(Color.error("ERROR: %s\n" % msg))
def _stdout(self, msg):
sys.stdout.write(msg)
sys.stdout.flush()
def _stderr(self, msg):
sys.stderr.write(msg)
sys.stderr.flush()
logger = Logger()
@@ -0,0 +1,47 @@
# HG changeset patch
# User Barry Warsaw <barry@python.org>
# Date 1302190091 14400
# Node ID bd0f73a9538e05f526feaf05821e68bdcff498fa
# Parent 2e4cdaffe493e879fb5367a4aa454491de451137
Backport for Python 2.7 of issue 11715 support for building Python on
multiarch Debian/Ubuntu.
diff --git a/setup.py b/setup.py
--- setup.py.orig
+++ setup.py
@@ -345,10 +345,33 @@ class PyBuildExt(build_ext):
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ with open(tmpfile) as fp:
+ multiarch_path_component = fp.readline().strip()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,45 @@
--- setup.py.orig 2011-07-07 19:19:43.800122463 +0900
+++ setup.py 2011-07-07 19:25:04.548416377 +0900
@@ -13,6 +13,7 @@
from distutils.command.build_ext import build_ext
from distutils.command.install import install
from distutils.command.install_lib import install_lib
+from distutils.spawn import find_executable
# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []
@@ -242,10 +243,34 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ fp = open(tmpfile)
+ multiarch_path_component = fp.readline().strip()
+ fp.close()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,45 @@
--- setup.py.orig 2011-07-07 19:19:43.800122463 +0900
+++ setup.py 2011-07-07 19:25:04.548416377 +0900
@@ -13,6 +13,7 @@
from distutils.command.build_ext import build_ext
from distutils.command.install import install
from distutils.command.install_lib import install_lib
+from distutils.spawn import find_executable
# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []
@@ -242,10 +243,34 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ fp = open(tmpfile)
+ multiarch_path_component = fp.readline().strip()
+ fp.close()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,44 @@
--- setup.py.orig 2011-07-07 19:41:48.610196111 +0900
+++ setup.py 2011-07-07 19:46:44.986310031 +0900
@@ -14,6 +14,7 @@
from distutils.command.build_ext import build_ext
from distutils.command.install import install
from distutils.command.install_lib import install_lib
+from distutils.spawn import find_executable
# This global variable is used to hold the list of modules to be disabled.
disabled_module_list = []
@@ -308,10 +309,33 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ with open(tmpfile) as fp:
+ multiarch_path_component = fp.readline().strip()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,38 @@
--- setup.py.orig 2011-07-07 20:26:15.000000000 +0900
+++ setup.py 2011-07-07 20:29:28.735543350 +0900
@@ -370,12 +370,35 @@
return platform
return sys.platform
+ def add_multiarch_paths(self):
+ # Debian/Ubuntu multiarch support.
+ # https://wiki.ubuntu.com/MultiarchSpec
+ if not find_executable('dpkg-architecture'):
+ return
+ tmpfile = os.path.join(self.build_temp, 'multiarch')
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+ ret = os.system(
+ 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
+ tmpfile)
+ try:
+ if ret >> 8 == 0:
+ with open(tmpfile) as fp:
+ multiarch_path_component = fp.readline().strip()
+ add_dir_to_list(self.compiler.library_dirs,
+ '/usr/lib/' + multiarch_path_component)
+ add_dir_to_list(self.compiler.include_dirs,
+ '/usr/include/' + multiarch_path_component)
+ finally:
+ os.unlink(tmpfile)
+
def detect_modules(self):
# Ensure that /usr/local is always used, but the local build
# directories (i.e. '.' and 'Include') must be first. See issue
# 10520.
add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
+ self.add_multiarch_paths()
# Add paths specified in the environment variables LDFLAGS and
# CPPFLAGS for header and library files.
@@ -0,0 +1,34 @@
--- Include/pyport.h.orig 2007-03-12 23:26:06.000000000 -0700
+++ Include/pyport.h 2007-03-12 23:29:35.000000000 -0700
@@ -152,11 +152,23 @@ typedef PY_LONG_LONG Py_intptr_t;
#if defined(PYOS_OS2) && defined(PYCC_GCC)
#include <sys/types.h>
#endif
+
+#if (defined __APPLE__) && (!defined _POSIX_C_SOURCE)
+#define TEMPORARILY_DEFINING__POSIX_C_SOURCE /* so we can #undef it later */
+#define _POSIX_C_SOURCE /* avoid deprecated struct ostat in sys/stat.h */
+#endif
+
#include <sys/stat.h>
#elif defined(HAVE_STAT_H)
#include <stat.h>
#endif
+/* Mac OS X: undefine _POSIX_C_SOURCE if it wasn't defined before */
+#ifdef TEMPORARILY_DEFINING__POSIX_C_SOURCE
+#undef _POSIX_C_SOURCE
+#undef TEMPORARILY_DEFINING__POSIX_C_SOURCE
+#endif
+
#if defined(PYCC_VACPP)
/* VisualAge C/C++ Failed to Define MountType Field in sys/stat.h */
#define S_IFMT (S_IFDIR|S_IFCHR|S_IFREG)
@@ -393,6 +405,7 @@ extern char * _getpty(int *, int, mode_t
/* BSDI does not supply a prototype for the 'openpty' and 'forkpty'
functions, even though they are included in libutil. */
#include <termios.h>
+struct winsize;
extern int openpty(int *, int *, char *, struct termios *, struct winsize *);
extern int forkpty(int *, char *, struct termios *, struct winsize *);
#endif /* !defined(HAVE_PTY_H) && !defined(HAVE_LIBUTIL_H) */
@@ -0,0 +1,18 @@
--- Lib/cgi.py.orig 2006-08-11 09:14:38.000000000 +0200
+++ Lib/cgi.py 2007-08-21 15:36:54.000000000 +0200
@@ -1,13 +1,6 @@
-#! /usr/local/bin/python
+#! __PREFIX__/bin/python2.4
-# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is
-# intentionally NOT "/usr/bin/env python". On many systems
-# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
-# scripts, and /usr/local/bin is the default directory where Python is
-# installed, so /usr/bin/env would be unable to find python. Granted,
-# binary installations by Linux vendors often install Python in
-# /usr/bin. So let those vendors patch cgi.py to match their choice
-# of installation.
+# NOTE: /usr/local/bin/python patched for MacPorts installation
"""Support module for CGI (Common Gateway Interface) scripts.
@@ -0,0 +1,10 @@
--- Lib/site.py Tue Jul 20 04:28:28 2004
+++ Lib/site.py.new Mon Apr 4 10:47:12 2005
@@ -186,6 +186,7 @@
else:
sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")]
if sys.platform == 'darwin':
+ sitedirs.append( os.path.join('__PREFIX__', 'lib', 'python2.4', 'site-packages') )
# for framework builds *only* we add the standard Apple
# locations. Currently only per-user, but /Library and
# /Network/Library could be added too
@@ -0,0 +1,11 @@
--- Mac/OSX/IDLE/Makefile.in.orig 2006-10-08 10:41:25.000000000 -0700
+++ Mac/OSX/IDLE/Makefile.in 2007-04-27 13:27:07.000000000 -0700
@@ -21,7 +21,7 @@
BUNDLEBULDER=$(srcdir)/../../../Lib/plat-mac/bundlebuilder.py
-PYTHONAPPSDIR=/Applications/MacPython $(VERSION)
+PYTHONAPPSDIR=__APPLICATIONS_DIR__/MacPython $(VERSION)
all: IDLE.app
@@ -0,0 +1,20 @@
--- Mac/OSX/Makefile.in.orig 2006-10-08 10:41:25.000000000 -0700
+++ Mac/OSX/Makefile.in 2007-04-27 11:07:02.000000000 -0700
@@ -5,7 +5,7 @@
VERSION=@VERSION@
builddir = ../..
srcdir = @srcdir@
-prefix=/Library/Frameworks/Python.framework/Versions/$(VERSION)
+prefix=__FRAMEWORKS_DIR__/Python.framework/Versions/$(VERSION)
LIBDEST=$(prefix)/lib/python$(VERSION)
BUILDPYTHON=$(builddir)/python.exe
RUNSHARED= @RUNSHARED@
@@ -16,7 +16,7 @@
# These are normally glimpsed from the previous set
bindir=@exec_prefix@/bin
-PYTHONAPPSPATH=/Applications/MacPython $(VERSION)
+PYTHONAPPSPATH=__APPLICATIONS_DIR__/MacPython $(VERSION)
PYTHONAPPSDIR=$(PYTHONAPPSPATH)
APPINSTALLDIR=$(prefix)/Resources/Python.app
@@ -0,0 +1,20 @@
--- Mac/OSX/PythonLauncher/Makefile.in.orig 2006-10-08 10:41:25.000000000 -0700
+++ Mac/OSX/PythonLauncher/Makefile.in 2007-04-27 13:33:26.000000000 -0700
@@ -20,7 +20,7 @@
BUNDLEBULDER=$(srcdir)/../../../Lib/plat-mac/bundlebuilder.py
-PYTHONAPPSDIR=/Applications/MacPython $(VERSION)
+PYTHONAPPSDIR=__APPLICATIONS_DIR__/MacPython $(VERSION)
OBJECTS=FileSettings.o MyAppDelegate.o MyDocument.o PreferencesWindowController.o doscript.o main.o
all: PythonLauncher.app
@@ -56,7 +56,7 @@
--resource=$(srcdir)/factorySettings.plist \
--plist=$(srcdir)/Info.plist \
build
- find "PythonLauncher.app" -name '.svn' -print0 | xargs -0 rm -r
+ find "PythonLauncher.app" -name '.svn' -print0 | xargs -0 rm -r || :
FileSettings.o: $(srcdir)/FileSettings.m
@@ -0,0 +1,11 @@
--- Makefile.pre.in.orig 2006-10-08 10:41:25.000000000 -0700
+++ Makefile.pre.in 2007-04-20 18:06:11.000000000 -0700
@@ -56,7 +56,7 @@
OPT= @OPT@
BASECFLAGS= @BASECFLAGS@
CFLAGS= $(BASECFLAGS) $(OPT)
-CPPFLAGS= -I. -I$(srcdir)/Include
+CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir)/Include
LDFLAGS= @LDFLAGS@
LDLAST= @LDLAST@
SGI_ABI= @SGI_ABI@
@@ -0,0 +1,25 @@
--- configure.orig 2007-04-05 21:32:57.000000000 -0700
+++ configure 2007-04-05 21:32:59.000000000 -0700
@@ -3907,7 +3907,12 @@
;;
# is there any other compiler on Darwin besides gcc?
Darwin*)
- BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd"
+ if [[ `/usr/bin/arch` = 'ppc' ]]
+ then
+ BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common"
+ else
+ BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -fno-common"
+ fi
if test "${enable_universalsdk}"; then
BASECFLAGS="-arch ppc -arch i386 -isysroot ${UNIVERSALSDK} ${BASECFLAGS}"
fi
@@ -10328,7 +10333,7 @@
else
LIBTOOL_CRUFT=""
fi
- LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs -arch_only ppc'
+ LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs -arch_only '`/usr/bin/arch`
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)'
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';;
esac
@@ -0,0 +1,20 @@
--- configure.orig 2009-08-31 01:54:27.000000000 +1000
+++ configure 2009-08-31 01:55:24.000000000 +1000
@@ -10321,7 +10321,7 @@
Darwin/[01234567].*)
LIBTOOL_CRUFT="-framework System -lcc_dynamic"
if test -z "${enable_universalsdk}"; then
- LIBTOOL_CRUFT="${LIBTOOL_CRUFT} -arch_only `arch`"
+ LIBTOOL_CRUFT="${LIBTOOL_CRUFT}"
fi
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)'
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';;
@@ -10333,7 +10333,7 @@
else
LIBTOOL_CRUFT=""
fi
- LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs -arch_only '`/usr/bin/arch`
+ LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs'
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)'
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';;
esac
@@ -0,0 +1,14 @@
--- configure.orig 2009-08-31 01:29:04.000000000 +1000
+++ configure 2009-08-31 01:30:05.000000000 +1000
@@ -3909,9 +3909,9 @@
Darwin*)
if [[ `/usr/bin/arch` = 'ppc' ]]
then
- BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common"
+ BASECFLAGS="$BASECFLAGS -mno-fused-madd -fno-common"
else
- BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -fno-common"
+ BASECFLAGS="$BASECFLAGS -fno-common"
fi
if test "${enable_universalsdk}"; then
BASECFLAGS="-arch ppc -arch i386 -isysroot ${UNIVERSALSDK} ${BASECFLAGS}"
@@ -0,0 +1,19 @@
*** Mac/Modules/gestaltmodule.c 2010-11-21 15:35:00.000000000 +0900
--- Mac/Modules/gestaltmodule.c.new 2010-11-21 15:48:27.000000000 +0900
***************
*** 34,40 ****
{
OSErr iErr;
OSType selector;
! long response;
if (!PyArg_Parse(args, "O&", PyMac_GetOSType, &selector))
return NULL;
iErr = Gestalt ( selector, &response );
--- 34,40 ----
{
OSErr iErr;
OSType selector;
! SInt32 response;
if (!PyArg_Parse(args, "O&", PyMac_GetOSType, &selector))
return NULL;
iErr = Gestalt ( selector, &response );
@@ -0,0 +1,427 @@
--- Mac/Modules/macosmodule.c 2004-11-05 08:02:59.000000000 +0100
+++ Mac/Modules/macosmodule.c 2009-09-05 02:07:14.000000000 +0200
@@ -40,7 +40,7 @@
typedef struct {
PyObject_HEAD
- short fRefNum;
+ FSIORefNum fRefNum;
int isclosed;
} rfobject;
@@ -54,7 +54,7 @@
do_close(rfobject *self)
{
if (self->isclosed ) return;
- (void)FSClose(self->fRefNum);
+ (void)FSCloseFork(self->fRefNum);
self->isclosed = 1;
}
@@ -68,6 +68,7 @@
long n;
PyObject *v;
OSErr err;
+ ByteCount n2;
if (self->isclosed) {
PyErr_SetString(PyExc_ValueError, "Operation on closed file");
@@ -81,13 +82,13 @@
if (v == NULL)
return NULL;
- err = FSRead(self->fRefNum, &n, PyString_AsString(v));
+ err = FSReadFork(self->fRefNum, fsAtMark, 0, n, PyString_AsString(v), &n2);
if (err && err != eofErr) {
PyMac_Error(err);
Py_DECREF(v);
return NULL;
}
- _PyString_Resize(&v, n);
+ _PyString_Resize(&v, n2);
return v;
}
@@ -109,7 +110,7 @@
}
if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
return NULL;
- err = FSWrite(self->fRefNum, &size, buffer);
+ err = FSWriteFork(self->fRefNum, fsAtMark, 0, size, buffer, NULL);
if (err) {
PyMac_Error(err);
return NULL;
@@ -126,47 +127,36 @@
static PyObject *
rf_seek(rfobject *self, PyObject *args)
{
- long amount, pos;
+ long amount;
int whence = SEEK_SET;
- long eof;
+ int mode;
OSErr err;
if (self->isclosed) {
PyErr_SetString(PyExc_ValueError, "Operation on closed file");
return NULL;
}
- if (!PyArg_ParseTuple(args, "l|i", &amount, &whence))
+ if (!PyArg_ParseTuple(args, "l|i", &amount, &whence)) {
return NULL;
-
- if ((err = GetEOF(self->fRefNum, &eof)))
- goto ioerr;
+ }
switch (whence) {
case SEEK_CUR:
- if ((err = GetFPos(self->fRefNum, &pos)))
- goto ioerr;
+ mode = fsFromMark;
break;
case SEEK_END:
- pos = eof;
+ mode = fsFromLEOF;
break;
case SEEK_SET:
- pos = 0;
+ mode = fsFromStart;
break;
default:
PyErr_BadArgument();
return NULL;
}
-
- pos += amount;
-
- /* Don't bother implementing seek past EOF */
- if (pos > eof || pos < 0) {
- PyErr_BadArgument();
- return NULL;
- }
-
- if ((err = SetFPos(self->fRefNum, fsFromStart, pos)) ) {
-ioerr:
+
+ err = FSSetForkPosition(self->fRefNum, mode, amount);
+ if (err != noErr) {
PyMac_Error(err);
return NULL;
}
@@ -182,7 +172,7 @@
static PyObject *
rf_tell(rfobject *self, PyObject *args)
{
- long where;
+ long long where;
OSErr err;
if (self->isclosed) {
@@ -191,11 +181,13 @@
}
if (!PyArg_ParseTuple(args, ""))
return NULL;
- if ((err = GetFPos(self->fRefNum, &where)) ) {
+
+ err = FSGetForkPosition(self->fRefNum, &where);
+ if (err != noErr) {
PyMac_Error(err);
return NULL;
}
- return PyInt_FromLong(where);
+ return PyLong_FromLongLong(where);
}
static char rf_close__doc__[] =
@@ -281,6 +273,7 @@
Rftype__doc__ /* Documentation string */
};
+
/* End of code for Resource fork objects */
/* -------------------------------------------------------- */
@@ -292,17 +285,61 @@
static PyObject *
MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
{
- FSSpec fss;
- FInfo info;
PyObject *creator, *type, *res;
OSErr err;
-
- if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
+ FSRef ref;
+ FSCatalogInfo cataloginfo;
+ FileInfo* finfo;
+
+ if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &ref)) {
+#ifndef __LP64__
+ /* This function is documented to take an FSSpec as well,
+ * which only works in 32-bit mode.
+ */
+ PyErr_Clear();
+ FSSpec fss;
+ FInfo info;
+
+ if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
+ return NULL;
+
+ if ((err = FSpGetFInfo(&fss, &info)) != noErr) {
+ return PyErr_Mac(MacOS_Error, err);
+ }
+ creator = PyString_FromStringAndSize(
+ (char *)&info.fdCreator, 4);
+ type = PyString_FromStringAndSize((char *)&info.fdType, 4);
+ res = Py_BuildValue("OO", creator, type);
+ Py_DECREF(creator);
+ Py_DECREF(type);
+ return res;
+#else /* __LP64__ */
+ return NULL;
+#endif /* __LP64__ */
+ }
+
+ err = FSGetCatalogInfo(&ref,
+ kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
+ NULL, NULL, NULL);
+ if (err != noErr) {
+ PyErr_Mac(MacOS_Error, err);
return NULL;
- if ((err = FSpGetFInfo(&fss, &info)) != noErr)
- return PyErr_Mac(MacOS_Error, err);
- creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4);
- type = PyString_FromStringAndSize((char *)&info.fdType, 4);
+ }
+
+ if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
+ /* Directory: doesn't have type/creator info.
+ *
+ * The specific error code is for backward compatibility with
+ * earlier versions.
+ */
+ PyErr_Mac(MacOS_Error, fnfErr);
+ return NULL;
+
+ }
+ finfo = (FileInfo*)&(cataloginfo.finderInfo);
+ creator = PyString_FromStringAndSize((char*)&(finfo->fileCreator), 4);
+ type = PyString_FromStringAndSize((char*)&(finfo->fileType), 4);
+
res = Py_BuildValue("OO", creator, type);
Py_DECREF(creator);
Py_DECREF(type);
@@ -314,20 +351,66 @@
static PyObject *
MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
{
- FSSpec fss;
ResType creator, type;
- FInfo info;
+ FSRef ref;
+ FileInfo* finfo;
OSErr err;
-
+ FSCatalogInfo cataloginfo;
+
if (!PyArg_ParseTuple(args, "O&O&O&",
+ PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) {
+#ifndef __LP64__
+ /* Try to handle FSSpec arguments, for backward compatibility */
+ FSSpec fss;
+ FInfo info;
+
+ if (!PyArg_ParseTuple(args, "O&O&O&",
PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
+ return NULL;
+
+ if ((err = FSpGetFInfo(&fss, &info)) != noErr)
+ return PyErr_Mac(MacOS_Error, err);
+
+ info.fdCreator = creator;
+ info.fdType = type;
+
+ if ((err = FSpSetFInfo(&fss, &info)) != noErr)
+ return PyErr_Mac(MacOS_Error, err);
+ Py_INCREF(Py_None);
+ return Py_None;
+#else /* __LP64__ */
return NULL;
- if ((err = FSpGetFInfo(&fss, &info)) != noErr)
- return PyErr_Mac(MacOS_Error, err);
- info.fdCreator = creator;
- info.fdType = type;
- if ((err = FSpSetFInfo(&fss, &info)) != noErr)
- return PyErr_Mac(MacOS_Error, err);
+#endif /* __LP64__ */
+ }
+
+ err = FSGetCatalogInfo(&ref,
+ kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
+ NULL, NULL, NULL);
+ if (err != noErr) {
+ PyErr_Mac(MacOS_Error, err);
+ return NULL;
+ }
+
+ if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
+ /* Directory: doesn't have type/creator info.
+ *
+ * The specific error code is for backward compatibility with
+ * earlier versions.
+ */
+ PyErr_Mac(MacOS_Error, fnfErr);
+ return NULL;
+
+ }
+ finfo = (FileInfo*)&(cataloginfo.finderInfo);
+ finfo->fileCreator = creator;
+ finfo->fileType = type;
+
+ err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &cataloginfo);
+ if (err != noErr) {
+ PyErr_Mac(MacOS_Error, fnfErr);
+ return NULL;
+ }
+
Py_INCREF(Py_None);
return Py_None;
}
@@ -375,6 +458,7 @@
/* And try again... */
h = GetResource('Estr', err);
}
+ Py_DECREF(m);
}
}
/*
@@ -398,6 +482,9 @@
return Py_BuildValue("s", buf);
}
+
+#ifndef __LP64__
+
static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
static PyObject *
@@ -416,7 +503,7 @@
return NULL;
olddialog = curdialog;
curdialog = NULL;
-
+
if ( resid != -1 ) {
curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
if ( curdialog ) {
@@ -451,11 +538,13 @@
if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
return NULL;
+
DebugStr(message);
Py_INCREF(Py_None);
return Py_None;
}
+
static char SysBeep_doc[] = "BEEEEEP!!!";
static PyObject *
@@ -470,6 +559,8 @@
return Py_None;
}
+#endif /* __LP64__ */
+
static char WMAvailable_doc[] =
"True if this process can interact with the display."
"Will foreground the application on the first call as a side-effect."
@@ -529,51 +620,37 @@
{
OSErr err;
char *mode = "r";
- FSSpec fss;
- SignedByte permission = 1;
+ FSRef ref;
+ SInt8 permission = fsRdPerm;
rfobject *fp;
+ HFSUniStr255 name;
- if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode))
+ if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSRef, &ref, &mode))
return NULL;
while (*mode) {
switch (*mode++) {
case '*': break;
- case 'r': permission = 1; break;
- case 'w': permission = 2; break;
+ case 'r': permission = fsRdPerm; break;
+ case 'w': permission = fsWrPerm; break;
case 'b': break;
default:
PyErr_BadArgument();
return NULL;
}
}
+
+ err = FSGetResourceForkName(&name);
+ if (err != noErr) {
+ PyMac_Error(err);
+ return NULL;
+ }
if ( (fp = newrfobject()) == NULL )
return NULL;
-
- err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
+
- if ( err == fnfErr ) {
- /* In stead of doing complicated things here to get creator/type
- ** correct we let the standard i/o library handle it
- */
- FILE *tfp;
- char pathname[PATHNAMELEN];
-
- if ( (err=PyMac_GetFullPathname(&fss, pathname, PATHNAMELEN)) ) {
- PyMac_Error(err);
- Py_DECREF(fp);
- return NULL;
- }
-
- if ( (tfp = fopen(pathname, "w")) == NULL ) {
- PyMac_Error(fnfErr); /* What else... */
- Py_DECREF(fp);
- return NULL;
- }
- fclose(tfp);
- err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum);
- }
- if ( err ) {
+ err = FSOpenFork(&ref, name.length, name.unicode, permission, &fp->fRefNum);
+ if (err != noErr) {
Py_DECREF(fp);
PyMac_Error(err);
return NULL;
@@ -583,15 +660,18 @@
}
+
static PyMethodDef MacOS_Methods[] = {
{"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc},
{"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc},
{"GetErrorString", MacOS_GetErrorString, 1, geterr_doc},
{"openrf", MacOS_openrf, 1, openrf_doc},
+#ifndef __LP64__
{"splash", MacOS_splash, 1, splash_doc},
{"DebugStr", MacOS_DebugStr, 1, DebugStr_doc},
- {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
{"SysBeep", MacOS_SysBeep, 1, SysBeep_doc},
+#endif /* __LP64__ */
+ {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc},
{"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc},
{NULL, NULL} /* Sentinel */
};
@@ -0,0 +1,20 @@
--- Python/mactoolboxglue.c 2006-10-08 19:41:25.000000000 +0200
+++ Python/mactoolboxglue.c 2009-09-05 01:25:57.000000000 +0200
@@ -414,7 +414,7 @@
GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs")
GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs")
-
+/*
GLUE_NEW(Track, TrackObj_New, "Carbon.Qt")
GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt")
GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt")
@@ -427,7 +427,7 @@
GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt")
GLUE_NEW(Media, MediaObj_New, "Carbon.Qt")
GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt")
-
+*/
GLUE_NEW(Handle, ResObj_New, "Carbon.Res")
GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res")
GLUE_NEW(Handle, OptResObj_New, "Carbon.Res")
@@ -0,0 +1,18 @@
--- Include/pymactoolbox.h 2004-11-05 08:02:59.000000000 +0100
+++ Include/pymactoolbox.h 2009-09-05 01:26:30.000000000 +0200
@@ -134,6 +134,7 @@
extern int GWorldObj_Convert(PyObject *, GWorldPtr *);
/* Qt exports */
+/*
extern PyObject *TrackObj_New(Track);
extern int TrackObj_Convert(PyObject *, Track *);
extern PyObject *MovieObj_New(Movie);
@@ -146,6 +147,7 @@
extern int UserDataObj_Convert(PyObject *, UserData *);
extern PyObject *MediaObj_New(Media);
extern int MediaObj_Convert(PyObject *, Media *);
+*/
/* Res exports */
extern PyObject *ResObj_New(Handle);
@@ -0,0 +1,46 @@
--- setup.py.orig 2006-10-08 11:41:25.000000000 -0600
+++ setup.py 2008-11-19 22:13:50.000000000 -0700
@@ -15,7 +15,7 @@
from distutils.command.install_lib import install_lib
# This global variable is used to hold the list of modules to be disabled.
-disabled_module_list = []
+disabled_module_list = ["readline"]
def add_dir_to_list(dirlist, dir):
"""Add the directory 'dir' to the list 'dirlist' (at the front) if
@@ -246,11 +246,11 @@
# Add paths to popular package managers on OS X/darwin
if sys.platform == "darwin":
# Fink installs into /sw by default
- add_dir_to_list(self.compiler.library_dirs, '/sw/lib')
- add_dir_to_list(self.compiler.include_dirs, '/sw/include')
+ #add_dir_to_list(self.compiler.library_dirs, '/sw/lib')
+ #add_dir_to_list(self.compiler.include_dirs, '/sw/include')
# DarwinPorts installs into /opt/local by default
- #add_dir_to_list(self.compiler.library_dirs, '/opt/local/lib')
- #add_dir_to_list(self.compiler.include_dirs, '/opt/local/include')
+ add_dir_to_list(self.compiler.library_dirs, '__PREFIX__/lib')
+ add_dir_to_list(self.compiler.include_dirs, '__PREFIX__/include')
if os.path.normpath(sys.prefix) != '/usr':
add_dir_to_list(self.compiler.library_dirs,
@@ -357,7 +357,7 @@
exts.append( Extension('unicodedata', ['unicodedata.c']) )
# access to ISO C locale support
data = open('pyconfig.h').read()
- m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
+ m = re.search(r"#\s*define\s+(HAVE_LIBINTL_H|WITH_LIBINTL)\s+1\s*", data)
if m is not None:
locale_libs = ['intl']
else:
@@ -954,7 +954,8 @@
self.extensions.extend(exts)
# Call the method for detecting whether _tkinter can be compiled
- self.detect_tkinter(inc_dirs, lib_dirs)
+ if ("--disable-tk" not in sysconfig.get_config_var("CONFIG_ARGS")):
+ self.detect_tkinter(inc_dirs, lib_dirs)
def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
# The _tkinter module, using frameworks. Since frameworks are quite
@@ -0,0 +1,2 @@
g/defined(__APPLE__)/s//0/g
w
@@ -0,0 +1,2 @@
g/'darwin', /s///
w
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,18 @@
--- Lib/cgi.py.orig 2006-08-10 19:41:07.000000000 +0200
+++ Lib/cgi.py 2007-08-21 15:36:54.000000000 +0200
@@ -1,13 +1,6 @@
-#! /usr/local/bin/python
+#! __PREFIX__/bin/python2.5
-# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is
-# intentionally NOT "/usr/bin/env python". On many systems
-# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
-# scripts, and /usr/local/bin is the default directory where Python is
-# installed, so /usr/bin/env would be unable to find python. Granted,
-# binary installations by Linux vendors often install Python in
-# /usr/bin. So let those vendors patch cgi.py to match their choice
-# of installation.
+# NOTE: /usr/local/bin/python patched for MacPorts installation
"""Support module for CGI (Common Gateway Interface) scripts.
@@ -0,0 +1,51 @@
--- Lib/distutils/dist.py.orig 2005-03-23 11:54:36.000000000 -0700
+++ Lib/distutils/dist.py 2008-07-25 21:27:15.000000000 -0600
@@ -57,6 +57,7 @@
('quiet', 'q', "run quietly (turns verbosity off)"),
('dry-run', 'n', "don't actually do anything"),
('help', 'h', "show detailed help message"),
+ ('no-user-cfg', None,'ignore pydistutils.cfg in your home directory'),
]
# 'common_usage' is a short (2-3 line) string describing the common
@@ -264,6 +265,12 @@
else:
sys.stderr.write(msg + "\n")
+ # no-user-cfg is handled before other command line args
+ # because other args override the config files, and this
+ # one is needed before we can load the config files.
+ # If attrs['script_args'] wasn't passed, assume false.
+ self.want_user_cfg = '--no-user-cfg' not in (self.script_args or [])
+
self.finalize_options()
# __init__ ()
@@ -324,6 +331,9 @@
Distutils __inst__.py file lives), a file in the user's home
directory named .pydistutils.cfg on Unix and pydistutils.cfg
on Windows/Mac, and setup.cfg in the current directory.
+
+ The file in the user's home directory can be disabled with the
+ --no-user-cfg option.
"""
files = []
check_environ()
@@ -343,7 +353,7 @@
user_filename = "pydistutils.cfg"
# And look for the user config file
- if os.environ.has_key('HOME'):
+ if self.want_user_cfg and os.environ.has_key('HOME'):
user_file = os.path.join(os.environ.get('HOME'), user_filename)
if os.path.isfile(user_file):
files.append(user_file)
@@ -353,6 +363,8 @@
if os.path.isfile(local_file):
files.append(local_file)
+ if DEBUG:
+ print "using config files: %s" % ', '.join(files)
return files
# find_config_files ()
@@ -0,0 +1,31 @@
--- Makefile.pre.in.orig 2007-12-05 13:43:57.000000000 -0700
+++ Makefile.pre.in 2008-07-25 21:41:02.000000000 -0600
@@ -348,8 +348,8 @@
# Build the shared modules
sharedmods: $(BUILDPYTHON)
case $$MAKEFLAGS in \
- *-s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q build;; \
- *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py build;; \
+ *-s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q --no-user-cfg build;; \
+ *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py --no-user-cfg build;; \
esac
# Build static library
@@ -894,7 +904,7 @@
# Install the dynamically loadable modules
# This goes into $(exec_prefix)
sharedinstall:
- $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py install \
+ $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py --no-user-cfg install \
--prefix=$(prefix) \
--install-scripts=$(BINDIR) \
--install-platlib=$(DESTSHARED) \
@@ -968,7 +978,7 @@
# This installs a few of the useful scripts in Tools/scripts
scriptsinstall:
SRCDIR=$(srcdir) $(RUNSHARED) \
- ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/setup.py install \
+ ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/setup.py --no-user-cfg install \
--prefix=$(prefix) \
--install-scripts=$(BINDIR) \
--root=/$(DESTDIR)
@@ -0,0 +1,20 @@
--- configure.orig 2009-06-24 13:57:38.000000000 -0700
+++ configure 2009-06-24 13:58:38.000000000 -0700
@@ -11362,7 +11362,7 @@
if test "${enable_universalsdk}"; then
:
else
- LIBTOOL_CRUFT="${LIBTOOL_CRUFT} -arch_only `arch`"
+ LIBTOOL_CRUFT="${LIBTOOL_CRUFT}"
fi
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)'
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';;
@@ -11374,7 +11374,7 @@
else
LIBTOOL_CRUFT=""
fi
- LIBTOOL_CRUFT=$LIBTOOL_CRUFT" -lSystem -lSystemStubs -arch_only `arch`"
+ LIBTOOL_CRUFT=$LIBTOOL_CRUFT" -lSystem -lSystemStubs"
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)'
LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';;
esac
@@ -0,0 +1,11 @@
--- configure.orig 2008-10-15 18:00:59.000000000 -0700
+++ configure 2008-10-15 18:02:47.000000000 -0700
@@ -4538,7 +4538,7 @@
;;
# is there any other compiler on Darwin besides gcc?
Darwin*)
- BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd"
+ BASECFLAGS="$BASECFLAGS -mno-fused-madd"
if test "${enable_universalsdk}"; then
BASECFLAGS="-arch ppc -arch i386 -isysroot ${UNIVERSALSDK} ${BASECFLAGS}"
fi
@@ -0,0 +1,19 @@
*** Mac/Modules/gestaltmodule.c 2010-11-21 14:34:58.000000000 +0900
--- Mac/Modules/gestaltmodule.c.new 2010-11-21 14:38:30.000000000 +0900
***************
*** 34,40 ****
{
OSErr iErr;
OSType selector;
! long response;
if (!PyArg_ParseTuple(args, "O&", PyMac_GetOSType, &selector))
return NULL;
iErr = Gestalt ( selector, &response );
--- 34,40 ----
{
OSErr iErr;
OSType selector;
! SInt32 response;
if (!PyArg_ParseTuple(args, "O&", PyMac_GetOSType, &selector))
return NULL;
iErr = Gestalt ( selector, &response );
@@ -0,0 +1,13 @@
--- pyconfig.h.in.orig 2009-08-16 10:22:50.000000000 -0700
+++ pyconfig.h.in 2009-08-16 10:23:24.000000000 -0700
@@ -4,6 +4,10 @@
#ifndef Py_PYCONFIG_H
#define Py_PYCONFIG_H
+// Required on Darwin 10+
+#ifndef _DARWIN_C_SOURCE
+#define _DARWIN_C_SOURCE
+#endif
/* Define for AIX if your compiler is a genuine IBM xlC/xlC_r and you want
support for AIX C++ shared extension modules. */
@@ -0,0 +1,80 @@
--- setup.py.orig 2008-10-16 12:58:19.000000000 -0600
+++ setup.py 2009-06-07 20:55:17.000000000 -0600
@@ -609,7 +609,7 @@
# a release. Most open source OSes come with one or more
# versions of BerkeleyDB already installed.
- max_db_ver = (4, 5)
+ max_db_ver = (4, 6)
# NOTE: while the _bsddb.c code links against BerkeleyDB 4.6.x
# we leave that version disabled by default as it has proven to be
# quite a buggy library release on many platforms.
@@ -636,6 +636,7 @@
db_inc_paths.append('/usr/local/include/db4%d' % x)
db_inc_paths.append('/pkg/db-4.%d/include' % x)
db_inc_paths.append('/opt/db-4.%d/include' % x)
+ db_inc_paths.append('__PREFIX__/include/db4%d' % x)
# 3.x minor number specific paths
for x in (3,):
db_inc_paths.append('/usr/include/db3%d' % x)
@@ -711,6 +712,7 @@
# check lib directories parallel to the location of the header
db_dirs_to_check = [
+ os.path.join('__PREFIX__', 'lib', 'db46'),
os.path.join(db_incdir, '..', 'lib64'),
os.path.join(db_incdir, '..', 'lib'),
os.path.join(db_incdir, '..', '..', 'lib64'),
@@ -1212,13 +1214,7 @@
def detect_tkinter(self, inc_dirs, lib_dirs):
# The _tkinter module.
- # Rather than complicate the code below, detecting and building
- # AquaTk is a separate method. Only one Tkinter will be built on
- # Darwin - either AquaTk, if it is found, or X11 based Tk.
platform = self.get_platform()
- if (platform == 'darwin' and
- self.detect_tkinter_darwin(inc_dirs, lib_dirs)):
- return
# Assume we haven't found any of the libraries or include files
# The versions with dots are used on Unix, and the versions without
--- setup.py.orig 2009-09-10 19:41:32.000000000 +1000
+++ setup.py 2009-09-10 19:48:30.000000000 +1000
@@ -1197,7 +1197,7 @@
# For 8.4a2, the X11 headers are not included. Rather than include a
# complicated search, this is a hard-coded path. It could bail out
# if X11 libs are not found...
- include_dirs.append('/usr/X11R6/include')
+ #include_dirs.append('/usr/X11R6/include')
frameworks = ['-framework', 'Tcl', '-framework', 'Tk']
ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
@@ -1262,17 +1262,17 @@
if platform == 'sunos5':
include_dirs.append('/usr/openwin/include')
added_lib_dirs.append('/usr/openwin/lib')
- elif os.path.exists('/usr/X11R6/include'):
- include_dirs.append('/usr/X11R6/include')
- added_lib_dirs.append('/usr/X11R6/lib64')
- added_lib_dirs.append('/usr/X11R6/lib')
- elif os.path.exists('/usr/X11R5/include'):
- include_dirs.append('/usr/X11R5/include')
- added_lib_dirs.append('/usr/X11R5/lib')
- else:
+ #elif os.path.exists('/usr/X11R6/include'):
+ # include_dirs.append('/usr/X11R6/include')
+ # added_lib_dirs.append('/usr/X11R6/lib64')
+ # added_lib_dirs.append('/usr/X11R6/lib')
+ #elif os.path.exists('/usr/X11R5/include'):
+ # include_dirs.append('/usr/X11R5/include')
+ # added_lib_dirs.append('/usr/X11R5/lib')
+ #else:
# Assume default location for X11
- include_dirs.append('/usr/X11/include')
- added_lib_dirs.append('/usr/X11/lib')
+ # include_dirs.append('/usr/X11/include')
+ # added_lib_dirs.append('/usr/X11/lib')
# If Cygwin, then verify that X is installed before proceeding
if platform == 'cygwin':
@@ -0,0 +1,3 @@
g/defined(__APPLE__)/s//0/g
w
@@ -0,0 +1,3 @@
g/'darwin', /s///
w
@@ -0,0 +1,18 @@
--- Lib/cgi.py.orig 2006-08-10 19:41:07.000000000 +0200
+++ Lib/cgi.py 2007-08-21 15:36:54.000000000 +0200
@@ -1,13 +1,6 @@
-#! /usr/local/bin/python
+#! @@PREFIX@@/bin/python2.6
-# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is
-# intentionally NOT "/usr/bin/env python". On many systems
-# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
-# scripts, and /usr/local/bin is the default directory where Python is
-# installed, so /usr/bin/env would be unable to find python. Granted,
-# binary installations by Linux vendors often install Python in
-# /usr/bin. So let those vendors patch cgi.py to match their choice
-# of installation.
+# NOTE: /usr/local/bin/python patched for MacPorts installation
"""Support module for CGI (Common Gateway Interface) scripts.
@@ -0,0 +1,11 @@
--- Lib/ctypes/macholib/dyld.py.orig 2008-02-21 11:52:20.000000000 -0700
+++ Lib/ctypes/macholib/dyld.py 2009-10-11 02:42:21.000000000 -0600
@@ -26,7 +26,7 @@
DEFAULT_LIBRARY_FALLBACK = [
os.path.expanduser("~/lib"),
- "/usr/local/lib",
+ "@@PREFIX@@/lib",
"/lib",
"/usr/lib",
]
@@ -0,0 +1,51 @@
--- Lib/distutils/dist.py.orig 2008-09-03 05:13:56.000000000 -0600
+++ Lib/distutils/dist.py 2008-10-03 18:33:47.000000000 -0600
@@ -60,6 +60,7 @@
('quiet', 'q', "run quietly (turns verbosity off)"),
('dry-run', 'n', "don't actually do anything"),
('help', 'h', "show detailed help message"),
+ ('no-user-cfg', None,'ignore pydistutils.cfg in your home directory'),
]
# 'common_usage' is a short (2-3 line) string describing the common
@@ -267,6 +268,12 @@
else:
sys.stderr.write(msg + "\n")
+ # no-user-cfg is handled before other command line args
+ # because other args override the config files, and this
+ # one is needed before we can load the config files.
+ # If attrs['script_args'] wasn't passed, assume false.
+ self.want_user_cfg = '--no-user-cfg' not in (self.script_args or [])
+
self.finalize_options()
# __init__ ()
@@ -327,6 +334,9 @@
Distutils __inst__.py file lives), a file in the user's home
directory named .pydistutils.cfg on Unix and pydistutils.cfg
on Windows/Mac, and setup.cfg in the current directory.
+
+ The file in the user's home directory can be disabled with the
+ --no-user-cfg option.
"""
files = []
check_environ()
@@ -347,7 +357,7 @@
# And look for the user config file
user_file = os.path.join(os.path.expanduser('~'), user_filename)
- if os.path.isfile(user_file):
+ if self.want_user_cfg and os.path.isfile(user_file):
files.append(user_file)
# All platforms support local setup.cfg
@@ -355,6 +365,8 @@
if os.path.isfile(local_file):
files.append(local_file)
+ if DEBUG:
+ print "using config files: %s" % ', '.join(files)
return files
# find_config_files ()
@@ -0,0 +1,20 @@
--- Mac/IDLE/Makefile.in.orig 2009-01-02 04:47:17.000000000 -0700
+++ Mac/IDLE/Makefile.in 2009-04-16 00:54:43.000000000 -0600
@@ -22,7 +22,7 @@
BUNDLEBULDER=$(srcdir)/../../Lib/plat-mac/bundlebuilder.py
-PYTHONAPPSDIR=/Applications/$(PYTHONFRAMEWORK) $(VERSION)
+PYTHONAPPSDIR=@@APPLICATIONS_DIR@@/$(PYTHONFRAMEWORK) $(VERSION)
all: IDLE.app
@@ -42,7 +42,7 @@
$(srcdir)/../Icons/PythonSource.icns \
$(srcdir)/../Icons/PythonCompiled.icns Info.plist
rm -fr IDLE.app
- $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(BUNDLEBULDER) \
+ PYTHONHOME=$(DESTDIR)$(prefix) $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(BUNDLEBULDER) \
--builddir=. \
--name=IDLE \
--link-exec \
@@ -0,0 +1,20 @@
--- Mac/Makefile.in.orig 2009-03-30 13:58:41.000000000 -0600
+++ Mac/Makefile.in 2009-04-16 00:54:26.000000000 -0600
@@ -19,7 +19,7 @@
# These are normally glimpsed from the previous set
bindir=$(prefix)/bin
-PYTHONAPPSDIR=/Applications/$(PYTHONFRAMEWORK) $(VERSION)
+PYTHONAPPSDIR=@@APPLICATIONS_DIR@@/$(PYTHONFRAMEWORK) $(VERSION)
APPINSTALLDIR=$(prefix)/Resources/Python.app
# Variables for installing the "normal" unix binaries
@@ -224,7 +224,7 @@
cd IDLE && make install
install_BuildApplet:
- $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(srcdir)/scripts/BuildApplet.py \
+ PYTHONHOME=$(DESTDIR)$(prefix) $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(srcdir)/scripts/BuildApplet.py \
--destroot "$(DESTDIR)" \
--python=$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)`test -f "$(DESTDIR)$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)-32" && echo "-32"` \
--output "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app" \
@@ -0,0 +1,25 @@
--- Mac/PythonLauncher/Makefile.in.orig 2009-01-02 04:47:17.000000000 -0700
+++ Mac/PythonLauncher/Makefile.in 2009-04-16 00:55:11.000000000 -0600
@@ -1,3 +1,4 @@
+prefix=@prefix@
CC=@CC@
LD=@CC@
BASECFLAGS=@BASECFLAGS@
@@ -21,7 +22,7 @@
BUNDLEBULDER=$(srcdir)/../../Lib/plat-mac/bundlebuilder.py
-PYTHONAPPSDIR=/Applications/$(PYTHONFRAMEWORK) $(VERSION)
+PYTHONAPPSDIR=@@APPLICATIONS_DIR@@/$(PYTHONFRAMEWORK) $(VERSION)
OBJECTS=FileSettings.o MyAppDelegate.o MyDocument.o PreferencesWindowController.o doscript.o main.o
all: Python\ Launcher.app
@@ -42,7 +43,7 @@
$(srcdir)/../Icons/PythonCompiled.icns \
$(srcdir)/factorySettings.plist
rm -fr "Python Launcher.app"
- $(RUNSHARED) $(BUILDPYTHON) $(BUNDLEBULDER) \
+ PYTHONHOME=$(DESTDIR)$(prefix) $(RUNSHARED) $(BUILDPYTHON) $(BUNDLEBULDER) \
--builddir=. \
--name="Python Launcher" \
--executable="Python Launcher" \
@@ -0,0 +1,11 @@
--- Mac/Tools/Doc/setup.py.diff 2008-03-29 09:24:25.000000000 -0600
+++ Mac/Tools/Doc/setup.py 2008-10-04 19:53:40.000000000 -0600
@@ -30,7 +30,7 @@
MAJOR_VERSION='2.4'
MINOR_VERSION='2.4.1'
-DESTDIR='/Applications/MacPython-%s/PythonIDE.app/Contents/Resources/English.lproj/PythonDocumentation' % MAJOR_VERSION
+DESTDIR='@@APPLICATIONS_DIR@@/MacPython-%s/PythonIDE.app/Contents/Resources/English.lproj/PythonDocumentation' % MAJOR_VERSION
class DocBuild(build):
def initialize_options(self):
@@ -0,0 +1,11 @@
--- setup.py.orig 2010-10-19 22:33:25.000000000 +0200
+++ setup.py 2010-10-19 22:33:54.000000000 +0200
@@ -799,7 +799,7 @@
# BerkeleyDB 4.6.x is not stable on many architectures.
arch = platform_machine()
if arch not in ('i386', 'i486', 'i586', 'i686',
- 'x86_64', 'ia64'):
+ 'x86_64', 'ia64', 'Power Macintosh'):
return False
return True
@@ -0,0 +1,11 @@
--- setup.py.orig 2009-03-31 12:20:48.000000000 -0600
+++ setup.py 2009-09-17 00:33:12.000000000 -0600
@@ -17,7 +17,7 @@
from distutils.command.install_lib import install_lib
# This global variable is used to hold the list of modules to be disabled.
-disabled_module_list = []
+disabled_module_list = ["_tkinter"]
def add_dir_to_list(dirlist, dir):
"""Add the directory 'dir' to the list 'dirlist' (at the front) if
@@ -0,0 +1,20 @@
--- Modules/posixmodule.c.orig 2011-05-28 16:57:40.000000000 -0400
+++ Modules/posixmodule.c 2011-05-28 16:56:40.000000000 -0400
@@ -455,7 +455,7 @@
#endif
/* Return a dictionary corresponding to the POSIX environment table */
-#ifdef WITH_NEXT_FRAMEWORK
+#ifdef __APPLE__
/* On Darwin/MacOSX a shared library or framework has no access to
** environ directly, we must obtain it with _NSGetEnviron().
*/
@@ -477,7 +477,7 @@
d = PyDict_New();
if (d == NULL)
return NULL;
-#ifdef WITH_NEXT_FRAMEWORK
+#ifdef __APPLE__
if (environ == NULL)
environ = *_NSGetEnviron();
#endif
+454
View File
@@ -0,0 +1,454 @@
import os
import sys
import errno
import shutil
import re
import posixpath
import tarfile
import platform
import urllib
import subprocess
import shlex
import select
from pythonbrew.define import PATH_BIN, PATH_HOME_ETC_CURRENT, PATH_PYTHONS
from pythonbrew.exceptions import ShellCommandException
from pythonbrew.log import logger
def size_format(b):
kb = 1000
mb = kb*kb
b = float(b)
if b >= mb:
return "%.1fMb" % (b/mb)
if b >= kb:
return "%.1fKb" % (b/kb)
return "%.0fbytes" % (b)
def is_url(name):
if ':' not in name:
return False
scheme = name.split(':', 1)[0].lower()
return scheme in ['http', 'https', 'file', 'ftp']
def is_file(name):
if ':' not in name:
return False
scheme = name.split(':', 1)[0].lower()
return scheme == 'file'
def splitext(name):
base, ext = os.path.splitext(name)
if base.lower().endswith('.tar'):
ext = base[-4:] + ext
base = base[:-4]
return base, ext
def is_archive_file(name):
ext = splitext(name)[1].lower()
archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar')
if ext in archives:
return True
return False
def is_html(content_type):
if content_type and content_type.startswith('text/html'):
return True
return False
def is_gzip(content_type, filename):
if(content_type == 'application/x-gzip'
or tarfile.is_tarfile(filename)
or splitext(filename)[1].lower() in ('.tar', '.tar.gz', '.tgz')):
return True
return False
def is_macosx():
mac_ver = platform.mac_ver()[0]
return mac_ver >= '10.6'
def get_macosx_deployment_target():
m = re.search('^([0-9]+\.[0-9]+)', platform.mac_ver()[0])
if m:
return m.group(1)
return None
def _py_version_cmp(v, v1, v2):
if is_str(v):
v = Version(v)
return v >= v1 and v < v2
def is_python24(version):
return _py_version_cmp(version, '2.4', '2.5')
def is_python25(version):
return _py_version_cmp(version, '2.5', '2.6')
def is_python26(version):
return _py_version_cmp(version, '2.6', '2.7')
def is_python27(version):
return _py_version_cmp(version, '2.7', '2.8')
def is_python30(version):
return _py_version_cmp(version, '3.0', '3.1')
def is_python31(version):
return _py_version_cmp(version, '3.1', '3.2')
def is_python32(version):
return _py_version_cmp(version, '3.2', '3.3')
def makedirs(path):
if not os.path.exists(path):
os.makedirs(path)
def symlink(src, dst):
try:
os.symlink(src, dst)
except:
pass
def unlink(path):
try:
os.unlink(path)
except OSError:
e = sys.exc_info()[1]
if errno.ENOENT != e.errno:
raise
def rm_r(path):
"""like rm -r command."""
if os.path.isdir(path):
shutil.rmtree(path)
elif os.path.isfile(path):
unlink(path)
def off():
set_current_path(PATH_BIN)
def split_leading_dir(path):
path = str(path)
path = path.lstrip('/').lstrip('\\')
if '/' in path and (('\\' in path and path.find('/') < path.find('\\'))
or '\\' not in path):
return path.split('/', 1)
elif '\\' in path:
return path.split('\\', 1)
else:
return path, ''
def has_leading_dir(paths):
"""Returns true if all the paths have the same leading path name
(i.e., everything is in one subdirectory in an archive)"""
common_prefix = None
for path in paths:
prefix, rest = split_leading_dir(path)
if not prefix:
return False
elif common_prefix is None:
common_prefix = prefix
elif prefix != common_prefix:
return False
return True
def untar_file(filename, location):
if not os.path.exists(location):
os.makedirs(location)
if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'):
mode = 'r:gz'
elif filename.lower().endswith('.bz2') or filename.lower().endswith('.tbz'):
mode = 'r:bz2'
elif filename.lower().endswith('.tar'):
mode = 'r'
else:
logger.error('Cannot determine compression type for file %s' % filename)
mode = 'r:*'
tar = tarfile.open(filename, mode)
try:
# note: python<=2.5 doesnt seem to know about pax headers, filter them
leading = has_leading_dir([
member.name for member in tar.getmembers()
if member.name != 'pax_global_header'
])
for member in tar.getmembers():
fn = member.name
if fn == 'pax_global_header':
continue
if leading:
fn = split_leading_dir(fn)[1]
path = os.path.join(location, fn)
if member.isdir():
if not os.path.exists(path):
os.makedirs(path)
else:
try:
fp = tar.extractfile(member)
except (KeyError, AttributeError):
e = sys.exc_info()[1]
# Some corrupt tar files seem to produce this
# (specifically bad symlinks)
logger.error('In the tar file %s the member %s is invalid: %s'
% (filename, member.name, e))
continue
if not os.path.exists(os.path.dirname(path)):
os.makedirs(os.path.dirname(path))
destfp = open(path, 'wb')
try:
shutil.copyfileobj(fp, destfp)
finally:
destfp.close()
fp.close()
# note: configure ...etc
os.chmod(path, member.mode)
# note: the file timestamps should be such that asdl_c.py is not invoked.
os.utime(path, (member.mtime, member.mtime))
finally:
tar.close()
def extract_downloadfile(content_type, download_file, target_dir):
logger.info("Extracting %s into %s" % (os.path.basename(download_file), target_dir))
if is_gzip(content_type, download_file):
untar_file(download_file, target_dir)
else:
logger.error("Cannot determine archive format of %s" % download_file)
return False
return True
def get_command_path(command):
p = subprocess.Popen('command -v %s' % command, stdout=subprocess.PIPE, shell=True)
return to_str(p.communicate()[0].strip())
def get_using_python_path():
return get_command_path('python')
def get_using_python_pkgname():
"""return: Python-<VERSION> or None"""
path = get_using_python_path()
for d in sorted(os.listdir(PATH_PYTHONS)):
if not os.path.exists(os.path.join(PATH_PYTHONS, d, 'bin','python')):
continue
if path and os.path.samefile(path, os.path.join(PATH_PYTHONS, d, 'bin','python')):
return d
return None
def get_installed_pythons_pkgname():
"""Get the installed python versions list."""
return [d for d in sorted(os.listdir(PATH_PYTHONS))]
def is_installed(name):
pkgname = Package(name).name
pkgdir = os.path.join(PATH_PYTHONS, pkgname)
if not os.path.isdir(pkgdir):
return False
return True
def set_current_path(path):
fp = open(PATH_HOME_ETC_CURRENT, 'w')
fp.write('PATH_PYTHONBREW_CURRENT="%s"\n' % (path))
fp.close()
def path_to_fileurl(path):
path = os.path.normcase(os.path.abspath(path))
url = urllib.quote(path)
url = url.replace(os.path.sep, '/')
url = url.lstrip('/')
return 'file:///' + url
def fileurl_to_path(url):
assert url.startswith('file:'), ('Illegal scheme:%s' % url)
url = '/' + url[len('file:'):].lstrip('/')
return urllib.unquote(url)
def to_str(val):
try:
# python3
if type(val) is bytes:
return val.decode()
except:
if type(val) is unicode:
return val.encode("utf-8")
return val
def is_str(val):
try:
# python2
return isinstance(val, basestring)
except:
# python3
return isinstance(val, str)
return False
def is_sequence(val):
if is_str(val):
return False
return (hasattr(val, "__getitem__") or hasattr(val, "__iter__"))
def bltin_any(iter):
try:
return any(iter)
except:
# python2.4
for it in iter:
if it:
return True
return False
#-----------------------------
# class
#-----------------------------
class Subprocess(object):
def __init__(self, log=None, cwd=None, verbose=False, debug=False):
self._log = log
self._cwd = cwd
self._verbose = verbose
self._debug = debug
def chdir(self, cwd):
self._cwd = cwd
def shell(self, cmd):
if self._debug:
logger.log(cmd)
if is_sequence(cmd):
cmd = ''.join(cmd)
if self._log:
if self._verbose:
cmd = "(%s) 2>&1 | tee '%s'" % (cmd, self._log)
else:
cmd = "(%s) >> '%s' 2>&1" % (cmd, self._log)
returncode = subprocess.call(cmd, shell=True, cwd=self._cwd)
if returncode:
raise ShellCommandException('%s: failed to `%s`' % (returncode, cmd))
def call(self, cmd):
if is_str(cmd):
cmd = shlex.split(cmd)
if self._debug:
logger.log(cmd)
fp = ((self._log and open(self._log, 'a')) or None)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self._cwd)
while p.returncode is None:
while bltin_any(select.select([p.stdout], [], [])):
line = to_str(p.stdout.readline())
if not line:
break
if self._verbose:
logger.log(line.strip())
if fp:
fp.write(line)
fp.flush()
p.poll()
if fp:
fp.close()
return p.returncode
def check_call(self, cmd):
returncode = self.call(cmd)
if returncode:
raise ShellCommandException('%s: failed to `%s`' % (returncode, cmd))
class Package(object):
def __init__(self, name, alias=None):
self.name = None
self.version = None
self.alias = None
if is_archive_file(name):
name = splitext(name)[0]
m = re.search("^Python-(.*)$", name)
if m:
self.name = name
self.version = self.alias = m.group(1)
else:
self.name = "Python-%s" % name
self.version = self.alias = name
if alias:
self.name = 'Python-%s' % alias
self.alias = alias
class Link(object):
def __init__(self, url):
self._url = url
@property
def filename(self):
url = self._url
url = url.split('#', 1)[0]
url = url.split('?', 1)[0]
url = url.rstrip('/')
name = posixpath.basename(url)
assert name, ('URL %r produced no filename' % url)
return name
@property
def base_url(self):
return posixpath.basename(self._url.split('#', 1)[0].split('?', 1)[0])
class Version(object):
"""version compare
"""
def __init__(self, v):
self._version = v
self._p = self._parse_version(v)
def __lt__(self, o):
if is_str(o):
o = self._parse_version(o)
return self._p < o
def __le__(self, o):
if is_str(o):
o = self._parse_version(o)
return self._p <= o
def __eq__(self, o):
if is_str(o):
o = self._parse_version(o)
return self._p == o
def __ne__(self, o):
if is_str(o):
o = self._parse_version(o)
return self._p != o
def __gt__(self, o):
if is_str(o):
o = self._parse_version(o)
return self._p > o
def __ge__(self, o):
if is_str(o):
o = self._parse_version(o)
return self._p >= o
def _parse_version(self, s):
"""see pkg_resouce.parse_version
"""
component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c','dev':'@'}.get
def _parse_version_parts(s):
for part in component_re.split(s):
part = replace(part,part)
if not part or part=='.':
continue
if part[:1] in '0123456789':
yield part.zfill(8) # pad for numeric comparison
else:
yield '*'+part
yield '*final' # ensure that alpha/beta/candidate are before final
parts = []
for part in _parse_version_parts(s.lower()):
if part.startswith('*'):
if part<'*final': # remove '-' before a prerelease tag
while parts and parts[-1]=='*final-': parts.pop()
# remove trailing zeros from each series of numeric parts
while parts and parts[-1]=='00000000':
parts.pop()
parts.append(part)
return tuple(parts)
def __repr__(self):
return self._version
+25
View File
@@ -0,0 +1,25 @@
from pythonbrew.installer import install_pythonbrew, upgrade_pythonbrew, systemwide_pythonbrew
from optparse import OptionParser
if __name__ == "__main__":
parser = OptionParser()
parser.add_option(
'-U', '--upgrade',
dest="upgrade",
action="store_true",
default=False,
help="Upgrade."
)
parser.add_option(
'--systemwide',
dest="systemwide",
action="store_true",
default=False,
help="systemwide install."
)
(opt, arg) = parser.parse_args()
if opt.systemwide:
systemwide_pythonbrew()
elif opt.upgrade:
upgrade_pythonbrew()
else:
install_pythonbrew()
Executable
+35
View File
@@ -0,0 +1,35 @@
import os
from setuptools import setup, find_packages
from pythonbrew.define import VERSION
README = os.path.join(os.path.dirname(__file__),'PKG-INFO')
long_description = open(README).read() + "\n"
setup(name='pythonbrew',
version=VERSION,
description="Manage python installations in your $HOME",
long_description=long_description,
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Topic :: Software Development :: Build Tools',
'Programming Language :: Python :: 2.4',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2',
],
keywords='pythonbrew pip easy_install distutils setuptools virtualenv',
author='utahta',
author_email='labs.ninxit@gmail.com',
url='https://github.com/utahta/pythonbrew',
license='MIT',
packages=find_packages(),
include_package_data=True,
entry_points=dict(console_scripts=['pythonbrew_install=pythonbrew.installer:install_pythonbrew']),
test_suite='nose.collector',
tests_require=['nose'],
zip_safe=False)
+1
View File
@@ -0,0 +1 @@
1.1
View File
-5
View File
@@ -1,5 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
def test_dummy():
pass
+138
View File
@@ -0,0 +1,138 @@
# coding=utf-8
#---------------------------------------------------------------------------
# Copyright 2011 utahta
#---------------------------------------------------------------------------
import os
import shutil
#---------------------------------------------------------------------------
# Settings
#---------------------------------------------------------------------------
PYTHONBREW_ROOT = '/tmp/pythonbrew.test'
TESTPY_VERSION = ['2.4.6', '2.5.5', '2.6.6', '3.2']
def _cleanall():
if os.path.isdir(PYTHONBREW_ROOT):
shutil.rmtree(PYTHONBREW_ROOT)
def _install_pythonbrew():
from pythonbrew.installer import install_pythonbrew
install_pythonbrew()
def setup():
os.environ['PYTHONBREW_ROOT'] = PYTHONBREW_ROOT
_cleanall()
_install_pythonbrew()
def teardown():
_cleanall()
class Options(object):
def __init__(self, opts):
for (k,v) in opts.items():
setattr(self, k, v)
#---------------------------------------------------------------------------
# Test
#---------------------------------------------------------------------------
def test_00_update():
from pythonbrew.commands.update import UpdateCommand
c = UpdateCommand()
c.run_command(Options({'master':False, 'develop':False, 'config':False, 'force':False}),
None)
def test_01_help():
from pythonbrew.commands.help import HelpCommand
c = HelpCommand()
c.run_command(None, None)
def test_02_version():
from pythonbrew.commands.version import VersionCommand
c = VersionCommand()
c.run_command(None, None)
def test_03_install():
from pythonbrew.commands.install import InstallCommand
py_version = TESTPY_VERSION.pop(0)
o = Options({'force':True, 'no_test':True, 'verbose':False, 'configure':"",
'no_setuptools': False, 'alias':None, 'jobs':2,
'framework':False, 'universal':False, 'static':False})
c = InstallCommand()
c.run_command(o, [py_version]) # pybrew install -f -j2 2.4.6
c.run_command(o, TESTPY_VERSION) # pybrew install -f -j2 2.5.6 2.6.6 3.2
def test_04_switch():
from pythonbrew.commands.switch import SwitchCommand
for py_version in TESTPY_VERSION:
c = SwitchCommand()
c.run_command(None, [py_version])
def test_05_use():
from pythonbrew.commands.use import UseCommand
for py_version in TESTPY_VERSION:
c = UseCommand()
c.run_command(None, [py_version])
def test_06_off():
from pythonbrew.commands.off import OffCommand
c = OffCommand()
c.run_command(None, None)
def test_07_list():
from pythonbrew.commands.list import ListCommand
c = ListCommand()
c.run_command(Options({'all_versions':False, 'known':False}),
None)
def test_08_py():
from pythonbrew.commands.py import PyCommand
TESTPY_FILE = os.path.join(PYTHONBREW_ROOT, 'etc', 'testfile.py')
fp = open(TESTPY_FILE, 'w')
fp.write("print('test')")
fp.close()
# Runs the python script
c = PyCommand()
c.run_command(Options({'pythons':[], 'verbose':False, 'bin':"python", 'options':""}),
[TESTPY_FILE])
def test_09_buildout():
from pythonbrew.commands.buildout import BuildoutCommand
BUILDOUT_DIR = os.path.join(PYTHONBREW_ROOT, 'etc', 'buildout')
BUILDOUT_CONF = os.path.join(BUILDOUT_DIR, 'buildout.cfg')
if not os.path.isdir(BUILDOUT_DIR):
os.makedirs(BUILDOUT_DIR)
fp = open(BUILDOUT_CONF, 'w')
fp.write("""[buildout]
parts = test
develop =
[test]
recipe =
eggs =""")
fp.close()
# Runs the buildout
os.chdir(BUILDOUT_DIR)
c = BuildoutCommand()
c.run_command(Options({'python':'2.6.6'}), [])
def test_10_venv():
from pythonbrew.commands.venv import VenvCommand
c = VenvCommand()
o = Options({'python':'2.6.6', 'all':False, 'no_site_packages':False})
c.run_command(o, ['init'])
c.run_command(o, ['create', 'aaa'])
c.run_command(o, ['list'])
c.run_command(o, ['use', 'aaa'])
c.run_command(o, ['delete', 'aaa'])
def test_11_uninstall():
from pythonbrew.commands.uninstall import UninstallCommand
for py_version in TESTPY_VERSION:
c = UninstallCommand()
c.run_command(None, [py_version])
def test_12_clean():
from pythonbrew.commands.cleanup import CleanupCommand
c = CleanupCommand()
c.run_command(None, None)