PKYEjpythonz/__init__.py import os import sys from optparse import OptionParser from pythonz.commands import command_map, load_commands from pythonz.define import PATH_HOME_ETC, PATH_PYTHONS from pythonz.util import makedirs parser = OptionParser(usage="%prog COMMAND [OPTIONS]", prog="pythonz", add_help_option=False) parser.add_option( '-h', '--help', dest='help', action='store_true', help='Show help') parser.disable_interspersed_args() def main(): options, args = parser.parse_args(sys.argv[1:]) if options.help and not args: args = ['help'] if not args: args = ['help'] # as default makedirs(PATH_PYTHONS) makedirs(PATH_HOME_ETC) load_commands() command = args[0].lower() try: command = command_map[command] except KeyError: parser.error("Unknown command: `%s`" % command) return try: command.run(args[1:]) except KeyboardInterrupt: pass PKYE mmpythonz/__main__.py"""For development purposes, support invocation of pythonz with python -m.""" import pythonz pythonz.main() PKYEkXKpythonz/log.py import sys class Color(object): DEBUG = '\033[35m' INFO = '\033[32m' WARNING = '\033[31m' ERROR = '\033[31m' ENDC = '\033[0m' @classmethod def _deco(cls, msg, color): return '%s%s%s' % (color, msg, cls.ENDC) @classmethod def debug(cls, msg): return cls._deco(msg, cls.DEBUG) @classmethod def info(cls, msg): return cls._deco(msg, cls.INFO) @classmethod def warning(cls, msg): return cls._deco(msg, cls.WARNING) @classmethod def error(cls, msg): return cls._deco(msg, cls.ERROR) class Logger(object): def debug(self, msg): self._stdout(Color.debug("DEBUG: %s\n" % msg)) def log(self, msg): self._stdout("%s\n" % (msg)) def info(self, msg): self._stdout(Color.info('%s\n' % msg)) def warning(self, msg): self._stderr(Color.warning("WARNING: %s\n" % msg)) def error(self, msg): self._stderr(Color.error("ERROR: %s\n" % msg)) def _stdout(self, msg): sys.stdout.write(msg) sys.stdout.flush() def _stderr(self, msg): sys.stderr.write(msg) sys.stderr.flush() logger = Logger() PK3Hpythonz/define.py import os # pythonz installer root path INSTALLER_ROOT = os.path.dirname(os.path.abspath(__file__)) # Root # pythonz root path SYSTEMWIDE_PATH = '/usr/local/pythonz' ROOT = os.environ.get('PYTHONZ_ROOT') or os.path.join(os.environ['HOME'], '.pythonz') if not os.path.abspath(os.path.dirname(__file__)).startswith(SYSTEMWIDE_PATH) else SYSTEMWIDE_PATH # directories PATH_PYTHONS = os.path.join(ROOT, 'pythons') PATH_BUILD = os.path.join(ROOT, 'build') PATH_DISTS = os.path.join(ROOT, 'dists') PATH_ETC = os.path.join(ROOT, 'etc') PATH_BASH_COMPLETION = os.path.join(PATH_ETC, 'bash_completion.d') PATH_BIN = os.path.join(ROOT, 'bin') PATH_LOG = os.path.join(ROOT, 'log') PATH_SCRIPTS = os.path.join(ROOT, 'scripts') PATH_SCRIPTS_PYTHONZ = os.path.join(PATH_SCRIPTS, 'pythonz') PATH_SCRIPTS_PYTHONZ_COMMANDS = os.path.join(PATH_SCRIPTS_PYTHONZ, 'commands') PATH_SCRIPTS_PYTHONZ_INSTALLER = os.path.join(PATH_SCRIPTS_PYTHONZ, 'installer') PATH_PATCHES = os.path.join(INSTALLER_ROOT, 'patches') PATH_PATCHES_ALL = os.path.join(PATH_PATCHES, 'all') PATH_PATCHES_OSX = os.path.join(PATH_PATCHES, 'osx') # files PATH_BIN_PYTHONZ = os.path.join(PATH_BIN, 'pythonz') # Home # pythonz home path PATH_HOME = os.environ.get('PYTHONZ_HOME') or os.path.join(os.environ['HOME'], '.pythonz') # directories PATH_HOME_ETC = os.path.join(PATH_HOME, 'etc') # pythonz download PYTHONZ_UPDATE_URL = 'https://github.com/saghul/pythonz/archive/master.tar.gz' PK3HGAApythonz/downloader.pyimport sys import os from pythonz.util import PY3K from pythonz.log import logger if PY3K: from urllib.request import Request, urlopen else: from urllib2 import urlopen, Request try: from resumable import urlretrieve, DownloadError, sha256 except ImportError: from mmap import mmap as _mmap, ACCESS_READ import hashlib if PY3K: from urllib.request import urlretrieve as _urlretrieve mmap = _mmap else: from contextlib import closing mmap = lambda *args, **kwargs: closing(_mmap(*args, **kwargs)) from urllib import urlretrieve as _urlretrieve class DownloadError(Exception): """Exception during download""" def sha256(filename): with open(filename, 'rb') as f: with mmap(f.fileno(), 0, access=ACCESS_READ) as m: return hashlib.sha256(m).hexdigest() def validate_sha256(filename, sha256sum): if sha256sum is not None: return sha256(filename) == sha256sum else: logger.warning("sha256sum unavailable, skipping verification.\nMake " "sure that the server you're downloading from is trusted") return True def urlretrieve(url, filename, reporthook, sha256sum): try: _urlretrieve(url, filename, reporthook) if not validate_sha256(filename, sha256sum): raise DownloadError("Corrupted download, the sha256 doesn't match") except BaseException: os.unlink(filename) raise class ProgressBar(object): def __init__(self, out=sys.stdout): self._term_width = 79 self._out = out def update_line(self, current): num_bar = int(current / 100.0 * (self._term_width - 5)) bars = '#' * num_bar spaces = ' ' * (self._term_width - 5 - num_bar) percentage = '%3d' % int(current) + '%\r' result = bars + spaces + ' ' + percentage if not PY3K: # Python 2.x return result.decode("utf-8") return result def reporthook(self, blocknum, bs, size): if size in (-1, None): # disable progress bar if size not known return current = (blocknum * bs * 100) / size if current > 100: current = 100 self._out.write(self.update_line(current)) self._out.flush() def finish(self): self._out.write(self.update_line(100)) self._out.flush() class HEADRequest(Request): def get_method(self): return "HEAD" class Downloader(object): @classmethod def read(cls, url): try: r = urlopen(url) except IOError: raise DownloadError('Failed to fetch %s' % url) else: return r.read() @classmethod def read_head_info(cls, url): try: req = HEADRequest(url) res = urlopen(req) except IOError: raise DownloadError('Failed to fetch %s' % url) else: if res.code != 200: raise DownloadError('Failed to fetch %s' % url) return res.info() @classmethod def fetch(cls, url, filename, expected_sha256=None): b = ProgressBar() try: urlretrieve(url, filename, b.reporthook, sha256sum=expected_sha256) sys.stdout.write('\n') except DownloadError: if os.path.exists(filename): os.unlink(filename) raise except IOError: sys.stdout.write('\n') raise DownloadError('Failed to fetch %s from %s' % (filename, url)) PK3H|..pythonz/util.py import os import sys import errno import shutil import re import posixpath import tarfile import platform import subprocess import shlex import select PY3K = sys.version_info >= (3,) if not PY3K: from urllib import quote as urlquote, unquote as urlunquote from urllib2 import urlparse else: from urllib.parse import urlparse, quote as urlquote, unquote as urlunquote from pythonz.define import PATH_PYTHONS from pythonz.log import logger def is_url(name): try: result = urlparse.urlparse(name) except Exception: return False else: return result.scheme in ('http', 'https', 'file', 'ftp') def is_file(name): try: result = urlparse.urlparse(name) except Exception: return False else: return result.scheme == 'file' def splitext(name): base, ext = os.path.splitext(name) if base.lower().endswith('.tar'): ext = base[-4:] + ext base = base[:-4] return base, ext def is_archive_file(name): ext = splitext(name)[1].lower() return ext in ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar') def is_html(content_type): return content_type and content_type.startswith('text/html') def is_gzip(content_type, filename): return content_type == 'application/x-gzip' or tarfile.is_tarfile(filename) or splitext(filename)[1].lower() in ('.tar', '.tar.gz', '.tgz', '.tar.bz2', '.tbz') def get_macosx_deployment_target(): m = re.search('^([0-9]+\.[0-9]+)', platform.mac_ver()[0]) if m: return m.group(1) return None def _py_version_cmp(v, v1, v2): if is_str(v): v = Version(v) return v >= v1 and v < v2 def is_python24(version): return _py_version_cmp(version, '2.4', '2.5') def is_python25(version): return _py_version_cmp(version, '2.5', '2.6') def is_python26(version): return _py_version_cmp(version, '2.6', '2.7') def is_python27(version): return _py_version_cmp(version, '2.7', '2.8') def is_python30(version): return _py_version_cmp(version, '3.0', '3.1') def is_python31(version): return _py_version_cmp(version, '3.1', '3.2') def is_python32(version): return _py_version_cmp(version, '3.2', '3.3') def is_python33(version): return _py_version_cmp(version, '3.3', '3.4') def makedirs(path): if not os.path.exists(path): os.makedirs(path) def symlink(src, dst): try: os.symlink(src, dst) except OSError: pass def unlink(path): try: os.unlink(path) except OSError as e: if e.errno != errno.ENOENT: raise def rm_r(path): """like rm -r command.""" if os.path.isdir(path): shutil.rmtree(path) elif os.path.isfile(path): unlink(path) def split_leading_dir(path): path = str(path) path = path.lstrip('/').lstrip('\\') if '/' in path and (('\\' in path and path.find('/') < path.find('\\')) or '\\' not in path): return path.split('/', 1) elif '\\' in path: return path.split('\\', 1) else: return path, '' def has_leading_dir(paths): """Returns true if all the paths have the same leading path name (i.e., everything is in one subdirectory in an archive)""" common_prefix = None for path in paths: prefix, rest = split_leading_dir(path) if not prefix: return False elif common_prefix is None: common_prefix = prefix elif prefix != common_prefix: return False return True def untar_file(filename, location): if not os.path.exists(location): os.makedirs(location) if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): mode = 'r:gz' elif filename.lower().endswith('.bz2') or filename.lower().endswith('.tbz'): mode = 'r:bz2' elif filename.lower().endswith('.tar'): mode = 'r' else: logger.error('Cannot determine compression type for file %s' % filename) mode = 'r:*' tar = tarfile.open(filename, mode) try: # note: python<=2.5 doesnt seem to know about pax headers, filter them leading = has_leading_dir([ member.name for member in tar.getmembers() if not member.name.startswith('.') and member.name != 'pax_global_header' ]) for member in tar.getmembers(): fn = member.name if fn == 'pax_global_header': continue if leading: fn = split_leading_dir(fn)[1] path = os.path.join(location, fn) if member.isdir(): if not os.path.exists(path): os.makedirs(path) else: try: fp = tar.extractfile(member) except (KeyError, AttributeError): e = sys.exc_info()[1] # Some corrupt tar files seem to produce this # (specifically bad symlinks) logger.error('In the tar file %s the member %s is invalid: %s' % (filename, member.name, e)) continue if not os.path.exists(os.path.dirname(path)): os.makedirs(os.path.dirname(path)) destfp = open(path, 'wb') try: shutil.copyfileobj(fp, destfp) finally: destfp.close() fp.close() # note: configure ...etc os.chmod(path, member.mode) # note: the file timestamps should be such that asdl_c.py is not invoked. os.utime(path, (member.mtime, member.mtime)) finally: tar.close() def extract_downloadfile(content_type, download_file, target_dir): logger.info("Extracting %s into %s" % (os.path.basename(download_file), target_dir)) if is_gzip(content_type, download_file): untar_file(download_file, target_dir) else: raise RuntimeError("Cannot determine archive format of %s" % download_file) def is_installed(pkg): return os.path.isdir(os.path.join(PATH_PYTHONS, pkg.name)) def path_to_fileurl(path): path = os.path.normcase(os.path.abspath(path)) url = urlquote(path) url = url.replace(os.path.sep, '/') url = url.lstrip('/') return 'file:///' + url def fileurl_to_path(url): assert url.startswith('file:'), ('Illegal scheme:%s' % url) url = '/' + url[len('file:'):].lstrip('/') return urlunquote(url) def to_str(val): if not PY3K: # python2 if isinstance(val, unicode): return val.encode("utf-8") return val if isinstance(val, bytes): return val.decode("utf-8") return val def is_str(val): if not PY3K: # python2 return isinstance(val, basestring) # python3 return isinstance(val, str) def is_sequence(val): if is_str(val): return False return (hasattr(val, "__getitem__") or hasattr(val, "__iter__")) #----------------------------- # class #----------------------------- class ShellCommandException(Exception): """General exception during shell command""" class Subprocess(object): def __init__(self, log=None, cwd=None, verbose=False, debug=False): self._log = log self._cwd = cwd self._verbose = verbose self._debug = debug def chdir(self, cwd): self._cwd = cwd def shell(self, cmd): if self._debug: logger.log(cmd) if is_sequence(cmd): cmd = ''.join(cmd) if self._log: if self._verbose: cmd = "(%s) 2>&1 | tee '%s'" % (cmd, self._log) else: cmd = "(%s) >> '%s' 2>&1" % (cmd, self._log) returncode = subprocess.call(cmd, shell=True, cwd=self._cwd) if returncode: raise ShellCommandException('%s: failed to `%s`' % (returncode, cmd)) def call(self, cmd): if is_str(cmd): cmd = shlex.split(cmd) if self._debug: logger.log(cmd) fp = ((self._log and open(self._log, 'a')) or None) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self._cwd) while p.returncode is None: while any(select.select([p.stdout], [], [])): line = to_str(p.stdout.readline()) if not line: break if self._verbose: logger.log(line.strip()) if fp: fp.write(line) fp.flush() p.poll() if fp: fp.close() return p.returncode def check_call(self, cmd): returncode = self.call(cmd) if returncode: raise ShellCommandException('%s: failed to `%s`' % (returncode, cmd)) class Package(object): def __init__(self, version, type): type = type.lower() if type == 'cpython': tag = 'CPython' elif type == 'stackless': tag = 'Stackless' elif type == 'pypy': tag = 'PyPy' elif type == 'pypy3': tag = 'PyPy3' elif type == 'jython': tag = 'Jython' else: raise ValueError('invalid type: %s' % type) self.type = type self.tag = tag self.version = version @property def name(self): return '%s-%s' % (self.tag, self.version) class Link(object): def __init__(self, url): self._url = url @property def filename(self): url = self._url url = url.split('#', 1)[0] url = url.split('?', 1)[0] url = url.rstrip('/') name = posixpath.basename(url) assert name, ('URL %r produced no filename' % url) return name @property def base_url(self): return posixpath.basename(self._url.split('#', 1)[0].split('?', 1)[0]) class Version(object): """version compare """ def __init__(self, v): self._version = v self._p = self._parse_version(v) def __lt__(self, o): if is_str(o): o = self._parse_version(o) return self._p < o def __le__(self, o): if is_str(o): o = self._parse_version(o) return self._p <= o def __eq__(self, o): if is_str(o): o = self._parse_version(o) return self._p == o def __ne__(self, o): if is_str(o): o = self._parse_version(o) return self._p != o def __gt__(self, o): if is_str(o): o = self._parse_version(o) return self._p > o def __ge__(self, o): if is_str(o): o = self._parse_version(o) return self._p >= o def _parse_version(self, s): """see pkg_resouce.parse_version """ component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE) replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c','dev':'@'}.get def _parse_version_parts(s): for part in component_re.split(s): part = replace(part,part) if not part or part=='.': continue if part[:1] in '0123456789': yield part.zfill(8) # pad for numeric comparison else: yield '*'+part yield '*final' # ensure that alpha/beta/candidate are before final parts = [] for part in _parse_version_parts(s.lower()): if part.startswith('*'): if part<'*final': # remove '-' before a prerelease tag while parts and parts[-1]=='*final-': parts.pop() # remove trailing zeros from each series of numeric parts while parts and parts[-1]=='00000000': parts.pop() parts.append(part) return tuple(parts) def __repr__(self): return self._version PK34HUOpythonz/version.py __version__ = '1.11.2' PKz0G($pythonz/commands/__init__.py import os import re import sys from optparse import OptionParser command_map = {} class Command(object): name = None usage = None summary = '' def __init__(self): self.parser = OptionParser(usage=self.usage, prog='pythonz %s' % self.name) command_map[self.name] = self def run(self, args): options, args = self.parser.parse_args(args) self.run_command(options, args) def load_commands(): modules = ['pythonz.commands.%s' % os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(__file__)) if os.path.splitext(file)[1] == '.py' and file != os.path.basename(__file__)] list(map(__import__, modules)) PKYEwfddpythonz/commands/cleanup.py import os from pythonz.commands import Command from pythonz.define import PATH_BUILD, PATH_DISTS from pythonz.util import rm_r class CleanupCommand(Command): name = "cleanup" usage = "%prog" summary = "Remove stale source folders and archives" def __init__(self): super(CleanupCommand, self).__init__() self.parser.add_option( '-a', '--all', dest='clean_all', action='store_true', default=False, help='Clean all, including the build directory. Note that debug symbols will be gone too!' ) def run_command(self, options, args): if options.clean_all: self._cleanup(PATH_BUILD) self._cleanup(PATH_DISTS) def _cleanup(self, root): for dir in os.listdir(root): rm_r(os.path.join(root, dir)) CleanupCommand() PKYEpo0pythonz/commands/help.py from pythonz.commands import Command, command_map from pythonz.log import logger class HelpCommand(Command): name = "help" usage = "%prog [COMMAND]" summary = "Show available commands" def run_command(self, options, args): if args: command = args[0] if command not in command_map: self.parser.error("Unknown command: `%s`" % command) return command = command_map[command] command.parser.print_help() return self.parser.print_help() logger.log("\nCommands available:") commands = [command_map[key] for key in sorted(command_map.keys())] for command in commands: logger.log(" %s: %s" % (command.name, command.summary)) logger.log("\nFurther Instructions:") logger.log(" https://github.com/saghul/pythonz") HelpCommand() PKYEwZ<<pythonz/commands/uninstall.py import os from pythonz.commands import Command from pythonz.define import PATH_PYTHONS from pythonz.util import rm_r, Package, is_installed from pythonz.log import logger class UninstallCommand(Command): name = "uninstall" usage = "%prog [options] VERSION" summary = "Uninstall the given version of python" def __init__(self): super(UninstallCommand, self).__init__() self.parser.add_option( "-t", "--type", dest="type", default="cpython", help="Type of Python version: cpython, stackless, pypy, pypy3 or jython." ) def run_command(self, options, args): if args: # Uninstall pythons for arg in args: pkg = Package(arg, options.type) pkgname = pkg.name if not is_installed(pkg): logger.error("`%s` is not installed." % pkgname) continue rm_r(os.path.join(PATH_PYTHONS, pkgname)) else: self.parser.print_help() UninstallCommand() PKYEgoI22pythonz/commands/version.py from pythonz.commands import Command from pythonz.log import logger from pythonz.version import __version__ class VersionCommand(Command): name = "version" usage = "%prog" summary = "Show version" def run_command(self, options, args): logger.log(__version__) VersionCommand() PKm3Ht344 4 pythonz/commands/install.py import sys from pythonz.commands import Command from pythonz.installer.pythoninstaller import PythonInstaller, AlreadyInstalledError from pythonz.log import logger class InstallCommand(Command): name = "install" usage = "%prog [OPTIONS] VERSION" summary = "Build and install the given version of python" def __init__(self): super(InstallCommand, self).__init__() self.parser.add_option( "-t", "--type", dest="type", default="cpython", help="Type of Python version: cpython, stackless, pypy, pypy3 or jython." ) self.parser.add_option( "-f", "--force", dest="force", action="store_true", default=False, help="Force installation of python even if tests fail." ) self.parser.add_option( "--run-tests", dest="run_tests", action="store_true", default=False, help="Run `make test` after compiling." ) self.parser.add_option( "--url", dest="url", default=None, help="URL used to download the specified python version." ) self.parser.add_option( "--file", dest="file", default=None, help="File pinting to the python version to be installed." ) self.parser.add_option( "-v", "--verbose", dest="verbose", action="store_true", default=False, help="Display log information on the console." ) self.parser.add_option( "-C", "--configure", dest="configure", default="", metavar="CONFIGURE_OPTIONS", help="Options passed directly to configure." ) self.parser.add_option( "--framework", dest="framework", action="store_true", default=False, help="Build Framework. (OSX only)" ) self.parser.add_option( "--universal", dest="universal", action="store_true", default=False, help="Build for both 32 & 64 bit Intel. (OSX only)" ) self.parser.add_option( "--shared", dest="shared", action="store_true", default=False, help="Build shared libraries." ) self.parser.add_option( "--reinstall", dest="reinstall", action="store_true", default=False, help="Reinstall Python version, if already installed." ) self.parser.add_option( "--external", dest="external_path", default="", help="Install Python version in specified directory." ) def run_command(self, options, args): if not args: self.parser.print_help() sys.exit(1) for arg in args: try: p = PythonInstaller.get_installer(arg, options) p.install() except AlreadyInstalledError as e: logger.info(e) except Exception: import traceback traceback.print_exc() continue InstallCommand() PKפ3Hixpythonz/commands/list.py import os from pythonz.commands import Command from pythonz.define import PATH_PYTHONS from pythonz.installer.pythoninstaller import CPythonInstaller, StacklessInstaller, PyPyInstaller, PyPy3Installer, JythonInstaller from pythonz.log import logger PY_INSTALLERS = {'cpython': CPythonInstaller, 'stackless': StacklessInstaller, 'pypy': PyPyInstaller, 'pypy3': PyPy3Installer, 'jython': JythonInstaller} PY_TYPES = sorted(PY_INSTALLERS.keys()) class ListCommand(Command): name = "list" usage = "%prog [options]" summary = "List the installed python versions" def __init__(self): super(ListCommand, self).__init__() self.parser.add_option( '-a', '--all-versions', dest='all_versions', action='store_true', default=False, help='Show the all available python versions.' ) self.parser.add_option( '-p', '--path', dest='path', action='store_true', default=False, help='Show the path for all Python installations.' ) self.parser.add_option( '-t', '--type', dest='py_type', choices=PY_TYPES, default=[], help=('Use with -a to list only certain Python types. ' 'Available choices: {0}'.format(PY_TYPES)) ) def run_command(self, options, args): if options.all_versions: self.all(py_type=options.py_type) else: self.installed(path=options.path) def installed(self, path): logger.log("# Installed Python versions") for d in sorted(os.listdir(PATH_PYTHONS)): if path: logger.log(' %-16s %s/%s' % (d, PATH_PYTHONS, d)) else: logger.log(' %s' % d) def all(self, py_type): logger.log('# Available Python versions') py_types = [ty for ty in PY_TYPES if py_type in ty] if py_type else PY_TYPES for type_ in py_types: logger.log(' # %s:' % type_) for version in sorted(PY_INSTALLERS[type_].supported_versions): logger.log(' %s' % version) ListCommand() PK3H.pythonz/commands/locate.py import os import sys from pythonz.commands import Command from pythonz.define import PATH_PYTHONS from pythonz.util import Package, is_installed from pythonz.log import logger class LocateCommand(Command): name = "locate" usage = "%prog [options] VERSION" summary = "Locate the given version of python" def __init__(self): super(LocateCommand, self).__init__() self.parser.add_option( "-t", "--type", dest="type", default="cpython", help="Type of Python version: cpython, stackless, pypy, pypy3 or jython." ) def run_command(self, options, args): if not args or len(args) > 1: self.parser.print_help() sys.exit(1) pkg = Package(args[0], options.type) pkgname = pkg.name if not is_installed(pkg): logger.error("`%s` is not installed." % pkgname) sys.exit(1) for bin in ('python3', 'python', 'pypy3', 'pypy'): path = os.path.join(PATH_PYTHONS, pkgname, 'bin', bin) if os.path.exists(path): break else: # fallback path = os.path.join(PATH_PYTHONS, pkgname, 'bin', 'python') logger.log(path) LocateCommand() PK3Hopythonz/commands/update.py import os import sys from pythonz.commands import Command from pythonz.define import PATH_DISTS, ROOT, PATH_BUILD, PYTHONZ_UPDATE_URL from pythonz.downloader import Downloader, DownloadError from pythonz.log import logger from pythonz.util import rm_r, extract_downloadfile, unlink, Subprocess class UpdateCommand(Command): name = "update" usage = "%prog" summary = "Update pythonz to the latest version" def run_command(self, options, args): headinfo = Downloader.read_head_info(PYTHONZ_UPDATE_URL) content_type = headinfo['content-type'] filename = "pythonz-latest" distname = "%s.tgz" % filename download_file = os.path.join(PATH_DISTS, distname) # Remove old tarball unlink(download_file) logger.info("Downloading %s as %s" % (distname, download_file)) try: Downloader.fetch(PYTHONZ_UPDATE_URL, download_file) except DownloadError: unlink(download_file) logger.error("Failed to download. `%s`" % PYTHONZ_UPDATE_URL) sys.exit(1) except: unlink(download_file) raise extract_dir = os.path.join(PATH_BUILD, filename) rm_r(extract_dir) extract_downloadfile(content_type, download_file, extract_dir) try: logger.info("Installing %s into %s" % (extract_dir, ROOT)) s = Subprocess() s.check_call([sys.executable, os.path.join(extract_dir, 'pythonz_install.py'), '--upgrade']) except: logger.error("Failed to update pythonz.") sys.exit(1) logger.info("pythonz has been updated.") UpdateCommand() PKYEw^pythonz/installer/__init__.py import os from pythonz.installer.pythonzinstaller import PythonzInstaller from pythonz.log import logger from pythonz.define import INSTALLER_ROOT, ROOT, PATH_ETC def install_pythonz(): PythonzInstaller.install(INSTALLER_ROOT) # for bash shrc = yourshrc = "bashrc" logger.log(""" Well-done! Congratulations! The pythonz is installed as: %(ROOT)s Please add the following line to the end of your ~/.%(yourshrc)s [[ -s %(PATH_ETC)s/%(shrc)s ]] && source %(PATH_ETC)s/%(shrc)s After that, exit this shell, start a new one, and install some fresh pythons: pythonz install 2.7.2 pythonz install 3.2 For further instructions, run: pythonz help The default help messages will popup and tell you what to do! Enjoy pythonz at %(ROOT)s!! """ % {'ROOT': ROOT, 'yourshrc': yourshrc, 'shrc': shrc, 'PATH_ETC': PATH_ETC.replace(os.getenv('HOME'), '$HOME')}) def upgrade_pythonz(): PythonzInstaller.install(INSTALLER_ROOT) def systemwide_pythonz(): PythonzInstaller.install(INSTALLER_ROOT) PythonzInstaller.systemwide_install() logger.log(""" Well-done! Congratulations! The pythonz is installed as: %(ROOT)s After that, exit this shell, start a new one, and install some fresh pythons: pythonz install 2.7.2 pythonz install 3.2 For further instructions, run: pythonz help The default help messages will popup and tell you what to do! Enjoy pythonz at %(ROOT)s!! """ % {'ROOT':ROOT}) PK:3H (^.^.pythonz/installer/versions.pyversions = { 'cpython': { '2.4': 'ff746de0fae8691c082414b42a2bb172da8797e6e8ff66c9a39d2e452f7034e9', '2.4.1': 'f449c3b167389324c525ad99d02376c518ac11e163dbbbc13bc88a5c7101fd00', '2.4.2': '2653e1846e87fd9b3ee287fefc965c80c54646548b4913a22265b0dd54493adf', '2.4.3': '985a413932f5e31e6280b37da6b285a3a0b2748c6786643989ed9b23de97e2d5', '2.4.4': '92be6e20cbc3111d9dd0c016d72ef7914c23b879dc52df7ba28df97afbf12e2e', '2.4.5': '6ae6f67a388a7f70ed3a20eebab5aae995ee433089d1f1724095c62f4b7389a1', '2.4.6': 'b03f269e826927f05c966cf4f4414f3c93ee2314960859e7f8375e24e82f8b02', '2.5': 'd7bbf42e36003c6065cd19f3e67d283521858515ee923220f654131cebe1d8f2', '2.5.1': '1f5caee846049ca30d996f9403eefdb996295c4af664867e35dcc5eb36e4e7e8', '2.5.2': '834afe8a88adaf623b05ac5dd6700dd5bb5d0d5553fc74ad529359a3496e4ae3', '2.5.3': 'c3fee607d20a77dfb72ea2e627eb4d95d25c735603435abde62c57015a0445bd', '2.5.4': '3d3b205611ee503a38a9433d5645a571668420bb219242c7f51af85f05664da6', '2.5.5': '03be1019c4fe93daeb53ba9e4294bf22a8ed4cb854cbd57e24e16f6bf63e2392', '2.5.6': 'c2e4377597241b1065677d23327c04d0f41945d370c61a491cc88be367234c5d', '2.6': '7c2f21a968a737a59ed0729f4b1dc154dc3aa183c20be96055186fe43c6742d0', '2.6.1': 'fb65e93678e1327e3e8559cc56e1e00ed8c07162b21287a3502677892c5c515c', '2.6.2': 'e37ecdf249f248f4fea227adbca09c778670b64fcb5e45947ec3e093cbc12c86', '2.6.3': 'a71b55540690425fd82ab00819aeb92c1b23cbb4730a0ccd2e25c833b22a812e', '2.6.4': '1a25a47506e4165704cfe2b07c0a064b0b5762a2d18b8fbdad5af688aeacd252', '2.6.5': 'b331dafdce3361834fee783795d4f68ae7cf7d379e9137c2d8e8531cea615ede', '2.6.6': '372f66db46d773214e4619df1794a26449158f626138d4d2141a64c2f017fae1', '2.6.7': 'a8093eace4cfd3e06b05f0deb5d765e3c6cec65908048640a8cadd7a948b3826', '2.6.8': '5bf02a75ffa2fcaa5a3cabb8201998519b045541975622316888ea468d9512f7', '2.6.9': '7277b1285d8a82f374ef6ebaac85b003266f7939b3f2a24a3af52f9523ac94db', '2.7': '5670dd6c0c93b0b529781d070852f7b51ce6855615b16afcd318341af2910fb5', '2.7.1': 'ca13e7b1860821494f70de017202283ad73b1fb7bd88586401c54ef958226ec8', '2.7.2': '1d54b7096c17902c3f40ffce7e5b84e0072d0144024184fff184a84d563abbb3', '2.7.3': 'd4c20f2b5faf95999fd5fecb3f7d32071b0820516224a6d2b72932ab47a1cb8e', '2.7.4': '98c5eb9c8e65effcc0122112ba17a0bce880aa23ecb560af56b55eb55632b81a', '2.7.5': '8e1b5fa87b91835afb376a9c0d319d41feca07ffebc0288d97ab08d64f48afbf', '2.7.6': '99c6860b70977befa1590029fae092ddb18db1d69ae67e8b9385b66ed104ba58', '2.7.7': '7f49c0a6705ad89d925181e27d0aaa025ee4731ce0de64776c722216c3e66c42', '2.7.8': '74d70b914da4487aa1d97222b29e9554d042f825f26cb2b93abd20fdda56b557', '2.7.9': 'c8bba33e66ac3201dabdc556f0ea7cfe6ac11946ec32d357c4c6f9b018c12c5b', '2.7.10': 'eda8ce6eec03e74991abb5384170e7c65fcd7522e409b8e83d7e6372add0f12a', '2.7.11': '82929b96fd6afc8da838b149107078c02fa1744b7e60999a8babbc0d3fa86fc6', '3.0': '4d5d6ab2f893144a382ae1ea1de88a7825eb98111e26cfde627b9f3d9fd462b4', '3.0.1': '7d5f2feae9035f1d3d9e6bb7f092dbf374d6bb4b25abd0d2d11f13bba1cb04de', '3.1': '99a034cf574ea3c26412b0a0728126d7fd6ea9593d099d807a25d216ed031e6a', '3.1.1': '5d85d7bff11c4db44920af99f64f4227c816f897f6bfa9dd8a2611165ca5f0a1', '3.1.2': 'dffbc0561a161a4a576c6059e6990a9859a0be16ba9b5736eabe4abbb2700d1c', '3.1.3': '6311823aeda8be6a7a2b67caaeff48abce6626c9940ba7ed81f9c978666a36bd', '3.1.4': 'fadc05ea6d05360cff189944a85ecd2180bbc308784d168b350450e70bbdd846', '3.1.5': 'd12dae6d06f52ef6bf1271db4d5b4d14b5dd39813e324314e72b648ef1bc0103', '3.2': '27b35bfcbbf01de9564c0265d72b58ba3ff3d56df0615765372f2aa09dc20da9', '3.2.1': '7cff29d984696d9fe8c7bea54da5b9ad36acef33ff5cf0d3e37e4d12fb21c572', '3.2.2': 'acc6a13cb4fed0b7e86716324a8437e326645b8076177eede5a0cad99ec0313c', '3.2.3': '74c33e165edef7532cef95fd9a325a06878b5bfc8a5d038161573f283eaf9809', '3.2.4': '71c3139908ccc1c544ba1e331a3c22b3f1c09f562438a054fd6f4e2628de8b9a', '3.2.5': '5eae0ab92a0bb9e3a1bf9c7cd046bc3de58996b049bd894d095978b6b085099f', '3.3.0': 'cfe531eaace2503e13a74addc7f4a89482e99f8b8fca51b469ae5c83f450604e', '3.3.1': '671dc3632f311e63c6733703aa0a1ad90c99277ddc8299d39e487718a50319bd', '3.3.2': 'de664fca3b8e0ab20fb42bfed1a36e26f116f1853e88ada12dbc938761036172', '3.3.3': '30b60839bfe0ae8a2dba11e909328459bb8ee4a258afe7494b06b2ceda080efc', '3.3.4': 'ea055db9dd004a6ecd7690abc9734573763686dd768122316bae2dfd026412af', '3.3.5': '916bc57dd8524dc27429bebae7b39d6942742cf9699b875b2b496a3d960c7168', '3.3.6': '0a58ad1f1def4ecc90b18b0c410a3a0e1a48cf7692c75d1f83d0af080e5d2034', '3.4.0': 'd2c83ea0217769a73e8b1ee33ffbca814903f8568e30f8d13e68e3d1f743449c', '3.4.1': '8d007e3ef80b128a292be101201e75dec5480e5632e994771e7c231d17720b66', '3.4.2': '44a3c1ef1c7ca3e4fd25242af80ed72da941203cb4ed1a8c1b724d9078965dd8', '3.4.3': '8b743f56e9e50bf0923b9e9c45dd927c071d7aa56cd46569d8818add8cf01147', '3.5.0': '584e3d5a02692ca52fce505e68ecd77248a6f2c99adf9db144a39087336b0fe0', '3.5.1': '687e067d9f391da645423c7eda8205bae9d35edc0c76ef5218dcbe4cc770d0d7' }, 'stackless': { '2.6.5': 'ac1956d7f9715cc56e92992d39b24f0869cd9955fd2b8cf52b163530194d07b1', '2.7.2': 'e2e2706b22839e3e3f45085d0ec8030dd7374d8a65d3297981b7189a7c613197', '3.1.3': '7aab20f509b5e3ad14a8e7c316401ac51377048ae85325ac3838a1494c019863', '3.2.2': '779700f12b451a350fe7af4cd2849842adc7006dc83fe14712dd1a0999277b07', '3.2.5': 'b021125e578ddd267d38feee9e1cbdb675f6aab247a2b88f4494abcf23babb05', '3.3.5': '197b41ccd7ec998ff612c67df9b8eb827a58f4eda715ca034c43c94bf17d5c0f' }, 'pypy': { '1.8': {'linux': '9c293d8540780260718f8fd8dc433c97b614a31b115ccfe2d68df720ad7e55b1', 'linux64': '1045606cceb993844a016b76c55aa43a9924bcf526f91a0572fc97cee69b61dc', 'darwin': 'b823b6b919082cfb67861b8253313b877618672377164086c0364fa8eaa88b8a'}, '1.9': {'linux': '1e3f9c3d06f8bbfa0dcb1301b40c298096249a7d7c2b4594b3fb1c3e7b9888f2', 'linux64': '4298252515e78c96f4ecd9f25be957411c060ece02d9213eef8d781cf528d18f', 'darwin': '4858f200e32c1070c77c1234ea0e9473eeda98bcd3832c4231f3e46e4e3b74b1'}, '2.0': {'linux': '275dbbee67eac527a1177403a0386b17d008740f83030544800d87994edd46b9', 'linux64': '14c716d53a507eece89606d547456b886dbdfc0ba6e3fb29062fafe86d1b6038', 'darwin': '6d190f32c9dce9d36d4a2bb91faed581a50fb7fa6249eee201dbf5dbc3e3c7d7'}, '2.0.1': {'linux': '548686c5b95b424c79586d9a303ed41fca8eba52bd35c1527f39f5cd8fa35ea9', 'linux64': '0eb57e28f2bd5f2a4ad396df322de5adf711eb7d9a2bfeb8be2d9eb9e125c5cc', 'darwin': '337f2fda672827f2d706fd98e3344a83a8b80675e21b83dd6933da38d110c857'}, '2.0.2': {'linux': '3b43c1ac147f6bb11981dd7f8c5458b95d6bdcf1adceb8043c32ca5e8fcab4da', 'linux64': '3f9bc07959a2d6058a0c1b84da837e2ec457642fe03ac46123d145c419a7b5cd', 'darwin': '34f5a7bf22a8bca3b9d79ae3186016c34638669ab19b4af6e38412181c757761'}, '2.1': {'linux': '9c0a38a40d3b4e642a159e51abef2827b33e3f7a254365daa24eae85d840eaf5', 'linux64': '80f90bb473635a0249049e87c5cc7cf738e13537c1f1e2857b6345848a3e6d20', 'darwin': 'd0d788c6d54bb866ace67a1740133cb5bc62357b5ca4783244097f1f648876f0'}, '2.2': {'linux': '2bdab70106f6b6d0dd97e42535ce73711c987887fb81fb821801f6fdcd92cdc4', 'linux64': '1583af0122c6ccb0cb95f8c3732925551ce3ca6d5ea0657e21523f8bf97837a3', 'darwin': '8aa943de7ec38f13fa836b6964dbf58b45142e4fe7b3fdd5fffe37fdcf974e01'}, '2.2.1': {'linux': '4d13483a0e13fc617a7b3d36918ed0e63cf07a7d2827c0a08132b80bc401a55a', 'linux64': '022d611ac62a276890d3e262f4f7cc839fcf9f5e1416df01dcd83ba335eacb16', 'darwin': '93e215dcffc9073acf41c63518f47fb59de60386aca4416cfe32190c7a096f29'}, '2.3': {'linux': '9071072d42344fb37cc588429864b00fff447bd5d33d51008641fe6822823f1b', 'linux64': '777dbdd9c67ad1b8906288b01ae76bc9f7b80c95e967836f9a700a1679b80008', 'darwin': 'df7ca23ba6c8a63149d910b482be04f069b26dd1f7d0ca15e6342cac94e759d7'}, '2.3.1': {'linux': '3eed698e8533cca7cbd2c2c87fce39dc14baa7dec03f4b082d870131d2a470e4', 'linux64': 'dab7940496d96f1f255a8ef402fa96b94444775e373484e057d2fcabc3928b42', 'darwin': '12e363bf5ea3a508600e043b68c47d4148359ca3d999ee207665bb139f8fbf37'}, '2.4.0': {'linux': 'a24adb366f87ac0eba829d7188a156a7d897e71893689fab06502c3f4152ac0e', 'linux64': '27cdc0d6e8bce2637678f6d076fc780877dffe1bf9aec9e253f95219af9ed099', 'darwin': '3eb8afdfa42bc9b08b4d3058e21d4ce978a52722fdcfdc67d6c3ee5013a51aaa'}, '2.5.0': {'linux': '3dfd56a986d25929b4ed9f40a5484f72f1d513cd816cf8aaa683106c3391247c', 'linux64': '7764fb6b662407f8709eaa334c542aac9cb6bfe3291ac198dad0980ca129f3c2', 'darwin': '30b392b969b54cde281b07f5c10865a7f2e11a229c46b8af384ca1d3fe8d4e6e'}, '2.5.1': {'linux': 'c0035a2650cafcb384050a8c476ddc41c9fd40b0c3677fab68026f57c715907a', 'linux64': '68e0955dbc80a0d51dfa9a8a76d8623f34920ece1bcbc6d910c2be019a653ba8', 'darwin': 'db40dc8b5e95ef9c3322bd9897099e91555ef34188cf1c3852a92b081142d183'}, '2.6.0': {'linux': '6e0b052c40a59bf5a85ee239980bbcab8b031b4c2bc33b99efe1b072977d9910', 'linux64': 'f5d2b0e3594cec57e32d3e43a951041ec330e1e962a836be470d591633e51388', 'darwin': '77f1d056484e40e0a8e2e2b2b489eedfe785605ef36b144ffce05f7b748f6acd'}, '2.6.1': {'linux': 'd010b1f1aafdb01beb107f16843985508ce81698260ce830690686d9b2768c88', 'linux64': '78a48490d1b2dba8571156c2bf822324ca7dae6f6a56a4bbb96d3e8e8885367b', 'darwin': '4a78ef76ec38a49a9de40225c337e89486fa09938c600df2bd2dd60110066f65'}, '4.0.0': {'linux': '365600947775bc73a902a5b1d11f8b96cf49f07cdbbab28bb47240097b4bb4c5', 'linux64': '30365cf4fa6cd8e9ff44126f06dcaebefda35c2543ddcf9b9e8516c29cabe726', 'darwin': 'd9e590fe5b9461bbdff56c76636e844ef90a297f82d0d2e204866c8a21759a50'}, '4.0.1': {'linux': '721920fcbb6aefc9a98e868e32b7f4ea5fd68b7f9305d08d0a2595327c9c0611', 'linux64': '0d6090cee59f4b9bab91ddbea76580d0c232b78dae65aaa9e8fa8d4449ba25b4', 'darwin': '06be1299691f7ea558bf8e3bdf3d20debb8ba03cd7cadf04f2d6cbd5fd084430'} }, 'pypy3': { '2.3.1': {'linux': '7eddc6826e58c9c89e68b59ec8caf1596b76401517ad8d26ad5e18e0ffa45db9', 'linux64': '303df2cf4766db20ec77786d9091dce284fdab01d7173c5828a35e86bc931b99', 'darwin': '600d4dad2039b8035582c0e0ce9b71e8236d95db26cff48c84c6d1e0ea6814c1'}, '2.4.0': {'linux': '108fdcccfddb9b2cb2fc3cbca5e6f7902ed3ab74a24c8ae29da7fbdadbab4345', 'linux64': '24e680b1742af7361107876a421dd793f5ef852dd5f097546f84b1378f7f70cc', 'darwin': 'dcd86bdb753e93dbf55e1f3af3ffa97eea328b8b77aa60e92ea2260a6258cedb'} }, 'jython': { '2.5.0': 'e3d8209ef9eb143df8101a5da6b3482cf457084e3a6247031fd510d71c13ab98', '2.5.1': '229dfd1ed9728aa7e00c71f111d08fa777a4edcd03383779c74216765098f9c5', '2.5.2': '1b7168b961e31ddd89012a36cde611c340dadfd8b60b81c4248b026730ee2f29', '2.5.3': '05405966cdfa57abc8e705dd6aab92b8240097ce709fb916c8a0dbcaa491f99e', '2.7.0': 'b44352ece72382268a60e2848741c96609a91d796bb9a9c6ebeff62f0c12c9cf' } } PK3H* ^^$pythonz/installer/pythoninstaller.py import ctypes import os import sys import shutil import mimetypes import multiprocessing import re import subprocess from pythonz.installer.versions import versions from pythonz.util import symlink, makedirs, Package, is_url, Link,\ unlink, is_html, Subprocess, rm_r, is_python26, is_python27,\ extract_downloadfile, is_archive_file, path_to_fileurl, is_file,\ fileurl_to_path, is_python30, is_python31, is_python32,\ get_macosx_deployment_target, Version, is_python25, is_python24, is_python33 from pythonz.define import PATH_BUILD, PATH_DISTS, PATH_PYTHONS, PATH_LOG, \ PATH_PATCHES_ALL, PATH_PATCHES_OSX from pythonz.downloader import Downloader, DownloadError, sha256 from pythonz.log import logger class AlreadyInstalledError(Exception): pass class PythonInstaller(object): @staticmethod def get_installer(version, options): type = options.type.lower() if type == 'cpython': return CPythonInstaller(version, options) elif type == 'stackless': return StacklessInstaller(version, options) elif type == 'pypy': return PyPyInstaller(version, options) elif type == 'pypy3': return PyPy3Installer(version, options) elif type == 'jython': return JythonInstaller(version, options) raise RuntimeError('invalid type specified: %s' % type) class Installer(object): def __init__(self, version, options): # create directories makedirs(PATH_BUILD) makedirs(PATH_DISTS) makedirs(PATH_LOG) if options.file is not None: if not (is_archive_file(options.file) and os.path.isfile(options.file)): logger.error('invalid file specified: %s' % options.file) raise RuntimeError self.download_url = path_to_fileurl(options.file) elif options.url is not None: if not is_url(options.url): logger.error('invalid URL specified: %s' % options.url) raise RuntimeError self.download_url = options.url else: self.download_url = self.get_version_url(version) if version not in self.supported_versions: logger.warning("Unsupported Python version: `%s`, trying with the following URL anyway: %s" % (version, self.download_url)) self.pkg = Package(version, options.type) if options.external_path: if not os.path.isabs(options.external_path): options.external_path = os.path.join( os.path.abspath(os.path.curdir), options.external_path) self.install_dir = os.path.join(options.external_path, self.pkg.name) else: self.install_dir = os.path.join(PATH_PYTHONS, self.pkg.name) self.build_dir = os.path.join(PATH_BUILD, self.pkg.name) filename = Link(self.download_url).filename self.download_file = os.path.join(PATH_DISTS, filename) # cleanup if os.path.isdir(self.build_dir): shutil.rmtree(self.build_dir) if os.path.isdir(self.install_dir): if options.reinstall: shutil.rmtree(self.install_dir) else: raise AlreadyInstalledError("You have already installed `%s`" % self.pkg.name) self.options = options self.logfile = os.path.join(PATH_LOG, 'build.log') self.patches = [] self.configure_options = [] @classmethod def get_version_url(cls, version): raise NotImplementedError @property def expected_sha256(self): return self.supported_versions.get(self.pkg.version) def download(self): if os.path.isfile(self.download_file) and sha256(self.download_file) == self.expected_sha256: logger.info("Use the previously fetched %s" % (self.download_file)) else: base_url = Link(self.download_url).base_url logger.info("Downloading %s as %s" % (base_url, self.download_file)) try: Downloader.fetch(self.download_url, self.download_file, self.expected_sha256) except DownloadError: logger.error("Failed to download.\n%s" % (sys.exc_info()[1])) raise def install(self): raise NotImplementedError class CPythonInstaller(Installer): version_re = re.compile(r'(\d\.\d(\.\d+)?)(.*)') supported_versions = versions['cpython'] def __init__(self, version, options): super(CPythonInstaller, self).__init__(version, options) if Version(self.pkg.version) >= '3.1': self.configure_options.append('--with-computed-gotos') if sys.platform == "darwin": # set configure options target = get_macosx_deployment_target() if target: self.configure_options.append('MACOSX_DEPLOYMENT_TARGET=%s' % target) # set build options if options.framework and options.shared: logger.error("Can't specify both framework and shared.") raise Exception if options.framework: self.configure_options.append('--enable-framework=%s' % os.path.join(self.install_dir, 'Frameworks')) if options.shared: self.configure_options.append('--enable-shared') if options.universal: self.configure_options.append('--enable-universalsdk=/') self.configure_options.append('--with-universal-archs=intel') else: if options.shared: self.configure_options.append('--enable-shared') @classmethod def get_version_url(cls, version): if version not in cls.supported_versions: # Unsupported alpha, beta or rc versions match = cls.version_re.match(version) if match is not None: groups = match.groups() base_version = groups[0] version = groups[0] + groups[2] return 'http://www.python.org/ftp/python/%(base_version)s/Python-%(version)s.tgz' % {'base_version': base_version, 'version': version} return 'http://www.python.org/ftp/python/%(version)s/Python-%(version)s.tgz' % {'version': version} def _apply_patches(self): try: s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose) for patch in self.patches: if type(patch) is dict: for ed, source in patch.items(): s.shell('ed - %s < %s' % (source, ed)) else: s.shell("patch -p0 < %s" % patch) except Exception: raise RuntimeError("Failed to patch `%s`.\n%s" % (self.build_dir, sys.exc_info()[1])) def _append_patch(self, patch_dir, patch_files): for patch in patch_files: if type(patch) is dict: tmp = patch patch = {} for key in tmp.keys(): patch[os.path.join(patch_dir, key)] = tmp[key] self.patches.append(patch) else: self.patches.append(os.path.join(patch_dir, patch)) def install(self): # get content type. if is_file(self.download_url): path = fileurl_to_path(self.download_url) self.content_type = mimetypes.guess_type(path)[0] else: headerinfo = Downloader.read_head_info(self.download_url) self.content_type = headerinfo['content-type'] if is_html(self.content_type): # note: maybe got 404 or 503 http status code. logger.error("Invalid content-type: `%s`" % self.content_type) return self.download_and_extract() logger.info("\nThis could take a while. You can run the following command on another shell to track the status:") logger.info(" tail -f %s\n" % self.logfile) logger.info("Installing %s into %s" % (self.pkg.name, self.install_dir)) try: self.patch() self.configure() self.make() self.make_install() except Exception: import traceback traceback.print_exc() rm_r(self.install_dir) logger.error("Failed to install %s. Check %s to see why." % (self.pkg.name, self.logfile)) raise self.symlink() logger.info("\nInstalled %(pkgname)s successfully." % {"pkgname": self.pkg.name}) def download_and_extract(self): self.download() extract_downloadfile(self.content_type, self.download_file, self.build_dir) def _patch(self): version = Version(self.pkg.version) common_patch_dir = os.path.join(PATH_PATCHES_ALL, "common") if is_python24(version): patch_dir = os.path.join(PATH_PATCHES_ALL, "python24") self._append_patch(patch_dir, ['patch-setup.py.diff']) elif is_python25(version): patch_dir = os.path.join(PATH_PATCHES_ALL, "python25") self._append_patch(patch_dir, ['patch-setup.py.diff', 'patch-svnversion.patch']) elif is_python26(version): self._append_patch(common_patch_dir, ['patch-setup.py.diff']) patch_dir = os.path.join(PATH_PATCHES_ALL, "python26") if version < '2.6.5': self._append_patch(patch_dir, ['patch-nosslv2-1.diff']) elif version < '2.6.6': self._append_patch(patch_dir, ['patch-nosslv2-2.diff']) elif version < '2.6.9': self._append_patch(patch_dir, ['patch-nosslv2-3.diff']) elif is_python27(version): if version < '2.7.2': self._append_patch(common_patch_dir, ['patch-setup.py.diff']) elif is_python30(version): patch_dir = os.path.join(PATH_PATCHES_ALL, "python30") self._append_patch(patch_dir, ['patch-setup.py.diff', 'patch-nosslv2.diff']) elif is_python31(version): if version < '3.1.4': self._append_patch(common_patch_dir, ['patch-setup.py.diff']) elif is_python32(version): if version == '3.2': patch_dir = os.path.join(PATH_PATCHES_ALL, "python32") self._append_patch(patch_dir, ['patch-setup.py.diff']) def _patch_osx(self): version = Version(self.pkg.version) if is_python24(version): PATH_PATCHES_OSX_PYTHON24 = os.path.join(PATH_PATCHES_OSX, "python24") if version == '2.4': self._append_patch(PATH_PATCHES_OSX_PYTHON24, ['patch240-configure', 'patch240-setup.py.diff', 'patch240-Mac-OSX-Makefile.in', 'patch240-gestaltmodule.c.diff', 'patch240-sysconfig.py.diff']) elif version < '2.4.4': self._append_patch(PATH_PATCHES_OSX_PYTHON24, ['patch241-configure', 'patch240-setup.py.diff', 'patch240-Mac-OSX-Makefile.in', 'patch240-gestaltmodule.c.diff']) else: self._append_patch(PATH_PATCHES_OSX_PYTHON24, ['patch244-configure', 'patch244-setup.py.diff', 'patch244-Mac-OSX-Makefile.in', 'patch244-gestaltmodule.c.diff']) self._append_patch(PATH_PATCHES_OSX_PYTHON24, [ 'patch-Makefile.pre.in', 'patch-Lib-cgi.py.diff', 'patch-Lib-site.py.diff', 'patch-Include-pyport.h', 'patch-configure-badcflags.diff', 'patch-macosmodule.diff', 'patch-mactoolboxglue.diff', 'patch-pymactoolbox.diff']) elif is_python25(version): PATH_PATCHES_OSX_PYTHON25 = os.path.join(PATH_PATCHES_OSX, "python25") if version == '2.5': self._append_patch(PATH_PATCHES_OSX_PYTHON25, ['patch250-setup.py.diff']) elif version == '2.5.1': self._append_patch(PATH_PATCHES_OSX_PYTHON25, ['patch251-setup.py.diff']) else: self._append_patch(PATH_PATCHES_OSX_PYTHON25, ['patch252-setup.py.diff']) self._append_patch(PATH_PATCHES_OSX_PYTHON25, [ 'patch-Makefile.pre.in.diff', 'patch-Lib-cgi.py.diff', 'patch-Lib-distutils-dist.py.diff', 'patch-configure-badcflags.diff', 'patch-configure-arch_only.diff', 'patch-64bit.diff', 'patch-pyconfig.h.in.diff', 'patch-gestaltmodule.c.diff', {'_localemodule.c.ed': 'Modules/_localemodule.c'}, {'locale.py.ed': 'Lib/locale.py'}]) elif is_python26(version): PATH_PATCHES_OSX_PYTHON26 = os.path.join(PATH_PATCHES_OSX, "python26") self._append_patch(PATH_PATCHES_OSX_PYTHON26, [ 'patch-Lib-cgi.py.diff', 'patch-Lib-distutils-dist.py.diff', 'patch-Mac-IDLE-Makefile.in.diff', 'patch-Mac-Makefile.in.diff', 'patch-Mac-PythonLauncher-Makefile.in.diff', 'patch-Mac-Tools-Doc-setup.py.diff', 'patch-setup.py-db46.diff', 'patch-Lib-ctypes-macholib-dyld.py.diff', 'patch-setup_no_tkinter.py.diff', {'_localemodule.c.ed': 'Modules/_localemodule.c'}, {'locale.py.ed': 'Lib/locale.py'}]) if version < '2.6.9': patch_dir = os.path.join(PATH_PATCHES_ALL, "python26") self._append_patch(patch_dir, ['patch-nosslv2-3.diff']) elif is_python27(version): PATH_PATCHES_OSX_PYTHON27 = os.path.join(PATH_PATCHES_OSX, "python27") if version < '2.7.4': self._append_patch(PATH_PATCHES_OSX_PYTHON27, ['patch-Modules-posixmodule.diff']) elif version == '2.7.6': self._append_patch(PATH_PATCHES_OSX_PYTHON27, ['python-276-dtrace.diff']) elif is_python33(version): PATH_PATCHES_OSX_PYTHON33 = os.path.join(PATH_PATCHES_OSX, "python33") if version == '3.3.4': self._append_patch(PATH_PATCHES_OSX_PYTHON33, ['python-334-dtrace.diff']) def patch(self): if sys.platform == "darwin": self._patch_osx() else: self._patch() self._apply_patches() def configure(self): s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose) cmd = "./configure --prefix=%s %s %s" % (self.install_dir, self.options.configure, ' '.join(self.configure_options)) if self.options.verbose: logger.log(cmd) s.check_call(cmd) def make(self): try: jobs = multiprocessing.cpu_count() except NotImplementedError: make = 'make' else: make = 'make -j%s' % jobs s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose) s.check_call(make) if self.options.run_tests: if self.options.force: # note: ignore tests failure error. s.call("make test") else: s.check_call("make test") def make_install(self): s = Subprocess(log=self.logfile, cwd=self.build_dir, verbose=self.options.verbose) s.check_call("make install") def symlink(self): install_dir = os.path.realpath(self.install_dir) bin_dir = os.path.join(install_dir, 'bin') if self.options.framework: # create symlink bin -> /path/to/Frameworks/Python.framework/Versions/?.?/bin if os.path.exists(bin_dir): rm_r(bin_dir) m = re.match(r'\d\.\d', self.pkg.version) if m: version = m.group(0) symlink(os.path.join(install_dir, 'Frameworks', 'Python.framework', 'Versions', version, 'bin'), os.path.join(bin_dir)) path_python = os.path.join(bin_dir, 'python') if not os.path.isfile(path_python): for f in os.listdir(bin_dir): if re.match(r'python\d\.\d$', f): symlink(os.path.join(bin_dir, f), path_python) break class StacklessInstaller(CPythonInstaller): supported_versions = versions['stackless'] def _patch_osx(self): super(StacklessInstaller, self)._patch_osx() version = Version(self.pkg.version) if version in ('3.2.5', '3.3.5'): PATH_PATCHES_OSX_PYTHON33 = os.path.join(PATH_PATCHES_OSX, "python33") self._append_patch(PATH_PATCHES_OSX_PYTHON33, ['stackless-335-compile.diff']) @classmethod def get_version_url(cls, version): return 'http://www.stackless.com/binaries/stackless-%(version)s-export.tar.bz2' % {'version': version.replace('.', '')} class PyPyInstaller(Installer): supported_versions = versions['pypy'] @classmethod def get_version_url(cls, version): if sys.platform == 'darwin': return 'https://bitbucket.org/pypy/pypy/downloads/pypy-%(version)s-osx64.tar.bz2' % {'version': version} else: # Linux logger.warning("Linux binaries are dynamically linked, as is usual, and thus might not be usable due to the sad story of linux binary compatibility, check the PyPy website for more information") arch = {4: '', 8: '64'}[ctypes.sizeof(ctypes.c_size_t)] return 'https://bitbucket.org/pypy/pypy/downloads/pypy-%(version)s-linux%(arch)s.tar.bz2' % {'arch': arch, 'version': version} @property def expected_sha256(self): platform_checksums = self.supported_versions.get(self.pkg.version) if platform_checksums is not None: if sys.platform == 'darwin': return platform_checksums['darwin'] elif 'linux' in sys.platform: arch = {4: '', 8: '64'}[ctypes.sizeof(ctypes.c_size_t)] return platform_checksums['linux' + arch] else: raise ValueError('Unsupported platform: ' + sys.platform) def install(self): # get content type. if is_file(self.download_url): path = fileurl_to_path(self.download_url) self.content_type = mimetypes.guess_type(path)[0] else: headerinfo = Downloader.read_head_info(self.download_url) self.content_type = headerinfo['content-type'] if is_html(self.content_type): # note: maybe got 404 or 503 http status code. logger.error("Invalid content-type: `%s`" % self.content_type) return self.download_and_extract() logger.info("Installing %s into %s" % (self.pkg.name, self.install_dir)) shutil.copytree(self.build_dir, self.install_dir) self.symlink() logger.info("\nInstalled %(pkgname)s successfully." % {"pkgname": self.pkg.name}) def download_and_extract(self): self.download() extract_downloadfile(self.content_type, self.download_file, self.build_dir) def symlink(self): install_dir = os.path.realpath(self.install_dir) bin_dir = os.path.join(install_dir, 'bin') symlink(os.path.join(bin_dir, 'pypy'), os.path.join(bin_dir, 'python')) class PyPy3Installer(PyPyInstaller): supported_versions = versions['pypy3'] @classmethod def get_version_url(cls, version): if sys.platform == 'darwin': return 'https://bitbucket.org/pypy/pypy/downloads/pypy3-%(version)s-osx64.tar.bz2' % {'version': version} else: # Linux logger.warning("Linux binaries are dynamically linked, as is usual, and thus might not be usable due to the sad story of linux binary compatibility, check the PyPy website for more information") arch = {4: '', 8: '64'}[ctypes.sizeof(ctypes.c_size_t)] return 'https://bitbucket.org/pypy/pypy/downloads/pypy3-%(version)s-linux%(arch)s.tar.bz2' % {'arch': arch, 'version': version} class JythonInstaller(Installer): supported_versions = versions['jython'] def __init__(self, version, options): super(JythonInstaller, self).__init__(version, options) filename = 'jython-installer-%s.jar' % version self.download_file = os.path.join(PATH_DISTS, filename) @classmethod def get_version_url(cls, version): if version in ('2.5.0', '2.5.1', '2.5.2'): return 'https://downloads.sourceforge.net/project/jython/jython/%(version)s/jython_installer-%(version)s.jar' % {'version': version} else: return 'http://search.maven.org/remotecontent?filepath=org/python/jython-installer/%(version)s/jython-installer-%(version)s.jar' % {'version': version} def install(self): # check if java is installed r = subprocess.call("command -v java > /dev/null", shell=True) if r != 0: logger.error("Jython requires Java to be installed, but the 'java' command was not found in the path.") return # get content type. if is_file(self.download_url): path = fileurl_to_path(self.download_url) self.content_type = mimetypes.guess_type(path)[0] else: try: headerinfo = Downloader.read_head_info(self.download_url) except DownloadError: self.content_type = None else: self.content_type = headerinfo['content-type'] if is_html(self.content_type): # note: maybe got 404 or 503 http status code. logger.error("Invalid content-type: `%s`" % self.content_type) return self.download() logger.info("\nThis could take a while. You can run the following command on another shell to track the status:") logger.info(" tail -f %s\n" % self.logfile) logger.info("Installing %s into %s" % (self.pkg.name, self.install_dir)) cmd = 'java -jar %s -s -d %s' % (self.download_file, self.install_dir) s = Subprocess(log=self.logfile, verbose=self.options.verbose) s.check_call(cmd) self.symlink() logger.info("\nInstalled %(pkgname)s successfully." % {"pkgname": self.pkg.name}) def symlink(self): install_dir = os.path.realpath(self.install_dir) bin_dir = os.path.join(install_dir, 'bin') symlink(os.path.join(bin_dir, 'jython'), os.path.join(bin_dir, 'python')) PK3HEHo%pythonz/installer/pythonzinstaller.py import os import sys import glob import shutil import stat import time from pythonz.util import makedirs, rm_r from pythonz.define import PATH_BUILD, PATH_BIN, PATH_DISTS, PATH_PYTHONS,\ PATH_ETC, PATH_SCRIPTS, PATH_SCRIPTS_PYTHONZ,\ PATH_SCRIPTS_PYTHONZ_COMMANDS, PATH_BIN_PYTHONZ,\ PATH_LOG, PATH_PATCHES,\ PATH_SCRIPTS_PYTHONZ_INSTALLER, PATH_HOME_ETC, ROOT,\ PATH_BASH_COMPLETION class PythonzInstaller(object): """pythonz installer: """ @staticmethod def install(installer_root): # create directories makedirs(PATH_PYTHONS) makedirs(PATH_BUILD) makedirs(PATH_DISTS) makedirs(PATH_ETC) makedirs(PATH_BASH_COMPLETION) makedirs(PATH_BIN) makedirs(PATH_LOG) makedirs(PATH_HOME_ETC) # create script directories rm_r(PATH_SCRIPTS) makedirs(PATH_SCRIPTS) makedirs(PATH_SCRIPTS_PYTHONZ) makedirs(PATH_SCRIPTS_PYTHONZ_COMMANDS) makedirs(PATH_SCRIPTS_PYTHONZ_INSTALLER) # copy all .py files for path in glob.glob(os.path.join(installer_root,"*.py")): shutil.copy(path, PATH_SCRIPTS_PYTHONZ) for path in glob.glob(os.path.join(installer_root,"commands","*.py")): shutil.copy(path, PATH_SCRIPTS_PYTHONZ_COMMANDS) for path in glob.glob(os.path.join(installer_root,"installer","*.py")): shutil.copy(path, PATH_SCRIPTS_PYTHONZ_INSTALLER) # create patches direcotry DEST_PATCHES = os.path.join(PATH_SCRIPTS_PYTHONZ, 'patches') rm_r(DEST_PATCHES) shutil.copytree(PATH_PATCHES, DEST_PATCHES) # create a main file with open("%s/pythonz_main.py" % PATH_SCRIPTS, "w") as f: f.write("""import pythonz if __name__ == "__main__": pythonz.main() """) # create entry point file with open(PATH_BIN_PYTHONZ, "w") as f: f.write("""#!/usr/bin/env bash python %s/pythonz_main.py "$@" """ % PATH_SCRIPTS) # mode 0755 os.chmod(PATH_BIN_PYTHONZ, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) # create a bashrc for pythonz shutil.copy(os.path.join(installer_root,'etc','bashrc'), os.path.join(PATH_ETC,'bashrc')) # create a fish file for pythonz shutil.copy(os.path.join(installer_root, 'etc', 'pythonz.fish'), os.path.join(PATH_ETC, 'pythonz.fish')) #copy all *.sh files to bash_completion.d directory for path in glob.glob(os.path.join(installer_root,"etc","bash_completion.d","*.sh")): shutil.copy( path, PATH_BASH_COMPLETION ) @staticmethod def systemwide_install(): profile = """\ #begin-pythonz if [ -n "${BASH_VERSION:-}" -o -n "${ZSH_VERSION:-}" ] ; then export PYTHONZ_ROOT=%(root)s source "${PYTHONZ_ROOT}/etc/bashrc" fi #end-pythonz """ % {'root': ROOT} if os.path.isdir('/etc/profile.d'): with open('/etc/profile.d/pythonz.sh', 'w') as f: f.write(profile) elif os.path.isfile('/etc/profile'): # create backup shutil.copy('/etc/profile', '/tmp/profile.pythonz.%s' % int(time.time())) output = [] is_copy = True with open('/etc/profile', 'r') as f: for line in f: if line.startswith('#begin-pythonz'): is_copy = False continue elif line.startswith('#end-pythonz'): is_copy = True continue if is_copy: output.append(line) output.append(profile) with open('/etc/profile', 'w') as f: f.write(''.join(output)) PKYEpythonz/etc/bashrc# settings PATH_ROOT="$PYTHONZ_ROOT" if [ -z "${PATH_ROOT}" ] ; then PATH_ROOT="$HOME/.pythonz" fi PATH_ETC="$PATH_ROOT/etc" PATH_HOME="$PYTHONZ_HOME" if [ -z "${PATH_HOME}" ] ; then PATH_HOME="$HOME/.pythonz" fi PATH_HOME_ETC="$PATH_HOME/etc" # py file PY_PYTHONZ="$PATH_ROOT/bin/pythonz" # completion PYTHONZ_COMPLETION="$PATH_ETC/bash_completion.d/pythonz_completion.sh" # functions __pythonz_set_path() { export PATH=$PATH_ROOT/bin:$PATH } __pythonz_reload() { [[ -s "$PATH_ETC/bashrc" ]] && source "$PATH_ETC/bashrc" } __pythonz_update() { $pythonz "$@" [[ $? == 0 ]] && __pythonz_reload } __pythonz_find_command() { command_name="" for arg in "$@" ; do case $arg in --*) continue;; -*) continue;; *) command_name=$arg break ;; esac done } __pythonz_run() { __pythonz_find_command "$@" case $command_name in update) __pythonz_update "$@" ;; *) $pythonz "$@" ;; esac builtin hash -r } pythonz() { pythonz=$PY_PYTHONZ __pythonz_run "$@" } sudo-pythonz() { pythonz="sudo PYTHONZ_ROOT=$PATH_ROOT PATH=$PATH_PYTHONZ:$PATH_WITHOUT_PYTHONZ $PY_PYTHONZ" __pythonz_run "$@" } __pythonz_bash_completion() { if [ -s "$PYTHONZ_COMPLETION" ];then . $PYTHONZ_COMPLETION fi } # main __pythonz_set_path # nebale completion on bash >= 4 if [ ${BASH_VERSION} ] && [ ${BASH_VERSION:0:1} -ge 4 ]; then __pythonz_bash_completion declare -A _pythonz_context fi PKYEHXxxpythonz/etc/pythonz.fish# settings if [ -z "$PYTHONZ_ROOT" ] set PYTHONZ_ROOT "$HOME/.pythonz" end if [ -z "$PYTHONZ_HOME" ] set PYTHONZ_HOME "$HOME/.pythonz" end # functions function __pythonz_set_path if not contains "$PYTHONZ_ROOT/bin" $PATH set PATH "$PYTHONZ_ROOT/bin" $PATH end end function __pythonz_reload if [ -s "$PYTHONZ_ROOT/etc/pythonz.fish" ] . "$PYTHONZ_ROOT/etc/pythonz.fish" end end function __pythonz_update command pythonz $argv if [ $status = 0 ] __pythonz_reload end end function __pythonz_find_command for arg in $argv switch $arg case '-*' continue case '*' echo $arg return end end end function pythonz set -l command_name (__pythonz_find_command $argv) switch "$command_name" case update __pythonz_update $argv case '*' command pythonz $argv end end # main __pythonz_set_path PKYEQ&3pythonz/etc/bash_completion.d/pythonz_completion.shdeclare -A _pythonz_context _pythonz_complete(){ local option command commands type types types_regex command_option local available_versions installed_versions unique_versions installed_regex known_versions local logfile COMPREPLY=() types="cpython stackless pypy pypy3 jython" commands="cleanup help install list locate uninstall update version" if [ $COMP_CWORD -eq 1 ]; then _pythonz_context["pythonz"]="-h" _pythonz_compreply $commands ${_pythonz_context["pythonz"]} elif [ $COMP_CWORD -eq 2 ]; then _pythonz_context["type"]="cpython" _pythonz_context["install"]="-t -f -v -h --run-tests --framework --universal --shared --file --url --reinstall -C --configure" _pythonz_context["uninstall"]="-t -h" _pythonz_context["cleanup"]="-a -h" _pythonz_context["list"]="-a -h" _pythonz_context["locate"]="-t -h" _pythonz_context["update"]="--dev -h" _pythonz_context["version"]="-h" command=${COMP_WORDS[COMP_CWORD-1]} _pythonz_handle_command $command elif [ $COMP_CWORD -ge 3 ]; then command=${COMP_WORDS[1]} command_option=${COMP_WORDS[COMP_CWORD-1]} _pythonz_handle_command_option $command_option fi return 0 } _pythonz_handle_command(){ command=$* case "$command" in help|-h) commands=$( echo $commands | sed -e "s/help\|-h//g" ) _pythonz_compreply $commands ;; install) _pythonz_install ;; uninstall) _pythonz_uninstall ;; locate) _pythonz_locate ;; list|cleanup|update|version) _pythonz_compreply ${_pythonz_context["$command"]} ;; *) ;; esac } _pythonz_handle_command_option(){ option=$1 case "$option" in -h) ;; -t) _pythonz_update_command_options _pythonz_compreply $types ;; cpython|stackless|pypy|pypy3|jython) _pythonz_context["type"]=$option _pythonz_handle_command $command ;; --file) _pythonz_update_command_options _pythonz_handle_file ;; --url) _pythonz_update_command_options _pythonz_handle_url ;; *) _pythonz_update_command_options _pythonz_handle_command $command ;; esac } _pythonz_handle_file(){ COMPREPLY=( $(compgen -f -- ${COMP_WORDS[COMP_CWORD]} ) ) compopt -o plusdirs } _pythonz_handle_url(){ COMPREPLY=( $(compgen -W "http:// https:// file:// ftp://" -- ${COMP_WORDS[COMP_CWORD]} ) ) compopt -o nospace } _pythonz_update_command_options(){ if [[ $option == -* ]];then _pythonz_context["$command"]=$( echo ${_pythonz_context["$command"]} |sed -e "s/ /\n/g" |sed -e "s/^$option/ /" ) fi } _pythonz_install(){ _pythonz_available_versions _pythonz_compreply ${_pythonz_context["install"]} $available_versions } _pythonz_uninstall(){ _pythonz_installed_versions _pythonz_compreply ${_pythonz_context["uninstall"]} $installed_versions } _pythonz_locate(){ _pythonz_installed_versions _pythonz_compreply ${_pythonz_context["locate"]} $installed_versions } _pythonz_available_versions(){ _pythonz_installed_regex _pythonz_known_versions if [ -n "$installed_regex" ];then available_versions=$( echo $known_versions | sed -e "s/$installed_regex/ /g" ) else available_versions=$known_versions fi } _pythonz_installed_versions(){ type=${_pythonz_context["type"]} if [ -n "$type" ]; then installed_versions=$( pythonz list |egrep -i $type | awk '{print tolower($0)}' | sed -e "s/^.*$type-//g" ) fi } _pythonz_installed_regex(){ _pythonz_installed_versions installed_regex="" if [ -n "$installed_versions" ];then unique_versions=$( echo $installed_versions | sed -e 's/ /\n/g'| sed -e 's/\(.*\)/ \1 /g' ) installed_regex=$( echo $unique_versions |sed -e "s/ /|/g" -e "s/|$//" -e "s/|/ \\\| /g" -e "s/^/ /" -e "s/$/ /") fi } _pythonz_known_versions(){ type=${_pythonz_context["type"]} if [ -n "$type" ]; then known_versions=$( pythonz list -a |sed -n -e "/$type/,/#.*:/p" |sed -e "/#.*:/d" |awk '{print $1}' ) fi } _pythonz_compreply(){ COMPREPLY=( $( compgen -W "$*" -- ${COMP_WORDS[COMP_CWORD]}) ) } complete -F _pythonz_complete pythonz PKYEUFF.pythonz/patches/all/common/patch-setup.py.diff # HG changeset patch # User Barry Warsaw # Date 1302190091 14400 # Node ID bd0f73a9538e05f526feaf05821e68bdcff498fa # Parent 2e4cdaffe493e879fb5367a4aa454491de451137 Backport for Python 2.7 of issue 11715 support for building Python on multiarch Debian/Ubuntu. diff --git a/setup.py b/setup.py --- setup.py.orig +++ setup.py @@ -345,10 +345,34 @@ class PyBuildExt(build_ext): return platform return sys.platform + def add_multiarch_paths(self): + # Debian/Ubuntu multiarch support. + # https://wiki.ubuntu.com/MultiarchSpec + from distutils.spawn import find_executable + if not find_executable('dpkg-architecture'): + return + tmpfile = os.path.join(self.build_temp, 'multiarch') + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + ret = os.system( + 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' % + tmpfile) + try: + if ret >> 8 == 0: + with open(tmpfile) as fp: + multiarch_path_component = fp.readline().strip() + add_dir_to_list(self.compiler.library_dirs, + '/usr/lib/' + multiarch_path_component) + add_dir_to_list(self.compiler.include_dirs, + '/usr/include/' + multiarch_path_component) + finally: + os.unlink(tmpfile) + def detect_modules(self): # Ensure that /usr/local is always used add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') + self.add_multiarch_paths() # Add paths specified in the environment variables LDFLAGS and # CPPFLAGS for header and library files. PKYEyQQ0pythonz/patches/all/python24/patch-setup.py.diff--- setup.py.orig 2011-07-07 19:19:43.800122463 +0900 +++ setup.py 2011-07-07 19:25:04.548416377 +0900 @@ -13,6 +13,7 @@ from distutils.command.build_ext import build_ext from distutils.command.install import install from distutils.command.install_lib import install_lib +from distutils.spawn import find_executable # This global variable is used to hold the list of modules to be disabled. disabled_module_list = [] @@ -242,10 +243,34 @@ return platform return sys.platform + def add_multiarch_paths(self): + # Debian/Ubuntu multiarch support. + # https://wiki.ubuntu.com/MultiarchSpec + if not find_executable('dpkg-architecture'): + return + tmpfile = os.path.join(self.build_temp, 'multiarch') + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + ret = os.system( + 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' % + tmpfile) + try: + if ret >> 8 == 0: + fp = open(tmpfile) + multiarch_path_component = fp.readline().strip() + fp.close() + add_dir_to_list(self.compiler.library_dirs, + '/usr/lib/' + multiarch_path_component) + add_dir_to_list(self.compiler.include_dirs, + '/usr/include/' + multiarch_path_component) + finally: + os.unlink(tmpfile) + def detect_modules(self): # Ensure that /usr/local is always used add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') + self.add_multiarch_paths() # Add paths specified in the environment variables LDFLAGS and # CPPFLAGS for header and library files. PKYEyQQ0pythonz/patches/all/python25/patch-setup.py.diff--- setup.py.orig 2011-07-07 19:19:43.800122463 +0900 +++ setup.py 2011-07-07 19:25:04.548416377 +0900 @@ -13,6 +13,7 @@ from distutils.command.build_ext import build_ext from distutils.command.install import install from distutils.command.install_lib import install_lib +from distutils.spawn import find_executable # This global variable is used to hold the list of modules to be disabled. disabled_module_list = [] @@ -242,10 +243,34 @@ return platform return sys.platform + def add_multiarch_paths(self): + # Debian/Ubuntu multiarch support. + # https://wiki.ubuntu.com/MultiarchSpec + if not find_executable('dpkg-architecture'): + return + tmpfile = os.path.join(self.build_temp, 'multiarch') + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + ret = os.system( + 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' % + tmpfile) + try: + if ret >> 8 == 0: + fp = open(tmpfile) + multiarch_path_component = fp.readline().strip() + fp.close() + add_dir_to_list(self.compiler.library_dirs, + '/usr/lib/' + multiarch_path_component) + add_dir_to_list(self.compiler.include_dirs, + '/usr/include/' + multiarch_path_component) + finally: + os.unlink(tmpfile) + def detect_modules(self): # Ensure that /usr/local is always used add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') + self.add_multiarch_paths() # Add paths specified in the environment variables LDFLAGS and # CPPFLAGS for header and library files. PKYE@S3pythonz/patches/all/python25/patch-svnversion.patch--- configure.in +++ configure.in @@ -767,7 +767,7 @@ then SVNVERSION="svnversion \$(srcdir)" else - SVNVERSION="echo exported" + SVNVERSION="echo Unversioned directory" fi case $MACHDEP in --- Makefile.pre.in +++ Makefile.pre.in @@ -501,7 +501,7 @@ $(SIGNAL_OBJS) \ $(MODOBJS) \ $(srcdir)/Modules/getbuildinfo.c - $(CC) -c $(PY_CFLAGS) -DSVNVERSION=\"`LC_ALL=C $(SVNVERSION)`\" -o $@ $(srcdir)/Modules/getbuildinfo.c + $(CC) -c $(PY_CFLAGS) -DSVNVERSION="\"`LC_ALL=C $(SVNVERSION)`\"" -o $@ $(srcdir)/Modules/getbuildinfo.c Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile $(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ --- Modules/getbuildinfo.c +++ Modules/getbuildinfo.c @@ -48,5 +48,5 @@ static const char svnversion[] = SVNVERSION; if (svnversion[0] != '$') return svnversion; /* it was interpolated, or passed on command line */ - return "exported"; + return "Unversioned directory"; } --- Python/sysmodule.c +++ Python/sysmodule.c @@ -1161,7 +1161,7 @@ svnversion = _Py_svnversion(); - if (strcmp(svnversion, "exported") != 0) + if (strcmp(svnversion, "Unversioned directory") != 0 && strcmp(svnversion, "exported") != 0) svn_revision = svnversion; else if (istag) { len = strlen(_patchlevel_revision); PKYEEXQQ1pythonz/patches/all/python26/patch-nosslv2-1.diffdiff -r c9910fd022fc -r 0cc743bd3a6d Doc/library/ssl.rst --- Doc/library/ssl.rst +++ Doc/library/ssl.rst @@ -219,10 +219,6 @@ socket connection. Note that use of this setting requires a valid certificate validation file also be passed as a value of the ``ca_certs`` parameter. - -.. data:: PROTOCOL_SSLv2 - - Selects SSL version 2 as the channel encryption protocol. .. data:: PROTOCOL_SSLv23 diff -r c9910fd022fc -r 0cc743bd3a6d Lib/ssl.py --- Lib/ssl.py Tue Apr 10 10:59:35 2012 -0400 +++ Lib/ssl.py Tue May 29 14:31:16 2012 -0700 @@ -49,7 +49,6 @@ The following constants identify various SSL protocol variants: -PROTOCOL_SSLv2 PROTOCOL_SSLv3 PROTOCOL_SSLv23 PROTOCOL_TLSv1 @@ -61,7 +60,7 @@ from _ssl import SSLError from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 +from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import \ SSL_ERROR_ZERO_RETURN, \ @@ -406,8 +405,6 @@ return "TLSv1" elif protocol_code == PROTOCOL_SSLv23: return "SSLv23" - elif protocol_code == PROTOCOL_SSLv2: - return "SSLv2" elif protocol_code == PROTOCOL_SSLv3: return "SSLv3" else: diff -r c9910fd022fc -r 0cc743bd3a6d Lib/test/test_ssl.py --- Lib/test/test_ssl.py +++ Lib/test/test_ssl.py @@ -74,7 +74,6 @@ s.close() def testCrucialConstants(self): - ssl.PROTOCOL_SSLv2 ssl.PROTOCOL_SSLv23 ssl.PROTOCOL_SSLv3 ssl.PROTOCOL_TLSv1 @@ -834,27 +833,9 @@ badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir, "badkey.pem")) - def testProtocolSSL2(self): - if test_support.verbose: - sys.stdout.write("\n") - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) - def testProtocolSSL23(self): if test_support.verbose: sys.stdout.write("\n") - try: - tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) - except test_support.TestFailed, x: - # this fails on some older versions of OpenSSL (0.9.7l, for instance) - if test_support.verbose: - sys.stdout.write( - " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" - % str(x)) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) @@ -873,7 +854,6 @@ tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) @@ -883,7 +863,6 @@ tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False) diff -r c9910fd022fc -r 0cc743bd3a6d Modules/_ssl.c --- Modules/_ssl.c +++ Modules/_ssl.c @@ -61,8 +61,7 @@ }; enum py_ssl_version { - PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3, + PY_SSL_VERSION_SSL3=1, PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1, }; @@ -300,8 +299,6 @@ self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL3) self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ - else if (proto_version == PY_SSL_VERSION_SSL2) - self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL23) self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ PySSL_END_ALLOW_THREADS @@ -1627,8 +1624,6 @@ PY_SSL_CERT_REQUIRED); /* protocol versions */ - PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", - PY_SSL_VERSION_SSL2); PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", PY_SSL_VERSION_SSL3); PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", PKYEZ1pythonz/patches/all/python26/patch-nosslv2-2.diffdiff -r c9910fd022fc -r 0cc743bd3a6d Doc/library/ssl.rst --- Doc/library/ssl.rst +++ Doc/library/ssl.rst @@ -219,10 +219,6 @@ certificates will be required from the other side of the socket connection. Note that use of this setting requires a valid certificate validation file also be passed as a value of the ``ca_certs`` parameter. - -.. data:: PROTOCOL_SSLv2 - - Selects SSL version 2 as the channel encryption protocol. .. data:: PROTOCOL_SSLv23 diff -r c9910fd022fc -r 0cc743bd3a6d Lib/ssl.py --- Lib/ssl.py Tue Apr 10 10:59:35 2012 -0400 +++ Lib/ssl.py Tue May 29 14:31:16 2012 -0700 @@ -49,7 +49,6 @@ The following constants identify various SSL protocol variants: -PROTOCOL_SSLv2 PROTOCOL_SSLv3 PROTOCOL_SSLv23 PROTOCOL_TLSv1 @@ -61,7 +60,7 @@ from _ssl import SSLError from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 +from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import \ SSL_ERROR_ZERO_RETURN, \ @@ -406,8 +405,6 @@ return "TLSv1" elif protocol_code == PROTOCOL_SSLv23: return "SSLv23" - elif protocol_code == PROTOCOL_SSLv2: - return "SSLv2" elif protocol_code == PROTOCOL_SSLv3: return "SSLv3" else: diff -r c9910fd022fc -r 0cc743bd3a6d Lib/test/test_ssl.py --- Lib/test/test_ssl.py +++ Lib/test/test_ssl.py @@ -74,7 +74,6 @@ s.close() def testCrucialConstants(self): - ssl.PROTOCOL_SSLv2 ssl.PROTOCOL_SSLv23 ssl.PROTOCOL_SSLv3 ssl.PROTOCOL_TLSv1 @@ -834,27 +833,9 @@ badCertTest(os.path.join(os.path.dirname(__file__) or os.curdir, "badkey.pem")) - def testProtocolSSL2(self): - if test_support.verbose: - sys.stdout.write("\n") - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) - def testProtocolSSL23(self): if test_support.verbose: sys.stdout.write("\n") - try: - tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) - except test_support.TestFailed, x: - # this fails on some older versions of OpenSSL (0.9.7l, for instance) - if test_support.verbose: - sys.stdout.write( - " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" - % str(x)) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) @@ -873,7 +854,6 @@ tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) @@ -883,7 +863,6 @@ tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False) diff -r c9910fd022fc -r 0cc743bd3a6d Modules/_ssl.c --- Modules/_ssl.c +++ Modules/_ssl.c @@ -61,8 +61,7 @@ }; enum py_ssl_version { - PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3, + PY_SSL_VERSION_SSL3=1, PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1, }; @@ -300,8 +299,6 @@ self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL3) self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ - else if (proto_version == PY_SSL_VERSION_SSL2) - self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL23) self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ PySSL_END_ALLOW_THREADS @@ -1627,8 +1624,6 @@ PY_SSL_CERT_REQUIRED); /* protocol versions */ - PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", - PY_SSL_VERSION_SSL2); PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", PY_SSL_VERSION_SSL3); PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", PKYEb81pythonz/patches/all/python26/patch-nosslv2-3.diffdiff -r c9910fd022fc -r 0cc743bd3a6d Doc/library/ssl.rst --- Doc/library/ssl.rst Tue Apr 10 10:59:35 2012 -0400 +++ Doc/library/ssl.rst Tue May 29 14:31:16 2012 -0700 @@ -218,14 +218,6 @@ Note that use of this setting requires a valid certificate validation file also be passed as a value of the ``ca_certs`` parameter. -.. data:: PROTOCOL_SSLv2 - - Selects SSL version 2 as the channel encryption protocol. - - .. warning:: - - SSL version 2 is insecure. Its use is highly discouraged. - .. data:: PROTOCOL_SSLv23 Selects SSL version 2 or 3 as the channel encryption protocol. This is a diff -r c9910fd022fc -r 0cc743bd3a6d Lib/ssl.py --- Lib/ssl.py Tue Apr 10 10:59:35 2012 -0400 +++ Lib/ssl.py Tue May 29 14:31:16 2012 -0700 @@ -49,7 +49,6 @@ The following constants identify various SSL protocol variants: -PROTOCOL_SSLv2 PROTOCOL_SSLv3 PROTOCOL_SSLv23 PROTOCOL_TLSv1 @@ -61,7 +60,7 @@ from _ssl import SSLError from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 +from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import \ SSL_ERROR_ZERO_RETURN, \ @@ -406,8 +405,6 @@ return "TLSv1" elif protocol_code == PROTOCOL_SSLv23: return "SSLv23" - elif protocol_code == PROTOCOL_SSLv2: - return "SSLv2" elif protocol_code == PROTOCOL_SSLv3: return "SSLv3" else: diff -r c9910fd022fc -r 0cc743bd3a6d Lib/test/test_ssl.py --- Lib/test/test_ssl.py Tue Apr 10 10:59:35 2012 -0400 +++ Lib/test/test_ssl.py Tue May 29 14:31:16 2012 -0700 @@ -58,7 +58,6 @@ raise def test_constants(self): - ssl.PROTOCOL_SSLv2 ssl.PROTOCOL_SSLv23 ssl.PROTOCOL_SSLv3 ssl.PROTOCOL_TLSv1 @@ -829,19 +828,6 @@ bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir, "badkey.pem")) - def test_protocol_sslv2(self): - """Connecting to an SSLv2 server with various client options""" - if test_support.verbose: - sys.stdout.write("\ntest_protocol_sslv2 disabled, " - "as it fails on OpenSSL 1.0.0+") - return - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) - try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) - def test_protocol_sslv23(self): """Connecting to an SSLv23 server with various client options""" if test_support.verbose: @@ -877,7 +863,6 @@ try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) @@ -890,7 +875,6 @@ try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) - try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False) diff -r c9910fd022fc -r 0cc743bd3a6d Modules/_ssl.c --- Modules/_ssl.c Tue Apr 10 10:59:35 2012 -0400 +++ Modules/_ssl.c Tue May 29 14:31:16 2012 -0700 @@ -62,8 +62,7 @@ }; enum py_ssl_version { - PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3, + PY_SSL_VERSION_SSL3=1, PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1 }; @@ -302,8 +301,6 @@ self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL3) self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ - else if (proto_version == PY_SSL_VERSION_SSL2) - self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL23) self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ PySSL_END_ALLOW_THREADS @@ -1688,8 +1685,6 @@ PY_SSL_CERT_REQUIRED); /* protocol versions */ - PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", - PY_SSL_VERSION_SSL2); PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", PY_SSL_VERSION_SSL3); PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", PKYE^^/pythonz/patches/all/python30/patch-nosslv2.diff--- Doc/library/ssl.rst 2009-01-04 09:04:26.000000000 +0900 +++ Doc/library/ssl.rst 2013-08-10 01:33:57.400047147 +0900 @@ -217,10 +217,6 @@ validation file also be passed as a value of the ``ca_certs`` parameter. -.. data:: PROTOCOL_SSLv2 - - Selects SSL version 2 as the channel encryption protocol. - .. data:: PROTOCOL_SSLv23 Selects SSL version 2 or 3 as the channel encryption protocol. --- Lib/ssl.py 2009-01-04 08:47:58.000000000 +0900 +++ Lib/ssl.py 2013-08-10 01:32:30.448047220 +0900 @@ -48,7 +48,6 @@ The following constants identify various SSL protocol variants: -PROTOCOL_SSLv2 PROTOCOL_SSLv3 PROTOCOL_SSLv23 PROTOCOL_TLSv1 @@ -60,8 +59,7 @@ from _ssl import SSLError from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED -from _ssl import (PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, - PROTOCOL_TLSv1) +from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import ( SSL_ERROR_ZERO_RETURN, @@ -438,8 +436,6 @@ return "TLSv1" elif protocol_code == PROTOCOL_SSLv23: return "SSLv23" - elif protocol_code == PROTOCOL_SSLv2: - return "SSLv2" elif protocol_code == PROTOCOL_SSLv3: return "SSLv3" else: --- Lib/test/test_ssl.py 2008-09-09 01:45:19.000000000 +0900 +++ Lib/test/test_ssl.py 2013-08-10 01:47:16.888046481 +0900 @@ -58,7 +58,6 @@ s.close() def testCrucialConstants(self): - ssl.PROTOCOL_SSLv2 ssl.PROTOCOL_SSLv23 ssl.PROTOCOL_SSLv3 ssl.PROTOCOL_TLSv1 @@ -825,27 +824,9 @@ connector() t.join() - def testProtocolSSL2(self): - if support.verbose: - sys.stdout.write("\n") - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) - tryProtocolCombo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) - def testProtocolSSL23(self): if support.verbose: sys.stdout.write("\n") - try: - tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv2, True) - except support.TestFailed as x: - # this fails on some older versions of OpenSSL (0.9.7l, for instance) - if support.verbose: - sys.stdout.write( - " SSL2 client to SSL23 server test unexpectedly failed:\n %s\n" - % str(x)) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv3, True) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_SSLv23, True) tryProtocolCombo(ssl.PROTOCOL_SSLv23, ssl.PROTOCOL_TLSv1, True) @@ -864,7 +845,6 @@ tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_OPTIONAL) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv23, False) tryProtocolCombo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLSv1, False) @@ -874,7 +854,6 @@ tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_OPTIONAL) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, True, ssl.CERT_REQUIRED) - tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False) tryProtocolCombo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv23, False) --- Modules/_ssl.c 2009-02-03 05:41:29.000000000 +0900 +++ Modules/_ssl.c 2013-08-10 01:44:07.820046638 +0900 @@ -62,8 +62,10 @@ }; enum py_ssl_version { +#ifndef OPENSSL_NO_SSL2 PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3, +#endif + PY_SSL_VERSION_SSL3=1, PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1, }; @@ -299,8 +301,10 @@ self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ else if (proto_version == PY_SSL_VERSION_SSL3) self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ +#ifndef OPENSSL_NO_SSL2 else if (proto_version == PY_SSL_VERSION_SSL2) self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ +#endif else if (proto_version == PY_SSL_VERSION_SSL23) self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ PySSL_END_ALLOW_THREADS @@ -1691,8 +1695,10 @@ PY_SSL_CERT_REQUIRED); /* protocol versions */ +#ifndef OPENSSL_NO_SSL2 PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", PY_SSL_VERSION_SSL2); +#endif PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", PY_SSL_VERSION_SSL3); PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", PKYE9@@0pythonz/patches/all/python30/patch-setup.py.diff--- setup.py.orig 2011-07-07 19:41:48.610196111 +0900 +++ setup.py 2011-07-07 19:46:44.986310031 +0900 @@ -14,6 +14,7 @@ from distutils.command.build_ext import build_ext from distutils.command.install import install from distutils.command.install_lib import install_lib +from distutils.spawn import find_executable # This global variable is used to hold the list of modules to be disabled. disabled_module_list = [] @@ -308,10 +309,33 @@ return platform return sys.platform + def add_multiarch_paths(self): + # Debian/Ubuntu multiarch support. + # https://wiki.ubuntu.com/MultiarchSpec + if not find_executable('dpkg-architecture'): + return + tmpfile = os.path.join(self.build_temp, 'multiarch') + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + ret = os.system( + 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' % + tmpfile) + try: + if ret >> 8 == 0: + with open(tmpfile) as fp: + multiarch_path_component = fp.readline().strip() + add_dir_to_list(self.compiler.library_dirs, + '/usr/lib/' + multiarch_path_component) + add_dir_to_list(self.compiler.include_dirs, + '/usr/include/' + multiarch_path_component) + finally: + os.unlink(tmpfile) + def detect_modules(self): # Ensure that /usr/local is always used add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') + self.add_multiarch_paths() # Add paths specified in the environment variables LDFLAGS and # CPPFLAGS for header and library files. PKYEYTpp0pythonz/patches/all/python32/patch-setup.py.diff--- setup.py.orig 2011-07-07 20:26:15.000000000 +0900 +++ setup.py 2011-07-07 20:29:28.735543350 +0900 @@ -370,12 +370,35 @@ return platform return sys.platform + def add_multiarch_paths(self): + # Debian/Ubuntu multiarch support. + # https://wiki.ubuntu.com/MultiarchSpec + if not find_executable('dpkg-architecture'): + return + tmpfile = os.path.join(self.build_temp, 'multiarch') + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + ret = os.system( + 'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' % + tmpfile) + try: + if ret >> 8 == 0: + with open(tmpfile) as fp: + multiarch_path_component = fp.readline().strip() + add_dir_to_list(self.compiler.library_dirs, + '/usr/lib/' + multiarch_path_component) + add_dir_to_list(self.compiler.include_dirs, + '/usr/include/' + multiarch_path_component) + finally: + os.unlink(tmpfile) + def detect_modules(self): # Ensure that /usr/local is always used, but the local build # directories (i.e. '.' and 'Include') must be first. See issue # 10520. add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') + self.add_multiarch_paths() # Add paths specified in the environment variables LDFLAGS and # CPPFLAGS for header and library files. PKYE?Q3pythonz/patches/osx/python24/patch-Include-pyport.h--- Include/pyport.h.orig 2007-03-12 23:26:06.000000000 -0700 +++ Include/pyport.h 2007-03-12 23:29:35.000000000 -0700 @@ -152,11 +152,23 @@ #if defined(PYOS_OS2) && defined(PYCC_GCC) #include #endif + +#if (defined __APPLE__) && (!defined _POSIX_C_SOURCE) +#define TEMPORARILY_DEFINING__POSIX_C_SOURCE /* so we can #undef it later */ +#define _POSIX_C_SOURCE /* avoid deprecated struct ostat in sys/stat.h */ +#endif + #include #elif defined(HAVE_STAT_H) #include #endif +/* Mac OS X: undefine _POSIX_C_SOURCE if it wasn't defined before */ +#ifdef TEMPORARILY_DEFINING__POSIX_C_SOURCE +#undef _POSIX_C_SOURCE +#undef TEMPORARILY_DEFINING__POSIX_C_SOURCE +#endif + #if defined(PYCC_VACPP) /* VisualAge C/C++ Failed to Define MountType Field in sys/stat.h */ #define S_IFMT (S_IFDIR|S_IFCHR|S_IFREG) @@ -393,6 +405,7 @@ /* BSDI does not supply a prototype for the 'openpty' and 'forkpty' functions, even though they are included in libutil. */ #include +struct winsize; extern int openpty(int *, int *, char *, struct termios *, struct winsize *); extern int forkpty(int *, char *, struct termios *, struct winsize *); #endif /* !defined(HAVE_PTY_H) && !defined(HAVE_LIBUTIL_H) */ PKYEi((2pythonz/patches/osx/python24/patch-Lib-cgi.py.diff--- Lib/cgi.py.orig 2006-08-11 09:14:38.000000000 +0200 +++ Lib/cgi.py 2007-08-21 15:36:54.000000000 +0200 @@ -1,13 +1,6 @@ -#! /usr/local/bin/python +#! __PREFIX__/bin/python2.4 -# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is -# intentionally NOT "/usr/bin/env python". On many systems -# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI -# scripts, and /usr/local/bin is the default directory where Python is -# installed, so /usr/bin/env would be unable to find python. Granted, -# binary installations by Linux vendors often install Python in -# /usr/bin. So let those vendors patch cgi.py to match their choice -# of installation. +# NOTE: /usr/local/bin/python patched for MacPorts installation """Support module for CGI (Common Gateway Interface) scripts. PKYE&&3pythonz/patches/osx/python24/patch-Lib-site.py.diff--- Lib/site.py Tue Jul 20 04:28:28 2004 +++ Lib/site.py.new Mon Apr 4 10:47:12 2005 @@ -186,6 +186,7 @@ else: sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] if sys.platform == 'darwin': + sitedirs.append( os.path.join('__PREFIX__', 'lib', 'python2.4', 'site-packages') ) # for framework builds *only* we add the standard Apple # locations. Currently only per-user, but /Library and # /Network/Library could be added too PKYEӕ YY2pythonz/patches/osx/python24/patch-Makefile.pre.in--- Makefile.pre.in.orig 2006-10-08 10:41:25.000000000 -0700 +++ Makefile.pre.in 2007-04-20 18:06:11.000000000 -0700 @@ -56,7 +56,7 @@ OPT= @OPT@ BASECFLAGS= @BASECFLAGS@ CFLAGS= $(BASECFLAGS) $(OPT) -CPPFLAGS= -I. -I$(srcdir)/Include +CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir)/Include LDFLAGS= @LDFLAGS@ LDLAST= @LDLAST@ SGI_ABI= @SGI_ABI@ PKYE "22;pythonz/patches/osx/python24/patch-configure-badcflags.diff--- configure.orig 2009-08-31 01:29:04.000000000 +1000 +++ configure 2009-08-31 01:30:05.000000000 +1000 @@ -3817,9 +3817,9 @@ # is there any other compiler on Darwin besides gcc? Darwin*) if [[ `/usr/bin/arch` = 'ppc' ]]; then - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common" + BASECFLAGS="$BASECFLAGS -mno-fused-madd -fno-common" else - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -fno-common" + BASECFLAGS="$BASECFLAGS -fno-common" fi ;; esacPKYE ((3pythonz/patches/osx/python24/patch-macosmodule.diff--- Mac/Modules/macosmodule.c 2004-11-05 08:02:59.000000000 +0100 +++ Mac/Modules/macosmodule.c 2009-09-05 02:07:14.000000000 +0200 @@ -40,7 +40,7 @@ typedef struct { PyObject_HEAD - short fRefNum; + FSIORefNum fRefNum; int isclosed; } rfobject; @@ -54,7 +54,7 @@ do_close(rfobject *self) { if (self->isclosed ) return; - (void)FSClose(self->fRefNum); + (void)FSCloseFork(self->fRefNum); self->isclosed = 1; } @@ -68,6 +68,7 @@ long n; PyObject *v; OSErr err; + ByteCount n2; if (self->isclosed) { PyErr_SetString(PyExc_ValueError, "Operation on closed file"); @@ -81,13 +82,13 @@ if (v == NULL) return NULL; - err = FSRead(self->fRefNum, &n, PyString_AsString(v)); + err = FSReadFork(self->fRefNum, fsAtMark, 0, n, PyString_AsString(v), &n2); if (err && err != eofErr) { PyMac_Error(err); Py_DECREF(v); return NULL; } - _PyString_Resize(&v, n); + _PyString_Resize(&v, n2); return v; } @@ -109,7 +110,7 @@ } if (!PyArg_ParseTuple(args, "s#", &buffer, &size)) return NULL; - err = FSWrite(self->fRefNum, &size, buffer); + err = FSWriteFork(self->fRefNum, fsAtMark, 0, size, buffer, NULL); if (err) { PyMac_Error(err); return NULL; @@ -126,47 +127,36 @@ static PyObject * rf_seek(rfobject *self, PyObject *args) { - long amount, pos; + long amount; int whence = SEEK_SET; - long eof; + int mode; OSErr err; if (self->isclosed) { PyErr_SetString(PyExc_ValueError, "Operation on closed file"); return NULL; } - if (!PyArg_ParseTuple(args, "l|i", &amount, &whence)) + if (!PyArg_ParseTuple(args, "l|i", &amount, &whence)) { return NULL; - - if ((err = GetEOF(self->fRefNum, &eof))) - goto ioerr; + } switch (whence) { case SEEK_CUR: - if ((err = GetFPos(self->fRefNum, &pos))) - goto ioerr; + mode = fsFromMark; break; case SEEK_END: - pos = eof; + mode = fsFromLEOF; break; case SEEK_SET: - pos = 0; + mode = fsFromStart; break; default: PyErr_BadArgument(); return NULL; } - - pos += amount; - - /* Don't bother implementing seek past EOF */ - if (pos > eof || pos < 0) { - PyErr_BadArgument(); - return NULL; - } - - if ((err = SetFPos(self->fRefNum, fsFromStart, pos)) ) { -ioerr: + + err = FSSetForkPosition(self->fRefNum, mode, amount); + if (err != noErr) { PyMac_Error(err); return NULL; } @@ -182,7 +172,7 @@ static PyObject * rf_tell(rfobject *self, PyObject *args) { - long where; + long long where; OSErr err; if (self->isclosed) { @@ -191,11 +181,13 @@ } if (!PyArg_ParseTuple(args, "")) return NULL; - if ((err = GetFPos(self->fRefNum, &where)) ) { + + err = FSGetForkPosition(self->fRefNum, &where); + if (err != noErr) { PyMac_Error(err); return NULL; } - return PyInt_FromLong(where); + return PyLong_FromLongLong(where); } static char rf_close__doc__[] = @@ -281,6 +273,7 @@ Rftype__doc__ /* Documentation string */ }; + /* End of code for Resource fork objects */ /* -------------------------------------------------------- */ @@ -292,17 +285,61 @@ static PyObject * MacOS_GetCreatorAndType(PyObject *self, PyObject *args) { - FSSpec fss; - FInfo info; PyObject *creator, *type, *res; OSErr err; - - if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss)) + FSRef ref; + FSCatalogInfo cataloginfo; + FileInfo* finfo; + + if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &ref)) { +#ifndef __LP64__ + /* This function is documented to take an FSSpec as well, + * which only works in 32-bit mode. + */ + PyErr_Clear(); + FSSpec fss; + FInfo info; + + if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss)) + return NULL; + + if ((err = FSpGetFInfo(&fss, &info)) != noErr) { + return PyErr_Mac(MacOS_Error, err); + } + creator = PyString_FromStringAndSize( + (char *)&info.fdCreator, 4); + type = PyString_FromStringAndSize((char *)&info.fdType, 4); + res = Py_BuildValue("OO", creator, type); + Py_DECREF(creator); + Py_DECREF(type); + return res; +#else /* __LP64__ */ + return NULL; +#endif /* __LP64__ */ + } + + err = FSGetCatalogInfo(&ref, + kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo, + NULL, NULL, NULL); + if (err != noErr) { + PyErr_Mac(MacOS_Error, err); return NULL; - if ((err = FSpGetFInfo(&fss, &info)) != noErr) - return PyErr_Mac(MacOS_Error, err); - creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4); - type = PyString_FromStringAndSize((char *)&info.fdType, 4); + } + + if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) { + /* Directory: doesn't have type/creator info. + * + * The specific error code is for backward compatibility with + * earlier versions. + */ + PyErr_Mac(MacOS_Error, fnfErr); + return NULL; + + } + finfo = (FileInfo*)&(cataloginfo.finderInfo); + creator = PyString_FromStringAndSize((char*)&(finfo->fileCreator), 4); + type = PyString_FromStringAndSize((char*)&(finfo->fileType), 4); + res = Py_BuildValue("OO", creator, type); Py_DECREF(creator); Py_DECREF(type); @@ -314,20 +351,66 @@ static PyObject * MacOS_SetCreatorAndType(PyObject *self, PyObject *args) { - FSSpec fss; ResType creator, type; - FInfo info; + FSRef ref; + FileInfo* finfo; OSErr err; - + FSCatalogInfo cataloginfo; + if (!PyArg_ParseTuple(args, "O&O&O&", + PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) { +#ifndef __LP64__ + /* Try to handle FSSpec arguments, for backward compatibility */ + FSSpec fss; + FInfo info; + + if (!PyArg_ParseTuple(args, "O&O&O&", PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) + return NULL; + + if ((err = FSpGetFInfo(&fss, &info)) != noErr) + return PyErr_Mac(MacOS_Error, err); + + info.fdCreator = creator; + info.fdType = type; + + if ((err = FSpSetFInfo(&fss, &info)) != noErr) + return PyErr_Mac(MacOS_Error, err); + Py_INCREF(Py_None); + return Py_None; +#else /* __LP64__ */ return NULL; - if ((err = FSpGetFInfo(&fss, &info)) != noErr) - return PyErr_Mac(MacOS_Error, err); - info.fdCreator = creator; - info.fdType = type; - if ((err = FSpSetFInfo(&fss, &info)) != noErr) - return PyErr_Mac(MacOS_Error, err); +#endif /* __LP64__ */ + } + + err = FSGetCatalogInfo(&ref, + kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo, + NULL, NULL, NULL); + if (err != noErr) { + PyErr_Mac(MacOS_Error, err); + return NULL; + } + + if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) { + /* Directory: doesn't have type/creator info. + * + * The specific error code is for backward compatibility with + * earlier versions. + */ + PyErr_Mac(MacOS_Error, fnfErr); + return NULL; + + } + finfo = (FileInfo*)&(cataloginfo.finderInfo); + finfo->fileCreator = creator; + finfo->fileType = type; + + err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &cataloginfo); + if (err != noErr) { + PyErr_Mac(MacOS_Error, fnfErr); + return NULL; + } + Py_INCREF(Py_None); return Py_None; } @@ -375,6 +458,7 @@ /* And try again... */ h = GetResource('Estr', err); } + Py_DECREF(m); } } /* @@ -398,6 +482,9 @@ return Py_BuildValue("s", buf); } + +#ifndef __LP64__ + static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)"; static PyObject * @@ -416,7 +503,7 @@ return NULL; olddialog = curdialog; curdialog = NULL; - + if ( resid != -1 ) { curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1); if ( curdialog ) { @@ -451,11 +538,13 @@ if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object)) return NULL; + DebugStr(message); Py_INCREF(Py_None); return Py_None; } + static char SysBeep_doc[] = "BEEEEEP!!!"; static PyObject * @@ -470,6 +559,8 @@ return Py_None; } +#endif /* __LP64__ */ + static char WMAvailable_doc[] = "True if this process can interact with the display." "Will foreground the application on the first call as a side-effect." @@ -529,51 +620,37 @@ { OSErr err; char *mode = "r"; - FSSpec fss; - SignedByte permission = 1; + FSRef ref; + SInt8 permission = fsRdPerm; rfobject *fp; + HFSUniStr255 name; - if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode)) + if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSRef, &ref, &mode)) return NULL; while (*mode) { switch (*mode++) { case '*': break; - case 'r': permission = 1; break; - case 'w': permission = 2; break; + case 'r': permission = fsRdPerm; break; + case 'w': permission = fsWrPerm; break; case 'b': break; default: PyErr_BadArgument(); return NULL; } } + + err = FSGetResourceForkName(&name); + if (err != noErr) { + PyMac_Error(err); + return NULL; + } if ( (fp = newrfobject()) == NULL ) return NULL; - - err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum); + - if ( err == fnfErr ) { - /* In stead of doing complicated things here to get creator/type - ** correct we let the standard i/o library handle it - */ - FILE *tfp; - char pathname[PATHNAMELEN]; - - if ( (err=PyMac_GetFullPathname(&fss, pathname, PATHNAMELEN)) ) { - PyMac_Error(err); - Py_DECREF(fp); - return NULL; - } - - if ( (tfp = fopen(pathname, "w")) == NULL ) { - PyMac_Error(fnfErr); /* What else... */ - Py_DECREF(fp); - return NULL; - } - fclose(tfp); - err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum); - } - if ( err ) { + err = FSOpenFork(&ref, name.length, name.unicode, permission, &fp->fRefNum); + if (err != noErr) { Py_DECREF(fp); PyMac_Error(err); return NULL; @@ -583,15 +660,18 @@ } + static PyMethodDef MacOS_Methods[] = { {"GetCreatorAndType", MacOS_GetCreatorAndType, 1, getcrtp_doc}, {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc}, {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc}, {"openrf", MacOS_openrf, 1, openrf_doc}, +#ifndef __LP64__ {"splash", MacOS_splash, 1, splash_doc}, {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc}, - {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc}, {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc}, +#endif /* __LP64__ */ + {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc}, {"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc}, {NULL, NULL} /* Sentinel */ }; PKYE]'6pythonz/patches/osx/python24/patch-mactoolboxglue.diff--- Python/mactoolboxglue.c 2006-10-08 19:41:25.000000000 +0200 +++ Python/mactoolboxglue.c 2009-09-05 01:25:57.000000000 +0200 @@ -414,7 +414,7 @@ GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs") GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs") - +/* GLUE_NEW(Track, TrackObj_New, "Carbon.Qt") GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt") GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt") @@ -427,7 +427,7 @@ GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt") GLUE_NEW(Media, MediaObj_New, "Carbon.Qt") GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt") - +*/ GLUE_NEW(Handle, ResObj_New, "Carbon.Res") GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res") GLUE_NEW(Handle, OptResObj_New, "Carbon.Res") PKYEqII4pythonz/patches/osx/python24/patch-pymactoolbox.diff--- Include/pymactoolbox.h 2004-11-05 08:02:59.000000000 +0100 +++ Include/pymactoolbox.h 2009-09-05 01:26:30.000000000 +0200 @@ -134,6 +134,7 @@ extern int GWorldObj_Convert(PyObject *, GWorldPtr *); /* Qt exports */ +/* extern PyObject *TrackObj_New(Track); extern int TrackObj_Convert(PyObject *, Track *); extern PyObject *MovieObj_New(Movie); @@ -146,6 +147,7 @@ extern int UserDataObj_Convert(PyObject *, UserData *); extern PyObject *MediaObj_New(Media); extern int MediaObj_Convert(PyObject *, Media *); +*/ /* Res exports */ extern PyObject *ResObj_New(Handle); PKYEi^9pythonz/patches/osx/python24/patch240-Mac-OSX-Makefile.in--- Mac/OSX/Makefile.orig 2006-10-08 10:41:25.000000000 -0700 +++ Mac/OSX/Makefile 2007-04-27 11:07:02.000000000 -0700 @@ -5,7 +5,7 @@ VERSION=2.4 builddir = ../.. srcdir = ../.. -prefix=/Library/Frameworks/Python.framework/Versions/$(VERSION) +prefix=__FRAMEWORKS_DIR__/Python.framework/Versions/$(VERSION) LIBDEST=$(prefix)/lib/python$(VERSION) BUILDPYTHON=$(builddir)/python.exe DESTDIR= @@ -16,7 +16,7 @@ # These are normally glimpsed from the previous set bindir=/usr/local/bin -PYTHONAPPSPATH=/Applications/MacPython-$(VERSION) +PYTHONAPPSPATH=__APPLICATIONS_DIR__/MacPython-$(VERSION) PYTHONAPPSDIR=$(PYTHONAPPSPATH) APPINSTALLDIR=$(prefix)/Resources/Python.app PKYEpgDD/pythonz/patches/osx/python24/patch240-configure--- configure.orig 2007-04-05 21:32:57.000000000 -0700 +++ configure 2007-04-05 21:32:59.000000000 -0700 @@ -3816,7 +3816,11 @@ ;; # is there any other compiler on Darwin besides gcc? Darwin*) - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd" + if [[ `/usr/bin/arch` = 'ppc' ]]; then + BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common" + else + BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -fno-common" + fi ;; esac ;; @@ -10183,12 +10183,12 @@ case $ac_sys_system/$ac_sys_release in Darwin/1.3*) - LIBTOOL_CRUFT="-lcc_dynamic -arch_only ppc" + LIBTOOL_CRUFT="-lcc_dynamic -arch_only "`/usr/bin/arch` LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; Darwin/*) - LIBTOOL_CRUFT="-lcc_dynamic -arch_only ppc" + LIBTOOL_CRUFT="-lcc_dynamic -arch_only "`/usr/bin/arch` LIBTOOL_CRUFT="$LIBTOOL_CRUFT" LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; esac PKYE9>>:pythonz/patches/osx/python24/patch240-gestaltmodule.c.diff--- Mac/Modules/gestaltmodule.c.orig 2010-11-21 15:35:00.000000000 +0900 +++ Mac/Modules/gestaltmodule.c 2010-11-21 15:48:27.000000000 +0900 @@ -36,7 +36,7 @@ char *str; int size; OSType selector; - long response; + SInt32 response; if (!PyArg_Parse(args, "s#", &str, &size)) return NULL; if (size != 4) {PKYEg3pythonz/patches/osx/python24/patch240-setup.py.diff--- setup.py.orig 2006-10-08 11:41:25.000000000 -0600 +++ setup.py 2008-11-19 22:13:50.000000000 -0700 @@ -15,7 +15,7 @@ from distutils.command.install_lib import install_lib # This global variable is used to hold the list of modules to be disabled. -disabled_module_list = [] +disabled_module_list = ["readline"] def add_dir_to_list(dirlist, dir): """Add the directory 'dir' to the list 'dirlist' (at the front) if @@ -246,11 +246,11 @@ # Add paths to popular package managers on OS X/darwin if sys.platform == "darwin": # Fink installs into /sw by default - add_dir_to_list(self.compiler.library_dirs, '/sw/lib') - add_dir_to_list(self.compiler.include_dirs, '/sw/include') + #add_dir_to_list(self.compiler.library_dirs, '/sw/lib') + #add_dir_to_list(self.compiler.include_dirs, '/sw/include') # DarwinPorts installs into /opt/local by default - add_dir_to_list(self.compiler.library_dirs, '/opt/local/lib') - add_dir_to_list(self.compiler.include_dirs, '/opt/local/include') + add_dir_to_list(self.compiler.library_dirs, '__PREFIX__/lib') + add_dir_to_list(self.compiler.include_dirs, '__PREFIX__/include') if os.path.normpath(sys.prefix) != '/usr': add_dir_to_list(self.compiler.library_dirs, @@ -357,7 +357,7 @@ exts.append( Extension('unicodedata', ['unicodedata.c']) ) # access to ISO C locale support data = open('pyconfig.h').read() - m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data) + m = re.search(r"#\s*define\s+(HAVE_LIBINTL_H|WITH_LIBINTL)\s+1\s*", data) if m is not None: locale_libs = ['intl'] else: @@ -954,7 +954,8 @@ self.extensions.extend(exts) # Call the method for detecting whether _tkinter can be compiled - self.detect_tkinter(inc_dirs, lib_dirs) + if ("--disable-tk" not in sysconfig.get_config_var("CONFIG_ARGS")): + self.detect_tkinter(inc_dirs, lib_dirs) def detect_tkinter_darwin(self, inc_dirs, lib_dirs): # The _tkinter module, using frameworks. Since frameworks are quite PKYE?kC7pythonz/patches/osx/python24/patch240-sysconfig.py.diff--- Lib/distutils/sysconfig.py.orig 2007-04-05 21:32:57.000000000 -0700 +++ Lib/distutils/sysconfig.py 2007-04-05 21:32:59.000000000 -0700 @@ -365,7 +365,7 @@ if sys.platform == 'darwin' and g.has_key('CONFIGURE_MACOSX_DEPLOYMENT_TARGET'): cfg_target = g['CONFIGURE_MACOSX_DEPLOYMENT_TARGET'] cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '') - if cfg_target != cur_target: + if cfg_target != cur_target and not cur_target=="": my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure' % (cur_target, cfg_target)) raise DistutilsPlatformError(my_msg)PKYE2F/pythonz/patches/osx/python24/patch241-configure--- configure.orig 2007-04-05 21:32:57.000000000 -0700 +++ configure 2007-04-05 21:32:59.000000000 -0700 @@ -3907,7 +3907,11 @@ ;; # is there any other compiler on Darwin besides gcc? Darwin*) - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd" + if [[ `/usr/bin/arch` = 'ppc' ]]; then + BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common" + else + BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -fno-common" + fi ;; esac ;; @@ -10328,7 +10333,7 @@ else LIBTOOL_CRUFT="" fi - LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs -arch_only ppc' + LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs -arch_only '`/usr/bin/arch` LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; esac PKYEJE9pythonz/patches/osx/python24/patch244-Mac-OSX-Makefile.in--- Mac/OSX/Makefile.in.orig 2006-10-08 10:41:25.000000000 -0700 +++ Mac/OSX/Makefile.in 2007-04-27 11:07:02.000000000 -0700 @@ -5,7 +5,7 @@ VERSION=@VERSION@ builddir = ../.. srcdir = @srcdir@ -prefix=/Library/Frameworks/Python.framework/Versions/$(VERSION) +prefix=__FRAMEWORKS_DIR__/Python.framework/Versions/$(VERSION) LIBDEST=$(prefix)/lib/python$(VERSION) BUILDPYTHON=$(builddir)/python.exe RUNSHARED= @RUNSHARED@ @@ -16,7 +16,7 @@ # These are normally glimpsed from the previous set bindir=@exec_prefix@/bin -PYTHONAPPSPATH=/Applications/MacPython $(VERSION) +PYTHONAPPSPATH=__APPLICATIONS_DIR__/MacPython $(VERSION) PYTHONAPPSDIR=$(PYTHONAPPSPATH) APPINSTALLDIR=$(prefix)/Resources/Python.app PKYEǨbb/pythonz/patches/osx/python24/patch244-configure--- configure.orig 2007-04-05 21:32:57.000000000 -0700 +++ configure 2007-04-05 21:32:59.000000000 -0700 @@ -3907,7 +3907,11 @@ ;; # is there any other compiler on Darwin besides gcc? Darwin*) - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd" + if [[ `/usr/bin/arch` = 'ppc' ]]; then + BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd -fno-common" + else + BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -fno-common" + fi if test "${enable_universalsdk}"; then BASECFLAGS="-arch ppc -arch i386 -isysroot ${UNIVERSALSDK} ${BASECFLAGS}" fi @@ -10328,7 +10333,7 @@ else LIBTOOL_CRUFT="" fi - LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs -arch_only ppc' + LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -lSystem -lSystemStubs -arch_only '`/usr/bin/arch` LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; esac PKYE >\\:pythonz/patches/osx/python24/patch244-gestaltmodule.c.diff--- Mac/Modules/gestaltmodule.c.orig 2010-11-21 15:35:00.000000000 +0900 +++ Mac/Modules/gestaltmodule.c 2010-11-21 15:48:27.000000000 +0900 @@ -36,7 +36,7 @@ { OSErr iErr; OSType selector; - long response; + SInt32 response; if (!PyArg_Parse(args, "O&", PyMac_GetOSType, &selector)) return NULL; iErr = Gestalt ( selector, &response );PKYEG#3pythonz/patches/osx/python24/patch244-setup.py.diff--- setup.py.orig 2006-10-08 11:41:25.000000000 -0600 +++ setup.py 2008-11-19 22:13:50.000000000 -0700 @@ -15,7 +15,7 @@ from distutils.command.install_lib import install_lib # This global variable is used to hold the list of modules to be disabled. -disabled_module_list = [] +disabled_module_list = ["readline"] def add_dir_to_list(dirlist, dir): """Add the directory 'dir' to the list 'dirlist' (at the front) if @@ -246,11 +246,11 @@ # Add paths to popular package managers on OS X/darwin if sys.platform == "darwin": # Fink installs into /sw by default - add_dir_to_list(self.compiler.library_dirs, '/sw/lib') - add_dir_to_list(self.compiler.include_dirs, '/sw/include') + #add_dir_to_list(self.compiler.library_dirs, '/sw/lib') + #add_dir_to_list(self.compiler.include_dirs, '/sw/include') # DarwinPorts installs into /opt/local by default - #add_dir_to_list(self.compiler.library_dirs, '/opt/local/lib') - #add_dir_to_list(self.compiler.include_dirs, '/opt/local/include') + add_dir_to_list(self.compiler.library_dirs, '__PREFIX__/lib') + add_dir_to_list(self.compiler.include_dirs, '__PREFIX__/include') if os.path.normpath(sys.prefix) != '/usr': add_dir_to_list(self.compiler.library_dirs, @@ -357,7 +357,7 @@ exts.append( Extension('unicodedata', ['unicodedata.c']) ) # access to ISO C locale support data = open('pyconfig.h').read() - m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data) + m = re.search(r"#\s*define\s+(HAVE_LIBINTL_H|WITH_LIBINTL)\s+1\s*", data) if m is not None: locale_libs = ['intl'] else: @@ -954,7 +954,8 @@ self.extensions.extend(exts) # Call the method for detecting whether _tkinter can be compiled - self.detect_tkinter(inc_dirs, lib_dirs) + if ("--disable-tk" not in sysconfig.get_config_var("CONFIG_ARGS")): + self.detect_tkinter(inc_dirs, lib_dirs) def detect_tkinter_darwin(self, inc_dirs, lib_dirs): # The _tkinter module, using frameworks. Since frameworks are quite PKYEe@/pythonz/patches/osx/python25/_localemodule.c.edg/defined(__APPLE__)/s//0/g w PKYE)pythonz/patches/osx/python25/locale.py.edg/'darwin', /s/// w PKYEi-pythonz/patches/osx/python25/patch-64bit.diff--- Include/pymactoolbox.h.orig 2004-11-05 18:02:59.000000000 +1100 +++ Include/pymactoolbox.h 2009-09-10 18:08:58.000000000 +1000 @@ -8,7 +8,9 @@ #endif #include +#ifndef __LP64__ #include +#endif /* !__LP64__ */ /* ** Helper routines for error codes and such. @@ -18,8 +20,10 @@ PyObject *PyMac_GetOSErrException(void); /* Initialize & return it */ PyObject *PyErr_Mac(PyObject *, int); /* Exception with a mac error */ PyObject *PyMac_Error(OSErr); /* Uses PyMac_GetOSErrException */ +#ifndef __LP64__ extern OSErr PyMac_GetFullPathname(FSSpec *, char *, int); /* convert fsspec->path */ +#endif /* !__LP64__ */ /* ** These conversion routines are defined in mactoolboxglue.c itself. */ @@ -83,9 +87,10 @@ #endif /* USE_TOOLBOX_OBJECT_GLUE */ /* macfs exports */ +#ifndef __LP64__ int PyMac_GetFSSpec(PyObject *, FSSpec *); /* argument parser for FSSpec */ PyObject *PyMac_BuildFSSpec(FSSpec *); /* Convert FSSpec to PyObject */ - +#endif /* !__LP64__ */ int PyMac_GetFSRef(PyObject *, FSRef *); /* argument parser for FSRef */ PyObject *PyMac_BuildFSRef(FSRef *); /* Convert FSRef to PyObject */ @@ -101,39 +106,54 @@ extern int CmpInstObj_Convert(PyObject *, ComponentInstance *); /* Ctl exports */ +#ifndef __LP64__ extern PyObject *CtlObj_New(ControlHandle); extern int CtlObj_Convert(PyObject *, ControlHandle *); +#endif /* !__LP64__ */ /* Dlg exports */ +#ifndef __LP64__ extern PyObject *DlgObj_New(DialogPtr); extern int DlgObj_Convert(PyObject *, DialogPtr *); extern PyObject *DlgObj_WhichDialog(DialogPtr); +#endif /* !__LP64__ */ /* Drag exports */ +#ifndef __LP64__ extern PyObject *DragObj_New(DragReference); extern int DragObj_Convert(PyObject *, DragReference *); +#endif /* !__LP64__ */ /* List exports */ +#ifndef __LP64__ extern PyObject *ListObj_New(ListHandle); extern int ListObj_Convert(PyObject *, ListHandle *); +#endif /* !__LP64__ */ /* Menu exports */ +#ifndef __LP64__ extern PyObject *MenuObj_New(MenuHandle); extern int MenuObj_Convert(PyObject *, MenuHandle *); +#endif /* !__LP64__ */ /* Qd exports */ +#ifndef __LP64__ extern PyObject *GrafObj_New(GrafPtr); extern int GrafObj_Convert(PyObject *, GrafPtr *); extern PyObject *BMObj_New(BitMapPtr); extern int BMObj_Convert(PyObject *, BitMapPtr *); extern PyObject *QdRGB_New(RGBColor *); extern int QdRGB_Convert(PyObject *, RGBColor *); +#endif /* !__LP64__ */ /* Qdoffs exports */ +#ifndef __LP64__ extern PyObject *GWorldObj_New(GWorldPtr); extern int GWorldObj_Convert(PyObject *, GWorldPtr *); +#endif /* !__LP64__ */ /* Qt exports */ +#ifndef __LP64__ extern PyObject *TrackObj_New(Track); extern int TrackObj_Convert(PyObject *, Track *); extern PyObject *MovieObj_New(Movie); @@ -146,6 +166,7 @@ extern int UserDataObj_Convert(PyObject *, UserData *); extern PyObject *MediaObj_New(Media); extern int MediaObj_Convert(PyObject *, Media *); +#endif /* !__LP64__ */ /* Res exports */ extern PyObject *ResObj_New(Handle); @@ -154,13 +175,17 @@ extern int OptResObj_Convert(PyObject *, Handle *); /* TE exports */ +#ifndef __LP64__ extern PyObject *TEObj_New(TEHandle); extern int TEObj_Convert(PyObject *, TEHandle *); +#endif /* !__LP64__ */ /* Win exports */ +#ifndef __LP64__ extern PyObject *WinObj_New(WindowPtr); extern int WinObj_Convert(PyObject *, WindowPtr *); extern PyObject *WinObj_WhichWindow(WindowPtr); +#endif /* !__LP64__ */ /* CF exports */ extern PyObject *CFObj_New(CFTypeRef); --- Python/mactoolboxglue.c.orig 2006-07-12 02:44:25.000000000 +1000 +++ Python/mactoolboxglue.c 2009-09-10 19:26:39.000000000 +1000 @@ -105,7 +105,7 @@ return PyErr_Mac(PyMac_GetOSErrException(), err); } - +#ifndef __LP64__ OSErr PyMac_GetFullPathname(FSSpec *fss, char *path, int len) { @@ -153,6 +153,7 @@ Py_XDECREF(fs); return err; } +#endif /* !__LP64__ */ /* Convert a 4-char string object argument to an OSType value */ int @@ -417,6 +418,7 @@ GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs") GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs") +#ifndef __LP64__ GLUE_NEW(Track, TrackObj_New, "Carbon.Qt") GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt") GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt") @@ -429,6 +431,7 @@ GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt") GLUE_NEW(Media, MediaObj_New, "Carbon.Qt") GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt") +#endif /* !__LP64__ */ GLUE_NEW(Handle, ResObj_New, "Carbon.Res") GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res") --- Modules/_ctypes/libffi/src/darwin/ffitarget.h.orig 2006-05-26 07:58:05.000000000 +1000 +++ Modules/_ctypes/libffi/src/darwin/ffitarget.h 2009-09-10 20:15:39.000000000 +1000 @@ -4,7 +4,7 @@ * created by configure). This makes is possible to build a univeral binary * of ctypes in one go. */ -#if defined(__i386__) +#if defined(__i386__) || defined(__x86_64__) #ifndef X86_DARWIN #define X86_DARWIN @@ -13,7 +13,7 @@ #include "../src/x86/ffitarget.h" -#elif defined(__ppc__) +#elif defined(__ppc__) || defined(__ppc64__) #ifndef POWERPC_DARWIN #define POWERPC_DARWIN --- Mac/Modules/res/_Resmodule.c.orig 2005-07-04 06:59:44.000000000 +1000 +++ Mac/Modules/res/_Resmodule.c 2009-09-10 20:44:43.000000000 +1000 @@ -414,6 +414,7 @@ return _res; } +#ifndef __LP64__ static PyObject *ResObj_as_Control(ResourceObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -431,6 +432,7 @@ return _res; } +#endif /* !__LP64__ */ static PyObject *ResObj_LoadResource(ResourceObject *_self, PyObject *_args) { @@ -501,10 +503,12 @@ PyDoc_STR("(long newSize) -> None")}, {"GetNextFOND", (PyCFunction)ResObj_GetNextFOND, 1, PyDoc_STR("() -> (Handle _rv)")}, +#ifndef __LP64__ {"as_Control", (PyCFunction)ResObj_as_Control, 1, PyDoc_STR("Return this resource/handle as a Control")}, {"as_Menu", (PyCFunction)ResObj_as_Menu, 1, PyDoc_STR("Return this resource/handle as a Menu")}, +#endif /* !__LP64__ */ {"LoadResource", (PyCFunction)ResObj_LoadResource, 1, PyDoc_STR("() -> None")}, {"AutoDispose", (PyCFunction)ResObj_AutoDispose, 1, @@ -1152,6 +1156,7 @@ return _res; } +#ifndef __LP64__ static PyObject *Res_OpenRFPerm(PyObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -1287,6 +1292,7 @@ _res = Py_None; return _res; } +#endif /* !__LP64__ */ static PyObject *Res_InsertResourceFile(PyObject *_self, PyObject *_args) { @@ -1327,6 +1333,7 @@ return _res; } +#ifndef __LP64__ static PyObject *Res_FSpResourceFileAlreadyOpen(PyObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -1413,6 +1420,7 @@ nextRefNum); return _res; } +#endif /* !__LP64__ */ static PyObject *Res_FSOpenResFile(PyObject *_self, PyObject *_args) { @@ -1438,6 +1446,7 @@ return _res; } +#ifndef __LP64__ static PyObject *Res_FSCreateResFile(PyObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -1534,6 +1543,7 @@ PyMac_BuildFSSpec, &newSpec); return _res; } +#endif /* !__LP64__ */ static PyObject *Res_FSOpenResourceFile(PyObject *_self, PyObject *_args) { @@ -1637,6 +1647,7 @@ PyDoc_STR("(short refNum) -> (short _rv)")}, {"SetResFileAttrs", (PyCFunction)Res_SetResFileAttrs, 1, PyDoc_STR("(short refNum, short attrs) -> None")}, +#ifndef __LP64__ {"OpenRFPerm", (PyCFunction)Res_OpenRFPerm, 1, PyDoc_STR("(Str255 fileName, short vRefNum, SignedByte permission) -> (short _rv)")}, {"HOpenResFile", (PyCFunction)Res_HOpenResFile, 1, @@ -1647,10 +1658,12 @@ PyDoc_STR("(FSSpec spec, SignedByte permission) -> (short _rv)")}, {"FSpCreateResFile", (PyCFunction)Res_FSpCreateResFile, 1, PyDoc_STR("(FSSpec spec, OSType creator, OSType fileType, ScriptCode scriptTag) -> None")}, +#endif /* !__LP64__ */ {"InsertResourceFile", (PyCFunction)Res_InsertResourceFile, 1, PyDoc_STR("(SInt16 refNum, RsrcChainLocation where) -> None")}, {"DetachResourceFile", (PyCFunction)Res_DetachResourceFile, 1, PyDoc_STR("(SInt16 refNum) -> None")}, +#ifndef __LP64__ {"FSpResourceFileAlreadyOpen", (PyCFunction)Res_FSpResourceFileAlreadyOpen, 1, PyDoc_STR("(FSSpec resourceFile) -> (Boolean _rv, Boolean inChain, SInt16 refNum)")}, {"FSpOpenOrphanResFile", (PyCFunction)Res_FSpOpenOrphanResFile, 1, @@ -1659,14 +1672,17 @@ PyDoc_STR("() -> (SInt16 refNum)")}, {"GetNextResourceFile", (PyCFunction)Res_GetNextResourceFile, 1, PyDoc_STR("(SInt16 curRefNum) -> (SInt16 nextRefNum)")}, +#endif /* !__LP64__ */ {"FSOpenResFile", (PyCFunction)Res_FSOpenResFile, 1, PyDoc_STR("(FSRef ref, SignedByte permission) -> (short _rv)")}, +#ifndef __LP64__ {"FSCreateResFile", (PyCFunction)Res_FSCreateResFile, 1, PyDoc_STR("(FSRef parentRef, Buffer nameLength) -> (FSRef newRef, FSSpec newSpec)")}, {"FSResourceFileAlreadyOpen", (PyCFunction)Res_FSResourceFileAlreadyOpen, 1, PyDoc_STR("(FSRef resourceFileRef) -> (Boolean _rv, Boolean inChain, SInt16 refNum)")}, {"FSCreateResourceFile", (PyCFunction)Res_FSCreateResourceFile, 1, PyDoc_STR("(FSRef parentRef, Buffer nameLength, Buffer forkNameLength) -> (FSRef newRef, FSSpec newSpec)")}, +#endif /* !__LP64__ */ {"FSOpenResourceFile", (PyCFunction)Res_FSOpenResourceFile, 1, PyDoc_STR("(FSRef ref, Buffer forkNameLength, SignedByte permissions) -> (SInt16 refNum)")}, {"Handle", (PyCFunction)Res_Handle, 1, --- Mac/Modules/MacOS.c.orig 2006-07-26 05:20:54.000000000 +1000 +++ Mac/Modules/MacOS.c 2009-09-10 21:47:34.000000000 +1000 @@ -54,7 +54,7 @@ do_close(rfobject *self) { if (self->isclosed ) return; - (void)FSClose(self->fRefNum); + (void)FSCloseFork(self->fRefNum); self->isclosed = 1; } @@ -68,6 +68,7 @@ long n; PyObject *v; OSErr err; + ByteCount n2; if (self->isclosed) { PyErr_SetString(PyExc_ValueError, "Operation on closed file"); @@ -81,13 +82,13 @@ if (v == NULL) return NULL; - err = FSRead(self->fRefNum, &n, PyString_AsString(v)); + err = FSReadFork(self->fRefNum, fsAtMark, 0, n, PyString_AsString(v), &n2); if (err && err != eofErr) { PyMac_Error(err); Py_DECREF(v); return NULL; } - _PyString_Resize(&v, n); + _PyString_Resize(&v, n2); return v; } @@ -109,7 +110,7 @@ } if (!PyArg_ParseTuple(args, "s#", &buffer, &size)) return NULL; - err = FSWrite(self->fRefNum, &size, buffer); + err = FSWriteFork(self->fRefNum, fsAtMark, 0, size, buffer, NULL); if (err) { PyMac_Error(err); return NULL; @@ -126,9 +127,9 @@ static PyObject * rf_seek(rfobject *self, PyObject *args) { - long amount, pos; + long amount; int whence = SEEK_SET; - long eof; + int mode; OSErr err; if (self->isclosed) { @@ -138,35 +139,23 @@ if (!PyArg_ParseTuple(args, "l|i", &amount, &whence)) return NULL; - if ((err = GetEOF(self->fRefNum, &eof))) - goto ioerr; - switch (whence) { case SEEK_CUR: - if ((err = GetFPos(self->fRefNum, &pos))) - goto ioerr; + mode = fsFromMark; break; case SEEK_END: - pos = eof; + mode = fsFromLEOF; break; case SEEK_SET: - pos = 0; + mode = fsFromStart; break; default: PyErr_BadArgument(); return NULL; } - pos += amount; - - /* Don't bother implementing seek past EOF */ - if (pos > eof || pos < 0) { - PyErr_BadArgument(); - return NULL; - } - - if ((err = SetFPos(self->fRefNum, fsFromStart, pos)) ) { -ioerr: + err = FSSetForkPosition(self->fRefNum, mode, amount); + if (err != noErr) { PyMac_Error(err); return NULL; } @@ -182,7 +171,7 @@ static PyObject * rf_tell(rfobject *self, PyObject *args) { - long where; + long long where; OSErr err; if (self->isclosed) { @@ -191,11 +180,13 @@ } if (!PyArg_ParseTuple(args, "")) return NULL; - if ((err = GetFPos(self->fRefNum, &where)) ) { + + err = FSGetForkPosition(self->fRefNum, &where); + if (err != noErr) { PyMac_Error(err); return NULL; } - return PyInt_FromLong(where); + return PyLong_FromLongLong(where); } static char rf_close__doc__[] = @@ -292,17 +283,61 @@ static PyObject * MacOS_GetCreatorAndType(PyObject *self, PyObject *args) { - FSSpec fss; - FInfo info; PyObject *creator, *type, *res; OSErr err; - - if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss)) + FSRef ref; + FSCatalogInfo cataloginfo; + FileInfo* finfo; + + if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &ref)) { +#ifndef __LP64__ + /* This function is documented to take an FSSpec as well, + * which only works in 32-bit mode. + */ + PyErr_Clear(); + FSSpec fss; + FInfo info; + + if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss)) + return NULL; + + if ((err = FSpGetFInfo(&fss, &info)) != noErr) { + return PyErr_Mac(MacOS_Error, err); + } + creator = PyString_FromStringAndSize( + (char *)&info.fdCreator, 4); + type = PyString_FromStringAndSize((char *)&info.fdType, 4); + res = Py_BuildValue("OO", creator, type); + Py_DECREF(creator); + Py_DECREF(type); + return res; +#else /* __LP64__ */ + return NULL; +#endif /* __LP64__ */ + } + + err = FSGetCatalogInfo(&ref, + kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo, + NULL, NULL, NULL); + if (err != noErr) { + PyErr_Mac(MacOS_Error, err); return NULL; - if ((err = FSpGetFInfo(&fss, &info)) != noErr) - return PyErr_Mac(MacOS_Error, err); - creator = PyString_FromStringAndSize((char *)&info.fdCreator, 4); - type = PyString_FromStringAndSize((char *)&info.fdType, 4); + } + + if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) { + /* Directory: doesn't have type/creator info. + * + * The specific error code is for backward compatibility with + * earlier versions. + */ + PyErr_Mac(MacOS_Error, fnfErr); + return NULL; + + } + finfo = (FileInfo*)&(cataloginfo.finderInfo); + creator = PyString_FromStringAndSize((char*)&(finfo->fileCreator), 4); + type = PyString_FromStringAndSize((char*)&(finfo->fileType), 4); + res = Py_BuildValue("OO", creator, type); Py_DECREF(creator); Py_DECREF(type); @@ -314,20 +349,66 @@ static PyObject * MacOS_SetCreatorAndType(PyObject *self, PyObject *args) { - FSSpec fss; ResType creator, type; - FInfo info; + FSRef ref; + FileInfo* finfo; OSErr err; - + FSCatalogInfo cataloginfo; + if (!PyArg_ParseTuple(args, "O&O&O&", + PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) { +#ifndef __LP64__ + /* Try to handle FSSpec arguments, for backward compatibility */ + FSSpec fss; + FInfo info; + + if (!PyArg_ParseTuple(args, "O&O&O&", PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) + return NULL; + + if ((err = FSpGetFInfo(&fss, &info)) != noErr) + return PyErr_Mac(MacOS_Error, err); + + info.fdCreator = creator; + info.fdType = type; + + if ((err = FSpSetFInfo(&fss, &info)) != noErr) + return PyErr_Mac(MacOS_Error, err); + Py_INCREF(Py_None); + return Py_None; +#else /* __LP64__ */ + return NULL; +#endif /* __LP64__ */ + } + + err = FSGetCatalogInfo(&ref, + kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo, + NULL, NULL, NULL); + if (err != noErr) { + PyErr_Mac(MacOS_Error, err); return NULL; - if ((err = FSpGetFInfo(&fss, &info)) != noErr) - return PyErr_Mac(MacOS_Error, err); - info.fdCreator = creator; - info.fdType = type; - if ((err = FSpSetFInfo(&fss, &info)) != noErr) - return PyErr_Mac(MacOS_Error, err); + } + + if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) { + /* Directory: doesn't have type/creator info. + * + * The specific error code is for backward compatibility with + * earlier versions. + */ + PyErr_Mac(MacOS_Error, fnfErr); + return NULL; + + } + finfo = (FileInfo*)&(cataloginfo.finderInfo); + finfo->fileCreator = creator; + finfo->fileType = type; + + err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &cataloginfo); + if (err != noErr) { + PyErr_Mac(MacOS_Error, fnfErr); + return NULL; + } + Py_INCREF(Py_None); return Py_None; } @@ -399,6 +480,7 @@ return Py_BuildValue("s", buf); } +#ifndef __LP64__ static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)"; static PyObject * @@ -470,6 +552,7 @@ Py_INCREF(Py_None); return Py_None; } +#endif /* !__LP64__ */ static char WMAvailable_doc[] = "True if this process can interact with the display." @@ -530,17 +613,18 @@ { OSErr err; char *mode = "r"; - FSSpec fss; - SignedByte permission = 1; + FSRef ref; + SInt8 permission = fsRdPerm; rfobject *fp; + HFSUniStr255 name; - if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSSpec, &fss, &mode)) + if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSRef, &ref, &mode)) return NULL; while (*mode) { switch (*mode++) { case '*': break; - case 'r': permission = 1; break; - case 'w': permission = 2; break; + case 'r': permission = fsRdPerm; break; + case 'w': permission = fsWrPerm; break; case 'b': break; default: PyErr_BadArgument(); @@ -548,33 +632,18 @@ } } - if ( (fp = newrfobject()) == NULL ) + err = FSGetResourceForkName(&name); + if (err != noErr) { + PyMac_Error(err); return NULL; + } - err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum); + if ( (fp = newrfobject()) == NULL ) + return NULL; + - if ( err == fnfErr ) { - /* In stead of doing complicated things here to get creator/type - ** correct we let the standard i/o library handle it - */ - FILE *tfp; - char pathname[PATHNAMELEN]; - - if ( (err=PyMac_GetFullPathname(&fss, pathname, PATHNAMELEN)) ) { - PyMac_Error(err); - Py_DECREF(fp); - return NULL; - } - - if ( (tfp = fopen(pathname, "w")) == NULL ) { - PyMac_Error(fnfErr); /* What else... */ - Py_DECREF(fp); - return NULL; - } - fclose(tfp); - err = HOpenRF(fss.vRefNum, fss.parID, fss.name, permission, &fp->fRefNum); - } - if ( err ) { + err = FSOpenFork(&ref, name.length, name.unicode, permission, &fp->fRefNum); + if (err != noErr) { Py_DECREF(fp); PyMac_Error(err); return NULL; @@ -589,10 +658,12 @@ {"SetCreatorAndType", MacOS_SetCreatorAndType, 1, setcrtp_doc}, {"GetErrorString", MacOS_GetErrorString, 1, geterr_doc}, {"openrf", MacOS_openrf, 1, openrf_doc}, +#ifndef __LP64__ {"splash", MacOS_splash, 1, splash_doc}, {"DebugStr", MacOS_DebugStr, 1, DebugStr_doc}, - {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc}, {"SysBeep", MacOS_SysBeep, 1, SysBeep_doc}, +#endif /* !__LP64__ */ + {"GetTicks", MacOS_GetTicks, 1, GetTicks_doc}, {"WMAvailable", MacOS_WMAvailable, 1, WMAvailable_doc}, {NULL, NULL} /* Sentinel */ }; --- Mac/Modules/file/_Filemodule.c.orig 2006-05-29 07:57:35.000000000 +1000 +++ Mac/Modules/file/_Filemodule.c 2009-09-10 22:48:47.000000000 +1000 @@ -18,9 +18,11 @@ #include #ifdef USE_TOOLBOX_OBJECT_GLUE +#ifndef __LP64__ extern int _PyMac_GetFSSpec(PyObject *v, FSSpec *spec); -extern int _PyMac_GetFSRef(PyObject *v, FSRef *fsr); extern PyObject *_PyMac_BuildFSSpec(FSSpec *spec); +#endif /* !__LP64__ */ +extern int _PyMac_GetFSRef(PyObject *v, FSRef *fsr); extern PyObject *_PyMac_BuildFSRef(FSRef *spec); #define PyMac_GetFSSpec _PyMac_GetFSSpec @@ -28,20 +30,26 @@ #define PyMac_BuildFSSpec _PyMac_BuildFSSpec #define PyMac_BuildFSRef _PyMac_BuildFSRef #else +#ifndef __LP64__ extern int PyMac_GetFSSpec(PyObject *v, FSSpec *spec); -extern int PyMac_GetFSRef(PyObject *v, FSRef *fsr); extern PyObject *PyMac_BuildFSSpec(FSSpec *spec); +#endif /* !__LP64__ */ +extern int PyMac_GetFSRef(PyObject *v, FSRef *fsr); extern PyObject *PyMac_BuildFSRef(FSRef *spec); #endif /* Forward declarations */ +#ifndef __LP64__ static PyObject *FInfo_New(FInfo *itself); -static PyObject *FSRef_New(FSRef *itself); static PyObject *FSSpec_New(FSSpec *itself); +#define FSSpec_Convert PyMac_GetFSSpec +#endif /* !__LP64__ */ +static PyObject *FSRef_New(FSRef *itself); static PyObject *Alias_New(AliasHandle itself); +#ifndef __LP64__ static int FInfo_Convert(PyObject *v, FInfo *p_itself); +#endif /* !__LP64__ */ #define FSRef_Convert PyMac_GetFSRef -#define FSSpec_Convert PyMac_GetFSSpec static int Alias_Convert(PyObject *v, AliasHandle *p_itself); /* @@ -62,6 +70,7 @@ /* ** Optional fsspec and fsref pointers. None will pass NULL */ +#ifndef __LP64__ static int myPyMac_GetOptFSSpecPtr(PyObject *v, FSSpec **spec) { @@ -71,6 +80,7 @@ } return PyMac_GetFSSpec(v, *spec); } +#endif /* !__LP64__ */ static int myPyMac_GetOptFSRefPtr(PyObject *v, FSRef **ref) @@ -92,6 +102,7 @@ return Py_BuildValue("u#", itself->unicode, itself->length); } +#ifndef __LP64__ static OSErr _PyMac_GetFullPathname(FSSpec *fss, char *path, int len) { @@ -135,6 +146,7 @@ } return 0; } +#endif /* !__LP64__ */ static PyObject *File_Error; @@ -282,12 +294,28 @@ static PyObject *FSCatalogInfo_get_permissions(FSCatalogInfoObject *self, void *closure) { - return Py_BuildValue("(llll)", self->ob_itself.permissions[0], self->ob_itself.permissions[1], self->ob_itself.permissions[2], self->ob_itself.permissions[3]); + FSPermissionInfo* info = (FSPermissionInfo*)&(self->ob_itself.permissions); + return Py_BuildValue("(llll)", info->userID, info->groupID, info->userAccess, info->mode); } static int FSCatalogInfo_set_permissions(FSCatalogInfoObject *self, PyObject *v, void *closure) { - return PyArg_Parse(v, "(llll)", &self->ob_itself.permissions[0], &self->ob_itself.permissions[1], &self->ob_itself.permissions[2], &self->ob_itself.permissions[3])-1; + long userID; + long groupID; + long userAccess; + long mode; + int r; + + FSPermissionInfo* info = (FSPermissionInfo*)&(self->ob_itself.permissions); + + r = PyArg_Parse(v, "(llll)", &userID, &groupID, &userAccess, &mode); + if (!r) { + return -1; + } + info->userID = userID; + info->groupID = groupID; + info->userAccess = userAccess; + info->mode = mode; return 0; } @@ -501,6 +529,7 @@ /* ----------------------- Object type FInfo ------------------------ */ +#ifndef __LP64__ static PyTypeObject FInfo_Type; #define FInfo_Check(x) ((x)->ob_type == &FInfo_Type || PyObject_TypeCheck((x), &FInfo_Type)) @@ -682,6 +711,7 @@ FInfo_tp_free, /* tp_free */ }; +#endif /* !__LP64__ */ /* --------------------- End object type FInfo ---------------------- */ @@ -729,6 +759,7 @@ self->ob_type->tp_free((PyObject *)self); } +#ifndef __LP64__ static PyObject *Alias_ResolveAlias(AliasObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -818,6 +849,7 @@ wasChanged); return _res; } +#endif /* !__LP64__ */ static PyObject *Alias_FSResolveAliasWithMountFlags(AliasObject *_self, PyObject *_args) { @@ -891,6 +923,7 @@ } static PyMethodDef Alias_methods[] = { +#ifndef __LP64__ {"ResolveAlias", (PyCFunction)Alias_ResolveAlias, 1, PyDoc_STR("(FSSpec fromFile) -> (FSSpec target, Boolean wasChanged)")}, {"GetAliasInfo", (PyCFunction)Alias_GetAliasInfo, 1, @@ -899,6 +932,7 @@ PyDoc_STR("(FSSpec fromFile, unsigned long mountFlags) -> (FSSpec target, Boolean wasChanged)")}, {"FollowFinderAlias", (PyCFunction)Alias_FollowFinderAlias, 1, PyDoc_STR("(FSSpec fromFile, Boolean logon) -> (FSSpec target, Boolean wasChanged)")}, +#endif /* !__LP64__ */ {"FSResolveAliasWithMountFlags", (PyCFunction)Alias_FSResolveAliasWithMountFlags, 1, PyDoc_STR("(FSRef fromFile, unsigned long mountFlags) -> (FSRef target, Boolean wasChanged)")}, {"FSResolveAlias", (PyCFunction)Alias_FSResolveAlias, 1, @@ -1033,6 +1067,7 @@ /* ----------------------- Object type FSSpec ----------------------- */ +#ifndef __LP64__ static PyTypeObject FSSpec_Type; @@ -1488,6 +1523,7 @@ FSSpec_tp_free, /* tp_free */ }; +#endif /* !__LP64__ */ /* --------------------- End object type FSSpec --------------------- */ @@ -1568,7 +1604,9 @@ FSCatalogInfoBitmap whichInfo; FSCatalogInfo catalogInfo; FSRef newRef; +#ifndef __LP64__ FSSpec newSpec; +#endif /* !__LP64__ */ if (!PyArg_ParseTuple(_args, "u#lO&", &nameLength__in__, &nameLength__in_len__, &whichInfo, @@ -1580,11 +1618,20 @@ whichInfo, &catalogInfo, &newRef, - &newSpec); +#ifndef __LP64__ + &newSpec +#else + NULL +#endif /* !__LP64__ */ + ); if (_err != noErr) return PyMac_Error(_err); +#ifndef __LP64__ _res = Py_BuildValue("O&O&", FSRef_New, &newRef, FSSpec_New, &newSpec); +#else + _res = Py_BuildValue("O&O", FSRef_New, &newRef, Py_None); +#endif /* !__LP64__ */ return _res; } @@ -1598,7 +1645,9 @@ FSCatalogInfoBitmap whichInfo; FSCatalogInfo catalogInfo; FSRef newRef; +#ifndef __LP64__ FSSpec newSpec; +#endif /* !__LP64__ */ UInt32 newDirID; if (!PyArg_ParseTuple(_args, "u#lO&", &nameLength__in__, &nameLength__in_len__, @@ -1611,13 +1660,25 @@ whichInfo, &catalogInfo, &newRef, +#ifndef __LP64__ &newSpec, +#else + NULL, +#endif /* !__LP64__ */ &newDirID); if (_err != noErr) return PyMac_Error(_err); + +#ifndef __LP64__ _res = Py_BuildValue("O&O&l", FSRef_New, &newRef, FSSpec_New, &newSpec, newDirID); +#else + _res = Py_BuildValue("O&Ol", + FSRef_New, &newRef, + Py_None, + newDirID); +#endif /* !__LP64__ */ return _res; } @@ -1699,7 +1760,9 @@ FSCatalogInfoBitmap whichInfo; FSCatalogInfo catalogInfo; HFSUniStr255 outName; +#ifndef __LP64__ FSSpec fsSpec; +#endif /* !__LP64__ */ FSRef parentRef; if (!PyArg_ParseTuple(_args, "l", &whichInfo)) @@ -1708,14 +1771,26 @@ whichInfo, &catalogInfo, &outName, +#ifndef __LP64__ &fsSpec, +#else + NULL, +#endif /* !__LP64__ */ &parentRef); if (_err != noErr) return PyMac_Error(_err); +#ifndef __LP64__ _res = Py_BuildValue("O&O&O&O&", FSCatalogInfo_New, &catalogInfo, PyMac_BuildHFSUniStr255, &outName, FSSpec_New, &fsSpec, FSRef_New, &parentRef); +#else + _res = Py_BuildValue("O&O&OO&", + FSCatalogInfo_New, &catalogInfo, + PyMac_BuildHFSUniStr255, &outName, + Py_None, + FSRef_New, &parentRef); +#endif /* !__LP64__ */ return _res; } @@ -1784,7 +1859,7 @@ UniCharCount forkNameLength__len__; int forkNameLength__in_len__; SInt8 permissions; - SInt16 forkRefNum; + FSIORefNum forkRefNum; if (!PyArg_ParseTuple(_args, "u#b", &forkNameLength__in__, &forkNameLength__in_len__, &permissions)) @@ -2034,7 +2109,7 @@ /* --------------------- End object type FSRef ---------------------- */ - +#ifndef __LP64__ static PyObject *File_UnmountVol(PyObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -2562,6 +2637,7 @@ FSSpec_New, &spec); return _res; } +#endif /* !__LP64__ */ static PyObject *File_FSGetForkPosition(PyObject *_self, PyObject *_args) { @@ -2785,6 +2861,7 @@ return _res; } +#ifndef __LP64__ static PyObject *File_NewAlias(PyObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -2933,6 +3010,7 @@ wasAliased); return _res; } +#endif /* !__LP64__ */ static PyObject *File_FSNewAlias(PyObject *_self, PyObject *_args) { @@ -3050,6 +3128,7 @@ } static PyMethodDef File_methods[] = { +#ifndef __LP64__ {"UnmountVol", (PyCFunction)File_UnmountVol, 1, PyDoc_STR("(Str63 volName, short vRefNum) -> None")}, {"FlushVol", (PyCFunction)File_FlushVol, 1, @@ -3100,6 +3179,7 @@ PyDoc_STR("(short vRefNum, long dirID, Str255 oldName, long newDirID, Str255 newName) -> None")}, {"FSMakeFSSpec", (PyCFunction)File_FSMakeFSSpec, 1, PyDoc_STR("(short vRefNum, long dirID, Str255 fileName) -> (FSSpec spec)")}, +#endif /* !__LP64__ */ {"FSGetForkPosition", (PyCFunction)File_FSGetForkPosition, 1, PyDoc_STR("(SInt16 forkRefNum) -> (SInt64 position)")}, {"FSSetForkPosition", (PyCFunction)File_FSSetForkPosition, 1, @@ -3124,6 +3204,7 @@ PyDoc_STR("(UInt8 * path, FNMessage message, OptionBits flags) -> None")}, {"FNNotifyAll", (PyCFunction)File_FNNotifyAll, 1, PyDoc_STR("(FNMessage message, OptionBits flags) -> None")}, +#ifndef __LP64__ {"NewAlias", (PyCFunction)File_NewAlias, 1, PyDoc_STR("(FSSpec fromFile, FSSpec target) -> (AliasHandle alias)")}, {"NewAliasMinimalFromFullPath", (PyCFunction)File_NewAliasMinimalFromFullPath, 1, @@ -3136,6 +3217,7 @@ PyDoc_STR("(FSSpec fromFile, FSSpec target, AliasHandle alias) -> (Boolean wasChanged)")}, {"ResolveAliasFileWithMountFlagsNoUI", (PyCFunction)File_ResolveAliasFileWithMountFlagsNoUI, 1, PyDoc_STR("(FSSpec theSpec, Boolean resolveAliasChains, unsigned long mountFlags) -> (FSSpec theSpec, Boolean targetIsFolder, Boolean wasAliased)")}, +#endif /* !__LP64__ */ {"FSNewAlias", (PyCFunction)File_FSNewAlias, 1, PyDoc_STR("(FSRef fromFile, FSRef target) -> (AliasHandle inAlias)")}, {"FSResolveAliasFileWithMountFlags", (PyCFunction)File_FSResolveAliasFileWithMountFlags, 1, @@ -3150,7 +3232,7 @@ }; - +#ifndef __LP64__ int PyMac_GetFSSpec(PyObject *v, FSSpec *spec) { @@ -3188,12 +3270,15 @@ } return 0; } +#endif /* !__LP64__ */ int PyMac_GetFSRef(PyObject *v, FSRef *fsr) { OSStatus err; +#ifndef __LP64__ FSSpec fss; +#endif /* !__LP64__ */ if (FSRef_Check(v)) { *fsr = ((FSRefObject *)v)->ob_itself; @@ -3211,6 +3296,7 @@ return !err; } /* XXXX Should try unicode here too */ +#ifndef __LP64__ /* Otherwise we try to go via an FSSpec */ if (FSSpec_Check(v)) { fss = ((FSSpecObject *)v)->ob_itself; @@ -3219,15 +3305,18 @@ PyMac_Error(err); return 0; } +#endif /* !__LP64__ */ PyErr_SetString(PyExc_TypeError, "FSRef, FSSpec or pathname required"); return 0; } +#ifndef __LP64__ extern PyObject * PyMac_BuildFSSpec(FSSpec *spec) { return FSSpec_New(spec); } +#endif /* !__LP64__ */ extern PyObject * PyMac_BuildFSRef(FSRef *spec) @@ -3242,10 +3331,11 @@ PyObject *d; - +#ifndef __LP64__ PyMac_INIT_TOOLBOX_OBJECT_NEW(FSSpec *, PyMac_BuildFSSpec); - PyMac_INIT_TOOLBOX_OBJECT_NEW(FSRef *, PyMac_BuildFSRef); PyMac_INIT_TOOLBOX_OBJECT_CONVERT(FSSpec, PyMac_GetFSSpec); +#endif /* !__LP64__ */ + PyMac_INIT_TOOLBOX_OBJECT_NEW(FSRef *, PyMac_BuildFSRef); PyMac_INIT_TOOLBOX_OBJECT_CONVERT(FSRef, PyMac_GetFSRef); @@ -3262,6 +3352,7 @@ /* Backward-compatible name */ Py_INCREF(&FSCatalogInfo_Type); PyModule_AddObject(m, "FSCatalogInfoType", (PyObject *)&FSCatalogInfo_Type); +#ifndef __LP64__ FInfo_Type.ob_type = &PyType_Type; if (PyType_Ready(&FInfo_Type) < 0) return; Py_INCREF(&FInfo_Type); @@ -3269,6 +3360,7 @@ /* Backward-compatible name */ Py_INCREF(&FInfo_Type); PyModule_AddObject(m, "FInfoType", (PyObject *)&FInfo_Type); +#endif /* !__LP64__ */ Alias_Type.ob_type = &PyType_Type; if (PyType_Ready(&Alias_Type) < 0) return; Py_INCREF(&Alias_Type); @@ -3276,6 +3368,7 @@ /* Backward-compatible name */ Py_INCREF(&Alias_Type); PyModule_AddObject(m, "AliasType", (PyObject *)&Alias_Type); +#ifndef __LP64__ FSSpec_Type.ob_type = &PyType_Type; if (PyType_Ready(&FSSpec_Type) < 0) return; Py_INCREF(&FSSpec_Type); @@ -3283,6 +3376,7 @@ /* Backward-compatible name */ Py_INCREF(&FSSpec_Type); PyModule_AddObject(m, "FSSpecType", (PyObject *)&FSSpec_Type); +#endif /* !__LP64__ */ FSRef_Type.ob_type = &PyType_Type; if (PyType_Ready(&FSRef_Type) < 0) return; Py_INCREF(&FSRef_Type); Index: Lib/plat-mac/macresource.py =================================================================== --- Lib/plat-mac/macresource.py (revision 74680) +++ Lib/plat-mac/macresource.py (revision 74681) @@ -79,8 +79,8 @@ AppleSingle file""" try: refno = Res.FSpOpenResFile(pathname, 1) - except Res.Error, arg: - if arg[0] in (-37, -39): + except (AttributeError, Res.Error), arg: + if isinstance(arg, AttributeError) or arg[0] in (-37, -39): # No resource fork. We may be on OSX, and this may be either # a data-fork based resource file or a AppleSingle file # from the CVS repository. @@ -106,8 +106,8 @@ try: refno = Res.FSpOpenResFile(pathname, 1) Res.CloseResFile(refno) - except Res.Error, arg: - if arg[0] in (-37, -39): + except (AttributeError, Res.Error), arg: + if isinstance(arg, AttributeError) or arg[0] in (-37, -39): # No resource fork. We may be on OSX, and this may be either # a data-fork based resource file or a AppleSingle file # from the CVS repository. Index: Lib/plat-mac/applesingle.py =================================================================== --- Lib/plat-mac/applesingle.py (revision 74680) +++ Lib/plat-mac/applesingle.py (revision 74681) @@ -119,8 +119,13 @@ if not hasattr(infile, 'read'): if isinstance(infile, Carbon.File.Alias): infile = infile.ResolveAlias()[0] - if isinstance(infile, (Carbon.File.FSSpec, Carbon.File.FSRef)): - infile = infile.as_pathname() + + if hasattr(Carbon.File, "FSSpec"): + if isinstance(infile, (Carbon.File.FSSpec, Carbon.File.FSRef)): + infile = infile.as_pathname() + else: + if isinstance(infile, Carbon.File.FSRef): + infile = infile.as_pathname() infile = open(infile, 'rb') asfile = AppleSingle(infile, verbose=verbose) Index: Mac/scripts/BuildApplet.py =================================================================== --- Mac/scripts/BuildApplet.py (revision 74680) +++ Mac/scripts/BuildApplet.py (revision 74681) @@ -12,7 +12,10 @@ import os import MacOS -import EasyDialogs +try: + import EasyDialogs +except ImportError: + EasyDialogs = None import buildtools import getopt @@ -32,7 +35,10 @@ try: buildapplet() except buildtools.BuildError, detail: - EasyDialogs.Message(detail) + if EasyDialogs is None: + print detail + else: + EasyDialogs.Message(detail) def buildapplet(): @@ -46,6 +52,10 @@ # Ask for source text if not specified in sys.argv[1:] if not sys.argv[1:]: + if EasyDialogs is None: + usage() + sys.exit(1) + filename = EasyDialogs.AskFileForOpen(message='Select Python source or applet:', typeList=('TEXT', 'APPL')) if not filename: Index: Lib/plat-mac/buildtools.py =================================================================== --- Lib/plat-mac/buildtools.py (revision 74680) +++ Lib/plat-mac/buildtools.py (revision 74681) @@ -15,7 +15,10 @@ import MacOS import macostools import macresource -import EasyDialogs +try: + import EasyDialogs +except ImportError: + EasyDialogs = None import shutil @@ -67,9 +70,13 @@ rsrcname=None, others=[], raw=0, progress="default", destroot=""): if progress == "default": - progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120) - progress.label("Compiling...") - progress.inc(0) + if EasyDialogs is None: + print "Compiling %s"%(os.path.split(filename)[1],) + process = None + else: + progress = EasyDialogs.ProgressBar("Processing %s..."%os.path.split(filename)[1], 120) + progress.label("Compiling...") + progress.inc(0) # check for the script name being longer than 32 chars. This may trigger a bug # on OSX that can destroy your sourcefile. if '#' in os.path.split(filename)[1]: @@ -119,7 +126,11 @@ if MacOS.runtimemodel == 'macho': raise BuildError, "No updating yet for MachO applets" if progress: - progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120) + if EasyDialogs is None: + print "Updating %s"%(os.path.split(filename)[1],) + progress = None + else: + progress = EasyDialogs.ProgressBar("Updating %s..."%os.path.split(filename)[1], 120) else: progress = None if not output: PKYE1((2pythonz/patches/osx/python25/patch-Lib-cgi.py.diff--- Lib/cgi.py.orig 2006-08-10 19:41:07.000000000 +0200 +++ Lib/cgi.py 2007-08-21 15:36:54.000000000 +0200 @@ -1,13 +1,6 @@ -#! /usr/local/bin/python +#! __PREFIX__/bin/python2.5 -# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is -# intentionally NOT "/usr/bin/env python". On many systems -# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI -# scripts, and /usr/local/bin is the default directory where Python is -# installed, so /usr/bin/env would be unable to find python. Granted, -# binary installations by Linux vendors often install Python in -# /usr/bin. So let those vendors patch cgi.py to match their choice -# of installation. +# NOTE: /usr/local/bin/python patched for MacPorts installation """Support module for CGI (Common Gateway Interface) scripts. PKYE7=pythonz/patches/osx/python25/patch-Lib-distutils-dist.py.diff--- Lib/distutils/dist.py.orig 2005-03-23 11:54:36.000000000 -0700 +++ Lib/distutils/dist.py 2008-07-25 21:27:15.000000000 -0600 @@ -57,6 +57,7 @@ ('quiet', 'q', "run quietly (turns verbosity off)"), ('dry-run', 'n', "don't actually do anything"), ('help', 'h', "show detailed help message"), + ('no-user-cfg', None,'ignore pydistutils.cfg in your home directory'), ] # 'common_usage' is a short (2-3 line) string describing the common @@ -264,6 +265,12 @@ else: sys.stderr.write(msg + "\n") + # no-user-cfg is handled before other command line args + # because other args override the config files, and this + # one is needed before we can load the config files. + # If attrs['script_args'] wasn't passed, assume false. + self.want_user_cfg = '--no-user-cfg' not in (self.script_args or []) + self.finalize_options() # __init__ () @@ -324,6 +331,9 @@ Distutils __inst__.py file lives), a file in the user's home directory named .pydistutils.cfg on Unix and pydistutils.cfg on Windows/Mac, and setup.cfg in the current directory. + + The file in the user's home directory can be disabled with the + --no-user-cfg option. """ files = [] check_environ() @@ -343,7 +353,7 @@ user_filename = "pydistutils.cfg" # And look for the user config file - if os.environ.has_key('HOME'): + if self.want_user_cfg and os.environ.has_key('HOME'): user_file = os.path.join(os.environ.get('HOME'), user_filename) if os.path.isfile(user_file): files.append(user_file) @@ -353,6 +363,8 @@ if os.path.isfile(local_file): files.append(local_file) + if DEBUG: + print "using config files: %s" % ', '.join(files) return files # find_config_files () PKYEQ<7pythonz/patches/osx/python25/patch-Makefile.pre.in.diff--- Makefile.pre.in.orig 2007-12-05 13:43:57.000000000 -0700 +++ Makefile.pre.in 2008-07-25 21:41:02.000000000 -0600 @@ -348,8 +348,8 @@ # Build the shared modules sharedmods: $(BUILDPYTHON) case $$MAKEFLAGS in \ - *-s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q build;; \ - *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py build;; \ + *-s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q --no-user-cfg build;; \ + *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py --no-user-cfg build;; \ esac # Build static library @@ -894,7 +904,7 @@ # Install the dynamically loadable modules # This goes into $(exec_prefix) sharedinstall: - $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py install \ + $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py --no-user-cfg install \ --prefix=$(prefix) \ --install-scripts=$(BINDIR) \ --install-platlib=$(DESTSHARED) \ @@ -968,7 +978,7 @@ # This installs a few of the useful scripts in Tools/scripts scriptsinstall: SRCDIR=$(srcdir) $(RUNSHARED) \ - ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/setup.py install \ + ./$(BUILDPYTHON) $(srcdir)/Tools/scripts/setup.py --no-user-cfg install \ --prefix=$(prefix) \ --install-scripts=$(BINDIR) \ --root=/$(DESTDIR) PKYEӭ;pythonz/patches/osx/python25/patch-configure-arch_only.diff--- configure.orig 2009-06-24 13:57:38.000000000 -0700 +++ configure 2009-06-24 13:58:38.000000000 -0700 @@ -11362,7 +11362,7 @@ if test "${enable_universalsdk}"; then : else - LIBTOOL_CRUFT="${LIBTOOL_CRUFT} -arch_only `arch`" + LIBTOOL_CRUFT="${LIBTOOL_CRUFT}" fi LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; @@ -11374,7 +11374,7 @@ else LIBTOOL_CRUFT="" fi - LIBTOOL_CRUFT=$LIBTOOL_CRUFT" -lSystem -lSystemStubs -arch_only `arch`" + LIBTOOL_CRUFT=$LIBTOOL_CRUFT" -lSystem -lSystemStubs" LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -install_name $(PYTHONFRAMEWORKINSTALLDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK)' LIBTOOL_CRUFT=$LIBTOOL_CRUFT' -compatibility_version $(VERSION) -current_version $(VERSION)';; esac PKYE;pythonz/patches/osx/python25/patch-configure-badcflags.diff--- configure.orig 2008-10-15 18:00:59.000000000 -0700 +++ configure 2008-10-15 18:02:47.000000000 -0700 @@ -4538,7 +4538,7 @@ ;; # is there any other compiler on Darwin besides gcc? Darwin*) - BASECFLAGS="$BASECFLAGS -Wno-long-double -no-cpp-precomp -mno-fused-madd" + BASECFLAGS="$BASECFLAGS -mno-fused-madd" if test "${enable_universalsdk}"; then BASECFLAGS="-arch ppc -arch i386 -isysroot ${UNIVERSALSDK} ${BASECFLAGS}" fi PKYE<'**7pythonz/patches/osx/python25/patch-gestaltmodule.c.diff*** Mac/Modules/gestaltmodule.c 2010-11-21 14:34:58.000000000 +0900 --- Mac/Modules/gestaltmodule.c.new 2010-11-21 14:38:30.000000000 +0900 *************** *** 34,40 **** { OSErr iErr; OSType selector; ! long response; if (!PyArg_ParseTuple(args, "O&", PyMac_GetOSType, &selector)) return NULL; iErr = Gestalt ( selector, &response ); --- 34,40 ---- { OSErr iErr; OSType selector; ! SInt32 response; if (!PyArg_ParseTuple(args, "O&", PyMac_GetOSType, &selector)) return NULL; iErr = Gestalt ( selector, &response ); PKYE-5pythonz/patches/osx/python25/patch-pyconfig.h.in.diff--- pyconfig.h.in.orig 2009-08-16 10:22:50.000000000 -0700 +++ pyconfig.h.in 2009-08-16 10:23:24.000000000 -0700 @@ -4,6 +4,10 @@ #ifndef Py_PYCONFIG_H #define Py_PYCONFIG_H +// Required on Darwin 10+ +#ifndef _DARWIN_C_SOURCE +#define _DARWIN_C_SOURCE +#endif /* Define for AIX if your compiler is a genuine IBM xlC/xlC_r and you want support for AIX C++ shared extension modules. */ PKYE 3pythonz/patches/osx/python25/patch250-setup.py.diff--- setup.py.orig 2008-10-16 12:58:19.000000000 -0600 +++ setup.py 2009-06-07 20:55:17.000000000 -0600 @@ -609,7 +609,7 @@ # a release. Most open source OSes come with one or more # versions of BerkeleyDB already installed. - max_db_ver = (4, 4) + max_db_ver = (4, 6) min_db_ver = (3, 3) db_setup_debug = False # verbose debug prints from this script? @@ -636,6 +636,7 @@ db_inc_paths.append('/usr/local/include/db4%d' % x) db_inc_paths.append('/pkg/db-4.%d/include' % x) db_inc_paths.append('/opt/db-4.%d/include' % x) + db_inc_paths.append('__PREFIX__/include/db4%d' % x) # 3.x minor number specific paths for x in (3,): db_inc_paths.append('/usr/include/db3%d' % x) @@ -711,6 +712,7 @@ # check lib directories parallel to the location of the header db_dirs_to_check = [ + os.path.join('__PREFIX__', 'lib', 'db46'), os.path.join(db_incdir, '..', 'lib64'), os.path.join(db_incdir, '..', 'lib'), os.path.join(db_incdir, '..', '..', 'lib64'), @@ -1212,13 +1214,7 @@ def detect_tkinter(self, inc_dirs, lib_dirs): # The _tkinter module. - # Rather than complicate the code below, detecting and building - # AquaTk is a separate method. Only one Tkinter will be built on - # Darwin - either AquaTk, if it is found, or X11 based Tk. platform = self.get_platform() - if (platform == 'darwin' and - self.detect_tkinter_darwin(inc_dirs, lib_dirs)): - return # Assume we haven't found any of the libraries or include files # The versions with dots are used on Unix, and the versions without --- setup.py.orig 2009-09-10 19:41:32.000000000 +1000 +++ setup.py 2009-09-10 19:48:30.000000000 +1000 @@ -1197,7 +1197,7 @@ # For 8.4a2, the X11 headers are not included. Rather than include a # complicated search, this is a hard-coded path. It could bail out # if X11 libs are not found... - include_dirs.append('/usr/X11R6/include') + #include_dirs.append('/usr/X11R6/include') frameworks = ['-framework', 'Tcl', '-framework', 'Tk'] ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'], @@ -1262,17 +1262,17 @@ if platform == 'sunos5': include_dirs.append('/usr/openwin/include') added_lib_dirs.append('/usr/openwin/lib') - elif os.path.exists('/usr/X11R6/include'): - include_dirs.append('/usr/X11R6/include') - added_lib_dirs.append('/usr/X11R6/lib64') - added_lib_dirs.append('/usr/X11R6/lib') - elif os.path.exists('/usr/X11R5/include'): - include_dirs.append('/usr/X11R5/include') - added_lib_dirs.append('/usr/X11R5/lib') - else: + #elif os.path.exists('/usr/X11R6/include'): + # include_dirs.append('/usr/X11R6/include') + # added_lib_dirs.append('/usr/X11R6/lib64') + # added_lib_dirs.append('/usr/X11R6/lib') + #elif os.path.exists('/usr/X11R5/include'): + # include_dirs.append('/usr/X11R5/include') + # added_lib_dirs.append('/usr/X11R5/lib') + #else: # Assume default location for X11 - include_dirs.append('/usr/X11/include') - added_lib_dirs.append('/usr/X11/lib') + # include_dirs.append('/usr/X11/include') + # added_lib_dirs.append('/usr/X11/lib') # If Cygwin, then verify that X is installed before proceeding if platform == 'cygwin': PKYELM3pythonz/patches/osx/python25/patch251-setup.py.diff--- setup.py.orig 2008-10-16 12:58:19.000000000 -0600 +++ setup.py 2009-06-07 20:55:17.000000000 -0600 @@ -609,7 +609,7 @@ # a release. Most open source OSes come with one or more # versions of BerkeleyDB already installed. - max_db_ver = (4, 5) + max_db_ver = (4, 6) min_db_ver = (3, 3) db_setup_debug = False # verbose debug prints from this script? @@ -636,6 +636,7 @@ db_inc_paths.append('/usr/local/include/db4%d' % x) db_inc_paths.append('/pkg/db-4.%d/include' % x) db_inc_paths.append('/opt/db-4.%d/include' % x) + db_inc_paths.append('__PREFIX__/include/db4%d' % x) # 3.x minor number specific paths for x in (3,): db_inc_paths.append('/usr/include/db3%d' % x) @@ -711,6 +712,7 @@ # check lib directories parallel to the location of the header db_dirs_to_check = [ + os.path.join('__PREFIX__', 'lib', 'db46'), os.path.join(db_incdir, '..', 'lib64'), os.path.join(db_incdir, '..', 'lib'), os.path.join(db_incdir, '..', '..', 'lib64'), @@ -1212,13 +1214,7 @@ def detect_tkinter(self, inc_dirs, lib_dirs): # The _tkinter module. - # Rather than complicate the code below, detecting and building - # AquaTk is a separate method. Only one Tkinter will be built on - # Darwin - either AquaTk, if it is found, or X11 based Tk. platform = self.get_platform() - if (platform == 'darwin' and - self.detect_tkinter_darwin(inc_dirs, lib_dirs)): - return # Assume we haven't found any of the libraries or include files # The versions with dots are used on Unix, and the versions without --- setup.py.orig 2009-09-10 19:41:32.000000000 +1000 +++ setup.py 2009-09-10 19:48:30.000000000 +1000 @@ -1197,7 +1197,7 @@ # For 8.4a2, the X11 headers are not included. Rather than include a # complicated search, this is a hard-coded path. It could bail out # if X11 libs are not found... - include_dirs.append('/usr/X11R6/include') + #include_dirs.append('/usr/X11R6/include') frameworks = ['-framework', 'Tcl', '-framework', 'Tk'] ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'], @@ -1262,17 +1262,17 @@ if platform == 'sunos5': include_dirs.append('/usr/openwin/include') added_lib_dirs.append('/usr/openwin/lib') - elif os.path.exists('/usr/X11R6/include'): - include_dirs.append('/usr/X11R6/include') - added_lib_dirs.append('/usr/X11R6/lib64') - added_lib_dirs.append('/usr/X11R6/lib') - elif os.path.exists('/usr/X11R5/include'): - include_dirs.append('/usr/X11R5/include') - added_lib_dirs.append('/usr/X11R5/lib') - else: + #elif os.path.exists('/usr/X11R6/include'): + # include_dirs.append('/usr/X11R6/include') + # added_lib_dirs.append('/usr/X11R6/lib64') + # added_lib_dirs.append('/usr/X11R6/lib') + #elif os.path.exists('/usr/X11R5/include'): + # include_dirs.append('/usr/X11R5/include') + # added_lib_dirs.append('/usr/X11R5/lib') + #else: # Assume default location for X11 - include_dirs.append('/usr/X11/include') - added_lib_dirs.append('/usr/X11/lib') + # include_dirs.append('/usr/X11/include') + # added_lib_dirs.append('/usr/X11/lib') # If Cygwin, then verify that X is installed before proceeding if platform == 'cygwin': PKYEZ3pythonz/patches/osx/python25/patch252-setup.py.diff--- setup.py.orig 2008-10-16 12:58:19.000000000 -0600 +++ setup.py 2009-06-07 20:55:17.000000000 -0600 @@ -609,7 +609,7 @@ # a release. Most open source OSes come with one or more # versions of BerkeleyDB already installed. - max_db_ver = (4, 5) + max_db_ver = (4, 6) # NOTE: while the _bsddb.c code links against BerkeleyDB 4.6.x # we leave that version disabled by default as it has proven to be # quite a buggy library release on many platforms. @@ -636,6 +636,7 @@ db_inc_paths.append('/usr/local/include/db4%d' % x) db_inc_paths.append('/pkg/db-4.%d/include' % x) db_inc_paths.append('/opt/db-4.%d/include' % x) + db_inc_paths.append('__PREFIX__/include/db4%d' % x) # 3.x minor number specific paths for x in (3,): db_inc_paths.append('/usr/include/db3%d' % x) @@ -711,6 +712,7 @@ # check lib directories parallel to the location of the header db_dirs_to_check = [ + os.path.join('__PREFIX__', 'lib', 'db46'), os.path.join(db_incdir, '..', 'lib64'), os.path.join(db_incdir, '..', 'lib'), os.path.join(db_incdir, '..', '..', 'lib64'), @@ -1212,13 +1214,7 @@ def detect_tkinter(self, inc_dirs, lib_dirs): # The _tkinter module. - # Rather than complicate the code below, detecting and building - # AquaTk is a separate method. Only one Tkinter will be built on - # Darwin - either AquaTk, if it is found, or X11 based Tk. platform = self.get_platform() - if (platform == 'darwin' and - self.detect_tkinter_darwin(inc_dirs, lib_dirs)): - return # Assume we haven't found any of the libraries or include files # The versions with dots are used on Unix, and the versions without --- setup.py.orig 2009-09-10 19:41:32.000000000 +1000 +++ setup.py 2009-09-10 19:48:30.000000000 +1000 @@ -1197,7 +1197,7 @@ # For 8.4a2, the X11 headers are not included. Rather than include a # complicated search, this is a hard-coded path. It could bail out # if X11 libs are not found... - include_dirs.append('/usr/X11R6/include') + #include_dirs.append('/usr/X11R6/include') frameworks = ['-framework', 'Tcl', '-framework', 'Tk'] ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'], @@ -1262,17 +1262,17 @@ if platform == 'sunos5': include_dirs.append('/usr/openwin/include') added_lib_dirs.append('/usr/openwin/lib') - elif os.path.exists('/usr/X11R6/include'): - include_dirs.append('/usr/X11R6/include') - added_lib_dirs.append('/usr/X11R6/lib64') - added_lib_dirs.append('/usr/X11R6/lib') - elif os.path.exists('/usr/X11R5/include'): - include_dirs.append('/usr/X11R5/include') - added_lib_dirs.append('/usr/X11R5/lib') - else: + #elif os.path.exists('/usr/X11R6/include'): + # include_dirs.append('/usr/X11R6/include') + # added_lib_dirs.append('/usr/X11R6/lib64') + # added_lib_dirs.append('/usr/X11R6/lib') + #elif os.path.exists('/usr/X11R5/include'): + # include_dirs.append('/usr/X11R5/include') + # added_lib_dirs.append('/usr/X11R5/lib') + #else: # Assume default location for X11 - include_dirs.append('/usr/X11/include') - added_lib_dirs.append('/usr/X11/lib') + # include_dirs.append('/usr/X11/include') + # added_lib_dirs.append('/usr/X11/lib') # If Cygwin, then verify that X is installed before proceeding if platform == 'cygwin': PKYEO/pythonz/patches/osx/python26/_localemodule.c.edg/defined(__APPLE__)/s//0/g w PKYEt2)pythonz/patches/osx/python26/locale.py.edg/'darwin', /s/// w PKYEg~((2pythonz/patches/osx/python26/patch-Lib-cgi.py.diff--- Lib/cgi.py.orig 2006-08-10 19:41:07.000000000 +0200 +++ Lib/cgi.py 2007-08-21 15:36:54.000000000 +0200 @@ -1,13 +1,6 @@ -#! /usr/local/bin/python +#! @@PREFIX@@/bin/python2.6 -# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is -# intentionally NOT "/usr/bin/env python". On many systems -# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI -# scripts, and /usr/local/bin is the default directory where Python is -# installed, so /usr/bin/env would be unable to find python. Granted, -# binary installations by Linux vendors often install Python in -# /usr/bin. So let those vendors patch cgi.py to match their choice -# of installation. +# NOTE: /usr/local/bin/python patched for MacPorts installation """Support module for CGI (Common Gateway Interface) scripts. PKYEX00Cpythonz/patches/osx/python26/patch-Lib-ctypes-macholib-dyld.py.diff--- Lib/ctypes/macholib/dyld.py.orig 2008-02-21 11:52:20.000000000 -0700 +++ Lib/ctypes/macholib/dyld.py 2009-10-11 02:42:21.000000000 -0600 @@ -26,7 +26,7 @@ DEFAULT_LIBRARY_FALLBACK = [ os.path.expanduser("~/lib"), - "/usr/local/lib", + "@@PREFIX@@/lib", "/lib", "/usr/lib", ] PKYE[?=pythonz/patches/osx/python26/patch-Lib-distutils-dist.py.diff--- Lib/distutils/dist.py.orig 2008-09-03 05:13:56.000000000 -0600 +++ Lib/distutils/dist.py 2008-10-03 18:33:47.000000000 -0600 @@ -60,6 +60,7 @@ ('quiet', 'q', "run quietly (turns verbosity off)"), ('dry-run', 'n', "don't actually do anything"), ('help', 'h', "show detailed help message"), + ('no-user-cfg', None,'ignore pydistutils.cfg in your home directory'), ] # 'common_usage' is a short (2-3 line) string describing the common @@ -267,6 +268,12 @@ else: sys.stderr.write(msg + "\n") + # no-user-cfg is handled before other command line args + # because other args override the config files, and this + # one is needed before we can load the config files. + # If attrs['script_args'] wasn't passed, assume false. + self.want_user_cfg = '--no-user-cfg' not in (self.script_args or []) + self.finalize_options() # __init__ () @@ -327,6 +334,9 @@ Distutils __inst__.py file lives), a file in the user's home directory named .pydistutils.cfg on Unix and pydistutils.cfg on Windows/Mac, and setup.cfg in the current directory. + + The file in the user's home directory can be disabled with the + --no-user-cfg option. """ files = [] check_environ() @@ -347,7 +357,7 @@ # And look for the user config file user_file = os.path.join(os.path.expanduser('~'), user_filename) - if os.path.isfile(user_file): + if self.want_user_cfg and os.path.isfile(user_file): files.append(user_file) # All platforms support local setup.cfg @@ -355,6 +365,8 @@ if os.path.isfile(local_file): files.append(local_file) + if DEBUG: + print "using config files: %s" % ', '.join(files) return files # find_config_files () PKYEOj <pythonz/patches/osx/python26/patch-Mac-IDLE-Makefile.in.diff--- Mac/IDLE/Makefile.in.orig 2009-01-02 04:47:17.000000000 -0700 +++ Mac/IDLE/Makefile.in 2009-04-16 00:54:43.000000000 -0600 @@ -22,7 +22,7 @@ BUNDLEBULDER=$(srcdir)/../../Lib/plat-mac/bundlebuilder.py -PYTHONAPPSDIR=/Applications/$(PYTHONFRAMEWORK) $(VERSION) +PYTHONAPPSDIR=@@APPLICATIONS_DIR@@/$(PYTHONFRAMEWORK) $(VERSION) all: IDLE.app @@ -42,7 +42,7 @@ $(srcdir)/../Icons/PythonSource.icns \ $(srcdir)/../Icons/PythonCompiled.icns Info.plist rm -fr IDLE.app - $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(BUNDLEBULDER) \ + PYTHONHOME=$(DESTDIR)$(prefix) $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(BUNDLEBULDER) \ --builddir=. \ --name=IDLE \ --link-exec \ PKYEvӗ7pythonz/patches/osx/python26/patch-Mac-Makefile.in.diff--- Mac/Makefile.in.orig 2009-03-30 13:58:41.000000000 -0600 +++ Mac/Makefile.in 2009-04-16 00:54:26.000000000 -0600 @@ -19,7 +19,7 @@ # These are normally glimpsed from the previous set bindir=$(prefix)/bin -PYTHONAPPSDIR=/Applications/$(PYTHONFRAMEWORK) $(VERSION) +PYTHONAPPSDIR=@@APPLICATIONS_DIR@@/$(PYTHONFRAMEWORK) $(VERSION) APPINSTALLDIR=$(prefix)/Resources/Python.app # Variables for installing the "normal" unix binaries @@ -224,7 +224,7 @@ cd IDLE && make install install_BuildApplet: - $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(srcdir)/scripts/BuildApplet.py \ + PYTHONHOME=$(DESTDIR)$(prefix) $(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(srcdir)/scripts/BuildApplet.py \ --destroot "$(DESTDIR)" \ --python=$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)`test -f "$(DESTDIR)$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)-32" && echo "-32"` \ --output "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app" \ PKYE9ףFpythonz/patches/osx/python26/patch-Mac-PythonLauncher-Makefile.in.diff--- Mac/PythonLauncher/Makefile.in.orig 2009-01-02 04:47:17.000000000 -0700 +++ Mac/PythonLauncher/Makefile.in 2009-04-16 00:55:11.000000000 -0600 @@ -1,3 +1,4 @@ +prefix=@prefix@ CC=@CC@ LD=@CC@ BASECFLAGS=@BASECFLAGS@ @@ -21,7 +22,7 @@ BUNDLEBULDER=$(srcdir)/../../Lib/plat-mac/bundlebuilder.py -PYTHONAPPSDIR=/Applications/$(PYTHONFRAMEWORK) $(VERSION) +PYTHONAPPSDIR=@@APPLICATIONS_DIR@@/$(PYTHONFRAMEWORK) $(VERSION) OBJECTS=FileSettings.o MyAppDelegate.o MyDocument.o PreferencesWindowController.o doscript.o main.o all: Python\ Launcher.app @@ -42,7 +43,7 @@ $(srcdir)/../Icons/PythonCompiled.icns \ $(srcdir)/factorySettings.plist rm -fr "Python Launcher.app" - $(RUNSHARED) $(BUILDPYTHON) $(BUNDLEBULDER) \ + PYTHONHOME=$(DESTDIR)$(prefix) $(RUNSHARED) $(BUILDPYTHON) $(BUNDLEBULDER) \ --builddir=. \ --name="Python Launcher" \ --executable="Python Launcher" \ PKYEU0T>pythonz/patches/osx/python26/patch-Mac-Tools-Doc-setup.py.diff--- Mac/Tools/Doc/setup.py.diff 2008-03-29 09:24:25.000000000 -0600 +++ Mac/Tools/Doc/setup.py 2008-10-04 19:53:40.000000000 -0600 @@ -30,7 +30,7 @@ MAJOR_VERSION='2.4' MINOR_VERSION='2.4.1' -DESTDIR='/Applications/MacPython-%s/PythonIDE.app/Contents/Resources/English.lproj/PythonDocumentation' % MAJOR_VERSION +DESTDIR='@@APPLICATIONS_DIR@@/MacPython-%s/PythonIDE.app/Contents/Resources/English.lproj/PythonDocumentation' % MAJOR_VERSION class DocBuild(build): def initialize_options(self): PKYE5pythonz/patches/osx/python26/patch-setup.py-db46.diff--- setup.py.orig 2010-10-19 22:33:25.000000000 +0200 +++ setup.py 2010-10-19 22:33:54.000000000 +0200 @@ -799,7 +799,7 @@ # BerkeleyDB 4.6.x is not stable on many architectures. arch = platform_machine() if arch not in ('i386', 'i486', 'i586', 'i686', - 'x86_64', 'ia64'): + 'x86_64', 'ia64', 'Power Macintosh'): return False return True PKYEP;pythonz/patches/osx/python26/patch-setup_no_tkinter.py.diff--- setup.py.orig 2009-03-31 12:20:48.000000000 -0600 +++ setup.py 2009-09-17 00:33:12.000000000 -0600 @@ -17,7 +17,7 @@ from distutils.command.install_lib import install_lib # This global variable is used to hold the list of modules to be disabled. -disabled_module_list = [] +disabled_module_list = ["_tkinter"] def add_dir_to_list(dirlist, dir): """Add the directory 'dir' to the list 'dirlist' (at the front) if PKYE^ee;pythonz/patches/osx/python27/patch-Modules-posixmodule.diff--- Modules/posixmodule.c.orig 2011-05-28 16:57:40.000000000 -0400 +++ Modules/posixmodule.c 2011-05-28 16:56:40.000000000 -0400 @@ -455,7 +455,7 @@ #endif /* Return a dictionary corresponding to the POSIX environment table */ -#ifdef WITH_NEXT_FRAMEWORK +#ifdef __APPLE__ /* On Darwin/MacOSX a shared library or framework has no access to ** environ directly, we must obtain it with _NSGetEnviron(). */ @@ -477,7 +477,7 @@ d = PyDict_New(); if (d == NULL) return NULL; -#ifdef WITH_NEXT_FRAMEWORK +#ifdef __APPLE__ if (environ == NULL) environ = *_NSGetEnviron(); #endif PKYE? EE3pythonz/patches/osx/python27/python-276-dtrace.diff--- Doc/library/debug.rst +++ Doc/library/debug.rst @@ -14,4 +14,5 @@ profile.rst hotshot.rst timeit.rst - trace.rst \ No newline at end of file + trace.rst + dtrace.rst --- /dev/null +++ Doc/library/dtrace.rst @@ -0,0 +1,183 @@ +:mod:`dtrace` --- DTrace probes for Python +=============================================== + +.. module:: dtrace + :synopsis: DTrace probes for Python. + +**Source code:** :source:`Lib/dtrace.py` + +-------------- + +The :mod:`dtrace` module indicates if the CPython executable currently +running has been compiled with DTrace probes support. + +.. impl-detail:: + + DTrace probes are implementation details of the CPython interpreter! + No garantees are made about probe compatibility between versions of + CPython. DTrace scripts can stop working or work incorrectly without + warning when changing CPython versions. + +The :mod:`dtrace` module defines the following variable: + + +.. data:: available + + The variable will be ``True`` if the current CPython interpreter was + compiled with DTrace probe support. ``False`` if not. + + +DTrace probes +------------- + +DTrace scripts are run externally to CPython. DTrace probes export +selected events inside CPython interpreter in order to make them +accessible to external scripts. + +The probes are exported through the "python" provider. The available +probes are defined in the file :file:`Include/pydtrace.d`. + +To learn how to use DTrace, read `DTrace User Guide +`_. + +.. opcode:: function-entry (arg0, arg1, arg2) + + Fires when python code enters a new function. *arg0* is sourcecode + file path, *arg1* is the name of the funcion called, and *arg2* is + line number. + + The probe is not fired if Python code calls C functions. + +.. opcode:: function-return (arg0, arg1, arg2) + + Fires when Python code finishes execution of a function. Parameters + are the same as in ``function-entry``. + + The probe is not fired if the finishing function is written in C. + +.. opcode:: line (arg0, arg1, arg2) + + Fires when Python code changes the execution line. Parameters are the + same as in ``function-entry``. + + The probe is not fired in C functions. + +.. opcode:: gc-start (arg0) + + Fires when the Python interpreter starts a garbage collection cycle. + *arg0* is the generation to scan, like :func:`gc.collect()`. + +.. opcode:: gc-done (arg0) + + Fires when the Python interpreter finishes a garbage collection + cycle. *arg0* is the number of collected objects. + +.. opcode:: instance-new-start (arg0, arg1) + + Fires when an object instanciation starts. *arg0* is the class name, + *arg1* is the filename where the class is defined. + + The probe is not fired for most C code object creations. + +.. opcode:: instance-new-done (arg0, arg1) + + Fires when an object instanciation finishes. Parameters are the same + as in ``instance-new-done``. + + The probe is not fired for most C code object creations. + +.. opcode:: instance-delete-start (arg0, arg1) + + Fires when an object instance is going to be destroyed. Parameters + are the same as in ``instance-new-done``. + + The probe is not fired for most C code object destructions. + +.. opcode:: instance-delete-done (arg0, arg1) + + Fires when an object instance has been destroyed. parameters are the + same as in ``instance-new-done``. + + Between an ``instance-delete-start`` and corresponding + ``instance-delete-done`` others probes can fire if, for instance, + deletion of an instance creates a deletion cascade. + + The probe is not fired for most C code object destructions. + + +Python stack +------------ + +When a DTrace probe is fired, the DTrace script can examine the stack. +Since CPython is a Python interpreter coded in C, the stack will show C +functions, with no direct relation to the Python code currently being +executed. + +Using the special "jstack()" DTrace function, the user will be given +hints about the python program stack, if possible. In particular, the +augmented stack will show python function calls, filename, name +of the function or method, and the line number. + +DTrace scripts examples +----------------------- + +DTrace python provider is suffixed by the pid of the process to monitor. +In the examples, the pid will be 9876. + +Show the time spent doing garbage collection (in nanoseconds):: + + python9876:::gc-start + { + self->t = timestamp; + } + + python9876:::gc-done + /self->t/ + { + printf("%d", timestamp-self->t); + self->t = 0; + } + +Count how many instances are created of each class:: + + python9876:::instance-new-start + { + @v[copyinstr(arg1), copyinstr(arg0)] = count(); + } + +Observe time spent in object destruction, useful if datastructures are +complicated and deletion of an object can create a cascade effect:: + + python9876:::instance-delete-start + /self->t==0/ + { + self->t = timestamp; + self->level = 0; + } + + python9876:::instance-delete-start + /self->t/ + { + self->level += 1; + } + + python9876:::instance-delete-done + /(self->level) && (self->t)/ + { + self->level -= 1; + } + + python9876:::instance-delete-done + /(self->level==0) && (self->t)/ + { + @time = quantize(timestamp-self->t); + self->t = 0; + } + +To know which python source code lines create new TCP/IP connections:: + + pid9876::sock_connect:entry + { + @conn[jstack()] = count(); + } + --- Include/code.h +++ Include/code.h @@ -6,6 +6,8 @@ extern "C" { #endif +#include "pyconfig.h" + /* Bytecode object */ typedef struct { PyObject_HEAD @@ -25,6 +27,9 @@ int co_firstlineno; /* first source line number */ PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See Objects/lnotab_notes.txt for details. */ +#ifdef WITH_DTRACE + unsigned short *co_linenos; /* dtrace stack helper */ +#endif void *co_zombieframe; /* for optimization only (see frameobject.c) */ PyObject *co_weakreflist; /* to support weakrefs to code objects */ } PyCodeObject; --- /dev/null +++ Include/pydtrace.d @@ -0,0 +1,157 @@ +provider python { + probe function__entry(const char *, const char *, int); + probe function__return(const char *, const char *, int); + probe instance__new__start(const char *, const char *); + probe instance__new__done(const char *, const char *); + probe instance__delete__start(const char *, const char *); + probe instance__delete__done(const char *, const char *); + probe line(const char *, const char *, int); + probe gc__start(int); + probe gc__done(long); +}; + +#pragma D attributes Evolving/Evolving/Common provider python provider +#pragma D attributes Private/Private/Common provider python module +#pragma D attributes Private/Private/Common provider python function +#pragma D attributes Evolving/Evolving/Common provider python name +#pragma D attributes Evolving/Evolving/Common provider python args + + + +#ifdef PYDTRACE_STACK_HELPER +/* + * Python ustack helper. This relies on the first argument (PyFrame *) being + * on the stack; see Python/ceval.c for the contortions we go through to ensure + * this is the case. + * + * On x86, the PyFrame * is two slots up from the frame pointer; on SPARC, it's + * eight. + * + * Some details about this in "Python and DTrace in build 65": + * http://blogs.oracle.com/levon/entry/python_and_dtrace_in_build + */ + +/* + * Yes, this is as gross as it looks. DTrace cannot handle static functions, + * and our stat_impl.h has them in ILP32. + */ +#define _SYS_STAT_H + +/* +** When compiling in 32 bits: +** - Early inclusion to avoid problems with +** _FILE_OFFSET_BITS redefined. +** - Also, we must "undef" _POSIX_PTHREAD_SEMANTICS +** to avoid error compiling this source. +*/ +#include "pyconfig.h" +#undef _POSIX_PTHREAD_SEMANTICS + +#include +#include + +#include "pyport.h" +#include "object.h" +#include "pystate.h" +#include "pyarena.h" +#include "pythonrun.h" +#include "compile.h" +#include "frameobject.h" +#include "stringobject.h" + +#include "pydtrace_offsets.h" + +#if defined(__i386) +#define startframe PyEval_EvalFrameEx +#define endframe AFTER_PyEval_EvalFrameEx +#elif defined(__amd64) +#define startframe PyEval_EvalFrameExReal +#define endframe AFTER_PyEval_EvalFrameExReal +#elif defined(__sparc) +#define startframe PyEval_EvalFrameExReal +#define endframe AFTER_PyEval_EvalFrameExReal +#endif + +#ifdef __sparcv9 +#define STACK_BIAS (2048-1) +#else +#define STACK_BIAS 0 +#endif + +#define at_evalframe(addr) \ + ((uintptr_t)addr >= ((uintptr_t)&``startframe) && \ + (uintptr_t)addr < ((uintptr_t)&``endframe)) +#define probe dtrace:helper:ustack: +#define print_result(r) (r) + +#if defined(__i386) || defined(__amd64) +#define frame_ptr_addr ((uintptr_t)arg1 + sizeof(uintptr_t) * 2) +#elif defined(__sparc) +#define frame_ptr_addr ((uintptr_t)arg1 + STACK_BIAS + sizeof(uintptr_t) * 8) +#else +#error unknown architecture +#endif + +/* startframe and endframe are macro-expansions */ +extern uintptr_t startframe; +extern uintptr_t endframe; + +#define copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)(addr), sizeof(obj))) +#define pystr_addr(addr) ((char *)addr + offsetof(PyStringObject, ob_sval)) +#define copyin_str(dest, addr, obj) \ + (copyinto((uintptr_t)pystr_addr(addr), obj->ob_size, (dest))) +#define add_str(addr, obj) \ + copyin_str(this->result + this->pos, addr, obj); \ + this->pos += obj->ob_size; \ + this->result[this->pos] = '\0'; +#define add_digit(nr, div) ((nr / div) ? \ + (this->result[this->pos++] = '0' + ((nr / div) % 10)) : \ + (this->result[this->pos] = '\0')) +#define add_char(c) (this->result[this->pos++] = c) + +probe /at_evalframe(arg0)/ +{ + this->framep = *(uintptr_t *)copyin(frame_ptr_addr, sizeof(uintptr_t)); + this->frameo = copyin_obj(this->framep, PyFrameObject); + this->codep = this->frameo->f_code; + this->codeo = copyin_obj(this->codep, PyCodeObject); + /* If we just enter a function, show the definition line */ + this->lineno = this->codeo->co_firstlineno + + (this->frameo->f_lasti == -1 ? 0 : + *copyin_obj(this->codeo->co_linenos + this->frameo->f_lasti, + unsigned short)); + this->filenamep = this->codeo->co_filename; + this->fnamep = this->codeo->co_name; + this->filenameo = copyin_obj(this->filenamep, PyStringObject); + this->fnameo = copyin_obj(this->fnamep, PyStringObject); + + this->len = 1 + this->filenameo->ob_size + 1 + 5 + 2 + + this->fnameo->ob_size + 1 + 1; + + this->result = (char *)alloca(this->len); + this->pos = 0; + + add_char('@'); + add_str(this->filenamep, this->filenameo); + add_char(':'); + add_digit(this->lineno, 10000); + add_digit(this->lineno, 1000); + add_digit(this->lineno, 100); + add_digit(this->lineno, 10); + add_digit(this->lineno, 1); + add_char(' '); + add_char('('); + add_str(this->fnamep, this->fnameo); + add_char(')'); + this->result[this->pos] = '\0'; + + print_result(stringof(this->result)); +} + +probe /!at_evalframe(arg0)/ +{ + NULL; +} + +#endif /* PYDTRACE_STACK_HELPER */ + --- /dev/null +++ Include/pydtrace_offsets.c @@ -0,0 +1,21 @@ +#include +#include + +int main(int argc, const char* argv[]) { + if (argc != 3) { + printf("Parameter number incorrect\n"); + exit(1); + } + + printf("/* File autogenerated. DO NOT MODIFY MANUALLY */\n"); + printf("\n"); + printf("#ifndef PYDTRACE_OFFSETS_H\n"); + printf("#define PYDTRACE_OFFSETS_H\n"); + printf("\n"); + printf("#define AFTER_PyEval_EvalFrameEx %s\n", argv[1]); + printf("#define AFTER_PyEval_EvalFrameExReal %s\n", argv[2]); + printf("\n"); + printf("#endif\n"); + return 0; +} + --- /dev/null +++ Include/pydtrace_offsets.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +DTRACE_NM=$1 +CEVAL_O=$2 +PYDTRACE_OFFSETS=$3 +if test "$DTRACE_NM" = "OTHER" ; then + $PYDTRACE_OFFSETS \ + "`nm -n $CEVAL_O | grep \" T \" | \ + sed -n \"/ T PyEval_EvalFrameEx$/{n;p;}\" | \ + sed \"s/.* T \(.*\)$/\1/\"`" \ + "`nm -n $CEVAL_O | grep \" T \" | \ + sed -n \"/ T PyEval_EvalFrameExReal$/{n;p;}\" | \ + sed \"s/.* T \(.*\)$/\1/\"`" +fi +if test "$DTRACE_NM" = "SOLARIS" ; then + $PYDTRACE_OFFSETS \ + "`/usr/ccs/bin/nm -n $CEVAL_O | \ + /usr/bin/grep \"\\|FUNC \\|\" | \ + /usr/bin/grep -v \"\\|IGNORE \\|\" | \ + /usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \ + sed -n \"/ PyEval_EvalFrameEx$/{n;p;}\" | \ + sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`" \ + "`/usr/ccs/bin/nm -n $CEVAL_O | \ + /usr/bin/grep \"\\|FUNC \\|\" | \ + /usr/bin/grep -v \"\\|IGNORE \\|\" | \ + /usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \ + sed -n \"/ PyEval_EvalFrameExReal$/{n;p;}\" | \ + sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`" +fi + --- /dev/null +++ Lib/test/dtrace_sample.py @@ -0,0 +1,73 @@ +# Sample script for use by test_dtrace.py +# DO NOT MODIFY THIS FILE IN ANY WAY WITHOUT UPDATING test_dtrace.py!!!!! + +import gc + +def function_1() : + pass + +# Check stacktrace +def function_2() : + function_1() + +# CALL_FUNCTION_VAR +def function_3(dummy, dummy2) : + pass + +# CALL_FUNCTION_KW +def function_4(**dummy) : + pass + +# CALL_FUNCTION_VAR_KW +def function_5(dummy, dummy2, **dummy3) : + pass + +def test_entry_return_and_stack() : + function_1() + function_2() + function_3(*(1,2)) + function_4(**{"test":42}) + function_5(*(1,2), **{"test":42}) + +def test_line() : + a = 1 # Preamble + for i in xrange(2) : + a = i + b = i+2 + c = i+3 + d = a + b +c + a = 1 # Epilogue + +def test_instance_creation_destruction() : + class old_style_class() : + pass + class new_style_class(object) : + pass + + a = old_style_class() + del a + gc.collect() + b = new_style_class() + del b + gc.collect() + + a = old_style_class() + del old_style_class + gc.collect() + b = new_style_class() + del new_style_class + gc.collect() + del a + gc.collect() + del b + gc.collect() + +def test_garbage_collection() : + gc.collect() + +if __name__ == "__main__": + test_entry_return_and_stack() + test_line() + test_instance_creation_destruction() + test_garbage_collection() + --- /dev/null +++ Lib/test/test_dtrace.py @@ -0,0 +1,344 @@ +import sys, unittest, subprocess, os.path, dis, types, re +import dtrace +from test.test_support import TESTFN, run_unittest, findfile + +sample = os.path.abspath(findfile("dtrace_sample.py")) +if not dtrace.available : + raise unittest.SkipTest, "dtrace support not compiled in" + +def normalize(data) : + # DTRACE keeps a per-CPU buffer, and when showing the fired probes, + # buffers are concatenated. So if the operating system moves our + # thread around, the straight result can be "non causal". + # So we add timestamps to the probe firing, and sort by that field. + + # When compiling with '--with-pydebug' + data = "".join(re.split("\[[0-9]+ refs\]", data)) + + try : + result = [i.split("\t") \ + for i in data.replace("\r", "").split("\n") if len(i)] + result.sort(key = lambda i: int(i[0])) + result = "".join((i[1] for i in result)) + result = result.replace(" ", "") + except : + # If something goes wrong, rebuild the value so we can see the + # real result when the assert fails. + result = data.replace("\r", "").replace("\n", "") + return result + +dscript = """ +pid$target::PyEval_EvalCode:entry +""" +dscript = dscript.replace("\r", "").replace("\n", "") +result, _ = subprocess.Popen(["dtrace", "-q", "-l", "-n", dscript, + "-c", "%s %s" %(sys.executable, sample)], stdout=subprocess.PIPE, + stderr=subprocess.STDOUT).communicate() +if result.split("\n")[1].split()[-2:] != ["PyEval_EvalCode", "entry"] : + result2 = repr(result) + raise unittest.SkipTest("dtrace seems not to be working. " + \ + "Please, check your privileges. " + + "Result: " +result2) + +class DTraceTestsNormal(unittest.TestCase) : + def setUp(self) : + self.optimize = False + + def test_function_entry_return(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry,python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **function-entry*%(path)s*test_entry_return_and_stack*25 + **function-entry*%(path)s*function_1*6 + **function-return*%(path)s*function_1*7 + **function-entry*%(path)s*function_2*10 + **function-entry*%(path)s*function_1*6 + **function-return*%(path)s*function_1*7 + **function-return*%(path)s*function_2*11 + **function-entry*%(path)s*function_3*14 + **function-return*%(path)s*function_3*15 + **function-entry*%(path)s*function_4*18 + **function-return*%(path)s*function_4*19 + **function-entry*%(path)s*function_5*22 + **function-return*%(path)s*function_5*23 + **function-return*%(path)s*test_entry_return_and_stack*30 + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + @unittest.skipIf(sys.platform == 'darwin', + "MacOS X doesn't support jstack()") + def test_stack(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("[x]"); + jstack(); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + [x] + [%(path)s:25(test_entry_return_and_stack)] + [x] + [%(path)s:6(function_1)] + [%(path)s:26(test_entry_return_and_stack)] + [x] + [%(path)s:10(function_2)] + [%(path)s:27(test_entry_return_and_stack)] + [x] + [%(path)s:6(function_1)] + [%(path)s:11(function_2)] + [%(path)s:27(test_entry_return_and_stack)] + [x] + [%(path)s:14(function_3)] + [%(path)s:28(test_entry_return_and_stack)] + [x] + [%(path)s:18(function_4)] + [%(path)s:29(test_entry_return_and_stack)] + [x] + [%(path)s:22(function_5)] + [%(path)s:30(test_entry_return_and_stack)] + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + # When compiling with '--with-pydebug' + actual_result = "".join(re.split("\[[0-9]+ refs\]", actual_result)) + + actual_result = [i for i in actual_result.split("\n") if (("[" in i) + and not i.endswith(" () ]"))] + actual_result = "".join(actual_result) + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_garbage_collection(self) : + dscript = """ +python$target:::gc-start,python$target:::gc-done +{ + printf("%d\t**%s(%ld)\\n", timestamp, probename, arg0); +} +""" + + dscript = dscript.replace("\r", "").replace("\n", "") + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + for i in xrange(10) : + actual_result = actual_result.replace(str(i), "") + expected_result = "**gc-start()**gc-done()" * \ + actual_result.count("**gc-start()**") + + self.assertEqual(actual_result, expected_result) + + def test_verify_opcodes(self) : + # Verify that we are checking: + opcodes = set(["CALL_FUNCTION", "CALL_FUNCTION_VAR", + "CALL_FUNCTION_KW", "CALL_FUNCTION_VAR_KW"]) + with open(sample) as f : + obj = compile(f.read(), "sample", "exec") + class dump() : + def __init__(self) : + self.buf = [] + def write(self, v) : + self.buf.append(v) + + dump = dump() + stdout = sys.stdout + sys.stdout = dump + for i in obj.co_consts : + if isinstance(i, types.CodeType) and \ + (i.co_name == 'test_entry_return_and_stack') : + dis.dis(i) + sys.stdout = stdout + dump = "\n".join(dump.buf) + dump = dump.replace("\r", "").replace("\n", "").split() + for i in dump : + opcodes.discard(i) + # Are we verifying all the relevant opcodes? + self.assertEqual(set(), opcodes) # Are we verifying all opcodes? + + def test_line(self) : + dscript = """ +python$target:::line +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_line")/ +{ + printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **line*%(path)s*test_line*33 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*35 + **line*%(path)s*test_line*36 + **line*%(path)s*test_line*37 + **line*%(path)s*test_line*38 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*35 + **line*%(path)s*test_line*36 + **line*%(path)s*test_line*37 + **line*%(path)s*test_line*38 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*39 + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_instance_creation_destruction(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_instance_creation_destruction")/ +{ + self->trace = 1; +} + +python$target:::instance-new-start, +python$target:::instance-new-done, +python$target:::instance-delete-start, +python$target:::instance-delete-done +/self->trace/ +{ + printf("%%d\t**%%s* (%%s.%%s)\\n", timestamp, + probename, copyinstr(arg1), copyinstr(arg0)); +} + +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_instance_creation_destruction")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **instance-new-start*(__main__.old_style_class) + **instance-new-done*(__main__.old_style_class) + **instance-delete-start*(__main__.old_style_class) + **instance-delete-done*(__main__.old_style_class) + **instance-new-start*(__main__.new_style_class) + **instance-new-done*(__main__.new_style_class) + **instance-delete-start*(__main__.new_style_class) + **instance-delete-done*(__main__.new_style_class) + **instance-new-start*(__main__.old_style_class) + **instance-new-done*(__main__.old_style_class) + **instance-new-start*(__main__.new_style_class) + **instance-new-done*(__main__.new_style_class) + **instance-delete-start*(__main__.old_style_class) + **instance-delete-done*(__main__.old_style_class) + **instance-delete-start*(__main__.new_style_class) + **instance-delete-done*(__main__.new_style_class) + """ + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + + +# This class try to verify that dtrace probes +# are still working with optimizations enabled in the bytecode. +# +# Some tests will not actually verify it. For instance, +# source code compilation follows optimization status of +# current working Python. So, you should run the test +# both with an optimizing and a non optimizing Python. +class DTraceTestsOptimize(DTraceTestsNormal) : + def setUp(self) : + self.optimize = True + + +def test_main(): + run_unittest(DTraceTestsNormal) + run_unittest(DTraceTestsOptimize) + +if __name__ == '__main__': + test_main() + --- Lib/test/test_sys.py +++ Lib/test/test_sys.py @@ -517,6 +517,7 @@ self.assertEqual(sys.getsizeof(True, -1), size('l')) def test_objecttypes(self): + import dtrace # check all types defined in Objects/ size = test.test_support.calcobjsize vsize = test.test_support.calcvobjsize @@ -554,7 +555,10 @@ # complex check(complex(0,1), size('2d')) # code - check(get_cell().func_code, size('4i8Pi3P')) + if dtrace.available : + check(get_cell().func_code, size('4i8PiPH2P')) + else : + check(get_cell().func_code, size('4i8Pi3P')) # BaseException check(BaseException(), size('3P')) # UnicodeEncodeError --- Makefile.pre.in +++ Makefile.pre.in @@ -51,6 +51,13 @@ # Use this to make a link between python$(VERSION) and python in $(BINDIR) LN= @LN@ +DTRACE= @DTRACE@ +DFLAGS= @DFLAGS@ +DTRACEOBJS= @DTRACEOBJS@ +DTRACE_NM= @DTRACE_NM@ +DTRACE_LINKER= @DTRACE_LINKER@ + + # Portable install script (configure doesn't always guess right) INSTALL= @INSTALL@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ @@ -570,6 +577,7 @@ $(MODULE_OBJS) \ $(SIGNAL_OBJS) \ $(MODOBJS) \ + $(DTRACEOBJS) \ $(srcdir)/Modules/getbuildinfo.c $(CC) -c $(PY_CFLAGS) \ -DSVNVERSION="\"`LC_ALL=C $(SVNVERSION)`\"" \ @@ -577,6 +585,11 @@ -DHGTAG="\"`LC_ALL=C $(HGTAG)`\"" \ -DHGBRANCH="\"`LC_ALL=C $(HGBRANCH)`\"" \ -o $@ $(srcdir)/Modules/getbuildinfo.c + if test "$(DTRACEOBJS)" != "" ; then \ + $(DTRACE_LINKER) --relocatable \ + $@ $(DTRACEOBJS) -o $@.DTRACE ; \ + mv $@.DTRACE $@ ; \ + fi; Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile $(CC) -c $(PY_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ @@ -664,6 +677,52 @@ Python/formatter_string.o: $(srcdir)/Python/formatter_string.c \ $(STRINGLIB_HEADERS) + +Include/pydtrace.h: Include/pydtrace.d + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -h -s Include/pydtrace.d ; \ + else touch $@ ; \ + fi; + +Include/pydtrace_offsets.h: Include/pydtrace_offsets.c Python/ceval.o + $(CC) $(OPT) $(LDFLAGS) -o Include/pydtrace_offsets \ + Include/pydtrace_offsets.c + Include/pydtrace_offsets.sh $(DTRACE_NM) \ + Python/ceval.o Include/pydtrace_offsets > \ + Include/pydtrace_offsets.h + +Python/ceval.o: Include/pydtrace.h +Modules/gcmodule.o: Include/pydtrace.h +Objects/classobject.o: Include/pydtrace.h +Objects/typeobject.o: Include/pydtrace.h + +Python/pydtrace.o: Include/pydtrace.d Include/pydtrace_offsets.h \ + Python/ceval.o Modules/gcmodule.o \ + Objects/classobject.o Objects/typeobject.o + # We do the "touch" game to break a circular dependency between + # "Python/ceval.o" and "Include/pydtrace_offsets.h". + if test "$(DTRACE)" != "" ; then \ + touch -r Python/ceval.o Python/ceval.o.ts_dtrace ; \ + touch -r Modules/gcmodule.o Modules/gcmodule.o.ts_dtrace ; \ + touch -r Objects/classobject.o Objects/classobject.o.ts_dtrace ; \ + touch -r Objects/typeobject.o Objects/typeobject.o.ts_dtrace ; \ + $(DTRACE) -o $@ -DPYDTRACE_STACK_HELPER \ + $(CPPFLAGS) $(DFLAGS) \ + -C -G -s Include/pydtrace.d \ + Python/ceval.o Modules/gcmodule.o \ + Objects/classobject.o Objects/typeobject.o ; \ + touch -r Python/ceval.o.ts_dtrace Python/ceval.o ; \ + touch -r Modules/gcmodule.o.ts_dtrace Modules/gcmodule.o ; \ + touch -r Objects/classobject.o.ts_dtrace Objects/classobject.o ; \ + touch -r Objects/typeobject.o.ts_dtrace Objects/typeobject.o ; \ + rm Python/ceval.o.ts_dtrace ; \ + rm Modules/gcmodule.o.ts_dtrace ; \ + rm Objects/classobject.o.ts_dtrace ; \ + rm Objects/typeobject.o.ts_dtrace ; \ + else touch $@ ; \ + fi; + ############################################################################ # Header files @@ -1276,6 +1335,12 @@ find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name 'fficonfig.py' -exec rm -f {} ';' || true + rm -f Include/pydtrace.h + rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h + rm -f Python/ceval.o.ts_dtrace + rm -f Modules/gcmodule.o.ts_dtrace + rm -f Objects/classobject.o.ts_dtrace + rm -f Objects/typeobject.o.ts_dtrace -rm -f Lib/lib2to3/*Grammar*.pickle profile-removal: @@ -1305,6 +1370,12 @@ -o -name '*.orig' -o -name '*.rej' \ -o -name '*.bak' ')' \ -exec rm -f {} ';' + rm -f Include/pydtrace.h + rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h + rm -f Python/ceval.o.ts_dtrace + rm -f Modules/gcmodule.o.ts_dtrace + rm -f Objects/classobject.o.ts_dtrace + rm -f Objects/typeobject.o.ts_dtrace # Check for smelly exported symbols (not starting with Py/_Py) smelly: all --- /dev/null +++ Modules/dtracemodule.c @@ -0,0 +1,25 @@ +#include "Python.h" + +static PyMethodDef dtrace_methods[] = { + {NULL, NULL} +}; + + +PyMODINIT_FUNC initdtrace(void) +{ + PyObject *mod, *v; + + mod = Py_InitModule("dtrace", dtrace_methods); + if (!mod) + return; + +#ifdef WITH_DTRACE + v = Py_True; +#else + v = Py_False; +#endif + + Py_INCREF(v); + if (PyModule_AddObject(mod, "available", v) < 0) + return; +} --- Modules/gcmodule.c +++ Modules/gcmodule.c @@ -21,6 +21,10 @@ #include "Python.h" #include "frameobject.h" /* for PyFrame_ClearFreeList */ +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + /* Get an object's GC head */ #define AS_GC(o) ((PyGC_Head *)(o)-1) @@ -869,7 +873,12 @@ /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t -collect(int generation) +#ifdef WITH_DTRACE +collect2 +#else +collect +#endif +(int generation) { int i; Py_ssize_t m = 0; /* # objects collected */ @@ -1029,6 +1038,49 @@ return n+m; } +#ifdef WITH_DTRACE +static void +dtrace_gc_start(int collection) +{ + PYTHON_GC_START(collection); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static void +dtrace_gc_done(Py_ssize_t value) +{ + PYTHON_GC_DONE((long) value); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static Py_ssize_t +collect(int collection) +{ + Py_ssize_t value; + + if (PYTHON_GC_START_ENABLED()) + dtrace_gc_start(collection); + value = collect2(collection); + if (PYTHON_GC_DONE_ENABLED()) + dtrace_gc_done(value); + return value; +} +#endif /* WITH_DTRACE */ + static Py_ssize_t collect_generations(void) { --- Objects/classobject.c +++ Objects/classobject.c @@ -4,6 +4,10 @@ #include "Python.h" #include "structmember.h" +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + /* Free list for method objects to safe malloc/free overhead * The im_self element is used to chain the elements. */ @@ -553,6 +557,30 @@ PyObject *init; static PyObject *initstr; +#ifdef WITH_DTRACE + PyObject *mod; + char *mod_name; + char *cl_name; + + if (PYTHON_INSTANCE_NEW_START_ENABLED()) { + mod = PyDict_GetItemString(((PyClassObject *)klass)->cl_dict, + "__module__"); + + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + if (!mod_name) + mod_name = "?"; + } + cl_name = PyString_AS_STRING(((PyClassObject *)klass)->cl_name); + if (!cl_name) + cl_name = "?"; + + PYTHON_INSTANCE_NEW_START(cl_name, mod_name); + } +#endif + if (initstr == NULL) { initstr = PyString_InternFromString("__init__"); if (initstr == NULL) @@ -594,6 +622,26 @@ Py_DECREF(res); } } + +#ifdef WITH_DTRACE + if (PYTHON_INSTANCE_NEW_DONE_ENABLED()) { + mod = PyDict_GetItemString(((PyClassObject *)klass)->cl_dict, + "__module__"); + + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + if (!mod_name) + mod_name = "?"; + } + cl_name = PyString_AS_STRING(((PyClassObject *)klass)->cl_name); + if (!cl_name) + cl_name = "?"; + + PYTHON_INSTANCE_NEW_DONE(cl_name, mod_name); + } +#endif return (PyObject *)inst; } @@ -628,7 +676,12 @@ static void -instance_dealloc(register PyInstanceObject *inst) +#ifdef WITH_DTRACE +instance_dealloc2 +#else +instance_dealloc +#endif +(register PyInstanceObject *inst) { PyObject *error_type, *error_value, *error_traceback; PyObject *del; @@ -705,6 +758,49 @@ } } +#ifdef WITH_DTRACE +static void +instance_dealloc(register PyInstanceObject *inst) +{ + PyObject *mod; + char *mod_name = NULL; + char *cl_name = NULL; + PyClassObject *in_class; + + if (PYTHON_INSTANCE_DELETE_START_ENABLED() || + PYTHON_INSTANCE_DELETE_DONE_ENABLED()) { + in_class = inst->in_class; + Py_INCREF(in_class); + mod = PyDict_GetItemString(in_class->cl_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + if (!mod_name) + mod_name = "?"; + } + cl_name = PyString_AS_STRING(in_class->cl_name); + if (!cl_name) + cl_name = "?"; + } + + if (PYTHON_INSTANCE_DELETE_START_ENABLED() && cl_name) { + PYTHON_INSTANCE_DELETE_START(cl_name, mod_name); + } + + instance_dealloc2(inst); + + if (PYTHON_INSTANCE_DELETE_DONE_ENABLED() && cl_name) { + PYTHON_INSTANCE_DELETE_DONE(cl_name, mod_name); + } + + if (cl_name) { + Py_DECREF(in_class); + } +} +#endif + + static PyObject * instance_getattr1(register PyInstanceObject *inst, PyObject *name) { --- Objects/codeobject.c +++ Objects/codeobject.c @@ -104,6 +104,28 @@ co->co_lnotab = lnotab; co->co_zombieframe = NULL; co->co_weakreflist = NULL; +#ifdef WITH_DTRACE + i = PyString_Size(co->co_code); + co->co_linenos = PyMem_Malloc(sizeof(unsigned short) * i); + if (co->co_linenos) { + unsigned short *p = (unsigned short *)(co->co_linenos); + unsigned char *p2 = (unsigned char*)PyString_AsString(co->co_lnotab); + int size = PyString_Size(co->co_lnotab) / 2; + int i2; + unsigned short offset = 0; + + while (size) { + size -= 1; + i2 = *p2++; + i-=i2; + while (i2--) + *p++ = offset; + offset += *p2++; + } + while(i--) + *p++ = offset; + } +#endif } return co; } @@ -313,6 +335,10 @@ Py_XDECREF(co->co_filename); Py_XDECREF(co->co_name); Py_XDECREF(co->co_lnotab); +#ifdef WITH_DTRACE + if (co->co_linenos) + PyMem_Free(co->co_linenos); +#endif if (co->co_zombieframe != NULL) PyObject_GC_Del(co->co_zombieframe); if (co->co_weakreflist != NULL) --- Objects/typeobject.c +++ Objects/typeobject.c @@ -3,6 +3,10 @@ #include "Python.h" #include "structmember.h" +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + #include @@ -754,8 +758,29 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems) { PyObject *obj; - const size_t size = _PyObject_VAR_SIZE(type, nitems+1); + size_t size; + +#ifdef WITH_DTRACE + PyObject *mod; + char *mod_name; + + if (PYTHON_INSTANCE_NEW_START_ENABLED()) { + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_NEW_START((char *)(type->tp_name), mod_name); + } + } +#endif + /* note that we need to add one, for the sentinel */ + size = _PyObject_VAR_SIZE(type, nitems+1); if (PyType_IS_GC(type)) obj = _PyObject_GC_Malloc(size); @@ -777,6 +802,23 @@ if (PyType_IS_GC(type)) _PyObject_GC_TRACK(obj); + +#ifdef WITH_DTRACE + if (PYTHON_INSTANCE_NEW_DONE_ENABLED()) { + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_NEW_DONE((char *)(type->tp_name), mod_name); + } + } +#endif + return obj; } @@ -897,9 +939,56 @@ return 0; } +#ifdef WITH_DTRACE +static void subtype_dealloc2(PyObject *); /* Forward declaration */ + static void subtype_dealloc(PyObject *self) { + PyObject *mod; + char *mod_name; + PyTypeObject *type; + + type = Py_TYPE(self); + Py_INCREF(type); + + if (PYTHON_INSTANCE_DELETE_START_ENABLED()) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_DELETE_START((char *)(type->tp_name), mod_name); + } + + subtype_dealloc2(self); + + if (PYTHON_INSTANCE_DELETE_DONE_ENABLED()) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyString_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyString_AS_STRING(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_DELETE_DONE((char *)(type->tp_name), mod_name); + } + Py_DECREF(type); +} +#endif + +static void +#ifdef WITH_DTRACE +subtype_dealloc2 +#else +subtype_dealloc +#endif +(PyObject *self) +{ PyTypeObject *type, *base; destructor basedealloc; PyThreadState *tstate = PyThreadState_GET(); --- Python/ceval.c +++ Python/ceval.c @@ -19,6 +19,10 @@ #include +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + #ifndef WITH_TSC #define READ_TIMESTAMP(var) @@ -120,6 +124,12 @@ #define CALL_FLAG_VAR 1 #define CALL_FLAG_KW 2 +#ifdef WITH_DTRACE +static void maybe_dtrace_line(PyFrameObject *frame, + int *instr_lb, int *instr_ub, + int *instr_prev); +#endif + #ifdef LLTRACE static int lltrace; static int prtrace(PyObject *, char *); @@ -672,6 +682,50 @@ NULL); } +#ifdef WITH_DTRACE +static void +dtrace_entry(PyFrameObject *f) +{ + const char *filename; + const char *fname; + int lineno; + + filename = PyString_AsString(f->f_code->co_filename); + fname = PyString_AsString(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + + PYTHON_FUNCTION_ENTRY((char *)filename, (char *)fname, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static void +dtrace_return(PyFrameObject *f) +{ + const char *filename; + const char *fname; + int lineno; + + filename = PyString_AsString(f->f_code->co_filename); + fname = PyString_AsString(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + PYTHON_FUNCTION_RETURN((char *)filename, (char *)fname, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} +#endif /* Interpreter main loop */ @@ -683,8 +737,16 @@ return PyEval_EvalFrameEx(f, 0); } + PyObject * +#if defined(WITH_DTRACE) && defined(__amd64) +PyEval_EvalFrameExReal(long a1, long a2, long a3, long a4, long a5, long a6, + PyFrameObject *f, int throwflag) +#elif defined(WITH_DTRACE) && defined(__sparc) +PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag) +#else PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +#endif { #ifdef DXPAIRS int lastopcode = 0; @@ -910,6 +972,11 @@ } } +#ifdef WITH_DTRACE + if (PYTHON_FUNCTION_ENTRY_ENABLED()) + dtrace_entry(f); +#endif + co = f->f_code; names = co->co_names; consts = co->co_consts; @@ -1096,6 +1163,12 @@ /* Main switch on opcode */ READ_TIMESTAMP(inst0); +#ifdef WITH_DTRACE + if (PYTHON_LINE_ENABLED()) { + maybe_dtrace_line(f, &instr_lb, &instr_ub, &instr_prev); + } +#endif + switch (opcode) { /* BEWARE! @@ -3001,6 +3074,10 @@ /* pop frame */ exit_eval_frame: +#ifdef WITH_DTRACE + if (PYTHON_FUNCTION_RETURN_ENABLED()) + dtrace_return(f); +#endif Py_LeaveRecursiveCall(); tstate->frame = f->f_back; @@ -3696,6 +3773,57 @@ return result; } +/* + * These shenanigans look like utter madness, but what we're actually doing is + * making sure that the ustack helper will see the PyFrameObject pointer on the + * stack. We have two tricky cases: + * + * amd64 + * + * We use up the six registers for passing arguments, meaning the call can't + * use a register for passing 'f', and has to push it onto the stack in a known + * location. + * + * And how does "throwflag" figure in to this? -PN + * + * SPARC + * + * Here the problem is that (on 32-bit) the compiler is re-using %i0 before + * some calls inside PyEval_EvalFrameReal(), which means that when it's saved, + * it's just some junk value rather than the real first argument. So, instead, + * we trace our proxy PyEval_EvalFrame(), where we 'know' the compiler won't + * decide to re-use %i0. We also need to defeat optimization of our proxy. + */ + +#if defined(WITH_DTRACE) + +#if defined(__amd64) + +PyObject * +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + volatile PyObject *f2; + f2 = PyEval_EvalFrameExReal(0, 0, 0, 0, 0, 0, f, throwflag); + return (PyObject *)f2; +} + +#elif defined(__sparc) + +volatile int dummy; + +PyObject * +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + volatile PyObject *f2; + f2 = PyEval_EvalFrameExReal(f, throwflag); + dummy = f->ob_refcnt; + return (PyObject *)f2; +} + +#endif +#endif + + PyObject * _PyEval_CallTracing(PyObject *func, PyObject *args) { @@ -3714,6 +3842,51 @@ return result; } +#ifdef WITH_DTRACE +/* See Objects/lnotab_notes.txt for a description of how tracing works. */ +/* Practically a ripoff of "maybe_call_line_trace" function. */ +static void +maybe_dtrace_line(PyFrameObject *frame, int *instr_lb, int *instr_ub, + int *instr_prev) +{ + int line = frame->f_lineno; + char *co_filename, *co_name; + + /* If the last instruction executed isn't in the current + instruction window, reset the window. + */ + if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) { + PyAddrPair bounds; + line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, + &bounds); + *instr_lb = bounds.ap_lower; + *instr_ub = bounds.ap_upper; + } + /* If the last instruction falls at the start of a line or if + it represents a jump backwards, update the frame's line + number and call the trace function. */ + if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) { + frame->f_lineno = line; + co_filename = PyString_AsString(frame->f_code->co_filename); + if (!co_filename) + co_filename = "?"; + co_name = PyString_AsString(frame->f_code->co_name); + if (!co_name) + co_name = "?"; + PYTHON_LINE(co_filename, co_name, line); + } + *instr_prev = frame->f_lasti; + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} +#endif + /* See Objects/lnotab_notes.txt for a description of how tracing works. */ static int maybe_call_line_trace(Py_tracefunc func, PyObject *obj, --- Python/sysmodule.c +++ Python/sysmodule.c @@ -1399,7 +1399,6 @@ Py_XDECREF(sysin); Py_XDECREF(sysout); Py_XDECREF(syserr); - SET_SYS_FROM_STRING("version", PyString_FromString(Py_GetVersion())); SET_SYS_FROM_STRING("hexversion", --- configure +++ configure @@ -639,6 +639,11 @@ MACHDEP_OBJS DYNLOADFILE DLINCLDIR +DTRACEOBJS +DTRACE_LINKER +DTRACE_NM +DFLAGS +DTRACE THREADOBJ LDLAST USE_THREAD_MODULE @@ -801,6 +806,7 @@ with_tsc with_pymalloc with_valgrind +with_dtrace with_wctype_functions with_fpectl with_libm @@ -1482,6 +1488,7 @@ --with(out)-tsc enable/disable timestamp counter profile --with(out)-pymalloc disable/enable specialized mallocs --with-valgrind Enable Valgrind support + --with(out)-dtrace disable/enable dtrace support --with-wctype-functions use wctype.h functions --with-fpectl enable SIGFPE catching --with-libm=STRING math library @@ -10066,6 +10073,181 @@ fi +# Check for dtrace support +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dtrace" >&5 +$as_echo_n "checking for --with-dtrace... " >&6; } + +# Check whether --with-dtrace was given. +if test "${with_dtrace+set}" = set; then : + withval=$with_dtrace; +else + with_dtrace=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_dtrace" >&5 +$as_echo "$with_dtrace" >&6; } + + + + + +DTRACE= +DFLAGS= +if test "$with_dtrace" = "yes" +then + DTRACE_NM=OTHER + DTRACE_LINKER=ld + DTRACEOBJS="Python/pydtrace.o" + # Extract the first word of "dtrace", so it can be a program name with args. +set dummy dtrace; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/sbin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DTRACE" && ac_cv_path_DTRACE="dtrace" + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + if test "$ac_cv_sizeof_long" -eq 8 + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + sys_release="$ac_sys_release" + if test $ac_sys_system = "SunOS" + then + if test $sys_release="5.11" + then + sys_release=`uname -v` + fi + fi + case $ac_sys_system/$sys_release in + SunOS/5.10) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/11.*) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/*) + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + Darwin/*) + DTRACEOBJS="" # Not needed in Mac + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + if test "$ac_cv_sizeof_long" -eq 8 + then + DFLAGS="-arch i386" + else + DFLAGS="-arch x86_64" + fi + ;; + esac + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + +fi + + + # Check for --with-wctype-functions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-wctype-functions" >&5 $as_echo_n "checking for --with-wctype-functions... " >&6; } --- configure.ac +++ configure.ac @@ -2830,6 +2830,69 @@ ) fi +# Check for dtrace support +AC_MSG_CHECKING(for --with-dtrace) +AC_ARG_WITH(dtrace, + AC_HELP_STRING(--with(out)-dtrace, disable/enable dtrace support),, + with_dtrace=no) +AC_MSG_RESULT($with_dtrace) + +AC_SUBST(DTRACE) +AC_SUBST(DFLAGS) +AC_SUBST(DTRACE_NM) +AC_SUBST(DTRACE_LINKER) +DTRACE= +DFLAGS= +if test "$with_dtrace" = "yes" +then + DTRACE_NM=OTHER + DTRACE_LINKER=ld + DTRACEOBJS="Python/pydtrace.o" + AC_PATH_PROG(DTRACE, [dtrace], [dtrace], [$PATH$PATH_SEPARATOR/usr/sbin]) + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + sys_release="$ac_sys_release" + if test $ac_sys_system = "SunOS" + then + if test $sys_release="5.11" + then + sys_release=`uname -v` + fi + fi + case $ac_sys_system/$sys_release in + SunOS/5.10) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/11.*) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/*) + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + Darwin/*) + DTRACEOBJS="" # Not needed in Mac + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-arch i386" + else + DFLAGS="-arch x86_64" + fi + ;; + esac + AC_DEFINE(WITH_DTRACE, 1, + [Define if you want to compile in Dtrace support]) +fi + +AC_SUBST(DTRACEOBJS) + # Check for --with-wctype-functions AC_MSG_CHECKING(for --with-wctype-functions) AC_ARG_WITH(wctype-functions, --- pyconfig.h.in +++ pyconfig.h.in @@ -1101,6 +1101,9 @@ /* Define if you want documentation strings in extension modules */ #undef WITH_DOC_STRINGS +/* Define to compile in Dtrace support */ +#undef WITH_DTRACE + /* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic linker (dyld) instead of the old-style (NextStep) dynamic linker (rld). Dyld is necessary to support frameworks. */ --- setup.py +++ setup.py @@ -679,6 +679,9 @@ # http://mail.python.org/pipermail/python-dev/2006-January/060023.html #exts.append( Extension('timing', ['timingmodule.c']) ) + # jcea DTRACE probes + exts.append( Extension('dtrace', ['dtracemodule.c']) ) + # # Here ends the simple stuff. From here on, modules need certain # libraries, are platform-specific, or present other surprises. PKYE]jjj3pythonz/patches/osx/python33/python-334-dtrace.diff--- Doc/library/debug.rst +++ Doc/library/debug.rst @@ -15,3 +15,4 @@ profile.rst timeit.rst trace.rst + dtrace.rst --- /dev/null +++ Doc/library/dtrace.rst @@ -0,0 +1,183 @@ +:mod:`dtrace` --- DTrace probes for Python +=============================================== + +.. module:: dtrace + :synopsis: DTrace probes for Python. + +**Source code:** :source:`Lib/dtrace.py` + +-------------- + +The :mod:`dtrace` module indicates if the CPython executable currently +running has been compiled with DTrace probes support. + +.. impl-detail:: + + DTrace probes are implementation details of the CPython interpreter! + No garantees are made about probe compatibility between versions of + CPython. DTrace scripts can stop working or work incorrectly without + warning when changing CPython versions. + +The :mod:`dtrace` module defines the following variable: + + +.. data:: available + + The variable will be ``True`` if the current CPython interpreter was + compiled with DTrace probe support. ``False`` if not. + + +DTrace probes +------------- + +DTrace scripts are run externally to CPython. DTrace probes export +selected events inside CPython interpreter in order to make them +accessible to external scripts. + +The probes are exported through the "python" provider. The available +probes are defined in the file :file:`Include/pydtrace.d`. + +To learn how to use DTrace, read `DTrace User Guide +`_. + +.. opcode:: function-entry (arg0, arg1, arg2) + + Fires when python code enters a new function. *arg0* is sourcecode + file path, *arg1* is the name of the funcion called, and *arg2* is + line number. + + The probe is not fired if Python code calls C functions. + +.. opcode:: function-return (arg0, arg1, arg2) + + Fires when Python code finishes execution of a function. Parameters + are the same as in ``function-entry``. + + The probe is not fired if the finishing function is written in C. + +.. opcode:: line (arg0, arg1, arg2) + + Fires when Python code changes the execution line. Parameters are the + same as in ``function-entry``. + + The probe is not fired in C functions. + +.. opcode:: gc-start (arg0) + + Fires when the Python interpreter starts a garbage collection cycle. + *arg0* is the generation to scan, like :func:`gc.collect()`. + +.. opcode:: gc-done (arg0) + + Fires when the Python interpreter finishes a garbage collection + cycle. *arg0* is the number of collected objects. + +.. opcode:: instance-new-start (arg0, arg1) + + Fires when an object instanciation starts. *arg0* is the class name, + *arg1* is the filename where the class is defined. + + The probe is not fired for most C code object creations. + +.. opcode:: instance-new-done (arg0, arg1) + + Fires when an object instanciation finishes. Parameters are the same + as in ``instance-new-done``. + + The probe is not fired for most C code object creations. + +.. opcode:: instance-delete-start (arg0, arg1) + + Fires when an object instance is going to be destroyed. Parameters + are the same as in ``instance-new-done``. + + The probe is not fired for most C code object destructions. + +.. opcode:: instance-delete-done (arg0, arg1) + + Fires when an object instance has been destroyed. parameters are the + same as in ``instance-new-done``. + + Between an ``instance-delete-start`` and corresponding + ``instance-delete-done`` others probes can fire if, for instance, + deletion of an instance creates a deletion cascade. + + The probe is not fired for most C code object destructions. + + +Python stack +------------ + +When a DTrace probe is fired, the DTrace script can examine the stack. +Since CPython is a Python interpreter coded in C, the stack will show C +functions, with no direct relation to the Python code currently being +executed. + +Using the special "jstack()" DTrace function, the user will be given +hints about the python program stack, if possible. In particular, the +augmented stack will show python function calls, filename, name +of the function or method, and the line number. + +DTrace scripts examples +----------------------- + +DTrace python provider is suffixed by the pid of the process to monitor. +In the examples, the pid will be 9876. + +Show the time spent doing garbage collection (in nanoseconds):: + + python9876:::gc-start + { + self->t = timestamp; + } + + python9876:::gc-done + /self->t/ + { + printf("%d", timestamp-self->t); + self->t = 0; + } + +Count how many instances are created of each class:: + + python9876:::instance-new-start + { + @v[copyinstr(arg1), copyinstr(arg0)] = count(); + } + +Observe time spent in object destruction, useful if datastructures are +complicated and deletion of an object can create a cascade effect:: + + python9876:::instance-delete-start + /self->t==0/ + { + self->t = timestamp; + self->level = 0; + } + + python9876:::instance-delete-start + /self->t/ + { + self->level += 1; + } + + python9876:::instance-delete-done + /(self->level) && (self->t)/ + { + self->level -= 1; + } + + python9876:::instance-delete-done + /(self->level==0) && (self->t)/ + { + @time = quantize(timestamp-self->t); + self->t = 0; + } + +To know which python source code lines create new TCP/IP connections:: + + pid9876::sock_connect:entry + { + @conn[jstack()] = count(); + } + --- Include/code.h +++ Include/code.h @@ -7,6 +7,8 @@ extern "C" { #endif +#include "pyconfig.h" + /* Bytecode object */ typedef struct { PyObject_HEAD @@ -28,6 +30,9 @@ int co_firstlineno; /* first source line number */ PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See Objects/lnotab_notes.txt for details. */ +#ifdef WITH_DTRACE + unsigned short *co_linenos; /* dtrace stack helper */ +#endif void *co_zombieframe; /* for optimization only (see frameobject.c) */ PyObject *co_weakreflist; /* to support weakrefs to code objects */ } PyCodeObject; --- /dev/null +++ Include/pydtrace.d @@ -0,0 +1,177 @@ +provider python { + probe function__entry(const char *, const char *, int); + probe function__return(const char *, const char *, int); + probe instance__new__start(const char *, const char *); + probe instance__new__done(const char *, const char *); + probe instance__delete__start(const char *, const char *); + probe instance__delete__done(const char *, const char *); + probe line(const char *, const char *, int); + probe gc__start(int); + probe gc__done(long); +}; + +#pragma D attributes Evolving/Evolving/Common provider python provider +#pragma D attributes Private/Private/Common provider python module +#pragma D attributes Private/Private/Common provider python function +#pragma D attributes Evolving/Evolving/Common provider python name +#pragma D attributes Evolving/Evolving/Common provider python args + + + +#ifdef PYDTRACE_STACK_HELPER +/* + * Python ustack helper. This relies on the first argument (PyFrame *) being + * on the stack; see Python/ceval.c for the contortions we go through to ensure + * this is the case. + * + * On x86, the PyFrame * is two slots up from the frame pointer; on SPARC, it's + * eight. + * + * Some details about this in "Python and DTrace in build 65": + * http://blogs.oracle.com/levon/entry/python_and_dtrace_in_build + */ + +/* + * Yes, this is as gross as it looks. DTrace cannot handle static functions, + * and our stat_impl.h has them in ILP32. + */ +#define _SYS_STAT_H + +/* +** When compiling in 32 bits: +** - Early inclusion to avoid problems with +** _FILE_OFFSET_BITS redefined. +** - Also, we must "undef" _POSIX_PTHREAD_SEMANTICS +** to avoid error compiling this source. +*/ +#include "pyconfig.h" +#undef _POSIX_PTHREAD_SEMANTICS + +#include +#include + +#include "pyport.h" +#include "pyatomic.h" +/* "string" type is used in dtrace */ +#define string stringDTRACE +#include "object.h" +#include "pystate.h" +#include "pyarena.h" +#include "pythonrun.h" +#include "compile.h" +#include "frameobject.h" +/* Avoid a compile error because a symbol (equivalent) redefinition */ +#undef __STDC__ +/* "self" has an special meaning for dtrace */ +#define self selfDTRACE +#include "unicodeobject.h" +#undef string +#undef self + +#include "pydtrace_offsets.h" + +#if defined(__i386) +#define startframe PyEval_EvalFrameEx +#define endframe AFTER_PyEval_EvalFrameEx +#elif defined(__amd64) +#define startframe PyEval_EvalFrameExReal +#define endframe AFTER_PyEval_EvalFrameExReal +#elif defined(__sparc) +#define startframe PyEval_EvalFrameExReal +#define endframe AFTER_PyEval_EvalFrameExReal +#endif + +#ifdef __sparcv9 +#define STACK_BIAS (2048-1) +#else +#define STACK_BIAS 0 +#endif + +#define at_evalframe(addr) \ + ((uintptr_t)addr >= ((uintptr_t)&``startframe) && \ + (uintptr_t)addr < ((uintptr_t)&``endframe)) +#define probe dtrace:helper:ustack: +#define print_result(r) (r) + +#if defined(__i386) || defined(__amd64) +#define frame_ptr_addr ((uintptr_t)arg1 + sizeof(uintptr_t) * 2) +#elif defined(__sparc) +#define frame_ptr_addr ((uintptr_t)arg1 + STACK_BIAS + sizeof(uintptr_t) * 8) +#else +#error unknown architecture +#endif + +/* startframe and endframe are macro-expansions */ +extern uintptr_t startframe; +extern uintptr_t endframe; + + +#define copyin_obj(addr, obj) ((obj *)copyin((uintptr_t)(addr), sizeof(obj))) + +/* +** Check if the string is ASCII. Don't use bitfields, because the +** packing in GCC and D are different. BEWARE!!!. +** The size of the structures are also different!. That is the reason for +** the negative offset. BEWARE!!! +*/ +#define pystr_len(addr) ((*(((char *)addr)+PYDTRACE_ASCII_OFFSET)) & PYDTRACE_ASCII_MASK ? \ + (addr)->_base.length : \ + *(Py_ssize_t *)(((char *)(addr)) + PYDTRACE_UTF8_LENGTH_OFFSET)) +#define pystr_addr(addr, addr2) ((*(((char *)addr)+PYDTRACE_ASCII_OFFSET)) & PYDTRACE_ASCII_MASK ? \ + (char *)(((char *)(addr2)) + PYDTRACE_PyASCIIObject_SIZE) : \ + (char *)*(uintptr_t *)(((char *)(addr)) + PYDTRACE_UTF8_OFFSET)) + +#define add_digit(nr, div) (((nr) / div) ? \ + (this->result[this->pos++] = '0' + (((nr) / div) % 10)) : \ + (this->result[this->pos] = '\0')) +#define add_char(c) (this->result[this->pos++] = c) + +probe /at_evalframe(arg0)/ +{ + this->framep = *(uintptr_t *)copyin(frame_ptr_addr, sizeof(uintptr_t)); + this->frameo = copyin_obj(this->framep, PyFrameObject); + this->codep = this->frameo->f_code; + this->codeo = copyin_obj(this->codep, PyCodeObject); + /* If we just enter a function, show the definition line */ + this->lineno = this->codeo->co_firstlineno + + (this->frameo->f_lasti == -1 ? 0 : + *copyin_obj(this->codeo->co_linenos + this->frameo->f_lasti, + unsigned short)); + this->filenameo = copyin_obj(this->codeo->co_filename, PyCompactUnicodeObject); + this->len_filename = pystr_len(this->filenameo); + this->nameo = copyin_obj(this->codeo->co_name, PyCompactUnicodeObject); + this->len_name = pystr_len(this->nameo); + this->len = 1 + (this->len_filename) + 1 + 5 + 2 + + (this->len_name) + 1 + 1; + + this->result = (char *)alloca(this->len); + this->pos = 0; + add_char('@'); + + copyinto((uintptr_t)pystr_addr(this->filenameo, this->codeo->co_filename), this->len_filename, this->result+this->pos); + this->pos += this->len_filename; + + add_char(':'); + add_digit(this->lineno, 10000); + add_digit(this->lineno, 1000); + add_digit(this->lineno, 100); + add_digit(this->lineno, 10); + add_digit(this->lineno, 1); + add_char(' '); + add_char('('); + + copyinto((uintptr_t)pystr_addr(this->nameo, this->codeo->co_name), this->len_name, this->result+this->pos); + this->pos += this->len_name; + + add_char(')'); + this->result[this->pos] = '\0'; + print_result(stringof(this->result)); +} + +probe /!at_evalframe(arg0)/ +{ + NULL; +} + +#endif /* PYDTRACE_STACK_HELPER */ + --- /dev/null +++ Include/pydtrace_offsets.c @@ -0,0 +1,40 @@ +#include "Python.h" +#include "unicodeobject.h" +#include +#include + +int main(int argc, const char* argv[]) { + PyCompactUnicodeObject o; + unsigned char *p = (unsigned char *)(&o); + + if (argc != 3) { + printf("Parameter number incorrect\n"); + exit(1); + } + + memset(&o, 0, sizeof(o)); + o._base.state.ascii = 1; + while (!*p) p++; + + printf("/* File autogenerated. DO NOT MODIFY MANUALLY */\n"); + printf("\n"); + printf("#ifndef PYDTRACE_OFFSETS_H\n"); + printf("#define PYDTRACE_OFFSETS_H\n"); + printf("\n"); + printf("#define PYDTRACE_ASCII_OFFSET %d\n", + p-(unsigned char *)(&o)); + printf("#define PYDTRACE_ASCII_MASK %d\n", *p); + printf("#define PYDTRACE_PyASCIIObject_SIZE %d\n", + sizeof(PyASCIIObject)); + printf("#define PYDTRACE_UTF8_LENGTH_OFFSET %d\n", + offsetof(PyCompactUnicodeObject, utf8_length)); + printf("#define PYDTRACE_UTF8_OFFSET %d\n", + offsetof(PyCompactUnicodeObject, utf8)); + printf("\n"); + printf("#define AFTER_PyEval_EvalFrameEx %s\n", argv[1]); + printf("#define AFTER_PyEval_EvalFrameExReal %s\n", argv[2]); + printf("\n"); + printf("#endif\n"); + return 0; +} + --- /dev/null +++ Include/pydtrace_offsets.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +DTRACE_NM=$1 +CEVAL_O=$2 +PYDTRACE_OFFSETS=$3 +if test "$DTRACE_NM" = "OTHER" ; then + $PYDTRACE_OFFSETS \ + "`nm -n $CEVAL_O | grep \" T \" | \ + sed -n \"/ T PyEval_EvalFrameEx$/{n;p;}\" | \ + sed \"s/.* T \(.*\)$/\1/\"`" \ + "`nm -n $CEVAL_O | grep \" T \" | \ + sed -n \"/ T PyEval_EvalFrameExReal$/{n;p;}\" | \ + sed \"s/.* T \(.*\)$/\1/\"`" +fi +if test "$DTRACE_NM" = "SOLARIS" ; then + $PYDTRACE_OFFSETS \ + "`/usr/ccs/bin/nm -n $CEVAL_O | \ + /usr/bin/grep \"\\|FUNC \\|\" | \ + /usr/bin/grep -v \"\\|IGNORE \\|\" | \ + /usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \ + sed -n \"/ PyEval_EvalFrameEx$/{n;p;}\" | \ + sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`" \ + "`/usr/ccs/bin/nm -n $CEVAL_O | \ + /usr/bin/grep \"\\|FUNC \\|\" | \ + /usr/bin/grep -v \"\\|IGNORE \\|\" | \ + /usr/bin/tr -d \"\\[\\]\\|\" | sort -n | \ + sed -n \"/ PyEval_EvalFrameExReal$/{n;p;}\" | \ + sed \"s/.* \([a-zA-Z0-9_]*\)$/\1/\"`" +fi + --- /dev/null +++ Lib/test/dtrace_sample.py @@ -0,0 +1,80 @@ +# Sample script for use by test_dtrace.py +# DO NOT MODIFY THIS FILE IN ANY WAY WITHOUT UPDATING test_dtrace.py!!!!! + +import gc + +def function_1() : + pass + +# Check stacktrace +def function_2() : + function_1() + +# CALL_FUNCTION_VAR +def function_3(dummy, dummy2) : + pass + +# CALL_FUNCTION_KW +def function_4(**dummy) : + pass + +# CALL_FUNCTION_VAR_KW +def function_5(dummy, dummy2, **dummy3) : + pass + +def test_entry_return_and_stack() : + function_1() + function_2() + function_3(*(1,2)) + function_4(**{"test":42}) + function_5(*(1,2), **{"test":42}) + +def test_line() : + a = 1 # Preamble + for i in range(2) : + a = i + b = i+2 + c = i+3 + d = a + b +c + a = 1 # Epilogue + +def test_unicode_entry_return_and_stack() : + def únícódé() : + pass + únícódé() + +def test_instance_creation_destruction() : + class old_style_class() : + pass + class new_style_class(object) : + pass + + a = old_style_class() + del a + gc.collect() + b = new_style_class() + del b + gc.collect() + + a = old_style_class() + del old_style_class + gc.collect() + b = new_style_class() + del new_style_class + gc.collect() + del a + gc.collect() + del b + gc.collect() + +def test_garbage_collection() : + gc.collect() + + +if __name__ == "__main__": + test_entry_return_and_stack() + test_line() + test_unicode_entry_return_and_stack() + test_instance_creation_destruction() + test_garbage_collection() + --- /dev/null +++ Lib/test/test_dtrace.py @@ -0,0 +1,447 @@ +import sys, unittest, subprocess, os.path, dis, types, re +import dtrace +from test.support import TESTFN, run_unittest, findfile + +sample = os.path.abspath(findfile("dtrace_sample.py")) +if not dtrace.available : + raise unittest.SkipTest("dtrace support not compiled in") + +def normalize(data) : + # DTRACE keeps a per-CPU buffer, and when showing the fired probes, + # buffers are concatenated. So if the operating system moves our + # thread around, the straight result can be "non causal". + # So we add timestamps to the probe firing, and sort by that field. + + result = data if isinstance(data, str) else data.decode("ascii") + # When compiling with '--with-pydebug' + result = "".join(re.split("\[[0-9]+ refs\]", result)) + + try : + result = [i.split("\t") \ + for i in result.replace("\r", "").split("\n") if len(i)] + result.sort(key = lambda i: int(i[0])) + result = "".join((i[1] for i in result)) + result = result.replace(" ", "") + except : + # If something goes wrong, rebuild the value so we can see the + # real result when the assert fails. + result = data if isinstance(data, str) else data.decode("ascii") + result = result.replace("\r", "").replace("\n", "") + return result + +dscript = """ +pid$target::PyEval_EvalCode:entry +""" +dscript = dscript.replace("\r", "").replace("\n", "") +result, _ = subprocess.Popen(["dtrace", "-q", "-l", "-n", dscript, + "-c", "%s %s" %(sys.executable, sample)], stdout=subprocess.PIPE, + stderr=subprocess.STDOUT).communicate() +if result.decode("ascii").split("\n")[1].split()[-2:] != \ + ["PyEval_EvalCode", "entry"] : + result2 = repr(result) + raise unittest.SkipTest("dtrace seems not to be working. " + \ + "Please, check your privileges. " + + "Result: " +result2) + +class DTraceTestsNormal(unittest.TestCase) : + def setUp(self) : + self.optimize = False + + def test_function_entry_return(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry,python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **function-entry*%(path)s*test_entry_return_and_stack*25 + **function-entry*%(path)s*function_1*6 + **function-return*%(path)s*function_1*7 + **function-entry*%(path)s*function_2*10 + **function-entry*%(path)s*function_1*6 + **function-return*%(path)s*function_1*7 + **function-return*%(path)s*function_2*11 + **function-entry*%(path)s*function_3*14 + **function-return*%(path)s*function_3*15 + **function-entry*%(path)s*function_4*18 + **function-return*%(path)s*function_4*19 + **function-entry*%(path)s*function_5*22 + **function-return*%(path)s*function_5*23 + **function-return*%(path)s*test_entry_return_and_stack*30 + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + @unittest.skipIf(sys.platform == 'darwin', + "MacOS X doesn't support jstack()") + def test_stack(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("[x]"); + jstack(); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + [x] + [%(path)s:25(test_entry_return_and_stack)] + [x] + [%(path)s:6(function_1)] + [%(path)s:26(test_entry_return_and_stack)] + [x] + [%(path)s:10(function_2)] + [%(path)s:27(test_entry_return_and_stack)] + [x] + [%(path)s:6(function_1)] + [%(path)s:11(function_2)] + [%(path)s:27(test_entry_return_and_stack)] + [x] + [%(path)s:14(function_3)] + [%(path)s:28(test_entry_return_and_stack)] + [x] + [%(path)s:18(function_4)] + [%(path)s:29(test_entry_return_and_stack)] + [x] + [%(path)s:22(function_5)] + [%(path)s:30(test_entry_return_and_stack)] + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = actual_result.decode("ascii") + # When compiling with '--with-pydebug' + actual_result = "".join(re.split("\[[0-9]+ refs\]", actual_result)) + + actual_result = [i for i in actual_result.split("\n") \ + if (("[" in i) and not i.endswith(" () ]"))] + actual_result = "".join(actual_result) + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_garbage_collection(self) : + dscript = """ +python$target:::gc-start,python$target:::gc-done +{ + printf("%d\t**%s(%ld)\\n", timestamp, probename, arg0); +} +""" + + dscript = dscript.replace("\r", "").replace("\n", "") + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + for i in range(10) : + actual_result = actual_result.replace(str(i), "") + expected_result = "**gc-start()**gc-done()" * \ + actual_result.count("**gc-start()**") + + self.assertEqual(actual_result, expected_result) + + def test_verify_opcodes(self) : + # Verify that we are checking: + opcodes = set(["CALL_FUNCTION", "CALL_FUNCTION_VAR", + "CALL_FUNCTION_KW", "CALL_FUNCTION_VAR_KW"]) + with open(sample, encoding="utf-8") as f : + obj = compile(f.read(), "sample", "exec") + class dump() : + def __init__(self) : + self.buf = [] + def write(self, v) : + self.buf.append(v) + + dump = dump() + stdout = sys.stdout + sys.stdout = dump + for i in obj.co_consts : + if isinstance(i, types.CodeType) and \ + (i.co_name == 'test_entry_return_and_stack') : + dis.dis(i) + sys.stdout = stdout + dump = "\n".join(dump.buf) + dump = dump.replace("\r", "").replace("\n", "").split() + for i in dump : + opcodes.discard(i) + # Are we verifying all the relevant opcodes? + self.assertEqual(set(), opcodes) # Are we verifying all opcodes? + + def test_line(self) : + dscript = """ +python$target:::line +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_line")/ +{ + printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **line*%(path)s*test_line*33 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*35 + **line*%(path)s*test_line*36 + **line*%(path)s*test_line*37 + **line*%(path)s*test_line*38 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*35 + **line*%(path)s*test_line*36 + **line*%(path)s*test_line*37 + **line*%(path)s*test_line*38 + **line*%(path)s*test_line*34 + **line*%(path)s*test_line*39 + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_instance_creation_destruction(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_instance_creation_destruction")/ +{ + self->trace = 1; +} + +python$target:::instance-new-start, +python$target:::instance-new-done, +python$target:::instance-delete-start, +python$target:::instance-delete-done +/self->trace/ +{ + printf("%%d\t**%%s* (%%s.%%s)\\n", timestamp, + probename, copyinstr(arg1), copyinstr(arg0)); +} + +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_instance_creation_destruction")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **instance-new-start*(__main__.old_style_class) + **instance-new-done*(__main__.old_style_class) + **instance-delete-start*(__main__.old_style_class) + **instance-delete-done*(__main__.old_style_class) + **instance-new-start*(__main__.new_style_class) + **instance-new-done*(__main__.new_style_class) + **instance-delete-start*(__main__.new_style_class) + **instance-delete-done*(__main__.new_style_class) + **instance-new-start*(__main__.old_style_class) + **instance-new-done*(__main__.old_style_class) + **instance-new-start*(__main__.new_style_class) + **instance-new-done*(__main__.new_style_class) + **instance-delete-start*(__main__.old_style_class) + **instance-delete-done*(__main__.old_style_class) + **instance-delete-start*(__main__.new_style_class) + **instance-delete-done*(__main__.new_style_class) + """ + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + def test_unicode_function_entry_return(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry,python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("%%d\t**%%s*%%s*%%s*%%d\\n", timestamp, + probename, copyinstr(arg0), + copyinstr(arg1), arg2); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + **function-entry*%(path)s*test_unicode_entry_return_and_stack*41 + **function-entry*%(path)s*únícódé*42 + **function-return*%(path)s*únícódé*43 + **function-return*%(path)s*test_unicode_entry_return_and_stack*44 + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = actual_result.decode("utf8") + actual_result = normalize(actual_result) + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + @unittest.skipIf(sys.platform == 'darwin', + "MacOS X doesn't support jstack()") + def test_unicode_stack(self) : + dscript = """ +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ +{ + self->trace = 1; +} +python$target:::function-entry +/(copyinstr(arg0)=="%(path)s") && (self->trace)/ +{ + printf("[x]"); + jstack(); +} +python$target:::function-return +/(copyinstr(arg0)=="%(path)s") && +(copyinstr(arg1)=="test_unicode_entry_return_and_stack")/ +{ + self->trace = 0; +} +""" %{"path":sample} + + dscript = dscript.replace("\r", "").replace("\n", "") + expected_result = """ + [x] + [%(path)s:41(test_unicode_entry_return_and_stack)] + [x] + [%(path)s:42(únícódé)] + [%(path)s:44(test_unicode_entry_return_and_stack)] + """ %{"path":sample} + + command = "%s %s" %(sys.executable, sample) + if self.optimize : + command = "%s -OO %s" %(sys.executable, sample) + actual_result, _ = subprocess.Popen(["dtrace", "-q", "-n", + dscript, + "-c", command], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() + + actual_result = actual_result.decode("utf8") + # When compiling with '--with-pydebug' + actual_result = "".join(re.split("\[[0-9]+ refs\]", actual_result)) + + actual_result = [i for i in actual_result.split("\n") \ + if (("[" in i) and not i.endswith(" () ]"))] + actual_result = "".join(actual_result) + actual_result = actual_result.replace("\r", "").replace("\n", + "").replace(" ", "") + expected_result = expected_result.replace("\r", "").replace("\n", + "").replace(" ", "") + self.assertEqual(actual_result, expected_result) + + + +# This class try to verify that dtrace probes +# are still working with optimizations enabled in the bytecode. +# +# Some tests will not actually verify it. For instance, +# source code compilation follows optimization status of +# current working Python. So, you should run the test +# both with an optimizing and a non optimizing Python. +class DTraceTestsOptimize(DTraceTestsNormal) : + def setUp(self) : + self.optimize = True + + +def test_main(): + run_unittest(DTraceTestsNormal) + run_unittest(DTraceTestsOptimize) + +if __name__ == '__main__': + test_main() + --- Lib/test/test_sys.py +++ Lib/test/test_sys.py @@ -640,6 +640,7 @@ self.assertEqual(sys.getsizeof(True, -1), size('') + self.longdigit) def test_objecttypes(self): + import dtrace # check all types defined in Objects/ size = test.support.calcobjsize vsize = test.support.calcvobjsize @@ -665,13 +666,17 @@ return inner check(get_cell().__closure__[0], size('P')) # code - check(get_cell().__code__, size('5i9Pi3P')) - check(get_cell.__code__, size('5i9Pi3P')) + if dtrace.available : + code = '5i9PiPH2P' + else : + code = '5i9Pi3P' + check(get_cell().__code__, size(code)) + check(get_cell.__code__, size(code)) def get_cell2(x): def inner(): return x return inner - check(get_cell2.__code__, size('5i9Pi3P') + 1) + check(get_cell2.__code__, size(code) + 1) # complex check(complex(0,1), size('2d')) # method_descriptor (descriptor object) --- Makefile.pre.in +++ Makefile.pre.in @@ -52,6 +52,13 @@ # Use this to make a link between python$(VERSION) and python in $(BINDIR) LN= @LN@ +DTRACE= @DTRACE@ +DFLAGS= @DFLAGS@ +DTRACEOBJS= @DTRACEOBJS@ +DTRACE_NM= @DTRACE_NM@ +DTRACE_LINKER= @DTRACE_LINKER@ + + # Portable install script (configure doesn't always guess right) INSTALL= @INSTALL@ INSTALL_PROGRAM=@INSTALL_PROGRAM@ @@ -512,7 +519,7 @@ $(AR) $(ARFLAGS) $@ $(MODOBJS) $(RANLIB) $@ -libpython$(LDVERSION).so: $(LIBRARY_OBJS) +libpython$(LDVERSION).so: $(LIBRARY_OBJS) $(DTRACEOBJS) if test $(INSTSONAME) != $(LDLIBRARY); then \ $(BLDSHARED) -Wl,-h$(INSTSONAME) -o $(INSTSONAME) $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ $(LN) -f $(INSTSONAME) $@; \ @@ -523,9 +530,8 @@ libpython3.so: libpython$(LDVERSION).so $(BLDSHARED) $(NO_AS_NEEDED) -o $@ -Wl,-h$@ $^ -libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) - $(CC) -dynamiclib -Wl,-single_module $(PY_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST); \ - +libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) $(DTRACEOBJS) + $(CC) -dynamiclib -Wl,-single_module $(PY_LDFLAGS) -undefined dynamic_lookup -Wl,-install_name,$(prefix)/lib/libpython$(LDVERSION).dylib -Wl,-compatibility_version,$(VERSION) -Wl,-current_version,$(VERSION) -o $@ $(LIBRARY_OBJS) $(DTRACEOBJS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) libpython$(VERSION).sl: $(LIBRARY_OBJS) $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) $(LDLAST) @@ -625,12 +631,18 @@ $(MODULE_OBJS) \ $(SIGNAL_OBJS) \ $(MODOBJS) \ + $(DTRACEOBJS) \ $(srcdir)/Modules/getbuildinfo.c $(CC) -c $(PY_CORE_CFLAGS) \ -DHGVERSION="\"`LC_ALL=C $(HGVERSION)`\"" \ -DHGTAG="\"`LC_ALL=C $(HGTAG)`\"" \ -DHGBRANCH="\"`LC_ALL=C $(HGBRANCH)`\"" \ -o $@ $(srcdir)/Modules/getbuildinfo.c + if test "$(DTRACEOBJS)" != "" ; then \ + $(DTRACE_LINKER) --relocatable \ + $@ $(DTRACEOBJS) -o $@.DTRACE ; \ + mv $@.DTRACE $@ ; \ + fi; Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile $(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \ @@ -760,6 +772,46 @@ Objects/typeslots.inc: $(srcdir)/Include/typeslots.h $(srcdir)/Objects/typeslots.py $(PYTHON) $(srcdir)/Objects/typeslots.py < $(srcdir)/Include/typeslots.h > Objects/typeslots.inc +Include/pydtrace.h: Include/pydtrace.d + if test "$(DTRACE)" != "" ; then \ + $(DTRACE) -o $@ $(DFLAGS) \ + -C -h -s Include/pydtrace.d ; \ + else touch $@ ; \ + fi; + +Include/pydtrace_offsets.h: $(srcdir)/Include/pydtrace_offsets.c $(srcdir)/Python/ceval.o + $(CC) $(PY_CORE_CFLAGS) -o $(srcdir)/Include/pydtrace_offsets \ + $(srcdir)/Include/pydtrace_offsets.c + $(srcdir)/Include/pydtrace_offsets.sh $(DTRACE_NM) \ + $(srcdir)/Python/ceval.o $(srcdir)/Include/pydtrace_offsets > \ + $(srcdir)/Include/pydtrace_offsets.h + +Python/ceval.o: Include/pydtrace.h +Modules/gcmodule.o: Include/pydtrace.h +Objects/typeobject.o: Include/pydtrace.h + +Python/pydtrace.o: $(srcdir)/Include/pydtrace.d $(srcdir)/Include/pydtrace_offsets.h \ + Python/ceval.o Modules/gcmodule.o Objects/typeobject.o + # We do the "touch" game to break a circular dependency between + # "Python/ceval.o" and "Include/pydtrace_offsets.h". + if test "$(DTRACE)" != "" ; then \ + touch -r Python/ceval.o Python/ceval.o.ts_dtrace ; \ + touch -r Modules/gcmodule.o Modules/gcmodule.o.ts_dtrace ; \ + touch -r Objects/typeobject.o Objects/typeobject.o.ts_dtrace ; \ + $(DTRACE) -o $@ -DPYDTRACE_STACK_HELPER \ + $(DFLAGS) $(PY_CPPFLAGS) \ + -C -G -s $(srcdir)/Include/pydtrace.d \ + Python/ceval.o Modules/gcmodule.o \ + Objects/typeobject.o; \ + touch -r Python/ceval.o.ts_dtrace Python/ceval.o ; \ + touch -r Modules/gcmodule.o.ts_dtrace Modules/gcmodule.o ; \ + touch -r Objects/typeobject.o.ts_dtrace Objects/typeobject.o ; \ + rm Python/ceval.o.ts_dtrace ; \ + rm Modules/gcmodule.o.ts_dtrace ; \ + rm Objects/typeobject.o.ts_dtrace ; \ + else touch $@ ; \ + fi; + ############################################################################ # Header files @@ -1396,6 +1448,11 @@ find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name '*.py' -exec rm -f {} ';' || true find build -name '*.py[co]' -exec rm -f {} ';' || true + rm -f Include/pydtrace.h + rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h + rm -f Python/ceval.o.ts_dtrace + rm -f Modules/gcmodule.o.ts_dtrace + rm -f Objects/typeobject.o.ts_dtrace -rm -f pybuilddir.txt -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f Modules/_testembed Modules/_freeze_importlib @@ -1426,6 +1483,11 @@ -o -name '*.orig' -o -name '*.rej' \ -o -name '*.bak' ')' \ -exec rm -f {} ';' + rm -f Include/pydtrace.h + rm -f Include/pydtrace_offsets Include/pydtrace_offsets.h + rm -f Python/ceval.o.ts_dtrace + rm -f Modules/gcmodule.o.ts_dtrace + rm -f Objects/typeobject.o.ts_dtrace # Check for smelly exported symbols (not starting with Py/_Py) smelly: all --- Modules/Setup.dist +++ Modules/Setup.dist @@ -386,3 +386,5 @@ # Another example -- the 'xxsubtype' module shows C-level subtyping in action xxsubtype xxsubtype.c + +dtrace dtracemodule.c --- /dev/null +++ Modules/dtracemodule.c @@ -0,0 +1,39 @@ +#include "Python.h" + +static PyMethodDef dtrace_methods[] = { + {NULL, NULL} /* sentinel */ +}; + + +static struct PyModuleDef dtracemodule = { + PyModuleDef_HEAD_INIT, + "dtrace", + NULL, + -1, + dtrace_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit_dtrace(void) +{ + PyObject *m, *v; + + m = PyModule_Create(&dtracemodule); + if (m) { +#ifdef WITH_DTRACE + v = Py_True; +#else + v = Py_False; +#endif + Py_INCREF(v); + if (PyModule_AddObject(m, "available", v) < 0) { + Py_DECREF(m); + return NULL; + } + } + return m; +} --- Modules/gcmodule.c +++ Modules/gcmodule.c @@ -26,6 +26,10 @@ #include "Python.h" #include "frameobject.h" /* for PyFrame_ClearFreeList */ +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + /* Get an object's GC head */ #define AS_GC(o) ((PyGC_Head *)(o)-1) @@ -841,7 +845,12 @@ /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t -collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) +#ifdef WITH_DTRACE +collect2 +#else +collect +#endif +(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) { int i; Py_ssize_t m = 0; /* # objects collected */ @@ -1000,6 +1009,49 @@ return n+m; } +#ifdef WITH_DTRACE +static void +dtrace_gc_start(int collection) +{ + PYTHON_GC_START(collection); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static void +dtrace_gc_done(Py_ssize_t value) +{ + PYTHON_GC_DONE((long) value); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static Py_ssize_t +collect(int collection, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable) +{ + Py_ssize_t value; + + if (PYTHON_GC_START_ENABLED()) + dtrace_gc_start(collection); + value = collect2(collection, n_collected, n_uncollectable); + if (PYTHON_GC_DONE_ENABLED()) + dtrace_gc_done(value); + return value; +} +#endif /* WITH_DTRACE */ + /* Invoke progress callbacks to notify clients that garbage collection * is starting or stopping */ --- Objects/codeobject.c +++ Objects/codeobject.c @@ -147,6 +147,37 @@ co->co_lnotab = lnotab; co->co_zombieframe = NULL; co->co_weakreflist = NULL; + +#ifdef WITH_DTRACE + /* + ** Cache UTF8 internally, available + ** for the pythonframe stack walker. + */ + PyUnicode_AsUTF8(filename); + PyUnicode_AsUTF8(name); + + i = PyBytes_Size(co->co_code); + co->co_linenos = PyMem_Malloc(sizeof(unsigned short) * i); + if (co->co_linenos) { + unsigned short *p = (unsigned short *)(co->co_linenos); + unsigned char *p2 = (unsigned char*)PyBytes_AsString(co->co_lnotab); + int size = PyBytes_Size(co->co_lnotab) / 2; + int i2; + unsigned short offset = 0; + + while (size) { + size -= 1; + i2 = *p2++; + i-=i2; + while (i2--) + *p++ = offset; + offset += *p2++; + } + while(i--) + *p++ = offset; + } +#endif + return co; } --- Objects/frameobject.c +++ Objects/frameobject.c @@ -714,6 +714,15 @@ f->f_lineno = code->co_firstlineno; f->f_iblock = 0; +#ifdef WITH_DTRACE + /* + ** Cache UTF8 internally, available + ** for the pythonframe stack walker. + */ + PyUnicode_AsUTF8(f->f_code->co_filename); + PyUnicode_AsUTF8(f->f_code->co_name); +#endif + _PyObject_GC_TRACK(f); return f; } --- Objects/typeobject.c +++ Objects/typeobject.c @@ -4,6 +4,10 @@ #include "frameobject.h" #include "structmember.h" +#ifdef WITH_DTRACE +#include "pydtrace.h" +#endif + #include @@ -753,8 +757,29 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems) { PyObject *obj; - const size_t size = _PyObject_VAR_SIZE(type, nitems+1); + size_t size; + +#ifdef WITH_DTRACE + PyObject *mod; + char *mod_name; + + if (PYTHON_INSTANCE_NEW_START_ENABLED()) { + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_NEW_START((char *)(type->tp_name), mod_name); + } + } +#endif + /* note that we need to add one, for the sentinel */ + size = _PyObject_VAR_SIZE(type, nitems+1); if (PyType_IS_GC(type)) obj = _PyObject_GC_Malloc(size); @@ -776,6 +801,23 @@ if (PyType_IS_GC(type)) _PyObject_GC_TRACK(obj); + +#ifdef WITH_DTRACE + if (PYTHON_INSTANCE_NEW_DONE_ENABLED()) { + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_NEW_DONE((char *)(type->tp_name), mod_name); + } + } +#endif + return obj; } @@ -896,9 +938,56 @@ return 0; } +#ifdef WITH_DTRACE +static void subtype_dealloc2(PyObject *); /* Forward declaration */ + static void subtype_dealloc(PyObject *self) { + PyObject *mod; + char *mod_name; + PyTypeObject *type; + + type = Py_TYPE(self); + Py_INCREF(type); + + if (PYTHON_INSTANCE_DELETE_START_ENABLED()) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_DELETE_START((char *)(type->tp_name), mod_name); + } + + subtype_dealloc2(self); + + if (PYTHON_INSTANCE_DELETE_DONE_ENABLED()) { + mod = PyDict_GetItemString(type->tp_dict, "__module__"); + if (mod == NULL || !PyUnicode_Check(mod)) { + mod_name = "?"; + } else { + mod_name = PyUnicode_AsUTF8(mod); + if (!mod_name) + mod_name = "?"; + } + PYTHON_INSTANCE_DELETE_DONE((char *)(type->tp_name), mod_name); + } + Py_DECREF(type); +} +#endif + +static void +#ifdef WITH_DTRACE +subtype_dealloc2 +#else +subtype_dealloc +#endif +(PyObject *self) +{ PyTypeObject *type, *base; destructor basedealloc; PyThreadState *tstate = PyThreadState_GET(); --- Python/ceval.c +++ Python/ceval.c @@ -18,6 +18,13 @@ #include +#ifdef WITH_DTRACE +#include "pydtrace.h" +#else +/* We can not have conditional compilation inside macros */ +#define PYTHON_LINE_ENABLED() (0) +#endif + #ifndef WITH_TSC #define READ_TIMESTAMP(var) @@ -119,6 +126,12 @@ #define CALL_FLAG_VAR 1 #define CALL_FLAG_KW 2 +#ifdef WITH_DTRACE +static void maybe_dtrace_line(PyFrameObject *frame, + int *instr_lb, int *instr_ub, + int *instr_prev); +#endif + #ifdef LLTRACE static int lltrace; static int prtrace(PyObject *, char *); @@ -776,6 +789,49 @@ NULL, NULL); } +#ifdef WITH_DTRACE +static void +dtrace_entry(PyFrameObject *f) +{ + char *filename; + char *name; + int lineno; + + filename = PyUnicode_AsUTF8(f->f_code->co_filename); + name = PyUnicode_AsUTF8(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + PYTHON_FUNCTION_ENTRY(filename, name, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} + +static void +dtrace_return(PyFrameObject *f) +{ + char *filename; + char *name; + int lineno; + + filename = PyUnicode_AsUTF8(f->f_code->co_filename); + name = PyUnicode_AsUTF8(f->f_code->co_name); + lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + PYTHON_FUNCTION_RETURN(filename, name, lineno); + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} +#endif /* Interpreter main loop */ @@ -787,8 +843,16 @@ return PyEval_EvalFrameEx(f, 0); } + PyObject * +#if defined(WITH_DTRACE) && defined(__amd64) +PyEval_EvalFrameExReal(long a1, long a2, long a3, long a4, long a5, long a6, + PyFrameObject *f, int throwflag) +#elif defined(WITH_DTRACE) && defined(__sparc) +PyEval_EvalFrameExReal(PyFrameObject *f, int throwflag) +#else PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +#endif { #ifdef DXPAIRS int lastopcode = 0; @@ -915,7 +979,7 @@ #ifdef LLTRACE #define FAST_DISPATCH() \ { \ - if (!lltrace && !_Py_TracingPossible) { \ + if (!lltrace && !_Py_TracingPossible && !PYTHON_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ goto *opcode_targets[*next_instr++]; \ } \ @@ -924,7 +988,7 @@ #else #define FAST_DISPATCH() \ { \ - if (!_Py_TracingPossible) { \ + if (!_Py_TracingPossible && !PYTHON_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ goto *opcode_targets[*next_instr++]; \ } \ @@ -1160,6 +1224,11 @@ } } +#ifdef WITH_DTRACE + if (PYTHON_FUNCTION_ENTRY_ENABLED()) + dtrace_entry(f); +#endif + co = f->f_code; names = co->co_names; consts = co->co_consts; @@ -1347,6 +1416,12 @@ /* Main switch on opcode */ READ_TIMESTAMP(inst0); +#ifdef WITH_DTRACE + if (PYTHON_LINE_ENABLED()) { + maybe_dtrace_line(f, &instr_lb, &instr_ub, &instr_prev); + } +#endif + switch (opcode) { /* BEWARE! @@ -3077,6 +3152,10 @@ /* pop frame */ exit_eval_frame: +#ifdef WITH_DTRACE + if (PYTHON_FUNCTION_RETURN_ENABLED()) + dtrace_return(f); +#endif Py_LeaveRecursiveCall(); tstate->frame = f->f_back; @@ -3773,6 +3852,57 @@ return result; } +/* + * These shenanigans look like utter madness, but what we're actually doing is + * making sure that the ustack helper will see the PyFrameObject pointer on the + * stack. We have two tricky cases: + * + * amd64 + * + * We use up the six registers for passing arguments, meaning the call can't + * use a register for passing 'f', and has to push it onto the stack in a known + * location. + * + * And how does "throwflag" figure in to this? -PN + * + * SPARC + * + * Here the problem is that (on 32-bit) the compiler is re-using %i0 before + * some calls inside PyEval_EvalFrameReal(), which means that when it's saved, + * it's just some junk value rather than the real first argument. So, instead, + * we trace our proxy PyEval_EvalFrame(), where we 'know' the compiler won't + * decide to re-use %i0. We also need to defeat optimization of our proxy. + */ + +#if defined(WITH_DTRACE) + +#if defined(__amd64) + +PyObject * +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + volatile PyObject *f2; + f2 = PyEval_EvalFrameExReal(0, 0, 0, 0, 0, 0, f, throwflag); + return (PyObject *)f2; +} + +#elif defined(__sparc) + +volatile int dummy; + +PyObject * +PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) +{ + volatile PyObject *f2; + f2 = PyEval_EvalFrameExReal(f, throwflag); + dummy = f->ob_refcnt; + return (PyObject *)f2; +} + +#endif +#endif + + PyObject * _PyEval_CallTracing(PyObject *func, PyObject *args) { @@ -3791,6 +3921,51 @@ return result; } +#ifdef WITH_DTRACE +/* See Objects/lnotab_notes.txt for a description of how tracing works. */ +/* Practically a ripoff of "maybe_call_line_trace" function. */ +static void +maybe_dtrace_line(PyFrameObject *frame, + int *instr_lb, int *instr_ub, int *instr_prev) +{ + int line = frame->f_lineno; + char *co_filename, *co_name; + + /* If the last instruction executed isn't in the current + instruction window, reset the window. + */ + if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) { + PyAddrPair bounds; + line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, + &bounds); + *instr_lb = bounds.ap_lower; + *instr_ub = bounds.ap_upper; + } + /* If the last instruction falls at the start of a line or if + it represents a jump backwards, update the frame's line + number and call the trace function. */ + if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) { + frame->f_lineno = line; + co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename); + if (!co_filename) + co_filename = "?"; + co_name = PyUnicode_AsUTF8(frame->f_code->co_name); + if (!co_name) + co_name = "?"; + PYTHON_LINE(co_filename, co_name, line); + } + *instr_prev = frame->f_lasti; + + /* + * Currently a USDT tail-call will not receive the correct arguments. + * Disable the tail call here. + */ +#if defined(__sparc) + asm("nop"); +#endif +} +#endif + /* See Objects/lnotab_notes.txt for a description of how tracing works. */ static int maybe_call_line_trace(Py_tracefunc func, PyObject *obj, --- configure +++ configure @@ -639,6 +639,11 @@ MACHDEP_OBJS DYNLOADFILE DLINCLDIR +DTRACEOBJS +DTRACE_LINKER +DTRACE_NM +DFLAGS +DTRACE THREADOBJ LDLAST USE_THREAD_MODULE @@ -806,6 +811,7 @@ with_tsc with_pymalloc with_valgrind +with_dtrace with_fpectl with_libm with_libc @@ -1486,6 +1492,7 @@ --with(out)-tsc enable/disable timestamp counter profile --with(out)-pymalloc disable/enable specialized mallocs --with-valgrind Enable Valgrind support + --with(out)-dtrace disable/enable dtrace support --with-fpectl enable SIGFPE catching --with-libm=STRING math library --with-libc=STRING C library @@ -10233,6 +10240,181 @@ OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT" fi +# Check for dtrace support +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dtrace" >&5 +$as_echo_n "checking for --with-dtrace... " >&6; } + +# Check whether --with-dtrace was given. +if test "${with_dtrace+set}" = set; then : + withval=$with_dtrace; +else + with_dtrace=no +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_dtrace" >&5 +$as_echo "$with_dtrace" >&6; } + + + + + +DTRACE= +DFLAGS= +if test "$with_dtrace" = "yes" +then + DTRACE_NM=OTHER + DTRACE_LINKER=ld + DTRACEOBJS="Python/pydtrace.o" + # Extract the first word of "dtrace", so it can be a program name with args. +set dummy dtrace; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/sbin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DTRACE" && ac_cv_path_DTRACE="dtrace" + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + if test "$ac_cv_sizeof_long" -eq 8 + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + sys_release="$ac_sys_release" + if test $ac_sys_system = "SunOS" + then + if test $sys_release="5.11" + then + sys_release=`uname -v` + fi + fi + case $ac_sys_system/$sys_release in + SunOS/5.10) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/11.*) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/*) + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + Darwin/*) + DTRACEOBJS="" # Not needed in Mac + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + + if test "$ac_cv_sizeof_long" -eq 8 + then + DFLAGS="-arch i386" + else + DFLAGS="-arch x86_64" + fi + ;; + esac + +$as_echo "#define WITH_DTRACE 1" >>confdefs.h + +fi + + + # -I${DLINCLDIR} is added to the compile rule for importdl.o DLINCLDIR=. --- configure.ac +++ configure.ac @@ -2764,6 +2764,69 @@ OPT="-DDYNAMIC_ANNOTATIONS_ENABLED=1 $OPT" fi +# Check for dtrace support +AC_MSG_CHECKING(for --with-dtrace) +AC_ARG_WITH(dtrace, + AC_HELP_STRING(--with(out)-dtrace, disable/enable dtrace support),, + with_dtrace=no) +AC_MSG_RESULT($with_dtrace) + +AC_SUBST(DTRACE) +AC_SUBST(DFLAGS) +AC_SUBST(DTRACE_NM) +AC_SUBST(DTRACE_LINKER) +DTRACE= +DFLAGS= +if test "$with_dtrace" = "yes" +then + DTRACE_NM=OTHER + DTRACE_LINKER=ld + DTRACEOBJS="Python/pydtrace.o" + AC_PATH_PROG(DTRACE, [dtrace], [dtrace], [$PATH$PATH_SEPARATOR/usr/sbin]) + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-64" + else + DFLAGS="-32" + fi + sys_release="$ac_sys_release" + if test $ac_sys_system = "SunOS" + then + if test $sys_release="5.11" + then + sys_release=`uname -v` + fi + fi + case $ac_sys_system/$sys_release in + SunOS/5.10) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/11.*) + DTRACE_NM=SOLARIS + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + SunOS/*) + DTRACE_LINKER=/usr/ccs/bin/ld + ;; + Darwin/*) + DTRACEOBJS="" # Not needed in Mac + AC_CHECK_SIZEOF([long]) + if [test "$ac_cv_sizeof_long" -eq 8] + then + DFLAGS="-arch i386" + else + DFLAGS="-arch x86_64" + fi + ;; + esac + AC_DEFINE(WITH_DTRACE, 1, + [Define if you want to compile in Dtrace support]) +fi + +AC_SUBST(DTRACEOBJS) + # -I${DLINCLDIR} is added to the compile rule for importdl.o AC_SUBST(DLINCLDIR) DLINCLDIR=. --- pyconfig.h.in +++ pyconfig.h.in @@ -1306,6 +1306,9 @@ /* Define if you want documentation strings in extension modules */ #undef WITH_DOC_STRINGS +/* Define if you want to compile in Dtrace support */ +#undef WITH_DTRACE + /* Define if you want to use the new-style (Openstep, Rhapsody, MacOS) dynamic linker (dyld) instead of the old-style (NextStep) dynamic linker (rld). Dyld is necessary to support frameworks. */ --- setup.py +++ setup.py @@ -627,6 +627,9 @@ # syslog daemon interface exts.append( Extension('syslog', ['syslogmodule.c']) ) + # jcea DTRACE probes + exts.append( Extension('dtrace', ['dtracemodule.c']) ) + # # Here ends the simple stuff. From here on, modules need certain # libraries, are platform-specific, or present other surprises. PKYE@% 7pythonz/patches/osx/python33/stackless-335-compile.diff --- Stackless/module/channelobject.c +++ Stackless/module/channelobject.c @@ -624,8 +624,6 @@ PyChannel_SendException_M(PyChannelObjec return PyStackless_CallCMethod_Main(&def, (PyObject *) self, "OO", klass, args); } -static CHANNEL_SEND_EXCEPTION_HEAD(impl_channel_send_exception); - static PyObject * impl_channel_send_exception(PyChannelObject *self, PyObject *klass, PyObject *args) { @@ -1009,7 +1007,6 @@ channel_send_sequence(PyChannelObject *s { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); - /*unused: PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type;*/ PyObject *it; PyCFrameObject *f; --- Stackless/module/scheduling.c +++ Stackless/module/scheduling.c @@ -449,8 +449,7 @@ int slp_schedule_callback(PyTaskletObject *prev, PyTaskletObject *next) { PyObject *args; - PyThreadState *ts = PyThreadState_GET(); - + if (prev == NULL) prev = (PyTaskletObject *)Py_None; if (next == NULL) next = (PyTaskletObject *)Py_None; args = Py_BuildValue("(OO)", prev, next); @@ -1267,7 +1266,6 @@ schedule_task_destruct(PyObject **retval * field to help us with that, someone else with decref it. */ PyThreadState *ts = PyThreadState_GET(); - PyObject *tmpval=NULL; int fail = 0; /* we should have no nesting level */ --- Stackless/module/taskletobject.c +++ Stackless/module/taskletobject.c @@ -611,8 +611,7 @@ static int impl_tasklet_remove(PyTaskletObject *task) { PyThreadState *ts = PyThreadState_GET(); - PyTaskletObject *hold = ts->st.current; - + assert(PyTasklet_Check(task)); if (ts->st.main == NULL) return PyTasklet_Remove_M(task); assert(ts->st.current != NULL); @@ -737,6 +736,9 @@ PyTasklet_Run(PyTaskletObject *task) } static PyObject * +PyTasklet_Switch_M(PyTaskletObject *task); + +static PyObject * impl_tasklet_run_remove(PyTaskletObject *task, int remove) { STACKLESS_GETARG(); @@ -746,8 +748,13 @@ impl_tasklet_run_remove(PyTaskletObject PyTaskletObject *prev = ts->st.current; assert(PyTasklet_Check(task)); - if (ts->st.main == NULL) - return PyTasklet_Run_M(task); + if (ts->st.main == NULL) { + if (!remove) + return PyTasklet_Run_M(task); + else + return PyTasklet_Switch_M(task); + } + /* we always call impl_tasklet_insert, so we must * also uninsert in case of failure PK74Hlz(+pythonz_bd-1.11.2.dist-info/DESCRIPTION.rstpythonz: a Python installation manager ====================================== Overview -------- pythonz is a program to automate the building and installation of Python in the users $HOME. This is a fork of the original project, `pythonbrew `_. The original project seems to be unmaintained, and it also has some extra features which I don't really need, so I made this for to make something a bit simpler that works for *me*. You may also find it useful. CPython, Stackless, PyPy and Jython are supported. Installation ------------ The recommended way to download and install pythonz is to run these statements in your shell:: curl -kL https://raw.github.com/saghul/pythonz/master/pythonz-install | bash or:: fetch -o - https://raw.github.com/saghul/pythonz/master/pythonz-install | bash After that, pythonz installs itself to ``~/.pythonz``. Please add the following line to the end of your ``~/.bashrc``:: [[ -s $HOME/.pythonz/etc/bashrc ]] && source $HOME/.pythonz/etc/bashrc If you need to install pythonz into somewhere else, you can do that by setting a ``PYTHONZ_ROOT`` environment variable:: export PYTHONZ_ROOT=/path/to/pythonz curl -kLO https://raw.github.com/saghul/pythonz/master/pythonz-install chmod +x pythonz-install ./pythonz-install For Systemwide (Multi-User) installation ---------------------------------------- If the install script is run as root, pythonz will automatically install into ``/usr/local/pythonz``. pythonz will be automatically configured for every user on the system if you install it as root. After installing it, where you would normally use `sudo`, non-root users will need to use `sudo-pythonz`:: sudo-pythonz install 2.7.3 Before installing Pythons via Pythonz ------------------------------------- You might want to install some optional dependencies, for functionality that is often expected to be included in a Python build (it can be a bummer to discover these missing and have to rebuild your python setup). These include the following, ordered by (very roughly guessed) probability that you will need them:: Debian family (Ubuntu...) ^^^^^^^^^^^^^^^^^^^^^^^^^ :: sudo apt-get install build-essential zlib1g-dev libbz2-dev libssl-dev libreadline-dev libncurses5-dev libsqlite3-dev libgdbm-dev libdb-dev libexpat-dev libpcap-dev liblzma-dev libpcre3-dev If you need tkinter support, add **tk-dev**. RPM family (CentOS, RHEL...) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: yum groupinstall "Development tools" yum install zlib-devel bzip2-devel openssl-devel readline-devel ncurses-devel sqlite-devel gdbm-devel db4-devel expat-devel libpcap-devel xz-devel pcre-devel If you need tkinter support, add **tk-devel**. OSX ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: xcode-select --install Usage ----- :: pythonz command [options] version See the available commands ^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz help To get help on each individual command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz help Install some pythons ^^^^^^^^^^^^^^^^^^^^ :: pythonz install 2.7.3 pythonz install -t stackless 2.7.2 pythonz install -t jython 2.5.2 pythonz install -t pypy --url https://bitbucket.org/pypy/pypy/downloads/pypy-1.8-osx64.tar.bz2 1.8 pythonz install --verbose 2.7.2 pythonz install --configure="CC=gcc_4.1" 2.7.2 pythonz install --url http://www.python.org/ftp/python/2.7/Python-2.7.2.tgz 2.7.2 pythonz install --file /path/to/Python-2.7.2.tgz 2.7.2 pythonz install 2.7.3 3.2.3 pythonz install -t pypy3 2.3.1 List the installed pythons ^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz list List all the available python versions for installing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz list -a List all the available jython versions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz list -a -t jython Uninstall the specified python ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz uninstall 2.7.3 pythonz uninstall -t stackless 3.2.2 Remove stale source folders and archives ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz cleanup Upgrade pythonz to the latest version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz update Check the installed pythonz version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz version Print the path to the interpreter of a given version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz locate 2.7.7 Recommended way to use a pythonz-installed version of Python ------------------------------------------------------------ For Python <= 3.2 ^^^^^^^^^^^^^^^^^ Use `virtualenv`, e.g.:: mkvirtualenv -p $(pythonz locate 2.7.3) python2.7.3 For more information about virtualenv, checkout `its documentation `_. For Python >= 3.3 ^^^^^^^^^^^^^^^^^ Use `pyvenv` directly from Python, e.g.:: /usr/local/pythonz/pythons/CPython-3.4.1/bin/pyvenv pyvenv For more information about pyvenv, checkout `its documentation `_. DTrace support -------------- CPython versions 2.7.6 and 3.3.4 can be built with DTrace suport. Patches adding support for DTrace have been taken from `this page `_ by Jesús Cea. Building Python with DTrace support:: pythonz install --configure="--with-dtrace" 2.7.6 PK74HhDY^^,pythonz_bd-1.11.2.dist-info/entry_points.txt[console_scripts] pythonz = pythonz:main pythonz_install = pythonz.installer:install_pythonz PK74H, )))pythonz_bd-1.11.2.dist-info/metadata.json{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Build Tools", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3"], "extensions": {"python.commands": {"wrap_console": {"pythonz": "pythonz:main", "pythonz_install": "pythonz.installer:install_pythonz"}}, "python.details": {"contacts": [{"email": "saghul@gmail.com", "name": "saghul", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/berdario/pythonz/tree/bd"}}, "python.exports": {"console_scripts": {"pythonz": "pythonz:main", "pythonz_install": "pythonz.installer:install_pythonz"}}}, "extras": [], "generator": "bdist_wheel (0.26.0)", "license": "MIT", "metadata_version": "2.0", "name": "pythonz-bd", "run_requires": [{"environment": "python_version==\"3.5\"", "requires": ["resumable-urlretrieve"]}, {"environment": "python_version==\"3.6\"", "requires": ["resumable-urlretrieve"]}, {"environment": "python_version==\"3.7\"", "requires": ["resumable-urlretrieve"]}, {"environment": "python_version==\"3.8\"", "requires": ["resumable-urlretrieve"]}, {"environment": "python_version==\"3.9\"", "requires": ["resumable-urlretrieve"]}], "summary": "Manage python installations in your system, berdario's shallow fork", "version": "1.11.2"}PK74HGz)pythonz_bd-1.11.2.dist-info/top_level.txtpythonz PK74H''\\!pythonz_bd-1.11.2.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py2-none-any PK74HG@II$pythonz_bd-1.11.2.dist-info/METADATAMetadata-Version: 2.0 Name: pythonz-bd Version: 1.11.2 Summary: Manage python installations in your system, berdario's shallow fork Home-page: https://github.com/berdario/pythonz/tree/bd Author: saghul Author-email: saghul@gmail.com License: MIT Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Topic :: Software Development :: Build Tools Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.1 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Requires-Dist: resumable-urlretrieve; python_version=="3.5" Requires-Dist: resumable-urlretrieve; python_version=="3.6" Requires-Dist: resumable-urlretrieve; python_version=="3.7" Requires-Dist: resumable-urlretrieve; python_version=="3.8" Requires-Dist: resumable-urlretrieve; python_version=="3.9" pythonz: a Python installation manager ====================================== Overview -------- pythonz is a program to automate the building and installation of Python in the users $HOME. This is a fork of the original project, `pythonbrew `_. The original project seems to be unmaintained, and it also has some extra features which I don't really need, so I made this for to make something a bit simpler that works for *me*. You may also find it useful. CPython, Stackless, PyPy and Jython are supported. Installation ------------ The recommended way to download and install pythonz is to run these statements in your shell:: curl -kL https://raw.github.com/saghul/pythonz/master/pythonz-install | bash or:: fetch -o - https://raw.github.com/saghul/pythonz/master/pythonz-install | bash After that, pythonz installs itself to ``~/.pythonz``. Please add the following line to the end of your ``~/.bashrc``:: [[ -s $HOME/.pythonz/etc/bashrc ]] && source $HOME/.pythonz/etc/bashrc If you need to install pythonz into somewhere else, you can do that by setting a ``PYTHONZ_ROOT`` environment variable:: export PYTHONZ_ROOT=/path/to/pythonz curl -kLO https://raw.github.com/saghul/pythonz/master/pythonz-install chmod +x pythonz-install ./pythonz-install For Systemwide (Multi-User) installation ---------------------------------------- If the install script is run as root, pythonz will automatically install into ``/usr/local/pythonz``. pythonz will be automatically configured for every user on the system if you install it as root. After installing it, where you would normally use `sudo`, non-root users will need to use `sudo-pythonz`:: sudo-pythonz install 2.7.3 Before installing Pythons via Pythonz ------------------------------------- You might want to install some optional dependencies, for functionality that is often expected to be included in a Python build (it can be a bummer to discover these missing and have to rebuild your python setup). These include the following, ordered by (very roughly guessed) probability that you will need them:: Debian family (Ubuntu...) ^^^^^^^^^^^^^^^^^^^^^^^^^ :: sudo apt-get install build-essential zlib1g-dev libbz2-dev libssl-dev libreadline-dev libncurses5-dev libsqlite3-dev libgdbm-dev libdb-dev libexpat-dev libpcap-dev liblzma-dev libpcre3-dev If you need tkinter support, add **tk-dev**. RPM family (CentOS, RHEL...) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: yum groupinstall "Development tools" yum install zlib-devel bzip2-devel openssl-devel readline-devel ncurses-devel sqlite-devel gdbm-devel db4-devel expat-devel libpcap-devel xz-devel pcre-devel If you need tkinter support, add **tk-devel**. OSX ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: xcode-select --install Usage ----- :: pythonz command [options] version See the available commands ^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz help To get help on each individual command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz help Install some pythons ^^^^^^^^^^^^^^^^^^^^ :: pythonz install 2.7.3 pythonz install -t stackless 2.7.2 pythonz install -t jython 2.5.2 pythonz install -t pypy --url https://bitbucket.org/pypy/pypy/downloads/pypy-1.8-osx64.tar.bz2 1.8 pythonz install --verbose 2.7.2 pythonz install --configure="CC=gcc_4.1" 2.7.2 pythonz install --url http://www.python.org/ftp/python/2.7/Python-2.7.2.tgz 2.7.2 pythonz install --file /path/to/Python-2.7.2.tgz 2.7.2 pythonz install 2.7.3 3.2.3 pythonz install -t pypy3 2.3.1 List the installed pythons ^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz list List all the available python versions for installing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz list -a List all the available jython versions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz list -a -t jython Uninstall the specified python ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz uninstall 2.7.3 pythonz uninstall -t stackless 3.2.2 Remove stale source folders and archives ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz cleanup Upgrade pythonz to the latest version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz update Check the installed pythonz version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz version Print the path to the interpreter of a given version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: pythonz locate 2.7.7 Recommended way to use a pythonz-installed version of Python ------------------------------------------------------------ For Python <= 3.2 ^^^^^^^^^^^^^^^^^ Use `virtualenv`, e.g.:: mkvirtualenv -p $(pythonz locate 2.7.3) python2.7.3 For more information about virtualenv, checkout `its documentation `_. For Python >= 3.3 ^^^^^^^^^^^^^^^^^ Use `pyvenv` directly from Python, e.g.:: /usr/local/pythonz/pythons/CPython-3.4.1/bin/pyvenv pyvenv For more information about pyvenv, checkout `its documentation `_. DTrace support -------------- CPython versions 2.7.6 and 3.3.4 can be built with DTrace suport. Patches adding support for DTrace have been taken from `this page `_ by Jesús Cea. Building Python with DTrace support:: pythonz install --configure="--with-dtrace" 2.7.6 PK74H}[|!!"pythonz_bd-1.11.2.dist-info/RECORDpythonz/__init__.py,sha256=eQx96gXnCpEalMXcOXmEdGFoG89BkJYCYhUrMkq3wAA,990 pythonz/__main__.py,sha256=YGwk2kJvX0LUynWTCY2LTHszlDi-dh5K9UKaHtYER38,109 pythonz/define.py,sha256=wWaMrx0MV6pSHrTyU9_pf3Tw6MUWNTzYsSbsF2gY8nQ,1444 pythonz/downloader.py,sha256=aexZcRc0W3Rlnm6ySUJ4xsq1m0QGdZM5kbeYnIPe5Fk,3649 pythonz/log.py,sha256=8EhBIWed9q-qYVIMZXooMVoO3qBDCc__XKOf1FMvJNQ,1188 pythonz/util.py,sha256=nrJmrF6S4lR6JCUFbpMK7UxWXhwGdssiSewvDwR5Kzs,12021 pythonz/version.py,sha256=Byc51Jq2o4CFlz4coW7xCT_Q6h1-kanNX5Wui_yLi_8,24 pythonz/commands/__init__.py,sha256=yZF02Q5O1Sx20cDf4g6NAA4_LhzZg6qKLpPNPZhsWbE,677 pythonz/commands/cleanup.py,sha256=tR0o2memp65JaesWm6ScR25z-MLIDW2qayN6LydksoA,868 pythonz/commands/help.py,sha256=9gNkMPfvqcxDPTX639BZVLtkbn_hoPnoFZ4S38ci6-M,902 pythonz/commands/install.py,sha256=INgQYV20ruudtlHjAQF_FqTB35Q2BSlf2r3RXXJj5IE,3380 pythonz/commands/list.py,sha256=eTmwJAUpqaZw3yq82BUgNn1ZTzFIiCt3my45AE6CD78,2281 pythonz/commands/locate.py,sha256=D9ZSEXU4entEJ47R9nnBwGCGwr2X1b99LqZntVSk7p4,1272 pythonz/commands/uninstall.py,sha256=C1_S-oIPLzcb6lg1whgtmLUrDjx70ZO5iLccwJ6z5LE,1084 pythonz/commands/update.py,sha256=0WcpAm3m-KqkBZ7GEM0Q82k87dw2ax_0T4jmkGbbEgE,1683 pythonz/commands/version.py,sha256=KpLD45rTOX-ozMHAoGTqLv4Z8QjdTFtHmff59XLDvgE,306 pythonz/etc/bashrc,sha256=qhpdjS-Y5VXvyjviXgA1Y6d9RQ097IshiHSSrEpioD4,1543 pythonz/etc/pythonz.fish,sha256=TMsWzQC-8kt-pPyxCweMeqUmXzO4BsocipEwNsTbZ1Y,888 pythonz/etc/bash_completion.d/pythonz_completion.sh,sha256=CJLaiGJ2zhDb0hJ4QA03tLD_1p0CNiM6zRV6Q9nOFsU,4280 pythonz/installer/__init__.py,sha256=_gUL3aWWMsvCyG29aLDRo8Q6yN15EvSCf-6EqnGgjJk,1444 pythonz/installer/pythoninstaller.py,sha256=rLBesu39SJsLzKKtxIOuRhIiuq3bnMZ1mgPAikjhwB4,24206 pythonz/installer/pythonzinstaller.py,sha256=HKXJxvuXtS0H3eoiIrRSK45s-4_DhBygECkaVjMr-Mw,3806 pythonz/installer/versions.py,sha256=amoP1nEhsgsjJr2spgBDmisB058bZqaqKEwhw4NoVRk,11870 pythonz/patches/all/common/patch-setup.py.diff,sha256=LghjKPKZPTYBSDIKUdgZ3Co9avCI3oAo3aUbJlTKWkQ,1862 pythonz/patches/all/python24/patch-setup.py.diff,sha256=uPcQDIpUZcSCH5WOlfNhCP7mP8WY1vVgRnXK_zpbjuE,1873 pythonz/patches/all/python25/patch-setup.py.diff,sha256=uPcQDIpUZcSCH5WOlfNhCP7mP8WY1vVgRnXK_zpbjuE,1873 pythonz/patches/all/python25/patch-svnversion.patch,sha256=IZKKctJ0Ue5MLzlyVY0_gDa9TGYQAZH9k1Phj9HJqpI,1270 pythonz/patches/all/python26/patch-nosslv2-1.diff,sha256=iyDO9fmeFKVj4QV0wnT-kQ1_KJNyRcYfJiy2y7DVJxM,5201 pythonz/patches/all/python26/patch-nosslv2-2.diff,sha256=QjIwhzFzw4ilZNbTAGU0OV6TgIt_yMoWrbnViU2U7p4,5257 pythonz/patches/all/python26/patch-nosslv2-3.diff,sha256=iGcV8Uupxj8uXHnExt8AQwTTqIcgqnz3Ha0EFd5VvjY,5262 pythonz/patches/all/python30/patch-nosslv2.diff,sha256=3c85HsJrzQw6cgdSgFVouSPD2yq3C8FRTrMHbej9z2I,5214 pythonz/patches/all/python30/patch-setup.py.diff,sha256=dUWugBZn_8U5jmY2r63qquayO6Aerh-msXivXfN2Se8,1856 pythonz/patches/all/python32/patch-setup.py.diff,sha256=VczZ2pGTkewvwfT8naU_Tn97WUJFDHlTmo_WxiVoVPA,1648 pythonz/patches/osx/python24/patch-Include-pyport.h,sha256=_vWyjGj3hAjjh7Al3JBsO5z9uxQHFeqg1uXcvsQ699U,1255 pythonz/patches/osx/python24/patch-Lib-cgi.py.diff,sha256=WjaZ_SjqcvawSQydCXObm02DOttl7wEp0U3gQQW92Ug,808 pythonz/patches/osx/python24/patch-Lib-site.py.diff,sha256=tfYnXsgR3YC3XvdUYoYjvoRfjOF_Jiek-lliLaalfIw,550 pythonz/patches/osx/python24/patch-Makefile.pre.in,sha256=yYl1TJrYwU7Ho0bIK8VsdpIrO5-0y8_q-CrUBfo2N9Y,345 pythonz/patches/osx/python24/patch-configure-badcflags.diff,sha256=K5ENj0mgKd6tKG7cxWN2dZIZ2VI37GWTgGnx52Frgfo,562 pythonz/patches/osx/python24/patch-macosmodule.diff,sha256=Quywu2DQPDET4XLSzcGqBkoxZZrfnnFhhWWQW2_fsvc,10267 pythonz/patches/osx/python24/patch-mactoolboxglue.diff,sha256=I-bHQXRwghlHITefpT6mE0hN57AtgafcpeKpmmEeKTU,733 pythonz/patches/osx/python24/patch-pymactoolbox.diff,sha256=etcR5246P0fJhN5z7Y-wXfS8Vd_iLwo_WTXpwx3JbSU,585 pythonz/patches/osx/python24/patch240-Mac-OSX-Makefile.in,sha256=JpzBXWysct-fqJZYxgLfJ1q8UgQUPNcejfLtUmUXAjQ,683 pythonz/patches/osx/python24/patch240-configure,sha256=n4vUDsni2S10geXeUvwx-XVHfKrUUEdhKkbbHBpC024,1348 pythonz/patches/osx/python24/patch240-gestaltmodule.c.diff,sha256=CNpdcMcLMwyMc2eZYIMAMI9H5wvwyE1DDcMaeK6dG-M,318 pythonz/patches/osx/python24/patch240-setup.py.diff,sha256=14sIlEWh0DfejUv3PFfYUxdE0PMFaMA_rjW_CJYdwNM,2217 pythonz/patches/osx/python24/patch240-sysconfig.py.diff,sha256=H6bHHpPd6HAdTB3SzWqAP9N1fOfiuszBfzZO_MyOOQQ,660 pythonz/patches/osx/python24/patch241-configure,sha256=XHxLsgHIhpnW0AWbs-d0k3cM4fQEMAcu8xq5_0nbc70,1005 pythonz/patches/osx/python24/patch244-Mac-OSX-Makefile.in,sha256=_AyaVxtGxxSqOotJ95qxZGXFin2vXGUhbQrHzrQAmvU,721 pythonz/patches/osx/python24/patch244-configure,sha256=JV6yTRGxtcSrYwh_KlfGa2gN0LBkyD7qfs6GdxB7bYk,1122 pythonz/patches/osx/python24/patch244-gestaltmodule.c.diff,sha256=Gg3_P5YJGry-MYBUwJOUpXOMK0nS4Ke0OUjZSL7W-Eg,348 pythonz/patches/osx/python24/patch244-setup.py.diff,sha256=3bYl09dj2KoeNF8NGOHRFuO96V2XUdufVD6mNy5in0k,2219 pythonz/patches/osx/python25/_localemodule.c.ed,sha256=A5UQ8Pv-Gy7CUSxESYwgOt9nIJg5tbLg8OCekyM1M4E,30 pythonz/patches/osx/python25/locale.py.ed,sha256=cVQM_ksBYovV5jxhvV2oP-qX9k1XyxtVs0Gtp9A5ako,20 pythonz/patches/osx/python25/patch-64bit.diff,sha256=A3QJGyFCIB9yqUm909_qkOlUIwZi01vejzC_zhbcHsM,37004 pythonz/patches/osx/python25/patch-Lib-cgi.py.diff,sha256=bGB6czgLmtXInXhJzW65l-KnXLjaK-tzZbtC0721pY8,808 pythonz/patches/osx/python25/patch-Lib-distutils-dist.py.diff,sha256=KXgv8OASsZKAgPGDYAKEVkdNZKNsGBZKwKGTvB4EV2M,2050 pythonz/patches/osx/python25/patch-Makefile.pre.in.diff,sha256=KNqUXtJ8JkJOf5Dqp9iGBE4kdbiWCLMboK0IAUX2rUs,1449 pythonz/patches/osx/python25/patch-configure-arch_only.diff,sha256=LZCT6vTku5F6SvgU3Dsw3My7rEHOZq77YjYPCosrTJc,941 pythonz/patches/osx/python25/patch-configure-badcflags.diff,sha256=0Gft8GAvzCo4eBr-AIjxZum3SzpuxMP3r3Sru2BSVQM,460 pythonz/patches/osx/python25/patch-gestaltmodule.c.diff,sha256=GjXHDXcsMss438Jx9yZbQvPNvDeA4pa63BtVid0fkPQ,554 pythonz/patches/osx/python25/patch-pyconfig.h.in.diff,sha256=qTQGuajXfTeDyDkHRmV2hNUJB79z40KJqcGicC97CIY,396 pythonz/patches/osx/python25/patch250-setup.py.diff,sha256=GKZ3xEl24eMw28ygLddTA4ZkFKtBorfumbiKBkjaGL4,3711 pythonz/patches/osx/python25/patch251-setup.py.diff,sha256=u1Z8zpc6-J7VNkxeiZdHfywR4AsGHpX08zxei44J8CE,3711 pythonz/patches/osx/python25/patch252-setup.py.diff,sha256=s0NMa6cGyVe4Zs6SJ-zWLgBK5Bb1zcLeAZYN5-Fsmq8,3814 pythonz/patches/osx/python26/_localemodule.c.ed,sha256=0zU8fW_Nw0Xr64lm2nQzqi_a56K_qoP5lj9iNsdK72g,31 pythonz/patches/osx/python26/locale.py.ed,sha256=ATSE_TSUtOLKlGrfAqNSYxkuTRH0n9kI4wUh6Ao8BX4,21 pythonz/patches/osx/python26/patch-Lib-cgi.py.diff,sha256=ktHhxlzevIHdtUkfvenntAupYprnCAUXcWMSRpjTo7o,808 pythonz/patches/osx/python26/patch-Lib-ctypes-macholib-dyld.py.diff,sha256=lX3AWd6eEVRTRZlviTPx4Hx41D4OtMgxoflZ1pP2coQ,304 pythonz/patches/osx/python26/patch-Lib-distutils-dist.py.diff,sha256=6jJ65AN5peNiN2n663wxQlVc9lQZWav1x4774fZNKTw,2002 pythonz/patches/osx/python26/patch-Mac-IDLE-Makefile.in.diff,sha256=ITMdw56U5yij3BU-_lF2EqCZHPTKcXunkapyVx_OJhM,697 pythonz/patches/osx/python26/patch-Mac-Makefile.in.diff,sha256=eYggs06QubUQYVCApXnm_wB4oAEWS0CS3U2qH5FW2Fs,977 pythonz/patches/osx/python26/patch-Mac-PythonLauncher-Makefile.in.diff,sha256=5DbiM_a4ncGHSBugWGlb-0xo7F1i3cNwycZ9oYBqFaM,899 pythonz/patches/osx/python26/patch-Mac-Tools-Doc-setup.py.diff,sha256=iciZft5qkHsHA3GVhlv2i4PwSxZfErs_uw1oDUMvkR8,505 pythonz/patches/osx/python26/patch-setup.py-db46.diff,sha256=hCP-ZXj0JKtfXCp7yNpPUwJkAMV8D5iaFR4Hv3IP0XE,488 pythonz/patches/osx/python26/patch-setup_no_tkinter.py.diff,sha256=0s5K3XZyOzWlHNckGP9DrdIBSzxtn2hCixd4sqYpdRA,428 pythonz/patches/osx/python27/patch-Modules-posixmodule.diff,sha256=k4OxNxop2u_GzL72Z4NSwH1UtpRIivNNnyPF-Yp2Jg4,613 pythonz/patches/osx/python27/python-276-dtrace.diff,sha256=m_FggodcHIeRj2sCVqoCPLCMm0JXLoqbVQ8_S0Wdmk0,56389 pythonz/patches/osx/python33/python-334-dtrace.diff,sha256=EtzAnkNHI6CJ6xPTUgu4zWk4cJe_ZddjXvXx8wCWHdg,61034 pythonz/patches/osx/python33/stackless-335-compile.diff,sha256=OU8VgBovAByfuc-a-cbylJuQxT7X8DztG3a2B24VBEM,2448 pythonz_bd-1.11.2.dist-info/DESCRIPTION.rst,sha256=dWQAMUdsd3niKc3PUhc81riehdrvCkXi_PQ0alQyXM0,5402 pythonz_bd-1.11.2.dist-info/METADATA,sha256=gRBALjKuYAhHG3tP19l7M6Al9GX5s7cwhWHZHyvPWnE,6473 pythonz_bd-1.11.2.dist-info/RECORD,, pythonz_bd-1.11.2.dist-info/WHEEL,sha256=JTb7YztR8fkPg6aSjc571Q4eiVHCwmUDlX8PhuuqIIE,92 pythonz_bd-1.11.2.dist-info/entry_points.txt,sha256=MgDPjhBWP92CkqaSLRXx5qCJdE6AOXCs__7BT-dwqQA,94 pythonz_bd-1.11.2.dist-info/metadata.json,sha256=iLhnMXUk6FHjdO3Hj0qX_xgyAt_Tfi5-WlPwLtSV7-0,1577 pythonz_bd-1.11.2.dist-info/top_level.txt,sha256=_WnCrTZBul1zpfemu3G305GE2l06v2-H28O9Kuzim4Q,8 PKYEjpythonz/__init__.pyPKYE mmpythonz/__main__.pyPKYEkXKpythonz/log.pyPK3H} pythonz/define.pyPK3HGAAPpythonz/downloader.pyPK3H|..pythonz/util.pyPK34HUOLpythonz/version.pyPKz0G($.Mpythonz/commands/__init__.pyPKYEwfdd Ppythonz/commands/cleanup.pyPKYEpo0Spythonz/commands/help.pyPKYEwZ<<fWpythonz/commands/uninstall.pyPKYEgoI22ythonz/commands/version.pyPKm3Ht344 4 H]pythonz/commands/install.pyPKפ3Hixjpythonz/commands/list.pyPK3H.spythonz/commands/locate.pyPK3Hoypythonz/commands/update.pyPKYEw^pythonz/installer/__init__.pyPK:3H (^.^.pythonz/installer/versions.pyPK3H* ^^$Gpythonz/installer/pythoninstaller.pyPK3HEHo%pythonz/installer/pythonzinstaller.pyPKYE8"pythonz/etc/bashrcPKYEHXxxo(pythonz/etc/pythonz.fishPKYEQ&3,pythonz/etc/bash_completion.d/pythonz_completion.shPKYEUFF.&=pythonz/patches/all/common/patch-setup.py.diffPKYEyQQ0Dpythonz/patches/all/python24/patch-setup.py.diffPKYEyQQ0WLpythonz/patches/all/python25/patch-setup.py.diffPKYE@S3Spythonz/patches/all/python25/patch-svnversion.patchPKYEEXQQ1=Ypythonz/patches/all/python26/patch-nosslv2-1.diffPKYEZ1mpythonz/patches/all/python26/patch-nosslv2-2.diffPKYEb81pythonz/patches/all/python26/patch-nosslv2-3.diffPKYE^^/pythonz/patches/all/python30/patch-nosslv2.diffPKYE9@@0=pythonz/patches/all/python30/patch-setup.py.diffPKYEYTpp0˳pythonz/patches/all/python32/patch-setup.py.diffPKYE?Q3pythonz/patches/osx/python24/patch-Include-pyport.hPKYEi((2pythonz/patches/osx/python24/patch-Lib-cgi.py.diffPKYE&&39pythonz/patches/osx/python24/patch-Lib-site.py.diffPKYEӕ YY2pythonz/patches/osx/python24/patch-Makefile.pre.inPKYE "22;Ypythonz/patches/osx/python24/patch-configure-badcflags.diffPKYE ((3pythonz/patches/osx/python24/patch-macosmodule.diffPKYE]'6Ppythonz/patches/osx/python24/patch-mactoolboxglue.diffPKYEqII4pythonz/patches/osx/python24/patch-pymactoolbox.diffPKYEi^9pythonz/patches/osx/python24/patch240-Mac-OSX-Makefile.inPKYEpgDD/pythonz/patches/osx/python24/patch240-configurePKYE9>>:pythonz/patches/osx/python24/patch240-gestaltmodule.c.diffPKYEg3Epythonz/patches/osx/python24/patch240-setup.py.diffPKYE?kC7? pythonz/patches/osx/python24/patch240-sysconfig.py.diffPKYE2F/(pythonz/patches/osx/python24/patch241-configurePKYEJE9bpythonz/patches/osx/python24/patch244-Mac-OSX-Makefile.inPKYEǨbb/pythonz/patches/osx/python24/patch244-configurePKYE >\\:9pythonz/patches/osx/python24/patch244-gestaltmodule.c.diffPKYEG#3pythonz/patches/osx/python24/patch244-setup.py.diffPKYEe@/$pythonz/patches/osx/python25/_localemodule.c.edPKYE)T%pythonz/patches/osx/python25/locale.py.edPKYEi-%pythonz/patches/osx/python25/patch-64bit.diffPKYE1((2pythonz/patches/osx/python25/patch-Lib-cgi.py.diffPKYE7=pythonz/patches/osx/python25/patch-Lib-distutils-dist.py.diffPKYEQ<7[pythonz/patches/osx/python25/patch-Makefile.pre.in.diffPKYEӭ;Ypythonz/patches/osx/python25/patch-configure-arch_only.diffPKYE;_pythonz/patches/osx/python25/patch-configure-badcflags.diffPKYE<'**7pythonz/patches/osx/python25/patch-gestaltmodule.c.diffPKYE-5pythonz/patches/osx/python25/patch-pyconfig.h.in.diffPKYE 3pythonz/patches/osx/python25/patch250-setup.py.diffPKYELM3pythonz/patches/osx/python25/patch251-setup.py.diffPKYEZ3pythonz/patches/osx/python25/patch252-setup.py.diffPKYEO/pythonz/patches/osx/python26/_localemodule.c.edPKYEt2)%pythonz/patches/osx/python26/locale.py.edPKYEg~((2pythonz/patches/osx/python26/patch-Lib-cgi.py.diffPKYEX00Cpythonz/patches/osx/python26/patch-Lib-ctypes-macholib-dyld.py.diffPKYE[?=pythonz/patches/osx/python26/patch-Lib-distutils-dist.py.diffPKYEOj < pythonz/patches/osx/python26/patch-Mac-IDLE-Makefile.in.diffPKYEvӗ7pythonz/patches/osx/python26/patch-Mac-Makefile.in.diffPKYE9ףFpythonz/patches/osx/python26/patch-Mac-PythonLauncher-Makefile.in.diffPKYEU0T>pythonz/patches/osx/python26/patch-Mac-Tools-Doc-setup.py.diffPKYE5,pythonz/patches/osx/python26/patch-setup.py-db46.diffPKYEP;gpythonz/patches/osx/python26/patch-setup_no_tkinter.py.diffPKYE^ee;lpythonz/patches/osx/python27/patch-Modules-posixmodule.diffPKYE? EE3*"pythonz/patches/osx/python27/python-276-dtrace.diffPKYE]jjj3pythonz/patches/osx/python33/python-334-dtrace.diffPKYE@% 7{pythonz/patches/osx/python33/stackless-335-compile.diffPK74Hlz(+`pythonz_bd-1.11.2.dist-info/DESCRIPTION.rstPK74HhDY^^, pythonz_bd-1.11.2.dist-info/entry_points.txtPK74H, )))k pythonz_bd-1.11.2.dist-info/metadata.jsonPK74HGz)pythonz_bd-1.11.2.dist-info/top_level.txtPK74H''\\!*pythonz_bd-1.11.2.dist-info/WHEELPK74HG@II$pythonz_bd-1.11.2.dist-info/METADATAPK74H}[|!!"P.pythonz_bd-1.11.2.dist-info/RECORDPKVVQP