Index: Python/sysmodule.c =================================================================== --- Python/sysmodule.c (Revision 59932) +++ Python/sysmodule.c (Arbeitskopie) @@ -1045,6 +1045,50 @@ return shortbranch; } +static PyObject* +makecmdflags(void) +{ + PyObject *tup; + int size = 0; + + tup = PyTuple_New(20); + if (tup == NULL) { + return NULL; + } + +#define AddStringIf(flag, s) if (flag) do { \ + PyObject *str = PyString_FromString(s); \ + if (str == NULL) return NULL; \ + PyTuple_SET_ITEM(tup, size++, str); \ + } while(0) + + AddStringIf(Py_DebugFlag, "d"); + AddStringIf(Py_Py3kWarningFlag, "3"); + AddStringIf(Py_DivisionWarningFlag == 1, "Q1"); + AddStringIf(Py_DivisionWarningFlag == 2, "Q2"); + AddStringIf(_Py_QnewFlag, "Qnew"); + AddStringIf(Py_InspectFlag && Py_InteractiveFlag, "i"); + AddStringIf(Py_OptimizeFlag, "O"); + AddStringIf(Py_OptimizeFlag > 1, "OO"); + AddStringIf(Py_DontWriteBytecodeFlag, "B"); + AddStringIf(Py_NoSiteFlag, "S"); + AddStringIf(Py_IgnoreEnvironmentFlag, "E"); + AddStringIf(Py_TabcheckFlag, "t"); + AddStringIf(Py_TabcheckFlag > 1, "tt"); + /* AddStringIf(saw_unbuffered_flag, "u"); */ + AddStringIf(Py_VerboseFlag, "v"); +#ifdef RISCOS + AddStringIf(Py_RISCOSWimpFlag, "w"); +#endif + /* AddStringIf(skipfirstline, "x"); */ + AddStringIf(Py_UnicodeFlag, "U"); + + _PyTuple_Resize(&tup, size); + + return tup; +#undef AddStringIf +} + PyObject * _PySys_Init(void) { @@ -1131,6 +1175,11 @@ PyDict_SetItemString(sysdict, "dont_write_bytecode", v = PyBool_FromLong(Py_DontWriteBytecodeFlag)); Py_XDECREF(v); + + PyDict_SetItemString(sysdict, "cmd_flags", + v = makecmdflags()); + /*Py_XDECREF(v);*/ + /* * These release level checks are mutually exclusive and cover * the field, so don't get too fancy with the pre-processor! Index: Lib/site.py =================================================================== --- Lib/site.py (Revision 59932) +++ Lib/site.py (Arbeitskopie) @@ -62,6 +62,7 @@ import os import __builtin__ +_global_userdir = None def makepath(*paths): dir = os.path.abspath(os.path.join(*paths)) @@ -173,42 +174,91 @@ known_paths = None return known_paths -def addsitepackages(known_paths): + +def adduserpackages(known_paths=None): + """Add a per user site-package to sys.path + + Each user has its own python directory with site-packages in the + home directory. _global_userdirs contains (basedir, user site-packages) + although the directories may not exist. + + basedir is the root directory for all Python versions, userdir is the + user specific site-packages directory. userdir/.. can be used for + configuration data. + """ + global _global_userdir + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + if known_paths is None: + known_paths = sys.path + + #if sys.platform in ('os2emx', 'riscos'): + # # Don't know what to put here + # userdir = '' + # basedir = '' + if sys.platform == "darwin": + basedir = joinuser("~", "Library", "Python") + userdir = os.path.join(basedir, sys.version[:3], + "site-packages") + elif os.name == "nt": + base = os.environ.get("APPDATA") or "~" + basedir = joinuser(base, "Python") + userdir = os.path.join(basedir, + "Python" + sys.version[0] + sys.version[2], + "site-packages") + else: + basedir = joinuser("~", ".local") + userdir = os.path.join(basedir, "lib", "python" + sys.version[:3], + "site-packages") + + if os.path.isdir(userdir): + addsitedir(userdir, known_paths) + + _global_userdir = (basedir, userdir) + + +def addsitepackages(known_paths=None, prefixes=None): """Add site-packages (and possibly site-python) to sys.path""" - prefixes = [sys.prefix] - if sys.exec_prefix != sys.prefix: - prefixes.append(sys.exec_prefix) + sitedirs = [] + + if known_paths is None: + known_paths = sys.path + + if prefixes is None: + prefixes = [sys.prefix] + if sys.prefix != sys.exec_prefix: + prefixes.append(sys.exec_prefix) + for prefix in prefixes: - if prefix: - if sys.platform in ('os2emx', 'riscos'): - sitedirs = [os.path.join(prefix, "Lib", "site-packages")] - elif os.sep == '/': - sitedirs = [os.path.join(prefix, - "lib", - "python" + sys.version[:3], - "site-packages"), - os.path.join(prefix, "lib", "site-python")] - else: - sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] - if sys.platform == 'darwin': - # for framework builds *only* we add the standard Apple - # locations. Currently only per-user, but /Library and - # /Network/Library could be added too - if 'Python.framework' in prefix: - home = os.environ.get('HOME') - if home: - sitedirs.append( - os.path.join(home, - 'Library', - 'Python', - sys.version[:3], - 'site-packages')) - for sitedir in sitedirs: - if os.path.isdir(sitedir): - addsitedir(sitedir, known_paths) - return None + if not prefix: + continue + if sys.platform in ('os2emx', 'riscos'): + sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) + elif os.sep == '/': + sitedirs.append(os.path.join(prefix, "lib", + "python" + sys.version[:3], + "site-packages")) + sitedirs.append(os.path.join(prefix, "lib", "site-python")) + else: + sitedirs.append(prefix) + sitedirs.append(os.path.join(prefix, "lib", "site-packages")) + #if False and sys.platform == "darwin": + # # for framework builds *only* we add the standard Apple + # # locations. Currently only per-user, but /Library and + # # /Network/Library could be added too + # if 'Python.framework' in prefix: + # sitedirs.append( + # os.path.expanduser( + # os.path.join("~", "Library", "Python", + # sys.version[:3], "site-packages"))) + for sitedir in sitedirs: + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + + def setBEGINLIBPATH(): """The OS/2 EMX port has optional extension modules that do double duty as DLLs (and must use the .DLL file extension) for other extensions. @@ -393,13 +443,23 @@ pass +def execusercustomize(): + """Run custom user specific code, if available.""" + try: + import usercustomize + except ImportError: + pass + + def main(): abs__file__() paths_in_sys = removeduppaths() if (os.name == "posix" and sys.path and os.path.basename(sys.path[-1]) == "Modules"): addbuilddir() - paths_in_sys = addsitepackages(paths_in_sys) + adduserpackages() + #addsitepackages(prefixes=[os.path.join(sys.prefix, "local")]) + addsitepackages() if sys.platform == 'os2emx': setBEGINLIBPATH() setquit() @@ -408,6 +468,7 @@ aliasmbcs() setencoding() execsitecustomize() + execusercustomize() # Remove sys.setdefaultencoding() so that users cannot change the # encoding after initialization. The test for presence is needed when # this module is run as a script, because this code is executed twice. Index: Lib/distutils/command/install.py =================================================================== --- Lib/distutils/command/install.py (Revision 59932) +++ Lib/distutils/command/install.py (Arbeitskopie) @@ -18,7 +18,10 @@ from distutils.util import convert_path, subst_vars, change_root from distutils.errors import DistutilsOptionError from glob import glob +import site +userbase, usersite = site._global_userdir + if sys.version < "2.2": WINDOWS_SCHEME = { 'purelib': '$base', @@ -51,7 +54,21 @@ 'scripts': '$base/bin', 'data' : '$base', }, + 'unix_user': { + 'purelib': '$usersite', + 'platlib': '$usersite', + 'headers': '$userbase/include/python$py_version_short/$dist_name', + 'scripts': '~/bin', + 'data' : '$userbase', + }, 'nt': WINDOWS_SCHEME, + 'nt_user': { + 'purelib': '$usersite', + 'platlib': '$usersite', + 'headers': '$userbase/Python$py_version_nodot/Include/$dist_name', + 'scripts': '$userbase/Scripts', + 'data' : '$userbase', + }, 'mac': { 'purelib': '$base/Lib/site-packages', 'platlib': '$base/Lib/site-packages', @@ -59,6 +76,13 @@ 'scripts': '$base/Scripts', 'data' : '$base', }, + 'mac_user': { + 'purelib': '$usersite', + 'platlib': '$usersite', + 'headers': '$userbase/$py_version_short/include/$dist_name', + 'scripts': '~/bin', + 'data' : '$userbase', + }, 'os2': { 'purelib': '$base/Lib/site-packages', 'platlib': '$base/Lib/site-packages', @@ -86,6 +110,8 @@ "(Unix only) prefix for platform-specific files"), ('home=', None, "(Unix only) home directory to install under"), + ('user', None, + "install in user site-package '%s'" % usersite), # Or, just set the base director(y|ies) ('install-base=', None, @@ -137,7 +163,7 @@ "filename in which to record list of installed files"), ] - boolean_options = ['compile', 'force', 'skip-build'] + boolean_options = ['compile', 'force', 'skip-build', 'user'] negative_opt = {'no-compile' : 'compile'} @@ -148,6 +174,7 @@ self.prefix = None self.exec_prefix = None self.home = None + self.user = 0 # These select only the installation base; it's up to the user to # specify the installation scheme (currently, that means supplying @@ -166,6 +193,8 @@ self.install_lib = None # set to either purelib or platlib self.install_scripts = None self.install_data = None + self.install_userbase = userbase + self.install_usersite = usersite self.compile = None self.optimize = None @@ -241,6 +270,11 @@ raise DistutilsOptionError, \ "must supply either home or prefix/exec-prefix -- not both" + if self.user and (self.prefix or self.exec_prefix or self.home or + self.install_base or self.install_platbase): + raise DistutilsOptionError("can't combine user with with prefix/" + "exec_prefix/home or install_(plat)base") + # Next, stuff that's wrong (or dubious) only on certain platforms. if os.name != "posix": if self.exec_prefix: @@ -276,10 +310,13 @@ 'dist_fullname': self.distribution.get_fullname(), 'py_version': py_version, 'py_version_short': py_version[0:3], + 'py_version_nodot': py_version[0] + py_version[2], 'sys_prefix': prefix, 'prefix': prefix, 'sys_exec_prefix': exec_prefix, 'exec_prefix': exec_prefix, + 'userbase': userbase, + 'usersite': usersite, } self.expand_basedirs() @@ -301,6 +338,10 @@ self.dump_dirs("post-expand_dirs()") + # Create directories in the home dir: + if self.user: + self.create_home_path() + # Pick the actual directory to install all modules to: either # install_purelib or install_platlib, depending on whether this # module distribution is pure or not. Of course, if the user @@ -315,7 +356,8 @@ # Convert directories from Unix /-separated syntax to the local # convention. self.convert_paths('lib', 'purelib', 'platlib', - 'scripts', 'data', 'headers') + 'scripts', 'data', 'headers', + 'userbase', 'usersite') # Well, we're not actually fully completely finalized yet: we still # have to deal with 'extra_path', which is the hack for allowing @@ -376,7 +418,10 @@ "installation scheme is incomplete") return - if self.home is not None: + if self.user: + self.install_base = self.install_platbase = userbase + self.select_scheme("unix_user") + elif self.home is not None: self.install_base = self.install_platbase = self.home self.select_scheme("unix_home") else: @@ -401,7 +446,10 @@ def finalize_other (self): # Windows and Mac OS for now - if self.home is not None: + if self.user: + self.install_base = self.install_platbase = userbase + self.select_scheme(os.name + "_user") + elif self.home is not None: self.install_base = self.install_platbase = self.home self.select_scheme("unix_home") else: @@ -431,7 +479,7 @@ for attr in attrs: val = getattr(self, attr) if val is not None: - if os.name == 'posix': + if os.name == 'posix' or os.name == 'nt': val = os.path.expanduser(val) val = subst_vars(val, self.config_vars) setattr(self, attr, val) @@ -496,6 +544,16 @@ attr = "install_" + name setattr(self, attr, change_root(self.root, getattr(self, attr))) + def create_home_path(self): + """Create directories under ~ + """ + if not self.user: + return + home = convert_path(os.path.expanduser("~")) + for name, path in self.config_vars.iteritems(): + if path.startswith(home) and not os.path.isdir(path): + self.debug_print("os.makedirs('%s', 0700)" % path) + os.makedirs(path, 0700) # -- Command execution methods -------------------------------------