├── .gitignore ├── MANIFEST.in ├── README.rst ├── TODO.rst ├── garbage ├── inherit │ ├── a │ ├── b │ ├── c │ └── d ├── little-py │ └── PY │ │ ├── pythonrc.py │ │ ├── rvirtualenvinstall.egg-info │ │ ├── PKG-INFO │ │ └── entry_points.txt │ │ ├── rvirtualenvinstall │ │ ├── __init__.py │ │ ├── boot.py │ │ ├── develop.py │ │ ├── install.py │ │ └── scheme.py │ │ └── site.py ├── notes ├── schemes │ ├── install.linux.py27.normal.txt │ ├── install.linux.py27.prefixed.txt │ ├── install.macosmini.py26.normal.txt │ ├── install.macosmini.py26.prefixed.txt │ ├── install.macossrv.py25.normal.txt │ ├── install.macossrv.py25.prefixed.txt │ ├── install.py │ ├── install.sh │ ├── install.win.py26.normal.txt │ └── install.win.py26.prefixed.txt └── sysconfig │ ├── sysconfig27.py │ └── sysconfig32.py ├── rvirtualenv.py ├── rvirtualenv ├── __init__.py ├── copy.py ├── generate.py ├── rvirtualenvinstall │ ├── __init__.py │ ├── boot.py │ ├── develop.py │ ├── install.py │ └── scheme.py └── template │ ├── inst │ ├── bin │ │ ├── activate │ │ ├── activate.bat │ │ ├── activate.bat.template │ │ ├── activate.py │ │ ├── activate.template │ │ ├── deactivate.bat │ │ ├── deactivate.bat.template │ │ ├── getpythondist.py │ │ ├── python │ │ ├── python.bat │ │ └── python.py │ ├── rvirtualenvkeep.py │ └── setup.py │ └── venv │ ├── pythonrc.py │ ├── rvirtualenvinstall.egg-info │ ├── PKG-INFO │ └── entry_points.txt │ └── site.py ├── setup.py └── tests ├── __init__.py ├── helpers.py ├── installs ├── venvtest-distutils │ ├── setup.py │ └── venvtest.py └── venvtest-setuptools │ ├── setup.py │ └── venvtest.py ├── scripts └── print.py ├── test_all.py ├── test_copy.py ├── test_generate.py └── test_rvirtualenv.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | .*.sw? 3 | *~ 4 | 5 | /tests/installs/venvtest-distutils/build/ 6 | /tests/installs/venvtest-setuptools/VEnvTest.egg-info/ 7 | /tests/installs/venvtest-setuptools/build/ 8 | /tests/installs/venvtest-setuptools/dist/ 9 | 10 | pokus.* 11 | 12 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include rvirtualenv * 2 | global-exclude *.py[co] 3 | include README.rst TODO.rst 4 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ====================================== 2 | relocatable python virtual environment 3 | ====================================== 4 | 5 | package inspired a lot by ian bicking's virtualenv_ but created in fashion 6 | that it can be relocated freely through the filesystem, renamed, backuped, ... 7 | 8 | .. _virtualenv: http://bitbucket.org/ianb/virtualenv/ 9 | 10 | second nice feature is, that you can customize your python environment 11 | via ``{{ENV}}/pythonrc.py`` in any curious way you want. 12 | 13 | works with python3, pypy 14 | 15 | install 16 | ------- 17 | 18 | you can `install this package from pypi`_:: 19 | 20 | pip install RVirtualEnv 21 | 22 | # or 23 | easy_install RVirtualEnv 24 | 25 | # or just clone this repository 26 | git clone http://github.com/kvbik/rvirtualenv 27 | 28 | you should definitely `try development version`__ 29 | 30 | .. _install this package from pypi: http://pypi.python.org/pypi/RVirtualEnv 31 | 32 | __ development_ 33 | 34 | to create new virtual environment just call:: 35 | 36 | rvirtualenv ~/PYENV1 37 | 38 | # or directly from this repo 39 | 40 | ./rvirtualenv.py ~/PYENV2 41 | 42 | usage 43 | ----- 44 | 45 | to enable environment, do:: 46 | 47 | # on unix 48 | export PYTHONPATH=~/PYENV1:$PYTHONPATH 49 | 50 | # on windows 51 | set PYTHONPATH=c:\PYENV1;%PYTHONPATH% 52 | 53 | after that, you can call any python command (eg: ``pip`` or ``easy_install``, ``ipython``, ...) 54 | and it will have access to your virtual environment. 55 | 56 | if you don't want to mess up with environment, just call our wrapper:: 57 | 58 | # on unix 59 | ~/PYENV1/bin/python [any [params]] 60 | 61 | # on win 62 | c:\PYENV1\bin\python.bat [any [params]] 63 | 64 | it should work with mod-wsgi ``python-path`` option as well, 65 | and you can enable it in runtime via ``site.addsitedir(venv_directory)``. 66 | 67 | tests 68 | ----- 69 | 70 | if you are interested in testing this package, it should support many standard ways of running tests. 71 | nose is used for test discovery. 72 | 73 | you can run any of these commands: 74 | 75 | * ``python setup.py test`` 76 | * ``nosetests`` 77 | * ``./tests/test_all.py`` 78 | 79 | package was tested on: 80 | 81 | * archlinux with python 3.2 82 | * archlinux with python 2.7 83 | * macosx 10.6 python 2.6 84 | * ms windows with python 2.6 85 | * ubuntu 10.04 python 2.6 86 | * debian lenny with python 2.5 87 | * debian etch with python 2.4 88 | 89 | but there is no build environment yet. 90 | 91 | why 92 | --- 93 | 94 | main reasons why this package came into existence: 95 | 96 | * it does not copy python binary 97 | * it does not symlink core python libraries 98 | * you can just set up PYTHONPATH env variable 99 | and you can use any system-wide command (eg: easy_install, pip) 100 | * you can tune ``pythonrc.py`` file to your needs 101 | in any curious ways (useful for debugging/testing) 102 | 103 | todo 104 | ---- 105 | 106 | you can use the `issue tracker`__ for more (or in `TODO.rst` in this repo) 107 | but some of the long term goals are here 108 | 109 | * test building and installing some c extension 110 | * test install tools (``pip``, ``easy_install`` and others) 111 | * better virtualenv inheritance 112 | (and handle more virtualenvs defined on ``pythonpath``) 113 | 114 | __ https://github.com/kvbik/rvirtualenv/issues 115 | 116 | development 117 | ----------- 118 | 119 | see http://github.com/kvbik/rvirtualenv 120 | 121 | changelog 122 | --------- 123 | 124 | 0.3.x 125 | ~~~~~ 126 | 127 | aka branch `releases/rvirtualenv-0.3`__ 128 | 129 | __ https://github.com/kvbik/rvirtualenv/tree/releases/rvirtualenv-0.3 130 | 131 | 0.3.2 132 | ~~~~~ 133 | 134 | * sorry, this version does not work in interactive mode on windows, we will try hard to 135 | solve bill's issue 136 | * a subprocess call in ``python.py`` replaced with ``os.execvp``, which means less forks 137 | and `gunicorn`_ via `supervisor`_ should work when called via our ``python`` wrapper 138 | (see `issue #2`_ for more) 139 | * system-wide installed rvirtualenv does work and creates virtualenvs correctly 140 | - there were issues with read only fs for non privileged users 141 | * repository cleanup before `upload to pypi`_, so it should be installable 142 | (without any notes from build env - like ``#!/usr/bin/python2`` in `issue #1`_) 143 | * `setuptools_dummy`_ replaced in favour of plain `MANIFEST.in`_ 144 | 145 | .. _setuptools_dummy: http://pypi.python.org/pypi/setuptools_dummy/ 146 | .. _MANIFEST.in: http://docs.python.org/distutils/sourcedist.html#the-manifest-in-template 147 | .. _upload to pypi: http://pypi.python.org/pypi/RVirtualEnv 148 | .. _issue #1: https://github.com/kvbik/rvirtualenv/issues/1 149 | .. _gunicorn: http://gunicorn.org/ 150 | .. _supervisor: http://supervisord.org/ 151 | .. _issue #2: https://github.com/kvbik/rvirtualenv/pull/2 152 | 153 | 0.3.1 154 | ~~~~~ 155 | 156 | * implemented cmd-line virtualenv compatible options 157 | (``--no-site-packages``, ``--python``, ``--prompt``) 158 | * no site packages option for pythonrc 159 | * non python data installed to python package (fixed bug introduced in `0.3.0`_) 160 | 161 | 0.3.0 162 | ~~~~~ 163 | 164 | * `python3`_ support - it really works, tests are passing 165 | * support for `virtualenv wrapper`_ (via: ``source PY/bin/activate``) 166 | * inherit one virtualenv to another 167 | * ``bin/activate`` works, also on windows and relocatable 168 | * complete rewrite of venv 169 | * custom install command so you can define your own layout 170 | * proper functionality on macos and ubuntu 171 | 172 | .. _virtualenv wrapper: http://www.doughellmann.com/projects/virtualenvwrapper/ 173 | .. _python3: http://diveintopython3.org/ 174 | 175 | 0.2.x 176 | ~~~~~ 177 | 178 | aka branch `releases/rvirtualenv-0.2`__ 179 | 180 | __ https://github.com/kvbik/rvirtualenv/tree/releases/rvirtualenv-0.2 181 | 182 | * installing extensions into virtual environment works 183 | * not released, but merged to 0.3 184 | 185 | 0.2.3 186 | ~~~~~ 187 | 188 | * fixing problems with relative path when creating virtualenv 189 | * more compatibility with pip and uninstalling system packages (``sys.real_prefix``) 190 | * tests passing with distribute_ (aka setuptools_ fork) 191 | 192 | .. _distribute: http://bitbucket.org/tarek/distribute/ 193 | .. _setuptools: http://pypi.python.org/pypi/setuptools 194 | 195 | 0.2.2 196 | ~~~~~ 197 | 198 | initial versions (<=0.2.2) 199 | 200 | -------------------------------------------------------------------------------- /TODO.rst: -------------------------------------------------------------------------------- 1 | 2 | some more todos 3 | --------------- 4 | 5 | * do not fork so many processes, try to exec script in python 6 | something like ``python -c '__file__="neco.py"; execfile("neco.py")'`` (eg in ``pip/req.py``) 7 | 8 | * find the difference between pip installed and setup.py installed rvirtualenv - 9 | - all the \*.py files are executable in the second case on debian etch 10 | probably some distribute (setuptools fork) behaviour 11 | 12 | * add logging 13 | 14 | * clean up ``run_command`` (in ``rvirtualenv``, ``tests.test_rvirtualenv``) 15 | and use it for ``rvirtualenv.generate.run_setup`` 16 | 17 | * once ``distutils.install`` command is monkey-patched, 18 | do the same for ``setuptools.develop`` 19 | 20 | * run_command cleanup and tests 21 | test run_command 22 | use run_command from rvirtualenv in tests 23 | generate.run_setup VS run_command 24 | 25 | * use os.pathsep variable in python.py 26 | 27 | * virtualenv inheritance 28 | if you create one venv inside another it should take precedence 29 | not ready yet, try:: 30 | 31 | ./rvirtualenv.py PY1 32 | source PY1/bin/activate 33 | ./rvirtualenv.py PY2 34 | ./PY2/bin/python -c "import rvirtualenvkeep; print(rvirtualenvkeep.__file__)" 35 | 36 | it should return rvirtualenvkeep from PY2 37 | .. i repaired this one, but sys.path is ugly sometimes now.. 38 | 39 | * investigate and improve site.py execution 40 | 41 | -------------------------------------------------------------------------------- /garbage/inherit/a: -------------------------------------------------------------------------------- 1 | prazdny python 2 | 3 | /usr/lib/python27.zip 4 | /usr/lib/python2.7 5 | /usr/lib/python2.7/plat-linux2 6 | /usr/lib/python2.7/lib-tk 7 | /usr/lib/python2.7/lib-old 8 | /usr/lib/python2.7/lib-dynload 9 | /usr/lib/python2.7/site-packages 10 | /usr/lib/python2.7/site-packages/setuptools-0.6c11.egg-info 11 | 12 | -------------------------------------------------------------------------------- /garbage/inherit/b: -------------------------------------------------------------------------------- 1 | aktivovany python1 2 | 3 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY1/lib/python2.7/site-packages 4 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY1 5 | /home/kvbik/GIT/github/kvbik/rvirtualenv 6 | /usr/lib/python27.zip 7 | /usr/lib/python2.7 8 | /usr/lib/python2.7/plat-linux2 9 | /usr/lib/python2.7/lib-tk 10 | /usr/lib/python2.7/lib-old 11 | /usr/lib/python2.7/lib-dynload 12 | /usr/lib/python2.7/site-packages 13 | /usr/lib/python2.7/site-packages/setuptools-0.6c11.egg-info 14 | 15 | -------------------------------------------------------------------------------- /garbage/inherit/c: -------------------------------------------------------------------------------- 1 | pysteny python2 z aktivovaneho python1 2 | 3 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY2/lib/python2.7/site-packages 4 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY1/lib/python2.7/site-packages 5 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY2 6 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY1 7 | /home/kvbik/GIT/github/kvbik/rvirtualenv 8 | /usr/lib/python27.zip 9 | /usr/lib/python2.7 10 | /usr/lib/python2.7/plat-linux2 11 | /usr/lib/python2.7/lib-tk 12 | /usr/lib/python2.7/lib-old 13 | /usr/lib/python2.7/lib-dynload 14 | /usr/lib/python2.7/site-packages 15 | /usr/lib/python2.7/site-packages/setuptools-0.6c11.egg-info 16 | 17 | -------------------------------------------------------------------------------- /garbage/inherit/d: -------------------------------------------------------------------------------- 1 | python2 bez aktivovaneho python1 2 | 3 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY1 4 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY2 5 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY2/lib/python2.7/site-packages 6 | /home/kvbik/GIT/github/kvbik/rvirtualenv 7 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY1/lib/python2.7/site-packages 8 | /home/kvbik/GIT/github/kvbik/rvirtualenv/PY1 9 | /usr/lib/python27.zip 10 | /usr/lib/python2.7 11 | /usr/lib/python2.7/plat-linux2 12 | /usr/lib/python2.7/lib-tk 13 | /usr/lib/python2.7/lib-old 14 | /usr/lib/python2.7/lib-dynload 15 | /usr/lib/python2.7/site-packages 16 | /usr/lib/python2.7/site-packages/setuptools-0.6c11.egg-info 17 | 18 | -------------------------------------------------------------------------------- /garbage/little-py/PY/pythonrc.py: -------------------------------------------------------------------------------- 1 | 2 | scheme = 'unix' 3 | #extra_paths = ['/path/to/inheriting/site-packages/',] # add some if you need access to other venvs 4 | 5 | -------------------------------------------------------------------------------- /garbage/little-py/PY/rvirtualenvinstall.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: rvirtualenvinstall 3 | Version: 0.1 4 | Summary: UNKNOWN 5 | Home-page: UNKNOWN 6 | Author: UNKNOWN 7 | Author-email: UNKNOWN 8 | License: UNKNOWN 9 | Description: UNKNOWN 10 | Platform: UNKNOWN 11 | -------------------------------------------------------------------------------- /garbage/little-py/PY/rvirtualenvinstall.egg-info/entry_points.txt: -------------------------------------------------------------------------------- 1 | [distutils.commands] 2 | install = rvirtualenvinstall.install:install 3 | developp = rvirtualenvinstall.develop:develop 4 | -------------------------------------------------------------------------------- /garbage/little-py/PY/rvirtualenvinstall/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvbik/rvirtualenv/aaacde2171144bc3c1d8ab8668e36a0dbc29bf3d/garbage/little-py/PY/rvirtualenvinstall/__init__.py -------------------------------------------------------------------------------- /garbage/little-py/PY/rvirtualenvinstall/boot.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import path 3 | 4 | import rvirtualenvinstall.install 5 | from rvirtualenvinstall import scheme 6 | import pythonrc 7 | 8 | base = path.abspath(path.dirname(pythonrc.__file__)) 9 | 10 | # real_prefix is useful for pip and uninstalling system pkgs 11 | sys.real_prefix = sys.prefix 12 | # python uses this almost everywhere 13 | sys.prefix = base 14 | 15 | this_site_packages = [ 16 | scheme.get_scheme(pythonrc.scheme, 'purelib'), 17 | scheme.get_scheme(pythonrc.scheme, 'platlib'), 18 | ] 19 | 20 | scheme.add_to_path(getattr(pythonrc, 'extra_paths', [])) 21 | scheme.add_to_path(this_site_packages) 22 | 23 | -------------------------------------------------------------------------------- /garbage/little-py/PY/rvirtualenvinstall/develop.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | from setuptools.command.develop import develop as _develop 3 | 4 | 5 | class develop(_develop): 6 | description = "rvirtualenv's %s" % _develop.description 7 | def run(self): 8 | print('WTF') 9 | 10 | # don't know why isn't it overriden by entry_points 11 | setuptools.command.develop.develop = develop 12 | 13 | -------------------------------------------------------------------------------- /garbage/little-py/PY/rvirtualenvinstall/install.py: -------------------------------------------------------------------------------- 1 | import distutils 2 | from distutils.command.install import install as _install 3 | 4 | import pythonrc 5 | from rvirtualenvinstall import scheme 6 | 7 | 8 | class install(_install): 9 | description = "rvirtualenv's %s" % _install.description 10 | def finalize_options(self): 11 | _install.finalize_options(self) 12 | 13 | vars = {'dist_name': self.distribution.get_name(),} 14 | self.install_purelib = scheme.get_scheme(pythonrc.scheme, 'purelib') 15 | self.install_platlib = scheme.get_scheme(pythonrc.scheme, 'purelib') 16 | self.install_headers = scheme.get_scheme(pythonrc.scheme, 'headers', vars=vars) 17 | self.install_scripts = scheme.get_scheme(pythonrc.scheme, 'scripts') 18 | self.install_data = scheme.get_scheme(pythonrc.scheme, 'data') 19 | 20 | if self.distribution.ext_modules: # has extensions: non-pure 21 | self.install_lib = self.install_platlib 22 | else: 23 | self.install_lib = self.install_purelib 24 | 25 | # monkey patch for distutils 26 | distutils.command.install.install = install 27 | 28 | -------------------------------------------------------------------------------- /garbage/little-py/PY/rvirtualenvinstall/scheme.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import path 3 | import site 4 | from distutils.util import subst_vars 5 | 6 | INSTALL_SCHEMES = { 7 | 'custom': { 8 | 'purelib': '$base/lib/python/site-packages', 9 | 'platlib': '$base/lib/python$py_version_short/site-packages', 10 | 'headers': '$base/include/python$py_version_short/$dist_name', 11 | 'scripts': '$base/bin', 12 | 'data' : '$base', 13 | }, 14 | 'unix': { 15 | 'purelib': '$base/lib/python$py_version_short/site-packages', 16 | 'platlib': '$base/lib/python$py_version_short/site-packages', 17 | 'headers': '$base/include/python$py_version_short/$dist_name', 18 | 'scripts': '$base/bin', 19 | 'data' : '$base', 20 | }, 21 | 'windows': { 22 | 'purelib': '$base/Lib/site-packages', 23 | 'platlib': '$base/Lib/site-packages', 24 | 'headers': '$base/Include/$dist_name', 25 | 'scripts': '$base/Scripts', 26 | 'data' : '$base', 27 | }, 28 | 'os2': { 29 | 'purelib': '$base/Lib/site-packages', 30 | 'platlib': '$base/Lib/site-packages', 31 | 'headers': '$base/Include/$dist_name', 32 | 'scripts': '$base/Scripts', 33 | 'data' : '$base', 34 | }, 35 | 'darwin': { 36 | 'purelib': '$base/Library/Python$py_version_short/site-packages', 37 | 'platlib': '$base/Library/Python$py_version_short/site-packages', 38 | 'headers': '$base/Include/$dist_name', 39 | 'scripts': '$base/bin', 40 | 'data' : '$base', 41 | }, 42 | } 43 | 44 | def guess_scheme(): 45 | return 'unix' 46 | 47 | def get_scheme(platform, what, vars={}): 48 | # TODO: maybe use syslinux.get_path in next versions 49 | replace = { 50 | 'base': sys.prefix, 51 | 'py_version_short': sys.version[:3], 52 | 'dist_name': 'UNKNOWN', 53 | } 54 | replace.update(vars) 55 | line = INSTALL_SCHEMES[platform][what] 56 | line = path.join(*line.split('/')) 57 | return subst_vars(line, replace) 58 | 59 | def add_to_path(new_paths): 60 | "add dirs to the beginnig of sys.path" 61 | __plen = len(sys.path) 62 | for i in new_paths: 63 | if i not in sys.path: 64 | site.addsitedir(i) 65 | new = sys.path[__plen:] 66 | del sys.path[__plen:] 67 | sys.path[0:0] = new 68 | 69 | -------------------------------------------------------------------------------- /garbage/little-py/PY/site.py: -------------------------------------------------------------------------------- 1 | def __boot(): 2 | import sys, imp, os, os.path 3 | PYTHONPATH = os.environ.get('PYTHONPATH') 4 | if PYTHONPATH is None or (sys.platform=='win32' and not PYTHONPATH): 5 | PYTHONPATH = [] 6 | else: 7 | PYTHONPATH = PYTHONPATH.split(os.pathsep) 8 | 9 | pic = getattr(sys,'path_importer_cache',{}) 10 | stdpath = sys.path[len(PYTHONPATH):] 11 | mydir = os.path.dirname(__file__) 12 | #print "searching",stdpath,sys.path 13 | 14 | for item in stdpath: 15 | if item==mydir or not item: 16 | continue # skip if current dir. on Windows, or my own directory 17 | importer = pic.get(item) 18 | if importer is not None: 19 | loader = importer.find_module('site') 20 | if loader is not None: 21 | # This should actually reload the current module 22 | loader.load_module('site') 23 | break 24 | else: 25 | try: 26 | stream, path, descr = imp.find_module('site',[item]) 27 | except ImportError: 28 | continue 29 | if stream is None: 30 | continue 31 | try: 32 | # This should actually reload the current module 33 | imp.load_module('site',stream,path,descr) 34 | finally: 35 | stream.close() 36 | break 37 | else: 38 | raise ImportError("Couldn't find the real 'site' module") 39 | 40 | #print "loaded", __file__ 41 | 42 | known_paths = dict([(makepath(item)[1],1) for item in sys.path]) # 2.2 comp 43 | 44 | oldpos = getattr(sys,'__egginsert',0) # save old insertion position 45 | sys.__egginsert = 0 # and reset the current one 46 | 47 | for item in PYTHONPATH: 48 | addsitedir(item) 49 | 50 | sys.__egginsert += oldpos # restore effective old position 51 | 52 | d,nd = makepath(stdpath[0]) 53 | insert_at = None 54 | new_path = [] 55 | 56 | for item in sys.path: 57 | p,np = makepath(item) 58 | 59 | if np==nd and insert_at is None: 60 | # We've hit the first 'system' path entry, so added entries go here 61 | insert_at = len(new_path) 62 | 63 | if np in known_paths or insert_at is None: 64 | new_path.append(item) 65 | else: 66 | # new path after the insert point, back-insert it 67 | new_path.insert(insert_at, item) 68 | insert_at += 1 69 | 70 | sys.path[:] = new_path 71 | 72 | import rvirtualenvinstall.boot 73 | 74 | if __name__=='site': 75 | __boot() 76 | del __boot 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /garbage/notes: -------------------------------------------------------------------------------- 1 | 2 | ------------------------ 3 | 4 | rvirtualenv 5 | ~~~~~~~~~~~ 6 | 7 | vytvorit rvirtualenv.main 8 | presunout kod z __init__ a procistit, aby copy&spol bylo rozumne importovatelne 9 | 10 | rvirtualenv.utils 11 | nasypat tam helpers jako: basepath (rvirtualenv.__file__), is_windows, apod 12 | 13 | nosetests 14 | monkeypatched sys.stdout a encoding 15 | 16 | 17 | ------------------ 18 | 19 | -- zpetne kompatibilni (2 a 3) python kod 20 | http://www.voidspace.org.uk/python/articles/porting-mock-to-python-3.shtml 21 | 22 | mozna by stacilo predat setup.py install --moje-schema 23 | http://docs.python.org/install/index.html 24 | http://stackoverflow.com/questions/1710839/custom-distutils-commands 25 | http://stackoverflow.com/questions/1321270/how-to-extend-distutils-with-a-simple-post-install-script 26 | 27 | grr... 28 | /usr/lib/python3.2/distutils/core.py 29 | /usr/lib/python3.2/distutils/dist.py 30 | /usr/lib/python3.2/distutils/cmd.py 31 | 32 | 33 | -------------------------------- 34 | 35 | -- ve virtualenvu se taky ruzne fidluje s macosem 36 | https://bitbucket.org/ianb/virtualenv/src/204f249efc32/virtualenv_support/site.py#cl-570 37 | 38 | -- jo, jezdezovi to nejde 39 | http://d.pr/pdiK 40 | http://d.pr/FeCk 41 | 42 | -- v djangu taky fidlujou se schematem 43 | http://code.djangoproject.com/browser/django/trunk/setup.py#L39 44 | 45 | -- kez by mi to nekdo spravil.. 46 | https://gist.github.com/709004/ 47 | 48 | -- pak bych se konecne zaradil sem 49 | http://pypi.python.org/pypi?:action=browse&c=533&show=all 50 | 51 | 52 | 53 | .FFFFF.FFF 54 | ====================================================================== 55 | FAIL: test_install_venv_keep_package (tests.test_generate.TestGenerate) 56 | ---------------------------------------------------------------------- 57 | Traceback (most recent call last): 58 | File "/Users/kvbik/GIT/rvirtualenv/tests/test_generate.py", line 33, in test_install_venv_keep_package 59 | self.assertTrue(len(l) > 1) 60 | AssertionError 61 | 62 | 63 | /usr/bin/python -c "import sys; sys.prefix=r'/tmp/keke'; __file__='setup.py'; execfile('setup.py')" install 64 | 65 | /System/Library/Frameworks/Python.framework/Versions/2.5/Resources/Python.app/Contents/MacOS/Python -c "import sys; sys.real_prefix=r'/tmp/keke'; __file__='setup.py'; execfile('setup.py')" install 66 | 67 | 68 | 69 | i = distutils.command.install.install(distutils.core.Distribution()) 70 | i.initialize_options() 71 | i.finalize_options() 72 | 73 | /usr/bin/python -c "import sys; sys.prefix=r'/tmp/keke'; __file__='setup.py'; execfile('setup.py')" install 74 | 75 | 76 | -- asi proste pridam jinej install command do venvu, podobne jako rozbijej tyhlencti upload 77 | http://bazaar.launchpad.net/~python-distutils-extra-hackers/python-distutils-extra/debian/files 78 | http://aur.archlinux.org/packages/python-distutils-extra-bzr/python-distutils-extra-bzr/PKGBUILD 79 | 80 | 81 | -------------------------------------------------------------------------------- /garbage/schemes/install.linux.py27.normal.txt: -------------------------------------------------------------------------------- 1 | install_base: /usr 2 | install_data: /usr 3 | install_headers: /usr/include/python2.7/UNKNOWN 4 | install_lib: /usr/lib/python2.7/site-packages/ 5 | install_libbase: /usr/lib/python2.7/site-packages 6 | install_path_file: 1 7 | install_platbase: /usr 8 | install_platlib: /usr/lib/python2.7/site-packages 9 | install_purelib: /usr/lib/python2.7/site-packages 10 | install_scripts: /usr/bin 11 | install_userbase: /home/kvbik/.local 12 | install_usersite: /home/kvbik/.local/lib/python2.7/site-packages 13 | -------------------------------------------------------------------------------- /garbage/schemes/install.linux.py27.prefixed.txt: -------------------------------------------------------------------------------- 1 | install_base: /tmp/keke 2 | install_data: /tmp/keke 3 | install_headers: /tmp/keke/include/python2.7/UNKNOWN 4 | install_lib: /tmp/keke/lib/python2.7/site-packages/ 5 | install_libbase: /tmp/keke/lib/python2.7/site-packages 6 | install_path_file: 1 7 | install_platbase: /usr 8 | install_platlib: /usr/lib/python2.7/site-packages 9 | install_purelib: /tmp/keke/lib/python2.7/site-packages 10 | install_scripts: /tmp/keke/bin 11 | install_userbase: /home/kvbik/.local 12 | install_usersite: /home/kvbik/.local/lib/python2.7/site-packages 13 | -------------------------------------------------------------------------------- /garbage/schemes/install.macosmini.py26.normal.txt: -------------------------------------------------------------------------------- 1 | install_base: /System/Library/Frameworks/Python.framework/Versions/2.6 2 | install_data: /System/Library/Frameworks/Python.framework/Versions/2.6 3 | install_headers: /System/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6/UNKNOWN 4 | install_lib: /Library/Python/2.6/site-packages/ 5 | install_libbase: /Library/Python/2.6/site-packages 6 | install_path_file: 1 7 | install_platbase: /System/Library/Frameworks/Python.framework/Versions/2.6 8 | install_platlib: /Library/Python/2.6/site-packages 9 | install_purelib: /Library/Python/2.6/site-packages 10 | install_scripts: /usr/local/bin 11 | install_userbase: /Users/jakub.vysoky/.local 12 | install_usersite: /Users/jakub.vysoky/.local/lib/python2.6/site-packages 13 | -------------------------------------------------------------------------------- /garbage/schemes/install.macosmini.py26.prefixed.txt: -------------------------------------------------------------------------------- 1 | install_base: /tmp/keke 2 | install_data: /tmp/keke 3 | install_headers: /tmp/keke/include/python2.6/UNKNOWN 4 | install_lib: /Library/Python/2.6/site-packages/ 5 | install_libbase: /Library/Python/2.6/site-packages 6 | install_path_file: 1 7 | install_platbase: /System/Library/Frameworks/Python.framework/Versions/2.6 8 | install_platlib: /System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages 9 | install_purelib: /Library/Python/2.6/site-packages 10 | install_scripts: /usr/local/bin 11 | install_userbase: /Users/jakub.vysoky/.local 12 | install_usersite: /Users/jakub.vysoky/.local/lib/python2.6/site-packages 13 | -------------------------------------------------------------------------------- /garbage/schemes/install.macossrv.py25.normal.txt: -------------------------------------------------------------------------------- 1 | install_base: /System/Library/Frameworks/Python.framework/Versions/2.5 2 | install_data: /System/Library/Frameworks/Python.framework/Versions/2.5 3 | install_headers: /System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5/UNKNOWN 4 | install_lib: /Library/Python/2.5/site-packages/ 5 | install_libbase: /Library/Python/2.5/site-packages 6 | install_path_file: 1 7 | install_platbase: /System/Library/Frameworks/Python.framework/Versions/2.5 8 | install_platlib: /Library/Python/2.5/site-packages 9 | install_purelib: /Library/Python/2.5/site-packages 10 | install_scripts: /usr/local/bin 11 | -------------------------------------------------------------------------------- /garbage/schemes/install.macossrv.py25.prefixed.txt: -------------------------------------------------------------------------------- 1 | install_base: /tmp/keke 2 | install_data: /tmp/keke 3 | install_headers: /tmp/keke/include/python2.5/UNKNOWN 4 | install_lib: /Library/Python/2.5/site-packages/ 5 | install_libbase: /Library/Python/2.5/site-packages 6 | install_path_file: 1 7 | install_platbase: /System/Library/Frameworks/Python.framework/Versions/2.5 8 | install_platlib: /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages 9 | install_purelib: /Library/Python/2.5/site-packages 10 | install_scripts: /usr/local/bin 11 | -------------------------------------------------------------------------------- /garbage/schemes/install.py: -------------------------------------------------------------------------------- 1 | 2 | import distutils.command.install 3 | import distutils.core 4 | from distutils import command, core 5 | 6 | i = command.install.install(core.Distribution()) 7 | 8 | i.initialize_options() 9 | i.finalize_options() 10 | 11 | for a in dir(i): 12 | if a.startswith('install_'): 13 | print '%s: %s' % (a, getattr(i, a)) 14 | 15 | -------------------------------------------------------------------------------- /garbage/schemes/install.sh: -------------------------------------------------------------------------------- 1 | 2 | python -c "import sys; sys.prefix=r'/tmp/keke'; __file__='install.py'; execfile('install.py')" 3 | 4 | -------------------------------------------------------------------------------- /garbage/schemes/install.win.py26.normal.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvbik/rvirtualenv/aaacde2171144bc3c1d8ab8668e36a0dbc29bf3d/garbage/schemes/install.win.py26.normal.txt -------------------------------------------------------------------------------- /garbage/schemes/install.win.py26.prefixed.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvbik/rvirtualenv/aaacde2171144bc3c1d8ab8668e36a0dbc29bf3d/garbage/schemes/install.win.py26.prefixed.txt -------------------------------------------------------------------------------- /garbage/sysconfig/sysconfig27.py: -------------------------------------------------------------------------------- 1 | """Provide access to Python's configuration information. 2 | 3 | """ 4 | import sys 5 | import os 6 | from os.path import pardir, realpath 7 | from string import Template 8 | 9 | _INSTALL_SCHEMES = { 10 | 'posix_prefix': { 11 | 'stdlib': '{base}/lib/python{py_version_short}', 12 | 'platstdlib': '{platbase}/lib/python{py_version_short}', 13 | 'purelib': '{base}/lib/python{py_version_short}/site-packages', 14 | 'platlib': '{platbase}/lib/python{py_version_short}/site-packages', 15 | 'include': '{base}/include/python{py_version_short}', 16 | 'platinclude': '{platbase}/include/python{py_version_short}', 17 | 'scripts': '{base}/bin', 18 | 'data': '{base}', 19 | }, 20 | 'posix_home': { 21 | 'stdlib': '{base}/lib/python', 22 | 'platstdlib': '{base}/lib/python', 23 | 'purelib': '{base}/lib/python', 24 | 'platlib': '{base}/lib/python', 25 | 'include': '{base}/include/python', 26 | 'platinclude': '{base}/include/python', 27 | 'scripts': '{base}/bin', 28 | 'data' : '{base}', 29 | }, 30 | 'nt': { 31 | 'stdlib': '{base}/Lib', 32 | 'platstdlib': '{base}/Lib', 33 | 'purelib': '{base}/Lib/site-packages', 34 | 'platlib': '{base}/Lib/site-packages', 35 | 'include': '{base}/Include', 36 | 'platinclude': '{base}/Include', 37 | 'scripts': '{base}/Scripts', 38 | 'data' : '{base}', 39 | }, 40 | 'os2': { 41 | 'stdlib': '{base}/Lib', 42 | 'platstdlib': '{base}/Lib', 43 | 'purelib': '{base}/Lib/site-packages', 44 | 'platlib': '{base}/Lib/site-packages', 45 | 'include': '{base}/Include', 46 | 'platinclude': '{base}/Include', 47 | 'scripts': '{base}/Scripts', 48 | 'data' : '{base}', 49 | }, 50 | 'os2_home': { 51 | 'stdlib': '{userbase}/lib/python{py_version_short}', 52 | 'platstdlib': '{userbase}/lib/python{py_version_short}', 53 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', 54 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', 55 | 'include': '{userbase}/include/python{py_version_short}', 56 | 'scripts': '{userbase}/bin', 57 | 'data' : '{userbase}', 58 | }, 59 | 'nt_user': { 60 | 'stdlib': '{userbase}/Python{py_version_nodot}', 61 | 'platstdlib': '{userbase}/Python{py_version_nodot}', 62 | 'purelib': '{userbase}/Python{py_version_nodot}/site-packages', 63 | 'platlib': '{userbase}/Python{py_version_nodot}/site-packages', 64 | 'include': '{userbase}/Python{py_version_nodot}/Include', 65 | 'scripts': '{userbase}/Scripts', 66 | 'data' : '{userbase}', 67 | }, 68 | 'posix_user': { 69 | 'stdlib': '{userbase}/lib/python{py_version_short}', 70 | 'platstdlib': '{userbase}/lib/python{py_version_short}', 71 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', 72 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', 73 | 'include': '{userbase}/include/python{py_version_short}', 74 | 'scripts': '{userbase}/bin', 75 | 'data' : '{userbase}', 76 | }, 77 | 'osx_framework_user': { 78 | 'stdlib': '{userbase}/lib/python', 79 | 'platstdlib': '{userbase}/lib/python', 80 | 'purelib': '{userbase}/lib/python/site-packages', 81 | 'platlib': '{userbase}/lib/python/site-packages', 82 | 'include': '{userbase}/include', 83 | 'scripts': '{userbase}/bin', 84 | 'data' : '{userbase}', 85 | }, 86 | } 87 | 88 | _SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include', 89 | 'scripts', 'data') 90 | _PY_VERSION = sys.version.split()[0] 91 | _PY_VERSION_SHORT = sys.version[:3] 92 | _PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2] 93 | _PREFIX = os.path.normpath(sys.prefix) 94 | _EXEC_PREFIX = os.path.normpath(sys.exec_prefix) 95 | _CONFIG_VARS = None 96 | _USER_BASE = None 97 | 98 | def _safe_realpath(path): 99 | try: 100 | return realpath(path) 101 | except OSError: 102 | return path 103 | 104 | if sys.executable: 105 | _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) 106 | else: 107 | # sys.executable can be empty if argv[0] has been changed and Python is 108 | # unable to retrieve the real program name 109 | _PROJECT_BASE = _safe_realpath(os.getcwd()) 110 | 111 | if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): 112 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) 113 | # PC/VS7.1 114 | if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): 115 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) 116 | # PC/AMD64 117 | if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): 118 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) 119 | 120 | def is_python_build(): 121 | for fn in ("Setup.dist", "Setup.local"): 122 | if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): 123 | return True 124 | return False 125 | 126 | _PYTHON_BUILD = is_python_build() 127 | 128 | if _PYTHON_BUILD: 129 | for scheme in ('posix_prefix', 'posix_home'): 130 | _INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include' 131 | _INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}' 132 | 133 | def _format_template(s, **kwargs): 134 | if hasattr(s, 'format'): 135 | return s.format(**kwargs) 136 | t = Template(s.replace('{', '${')) 137 | return t.substitute(**kwargs) 138 | 139 | def _subst_vars(s, local_vars): 140 | try: 141 | return _format_template(s, **local_vars) 142 | except KeyError: 143 | try: 144 | return _format_template(s, **os.environ) 145 | except KeyError, var: 146 | raise AttributeError('{%s}' % var) 147 | 148 | def _extend_dict(target_dict, other_dict): 149 | target_keys = target_dict.keys() 150 | for key, value in other_dict.items(): 151 | if key in target_keys: 152 | continue 153 | target_dict[key] = value 154 | 155 | def _expand_vars(scheme, vars): 156 | res = {} 157 | if vars is None: 158 | vars = {} 159 | _extend_dict(vars, get_config_vars()) 160 | 161 | for key, value in _INSTALL_SCHEMES[scheme].items(): 162 | if os.name in ('posix', 'nt'): 163 | value = os.path.expanduser(value) 164 | res[key] = os.path.normpath(_subst_vars(value, vars)) 165 | return res 166 | 167 | def _get_default_scheme(): 168 | if os.name == 'posix': 169 | # the default scheme for posix is posix_prefix 170 | return 'posix_prefix' 171 | return os.name 172 | 173 | def _getuserbase(): 174 | env_base = os.environ.get("PYTHONUSERBASE", None) 175 | def joinuser(*args): 176 | return os.path.expanduser(os.path.join(*args)) 177 | 178 | # what about 'os2emx', 'riscos' ? 179 | if os.name == "nt": 180 | base = os.environ.get("APPDATA") or "~" 181 | return env_base and env_base or joinuser(base, "Python") 182 | 183 | if sys.platform == "darwin": 184 | framework = get_config_var("PYTHONFRAMEWORK") 185 | if framework: 186 | return joinuser("~", "Library", framework, "%d.%d"%( 187 | sys.version_info[:2])) 188 | 189 | return env_base and env_base or joinuser("~", ".local") 190 | 191 | 192 | def _parse_makefile(filename, vars=None): 193 | """Parse a Makefile-style file. 194 | 195 | A dictionary containing name/value pairs is returned. If an 196 | optional dictionary is passed in as the second argument, it is 197 | used instead of a new dictionary. 198 | """ 199 | import re 200 | # Regexes needed for parsing Makefile (and similar syntaxes, 201 | # like old-style Setup files). 202 | _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") 203 | _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") 204 | _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") 205 | 206 | if vars is None: 207 | vars = {} 208 | done = {} 209 | notdone = {} 210 | 211 | f = open(filename) 212 | try: 213 | lines = f.readlines() 214 | finally: 215 | f.close() 216 | 217 | for line in lines: 218 | if line.startswith('#') or line.strip() == '': 219 | continue 220 | m = _variable_rx.match(line) 221 | if m: 222 | n, v = m.group(1, 2) 223 | v = v.strip() 224 | # `$$' is a literal `$' in make 225 | tmpv = v.replace('$$', '') 226 | 227 | if "$" in tmpv: 228 | notdone[n] = v 229 | else: 230 | try: 231 | v = int(v) 232 | except ValueError: 233 | # insert literal `$' 234 | done[n] = v.replace('$$', '$') 235 | else: 236 | done[n] = v 237 | 238 | # do variable interpolation here 239 | while notdone: 240 | for name in notdone.keys(): 241 | value = notdone[name] 242 | m = _findvar1_rx.search(value) or _findvar2_rx.search(value) 243 | if m: 244 | n = m.group(1) 245 | found = True 246 | if n in done: 247 | item = str(done[n]) 248 | elif n in notdone: 249 | # get it on a subsequent round 250 | found = False 251 | elif n in os.environ: 252 | # do it like make: fall back to environment 253 | item = os.environ[n] 254 | else: 255 | done[n] = item = "" 256 | if found: 257 | after = value[m.end():] 258 | value = value[:m.start()] + item + after 259 | if "$" in after: 260 | notdone[name] = value 261 | else: 262 | try: value = int(value) 263 | except ValueError: 264 | done[name] = value.strip() 265 | else: 266 | done[name] = value 267 | del notdone[name] 268 | else: 269 | # bogus variable reference; just drop it since we can't deal 270 | del notdone[name] 271 | # strip spurious spaces 272 | for k, v in done.items(): 273 | if isinstance(v, str): 274 | done[k] = v.strip() 275 | 276 | # save the results in the global dictionary 277 | vars.update(done) 278 | return vars 279 | 280 | 281 | def _get_makefile_filename(): 282 | if _PYTHON_BUILD: 283 | return os.path.join(_PROJECT_BASE, "Makefile") 284 | return os.path.join(get_path('stdlib'), "config", "Makefile") 285 | 286 | 287 | def _init_posix(vars): 288 | """Initialize the module as appropriate for POSIX systems.""" 289 | # load the installed Makefile: 290 | makefile = _get_makefile_filename() 291 | try: 292 | _parse_makefile(makefile, vars) 293 | except IOError, e: 294 | msg = "invalid Python installation: unable to open %s" % makefile 295 | if hasattr(e, "strerror"): 296 | msg = msg + " (%s)" % e.strerror 297 | raise IOError(msg) 298 | 299 | # load the installed pyconfig.h: 300 | config_h = get_config_h_filename() 301 | try: 302 | f = open(config_h) 303 | try: 304 | parse_config_h(f, vars) 305 | finally: 306 | f.close() 307 | except IOError, e: 308 | msg = "invalid Python installation: unable to open %s" % config_h 309 | if hasattr(e, "strerror"): 310 | msg = msg + " (%s)" % e.strerror 311 | raise IOError(msg) 312 | 313 | # On MacOSX we need to check the setting of the environment variable 314 | # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so 315 | # it needs to be compatible. 316 | # If it isn't set we set it to the configure-time value 317 | if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in vars: 318 | cfg_target = vars['MACOSX_DEPLOYMENT_TARGET'] 319 | cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') 320 | if cur_target == '': 321 | cur_target = cfg_target 322 | os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target) 323 | elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')): 324 | msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" ' 325 | 'during configure' % (cur_target, cfg_target)) 326 | raise IOError(msg) 327 | 328 | # On AIX, there are wrong paths to the linker scripts in the Makefile 329 | # -- these paths are relative to the Python source, but when installed 330 | # the scripts are in another directory. 331 | if _PYTHON_BUILD: 332 | vars['LDSHARED'] = vars['BLDSHARED'] 333 | 334 | def _init_non_posix(vars): 335 | """Initialize the module as appropriate for NT""" 336 | # set basic install directories 337 | vars['LIBDEST'] = get_path('stdlib') 338 | vars['BINLIBDEST'] = get_path('platstdlib') 339 | vars['INCLUDEPY'] = get_path('include') 340 | vars['SO'] = '.pyd' 341 | vars['EXE'] = '.exe' 342 | vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT 343 | vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) 344 | 345 | # 346 | # public APIs 347 | # 348 | 349 | 350 | def parse_config_h(fp, vars=None): 351 | """Parse a config.h-style file. 352 | 353 | A dictionary containing name/value pairs is returned. If an 354 | optional dictionary is passed in as the second argument, it is 355 | used instead of a new dictionary. 356 | """ 357 | import re 358 | if vars is None: 359 | vars = {} 360 | define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") 361 | undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") 362 | 363 | while True: 364 | line = fp.readline() 365 | if not line: 366 | break 367 | m = define_rx.match(line) 368 | if m: 369 | n, v = m.group(1, 2) 370 | try: v = int(v) 371 | except ValueError: pass 372 | vars[n] = v 373 | else: 374 | m = undef_rx.match(line) 375 | if m: 376 | vars[m.group(1)] = 0 377 | return vars 378 | 379 | def get_config_h_filename(): 380 | """Returns the path of pyconfig.h.""" 381 | if _PYTHON_BUILD: 382 | if os.name == "nt": 383 | inc_dir = os.path.join(_PROJECT_BASE, "PC") 384 | else: 385 | inc_dir = _PROJECT_BASE 386 | else: 387 | inc_dir = get_path('platinclude') 388 | return os.path.join(inc_dir, 'pyconfig.h') 389 | 390 | def get_scheme_names(): 391 | """Returns a tuple containing the schemes names.""" 392 | schemes = _INSTALL_SCHEMES.keys() 393 | schemes.sort() 394 | return tuple(schemes) 395 | 396 | def get_path_names(): 397 | """Returns a tuple containing the paths names.""" 398 | return _SCHEME_KEYS 399 | 400 | def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): 401 | """Returns a mapping containing an install scheme. 402 | 403 | ``scheme`` is the install scheme name. If not provided, it will 404 | return the default scheme for the current platform. 405 | """ 406 | if expand: 407 | return _expand_vars(scheme, vars) 408 | else: 409 | return _INSTALL_SCHEMES[scheme] 410 | 411 | def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): 412 | """Returns a path corresponding to the scheme. 413 | 414 | ``scheme`` is the install scheme name. 415 | """ 416 | return get_paths(scheme, vars, expand)[name] 417 | 418 | def get_config_vars(*args): 419 | """With no arguments, return a dictionary of all configuration 420 | variables relevant for the current platform. 421 | 422 | On Unix, this means every variable defined in Python's installed Makefile; 423 | On Windows and Mac OS it's a much smaller set. 424 | 425 | With arguments, return a list of values that result from looking up 426 | each argument in the configuration variable dictionary. 427 | """ 428 | import re 429 | global _CONFIG_VARS 430 | if _CONFIG_VARS is None: 431 | _CONFIG_VARS = {} 432 | # Normalized versions of prefix and exec_prefix are handy to have; 433 | # in fact, these are the standard versions used most places in the 434 | # Distutils. 435 | _CONFIG_VARS['prefix'] = _PREFIX 436 | _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX 437 | _CONFIG_VARS['py_version'] = _PY_VERSION 438 | _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT 439 | _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] 440 | _CONFIG_VARS['base'] = _PREFIX 441 | _CONFIG_VARS['platbase'] = _EXEC_PREFIX 442 | _CONFIG_VARS['projectbase'] = _PROJECT_BASE 443 | 444 | if os.name in ('nt', 'os2'): 445 | _init_non_posix(_CONFIG_VARS) 446 | if os.name == 'posix': 447 | _init_posix(_CONFIG_VARS) 448 | 449 | # Setting 'userbase' is done below the call to the 450 | # init function to enable using 'get_config_var' in 451 | # the init-function. 452 | _CONFIG_VARS['userbase'] = _getuserbase() 453 | 454 | if 'srcdir' not in _CONFIG_VARS: 455 | _CONFIG_VARS['srcdir'] = _PROJECT_BASE 456 | 457 | # Convert srcdir into an absolute path if it appears necessary. 458 | # Normally it is relative to the build directory. However, during 459 | # testing, for example, we might be running a non-installed python 460 | # from a different directory. 461 | if _PYTHON_BUILD and os.name == "posix": 462 | base = _PROJECT_BASE 463 | try: 464 | cwd = os.getcwd() 465 | except OSError: 466 | cwd = None 467 | if (not os.path.isabs(_CONFIG_VARS['srcdir']) and 468 | base != cwd): 469 | # srcdir is relative and we are not in the same directory 470 | # as the executable. Assume executable is in the build 471 | # directory and make srcdir absolute. 472 | srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) 473 | _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) 474 | 475 | if sys.platform == 'darwin': 476 | kernel_version = os.uname()[2] # Kernel version (8.4.3) 477 | major_version = int(kernel_version.split('.')[0]) 478 | 479 | if major_version < 8: 480 | # On Mac OS X before 10.4, check if -arch and -isysroot 481 | # are in CFLAGS or LDFLAGS and remove them if they are. 482 | # This is needed when building extensions on a 10.3 system 483 | # using a universal build of python. 484 | for key in ('LDFLAGS', 'BASECFLAGS', 485 | # a number of derived variables. These need to be 486 | # patched up as well. 487 | 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): 488 | flags = _CONFIG_VARS[key] 489 | flags = re.sub('-arch\s+\w+\s', ' ', flags) 490 | flags = re.sub('-isysroot [^ \t]*', ' ', flags) 491 | _CONFIG_VARS[key] = flags 492 | else: 493 | # Allow the user to override the architecture flags using 494 | # an environment variable. 495 | # NOTE: This name was introduced by Apple in OSX 10.5 and 496 | # is used by several scripting languages distributed with 497 | # that OS release. 498 | if 'ARCHFLAGS' in os.environ: 499 | arch = os.environ['ARCHFLAGS'] 500 | for key in ('LDFLAGS', 'BASECFLAGS', 501 | # a number of derived variables. These need to be 502 | # patched up as well. 503 | 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): 504 | 505 | flags = _CONFIG_VARS[key] 506 | flags = re.sub('-arch\s+\w+\s', ' ', flags) 507 | flags = flags + ' ' + arch 508 | _CONFIG_VARS[key] = flags 509 | 510 | # If we're on OSX 10.5 or later and the user tries to 511 | # compiles an extension using an SDK that is not present 512 | # on the current machine it is better to not use an SDK 513 | # than to fail. 514 | # 515 | # The major usecase for this is users using a Python.org 516 | # binary installer on OSX 10.6: that installer uses 517 | # the 10.4u SDK, but that SDK is not installed by default 518 | # when you install Xcode. 519 | # 520 | CFLAGS = _CONFIG_VARS.get('CFLAGS', '') 521 | m = re.search('-isysroot\s+(\S+)', CFLAGS) 522 | if m is not None: 523 | sdk = m.group(1) 524 | if not os.path.exists(sdk): 525 | for key in ('LDFLAGS', 'BASECFLAGS', 526 | # a number of derived variables. These need to be 527 | # patched up as well. 528 | 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): 529 | 530 | flags = _CONFIG_VARS[key] 531 | flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) 532 | _CONFIG_VARS[key] = flags 533 | 534 | if args: 535 | vals = [] 536 | for name in args: 537 | vals.append(_CONFIG_VARS.get(name)) 538 | return vals 539 | else: 540 | return _CONFIG_VARS 541 | 542 | def get_config_var(name): 543 | """Return the value of a single variable using the dictionary returned by 544 | 'get_config_vars()'. 545 | 546 | Equivalent to get_config_vars().get(name) 547 | """ 548 | return get_config_vars().get(name) 549 | 550 | def get_platform(): 551 | """Return a string that identifies the current platform. 552 | 553 | This is used mainly to distinguish platform-specific build directories and 554 | platform-specific built distributions. Typically includes the OS name 555 | and version and the architecture (as supplied by 'os.uname()'), 556 | although the exact information included depends on the OS; eg. for IRIX 557 | the architecture isn't particularly important (IRIX only runs on SGI 558 | hardware), but for Linux the kernel version isn't particularly 559 | important. 560 | 561 | Examples of returned values: 562 | linux-i586 563 | linux-alpha (?) 564 | solaris-2.6-sun4u 565 | irix-5.3 566 | irix64-6.2 567 | 568 | Windows will return one of: 569 | win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) 570 | win-ia64 (64bit Windows on Itanium) 571 | win32 (all others - specifically, sys.platform is returned) 572 | 573 | For other non-POSIX platforms, currently just returns 'sys.platform'. 574 | """ 575 | import re 576 | if os.name == 'nt': 577 | # sniff sys.version for architecture. 578 | prefix = " bit (" 579 | i = sys.version.find(prefix) 580 | if i == -1: 581 | return sys.platform 582 | j = sys.version.find(")", i) 583 | look = sys.version[i+len(prefix):j].lower() 584 | if look == 'amd64': 585 | return 'win-amd64' 586 | if look == 'itanium': 587 | return 'win-ia64' 588 | return sys.platform 589 | 590 | if os.name != "posix" or not hasattr(os, 'uname'): 591 | # XXX what about the architecture? NT is Intel or Alpha, 592 | # Mac OS is M68k or PPC, etc. 593 | return sys.platform 594 | 595 | # Try to distinguish various flavours of Unix 596 | osname, host, release, version, machine = os.uname() 597 | 598 | # Convert the OS name to lowercase, remove '/' characters 599 | # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") 600 | osname = osname.lower().replace('/', '') 601 | machine = machine.replace(' ', '_') 602 | machine = machine.replace('/', '-') 603 | 604 | if osname[:5] == "linux": 605 | # At least on Linux/Intel, 'machine' is the processor -- 606 | # i386, etc. 607 | # XXX what about Alpha, SPARC, etc? 608 | return "%s-%s" % (osname, machine) 609 | elif osname[:5] == "sunos": 610 | if release[0] >= "5": # SunOS 5 == Solaris 2 611 | osname = "solaris" 612 | release = "%d.%s" % (int(release[0]) - 3, release[2:]) 613 | # fall through to standard osname-release-machine representation 614 | elif osname[:4] == "irix": # could be "irix64"! 615 | return "%s-%s" % (osname, release) 616 | elif osname[:3] == "aix": 617 | return "%s-%s.%s" % (osname, version, release) 618 | elif osname[:6] == "cygwin": 619 | osname = "cygwin" 620 | rel_re = re.compile (r'[\d.]+') 621 | m = rel_re.match(release) 622 | if m: 623 | release = m.group() 624 | elif osname[:6] == "darwin": 625 | # 626 | # For our purposes, we'll assume that the system version from 627 | # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set 628 | # to. This makes the compatibility story a bit more sane because the 629 | # machine is going to compile and link as if it were 630 | # MACOSX_DEPLOYMENT_TARGET. 631 | cfgvars = get_config_vars() 632 | macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET') 633 | if not macver: 634 | macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') 635 | 636 | if 1: 637 | # Always calculate the release of the running machine, 638 | # needed to determine if we can build fat binaries or not. 639 | 640 | macrelease = macver 641 | # Get the system version. Reading this plist is a documented 642 | # way to get the system version (see the documentation for 643 | # the Gestalt Manager) 644 | try: 645 | f = open('/System/Library/CoreServices/SystemVersion.plist') 646 | except IOError: 647 | # We're on a plain darwin box, fall back to the default 648 | # behaviour. 649 | pass 650 | else: 651 | try: 652 | m = re.search( 653 | r'ProductUserVisibleVersion\s*' + 654 | r'(.*?)', f.read()) 655 | f.close() 656 | if m is not None: 657 | macrelease = '.'.join(m.group(1).split('.')[:2]) 658 | # else: fall back to the default behaviour 659 | finally: 660 | f.close() 661 | 662 | if not macver: 663 | macver = macrelease 664 | 665 | if macver: 666 | release = macver 667 | osname = "macosx" 668 | 669 | if (macrelease + '.') >= '10.4.' and \ 670 | '-arch' in get_config_vars().get('CFLAGS', '').strip(): 671 | # The universal build will build fat binaries, but not on 672 | # systems before 10.4 673 | # 674 | # Try to detect 4-way universal builds, those have machine-type 675 | # 'universal' instead of 'fat'. 676 | 677 | machine = 'fat' 678 | cflags = get_config_vars().get('CFLAGS') 679 | 680 | archs = re.findall('-arch\s+(\S+)', cflags) 681 | archs = tuple(sorted(set(archs))) 682 | 683 | if len(archs) == 1: 684 | machine = archs[0] 685 | elif archs == ('i386', 'ppc'): 686 | machine = 'fat' 687 | elif archs == ('i386', 'x86_64'): 688 | machine = 'intel' 689 | elif archs == ('i386', 'ppc', 'x86_64'): 690 | machine = 'fat3' 691 | elif archs == ('ppc64', 'x86_64'): 692 | machine = 'fat64' 693 | elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): 694 | machine = 'universal' 695 | else: 696 | raise ValueError( 697 | "Don't know machine value for archs=%r"%(archs,)) 698 | 699 | elif machine == 'i386': 700 | # On OSX the machine type returned by uname is always the 701 | # 32-bit variant, even if the executable architecture is 702 | # the 64-bit variant 703 | if sys.maxint >= 2**32: 704 | machine = 'x86_64' 705 | 706 | elif machine in ('PowerPC', 'Power_Macintosh'): 707 | # Pick a sane name for the PPC architecture. 708 | # See 'i386' case 709 | if sys.maxint >= 2**32: 710 | machine = 'ppc64' 711 | else: 712 | machine = 'ppc' 713 | 714 | return "%s-%s-%s" % (osname, release, machine) 715 | 716 | 717 | def get_python_version(): 718 | return _PY_VERSION_SHORT 719 | -------------------------------------------------------------------------------- /garbage/sysconfig/sysconfig32.py: -------------------------------------------------------------------------------- 1 | """Provide access to Python's configuration information. 2 | 3 | """ 4 | import sys 5 | import os 6 | from os.path import pardir, realpath 7 | 8 | __all__ = [ 9 | 'get_config_h_filename', 10 | 'get_config_var', 11 | 'get_config_vars', 12 | 'get_makefile_filename', 13 | 'get_path', 14 | 'get_path_names', 15 | 'get_paths', 16 | 'get_platform', 17 | 'get_python_version', 18 | 'get_scheme_names', 19 | 'parse_config_h', 20 | ] 21 | 22 | _INSTALL_SCHEMES = { 23 | 'posix_prefix': { 24 | 'stdlib': '{base}/lib/python{py_version_short}', 25 | 'platstdlib': '{platbase}/lib/python{py_version_short}', 26 | 'purelib': '{base}/lib/python{py_version_short}/site-packages', 27 | 'platlib': '{platbase}/lib/python{py_version_short}/site-packages', 28 | 'include': 29 | '{base}/include/python{py_version_short}{abiflags}', 30 | 'platinclude': 31 | '{platbase}/include/python{py_version_short}{abiflags}', 32 | 'scripts': '{base}/bin', 33 | 'data': '{base}', 34 | }, 35 | 'posix_home': { 36 | 'stdlib': '{base}/lib/python', 37 | 'platstdlib': '{base}/lib/python', 38 | 'purelib': '{base}/lib/python', 39 | 'platlib': '{base}/lib/python', 40 | 'include': '{base}/include/python', 41 | 'platinclude': '{base}/include/python', 42 | 'scripts': '{base}/bin', 43 | 'data' : '{base}', 44 | }, 45 | 'nt': { 46 | 'stdlib': '{base}/Lib', 47 | 'platstdlib': '{base}/Lib', 48 | 'purelib': '{base}/Lib/site-packages', 49 | 'platlib': '{base}/Lib/site-packages', 50 | 'include': '{base}/Include', 51 | 'platinclude': '{base}/Include', 52 | 'scripts': '{base}/Scripts', 53 | 'data' : '{base}', 54 | }, 55 | 'os2': { 56 | 'stdlib': '{base}/Lib', 57 | 'platstdlib': '{base}/Lib', 58 | 'purelib': '{base}/Lib/site-packages', 59 | 'platlib': '{base}/Lib/site-packages', 60 | 'include': '{base}/Include', 61 | 'platinclude': '{base}/Include', 62 | 'scripts': '{base}/Scripts', 63 | 'data' : '{base}', 64 | }, 65 | 'os2_home': { 66 | 'stdlib': '{userbase}/lib/python{py_version_short}', 67 | 'platstdlib': '{userbase}/lib/python{py_version_short}', 68 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', 69 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', 70 | 'include': '{userbase}/include/python{py_version_short}', 71 | 'scripts': '{userbase}/bin', 72 | 'data' : '{userbase}', 73 | }, 74 | 'nt_user': { 75 | 'stdlib': '{userbase}/Python{py_version_nodot}', 76 | 'platstdlib': '{userbase}/Python{py_version_nodot}', 77 | 'purelib': '{userbase}/Python{py_version_nodot}/site-packages', 78 | 'platlib': '{userbase}/Python{py_version_nodot}/site-packages', 79 | 'include': '{userbase}/Python{py_version_nodot}/Include', 80 | 'scripts': '{userbase}/Scripts', 81 | 'data' : '{userbase}', 82 | }, 83 | 'posix_user': { 84 | 'stdlib': '{userbase}/lib/python{py_version_short}', 85 | 'platstdlib': '{userbase}/lib/python{py_version_short}', 86 | 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', 87 | 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', 88 | 'include': '{userbase}/include/python{py_version_short}', 89 | 'scripts': '{userbase}/bin', 90 | 'data' : '{userbase}', 91 | }, 92 | 'osx_framework_user': { 93 | 'stdlib': '{userbase}/lib/python', 94 | 'platstdlib': '{userbase}/lib/python', 95 | 'purelib': '{userbase}/lib/python/site-packages', 96 | 'platlib': '{userbase}/lib/python/site-packages', 97 | 'include': '{userbase}/include', 98 | 'scripts': '{userbase}/bin', 99 | 'data' : '{userbase}', 100 | }, 101 | } 102 | 103 | _SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include', 104 | 'scripts', 'data') 105 | _PY_VERSION = sys.version.split()[0] 106 | _PY_VERSION_SHORT = sys.version[:3] 107 | _PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2] 108 | _PREFIX = os.path.normpath(sys.prefix) 109 | _EXEC_PREFIX = os.path.normpath(sys.exec_prefix) 110 | _CONFIG_VARS = None 111 | _USER_BASE = None 112 | 113 | def _safe_realpath(path): 114 | try: 115 | return realpath(path) 116 | except OSError: 117 | return path 118 | 119 | if sys.executable: 120 | _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) 121 | else: 122 | # sys.executable can be empty if argv[0] has been changed and Python is 123 | # unable to retrieve the real program name 124 | _PROJECT_BASE = _safe_realpath(os.getcwd()) 125 | 126 | if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): 127 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) 128 | # PC/VS7.1 129 | if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): 130 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) 131 | # PC/AMD64 132 | if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): 133 | _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) 134 | 135 | def is_python_build(): 136 | for fn in ("Setup.dist", "Setup.local"): 137 | if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): 138 | return True 139 | return False 140 | 141 | _PYTHON_BUILD = is_python_build() 142 | 143 | if _PYTHON_BUILD: 144 | for scheme in ('posix_prefix', 'posix_home'): 145 | _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include' 146 | _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.' 147 | 148 | def _subst_vars(s, local_vars): 149 | try: 150 | return s.format(**local_vars) 151 | except KeyError: 152 | try: 153 | return s.format(**os.environ) 154 | except KeyError as var: 155 | raise AttributeError('{%s}' % var) 156 | 157 | def _extend_dict(target_dict, other_dict): 158 | target_keys = target_dict.keys() 159 | for key, value in other_dict.items(): 160 | if key in target_keys: 161 | continue 162 | target_dict[key] = value 163 | 164 | def _expand_vars(scheme, vars): 165 | res = {} 166 | if vars is None: 167 | vars = {} 168 | _extend_dict(vars, get_config_vars()) 169 | 170 | for key, value in _INSTALL_SCHEMES[scheme].items(): 171 | if os.name in ('posix', 'nt'): 172 | value = os.path.expanduser(value) 173 | res[key] = os.path.normpath(_subst_vars(value, vars)) 174 | return res 175 | 176 | def _get_default_scheme(): 177 | if os.name == 'posix': 178 | # the default scheme for posix is posix_prefix 179 | return 'posix_prefix' 180 | return os.name 181 | 182 | def _getuserbase(): 183 | env_base = os.environ.get("PYTHONUSERBASE", None) 184 | def joinuser(*args): 185 | return os.path.expanduser(os.path.join(*args)) 186 | 187 | # what about 'os2emx', 'riscos' ? 188 | if os.name == "nt": 189 | base = os.environ.get("APPDATA") or "~" 190 | return env_base if env_base else joinuser(base, "Python") 191 | 192 | if sys.platform == "darwin": 193 | framework = get_config_var("PYTHONFRAMEWORK") 194 | if framework: 195 | return env_base if env_base else joinuser("~", "Library", framework, "%d.%d"%( 196 | sys.version_info[:2])) 197 | 198 | return env_base if env_base else joinuser("~", ".local") 199 | 200 | 201 | def _parse_makefile(filename, vars=None): 202 | """Parse a Makefile-style file. 203 | 204 | A dictionary containing name/value pairs is returned. If an 205 | optional dictionary is passed in as the second argument, it is 206 | used instead of a new dictionary. 207 | """ 208 | import re 209 | # Regexes needed for parsing Makefile (and similar syntaxes, 210 | # like old-style Setup files). 211 | _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") 212 | _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") 213 | _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") 214 | 215 | if vars is None: 216 | vars = {} 217 | done = {} 218 | notdone = {} 219 | 220 | with open(filename, errors="surrogateescape") as f: 221 | lines = f.readlines() 222 | 223 | for line in lines: 224 | if line.startswith('#') or line.strip() == '': 225 | continue 226 | m = _variable_rx.match(line) 227 | if m: 228 | n, v = m.group(1, 2) 229 | v = v.strip() 230 | # `$$' is a literal `$' in make 231 | tmpv = v.replace('$$', '') 232 | 233 | if "$" in tmpv: 234 | notdone[n] = v 235 | else: 236 | try: 237 | v = int(v) 238 | except ValueError: 239 | # insert literal `$' 240 | done[n] = v.replace('$$', '$') 241 | else: 242 | done[n] = v 243 | 244 | # do variable interpolation here 245 | variables = list(notdone.keys()) 246 | 247 | # Variables with a 'PY_' prefix in the makefile. These need to 248 | # be made available without that prefix through sysconfig. 249 | # Special care is needed to ensure that variable expansion works, even 250 | # if the expansion uses the name without a prefix. 251 | renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') 252 | 253 | while len(variables) > 0: 254 | for name in tuple(variables): 255 | value = notdone[name] 256 | m = _findvar1_rx.search(value) or _findvar2_rx.search(value) 257 | if m is not None: 258 | n = m.group(1) 259 | found = True 260 | if n in done: 261 | item = str(done[n]) 262 | elif n in notdone: 263 | # get it on a subsequent round 264 | found = False 265 | elif n in os.environ: 266 | # do it like make: fall back to environment 267 | item = os.environ[n] 268 | 269 | elif n in renamed_variables: 270 | if name.startswith('PY_') and name[3:] in renamed_variables: 271 | item = "" 272 | 273 | elif 'PY_' + n in notdone: 274 | found = False 275 | 276 | else: 277 | item = str(done['PY_' + n]) 278 | 279 | else: 280 | done[n] = item = "" 281 | 282 | if found: 283 | after = value[m.end():] 284 | value = value[:m.start()] + item + after 285 | if "$" in after: 286 | notdone[name] = value 287 | else: 288 | try: 289 | value = int(value) 290 | except ValueError: 291 | done[name] = value.strip() 292 | else: 293 | done[name] = value 294 | variables.remove(name) 295 | 296 | if name.startswith('PY_') \ 297 | and name[3:] in renamed_variables: 298 | 299 | name = name[3:] 300 | if name not in done: 301 | done[name] = value 302 | 303 | 304 | else: 305 | # bogus variable reference; just drop it since we can't deal 306 | variables.remove(name) 307 | 308 | # strip spurious spaces 309 | for k, v in done.items(): 310 | if isinstance(v, str): 311 | done[k] = v.strip() 312 | 313 | # save the results in the global dictionary 314 | vars.update(done) 315 | return vars 316 | 317 | 318 | def get_makefile_filename(): 319 | """Return the path of the Makefile.""" 320 | if _PYTHON_BUILD: 321 | return os.path.join(_PROJECT_BASE, "Makefile") 322 | return os.path.join(get_path('stdlib'), 323 | 'config-{}{}'.format(_PY_VERSION_SHORT, sys.abiflags), 324 | 'Makefile') 325 | 326 | 327 | def _init_posix(vars): 328 | """Initialize the module as appropriate for POSIX systems.""" 329 | # load the installed Makefile: 330 | makefile = get_makefile_filename() 331 | try: 332 | _parse_makefile(makefile, vars) 333 | except IOError as e: 334 | msg = "invalid Python installation: unable to open %s" % makefile 335 | if hasattr(e, "strerror"): 336 | msg = msg + " (%s)" % e.strerror 337 | raise IOError(msg) 338 | # load the installed pyconfig.h: 339 | config_h = get_config_h_filename() 340 | try: 341 | with open(config_h) as f: 342 | parse_config_h(f, vars) 343 | except IOError as e: 344 | msg = "invalid Python installation: unable to open %s" % config_h 345 | if hasattr(e, "strerror"): 346 | msg = msg + " (%s)" % e.strerror 347 | raise IOError(msg) 348 | # On MacOSX we need to check the setting of the environment variable 349 | # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so 350 | # it needs to be compatible. 351 | # If it isn't set we set it to the configure-time value 352 | if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in vars: 353 | cfg_target = vars['MACOSX_DEPLOYMENT_TARGET'] 354 | cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') 355 | if cur_target == '': 356 | cur_target = cfg_target 357 | os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target) 358 | elif (list(map(int, cfg_target.split('.'))) > 359 | list(map(int, cur_target.split('.')))): 360 | msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" ' 361 | 'during configure' % (cur_target, cfg_target)) 362 | raise IOError(msg) 363 | # On AIX, there are wrong paths to the linker scripts in the Makefile 364 | # -- these paths are relative to the Python source, but when installed 365 | # the scripts are in another directory. 366 | if _PYTHON_BUILD: 367 | vars['LDSHARED'] = vars['BLDSHARED'] 368 | 369 | def _init_non_posix(vars): 370 | """Initialize the module as appropriate for NT""" 371 | # set basic install directories 372 | vars['LIBDEST'] = get_path('stdlib') 373 | vars['BINLIBDEST'] = get_path('platstdlib') 374 | vars['INCLUDEPY'] = get_path('include') 375 | vars['SO'] = '.pyd' 376 | vars['EXE'] = '.exe' 377 | vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT 378 | vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) 379 | 380 | # 381 | # public APIs 382 | # 383 | 384 | 385 | def parse_config_h(fp, vars=None): 386 | """Parse a config.h-style file. 387 | 388 | A dictionary containing name/value pairs is returned. If an 389 | optional dictionary is passed in as the second argument, it is 390 | used instead of a new dictionary. 391 | """ 392 | import re 393 | if vars is None: 394 | vars = {} 395 | define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") 396 | undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") 397 | 398 | while True: 399 | line = fp.readline() 400 | if not line: 401 | break 402 | m = define_rx.match(line) 403 | if m: 404 | n, v = m.group(1, 2) 405 | try: v = int(v) 406 | except ValueError: pass 407 | vars[n] = v 408 | else: 409 | m = undef_rx.match(line) 410 | if m: 411 | vars[m.group(1)] = 0 412 | return vars 413 | 414 | def get_config_h_filename(): 415 | """Return the path of pyconfig.h.""" 416 | if _PYTHON_BUILD: 417 | if os.name == "nt": 418 | inc_dir = os.path.join(_PROJECT_BASE, "PC") 419 | else: 420 | inc_dir = _PROJECT_BASE 421 | else: 422 | inc_dir = get_path('platinclude') 423 | return os.path.join(inc_dir, 'pyconfig.h') 424 | 425 | def get_scheme_names(): 426 | """Return a tuple containing the schemes names.""" 427 | schemes = list(_INSTALL_SCHEMES.keys()) 428 | schemes.sort() 429 | return tuple(schemes) 430 | 431 | def get_path_names(): 432 | """Return a tuple containing the paths names.""" 433 | return _SCHEME_KEYS 434 | 435 | def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): 436 | """Return a mapping containing an install scheme. 437 | 438 | ``scheme`` is the install scheme name. If not provided, it will 439 | return the default scheme for the current platform. 440 | """ 441 | if expand: 442 | return _expand_vars(scheme, vars) 443 | else: 444 | return _INSTALL_SCHEMES[scheme] 445 | 446 | def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): 447 | """Return a path corresponding to the scheme. 448 | 449 | ``scheme`` is the install scheme name. 450 | """ 451 | return get_paths(scheme, vars, expand)[name] 452 | 453 | def get_config_vars(*args): 454 | """With no arguments, return a dictionary of all configuration 455 | variables relevant for the current platform. 456 | 457 | On Unix, this means every variable defined in Python's installed Makefile; 458 | On Windows and Mac OS it's a much smaller set. 459 | 460 | With arguments, return a list of values that result from looking up 461 | each argument in the configuration variable dictionary. 462 | """ 463 | import re 464 | global _CONFIG_VARS 465 | if _CONFIG_VARS is None: 466 | _CONFIG_VARS = {} 467 | # Normalized versions of prefix and exec_prefix are handy to have; 468 | # in fact, these are the standard versions used most places in the 469 | # Distutils. 470 | _CONFIG_VARS['prefix'] = _PREFIX 471 | _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX 472 | _CONFIG_VARS['py_version'] = _PY_VERSION 473 | _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT 474 | _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] 475 | _CONFIG_VARS['base'] = _PREFIX 476 | _CONFIG_VARS['platbase'] = _EXEC_PREFIX 477 | _CONFIG_VARS['projectbase'] = _PROJECT_BASE 478 | try: 479 | _CONFIG_VARS['abiflags'] = sys.abiflags 480 | except AttributeError: 481 | # sys.abiflags may not be defined on all platforms. 482 | _CONFIG_VARS['abiflags'] = '' 483 | 484 | if os.name in ('nt', 'os2'): 485 | _init_non_posix(_CONFIG_VARS) 486 | if os.name == 'posix': 487 | _init_posix(_CONFIG_VARS) 488 | # Setting 'userbase' is done below the call to the 489 | # init function to enable using 'get_config_var' in 490 | # the init-function. 491 | _CONFIG_VARS['userbase'] = _getuserbase() 492 | 493 | if 'srcdir' not in _CONFIG_VARS: 494 | _CONFIG_VARS['srcdir'] = _PROJECT_BASE 495 | else: 496 | _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir']) 497 | 498 | 499 | # Convert srcdir into an absolute path if it appears necessary. 500 | # Normally it is relative to the build directory. However, during 501 | # testing, for example, we might be running a non-installed python 502 | # from a different directory. 503 | if _PYTHON_BUILD and os.name == "posix": 504 | base = _PROJECT_BASE 505 | try: 506 | cwd = os.getcwd() 507 | except OSError: 508 | cwd = None 509 | if (not os.path.isabs(_CONFIG_VARS['srcdir']) and 510 | base != cwd): 511 | # srcdir is relative and we are not in the same directory 512 | # as the executable. Assume executable is in the build 513 | # directory and make srcdir absolute. 514 | srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) 515 | _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) 516 | 517 | if sys.platform == 'darwin': 518 | kernel_version = os.uname()[2] # Kernel version (8.4.3) 519 | major_version = int(kernel_version.split('.')[0]) 520 | 521 | if major_version < 8: 522 | # On Mac OS X before 10.4, check if -arch and -isysroot 523 | # are in CFLAGS or LDFLAGS and remove them if they are. 524 | # This is needed when building extensions on a 10.3 system 525 | # using a universal build of python. 526 | for key in ('LDFLAGS', 'BASECFLAGS', 527 | # a number of derived variables. These need to be 528 | # patched up as well. 529 | 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): 530 | flags = _CONFIG_VARS[key] 531 | flags = re.sub('-arch\s+\w+\s', ' ', flags) 532 | flags = re.sub('-isysroot [^ \t]*', ' ', flags) 533 | _CONFIG_VARS[key] = flags 534 | else: 535 | # Allow the user to override the architecture flags using 536 | # an environment variable. 537 | # NOTE: This name was introduced by Apple in OSX 10.5 and 538 | # is used by several scripting languages distributed with 539 | # that OS release. 540 | if 'ARCHFLAGS' in os.environ: 541 | arch = os.environ['ARCHFLAGS'] 542 | for key in ('LDFLAGS', 'BASECFLAGS', 543 | # a number of derived variables. These need to be 544 | # patched up as well. 545 | 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): 546 | 547 | flags = _CONFIG_VARS[key] 548 | flags = re.sub('-arch\s+\w+\s', ' ', flags) 549 | flags = flags + ' ' + arch 550 | _CONFIG_VARS[key] = flags 551 | 552 | # If we're on OSX 10.5 or later and the user tries to 553 | # compiles an extension using an SDK that is not present 554 | # on the current machine it is better to not use an SDK 555 | # than to fail. 556 | # 557 | # The major usecase for this is users using a Python.org 558 | # binary installer on OSX 10.6: that installer uses 559 | # the 10.4u SDK, but that SDK is not installed by default 560 | # when you install Xcode. 561 | # 562 | CFLAGS = _CONFIG_VARS.get('CFLAGS', '') 563 | m = re.search('-isysroot\s+(\S+)', CFLAGS) 564 | if m is not None: 565 | sdk = m.group(1) 566 | if not os.path.exists(sdk): 567 | for key in ('LDFLAGS', 'BASECFLAGS', 568 | # a number of derived variables. These need to be 569 | # patched up as well. 570 | 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): 571 | 572 | flags = _CONFIG_VARS[key] 573 | flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags) 574 | _CONFIG_VARS[key] = flags 575 | 576 | if args: 577 | vals = [] 578 | for name in args: 579 | vals.append(_CONFIG_VARS.get(name)) 580 | return vals 581 | else: 582 | return _CONFIG_VARS 583 | 584 | def get_config_var(name): 585 | """Return the value of a single variable using the dictionary returned by 586 | 'get_config_vars()'. 587 | 588 | Equivalent to get_config_vars().get(name) 589 | """ 590 | return get_config_vars().get(name) 591 | 592 | def get_platform(): 593 | """Return a string that identifies the current platform. 594 | 595 | This is used mainly to distinguish platform-specific build directories and 596 | platform-specific built distributions. Typically includes the OS name 597 | and version and the architecture (as supplied by 'os.uname()'), 598 | although the exact information included depends on the OS; eg. for IRIX 599 | the architecture isn't particularly important (IRIX only runs on SGI 600 | hardware), but for Linux the kernel version isn't particularly 601 | important. 602 | 603 | Examples of returned values: 604 | linux-i586 605 | linux-alpha (?) 606 | solaris-2.6-sun4u 607 | irix-5.3 608 | irix64-6.2 609 | 610 | Windows will return one of: 611 | win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) 612 | win-ia64 (64bit Windows on Itanium) 613 | win32 (all others - specifically, sys.platform is returned) 614 | 615 | For other non-POSIX platforms, currently just returns 'sys.platform'. 616 | """ 617 | import re 618 | if os.name == 'nt': 619 | # sniff sys.version for architecture. 620 | prefix = " bit (" 621 | i = sys.version.find(prefix) 622 | if i == -1: 623 | return sys.platform 624 | j = sys.version.find(")", i) 625 | look = sys.version[i+len(prefix):j].lower() 626 | if look == 'amd64': 627 | return 'win-amd64' 628 | if look == 'itanium': 629 | return 'win-ia64' 630 | return sys.platform 631 | 632 | if os.name != "posix" or not hasattr(os, 'uname'): 633 | # XXX what about the architecture? NT is Intel or Alpha, 634 | # Mac OS is M68k or PPC, etc. 635 | return sys.platform 636 | 637 | # Try to distinguish various flavours of Unix 638 | osname, host, release, version, machine = os.uname() 639 | 640 | # Convert the OS name to lowercase, remove '/' characters 641 | # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") 642 | osname = osname.lower().replace('/', '') 643 | machine = machine.replace(' ', '_') 644 | machine = machine.replace('/', '-') 645 | 646 | if osname[:5] == "linux": 647 | # At least on Linux/Intel, 'machine' is the processor -- 648 | # i386, etc. 649 | # XXX what about Alpha, SPARC, etc? 650 | return "%s-%s" % (osname, machine) 651 | elif osname[:5] == "sunos": 652 | if release[0] >= "5": # SunOS 5 == Solaris 2 653 | osname = "solaris" 654 | release = "%d.%s" % (int(release[0]) - 3, release[2:]) 655 | # fall through to standard osname-release-machine representation 656 | elif osname[:4] == "irix": # could be "irix64"! 657 | return "%s-%s" % (osname, release) 658 | elif osname[:3] == "aix": 659 | return "%s-%s.%s" % (osname, version, release) 660 | elif osname[:6] == "cygwin": 661 | osname = "cygwin" 662 | rel_re = re.compile (r'[\d.]+') 663 | m = rel_re.match(release) 664 | if m: 665 | release = m.group() 666 | elif osname[:6] == "darwin": 667 | # 668 | # For our purposes, we'll assume that the system version from 669 | # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set 670 | # to. This makes the compatibility story a bit more sane because the 671 | # machine is going to compile and link as if it were 672 | # MACOSX_DEPLOYMENT_TARGET. 673 | cfgvars = get_config_vars() 674 | macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET') 675 | if not macver: 676 | macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') 677 | 678 | if 1: 679 | # Always calculate the release of the running machine, 680 | # needed to determine if we can build fat binaries or not. 681 | 682 | macrelease = macver 683 | # Get the system version. Reading this plist is a documented 684 | # way to get the system version (see the documentation for 685 | # the Gestalt Manager) 686 | try: 687 | f = open('/System/Library/CoreServices/SystemVersion.plist') 688 | except IOError: 689 | # We're on a plain darwin box, fall back to the default 690 | # behaviour. 691 | pass 692 | else: 693 | try: 694 | m = re.search( 695 | r'ProductUserVisibleVersion\s*' + 696 | r'(.*?)', f.read()) 697 | f.close() 698 | if m is not None: 699 | macrelease = '.'.join(m.group(1).split('.')[:2]) 700 | # else: fall back to the default behaviour 701 | finally: 702 | f.close() 703 | 704 | if not macver: 705 | macver = macrelease 706 | 707 | if macver: 708 | release = macver 709 | osname = "macosx" 710 | 711 | if (macrelease + '.') >= '10.4.' and \ 712 | '-arch' in get_config_vars().get('CFLAGS', '').strip(): 713 | # The universal build will build fat binaries, but not on 714 | # systems before 10.4 715 | # 716 | # Try to detect 4-way universal builds, those have machine-type 717 | # 'universal' instead of 'fat'. 718 | 719 | machine = 'fat' 720 | cflags = get_config_vars().get('CFLAGS') 721 | 722 | archs = re.findall('-arch\s+(\S+)', cflags) 723 | archs = tuple(sorted(set(archs))) 724 | 725 | if len(archs) == 1: 726 | machine = archs[0] 727 | elif archs == ('i386', 'ppc'): 728 | machine = 'fat' 729 | elif archs == ('i386', 'x86_64'): 730 | machine = 'intel' 731 | elif archs == ('i386', 'ppc', 'x86_64'): 732 | machine = 'fat3' 733 | elif archs == ('ppc64', 'x86_64'): 734 | machine = 'fat64' 735 | elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): 736 | machine = 'universal' 737 | else: 738 | raise ValueError( 739 | "Don't know machine value for archs=%r"%(archs,)) 740 | 741 | elif machine == 'i386': 742 | # On OSX the machine type returned by uname is always the 743 | # 32-bit variant, even if the executable architecture is 744 | # the 64-bit variant 745 | if sys.maxsize >= 2**32: 746 | machine = 'x86_64' 747 | 748 | elif machine in ('PowerPC', 'Power_Macintosh'): 749 | # Pick a sane name for the PPC architecture. 750 | # See 'i386' case 751 | if sys.maxsize >= 2**32: 752 | machine = 'ppc64' 753 | else: 754 | machine = 'ppc' 755 | 756 | return "%s-%s-%s" % (osname, release, machine) 757 | 758 | 759 | def get_python_version(): 760 | return _PY_VERSION_SHORT 761 | 762 | def _print_dict(title, data): 763 | for index, (key, value) in enumerate(sorted(data.items())): 764 | if index == 0: 765 | print('{0}: '.format(title)) 766 | print('\t{0} = "{1}"'.format(key, value)) 767 | 768 | def _main(): 769 | """Display all information sysconfig detains.""" 770 | print('Platform: "{0}"'.format(get_platform())) 771 | print('Python version: "{0}"'.format(get_python_version())) 772 | print('Current installation scheme: "{0}"'.format(_get_default_scheme())) 773 | print('') 774 | _print_dict('Paths', get_paths()) 775 | print('') 776 | _print_dict('Variables', get_config_vars()) 777 | 778 | if __name__ == '__main__': 779 | _main() 780 | -------------------------------------------------------------------------------- /rvirtualenv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from rvirtualenv import main 4 | 5 | if __name__ == '__main__': 6 | main() 7 | 8 | -------------------------------------------------------------------------------- /rvirtualenv/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import sys 4 | from os import path 5 | from optparse import OptionParser 6 | from subprocess import Popen, PIPE 7 | 8 | import rvirtualenv 9 | from rvirtualenv.copy import copy 10 | from rvirtualenv.generate import generate 11 | 12 | 13 | VERSION = (0, 3, 2) 14 | __version__ = VERSION 15 | __versionstr__ = '.'.join(map(str, VERSION)) 16 | 17 | 18 | def get_parser(): 19 | ''' 20 | options parser 21 | ''' 22 | parser = OptionParser(usage="%prog [OPTIONS] DEST_DIR") 23 | parser.add_option( 24 | '--no-site-packages', dest='sitepackages', action='store_false', default=True, 25 | help="Don't give access to the global site-packages dir to the virtual environment" 26 | ) 27 | parser.add_option( 28 | '-p', '--python', dest='python', metavar='PYTHON_EXE', default=sys.executable, 29 | help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' 30 | 'interpreter to create the new environment. The default is the interpreter that ' 31 | 'virtualenv was installed with (%s)' % sys.executable 32 | ) 33 | parser.add_option( 34 | '--prompt=', dest='prompt', 35 | help='Provides an alternative prompt prefix for this environment' 36 | ) 37 | return parser 38 | 39 | def get_base(): 40 | ''' 41 | path to rvirtualenv 42 | ''' 43 | return path.abspath(path.join(path.dirname(rvirtualenv.__file__), path.pardir)) 44 | 45 | def run_command(cmd): 46 | shell = sys.platform != 'win32' 47 | p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=shell) 48 | return map(lambda b: b.decode(sys.stdout.encoding or 'UTF-8'), p.communicate()) 49 | 50 | def create_subprocess(python, venv, sitepackages, prompt): 51 | ''' 52 | install rvirtualenv with given interpreter 53 | ''' 54 | cmd = ('''%s -c "import sys; sys.path.insert(0, %r); ''' 55 | '''from rvirtualenv import create; create(%r, %s, %r)"''') % \ 56 | (python, get_base(), venv, sitepackages, prompt) 57 | return run_command(cmd) 58 | 59 | def create(name, sitepackages, prompt): 60 | ''' 61 | create rvirtualenv 62 | ''' 63 | venv = path.join(os.getcwd(), name) 64 | copy(venv) 65 | generate(venv, sitepackages=sitepackages, prompt=prompt) 66 | 67 | def main(argv=None): 68 | ''' 69 | main call for rvirtualenv command 70 | ''' 71 | if argv is None: 72 | argv = sys.argv 73 | 74 | parser = get_parser() 75 | options, name = parser.parse_args(argv[1:]) 76 | 77 | if len(name) != 1: 78 | parser.print_help() 79 | parser.exit('Invalid parameter count.') 80 | 81 | create_subprocess(options.python, name[0], options.sitepackages, options.prompt) 82 | 83 | -------------------------------------------------------------------------------- /rvirtualenv/copy.py: -------------------------------------------------------------------------------- 1 | 2 | from os.path import join, dirname, isfile 3 | from os import makedirs, walk, remove 4 | import shutil 5 | 6 | import rvirtualenv 7 | 8 | 9 | def ignore(src, names): 10 | def invalid(s): 11 | if '__pycache__' in s: 12 | return True 13 | if s.endswith('pyc'): 14 | return True 15 | return False 16 | ignored = set() 17 | ignored.update(( i for i in names if invalid(i) )) 18 | return ignored 19 | 20 | def remove_ignored(src, dst, ignore=None): 21 | for base, dirs, files in walk(dst): 22 | ignored = set() 23 | if ignore is not None: 24 | ignored = ignore(base.replace(dst, src), dirs+files) 25 | for i in ignored: 26 | f = join(base, i) 27 | if not isfile(f): 28 | shutil.rmtree(f, True) 29 | else: 30 | remove(f) 31 | 32 | def copytree(src, dst, symlinks=False, ignore=None): 33 | shutil.copytree(src, dst, symlinks) 34 | remove_ignored(src, dst, ignore) 35 | 36 | def copy(where): 37 | ''' 38 | main function for copying template/venv into specified new virtualenv 39 | ''' 40 | base = dirname(rvirtualenv.__file__) 41 | copytree(join(base, 'template', 'venv'), where, ignore=ignore) 42 | makedirs(join(where, 'src')) 43 | copytree(join(base, 'template', 'inst'), join(where, 'src', 'rvirtualenvkeep'), ignore=ignore) 44 | copytree(join(base, 'rvirtualenvinstall'), join(where, 'rvirtualenvinstall'), ignore=ignore) 45 | 46 | -------------------------------------------------------------------------------- /rvirtualenv/generate.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | from os import path 4 | import sys 5 | from subprocess import Popen, PIPE 6 | 7 | import rvirtualenv 8 | from rvirtualenv.rvirtualenvinstall.scheme import guess_scheme 9 | 10 | 11 | def run_setup(pythonpath, install_dir): 12 | ''' 13 | install couple of helper modules via distutils 14 | because it creates its directory (via the correct schema) 15 | 16 | it must be called in subprocess 17 | because of possible setuptools monkeypatching 18 | ''' 19 | os.environ['PYTHONPATH'] = pythonpath 20 | install = [ 21 | '"%s"' % sys.executable, 22 | path.join(install_dir, 'setup.py'), 23 | 'install', 24 | ] 25 | install = ' '.join(install) 26 | 27 | shell = sys.platform != 'win32' 28 | stdout = stderr = PIPE 29 | p = Popen(install, stdout=stdout, stderr=stderr, shell=shell) 30 | stdoutdata, stderrdata = p.communicate() 31 | 32 | return stdoutdata, stdoutdata 33 | 34 | def generate(where, layout=None, sitepackages=True, prompt=None): 35 | ''' 36 | create dirs and files after virtualenv dir itself is prepared 37 | ''' 38 | generate_pythonrc_stuff(where, layout, sitepackages, prompt) 39 | install_venv_keep_package(where, path.join(where, 'src', 'rvirtualenvkeep')) 40 | 41 | def install_venv_keep_package(venv_base, install_dir): 42 | ''' 43 | install setup.py via distutils 44 | ''' 45 | run_setup(venv_base, install_dir) 46 | 47 | def generate_pythonrc_stuff(venv_base, layout, sitepackages, prompt): 48 | ''' 49 | insert correct lib dirs into pythonrc.py 50 | ''' 51 | # load pythonrc.py file 52 | base = path.dirname(rvirtualenv.__file__) 53 | f = open(path.join(base, 'template', 'venv', 'pythonrc.py'), 'r') 54 | content = f.read() 55 | f.close() 56 | 57 | if layout is None: 58 | layout = guess_scheme() 59 | 60 | # replace pattern in pythonrc.py 61 | patrn = "scheme = 'custom'" 62 | repl = "scheme = '%s'" % layout 63 | content = content.replace(patrn, repl) 64 | 65 | # update no-site-packages option 66 | patrn = "sitepackages = True" 67 | repl = "sitepackages = %s" % sitepackages 68 | content = content.replace(patrn, repl) 69 | 70 | # set custom prompt 71 | patrn = "#prompt = '[CUSTOM]' # set your custom prompt prefix (see -p option)" 72 | repl = "prompt = %r" % prompt 73 | if prompt is not None: 74 | content = content.replace(patrn, repl) 75 | 76 | # write it 77 | f = open(path.join(venv_base, 'pythonrc.py'), 'w') 78 | f.write(content) 79 | f.close() 80 | 81 | -------------------------------------------------------------------------------- /rvirtualenv/rvirtualenvinstall/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvbik/rvirtualenv/aaacde2171144bc3c1d8ab8668e36a0dbc29bf3d/rvirtualenv/rvirtualenvinstall/__init__.py -------------------------------------------------------------------------------- /rvirtualenv/rvirtualenvinstall/boot.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import path 3 | 4 | from rvirtualenvinstall import ( 5 | scheme, 6 | install, 7 | ) 8 | import pythonrc 9 | 10 | 11 | def boot(): 12 | base = path.abspath(path.dirname(pythonrc.__file__)) 13 | 14 | # real_prefix is useful for pip and uninstalling system pkgs 15 | sys.real_prefix = sys.prefix 16 | # python uses this almost everywhere 17 | sys.prefix = base 18 | 19 | if not pythonrc.sitepackages: 20 | sys.path = sys.__rvirtualenv_prev_path 21 | 22 | this_site_packages = [ 23 | scheme.get_scheme(pythonrc.scheme, 'purelib'), 24 | scheme.get_scheme(pythonrc.scheme, 'platlib'), 25 | ] 26 | 27 | scheme.add_to_path(getattr(pythonrc, 'extra_paths', [])) 28 | scheme.add_to_path(this_site_packages) 29 | 30 | install.monkeypatch() 31 | 32 | -------------------------------------------------------------------------------- /rvirtualenv/rvirtualenvinstall/develop.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | from setuptools.command.develop import develop as _develop 3 | 4 | 5 | class develop(_develop): 6 | description = "rvirtualenv's %s" % _develop.description 7 | def run(self): 8 | print('WTF') 9 | 10 | # don't know why isn't it overriden by entry_points 11 | setuptools.command.develop.develop = develop 12 | 13 | -------------------------------------------------------------------------------- /rvirtualenv/rvirtualenvinstall/install.py: -------------------------------------------------------------------------------- 1 | import distutils 2 | from distutils.command.install import install as _install 3 | 4 | import pythonrc 5 | from rvirtualenvinstall import scheme 6 | 7 | 8 | class install(_install): 9 | description = "rvirtualenv's %s" % _install.description 10 | def finalize_options(self): 11 | _install.finalize_options(self) 12 | 13 | vars = {'dist_name': self.distribution.get_name(),} 14 | self.install_purelib = scheme.get_scheme(pythonrc.scheme, 'purelib') 15 | self.install_platlib = scheme.get_scheme(pythonrc.scheme, 'purelib') 16 | self.install_headers = scheme.get_scheme(pythonrc.scheme, 'headers', vars=vars) 17 | self.install_scripts = scheme.get_scheme(pythonrc.scheme, 'scripts') 18 | self.install_data = scheme.get_scheme(pythonrc.scheme, 'data') 19 | 20 | if self.distribution.ext_modules: # has extensions: non-pure 21 | self.install_lib = self.install_platlib 22 | else: 23 | self.install_lib = self.install_purelib 24 | 25 | def monkeypatch(): 26 | "monkey patch for distutils install command" 27 | distutils.command.install.install = install 28 | 29 | -------------------------------------------------------------------------------- /rvirtualenv/rvirtualenvinstall/scheme.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import path 3 | import site 4 | from distutils.util import subst_vars 5 | 6 | INSTALL_SCHEMES = { 7 | 'custom': { 8 | 'purelib': '$base/lib/python/site-packages', 9 | 'platlib': '$base/lib/python$py_version_short/site-packages', 10 | 'headers': '$base/include/python$py_version_short/$dist_name', 11 | 'scripts': '$base/bin', 12 | 'data' : '$base/lib/python$py_version_short/site-packages', 13 | }, 14 | 'unix': { 15 | 'purelib': '$base/lib/python$py_version_short/site-packages', 16 | 'platlib': '$base/lib/python$py_version_short/site-packages', 17 | 'headers': '$base/include/python$py_version_short/$dist_name', 18 | 'scripts': '$base/bin', 19 | 'data' : '$base/lib/python$py_version_short/site-packages', 20 | }, 21 | 'windows': { 22 | 'purelib': '$base/Lib/site-packages', 23 | 'platlib': '$base/Lib/site-packages', 24 | 'headers': '$base/Include/$dist_name', 25 | 'scripts': '$base/Scripts', 26 | 'data' : '$base/Lib/site-packages', 27 | }, 28 | 'os2': { 29 | 'purelib': '$base/Lib/site-packages', 30 | 'platlib': '$base/Lib/site-packages', 31 | 'headers': '$base/Include/$dist_name', 32 | 'scripts': '$base/Scripts', 33 | 'data' : '$base/Lib/site-packages', 34 | }, 35 | 'darwin': { 36 | 'purelib': '$base/Library/Python$py_version_short/site-packages', 37 | 'platlib': '$base/Library/Python$py_version_short/site-packages', 38 | 'headers': '$base/Include/$dist_name', 39 | 'scripts': '$base/bin', 40 | 'data' : '$base/Library/Python$py_version_short/site-packages', 41 | }, 42 | } 43 | 44 | def guess_scheme(): 45 | return 'unix' 46 | 47 | def get_scheme(platform, what, vars={}): 48 | # TODO: maybe use syslinux.get_path in next versions 49 | replace = { 50 | 'base': sys.prefix, 51 | 'py_version_short': sys.version[:3], 52 | 'dist_name': 'UNKNOWN', 53 | } 54 | replace.update(vars) 55 | line = INSTALL_SCHEMES[platform][what] 56 | line = path.join(*line.split('/')) 57 | return subst_vars(line, replace) 58 | 59 | def add_to_path(new_paths): 60 | "add dirs to the beginnig of sys.path" 61 | __plen = len(sys.path) 62 | for i in new_paths: 63 | if i not in sys.path: 64 | site.addsitedir(i) 65 | new = sys.path[__plen:] 66 | del sys.path[__plen:] 67 | sys.path[0:0] = new 68 | 69 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/activate: -------------------------------------------------------------------------------- 1 | 2 | # you cannot guess path of included file in plain posix shell.. 3 | [ $BASH_SOURCE ] && b=`dirname ${BASH_SOURCE[0]}` || b=`dirname $0` 4 | b=`cd $b; pwd` 5 | 6 | $b/activate.py $b/activate.template $b/_activate 7 | 8 | source $b/_activate 9 | 10 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/activate.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | 4 | "%~dp0\activate.py" "%~dp0\activate.bat.template" "%~dp0\_activate.bat" 5 | call "%~dp0\_activate.bat" 6 | 7 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/activate.bat.template: -------------------------------------------------------------------------------- 1 | @echo off 2 | set VIRTUAL_ENV=__VIRTUAL_ENV__ 3 | 4 | if not defined PROMPT ( 5 | set PROMPT=$P$G 6 | ) 7 | 8 | if defined _OLD_VIRTUAL_PROMPT ( 9 | set PROMPT=%_OLD_VIRTUAL_PROMPT% 10 | ) 11 | 12 | if defined _OLD_VIRTUAL_PYTHONHOME ( 13 | set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% 14 | ) 15 | 16 | set _OLD_VIRTUAL_PROMPT=%PROMPT% 17 | set PROMPT=__VIRTUAL_WINPROMPT__ %PROMPT% 18 | 19 | if defined PYTHONHOME ( 20 | set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% 21 | set PYTHONHOME= 22 | ) 23 | 24 | if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%; goto SKIPPATH 25 | 26 | set _OLD_VIRTUAL_PATH=%PATH% 27 | 28 | :SKIPPATH 29 | set PATH=%VIRTUAL_ENV%\__BIN_NAME__;%PATH% 30 | 31 | :END 32 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/activate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from os import path 5 | 6 | def get_prompt(vname_path, vname): 7 | sys.path.insert(0, vname_path) 8 | import pythonrc 9 | prompt = getattr(pythonrc, 'prompt', '(%s)' % vname) 10 | return prompt 11 | 12 | def get_subst_values(): 13 | base = path.dirname(__file__) 14 | vname_path = path.abspath(path.join(base, path.pardir)) 15 | vname = path.split(vname_path)[-1] 16 | bin_path = path.split(base)[-1] 17 | prompt = get_prompt(vname_path, vname) 18 | return { 19 | '__VIRTUAL_PROMPT__': prompt, 20 | '__VIRTUAL_WINPROMPT__': prompt, 21 | '__VIRTUAL_ENV__': vname_path, 22 | '__VIRTUAL_NAME__': vname, 23 | '__BIN_NAME__': bin_path, 24 | } 25 | 26 | def generate(ftemplt, foutput): 27 | ftemplt = open(ftemplt, 'r').read() 28 | for k, v in get_subst_values().items(): 29 | ftemplt = ftemplt.replace(k, v) 30 | f = open(foutput, 'w') 31 | f.write(ftemplt) 32 | f.close() 33 | 34 | def main(argv=None): 35 | if argv is None: 36 | argv = sys.argv 37 | if len(argv) < 3: 38 | raise NotImplementedError 39 | generate(argv[1], argv[2]) 40 | 41 | if __name__ == '__main__': 42 | main() 43 | 44 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/activate.template: -------------------------------------------------------------------------------- 1 | # This file must be used with "source bin/activate" *from bash* 2 | # you cannot run it directly 3 | 4 | deactivate () { 5 | # reset old environment variables 6 | if [ -n "$_OLD_VIRTUAL_PATH" ] ; then 7 | PATH="$_OLD_VIRTUAL_PATH" 8 | export PATH 9 | unset _OLD_VIRTUAL_PATH 10 | fi 11 | if [ -n "$_OLD_VIRTUAL_PYTHONPATH" ] ; then 12 | PYTHONPATH="$_OLD_VIRTUAL_PYTHONPATH" 13 | export PYTHONPATH 14 | unset _OLD_VIRTUAL_PYTHONPATH 15 | fi 16 | if [ -n "$_OLD_VIRTUAL_PYTHONHOME" ] ; then 17 | PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" 18 | export PYTHONHOME 19 | unset _OLD_VIRTUAL_PYTHONHOME 20 | fi 21 | 22 | # This should detect bash and zsh, which have a hash command that must 23 | # be called to get it to forget past commands. Without forgetting 24 | # past commands the $PATH changes we made may not be respected 25 | if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then 26 | hash -r 27 | fi 28 | 29 | if [ -n "$_OLD_VIRTUAL_PS1" ] ; then 30 | PS1="$_OLD_VIRTUAL_PS1" 31 | export PS1 32 | unset _OLD_VIRTUAL_PS1 33 | fi 34 | 35 | unset VIRTUAL_ENV 36 | if [ ! "$1" = "nondestructive" ] ; then 37 | # Self destruct! 38 | unset -f deactivate 39 | [ "$PYTHONPATH" = ":" ] && unset PYTHONPATH 40 | fi 41 | } 42 | 43 | # unset irrelavent variables 44 | deactivate nondestructive 45 | 46 | VIRTUAL_ENV="__VIRTUAL_ENV__" 47 | export VIRTUAL_ENV 48 | 49 | _OLD_VIRTUAL_PATH="$PATH" 50 | PATH="$VIRTUAL_ENV/__BIN_NAME__:$PATH" 51 | export PATH 52 | 53 | [ $PYTHONPATH ] || PYTHONPATH=: 54 | _OLD_VIRTUAL_PYTHONPATH="$PYTHONPATH" 55 | PYTHONPATH="$VIRTUAL_ENV:$PYTHONPATH" 56 | export PYTHONPATH 57 | 58 | # unset PYTHONHOME if set 59 | # this will fail if PYTHONHOME is set to the empty string (which is bad anyway) 60 | # could use `if (set -u; : $PYTHONHOME) ;` in bash 61 | if [ -n "$PYTHONHOME" ] ; then 62 | _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" 63 | unset PYTHONHOME 64 | fi 65 | 66 | if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then 67 | _OLD_VIRTUAL_PS1="$PS1" 68 | if [ "x__VIRTUAL_PROMPT__" != x ] ; then 69 | PS1="__VIRTUAL_PROMPT__$PS1" 70 | else 71 | if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then 72 | # special case for Aspen magic directories 73 | # see http://www.zetadev.com/software/aspen/ 74 | PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1" 75 | else 76 | PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1" 77 | fi 78 | fi 79 | export PS1 80 | fi 81 | 82 | # This should detect bash and zsh, which have a hash command that must 83 | # be called to get it to forget past commands. Without forgetting 84 | # past commands the $PATH changes we made may not be respected 85 | if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then 86 | hash -r 87 | fi 88 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/deactivate.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | 4 | "%~dp0\activate.py" "%~dp0\deactivate.bat.template" "%~dp0\_deactivate.bat" 5 | call "%~dp0\_deactivate.bat" 6 | 7 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/deactivate.bat.template: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if defined _OLD_VIRTUAL_PROMPT ( 4 | set PROMPT=%_OLD_VIRTUAL_PROMPT% 5 | ) 6 | set _OLD_VIRTUAL_PROMPT= 7 | 8 | if defined _OLD_VIRTUAL_PYTHONHOME ( 9 | set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% 10 | set _OLD_VIRTUAL_PYTHONHOME= 11 | ) 12 | 13 | if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% 14 | 15 | set _OLD_VIRTUAL_PATH= 16 | 17 | :END 18 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/getpythondist.py: -------------------------------------------------------------------------------- 1 | import sys 2 | print(sys.executable) 3 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/python: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | p=`dirname $0` 4 | path=`cd $p; pwd` 5 | exec ${path}/python.py "$@" 6 | 7 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/python.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | 4 | for /f "tokens=*" %%i in ('%~dp0\getpythondist.py') do set python=%%i 5 | call "%python%" "%~dp0\python.py" %* 6 | 7 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/bin/python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | use this file directly, or just set PYTHONPATH to your virtualenv directory 5 | and run system wide python instance 6 | ''' 7 | 8 | import os, sys 9 | from os import path 10 | from os.path import join, dirname, pardir, abspath 11 | 12 | 13 | def get_this_path(): 14 | ''' 15 | we do expect scripts are installed just one level deeper from venv 16 | ''' 17 | base = dirname(__file__) 18 | thispath = abspath(join(base, pardir)) 19 | return thispath 20 | 21 | def inject_pythonpath(): 22 | ''' 23 | insert virtualevn path into pythonpath 24 | ''' 25 | pypath = os.environ.get('PYTHONPATH', '').split(path.pathsep) 26 | thispath = get_this_path() 27 | try: 28 | pypath.remove('') 29 | pypath.remove(thispath) 30 | except ValueError: 31 | pass 32 | pypath.insert(0, thispath) 33 | os.environ['PYTHONPATH'] = path.pathsep.join(pypath) 34 | 35 | def prepare_argv(argv=[]): 36 | ''' 37 | prepare argv to run 38 | * windows platform needs add quotes around arguments with spaces 39 | ''' 40 | def q(s): 41 | return '"%s"' % s.replace('"', '\\"') 42 | if sys.platform == 'win32': 43 | argv = map(q, argv) 44 | return tuple(argv) 45 | 46 | def run(argv): 47 | os.execvp(sys.executable, argv) 48 | 49 | def main(argv=None): 50 | if argv is None: 51 | argv = sys.argv 52 | inject_pythonpath() 53 | run(prepare_argv(argv)) 54 | 55 | if __name__ == '__main__': 56 | main() 57 | 58 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/rvirtualenvkeep.py: -------------------------------------------------------------------------------- 1 | """ 2 | congratulations, it seems, you are inside 3 | python relocatable virtual environment 4 | """ 5 | -------------------------------------------------------------------------------- /rvirtualenv/template/inst/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from os import path 3 | import sys 4 | from distutils.core import setup 5 | 6 | scripts = ( 7 | 'bin/python.py', 8 | 'bin/activate.py', 9 | ) 10 | 11 | if sys.platform == 'win32': 12 | scripts += ( 13 | 'bin/getpythondist.py', 14 | 'bin/python.bat', 15 | 'bin/activate.bat', 16 | 'bin/activate.bat.template', 17 | 'bin/deactivate.bat', 18 | 'bin/deactivate.bat.template', 19 | ) 20 | else: 21 | scripts += ( 22 | 'bin/python', 23 | 'bin/activate', 24 | 'bin/activate.template', 25 | ) 26 | 27 | os.chdir(path.abspath(path.dirname(__file__))) 28 | setup( 29 | name='rvirtualenvkeep', 30 | version='0.1', 31 | py_modules=['rvirtualenvkeep'], 32 | scripts=scripts, 33 | ) 34 | 35 | -------------------------------------------------------------------------------- /rvirtualenv/template/venv/pythonrc.py: -------------------------------------------------------------------------------- 1 | 2 | scheme = 'custom' 3 | sitepackages = True 4 | #prompt = '[CUSTOM]' # set your custom prompt prefix (see -p option) 5 | #extra_paths = ['/path/to/inheriting/site-packages/',] # add some if you need access to other venvs 6 | 7 | -------------------------------------------------------------------------------- /rvirtualenv/template/venv/rvirtualenvinstall.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: rvirtualenvinstall 3 | Version: 0.1 4 | Summary: UNKNOWN 5 | Home-page: UNKNOWN 6 | Author: UNKNOWN 7 | Author-email: UNKNOWN 8 | License: UNKNOWN 9 | Description: UNKNOWN 10 | Platform: UNKNOWN 11 | -------------------------------------------------------------------------------- /rvirtualenv/template/venv/rvirtualenvinstall.egg-info/entry_points.txt: -------------------------------------------------------------------------------- 1 | [distutils.commands] 2 | developp = rvirtualenvinstall.develop:develop 3 | -------------------------------------------------------------------------------- /rvirtualenv/template/venv/site.py: -------------------------------------------------------------------------------- 1 | def __boot(): 2 | import sys, imp, os, os.path 3 | sys.__rvirtualenv_prev_path = list(sys.path) 4 | PYTHONPATH = os.environ.get('PYTHONPATH') 5 | if PYTHONPATH is None or (sys.platform=='win32' and not PYTHONPATH): 6 | PYTHONPATH = [] 7 | else: 8 | PYTHONPATH = PYTHONPATH.split(os.pathsep) 9 | 10 | pic = getattr(sys,'path_importer_cache',{}) 11 | stdpath = sys.path[len(PYTHONPATH):] 12 | mydir = os.path.dirname(__file__) 13 | #print "searching",stdpath,sys.path 14 | 15 | for item in stdpath: 16 | if item==mydir or not item: 17 | continue # skip if current dir. on Windows, or my own directory 18 | importer = pic.get(item) 19 | if importer is not None: 20 | loader = importer.find_module('site') 21 | if loader is not None: 22 | # This should actually reload the current module 23 | loader.load_module('site') 24 | break 25 | else: 26 | try: 27 | stream, path, descr = imp.find_module('site',[item]) 28 | except ImportError: 29 | continue 30 | if stream is None: 31 | continue 32 | try: 33 | # This should actually reload the current module 34 | imp.load_module('site',stream,path,descr) 35 | finally: 36 | stream.close() 37 | break 38 | else: 39 | raise ImportError("Couldn't find the real 'site' module") 40 | 41 | #print "loaded", __file__ 42 | 43 | known_paths = dict([(makepath(item)[1],1) for item in sys.path]) # 2.2 comp 44 | 45 | oldpos = getattr(sys,'__egginsert',0) # save old insertion position 46 | sys.__egginsert = 0 # and reset the current one 47 | 48 | for item in PYTHONPATH: 49 | addsitedir(item) 50 | 51 | sys.__egginsert += oldpos # restore effective old position 52 | 53 | d,nd = makepath(stdpath[0]) 54 | insert_at = None 55 | new_path = [] 56 | 57 | for item in sys.path: 58 | p,np = makepath(item) 59 | 60 | if np==nd and insert_at is None: 61 | # We've hit the first 'system' path entry, so added entries go here 62 | insert_at = len(new_path) 63 | 64 | if np in known_paths or insert_at is None: 65 | new_path.append(item) 66 | else: 67 | # new path after the insert point, back-insert it 68 | new_path.insert(insert_at, item) 69 | insert_at += 1 70 | 71 | sys.path[:] = new_path 72 | 73 | import rvirtualenvinstall.boot 74 | rvirtualenvinstall.boot.boot() 75 | 76 | 77 | if __name__=='site': 78 | __boot() 79 | del __boot 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from os import path 3 | 4 | 5 | VERSION = (0, 3, 2) 6 | __version__ = VERSION 7 | __versionstr__ = '.'.join(map(str, VERSION)) 8 | 9 | f = open(path.join(path.dirname(__file__), 'README.rst')) 10 | long_description = f.read().strip() 11 | f.close() 12 | 13 | 14 | setup( 15 | name = 'RVirtualEnv', 16 | description = "relocatable python virtual environment", 17 | url = "http://github.com/kvbik/rvirtualenv", 18 | long_description = long_description, 19 | version = __versionstr__, 20 | author = "Jakub Vysoky", 21 | author_email = "jakub@borka.cz", 22 | license = "BSD", 23 | packages = ['rvirtualenv'], 24 | entry_points = { 25 | 'console_scripts': [ 26 | 'rvirtualenv = rvirtualenv:main', 27 | ], 28 | }, 29 | zip_safe = False, 30 | include_package_data = True, 31 | test_suite = "tests.test_all.runtests", 32 | classifiers = [ 33 | "Development Status :: 4 - Beta", 34 | "Programming Language :: Python", 35 | "Programming Language :: Python :: 2", 36 | "Programming Language :: Python :: 3", 37 | "Intended Audience :: Developers", 38 | "License :: OSI Approved :: BSD License", 39 | "Operating System :: OS Independent", 40 | ] 41 | ) 42 | 43 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kvbik/rvirtualenv/aaacde2171144bc3c1d8ab8668e36a0dbc29bf3d/tests/__init__.py -------------------------------------------------------------------------------- /tests/helpers.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | from os import path 4 | from shutil import rmtree 5 | from unittest import TestCase 6 | from tempfile import mkdtemp 7 | 8 | import rvirtualenv 9 | 10 | 11 | class InTempTestCase(TestCase): 12 | def setUp(self): 13 | # unittest limit 14 | self.maxDiff = None 15 | 16 | # store curr path 17 | self.oldcwd = os.getcwd() 18 | 19 | # create test dir structure 20 | self.directory = mkdtemp(prefix='test_rvirtualenv_') 21 | 22 | # new rvirtualenv 23 | self.virtualenv = path.join(self.directory, 'PY') 24 | 25 | # store base dir 26 | self.base = path.join(path.dirname(rvirtualenv.__file__), path.pardir) 27 | 28 | def tearDown(self): 29 | # go back 30 | os.chdir(self.oldcwd) 31 | 32 | # dir cleanup 33 | rmtree(self.directory, True) 34 | 35 | def store_directory_structure(mypath, content=None): 36 | ''' 37 | recursivelly traverse directory and store it in format: 38 | ( 39 | (mypath, None), 40 | (mypath/to, None), 41 | (mypath/to/dir, None), 42 | (mypath/to/dir/file.txt, {{ file's content }}), 43 | ) 44 | ''' 45 | d = {} 46 | for base, dirs, files in os.walk(mypath): 47 | d[base] = None 48 | for i in files: 49 | fn = path.join(base, i) 50 | if content is not None: 51 | d[fn] = content 52 | continue 53 | f = open(fn, 'rb') 54 | d[fn] = f.read() 55 | f.close() 56 | return d.items() 57 | 58 | def relpath(p, start): 59 | "os.path.relpath dummy replacement" 60 | return p.replace(path.join(start, ''), '', 1) 61 | 62 | -------------------------------------------------------------------------------- /tests/installs/venvtest-distutils/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name='VEnvTest', 5 | version='0.1.0', 6 | py_modules=['venvtest'], 7 | ) 8 | 9 | -------------------------------------------------------------------------------- /tests/installs/venvtest-distutils/venvtest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __versionstr__ = '0.1.0' 4 | 5 | def main(): 6 | print('venvtest') 7 | 8 | if __name__ == '__main__': 9 | main() 10 | 11 | -------------------------------------------------------------------------------- /tests/installs/venvtest-setuptools/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='VEnvTest', 5 | version='0.1.0', 6 | py_modules=['venvtest'], 7 | zip_safe=True, 8 | ) 9 | 10 | -------------------------------------------------------------------------------- /tests/installs/venvtest-setuptools/venvtest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __versionstr__ = '0.1.0' 4 | 5 | def main(): 6 | print('venvtest') 7 | 8 | if __name__ == '__main__': 9 | main() 10 | 11 | -------------------------------------------------------------------------------- /tests/scripts/print.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | 4 | if len(sys.argv) > 1: 5 | print(sys.argv[1:]) 6 | 7 | -------------------------------------------------------------------------------- /tests/test_all.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | poor man's nosetests 5 | ''' 6 | 7 | import sys 8 | from os import path 9 | import unittest 10 | 11 | 12 | def runtests(): 13 | base = path.abspath(path.join(path.dirname(__file__), path.pardir)) 14 | 15 | # hack pythonpath to contain dir to load proper module for testing 16 | oldpath = sys.path[:] 17 | if base in sys.path: 18 | sys.path.remove(base) 19 | sys.path.insert(0, base) 20 | 21 | r = unittest.TextTestRunner() 22 | l = unittest.TestLoader() 23 | 24 | m = [ 25 | 'tests.test_copy', 26 | 'tests.test_generate', 27 | 'tests.test_rvirtualenv', 28 | ] 29 | 30 | result = r.run(l.loadTestsFromNames(m)) 31 | sys.exit(not result.wasSuccessful()) 32 | 33 | if __name__ == '__main__': 34 | runtests() 35 | 36 | -------------------------------------------------------------------------------- /tests/test_copy.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | from os import path 4 | 5 | from tests.helpers import InTempTestCase, store_directory_structure 6 | 7 | import rvirtualenv 8 | from rvirtualenv.copy import copy, ignore, remove_ignored 9 | 10 | 11 | class TestCopy(InTempTestCase): 12 | def test_ignore(self): 13 | names = [ 14 | 'abc.txt', 15 | 'koko/koko.pyc', 16 | 'keke/__pycache__', 17 | 'def.py', 18 | ] 19 | expected = set([ 20 | 'koko/koko.pyc', 21 | 'keke/__pycache__', 22 | ]) 23 | self.failUnlessEqual(expected, ignore(None, names)) 24 | 25 | def test_remove_ignored(self): 26 | # create some dummy dir structures 27 | for i in ('FROM', 'TO'): 28 | os.makedirs(path.join(self.directory, i)) 29 | os.makedirs(path.join(self.directory, i, '__pycache__')) 30 | f = open(path.join(self.directory, i, 'test.pyc'), 'w'); f.close() 31 | f = open(path.join(self.directory, i, 'test.py'), 'w'); f.close() 32 | # call our logic 33 | remove_ignored(path.join(self.directory, 'FROM'), path.join(self.directory, 'TO'), ignore) 34 | # some files should be removed 35 | self.assertFalse(path.exists(path.join(self.directory, 'TO', '__pycache__'))) 36 | self.assertFalse(path.exists(path.join(self.directory, 'TO', 'test.pyc'))) 37 | # other should stay 38 | self.assertTrue(path.exists(path.join(self.directory, 'TO', 'test.py'))) 39 | # and originals must not be touched 40 | self.assertTrue(path.exists(path.join(self.directory, 'FROM', '__pycache__'))) 41 | self.assertTrue(path.exists(path.join(self.directory, 'FROM', 'test.pyc'))) 42 | self.assertTrue(path.exists(path.join(self.directory, 'FROM', 'test.py'))) 43 | 44 | def test_whole_copy(self): 45 | base = path.dirname(rvirtualenv.__file__) 46 | 47 | os.chdir(path.join(base, 'template', 'venv')) 48 | a = list(store_directory_structure('.')) 49 | 50 | os.chdir(base) 51 | b = store_directory_structure('.') 52 | # filter only rvirtualenvinstall 53 | b = [ i for i in b if 'rvirtualenvinstall' in i[0] ] 54 | # extract not wanted 55 | b = [ i for i in b if 'template' not in i[0] ] 56 | 57 | os.chdir(path.join(base, 'template')) 58 | c = store_directory_structure('.') 59 | patrn = path.join('.', 'inst') 60 | repl = path.join('.', 'src', 'rvirtualenvkeep') 61 | c = [ (i.replace(patrn, repl),j) for (i,j) in c if patrn in i ] 62 | 63 | d = [(path.join('.', 'src'), None)] 64 | 65 | expected = sorted(a+b+c+d) 66 | # extract not wanted - aka those that are ignored 67 | expected = [ i for i in expected if '__pycache__' not in i[0] ] 68 | expected = [ i for i in expected if not i[0].endswith('pyc') ] 69 | 70 | copy(self.virtualenv) 71 | 72 | os.chdir(self.virtualenv) 73 | x = store_directory_structure('.') 74 | x = [ i for i in x if '__pycache__' not in i[0] ] 75 | got = sorted(x) 76 | 77 | self.failUnlessEqual([i for (i,j) in expected], [i for (i,j) in got]) 78 | self.failUnlessEqual(expected, got) 79 | 80 | -------------------------------------------------------------------------------- /tests/test_generate.py: -------------------------------------------------------------------------------- 1 | 2 | from os import path 3 | 4 | from tests.helpers import InTempTestCase, store_directory_structure 5 | 6 | import rvirtualenv 7 | from rvirtualenv.generate import generate 8 | from rvirtualenv.copy import copy 9 | from rvirtualenv.rvirtualenvinstall.scheme import get_scheme, guess_scheme 10 | 11 | 12 | class TestGenerate(InTempTestCase): 13 | def test_whole_generate(self, layout=None): 14 | copy(self.virtualenv) 15 | generate(self.virtualenv, layout=layout) 16 | structure = store_directory_structure(self.virtualenv, content='') 17 | 18 | if layout is None: 19 | layout = guess_scheme() 20 | 21 | paths = set((i for i,j in structure)) 22 | vars = {'base': self.virtualenv} 23 | self.assertTrue(get_scheme(layout, 'purelib', vars=vars) in paths) 24 | self.assertTrue(get_scheme(layout, 'scripts', vars=vars) in paths) 25 | 26 | pybin = path.join(get_scheme(layout, 'scripts', vars=vars), 'python.py') 27 | self.assertTrue(path.exists(pybin)) 28 | 29 | pyrc = path.join(self.virtualenv, 'pythonrc.py') 30 | self.assertTrue(path.exists(pyrc)) 31 | 32 | content = open(pyrc, 'r').read() 33 | self.assertFalse("scheme = 'custom'" in content) 34 | 35 | -------------------------------------------------------------------------------- /tests/test_rvirtualenv.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | import os 4 | from os import path 5 | from subprocess import Popen, PIPE 6 | import textwrap 7 | import logging 8 | 9 | from tests.helpers import InTempTestCase, relpath 10 | 11 | from rvirtualenv import main 12 | from rvirtualenv.rvirtualenvinstall.scheme import get_scheme, guess_scheme 13 | 14 | 15 | class TestRVirtualEnv(InTempTestCase): 16 | def setUp(self): 17 | super(TestRVirtualEnv, self).setUp() 18 | 19 | vars = {'base': self.virtualenv} 20 | self.python = path.join(get_scheme(guess_scheme(), 'scripts', vars=vars), 'python.py') 21 | 22 | def install_venv_in_isolation(self, virtualenv=None, sitepackages=True, prompt=None): 23 | ''' 24 | install rvirtualenv itself, but do it in subprocess, 25 | because of possible interaction with other imported libraries 26 | (eg: setuptools and its monkeypatching) 27 | ''' 28 | if virtualenv is None: 29 | virtualenv = self.virtualenv 30 | cmd = ('''%s -c "import sys; sys.path.insert(0, %r); ''' 31 | '''from rvirtualenv import create; create(%r, %s, %r)"''') % \ 32 | (sys.executable, self.base, virtualenv, sitepackages, prompt) 33 | stdout, stderr = self.run_command(cmd) 34 | self.failUnlessEqual('', stdout.strip()) 35 | self.failUnlessEqual('', stderr.strip()) 36 | 37 | def install_venv(self, args=[], virtualenv=None): 38 | if virtualenv is None: 39 | virtualenv = self.virtualenv 40 | argv = [None, virtualenv] 41 | argv[1:1] = args 42 | main(argv) 43 | 44 | def run_rvirtualenv_command(self, virtualenv): 45 | os.chdir(self.directory) 46 | self.install_venv_in_isolation(virtualenv) 47 | 48 | pythonrc = path.join(virtualenv, 'pythonrc.py') 49 | self.assertTrue(path.exists(pythonrc)) 50 | 51 | self.assertTrue(path.exists(self.python)) 52 | 53 | def test_rvirtualenv_command_creates_distdirs_given_absolute(self): 54 | self.run_rvirtualenv_command(self.virtualenv) 55 | 56 | def test_rvirtualenv_command_creates_distdirs_given_relative(self): 57 | self.run_rvirtualenv_command('PY') 58 | 59 | def run_command(self, cmd): 60 | shell = sys.platform != 'win32' 61 | p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=shell) 62 | return map(lambda b: b.decode(sys.stdout.encoding or 'UTF-8'), p.communicate()) 63 | 64 | def test_python_itself(self): 65 | self.install_venv() 66 | 67 | cmd = '%s %s -c "print(128)"' % (sys.executable, self.python) 68 | stdout, stderr = self.run_command(cmd) 69 | self.failUnlessEqual('128', stdout.strip()) 70 | 71 | def test_venv_without_site_packages(self): 72 | ''' 73 | setuptools installed system-wide is needed for this test 74 | ''' 75 | v1 = path.join(self.directory, 'PY1') 76 | py1 = path.join(get_scheme(guess_scheme(), 'scripts', vars={'base': v1}), 'python.py') 77 | self.install_venv(args=[], virtualenv=v1) 78 | cmd = '%s %s -c "import setuptools"' % (sys.executable, py1) 79 | stdout, stderr = self.run_command(cmd) 80 | self.failUnlessEqual('', stderr.strip()) 81 | self.failUnlessEqual('', stdout.strip()) 82 | 83 | v2 = path.join(self.directory, 'PY2') 84 | py2 = path.join(get_scheme(guess_scheme(), 'scripts', vars={'base': v2}), 'python.py') 85 | self.install_venv(args=['--no-site-packages'], virtualenv=v2) 86 | cmd = '%s %s -c "import setuptools"' % (sys.executable, py2) 87 | stdout, stderr = self.run_command(cmd) 88 | self.assertTrue('ImportError: No module named setuptools' in stderr) 89 | 90 | def test_run_python_script(self): 91 | self.install_venv() 92 | 93 | script = path.join(self.base, 'tests', 'scripts','print.py') 94 | cmd = '%s %s %s' % (sys.executable, self.python, script) 95 | stdout, stderr = self.run_command(cmd) 96 | self.failUnlessEqual('', stdout) 97 | 98 | def test_run_python_script_with_args(self): 99 | self.install_venv() 100 | 101 | script = path.join(self.base, 'tests', 'scripts','print.py') 102 | cmd = '%s %s %s a b c' % (sys.executable, self.python, script) 103 | stdout, stderr = self.run_command(cmd) 104 | self.failUnlessEqual("['a', 'b', 'c']", stdout.strip()) 105 | 106 | def install_some_way(self, inst_type, inst_command='install'): 107 | self.install_venv() 108 | 109 | os.chdir(path.join(self.base, 'tests', 'installs', 110 | 'venvtest-%s' % inst_type)) 111 | inst = '%s %s setup.py %s' % \ 112 | (sys.executable, self.python, inst_command) 113 | stdout, stderr = self.run_command(inst) 114 | os.chdir(self.oldcwd) 115 | 116 | logging.info('stdout:') 117 | logging.info(stdout) 118 | logging.info('stderr:') 119 | logging.info(stderr) 120 | 121 | self.failUnlessEqual('', stderr) 122 | 123 | cmd = '%s %s -c "import venvtest; print(venvtest.__versionstr__)"' % \ 124 | (sys.executable, self.python) 125 | stdout, stderr = self.run_command(cmd) 126 | expected = '0.1.0' 127 | self.failUnlessEqual(expected, stdout.strip()) 128 | 129 | cmd = '%s %s -c "import venvtest; print(venvtest.__file__)"' % \ 130 | (sys.executable, self.python) 131 | stdout, stderr = self.run_command(cmd) 132 | a = len(self.virtualenv) 133 | b = -len('venvtest.pyX') 134 | env = stdout.strip()[:a] 135 | mod = stdout.strip()[b:] 136 | pth = stdout.strip()[a:b] 137 | 138 | logging.info(pth) 139 | 140 | self.failUnlessEqual(self.virtualenv, env) 141 | # it could be *.py or *.pyc - depending on distro 142 | self.failUnlessEqual('venvtest.py', mod.strip(r'\c/')) 143 | 144 | def test_install_distutils_way(self): 145 | self.install_some_way('distutils') 146 | 147 | def test_install_setuptools_way(self): 148 | ''' 149 | this test should skip if you don't have setuptools 150 | but other tests could fail too.. 151 | ''' 152 | inst_command = ('install' 153 | ' --single-version-externally-managed' 154 | ' --record %s' % path.join(self.directory, 'record.log')) 155 | self.install_some_way('setuptools', inst_command=inst_command) 156 | 157 | def activate_command_unix(self): 158 | scripts = relpath(path.dirname(self.python), self.directory) 159 | activate = 'source %s' % path.join(scripts, 'activate') 160 | deactivate = 'deactivate' 161 | run_command = 'bash run' 162 | run_file = 'run' 163 | shebang = '#!/bin/sh' 164 | self.activate_command(activate, deactivate, 165 | run_command, run_file, shebang) 166 | 167 | def activate_command_win(self): 168 | scripts = relpath(path.dirname(self.python), self.directory) 169 | activate = 'call %s' % path.join(scripts, 'activate.bat') 170 | deactivate = 'call deactivate.bat' 171 | run_command = 'run.bat' 172 | run_file = 'run.bat' 173 | shebang = '@echo off' 174 | out_filter = lambda x: x.lower() 175 | self.activate_command(activate, deactivate, 176 | run_command, run_file, shebang, out_filter) 177 | 178 | def activate_command(self, activate, deactivate, 179 | run_command, run_file, shebang, out_filter=lambda x:x): 180 | os.chdir(self.directory) 181 | self.install_venv() 182 | f = open(run_file, 'w') 183 | f.write(textwrap.dedent(''' 184 | %s 185 | %s 186 | python -c "import rvirtualenvkeep; print(rvirtualenvkeep.__file__)" 187 | %s 188 | ''' % (shebang, activate, deactivate)).strip()) 189 | f.close() 190 | stdout, stderr = self.run_command(run_command) 191 | stdout = out_filter(stdout) 192 | 193 | ''' 194 | from shutil import copytree, rmtree 195 | tempdir = path.join(self.base, 'TSTPY') 196 | rmtree(tempdir, True) 197 | copytree(self.directory, tempdir) 198 | ''' 199 | 200 | self.failUnlessEqual(stderr.strip(), '') 201 | self.assertTrue(stdout.strip().startswith(path.realpath(self.directory))) 202 | self.assertTrue( 203 | stdout.strip().endswith('rvirtualenvkeep.pyo') or \ 204 | stdout.strip().endswith('rvirtualenvkeep.pyc') or \ 205 | stdout.strip().endswith('rvirtualenvkeep.py') 206 | ) 207 | 208 | def test_activate_command(self): 209 | if sys.platform == 'win32': 210 | self.activate_command_win() 211 | else: 212 | self.activate_command_unix() 213 | 214 | def something_is_bad_on_win32_and_subprocess(self, py, command=None): 215 | replace_command = command 216 | 217 | if sys.platform == 'win32': 218 | name = 'pokus.bat' 219 | command = name 220 | bat = ('@echo off', '"%s" pokus.py' % sys.executable,) 221 | else: 222 | name = 'pokus.sh' 223 | command = 'sh pokus.sh' 224 | bat = ('#!/bin/sh', 'python pokus.py',) 225 | 226 | if replace_command is not None: 227 | command = replace_command 228 | 229 | write = '\n'.join(py) 230 | f = open('pokus.py', 'w'); f.write(write); f.close() 231 | 232 | write = '\n'.join(bat) 233 | f = open(name, 'w'); f.write(write); f.close() 234 | 235 | shell = True 236 | p = Popen(command, stdout=PIPE, stderr=PIPE, shell=shell) 237 | stdout, stderr = map( 238 | lambda b: b.decode(sys.stdout.encoding or 'UTF-8'), p.communicate()) 239 | self.failUnlessEqual('128', stdout.strip()) 240 | 241 | def test_something_is_bad_on_win32_and_os_system(self): 242 | py = ('import os', 'os.system("echo 128")') 243 | self.something_is_bad_on_win32_and_subprocess(py) 244 | 245 | def test_something_is_bad_on_win32_and_popen(self): 246 | py = ( 247 | 'from subprocess import Popen, PIPE', 248 | 'p = Popen("echo 128", shell=True)', 249 | 'p.communicate()', 250 | ) 251 | self.something_is_bad_on_win32_and_subprocess(py) 252 | 253 | def test_something_is_bad_on_win32_but_this_works(self): 254 | py = ('import os', 'os.system("echo 128")') 255 | #command = 'call pokus.bat' # this doesn't work either 256 | command = '"%s" pokus.py' % sys.executable 257 | self.something_is_bad_on_win32_and_subprocess(py, command) 258 | 259 | --------------------------------------------------------------------------------