Skip to content
Snippets Groups Projects
Commit 22105bdb authored by Thomas Reifenberger's avatar Thomas Reifenberger
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
mkp/_version.py export-subst
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# pyenv
.python-version
# Vim
*.swp
include README.md
include versioneer.py
include mkp/_version.py
import ast
import io
import os
import os.path
import pprint
import tarfile
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
_DIRECTORIES = [
'agents', 'checkman', 'checks', 'doc', 'inventory', 'notifications',
'pnp-templates', 'web',
]
_VERSION_PACKAGED = 'python-mkp'
def load_bytes(data):
bytes_io = io.BytesIO(data)
return Package(bytes_io)
def find_files(path):
result = {}
for directory in _DIRECTORIES:
result[directory] = _find_files_in_directory(os.path.join(path, directory))
return result
def _find_files_in_directory(path):
result = []
for root, dirs, files in os.walk(path):
for dirname in dirs:
if dirname.startswith('.'):
dirs.remove(dirname)
for filename in files:
if filename.startswith('.'):
continue
elif filename.endswith('~'):
continue
abspath = os.path.join(root, filename)
relpath = os.path.relpath(abspath, start=path)
result.append(relpath)
return result
def pack_to_bytes(info, path):
_patch_info(info)
bytes_io = io.BytesIO()
with tarfile.open(fileobj=bytes_io, mode='w:gz') as archive:
info_data = pprint.pformat(info).encode()
tarinfo, fileobj = _create_tarinfo_and_buffer(info_data, 'info')
archive.addfile(tarinfo, fileobj=fileobj)
for directory in _DIRECTORIES:
files = info['files'].get(directory, [])
if not files:
continue
directory_archive = _create_directory_archive(os.path.join(path, directory), files)
tarinfo, fileobj = _create_tarinfo_and_buffer(directory_archive, directory + '.tar')
archive.addfile(tarinfo, fileobj)
return bytes_io.getvalue()
def _patch_info(info):
info['version.packaged'] = _VERSION_PACKAGED
def _create_directory_archive(path, files):
bytes_io = io.BytesIO()
with tarfile.open(fileobj=bytes_io, mode='w') as archive:
for filename in files:
archive.add(os.path.join(path, filename), arcname=filename)
return bytes_io.getvalue()
def _create_tarinfo_and_buffer(data, filename):
tarinfo = tarfile.TarInfo(filename)
tarinfo.size = len(data)
bytes_io = io.BytesIO(data)
return tarinfo, bytes_io
class Package(object):
def __init__(self, fileobj):
self.archive = tarfile.open(fileobj=fileobj)
self._info = self._load_info()
def _load_info(self):
info_file = self.archive.extractfile('info')
return ast.literal_eval(info_file.read().decode())
@property
def info(self):
return self._info
def extract_files(self, path):
for directory in _DIRECTORIES:
self._extract_files_in_directory(path, directory)
def _extract_files_in_directory(self, path, directory):
files = self.info['files'].get(directory, [])
if not files:
return
target_path = os.path.join(path, directory)
os.makedirs(target_path)
dir_archive_file = self.archive.extractfile(directory + '.tar')
with tarfile.open(fileobj=dir_archive_file) as archive:
members = [member for member in archive.getmembers() if member.name in files]
archive.extractall(path=target_path, members=members)
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
# feature). Distribution tarballs (built by setup.py sdist) and build
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.
# This file is released into the public domain. Generated by
# versioneer-0.15 (https://github.com/warner/python-versioneer)
import errno
import os
import re
import subprocess
import sys
def get_keywords():
# these strings will be replaced by git during git-archive.
# setup.py/versioneer.py will grep for the variable names, so they must
# each be defined on a line of their own. _version.py will just call
# get_keywords().
git_refnames = "$Format:%d$"
git_full = "$Format:%H$"
keywords = {"refnames": git_refnames, "full": git_full}
return keywords
class VersioneerConfig:
pass
def get_config():
# these strings are filled in when 'setup.py versioneer' creates
# _version.py
cfg = VersioneerConfig()
cfg.VCS = "git"
cfg.style = "pep440"
cfg.tag_prefix = ""
cfg.parentdir_prefix = "python-"
cfg.versionfile_source = "mkp/_version.py"
cfg.verbose = False
return cfg
class NotThisMethod(Exception):
pass
LONG_VERSION_PY = {}
HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
def decorate(f):
if vcs not in HANDLERS:
HANDLERS[vcs] = {}
HANDLERS[vcs][method] = f
return f
return decorate
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
assert isinstance(commands, list)
p = None
for c in commands:
try:
dispcmd = str([c] + args)
# remember shell=False, so use git.cmd on windows, not just git
p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
stderr=(subprocess.PIPE if hide_stderr
else None))
break
except EnvironmentError:
e = sys.exc_info()[1]
if e.errno == errno.ENOENT:
continue
if verbose:
print("unable to run %s" % dispcmd)
print(e)
return None
else:
if verbose:
print("unable to find command, tried %s" % (commands,))
return None
stdout = p.communicate()[0].strip()
if sys.version_info[0] >= 3:
stdout = stdout.decode()
if p.returncode != 0:
if verbose:
print("unable to run %s (error)" % dispcmd)
return None
return stdout
def versions_from_parentdir(parentdir_prefix, root, verbose):
# Source tarballs conventionally unpack into a directory that includes
# both the project name and a version string.
dirname = os.path.basename(root)
if not dirname.startswith(parentdir_prefix):
if verbose:
print("guessing rootdir is '%s', but '%s' doesn't start with "
"prefix '%s'" % (root, dirname, parentdir_prefix))
raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
return {"version": dirname[len(parentdir_prefix):],
"full-revisionid": None,
"dirty": False, "error": None}
@register_vcs_handler("git", "get_keywords")
def git_get_keywords(versionfile_abs):
# the code embedded in _version.py can just fetch the value of these
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
# _version.py.
keywords = {}
try:
f = open(versionfile_abs, "r")
for line in f.readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
keywords["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
keywords["full"] = mo.group(1)
f.close()
except EnvironmentError:
pass
return keywords
@register_vcs_handler("git", "keywords")
def git_versions_from_keywords(keywords, tag_prefix, verbose):
if not keywords:
raise NotThisMethod("no keywords at all, weird")
refnames = keywords["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
print("keywords are unexpanded, not using")
raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
refs = set([r.strip() for r in refnames.strip("()").split(",")])
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
TAG = "tag: "
tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
if not tags:
# Either we're using git < 1.8.3, or there really are no tags. We use
# a heuristic: assume all version tags have a digit. The old git %d
# expansion behaves like git log --decorate=short and strips out the
# refs/heads/ and refs/tags/ prefixes that would let us distinguish
# between branches and tags. By ignoring refnames without digits, we
# filter out many common branch names like "release" and
# "stabilization", as well as "HEAD" and "master".
tags = set([r for r in refs if re.search(r'\d', r)])
if verbose:
print("discarding '%s', no digits" % ",".join(refs-tags))
if verbose:
print("likely tags: %s" % ",".join(sorted(tags)))
for ref in sorted(tags):
# sorting will prefer e.g. "2.0" over "2.0rc1"
if ref.startswith(tag_prefix):
r = ref[len(tag_prefix):]
if verbose:
print("picking %s" % r)
return {"version": r,
"full-revisionid": keywords["full"].strip(),
"dirty": False, "error": None
}
# no suitable tags, so version is "0+unknown", but full hex is still there
if verbose:
print("no suitable tags, using unknown + full revision id")
return {"version": "0+unknown",
"full-revisionid": keywords["full"].strip(),
"dirty": False, "error": "no suitable tags"}
@register_vcs_handler("git", "pieces_from_vcs")
def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
# this runs 'git' from the root of the source tree. This only gets called
# if the git-archive 'subst' keywords were *not* expanded, and
# _version.py hasn't already been rewritten with a short version string,
# meaning we're inside a checked out source tree.
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %s" % root)
raise NotThisMethod("no .git directory")
GITS = ["git"]
if sys.platform == "win32":
GITS = ["git.cmd", "git.exe"]
# if there is a tag, this yields TAG-NUM-gHEX[-dirty]
# if there are no tags, this yields HEX[-dirty] (no NUM)
describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
"--always", "--long"],
cwd=root)
# --long was added in git-1.5.5
if describe_out is None:
raise NotThisMethod("'git describe' failed")
describe_out = describe_out.strip()
full_out = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
if full_out is None:
raise NotThisMethod("'git rev-parse' failed")
full_out = full_out.strip()
pieces = {}
pieces["long"] = full_out
pieces["short"] = full_out[:7] # maybe improved later
pieces["error"] = None
# parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
# TAG might have hyphens.
git_describe = describe_out
# look for -dirty suffix
dirty = git_describe.endswith("-dirty")
pieces["dirty"] = dirty
if dirty:
git_describe = git_describe[:git_describe.rindex("-dirty")]
# now we have TAG-NUM-gHEX or HEX
if "-" in git_describe:
# TAG-NUM-gHEX
mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
if not mo:
# unparseable. Maybe git-describe is misbehaving?
pieces["error"] = ("unable to parse git-describe output: '%s'"
% describe_out)
return pieces
# tag
full_tag = mo.group(1)
if not full_tag.startswith(tag_prefix):
if verbose:
fmt = "tag '%s' doesn't start with prefix '%s'"
print(fmt % (full_tag, tag_prefix))
pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
% (full_tag, tag_prefix))
return pieces
pieces["closest-tag"] = full_tag[len(tag_prefix):]
# distance: number of commits since tag
pieces["distance"] = int(mo.group(2))
# commit: short hex revision ID
pieces["short"] = mo.group(3)
else:
# HEX: no tags
pieces["closest-tag"] = None
count_out = run_command(GITS, ["rev-list", "HEAD", "--count"],
cwd=root)
pieces["distance"] = int(count_out) # total number of commits
return pieces
def plus_or_dot(pieces):
if "+" in pieces.get("closest-tag", ""):
return "."
return "+"
def render_pep440(pieces):
# now build up version string, with post-release "local version
# identifier". Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
# get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
# exceptions:
# 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += plus_or_dot(pieces)
rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
if pieces["dirty"]:
rendered += ".dirty"
else:
# exception #1
rendered = "0+untagged.%d.g%s" % (pieces["distance"],
pieces["short"])
if pieces["dirty"]:
rendered += ".dirty"
return rendered
def render_pep440_pre(pieces):
# TAG[.post.devDISTANCE] . No -dirty
# exceptions:
# 1: no tags. 0.post.devDISTANCE
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
rendered += ".post.dev%d" % pieces["distance"]
else:
# exception #1
rendered = "0.post.dev%d" % pieces["distance"]
return rendered
def render_pep440_post(pieces):
# TAG[.postDISTANCE[.dev0]+gHEX] . The ".dev0" means dirty. Note that
# .dev0 sorts backwards (a dirty tree will appear "older" than the
# corresponding clean one), but you shouldn't be releasing software with
# -dirty anyways.
# exceptions:
# 1: no tags. 0.postDISTANCE[.dev0]
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += ".post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
rendered += plus_or_dot(pieces)
rendered += "g%s" % pieces["short"]
else:
# exception #1
rendered = "0.post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
rendered += "+g%s" % pieces["short"]
return rendered
def render_pep440_old(pieces):
# TAG[.postDISTANCE[.dev0]] . The ".dev0" means dirty.
# exceptions:
# 1: no tags. 0.postDISTANCE[.dev0]
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += ".post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
else:
# exception #1
rendered = "0.post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
return rendered
def render_git_describe(pieces):
# TAG[-DISTANCE-gHEX][-dirty], like 'git describe --tags --dirty
# --always'
# exceptions:
# 1: no tags. HEX[-dirty] (note: no 'g' prefix)
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
else:
# exception #1
rendered = pieces["short"]
if pieces["dirty"]:
rendered += "-dirty"
return rendered
def render_git_describe_long(pieces):
# TAG-DISTANCE-gHEX[-dirty], like 'git describe --tags --dirty
# --always -long'. The distance/hash is unconditional.
# exceptions:
# 1: no tags. HEX[-dirty] (note: no 'g' prefix)
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
else:
# exception #1
rendered = pieces["short"]
if pieces["dirty"]:
rendered += "-dirty"
return rendered
def render(pieces, style):
if pieces["error"]:
return {"version": "unknown",
"full-revisionid": pieces.get("long"),
"dirty": None,
"error": pieces["error"]}
if not style or style == "default":
style = "pep440" # the default
if style == "pep440":
rendered = render_pep440(pieces)
elif style == "pep440-pre":
rendered = render_pep440_pre(pieces)
elif style == "pep440-post":
rendered = render_pep440_post(pieces)
elif style == "pep440-old":
rendered = render_pep440_old(pieces)
elif style == "git-describe":
rendered = render_git_describe(pieces)
elif style == "git-describe-long":
rendered = render_git_describe_long(pieces)
else:
raise ValueError("unknown style '%s'" % style)
return {"version": rendered, "full-revisionid": pieces["long"],
"dirty": pieces["dirty"], "error": None}
def get_versions():
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
# __file__, we can work backwards from there to the root. Some
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
# case we can only use expanded keywords.
cfg = get_config()
verbose = cfg.verbose
try:
return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
verbose)
except NotThisMethod:
pass
try:
root = os.path.realpath(__file__)
# versionfile_source is the relative path from the top of the source
# tree (where the .git directory might live) to this file. Invert
# this to find the root from __file__.
for i in cfg.versionfile_source.split('/'):
root = os.path.dirname(root)
except NameError:
return {"version": "0+unknown", "full-revisionid": None,
"dirty": None,
"error": "unable to find root of source tree"}
try:
pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
return render(pieces, cfg.style)
except NotThisMethod:
pass
try:
if cfg.parentdir_prefix:
return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
except NotThisMethod:
pass
return {"version": "0+unknown", "full-revisionid": None,
"dirty": None,
"error": "unable to compute version"}
[bdist_wheel]
universal=1
[versioneer]
VCS = git
style = pep440
versionfile_source = mkp/_version.py
versionfile_build = mkp/_version.py
tag_prefix =
parentdir_prefix = python-
setup.py 0 → 100644
import sys
from setuptools import find_packages, setup
import versioneer
def read_md(filename):
try:
from pypandoc import convert
return convert(filename, 'rst')
except ImportError:
print("warning: pypandoc module not found, could not convert Markdown to RST")
return open(filename, 'r').read()
install_requirements = []
if sys.version_info < (3, 4):
install_requirements.append('enum34')
setup(
name='mkp',
version=versioneer.get_version(),
url='https://github.com/tom-mi/python-mkp/',
license='GPLv2',
author='Thomas Reifenberger',
tests_require=['pytest'],
install_requires=install_requirements,
author_email='tom-mi at rfnbrgr.de',
description='Pack and unpack Check_MK mkp files',
long_description=read_md('README.md'),
packages=find_packages(),
platforms='any',
classifiers=[
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Topic :: System :: Monitoring',
],
cmdclass=versioneer.get_cmdclass(),
)
import binascii
import pytest
@pytest.fixture()
def original_mkp_file():
return _unhexlify('''
1f8b0808191c475602ff746573742d312e302e6d6b7000eddb416f9b3014c0f19cf3295cedc0650b
8104225551a4dd76dc61d20ed31439e034a8809971da5553bffb6cdab4a44b35696ab255fbff1409
f4fc20d806737914f55a0f8e6ceca4d369b7759e6ea3f1381e44711a4769948e27d1c047926820c6
8313d8b6561a215ea493fdcebd123f02b9b51b6d827311bccf7371a3b746d4b25262a38c0ade0e45
90ab363345630b5dfbac8fa592ad12d2254bd16beb1da0afeb52cb7cb935a53f62636d731e86eabb
ac9a528d325d8556b536ec92d745a95a97e52ee442d5d6ef7e09da4665852cc32eb4f4c9c15797fc
28c8362abbac64dda53f9bd09ded4943aeb303d1a2be727fa5cdcd81b65adb625d64d2f7f2d0199b
ba796795eb9bb4ea50fbb55a75d15bdf5f3fb67e50ba6bee02db6ab91b84d8076c61cb2ee593df11
7a2d1e72af9469efa7211a8dfba15155d44ba3be6d0ba3f2bbf6789436c95e4e23b34b37a47bedb7
03fcc776cfd1c8ad827f67fd8fa77e7f7ffd8fa6c98cf5ff14fcd272c2f77f92cea2fe76770bece6
dffd266efe27936472e2f9d755be34eb7a652e0e3f07bf6b7fa5ba97cdb9f8a0ca528bcfda94f9d9
90551100000000000000000000000000fe7d7745d7c7acfefca3facf28a5fef3247eadb43fcefccf
92e4f9facff4e1fb8fd8dd0d6efed388facfd3787316ae8a3a5cc9763354d9468b603e9ffbdb60b1
5804f7917e7168407528000000000000000000000000000000000000000000000000f0627e02d592
a66f00780000
''')
def _unhexlify(data):
return binascii.unhexlify(data.replace(' ', '').replace('\n', ''))
import ast
import io
import tarfile
import mkp
DIRECTORIES = [
'agents', 'checkman', 'checks', 'doc', 'inventory', 'notifications',
'pnp-templates', 'web',
]
def test_load_bytes(original_mkp_file):
package = mkp.load_bytes(original_mkp_file)
assert type(package) == mkp.Package
assert package.info['title'] == 'Title of test'
def test_extract_files(original_mkp_file, tmpdir):
package = mkp.load_bytes(original_mkp_file)
package.extract_files(str(tmpdir))
assert tmpdir.join('agents', 'special', 'agent_test').exists()
assert tmpdir.join('checkman', 'test').exists()
assert tmpdir.join('checkman', 'test').open().read() == 'title: Hello World!\n'
def test_pack_to_bytes(tmpdir):
info = {
'files': {'agents': ['special/agent_test']},
'title': 'Test package',
}
tmpdir.join('agents', 'special', 'agent_test').write_binary(b'hello', ensure=True)
data = mkp.pack_to_bytes(info, str(tmpdir))
bytes_io = io.BytesIO(data)
archive = tarfile.open(fileobj=bytes_io)
info_file = archive.extractfile('info').read()
extracted_info = ast.literal_eval(info_file.decode())
assert extracted_info['files'] == info['files']
assert extracted_info['title'] == info['title']
assert extracted_info['version.packaged'] == 'python-mkp'
agents_archive_file = archive.extractfile('agents.tar')
agents_archive = tarfile.open(fileobj=agents_archive_file, mode='r:')
agent_file = agents_archive.extractfile('special/agent_test')
assert agent_file.read() == b'hello'
def test_find_files_searches_all_directories(tmpdir):
for directory in DIRECTORIES:
tmpdir.join(directory, 'test').write_binary(b'Foo', ensure=True)
result = mkp.find_files(str(tmpdir))
for directory in DIRECTORIES:
assert result[directory] == ['test']
def test_find_files_searches_subdirectories(tmpdir):
tmpdir.join('agents', 'special', 'agent_test').write_binary(b'hello', ensure=True)
result = mkp.find_files(str(tmpdir))
assert result['agents'] == ['special/agent_test']
def test_find_files_ignores_hidden_files_and_dirs(tmpdir):
tmpdir.join('agents', '.hidden').write_binary(b'hello', ensure=True)
tmpdir.join('agents', 'test~').write_binary(b'hello', ensure=True)
tmpdir.join('agents', '.hidden_dir', 'visible_file').write_binary(b'hello', ensure=True)
result = mkp.find_files(str(tmpdir))
assert result['agents'] == []
def test_pack_and_unpack_covers_all_known_directories(tmpdir):
info = {
'files': {key: ['test'] for key in DIRECTORIES},
}
source = tmpdir.join('source').mkdir()
dest = tmpdir.join('dest').mkdir()
for directory in DIRECTORIES:
source.join(directory, 'test').write_binary(b'Foo', ensure=True)
package_bytes = mkp.pack_to_bytes(info, str(source))
package = mkp.load_bytes(package_bytes)
package.extract_files(str(dest))
for directory in DIRECTORIES:
assert dest.join(directory, 'test').exists()
tox.ini 0 → 100644
[tox]
envlist = py27, py33, py34
[testenv]
deps = -rdev-requirements.txt
commands = py.test {posargs} --cov={envsitepackagesdir}/mkp
[pytest]
pep8maxlinelength = 119
addopts = --cache-clear --pep8 --flakes
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment