Skip to content

Commit

Permalink
Merge pull request #7625 from seberg/test-warning-filters
Browse files Browse the repository at this point in the history
TST: add a test for "ignore" warning filters
  • Loading branch information
pv committed Aug 2, 2017
2 parents 70ab20e + 41bcb9c commit 0a1cc4d
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 2 deletions.
2 changes: 1 addition & 1 deletion scipy/_lib/_numpy_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ def unique(ar, return_index=False, return_inverse=False, return_counts=False):
polyvalfromroots = np.polynomial.polynomial.polyvalfromroots
else:
def polyvalfromroots(x, r, tensor=True):
"""
r"""
Evaluate a polynomial specified by its roots at points x.
This function is copypasted from numpy 1.12.0.dev.
Expand Down
120 changes: 120 additions & 0 deletions scipy/_lib/tests/test_warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
"""
Tests which scan for certain occurrences in the code, they may not find
all of these occurrences but should catch almost all. This file was adapted
from numpy.
"""


from __future__ import division, absolute_import, print_function

import sys
import scipy

import pytest


if sys.version_info >= (3, 4):
from pathlib import Path
import ast
import tokenize

class ParseCall(ast.NodeVisitor):
def __init__(self):
self.ls = []

def visit_Attribute(self, node):
ast.NodeVisitor.generic_visit(self, node)
self.ls.append(node.attr)

def visit_Name(self, node):
self.ls.append(node.id)

class FindFuncs(ast.NodeVisitor):
def __init__(self, filename):
super().__init__()
self.__filename = filename
self.bad_filters = []
self.bad_stacklevels = []

def visit_Call(self, node):
p = ParseCall()
p.visit(node.func)
ast.NodeVisitor.generic_visit(self, node)

if p.ls[-1] == 'simplefilter' or p.ls[-1] == 'filterwarnings':
if node.args[0].s == "ignore":
self.bad_filters.append(
"{}:{}".format(self.__filename, node.lineno))

if p.ls[-1] == 'warn' and (
len(p.ls) == 1 or p.ls[-2] == 'warnings'):

if self.__filename == "_lib/tests/test_warnings.py":
# This file
return

# See if stacklevel exists:
if len(node.args) == 3:
return
args = {kw.arg for kw in node.keywords}
if "stacklevel" not in args:
self.bad_stacklevels.append(
"{}:{}".format(self.__filename, node.lineno))


@pytest.fixture(scope="session")
def warning_calls():
# combined "ignore" and stacklevel error
base = Path(scipy.__file__).parent

bad_filters = []
bad_stacklevels = []

for path in base.rglob("*.py"):
# use tokenize to auto-detect encoding on systems where no
# default encoding is defined (e.g. LANG='C')
with tokenize.open(str(path)) as file:
tree = ast.parse(file.read())
finder = FindFuncs(path.relative_to(base))
finder.visit(tree)
bad_filters.extend(finder.bad_filters)
bad_stacklevels.extend(finder.bad_stacklevels)

return bad_filters, bad_stacklevels


@pytest.mark.slow
@pytest.mark.skipif(sys.version_info < (3, 4), reason="needs Python >= 3.4")
def test_warning_calls_filters(warning_calls):
bad_filters, bad_stacklevels = warning_calls

# There is still one missing occurance in optimize.py,
# this is one that should be fixed and this removed then.
bad_filters = [item for item in bad_filters
if 'optimize.py' not in item]

if bad_filters:
raise AssertionError(
"ignore filter should not be used; found in:\n {}".format(
"\n ".join(bad_filters)))


@pytest.mark.slow
@pytest.mark.skipif(sys.version_info < (3, 4), reason="needs Python >= 3.4")
@pytest.mark.xfail(reason="stacklevels currently missing")
def test_warning_calls_stacklevels(warning_calls):
bad_filters, bad_stacklevels = warning_calls

msg = ""

if bad_filters:
msg += "ignore filter should not be used:\n {}".format(
"\n ".join(bad_filters))
msg += "\n\n"

if bad_stacklevels:
msg += "warnings should have an appropriate stacklevel:\n {}".format(
"\n ".join(bad_stacklevels))

if msg:
raise AssertionError(msg)
2 changes: 1 addition & 1 deletion scipy/signal/filter_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def freqz(b, a=1, worN=None, whole=False, plot=None):


def freqz_zpk(z, p, k, worN=None, whole=False):
"""
r"""
Compute the frequency response of a digital filter in ZPK form.
Given the Zeros, Poles and Gain of a digital filter, compute its frequency
Expand Down

0 comments on commit 0a1cc4d

Please sign in to comment.