[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:
parent
c0d524139e
commit
a999dc8472
17
CHANGELOG
17
CHANGELOG
|
@ -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
|
||||
===============================
|
||||
|
||||
* refined installation and metadata, created new setup.py,
|
||||
now based on setuptools/ez_setup (by flipping a bit you
|
||||
can use distutils).
|
||||
now based on setuptools/ez_setup (thanks to Ralf Schmitt
|
||||
for his support).
|
||||
|
||||
* improved the way of making py.* scripts available in
|
||||
windows environments, they are now added to the
|
||||
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
|
||||
(follows the filenames:LINENO: MSG convention)
|
||||
(thanks to Osmo Salomaa)
|
||||
|
||||
* fix to javascript-generation, "py.test --runbrowser"
|
||||
should work more reliably now
|
||||
|
|
16
MANIFEST
16
MANIFEST
|
@ -61,13 +61,20 @@ py/apigen/tracer/testing/test_docgen.py
|
|||
py/apigen/tracer/testing/test_model.py
|
||||
py/apigen/tracer/testing/test_package.py
|
||||
py/apigen/tracer/tracer.py
|
||||
py/bin/_docgen.py
|
||||
py/bin/_findpy.py
|
||||
py/bin/_genscripts.py
|
||||
py/bin/py.cleanup
|
||||
py/bin/py.countloc
|
||||
py/bin/py.lookup
|
||||
py/bin/py.rest
|
||||
py/bin/py.test
|
||||
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/enumerate.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_remote.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/code.py
|
||||
py/code/excinfo.py
|
||||
|
@ -419,4 +434,5 @@ py/xmlobj/testing/test_html.py
|
|||
py/xmlobj/testing/test_xml.py
|
||||
py/xmlobj/visit.py
|
||||
py/xmlobj/xml.py
|
||||
setup.cfg
|
||||
setup.py
|
37
_findpy.py
37
_findpy.py
|
@ -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__
|
|
@ -16,6 +16,7 @@ copyrighted by one or more of the following people and organizations:
|
|||
Contributors include::
|
||||
|
||||
Samuele Pedroni
|
||||
Chris Lamb
|
||||
Harald Armin Massa
|
||||
Ralf Schmitt
|
||||
Ian Bicking
|
||||
|
|
|
@ -1,9 +1,24 @@
|
|||
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
the py lib is a development support library featuring
|
||||
py.test, ad-hoc distributed execution, micro-threads
|
||||
and svn abstractions.
|
||||
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
|
||||
|
||||
"""
|
||||
from initpkg import initpkg
|
||||
|
||||
|
@ -11,18 +26,18 @@ version = "1.0.0a1"
|
|||
|
||||
initpkg(__name__,
|
||||
description = "pylib and py.test: agile development and test support library",
|
||||
revision = int('$LastChangedRevision: 57529 $'.split(':')[1][:-1]),
|
||||
lastchangedate = '$LastChangedDate: 2008-08-21 09:48:44 +0200 (Thu, 21 Aug 2008) $',
|
||||
revision = int('$LastChangedRevision: 57540 $'.split(':')[1][:-1]),
|
||||
lastchangedate = '$LastChangedDate: 2008-08-21 12:18:58 +0200 (Thu, 21 Aug 2008) $',
|
||||
version = version,
|
||||
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",
|
||||
platforms = ['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
||||
author = "holger krekel, Guido Wesdorp, Carl Friedrich Bolz, Armin Rigo, Maciej Fijalkowski & others",
|
||||
author_email = "holger at merlinux.eu, py-dev at codespeak.net",
|
||||
long_description = globals()['__doc__'],
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: POSIX",
|
||||
|
@ -38,6 +53,13 @@ initpkg(__name__,
|
|||
|
||||
# EXPORTED API
|
||||
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
|
||||
'test.__doc__' : ('./test/__init__.py', '__doc__'),
|
||||
'test.raises' : ('./test/outcome.py', 'raises'),
|
||||
|
|
|
@ -21,8 +21,21 @@ def pkg_to_dict(module):
|
|||
for key, value in defs.iteritems():
|
||||
chain = key.split('.')
|
||||
base = module
|
||||
for elem in chain:
|
||||
base = getattr(base, elem)
|
||||
# XXX generalize this:
|
||||
# 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] == '*':
|
||||
d.update(get_star_import_tree(base, key))
|
||||
else:
|
||||
|
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -1,24 +1,3 @@
|
|||
#!/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 ".".
|
||||
"""
|
||||
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()
|
||||
#!/usr/bin/env python
|
||||
from _findpy import py
|
||||
py.cmdline.pycleanup()
|
|
@ -1,23 +1,3 @@
|
|||
#!/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
|
||||
|
||||
parser = optparse.OptionParser(usage=__doc__)
|
||||
|
||||
if __name__ == '__main__':
|
||||
(options, args) = parser.parse_args()
|
||||
countloc(args)
|
||||
from _findpy import py
|
||||
py.cmdline.pycountloc()
|
|
@ -1,79 +1,3 @@
|
|||
#!/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__))
|
||||
#!/usr/bin/env python
|
||||
from _findpy import py
|
||||
try:
|
||||
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
|
||||
py.cmdline.pylookup()
|
|
@ -1,79 +1,3 @@
|
|||
#!/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 py.__.misc import rest
|
||||
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)
|
||||
|
||||
py.cmdline.pyrest()
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from _findpy import py
|
||||
py.test.cmdline.main()
|
||||
#!/usr/bin/env python
|
||||
from _findpy import py
|
||||
py.cmdline.pytest()
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%~dp0\..\py.cleanup" %*
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%~dp0\..\py.countloc" %*
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%~dp0\..\py.lookup" %*
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%~dp0\..\py.rest" %*
|
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
python "%~dp0\..\py.test" %*
|
|
@ -0,0 +1 @@
|
|||
#
|
|
@ -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()
|
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
import py
|
||||
|
||||
def main():
|
||||
py.test.cmdline.main()
|
|
@ -0,0 +1 @@
|
|||
#
|
|
@ -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
|
||||
|
|
@ -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`_
|
||||
`download py-0.9.0.zip`_
|
||||
easy_install py
|
||||
|
||||
.. _`download py-0.9.0.tar.gz`: http://codespeak.net/download/py/py-0.9.0.tar.gz
|
||||
.. _`download py-0.9.0.zip`: http://codespeak.net/download/py/py-0.9.0.zip
|
||||
to get the latest release of the py lib. On non-Windows systems you will
|
||||
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`_
|
||||
or `used locally`_.
|
||||
**IMPORTANT NOTE**: if you are using Windows and have previous
|
||||
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
|
||||
module (greenlet) yet and thus greenlets will not work
|
||||
out of the box.
|
||||
.. _`setuptools installation`: http://pypi.python.org/pypi/setuptools
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
and unpack it to a directory, where you then type::
|
||||
|
||||
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``
|
||||
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.
|
||||
Installing from subversion / develop mode
|
||||
============================================
|
||||
|
||||
There is a convenient way for Bash/Shell based systems
|
||||
to setup the ``PYTHONPATH`` as well as the shell ``PATH``, insert::
|
||||
To follow development or help with fixing things
|
||||
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
|
||||
specify your own checkout-directory.
|
||||
You should then be able to issue::
|
||||
|
||||
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`
|
||||
which contains your svn-controlled root package::
|
||||
python ~/path/to/checkout/py/env.py
|
||||
|
||||
svn propedit 'svn:externals' DIRECTORY
|
||||
or on windows:
|
||||
|
||||
which will open an editor where you can add
|
||||
the following line:
|
||||
\\path\\to\\checkout\\py\\env.cmd
|
||||
|
||||
py http://codespeak.net/svn/py/dist
|
||||
|
||||
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
|
||||
to get settings for PYTHONPATH and PATH.
|
||||
|
||||
|
||||
py subversion directory structure
|
||||
|
|
|
@ -5,8 +5,6 @@ Implementation and Customization of ``py.test``
|
|||
.. contents::
|
||||
.. sectnum::
|
||||
|
||||
|
||||
|
||||
.. _`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
|
||||
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`:
|
||||
|
||||
test items are collectors as well
|
||||
|
@ -84,48 +88,28 @@ it, otherwise we consider the "test" as passed.
|
|||
|
||||
.. _`package name`:
|
||||
|
||||
constructing the package name for modules
|
||||
-----------------------------------------
|
||||
constructing the package name for test modules
|
||||
-------------------------------------------------
|
||||
|
||||
Test modules are imported under their fully qualified
|
||||
name. Given a module ``path`` the fully qualified package
|
||||
name is constructed as follows:
|
||||
name. Given a filesystem ``fspath`` it is constructed as follows:
|
||||
|
||||
* determine the last "upward" directory from ``path`` that
|
||||
contains an ``__init__.py`` file. Going upwards
|
||||
means repeatedly calling the ``dirpath()`` method
|
||||
on a path object (which returns the parent directory
|
||||
as a path object).
|
||||
* walk the directories up to the last one that contains
|
||||
an ``__init__.py`` file.
|
||||
|
||||
* insert this base directory into the sys.path list
|
||||
as its first element
|
||||
* perform ``sys.path.insert(0, basedir)``.
|
||||
|
||||
* import the root package
|
||||
* import the root package as ``root``
|
||||
|
||||
* determine the fully qualified name for the module located
|
||||
at ``path`` ...
|
||||
* determine the fully qualified name for ``fspath`` by either:
|
||||
|
||||
* if the imported root package has a __package__ object
|
||||
then call ``__package__.getimportname(path)``
|
||||
* calling ``root.__pkg__.getimportname(fspath)`` if the
|
||||
``__pkg__`` exists.` or
|
||||
|
||||
* otherwise use the relative path of the module path to
|
||||
the base dir and turn slashes into dots and strike
|
||||
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
|
||||
|
@ -256,32 +240,27 @@ Customizing the collection process in a module
|
|||
If you have a module where you want to take responsibility for
|
||||
collecting your own test Items and possibly even for executing
|
||||
a test then you can provide `generative tests`_ that yield
|
||||
callables and possibly arguments as a tuple. This should
|
||||
serve some immediate purposes like paramtrized tests.
|
||||
callables and possibly arguments as a tuple. This is especially
|
||||
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
|
||||
|
||||
The other extension possibility goes deeper into the machinery
|
||||
and allows you to specify a custom test ``Item`` class which
|
||||
The other extension possibility is about
|
||||
specifying a custom test ``Item`` class which
|
||||
is responsible for setting up and executing an underlying
|
||||
test. [XXX not working: You can integrate your custom ``py.test.collect.Item`` subclass
|
||||
by binding an ``Item`` name to a test class.] Or you can
|
||||
extend the collection process for a whole directory tree
|
||||
by putting Items in a ``conftest.py`` configuration file.
|
||||
The collection process constantly looks at according names
|
||||
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.
|
||||
test. Or you can extend the collection process for a whole
|
||||
directory tree by putting Items in a ``conftest.py`` configuration file.
|
||||
The collection process dynamically consults the *chain of conftest.py*
|
||||
modules to determine collectors and items at ``Directory``, ``Module``,
|
||||
``Class``, ``Function`` or ``Generator`` level respectively.
|
||||
|
||||
Customizing execution of Functions
|
||||
----------------------------------
|
||||
|
||||
- Function test items allow total control of executing their
|
||||
contained test method. ``function.run()`` will get called by the
|
||||
- ``py.test.collect.Function`` test items control execution
|
||||
of a test function. ``function.run()`` will get called by the
|
||||
session in order to actually run a test. The method is responsible
|
||||
for performing proper setup/teardown ("Test Fixtures") for a
|
||||
Function test.
|
||||
|
@ -290,5 +269,4 @@ Customizing execution of Functions
|
|||
the default ``Function.run()`` to actually execute a python
|
||||
function with the given (usually empty set of) arguments.
|
||||
|
||||
|
||||
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
py lib documentation
|
||||
=================================================
|
||||
|
||||
The py lib aims at supporting a decent development process
|
||||
addressing deployment, versioning, testing and documentation
|
||||
perspectives.
|
||||
The py lib is a development support library featuring
|
||||
py.test, ad-hoc distributed execution, micro-threads
|
||||
(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`_
|
||||
|
||||
`0.9.0 release announcement`_
|
||||
`0.9.2 release announcement`_
|
||||
|
||||
Main tools and API
|
||||
----------------------
|
||||
|
@ -20,6 +22,8 @@ Main tools and API
|
|||
|
||||
`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.
|
||||
|
||||
`apigen`_: a new way to generate rich Python API documentation
|
||||
|
@ -27,8 +31,6 @@ Main tools and API
|
|||
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.io`_: Helper Classes for Capturing of Input/Output
|
||||
|
@ -59,4 +61,4 @@ Background and Motivation information
|
|||
.. _`Why What how py?`: why_py.html
|
||||
.. _`future`: future.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
|
||||
|
|
|
@ -5,7 +5,7 @@ Welcome to the 0.9.2 py lib and py.test release -
|
|||
mainly fixing Windows issues, providing better
|
||||
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.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:
|
||||
|
||||
Download/Install: http://codespeak.net/py/0.9.2/download.html
|
||||
|
||||
Documentation/API: http://codespeak.net/py/0.9.2/index.html
|
||||
|
||||
best and have fun,
|
||||
|
|
|
@ -59,10 +59,6 @@ import sys
|
|||
class Popen2IO:
|
||||
server_stmt = """
|
||||
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)
|
||||
sys.stdout = sys.stderr = StringIO.StringIO()
|
||||
#try:
|
||||
|
@ -75,6 +71,11 @@ sys.stdout = sys.stderr = StringIO.StringIO()
|
|||
|
||||
def __init__(self, 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.lock = thread.allocate_lock()
|
||||
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
import os, inspect, socket
|
||||
import sys
|
||||
from py.magic import autopath ; mypath = autopath()
|
||||
|
||||
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
|
||||
# for bootstrapping gateways
|
||||
|
@ -51,13 +55,10 @@ class InstallableGateway(gateway.Gateway):
|
|||
class PopenCmdGateway(InstallableGateway):
|
||||
def __init__(self, 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)
|
||||
super(PopenCmdGateway, self).__init__(io=io)
|
||||
|
||||
|
||||
class PopenGateway(PopenCmdGateway):
|
||||
""" This Gateway provides interaction with a newly started
|
||||
python subprocess.
|
||||
|
|
|
@ -3,6 +3,9 @@ A utility to build a Python extension module from C, wrapping distutils.
|
|||
"""
|
||||
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
|
||||
# environment and who knows what else. Currently we just save
|
||||
# and restore os.environ.
|
||||
|
@ -32,7 +35,7 @@ def make_module_from_c(cfile):
|
|||
lib = dirpath.join(modname+ext)
|
||||
|
||||
# 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:
|
||||
lib.remove()
|
||||
except EnvironmentError:
|
||||
|
|
|
@ -8,6 +8,10 @@ def test_win_killsubprocess():
|
|||
py.test.skip("you\'re using an older version of windows, which "
|
||||
"doesn\'t support 'taskkill' - py.misc.killproc is not "
|
||||
"available")
|
||||
try:
|
||||
import subprocess
|
||||
except ImportError:
|
||||
py.test.skip("no subprocess module")
|
||||
tmp = py.test.ensuretemp("test_win_killsubprocess")
|
||||
t = tmp.join("t.py")
|
||||
t.write("import time ; time.sleep(100)")
|
||||
|
|
156
setup.py
156
setup.py
|
@ -1,25 +1,46 @@
|
|||
"""
|
||||
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
|
||||
"""
|
||||
import os, sys
|
||||
|
||||
if 1: # set to zero if you want plain distutils
|
||||
import ez_setup
|
||||
ez_setup.use_setuptools()
|
||||
from setuptools import setup, Extension
|
||||
else:
|
||||
from distutils.core import setup, Extension
|
||||
import ez_setup
|
||||
ez_setup.use_setuptools()
|
||||
from setuptools 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():
|
||||
setup(cmdclass=cmdclass,
|
||||
setup(
|
||||
name='py',
|
||||
description='pylib and py.test: agile development and test support library',
|
||||
long_description = long_description,
|
||||
version='1.0.0a1',
|
||||
url='http://pylib.org',
|
||||
download_url='http://codespeak.net/py/0.9.2/download.html',
|
||||
license='MIT license',
|
||||
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
||||
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",
|
||||
["py/c-extension/greenlet/greenlet.c"]),],
|
||||
|
||||
py_modules=['_findpy'],
|
||||
long_description='the py lib is a development support library featuring py.test, ad-hoc distributed execution, micro-threads and svn abstractions.',
|
||||
classifiers=['Development Status :: 3 - Alpha',
|
||||
entry_points={'console_scripts': ['py.cleanup = py.cmdline:pycleanup',
|
||||
'py.countloc = py.cmdline:pycountloc',
|
||||
'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',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: POSIX',
|
||||
|
@ -40,12 +65,6 @@ def main():
|
|||
'Topic :: System :: Distributed Computing',
|
||||
'Topic :: Utilities',
|
||||
'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',
|
||||
'py.apigen',
|
||||
'py.apigen.rest',
|
||||
|
@ -61,6 +80,8 @@ def main():
|
|||
'py.builtin',
|
||||
'py.builtin.testing',
|
||||
'py.c-extension',
|
||||
'py.cmdline',
|
||||
'py.cmdline.testing',
|
||||
'py.code',
|
||||
'py.code.testing',
|
||||
'py.compat',
|
||||
|
@ -117,13 +138,20 @@ def main():
|
|||
'apigen/style.css',
|
||||
'apigen/todo-apigen.txt',
|
||||
'apigen/todo.txt',
|
||||
'bin/_docgen.py',
|
||||
'bin/_findpy.py',
|
||||
'bin/_genscripts.py',
|
||||
'bin/py.cleanup',
|
||||
'bin/py.countloc',
|
||||
'bin/py.lookup',
|
||||
'bin/py.rest',
|
||||
'bin/py.test',
|
||||
'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/dummy_greenlet.py',
|
||||
'c-extension/greenlet/greenlet.c',
|
||||
|
@ -201,100 +229,6 @@ def main():
|
|||
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__':
|
||||
main()
|
||||
|
Loading…
Reference in New Issue