[svn r57540] merge changes from release branch back

[svn merge -r 57430:HEAD ../release/0.9.x/ .]

* cmdline script organisation
* execnet windows fixes
* documentation updates
* test skips

also regen setup.py

--HG--
branch : trunk
This commit is contained in:
hpk 2008-08-21 12:18:58 +02:00
parent c0d524139e
commit a999dc8472
35 changed files with 596 additions and 508 deletions

View File

@ -1,20 +1,29 @@
$Id: CHANGELOG 57429 2008-08-18 15:08:39Z hpk $ $Id: CHANGELOG 57540 2008-08-21 10:18:58Z hpk $
Changes between 0.9.1 and 0.9.2 Changes between 0.9.1 and 0.9.2
=============================== ===============================
* refined installation and metadata, created new setup.py, * refined installation and metadata, created new setup.py,
now based on setuptools/ez_setup (by flipping a bit you now based on setuptools/ez_setup (thanks to Ralf Schmitt
can use distutils). for his support).
* improved the way of making py.* scripts available in * improved the way of making py.* scripts available in
windows environments, they are now added to the windows environments, they are now added to the
Scripts directory as ".cmd" files. Scripts directory as ".cmd" files.
* improved py.execnet bootstrapping on windows * py.path.svnwc.status() now is more complete and
uses xml output from the 'svn' command if available
(Guido Wesdorp)
* fix for py.path.svn* to work with svn 1.5
(Chris Lamb)
* fix path.relto(otherpath) method on windows to
use normcase for checking if a path is relative.
* py.test's traceback is better parseable from editors * py.test's traceback is better parseable from editors
(follows the filenames:LINENO: MSG convention) (follows the filenames:LINENO: MSG convention)
(thanks to Osmo Salomaa)
* fix to javascript-generation, "py.test --runbrowser" * fix to javascript-generation, "py.test --runbrowser"
should work more reliably now should work more reliably now

View File

@ -61,13 +61,20 @@ py/apigen/tracer/testing/test_docgen.py
py/apigen/tracer/testing/test_model.py py/apigen/tracer/testing/test_model.py
py/apigen/tracer/testing/test_package.py py/apigen/tracer/testing/test_package.py
py/apigen/tracer/tracer.py py/apigen/tracer/tracer.py
py/bin/_docgen.py
py/bin/_findpy.py py/bin/_findpy.py
py/bin/_genscripts.py
py/bin/py.cleanup py/bin/py.cleanup
py/bin/py.countloc py/bin/py.countloc
py/bin/py.lookup py/bin/py.lookup
py/bin/py.rest py/bin/py.rest
py/bin/py.test py/bin/py.test
py/bin/py.which py/bin/py.which
py/bin/win32/py.cleanup.cmd
py/bin/win32/py.countloc.cmd
py/bin/win32/py.lookup.cmd
py/bin/win32/py.rest.cmd
py/bin/win32/py.test.cmd
py/builtin/__init__.py py/builtin/__init__.py
py/builtin/enumerate.py py/builtin/enumerate.py
py/builtin/exception.py py/builtin/exception.py
@ -100,6 +107,14 @@ py/c-extension/greenlet/test_generator_nested.py
py/c-extension/greenlet/test_greenlet.py py/c-extension/greenlet/test_greenlet.py
py/c-extension/greenlet/test_remote.py py/c-extension/greenlet/test_remote.py
py/c-extension/greenlet/test_throw.py py/c-extension/greenlet/test_throw.py
py/cmdline/__init__.py
py/cmdline/pycleanup.py
py/cmdline/pycountloc.py
py/cmdline/pylookup.py
py/cmdline/pyrest.py
py/cmdline/pytest.py
py/cmdline/testing/__init__.py
py/cmdline/testing/test_generic.py
py/code/__init__.py py/code/__init__.py
py/code/code.py py/code/code.py
py/code/excinfo.py py/code/excinfo.py
@ -419,4 +434,5 @@ py/xmlobj/testing/test_html.py
py/xmlobj/testing/test_xml.py py/xmlobj/testing/test_xml.py
py/xmlobj/visit.py py/xmlobj/visit.py
py/xmlobj/xml.py py/xmlobj/xml.py
setup.cfg
setup.py setup.py

View File

@ -1,37 +0,0 @@
#!/usr/bin/env python
#
# find and import a version of 'py'
#
import sys
import os
from os.path import dirname as opd, exists, join, basename, abspath
def searchpy(current):
while 1:
last = current
initpy = join(current, '__init__.py')
if not exists(initpy):
pydir = join(current, 'py')
# recognize py-package and ensure it is importable
if exists(pydir) and exists(join(pydir, '__init__.py')):
#for p in sys.path:
# if p == current:
# return True
if current != sys.path[0]: # if we are already first, then ok
print >>sys.stderr, "inserting into sys.path:", current
sys.path.insert(0, current)
return True
current = opd(current)
if last == current:
return False
if not searchpy(abspath(os.curdir)):
if not searchpy(opd(abspath(sys.argv[0]))):
if not searchpy(opd(__file__)):
pass # let's hope it is just on sys.path
import py
if __name__ == '__main__':
print "py lib is at", py.__file__

View File

@ -16,6 +16,7 @@ copyrighted by one or more of the following people and organizations:
Contributors include:: Contributors include::
Samuele Pedroni Samuele Pedroni
Chris Lamb
Harald Armin Massa Harald Armin Massa
Ralf Schmitt Ralf Schmitt
Ian Bicking Ian Bicking

View File

@ -1,9 +1,24 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
the py lib is a development support library featuring The py lib is a development support library featuring these tools and APIs:
py.test, ad-hoc distributed execution, micro-threads
and svn abstractions. - `py.test`_: cross-project testing tool with many advanced features
- `py.execnet`_: ad-hoc code distribution to SSH, Socket and local sub processes
- `py.magic.greenlet`_: micro-threads on standard CPython ("stackless-light") and PyPy
- `py.path`_: path abstractions over local and subversion files
- `py.code`_: dynamic code compile and traceback printing support
The py lib and its tools should work well on Linux, Win32,
OSX, Python versions 2.3-2.6. For questions please go to
http://pylib.org/contact.html
.. _`py.test`: http://pylib.org/test.html
.. _`py.execnet`: http://pylib.org/execnet.html
.. _`py.magic.greenlet`: http://pylib.org/greenlet.html
.. _`py.path`: http://pylib.org/path.html
.. _`py.code`: http://pylib.org/code.html
""" """
from initpkg import initpkg from initpkg import initpkg
@ -11,18 +26,18 @@ version = "1.0.0a1"
initpkg(__name__, initpkg(__name__,
description = "pylib and py.test: agile development and test support library", description = "pylib and py.test: agile development and test support library",
revision = int('$LastChangedRevision: 57529 $'.split(':')[1][:-1]), revision = int('$LastChangedRevision: 57540 $'.split(':')[1][:-1]),
lastchangedate = '$LastChangedDate: 2008-08-21 09:48:44 +0200 (Thu, 21 Aug 2008) $', lastchangedate = '$LastChangedDate: 2008-08-21 12:18:58 +0200 (Thu, 21 Aug 2008) $',
version = version, version = version,
url = "http://pylib.org", url = "http://pylib.org",
download_url = "http://pypi.python.org/pypi?:action=display&name=py", download_url = "http://codespeak.net/py/0.9.2/download.html",
license = "MIT license", license = "MIT license",
platforms = ['unix', 'linux', 'osx', 'cygwin', 'win32'], platforms = ['unix', 'linux', 'osx', 'cygwin', 'win32'],
author = "holger krekel, Guido Wesdorp, Carl Friedrich Bolz, Armin Rigo, Maciej Fijalkowski & others", author = "holger krekel, Guido Wesdorp, Carl Friedrich Bolz, Armin Rigo, Maciej Fijalkowski & others",
author_email = "holger at merlinux.eu, py-dev at codespeak.net", author_email = "holger at merlinux.eu, py-dev at codespeak.net",
long_description = globals()['__doc__'], long_description = globals()['__doc__'],
classifiers = [ classifiers = [
"Development Status :: 3 - Alpha", "Development Status :: 4 - Beta",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"License :: OSI Approved :: MIT License", "License :: OSI Approved :: MIT License",
"Operating System :: POSIX", "Operating System :: POSIX",
@ -38,6 +53,13 @@ initpkg(__name__,
# EXPORTED API # EXPORTED API
exportdefs = { exportdefs = {
# py lib cmdline tools
'cmdline.pytest' : ('./cmdline/pytest.py', 'main',),
'cmdline.pyrest' : ('./cmdline/pyrest.py', 'main',),
'cmdline.pylookup' : ('./cmdline/pylookup.py', 'main',),
'cmdline.pycountloc' : ('./cmdline/pycountloc.py', 'main',),
'cmdline.pycleanup' : ('./cmdline/pycleanup.py', 'main',),
# helpers for use from test functions or collectors # helpers for use from test functions or collectors
'test.__doc__' : ('./test/__init__.py', '__doc__'), 'test.__doc__' : ('./test/__init__.py', '__doc__'),
'test.raises' : ('./test/outcome.py', 'raises'), 'test.raises' : ('./test/outcome.py', 'raises'),

View File

@ -21,8 +21,21 @@ def pkg_to_dict(module):
for key, value in defs.iteritems(): for key, value in defs.iteritems():
chain = key.split('.') chain = key.split('.')
base = module base = module
for elem in chain: # XXX generalize this:
base = getattr(base, elem) # a bit of special casing for greenlets which are
# not available on all the platforms that python/py
# lib runs
try:
for elem in chain:
base = getattr(base, elem)
except RuntimeError, exc:
if elem == "greenlet":
print exc.__class__.__name__, exc
print "Greenlets not supported on this platform. Skipping apigen doc for this module"
continue
else:
raise
if value[1] == '*': if value[1] == '*':
d.update(get_star_import_tree(base, key)) d.update(get_star_import_tree(base, key))
else: else:

61
py/bin/_docgen.py Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env python
""" quick tool to get documentation + apigen docs generated
given a certain targetpath, apigen docs will be placed in 'apigen',
user can choose to only build either docs or apigen docs: in this case,
the navigation bar will be adjusted
"""
from _findpy import py
pypath = py.__pkg__.getpath()
print "using pypath", pypath
import os
def run_tests(path, envvars='', args=''):
pytestpath = pypath.join('bin/py.test')
cmd = ('PYTHONPATH="%s" %s python "%s" %s "%s"' %
(pypath.dirpath(), envvars, pytestpath, args, path))
print cmd
errno = os.system(cmd)
assert not errno
def build_apigen_docs(targetpath, testargs=''):
run_tests(pypath,
'APIGEN_TARGET="%s/apigen" APIGEN_DOCRELPATH="../"' % (
targetpath,),
'%s --apigen="%s/apigen/apigen.py"' % (testargs, pypath))
def build_docs(targetpath, testargs):
docpath = pypath.join('doc')
run_tests(docpath, '',
testargs + ' --forcegen --apigen="%s/apigen/apigen.py"' % (pypath,))
docpath.copy(targetpath)
def build_nav(targetpath, docs=True, api=True):
pass
def build(targetpath, docs=True, api=True, testargs=''):
targetpath.ensure(dir=True)
if docs:
print 'building docs'
build_docs(targetpath, testargs)
if api:
print 'building api'
build_apigen_docs(targetpath, testargs)
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print 'usage: %s <targetdir> [options]'
print
print ' targetdir: a path to a directory (created if it doesn\'t'
print ' exist) where the docs are put'
print ' options: options passed to py.test when running the tests'
sys.exit(1)
targetpath = py.path.local(sys.argv[1])
args = ' '.join(sys.argv[2:])
build(targetpath, True, True, args)

34
py/bin/_genscripts.py Normal file
View File

@ -0,0 +1,34 @@
from _findpy import py
mydir = py.magic.autopath().dirpath()
def getbasename(name):
assert name[:2] == "py"
return "py." + name[2:]
def genscript_unix(name):
basename = getbasename(name)
path = mydir.join(basename)
path.write(py.code.Source("""
#!/usr/bin/env python
from _findpy import py
py.cmdline.%s()
""" % name).strip())
path.chmod(0755)
def genscript_windows(name):
basename = getbasename(name)
winbasename = basename + ".cmd"
path = mydir.join("win32").join(winbasename)
path.write(py.code.Source("""
@echo off
python "%%~dp0\..\%s" %%*
""" % (basename)).strip())
if __name__ == "__main__":
for name in dir(py.cmdline):
if name[0] != "_":
genscript_unix(name)
genscript_windows(name)

View File

@ -1,24 +1,3 @@
#!/usr/bin/env python #!/usr/bin/env python
from _findpy import py
"""\ py.cmdline.pycleanup()
py.cleanup [PATH]
Delete pyc file recursively, starting from PATH (which defaults to the current
working directory). Don't follow links and don't recurse into directories with
a ".".
"""
from _findpy import py
import py
parser = py.compat.optparse.OptionParser(usage=__doc__)
if __name__ == '__main__':
(options, args) = parser.parse_args()
if not args:
args = ["."]
for arg in args:
path = py.path.local(arg)
print "cleaning path", path
for x in path.visit('*.pyc', lambda x: x.check(dotfile=0, link=0)):
x.remove()

View File

@ -1,23 +1,3 @@
#!/usr/bin/env python #!/usr/bin/env python
from _findpy import py
# hands on script to compute the non-empty Lines of Code py.cmdline.pycountloc()
# for tests and non-test code
"""\
py.countloc [PATHS]
Count (non-empty) lines of python code and number of python files recursively
starting from a list of paths given on the command line (starting from the
current working directory). Distinguish between test files and normal ones and
report them separately.
"""
from _findpy import py
import py
from py.compat import optparse
from py.__.misc.cmdline.countloc import countloc
parser = optparse.OptionParser(usage=__doc__)
if __name__ == '__main__':
(options, args) = parser.parse_args()
countloc(args)

View File

@ -1,79 +1,3 @@
#!/usr/bin/env python #!/usr/bin/env python
"""\
py.lookup SEARCH_STRING [options]
Looks recursively at Python files for a SEARCH_STRING, starting from the
present working directory. Prints the line, with the filename and line-number
prepended."""
import sys, os
sys.path.insert(0, os.path.dirname(__file__))
from _findpy import py from _findpy import py
try: py.cmdline.pylookup()
from py.__.io.terminalwriter import ansi_print, terminal_width
except ImportError:
from py.__.misc.terminal_helper import ansi_print, terminal_width
import re
curdir = py.path.local()
def rec(p):
return p.check(dotfile=0)
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__)
parser.add_option("-i", "--ignore-case", action="store_true", dest="ignorecase",
help="ignore case distinctions")
parser.add_option("-C", "--context", action="store", type="int", dest="context",
default=0, help="How many lines of output to show")
def find_indexes(search_line, string):
indexes = []
before = 0
while 1:
i = search_line.find(string, before)
if i == -1:
break
indexes.append(i)
before = i + len(string)
return indexes
if __name__ == '__main__':
(options, args) = parser.parse_args()
string = args[0]
if options.ignorecase:
string = string.lower()
for x in curdir.visit('*.py', rec):
try:
s = x.read()
except py.error.ENOENT:
pass # whatever, probably broken link (ie emacs lock)
searchs = s
if options.ignorecase:
searchs = s.lower()
if s.find(string) != -1:
lines = s.splitlines()
if options.ignorecase:
searchlines = s.lower().splitlines()
else:
searchlines = lines
for i, (line, searchline) in enumerate(zip(lines, searchlines)):
indexes = find_indexes(searchline, string)
if not indexes:
continue
if not options.context:
sys.stdout.write("%s:%d: " %(x.relto(curdir), i+1))
last_index = 0
for index in indexes:
sys.stdout.write(line[last_index: index])
ansi_print(line[index: index+len(string)],
file=sys.stdout, esc=31, newline=False)
last_index = index + len(string)
sys.stdout.write(line[last_index:] + "\n")
else:
context = (options.context)/2
for count in range(max(0, i-context), min(len(lines) - 1, i+context+1)):
print "%s:%d: %s" %(x.relto(curdir), count+1, lines[count].rstrip())
print "-" * terminal_width

View File

@ -1,79 +1,3 @@
#!/usr/bin/env python #!/usr/bin/env python
"""
invoke
py.rest filename1.txt directory
to generate html files from ReST.
It is also possible to generate pdf files using the --topdf option.
http://docutils.sourceforge.net/docs/user/rst/quickref.html
"""
import os, sys
from _findpy import py from _findpy import py
from py.__.misc import rest py.cmdline.pyrest()
from py.__.rest import directive
from py.__.rest.latex import process_rest_file, process_configfile
if hasattr(sys.stdout, 'fileno') and os.isatty(sys.stdout.fileno()):
def log(msg):
print msg
else:
def log(msg):
pass
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__)
parser.add_option("--topdf", action="store_true", dest="topdf", default=False,
help="generate pdf files")
parser.add_option("--stylesheet", dest="stylesheet", default=None,
help="use specified latex style sheet")
parser.add_option("--debug", action="store_true", dest="debug",
default=False,
help="print debug output and don't delete files")
if __name__=='__main__':
(options, args) = parser.parse_args()
if len(args) == 0:
filenames = [py.path.svnwc()]
else:
filenames = [py.path.svnwc(x) for x in args]
if options.topdf:
directive.set_backend_and_register_directives("latex")
for p in filenames:
if not p.check():
log("path %s not found, ignoring" % p)
continue
def fil(p):
return p.check(fnmatch='*.txt', versioned=True)
def rec(p):
return p.check(dotfile=0)
if p.check(dir=1):
for x in p.visit(fil, rec):
rest.process(x)
elif p.check(file=1):
if p.ext == ".rst2pdfconfig":
directive.set_backend_and_register_directives("latex")
process_configfile(p, options.debug)
else:
if options.topdf:
cfg = p.new(ext=".rst2pdfconfig")
if cfg.check():
print "using config file %s" % (cfg, )
process_configfile(cfg, options.debug)
else:
process_rest_file(p.localpath,
options.stylesheet,
options.debug)
else:
rest.process(p)

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python #!/usr/bin/env python
from _findpy import py
from _findpy import py py.cmdline.pytest()
py.test.cmdline.main()

View File

@ -0,0 +1,2 @@
@echo off
python "%~dp0\..\py.cleanup" %*

View File

@ -0,0 +1,2 @@
@echo off
python "%~dp0\..\py.countloc" %*

View File

@ -0,0 +1,2 @@
@echo off
python "%~dp0\..\py.lookup" %*

2
py/bin/win32/py.rest.cmd Normal file
View File

@ -0,0 +1,2 @@
@echo off
python "%~dp0\..\py.rest" %*

2
py/bin/win32/py.test.cmd Normal file
View File

@ -0,0 +1,2 @@
@echo off
python "%~dp0\..\py.test" %*

1
py/cmdline/__init__.py Normal file
View File

@ -0,0 +1 @@
#

21
py/cmdline/pycleanup.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
"""\
py.cleanup [PATH]
Delete pyc file recursively, starting from PATH (which defaults to the current
working directory). Don't follow links and don't recurse into directories with
a ".".
"""
import py
def main():
parser = py.compat.optparse.OptionParser(usage=__doc__)
(options, args) = parser.parse_args()
if not args:
args = ["."]
for arg in args:
path = py.path.local(arg)
print "cleaning path", path
for x in path.visit('*.pyc', lambda x: x.check(dotfile=0, link=0)):
x.remove()

22
py/cmdline/pycountloc.py Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
# hands on script to compute the non-empty Lines of Code
# for tests and non-test code
"""\
py.countloc [PATHS]
Count (non-empty) lines of python code and number of python files recursively
starting from a list of paths given on the command line (starting from the
current working directory). Distinguish between test files and normal ones and
report them separately.
"""
from _findpy import py
import py
from py.compat import optparse
from py.__.misc.cmdline.countloc import countloc
def main():
parser = optparse.OptionParser(usage=__doc__)
(options, args) = parser.parse_args()
countloc(args)

74
py/cmdline/pylookup.py Executable file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python
"""\
py.lookup SEARCH_STRING [options]
Looks recursively at Python files for a SEARCH_STRING, starting from the
present working directory. Prints the line, with the filename and line-number
prepended."""
import sys, os
import py
from py.__.misc.terminal_helper import ansi_print, terminal_width
import re
curdir = py.path.local()
def rec(p):
return p.check(dotfile=0)
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__)
parser.add_option("-i", "--ignore-case", action="store_true", dest="ignorecase",
help="ignore case distinctions")
parser.add_option("-C", "--context", action="store", type="int", dest="context",
default=0, help="How many lines of output to show")
def find_indexes(search_line, string):
indexes = []
before = 0
while 1:
i = search_line.find(string, before)
if i == -1:
break
indexes.append(i)
before = i + len(string)
return indexes
def main():
(options, args) = parser.parse_args()
string = args[0]
if options.ignorecase:
string = string.lower()
for x in curdir.visit('*.py', rec):
try:
s = x.read()
except py.error.ENOENT:
pass # whatever, probably broken link (ie emacs lock)
searchs = s
if options.ignorecase:
searchs = s.lower()
if s.find(string) != -1:
lines = s.splitlines()
if options.ignorecase:
searchlines = s.lower().splitlines()
else:
searchlines = lines
for i, (line, searchline) in enumerate(zip(lines, searchlines)):
indexes = find_indexes(searchline, string)
if not indexes:
continue
if not options.context:
sys.stdout.write("%s:%d: " %(x.relto(curdir), i+1))
last_index = 0
for index in indexes:
sys.stdout.write(line[last_index: index])
ansi_print(line[index: index+len(string)],
file=sys.stdout, esc=31, newline=False)
last_index = index + len(string)
sys.stdout.write(line[last_index:] + "\n")
else:
context = (options.context)/2
for count in range(max(0, i-context), min(len(lines) - 1, i+context+1)):
print "%s:%d: %s" %(x.relto(curdir), count+1, lines[count].rstrip())
print "-" * terminal_width

83
py/cmdline/pyrest.py Executable file
View File

@ -0,0 +1,83 @@
#!/usr/bin/env python
"""
invoke
py.rest filename1.txt directory
to generate html files from ReST.
It is also possible to generate pdf files using the --topdf option.
http://docutils.sourceforge.net/docs/user/rst/quickref.html
"""
import os, sys
import py
if hasattr(sys.stdout, 'fileno') and os.isatty(sys.stdout.fileno()):
def log(msg):
print msg
else:
def log(msg):
pass
optparse = py.compat.optparse
parser = optparse.OptionParser(usage=__doc__)
parser.add_option("--topdf", action="store_true", dest="topdf", default=False,
help="generate pdf files")
parser.add_option("--stylesheet", dest="stylesheet", default=None,
help="use specified latex style sheet")
parser.add_option("--debug", action="store_true", dest="debug",
default=False,
help="print debug output and don't delete files")
def main():
try:
from py.__.misc import rest
from py.__.rest import directive
from py.__.rest.latex import process_rest_file, process_configfile
except ImportError, e:
print str(e)
sys.exit(1)
(options, args) = parser.parse_args()
if len(args) == 0:
filenames = [py.path.svnwc()]
else:
filenames = [py.path.svnwc(x) for x in args]
if options.topdf:
directive.set_backend_and_register_directives("latex")
for p in filenames:
if not p.check():
log("path %s not found, ignoring" % p)
continue
def fil(p):
return p.check(fnmatch='*.txt', versioned=True)
def rec(p):
return p.check(dotfile=0)
if p.check(dir=1):
for x in p.visit(fil, rec):
rest.process(x)
elif p.check(file=1):
if p.ext == ".rst2pdfconfig":
directive.set_backend_and_register_directives("latex")
process_configfile(p, options.debug)
else:
if options.topdf:
cfg = p.new(ext=".rst2pdfconfig")
if cfg.check():
print "using config file %s" % (cfg, )
process_configfile(cfg, options.debug)
else:
process_rest_file(p.localpath,
options.stylesheet,
options.debug)
else:
rest.process(p)

5
py/cmdline/pytest.py Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env python
import py
def main():
py.test.cmdline.main()

View File

@ -0,0 +1 @@
#

View File

@ -0,0 +1,55 @@
import py
import sys
binpath = py.path.local(py.__file__).dirpath("bin")
binwinpath = binpath.join("win32")
def setup_module(mod):
mod.tmpdir = py.test.ensuretemp(__name__)
mod.iswin32 = sys.platform == "win32"
def checkmain(name):
main = getattr(py.cmdline, name)
assert callable(main)
assert name[:2] == "py"
scriptname = "py." + name[2:]
assert binpath.join(scriptname).check()
assert binwinpath.join(scriptname + ".cmd").check()
def checkprocess(script):
assert script.check()
old = tmpdir.ensure(script.basename, dir=1).chdir()
try:
if iswin32:
cmd = script.basename
else:
cmd = "%s" %(script, )
if script.basename.startswith("py.lookup"):
cmd += " hello"
print "executing", script
try:
py.process.cmdexec(cmd)
except py.process.cmdexec.Error, e:
if cmd.find("py.rest") != -1 and \
e.out.find("module named") != -1:
return
raise
finally:
old.chdir()
def test_cmdline_namespace():
for name in dir(py.cmdline):
if name[0] != "_":
yield checkmain, name
def test_script_invocation():
if iswin32:
for script in binwinpath.listdir("py.*"):
assert script.ext == ".cmd"
yield checkprocess, script
else:
for script in binpath.listdir("py.*"):
yield checkprocess, script

View File

@ -1,104 +1,71 @@
Download and Installation of the py lib
===============================================
.. contents::
.. sectnum::
Downloading a tar/zip file and installing it "easy_install py"
=================================================== ===================================================
The latest public release: With a working `setuptools installation`_ you can install from the command line::
`download py-0.9.0.tar.gz`_ easy_install py
`download py-0.9.0.zip`_
.. _`download py-0.9.0.tar.gz`: http://codespeak.net/download/py/py-0.9.0.tar.gz to get the latest release of the py lib. On non-Windows systems you will
.. _`download py-0.9.0.zip`: http://codespeak.net/download/py/py-0.9.0.zip need a working C-compiler in order to successfully complete this step.
The py lib and its tools are expected to work well on Linux, Windows
and OSX, Python versions 2.3, 2.4, 2.5 and 2.6.
The py lib can be `globally installed via setup.py`_ **IMPORTANT NOTE**: if you are using Windows and have previous
or `used locally`_. installations of the py lib on your system, please download
and execute http://codespeak.net/svn/py/build/winpathclean.py
This will check that no previous files are getting in the way.
(Unfortunately we don't know about a way to execute this
code automatically during the above install).
WARNING: win32 there is no pre-packaged c-extension .. _`setuptools installation`: http://pypi.python.org/pypi/setuptools
module (greenlet) yet and thus greenlets will not work
out of the box.
Getting (and updating) via subversion Downloading a tar/zip archive and installing that
-------------------------------------------- ===================================================
Use Subversion to checkout the latest 0.9.x stable release: Go to the project pages and download a tar or zip file:
svn co http://codespeak.net/svn/py/release/0.9.x py-0.9.x http://pypi.python.org/pypi/py/
to obtain the complete code and documentation source. and unpack it to a directory, where you then type::
If you experience problems with the subversion checkout e.g.
because you have a http-proxy in between that doesn't proxy
DAV requests you can try to use "codespeak.net:8080" instead
of just "codespeak.net". Alternatively, you may tweak
your local subversion installation.
If you want to follow stable snapshots
then you may use the equivalent of this invocation:
svn co http://codespeak.net/svn/py/dist py-dist
.. _`globally installed via setup.py`:
Installation via setup.py
------------------------------
Go to your unpacked/checked out directory
and issue:
python setup.py install python setup.py install
If you don't have a working C-compiler you can do::
.. _`used locally`: python setup.py install_lib
Local Installation/Usage You will then not be able to use greenlets but otherwise
------------------------------ should be fine.
You need to put the checkout-directory into your ``PYTHONPATH`` Installing from subversion / develop mode
and you want to have the ``py-dist/py/bin/py.test`` script in ============================================
your (unixish) system path, which lets you execute test files
and directories.
There is a convenient way for Bash/Shell based systems To follow development or help with fixing things
to setup the ``PYTHONPATH`` as well as the shell ``PATH``, insert:: for the next release, checkout the complete code
and documentation source::
eval `python ~/path/to/py-dist/py/env.py` svn co http://codespeak.net/svn/py/release/0.9.x py-0.9.x
into your ``.bash_profile``. Of course, you need to You should then be able to issue::
specify your own checkout-directory.
python setup.py develop
.. _`svn-external scenario`: and work with the local version.
The py lib as an svn external If this doesn't work for you then you can also
------------------------------------------------------- source (linux) or execute (windows) some scripts
that set environment variables for using your checkout.
You can execute:
Add the py lib as an external to your project `DIRECTORY` python ~/path/to/checkout/py/env.py
which contains your svn-controlled root package::
svn propedit 'svn:externals' DIRECTORY or on windows:
which will open an editor where you can add \\path\\to\\checkout\\py\\env.cmd
the following line:
py http://codespeak.net/svn/py/dist to get settings for PYTHONPATH and PATH.
This will make your projcet automatically use the
most recent stable snapshot of the py lib.
Alternatively you may use this url for
integrating the development version:
http://codespeak.net/svn/py/trunk
or the next one for following the e.g. the 0.9 release branch
http://codespeak.net/svn/py/release/0.9.x
py subversion directory structure py subversion directory structure

View File

@ -5,8 +5,6 @@ Implementation and Customization of ``py.test``
.. contents:: .. contents::
.. sectnum:: .. sectnum::
.. _`basicpicture`: .. _`basicpicture`:
@ -71,6 +69,12 @@ By default all directories not starting with a dot are traversed,
looking for ``test_*.py`` and ``*_test.py`` files. Those files looking for ``test_*.py`` and ``*_test.py`` files. Those files
are imported under their `package name`_. are imported under their `package name`_.
The Module collector looks for test functions
and test classes and methods. Test functions and methods
are prefixed ``test`` by default. Test classes must
start with a capitalized ``Test`` prefix.
.. _`collector API`: .. _`collector API`:
test items are collectors as well test items are collectors as well
@ -84,48 +88,28 @@ it, otherwise we consider the "test" as passed.
.. _`package name`: .. _`package name`:
constructing the package name for modules constructing the package name for test modules
----------------------------------------- -------------------------------------------------
Test modules are imported under their fully qualified Test modules are imported under their fully qualified
name. Given a module ``path`` the fully qualified package name. Given a filesystem ``fspath`` it is constructed as follows:
name is constructed as follows:
* determine the last "upward" directory from ``path`` that * walk the directories up to the last one that contains
contains an ``__init__.py`` file. Going upwards an ``__init__.py`` file.
means repeatedly calling the ``dirpath()`` method
on a path object (which returns the parent directory
as a path object).
* insert this base directory into the sys.path list * perform ``sys.path.insert(0, basedir)``.
as its first element
* import the root package * import the root package as ``root``
* determine the fully qualified name for the module located * determine the fully qualified name for ``fspath`` by either:
at ``path`` ...
* if the imported root package has a __package__ object * calling ``root.__pkg__.getimportname(fspath)`` if the
then call ``__package__.getimportname(path)`` ``__pkg__`` exists.` or
* otherwise use the relative path of the module path to * otherwise use the relative path of the module path to
the base dir and turn slashes into dots and strike the base dir and turn slashes into dots and strike
the trailing ``.py``. the trailing ``.py``.
The Module collector will eventually trigger
``__import__(mod_fqdnname, ...)`` to finally get to
the live module object.
Side note: this whole logic is performed by local path
object's ``pyimport()`` method.
Module Collector
-----------------
The default Module collector looks for test functions
and test classes and methods. Test functions and methods
are prefixed ``test`` by default. Test classes must
start with a capitalized ``Test`` prefix.
Customizing the testing process Customizing the testing process
@ -256,32 +240,27 @@ Customizing the collection process in a module
If you have a module where you want to take responsibility for If you have a module where you want to take responsibility for
collecting your own test Items and possibly even for executing collecting your own test Items and possibly even for executing
a test then you can provide `generative tests`_ that yield a test then you can provide `generative tests`_ that yield
callables and possibly arguments as a tuple. This should callables and possibly arguments as a tuple. This is especially
serve some immediate purposes like paramtrized tests. useful for calling application test machinery with different
parameter sets but counting each of the calls as a separate
tests.
.. _`generative tests`: test.html#generative-tests .. _`generative tests`: test.html#generative-tests
The other extension possibility goes deeper into the machinery The other extension possibility is about
and allows you to specify a custom test ``Item`` class which specifying a custom test ``Item`` class which
is responsible for setting up and executing an underlying is responsible for setting up and executing an underlying
test. [XXX not working: You can integrate your custom ``py.test.collect.Item`` subclass test. Or you can extend the collection process for a whole
by binding an ``Item`` name to a test class.] Or you can directory tree by putting Items in a ``conftest.py`` configuration file.
extend the collection process for a whole directory tree The collection process dynamically consults the *chain of conftest.py*
by putting Items in a ``conftest.py`` configuration file. modules to determine collectors and items at ``Directory``, ``Module``,
The collection process constantly looks at according names ``Class``, ``Function`` or ``Generator`` level respectively.
in the *chain of conftest.py* modules to determine collectors
and items at ``Directory``, ``Module``, ``Class``, ``Function``
or ``Generator`` level. Note that, right now, except for ``Function``
items all classes are pure collectors, i.e. will return a list
of names (possibly empty).
XXX implement doctests as alternatives to ``Function`` items.
Customizing execution of Functions Customizing execution of Functions
---------------------------------- ----------------------------------
- Function test items allow total control of executing their - ``py.test.collect.Function`` test items control execution
contained test method. ``function.run()`` will get called by the of a test function. ``function.run()`` will get called by the
session in order to actually run a test. The method is responsible session in order to actually run a test. The method is responsible
for performing proper setup/teardown ("Test Fixtures") for a for performing proper setup/teardown ("Test Fixtures") for a
Function test. Function test.
@ -290,5 +269,4 @@ Customizing execution of Functions
the default ``Function.run()`` to actually execute a python the default ``Function.run()`` to actually execute a python
function with the given (usually empty set of) arguments. function with the given (usually empty set of) arguments.
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev .. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev

View File

@ -1,13 +1,15 @@
py lib documentation py lib documentation
================================================= =================================================
The py lib aims at supporting a decent development process The py lib is a development support library featuring
addressing deployment, versioning, testing and documentation py.test, ad-hoc distributed execution, micro-threads
perspectives. (greenlets) and uniform local path and svn abstractions.
Works on Linux, Windows and OSX, Python versions
2.3, 2.4, 2.5 and 2.6.
`Download and Installation`_ `Download and Installation`_
`0.9.0 release announcement`_ `0.9.2 release announcement`_
Main tools and API Main tools and API
---------------------- ----------------------
@ -20,6 +22,8 @@ Main tools and API
`py.path`_: local and subversion Path and Filesystem access `py.path`_: local and subversion Path and Filesystem access
`py.code`_: High-level access/manipulation of Python code and traceback objects.
`py lib scripts`_ describe the scripts contained in the ``py/bin`` directory. `py lib scripts`_ describe the scripts contained in the ``py/bin`` directory.
`apigen`_: a new way to generate rich Python API documentation `apigen`_: a new way to generate rich Python API documentation
@ -27,8 +31,6 @@ Main tools and API
support functionality support functionality
--------------------------------- ---------------------------------
`py.code`_: High-level access/manipulation of Python code and traceback objects.
`py.xml`_ for generating in-memory xml/html object trees `py.xml`_ for generating in-memory xml/html object trees
`py.io`_: Helper Classes for Capturing of Input/Output `py.io`_: Helper Classes for Capturing of Input/Output
@ -59,4 +61,4 @@ Background and Motivation information
.. _`Why What how py?`: why_py.html .. _`Why What how py?`: why_py.html
.. _`future`: future.html .. _`future`: future.html
.. _`miscellaneous features`: misc.html .. _`miscellaneous features`: misc.html
.. _`0.9.0 release announcement`: release-0.9.0.html .. _`0.9.2 release announcement`: release-0.9.2.html

View File

@ -5,7 +5,7 @@ Welcome to the 0.9.2 py lib and py.test release -
mainly fixing Windows issues, providing better mainly fixing Windows issues, providing better
packaging and integration with setuptools. packaging and integration with setuptools.
Summary of main feature of the py lib: Here is a quick summary of what it provides:
* py.test: cross-project testing tool with many advanced features * py.test: cross-project testing tool with many advanced features
* py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes * py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes
@ -17,6 +17,7 @@ Summary of main feature of the py lib:
See here for more information: See here for more information:
Download/Install: http://codespeak.net/py/0.9.2/download.html Download/Install: http://codespeak.net/py/0.9.2/download.html
Documentation/API: http://codespeak.net/py/0.9.2/index.html Documentation/API: http://codespeak.net/py/0.9.2/index.html
best and have fun, best and have fun,

View File

@ -59,10 +59,6 @@ import sys
class Popen2IO: class Popen2IO:
server_stmt = """ server_stmt = """
import os, sys, StringIO import os, sys, StringIO
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
io = Popen2IO(sys.stdout, sys.stdin) io = Popen2IO(sys.stdout, sys.stdin)
sys.stdout = sys.stderr = StringIO.StringIO() sys.stdout = sys.stderr = StringIO.StringIO()
#try: #try:
@ -75,6 +71,11 @@ sys.stdout = sys.stderr = StringIO.StringIO()
def __init__(self, infile, outfile): def __init__(self, infile, outfile):
self.outfile, self.infile = infile, outfile self.outfile, self.infile = infile, outfile
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(infile.fileno(), os.O_BINARY)
msvcrt.setmode(outfile.fileno(), os.O_BINARY)
self.readable = self.writeable = True self.readable = self.writeable = True
self.lock = thread.allocate_lock() self.lock = thread.allocate_lock()

View File

@ -2,8 +2,12 @@
import os, inspect, socket import os, inspect, socket
import sys import sys
from py.magic import autopath ; mypath = autopath() from py.magic import autopath ; mypath = autopath()
import py import py
if sys.platform == "win32":
win32 = True
import msvcrt
else:
win32 = False
# the list of modules that must be send to the other side # the list of modules that must be send to the other side
# for bootstrapping gateways # for bootstrapping gateways
@ -51,13 +55,10 @@ class InstallableGateway(gateway.Gateway):
class PopenCmdGateway(InstallableGateway): class PopenCmdGateway(InstallableGateway):
def __init__(self, cmd): def __init__(self, cmd):
infile, outfile = os.popen2(cmd) infile, outfile = os.popen2(cmd)
if sys.platform == 'win32':
import msvcrt
msvcrt.setmode(infile.fileno(), os.O_BINARY)
msvcrt.setmode(outfile.fileno(), os.O_BINARY)
io = inputoutput.Popen2IO(infile, outfile) io = inputoutput.Popen2IO(infile, outfile)
super(PopenCmdGateway, self).__init__(io=io) super(PopenCmdGateway, self).__init__(io=io)
class PopenGateway(PopenCmdGateway): class PopenGateway(PopenCmdGateway):
""" This Gateway provides interaction with a newly started """ This Gateway provides interaction with a newly started
python subprocess. python subprocess.

View File

@ -3,6 +3,9 @@ A utility to build a Python extension module from C, wrapping distutils.
""" """
import py import py
# set to true for automatic re-compilation of extensions
AUTOREGEN = True
# XXX we should distutils in a subprocess, because it messes up the # XXX we should distutils in a subprocess, because it messes up the
# environment and who knows what else. Currently we just save # environment and who knows what else. Currently we just save
# and restore os.environ. # and restore os.environ.
@ -32,7 +35,7 @@ def make_module_from_c(cfile):
lib = dirpath.join(modname+ext) lib = dirpath.join(modname+ext)
# XXX argl! we need better "build"-locations alltogether! # XXX argl! we need better "build"-locations alltogether!
if lib.check() and lib.stat().mtime < cfile.stat().mtime: if lib.check() and AUTOREGEN and lib.stat().mtime < cfile.stat().mtime:
try: try:
lib.remove() lib.remove()
except EnvironmentError: except EnvironmentError:

View File

@ -8,6 +8,10 @@ def test_win_killsubprocess():
py.test.skip("you\'re using an older version of windows, which " py.test.skip("you\'re using an older version of windows, which "
"doesn\'t support 'taskkill' - py.misc.killproc is not " "doesn\'t support 'taskkill' - py.misc.killproc is not "
"available") "available")
try:
import subprocess
except ImportError:
py.test.skip("no subprocess module")
tmp = py.test.ensuretemp("test_win_killsubprocess") tmp = py.test.ensuretemp("test_win_killsubprocess")
t = tmp.join("t.py") t = tmp.join("t.py")
t.write("import time ; time.sleep(100)") t.write("import time ; time.sleep(100)")

156
setup.py
View File

@ -1,25 +1,46 @@
""" """
setup file for 'py' package based on: setup file for 'py' package based on:
https://codespeak.net/svn/py/trunk, revision=57462 https://codespeak.net/svn/py/trunk, revision=57536
autogenerated by gensetup.py autogenerated by gensetup.py
""" """
import os, sys import os, sys
if 1: # set to zero if you want plain distutils import ez_setup
import ez_setup ez_setup.use_setuptools()
ez_setup.use_setuptools() from setuptools import setup, Extension
from setuptools import setup, Extension
else:
from distutils.core import setup, Extension
long_description = """
The py lib is a development support library featuring these tools and APIs:
- `py.test`_: cross-project testing tool with many advanced features
- `py.execnet`_: ad-hoc code distribution to SSH, Socket and local sub processes
- `py.magic.greenlet`_: micro-threads on standard CPython ("stackless-light") and PyPy
- `py.path`_: path abstractions over local and subversion files
- `py.code`_: dynamic code compile and traceback printing support
The py lib and its tools should work well on Linux, Win32,
OSX, Python versions 2.3-2.6. For questions please go to
http://pylib.org/contact.html
.. _`py.test`: http://pylib.org/test.html
.. _`py.execnet`: http://pylib.org/execnet.html
.. _`py.magic.greenlet`: http://pylib.org/greenlet.html
.. _`py.path`: http://pylib.org/path.html
.. _`py.code`: http://pylib.org/code.html
"""
def main(): def main():
setup(cmdclass=cmdclass, setup(
name='py', name='py',
description='pylib and py.test: agile development and test support library', description='pylib and py.test: agile development and test support library',
long_description = long_description,
version='1.0.0a1', version='1.0.0a1',
url='http://pylib.org', url='http://pylib.org',
download_url='http://codespeak.net/py/0.9.2/download.html',
license='MIT license', license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
author='holger krekel, Guido Wesdorp, Carl Friedrich Bolz, Armin Rigo, Maciej Fijalkowski & others', author='holger krekel, Guido Wesdorp, Carl Friedrich Bolz, Armin Rigo, Maciej Fijalkowski & others',
@ -27,9 +48,13 @@ def main():
ext_modules = [Extension("py.c-extension.greenlet.greenlet", ext_modules = [Extension("py.c-extension.greenlet.greenlet",
["py/c-extension/greenlet/greenlet.c"]),], ["py/c-extension/greenlet/greenlet.c"]),],
py_modules=['_findpy'], entry_points={'console_scripts': ['py.cleanup = py.cmdline:pycleanup',
long_description='the py lib is a development support library featuring py.test, ad-hoc distributed execution, micro-threads and svn abstractions.', 'py.countloc = py.cmdline:pycountloc',
classifiers=['Development Status :: 3 - Alpha', 'py.lookup = py.cmdline:pylookup',
'py.rest = py.cmdline:pyrest',
'py.test = py.cmdline:pytest',
'py.which = py.cmdline:pywhich']},
classifiers=['Development Status :: 4 - Beta',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
'Operating System :: POSIX', 'Operating System :: POSIX',
@ -40,12 +65,6 @@ def main():
'Topic :: System :: Distributed Computing', 'Topic :: System :: Distributed Computing',
'Topic :: Utilities', 'Topic :: Utilities',
'Programming Language :: Python'], 'Programming Language :: Python'],
scripts=['py/bin/py.cleanup',
'py/bin/py.countloc',
'py/bin/py.lookup',
'py/bin/py.rest',
'py/bin/py.test',
'py/bin/py.which'],
packages=['py', packages=['py',
'py.apigen', 'py.apigen',
'py.apigen.rest', 'py.apigen.rest',
@ -61,6 +80,8 @@ def main():
'py.builtin', 'py.builtin',
'py.builtin.testing', 'py.builtin.testing',
'py.c-extension', 'py.c-extension',
'py.cmdline',
'py.cmdline.testing',
'py.code', 'py.code',
'py.code.testing', 'py.code.testing',
'py.compat', 'py.compat',
@ -117,13 +138,20 @@ def main():
'apigen/style.css', 'apigen/style.css',
'apigen/todo-apigen.txt', 'apigen/todo-apigen.txt',
'apigen/todo.txt', 'apigen/todo.txt',
'bin/_docgen.py',
'bin/_findpy.py', 'bin/_findpy.py',
'bin/_genscripts.py',
'bin/py.cleanup', 'bin/py.cleanup',
'bin/py.countloc', 'bin/py.countloc',
'bin/py.lookup', 'bin/py.lookup',
'bin/py.rest', 'bin/py.rest',
'bin/py.test', 'bin/py.test',
'bin/py.which', 'bin/py.which',
'bin/win32/py.cleanup.cmd',
'bin/win32/py.countloc.cmd',
'bin/win32/py.lookup.cmd',
'bin/win32/py.rest.cmd',
'bin/win32/py.test.cmd',
'c-extension/greenlet/README.txt', 'c-extension/greenlet/README.txt',
'c-extension/greenlet/dummy_greenlet.py', 'c-extension/greenlet/dummy_greenlet.py',
'c-extension/greenlet/greenlet.c', 'c-extension/greenlet/greenlet.c',
@ -201,100 +229,6 @@ def main():
zip_safe=False, zip_safe=False,
) )
class Win32PathHandling:
""" a helper to remove things added to system PATHs in previous installations. """
_winreg = None
def __init__(self):
if sys.platform == 'win32':
try:
import _winreg
except ImportError:
print sys.stderr, "huh could not import _winreg on windows, ignoring"
else:
self._winreg = _winreg
def remove_pylib_path(self):
reg = self._winreg.ConnectRegistry(
None, self._winreg.HKEY_LOCAL_MACHINE)
key = r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
path = self.get_registry_value(reg, key, "Path")
newpath = self.prunepath(path)
if newpath != path:
print "PATH contains old py/bin/win32 scripts:", path
print "pruning and setting a new PATH:", newpath
self.set_registry_value(reg, key, "Path", newpath)
# Propagate changes to current command prompt
os.system("set PATH=%s" % path)
self.try_propagate_system()
def prunepath(self, path):
basename = os.path.basename
dirname = os.path.dirname
l = []
for p in path.split(';'):
if basename(p) == "win32" and basename(dirname(p)) == "bin" \
and basename(dirname(dirname(p))) == "py":
continue # prune this path
l.append(p)
return ";".join(l)
def try_propagate_system(self):
try:
import win32gui, win32con
except ImportError:
return
# Propagate changes throughout the system
win32gui.SendMessageTimeout(win32con.HWND_BROADCAST,
win32con.WM_SETTINGCHANGE, 0, "Environment",
win32con.SMTO_ABORTIFHUNG, 5000)
def get_registry_value(self, reg, key, value_name):
k = self._winreg.OpenKey(reg, key)
value = self._winreg.QueryValueEx(k, value_name)[0]
self._winreg.CloseKey(k)
return value
def set_registry_value(self, reg, key, value_name, value):
k = self._winreg.OpenKey(reg, key, 0, self._winreg.KEY_WRITE)
value_type = self._winreg.REG_SZ
# if we handle the Path value, then set its type to REG_EXPAND_SZ
# so that things like %SystemRoot% get automatically expanded by the
# command prompt
if value_name == "Path":
value_type = self._winreg.REG_EXPAND_SZ
self._winreg.SetValueEx(k, value_name, 0, value_type, value)
self._winreg.CloseKey(k)
# on windows we need to hack up the to-be-installed scripts
from distutils.command.install_scripts import install_scripts
class my_install_scripts(install_scripts):
def run(self):
install_scripts.run(self)
#print self.outfiles
for fn in self.outfiles:
basename = os.path.basename(fn)
if "." in basename:
#print "tackling", fn
newbasename = basename.replace(".", "_")
newfn = os.path.join(os.path.dirname(fn), newbasename)
if os.path.exists(newfn):
os.remove(newfn)
os.rename(fn, newfn)
newname = fn + ".cmd"
if os.path.exists(newname):
os.remove(newname)
f = open(newname, 'w')
f.write("@echo off\n")
f.write('python "%%~dp0\py_command_trampolin" %s %%*\n' % basename)
f.close()
w32path = Win32PathHandling()
w32path.remove_pylib_path()
if sys.platform == "win32":
cmdclass = {'install_scripts': my_install_scripts}
else:
cmdclass = {}
if __name__ == '__main__': if __name__ == '__main__':
main() main()