refined usage and options for "py.cleanup":
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files py.cleanup -e .swp -e .cache # also remove files with these extensions py.cleanup -s # remove "build" and "dist" directory next to setup.py files py.cleanup -d # also remove empty directories py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'" py.cleanup -n # dry run, only show what would be removed --HG-- branch : trunk
This commit is contained in:
parent
3234e6e978
commit
a3d15b2c60
21
CHANGELOG
21
CHANGELOG
|
@ -1,22 +1,37 @@
|
|||
Changes between 1.2.1 and 1.2.0
|
||||
=====================================
|
||||
|
||||
- add a new option "--funcargs" that shows available funcargs
|
||||
and their help strings (docstrings on the factory) for a
|
||||
given test path
|
||||
- refined usage and options for "py.cleanup":
|
||||
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
|
||||
py.cleanup -e .swp -e .cache # also remove files with these extensions
|
||||
py.cleanup -s # remove "build" and "dist" directory next to setup.py files
|
||||
py.cleanup -d # also remove empty directories
|
||||
py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
|
||||
py.cleanup -n # dry run, only show what would be removed
|
||||
|
||||
- add a new option "py.test --funcargs" which shows available funcargs
|
||||
and their help strings (docstrings on their respective factory function)
|
||||
for a given test path
|
||||
|
||||
- display a short and concise traceback if a funcarg lookup fails
|
||||
|
||||
- early-load "test*/conftest.py" files, i.e. conftest.py files in
|
||||
directories starting with 'test'. allows to conveniently keep and access
|
||||
test-related options without having to put a conftest.py into the package root dir.
|
||||
|
||||
- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
|
||||
|
||||
- fix issue78: always call python-level teardown functions even if the
|
||||
according setup failed. This includes refinements for calling setup_module/class functions
|
||||
which will now only be called once instead of the previous behaviour where they'd be called
|
||||
multiple times if they raise an exception (including a Skipped exception). Any exception
|
||||
will be re-corded and associated with all tests in the according module/class scope.
|
||||
|
||||
- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
|
||||
|
||||
- update apipkg.py to fix an issue where recursive imports might
|
||||
unnecessarily break importing
|
||||
|
||||
- fix plugin links
|
||||
|
||||
Changes between 1.2 and 1.1.1
|
||||
|
|
|
@ -1,47 +1,86 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""\
|
||||
py.cleanup [PATH]
|
||||
py.cleanup [PATH] ...
|
||||
|
||||
Delete typical python development related files recursively under the specified PATH (which defaults to the current working directory). Don't follow links and don't recurse into directories with a dot. Optionally remove setup.py related files and empty
|
||||
directories.
|
||||
|
||||
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
|
||||
import sys, subprocess
|
||||
|
||||
def main():
|
||||
parser = py.std.optparse.OptionParser(usage=__doc__)
|
||||
parser.add_option("-e", "--remove", dest="ext", default=".pyc", action="store",
|
||||
help="remove files with the given comma-separated list of extensions"
|
||||
)
|
||||
parser.add_option("-e", metavar="ENDING",
|
||||
dest="endings", default=[".pyc", "$py.class"], action="append",
|
||||
help=("(multi) recursively remove files with the given ending."
|
||||
" '.pyc' and '$py.class' are in the default list."))
|
||||
parser.add_option("-d", action="store_true", dest="removedir",
|
||||
help="remove empty directories.")
|
||||
parser.add_option("-s", action="store_true", dest="setup",
|
||||
help="remove 'build' and 'dist' directories next to setup.py files")
|
||||
parser.add_option("-a", action="store_true", dest="all",
|
||||
help="synonym for '-S -d -e pip-log.txt'")
|
||||
parser.add_option("-n", "--dryrun", dest="dryrun", default=False,
|
||||
action="store_true",
|
||||
help="display would-be-removed filenames"
|
||||
)
|
||||
parser.add_option("-d", action="store_true", dest="removedir",
|
||||
help="remove empty directories")
|
||||
help="don't actually delete but display would-be-removed filenames.")
|
||||
(options, args) = parser.parse_args()
|
||||
if not args:
|
||||
args = ["."]
|
||||
ext = options.ext.split(",")
|
||||
def shouldremove(p):
|
||||
return p.ext in ext
|
||||
|
||||
for arg in args:
|
||||
path = py.path.local(arg)
|
||||
py.builtin.print_("cleaning path", path, "of extensions", ext)
|
||||
for x in path.visit(shouldremove, lambda x: x.check(dotfile=0, link=0)):
|
||||
remove(x, options)
|
||||
if options.removedir:
|
||||
for x in path.visit(lambda x: x.check(dir=1),
|
||||
lambda x: x.check(dotfile=0, link=0)):
|
||||
if not x.listdir():
|
||||
remove(x, options)
|
||||
|
||||
def remove(path, options):
|
||||
if options.dryrun:
|
||||
py.builtin.print_("would remove", path)
|
||||
else:
|
||||
py.builtin.print_("removing", path)
|
||||
path.remove()
|
||||
|
||||
Cleanup(options, args).main()
|
||||
|
||||
class Cleanup:
|
||||
def __init__(self, options, args):
|
||||
if not args:
|
||||
args = ["."]
|
||||
self.options = options
|
||||
self.args = [py.path.local(x) for x in args]
|
||||
if options.all:
|
||||
options.setup = True
|
||||
options.removedir = True
|
||||
options.endings.append("pip-log.txt")
|
||||
|
||||
def main(self):
|
||||
if self.options.setup:
|
||||
for arg in self.args:
|
||||
self.setupclean(arg)
|
||||
|
||||
for path in self.args:
|
||||
py.builtin.print_("cleaning path", path,
|
||||
"of extensions", self.options.endings)
|
||||
for x in path.visit(self.shouldremove, self.recursedir):
|
||||
self.remove(x)
|
||||
if self.options.removedir:
|
||||
for x in path.visit(lambda x: x.check(dir=1), self.recursedir):
|
||||
if not x.listdir():
|
||||
self.remove(x)
|
||||
|
||||
def shouldremove(self, p):
|
||||
for ending in self.options.endings:
|
||||
if p.basename.endswith(ending):
|
||||
return True
|
||||
|
||||
def recursedir(self, path):
|
||||
return path.check(dotfile=0, link=0)
|
||||
|
||||
def remove(self, path):
|
||||
if not path.check():
|
||||
return
|
||||
if self.options.dryrun:
|
||||
py.builtin.print_("would remove", path)
|
||||
else:
|
||||
py.builtin.print_("removing", path)
|
||||
path.remove()
|
||||
|
||||
def XXXcallsetup(self, setup, *args):
|
||||
old = setup.dirpath().chdir()
|
||||
try:
|
||||
subprocess.call([sys.executable, str(setup)] + list(args))
|
||||
finally:
|
||||
old.chdir()
|
||||
|
||||
def setupclean(self, path):
|
||||
for x in path.visit("setup.py", self.recursedir):
|
||||
basepath = x.dirpath()
|
||||
self.remove(basepath / "build")
|
||||
self.remove(basepath / "dist")
|
||||
|
|
|
@ -45,8 +45,10 @@ class TestPyCleanup:
|
|||
assert p.check()
|
||||
pyc = p.new(ext='pyc')
|
||||
pyc.ensure()
|
||||
pyclass = p.new(basename=p.basename + '$py.class')
|
||||
result = testdir.runpybin("py.cleanup", tmpdir)
|
||||
assert not pyc.check()
|
||||
assert not pyclass.check()
|
||||
|
||||
def test_dir_remove_simple(self, testdir, tmpdir):
|
||||
subdir = tmpdir.mkdir("subdir")
|
||||
|
@ -59,3 +61,43 @@ class TestPyCleanup:
|
|||
result = testdir.runpybin("py.cleanup", tmpdir, '-d')
|
||||
assert result.ret == 0
|
||||
assert not subdir.check()
|
||||
|
||||
@py.test.mark.multi(opt=["-s"])
|
||||
def test_remove_setup_simple(self, testdir, tmpdir, opt):
|
||||
subdir = tmpdir.mkdir("subdir")
|
||||
p = subdir.ensure("setup.py")
|
||||
subdir.mkdir("build").ensure("hello", "world.py")
|
||||
egg1 = subdir.mkdir("something.egg-info")
|
||||
egg1.mkdir("whatever")
|
||||
okbuild = subdir.mkdir("preserved1").mkdir("build")
|
||||
egg2 = subdir.mkdir("preserved2").mkdir("other.egg-info")
|
||||
subdir.mkdir("dist")
|
||||
result = testdir.runpybin("py.cleanup", opt, subdir)
|
||||
assert result.ret == 0
|
||||
assert okbuild.check()
|
||||
assert egg1.check()
|
||||
assert egg2.check()
|
||||
assert subdir.join("preserved1").check()
|
||||
assert subdir.join("preserved2").check()
|
||||
assert not subdir.join("build").check()
|
||||
assert not subdir.join("dist").check()
|
||||
|
||||
def test_remove_all(self, testdir, tmpdir):
|
||||
tmpdir.ensure("setup.py")
|
||||
tmpdir.ensure("build", "xyz.py")
|
||||
tmpdir.ensure("dist", "abc.py")
|
||||
piplog = tmpdir.ensure("preserved2", "pip-log.txt")
|
||||
tmpdir.ensure("hello.egg-info")
|
||||
setup = tmpdir.ensure("setup.py")
|
||||
tmpdir.ensure("src/a/b")
|
||||
x = tmpdir.ensure("src/x.py")
|
||||
x2 = tmpdir.ensure("src/x.pyc")
|
||||
x3 = tmpdir.ensure("src/x$py.class")
|
||||
result = testdir.runpybin("py.cleanup", "-a", tmpdir)
|
||||
assert result.ret == 0
|
||||
assert len(tmpdir.listdir()) == 3
|
||||
assert setup.check()
|
||||
assert x.check()
|
||||
assert not x2.check()
|
||||
assert not x3.check()
|
||||
assert not piplog.check()
|
||||
|
|
Loading…
Reference in New Issue