Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def _validate(self, root, dirs, files):
# If any of the directories yet to be visited should be skipped, remove
# them from ``dirs`` so that we don't visit them in a future iteration.
# This guarantees that ``root`` is a valid directory that should not be
# skipped (since we're doing a top-down walk).
for skip_dir in self.skip_dirs:
if skip_dir in dirs:
dirs.remove(skip_dir)
invalid_dirs = []
if '__init__.py' not in files:
invalid_dirs.append(root)
return invalid_dirs
class ExecPermissionValidator(RepoValidator):
"""Flag code files that have execute permissions.
Parameters
----------
extensions : iterable of str, optional
File extensions of files to validate. Defaults to Python, Cython, and
C files (header and source files).
"""
reason = "Library code with execute permissions:"
def __init__(self, extensions=None):
if extensions is None:
extensions = {'.py', '.pyx', '.h', '.c'}
self.extensions = set(extensions)
This code was taken from verman's
``verman.Version.verman_system_call``. See licenses/verman.txt and
https://github.com/biocore/verman for more details.
"""
proc = subprocess.Popen(cmd, shell=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# communicate pulls all stdout/stderr from the PIPEs to
# avoid blocking -- don't remove this line!
stdout, stderr = proc.communicate()
return_value = proc.returncode
return stdout, stderr, return_value
class CopyrightHeadersValidator(RepoValidator):
"""Flag library files with non-standard copyright headers
See the current standard for scikit-bio's copyright headers at
``http://scikit-bio.org/docs/latest/development/new_module.html``
Individual files are ignored if the first line in the file is exactly:
# checklist.py:CopyrightHeadersValidator IGNORE
If a file is ignored, a ``ChecklistWarning`` is raised.
Parameters
----------
skip_dirs : iterable of str, optional
Directory names to skip during validation. Defaults to skipping any
directories named ``'data'`` or ``'__pycache__'`` (and anything
if tokens[pos][0] == tokenize.STRING:
pos += 3
# copyright header consists of 7 lines, and by discussion in
# preceding comment, spans through 14 tokens.
cheader = ''.join(map(lambda x: x[1], tokens[pos:pos + 14]))
# Ensure that there is no blank line at the end of the file
if (cheader != self.COPYRIGHT_HEADER or
(tokens[pos + 14][0] != tokenize.NL and
tokens[pos + 14][0] != tokenize.ENDMARKER)):
invalid_files.append(f.name)
f.close()
return invalid_files
class InitValidator(RepoValidator):
"""Flag library code directories that are missing init files.
This type of validation is important mainly because it is very easy to
forget to add an __init__.py file to a new test directory. If this
happens, nose will skip those tests unless it is run from the root of the
source repository. Thus, the tests will be skipped if the package is
pip-installed, e.g., as an end-user might install a release.
Parameters
----------
skip_dirs : iterable of str, optional
Directory names to skip during validation. Defaults to skipping any
directories named ``'data'`` or ``'__pycache__'`` (and anything
contained within them).
"""
Returns
-------
list of str
List of filepaths or dirpaths to be considered invalid (i.e., that
did not pass the validation checks).
See Also
--------
os.walk
"""
raise NotImplementedError("Subclasses must implement _validate.")
class InitValidator(RepoValidator):
"""Flag library code directories that are missing init files.
This type of validation is important mainly because it is very easy to
forget to add an __init__.py file to a new test directory. If this
happens, nose will skip those tests unless it is run from the root of the
source repository. Thus, the tests will be skipped if the package is
pip-installed, e.g., as an end-user might install a release.
Parameters
----------
skip_dirs : iterable of str, optional
Directory names to skip during validation. Defaults to skipping any
directories named ``'data'`` or ``'__pycache__'`` (and anything
contained within them).
"""
self.extensions = set(extensions)
def _validate(self, root, dirs, files):
invalid_fps = []
for f in files:
_, ext = os.path.splitext(f)
if ext in self.extensions:
fp = os.path.join(root, f)
if os.access(fp, os.X_OK):
invalid_fps.append(fp)
return invalid_fps
class GeneratedCythonValidator(RepoValidator):
"""Flag Cython files that are missing generated C files.
Flags Cython files that aren't paired with a generated C file. The
generated C file must be in the same directory as the Cython file, and its
name (besides the file extension) must match. The validator also ensures
that the generated C file is not empty.
Parameters
----------
cython_ext : str, optional
File extension for Cython files.
c_ext : str, optional
File extension for generated C files.
"""
reason = "Cython code missing generated C code"
def _validate(self, root, dirs, files):
# If any of the directories yet to be visited should be skipped, remove
# them from ``dirs`` so that we don't visit them in a future iteration.
# This guarantees that ``root`` is a valid directory that should not be
# skipped (since we're doing a top-down walk).
for skip_dir in self.skip_dirs:
if skip_dir in dirs:
dirs.remove(skip_dir)
invalid_dirs = []
if '__init__.py' not in files:
invalid_dirs.append(root)
return invalid_dirs
class ExecPermissionValidator(RepoValidator):
"""Flag code files that have execute permissions.
Parameters
----------
extensions : iterable of str, optional
File extensions of files to validate. Defaults to Python, Cython, and
C files (header and source files).
"""
reason = "Library code with execute permissions"
def __init__(self, extensions=None):
if extensions is None:
extensions = {'.py', '.pyx', '.h', '.c'}
self.extensions = set(extensions)
if c_ts < cython_ts:
invalid_fps.append(cython_fp)
return invalid_fps
def _get_timestamp(self, fp):
cmd = 'git log -1 --format="%%ad" -- %s' % fp
stdout, stderr, retval = self._system_call(cmd)
if retval != 0:
raise RuntimeError("Could not execute 'git log' command to "
"determine file timestamp.")
return dateutil.parser.parse(stdout.strip())
class APIRegressionValidator(RepoValidator):
"""Flag tests that import from a non-minimized subpackage hierarchy.
Flags tests that aren't imported from a minimally deep API target. (e.g.
skbio.TabularMSA vs skbio.alignment.TabularMSA). This should prevent
accidental regression in our API because tests will fail if any alias is
removed, and this checklist will fail if any test doesn't import from the
least deep API target.
"""
reason = ("The following tests import `A` but should import `B`"
" (file: A => B):")
def __init__(self):
self._imports = {}
def _validate(self, root, dirs, files):
self.extensions = set(extensions)
def _validate(self, root, dirs, files):
invalid_fps = []
for f in files:
_, ext = os.path.splitext(f)
if ext in self.extensions:
fp = os.path.join(root, f)
if os.access(fp, os.X_OK):
invalid_fps.append(fp)
return invalid_fps
class GeneratedCythonValidator(RepoValidator):
"""Flag Cython files that have missing or outdated generated C files.
Flags Cython files that aren't paired with an up-to-date generated C file.
The generated C file must be in the same directory as the Cython file, and
its name (besides the file extension) must match. The validator also
ensures that the generated C file is not empty and that it was generated at
the same time or later than the Cython file's timestamp.
Parameters
----------
cython_ext : str, optional
File extension for Cython files.
c_ext : str, optional
File extension for generated C files.
"""