1
1
import pytest
2
2
import warnings
3
+ from inspect import getsourcelines
3
4
4
5
from numpydoc import validate
5
6
import numpydoc .tests
@@ -1528,6 +1529,35 @@ def test_bad_docstrings(self, capsys, klass, func, msgs):
1528
1529
assert msg in " " .join (err [1 ] for err in result ["errors" ])
1529
1530
1530
1531
1532
+ def decorator (x ):
1533
+ """Test decorator."""
1534
+ return x
1535
+
1536
+
1537
+ @decorator
1538
+ @decorator
1539
+ class DecoratorClass :
1540
+ """
1541
+ Class and methods with decorators.
1542
+
1543
+ `DecoratorClass` has two decorators, `DecoratorClass.test_no_decorator` has no
1544
+ decorator and `DecoratorClass.test_three_decorators` has three decorators.
1545
+ `Validator.source_file_def_line` should return the `def` or `class` line number, not
1546
+ the line of the first decorator.
1547
+ """
1548
+
1549
+ def test_no_decorator (self ):
1550
+ """Test method without decorators."""
1551
+ pass
1552
+
1553
+ @decorator
1554
+ @decorator
1555
+ @decorator
1556
+ def test_three_decorators (self ):
1557
+ """Test method with three decorators."""
1558
+ pass
1559
+
1560
+
1531
1561
class TestValidatorClass :
1532
1562
@pytest .mark .parametrize ("invalid_name" , ["unknown_mod" , "unknown_mod.MyClass" ])
1533
1563
def test_raises_for_invalid_module_name (self , invalid_name ):
@@ -1544,3 +1574,28 @@ def test_raises_for_invalid_attribute_name(self, invalid_name):
1544
1574
msg = f"'{ obj_name } ' has no attribute '{ invalid_attr_name } '"
1545
1575
with pytest .raises (AttributeError , match = msg ):
1546
1576
numpydoc .validate .Validator ._load_obj (invalid_name )
1577
+
1578
+ @pytest .mark .parametrize (
1579
+ ["decorated_obj" , "def_line" ],
1580
+ [
1581
+ [
1582
+ "numpydoc.tests.test_validate.DecoratorClass" ,
1583
+ getsourcelines (DecoratorClass )[- 1 ] + 2 ,
1584
+ ],
1585
+ [
1586
+ "numpydoc.tests.test_validate.DecoratorClass.test_no_decorator" ,
1587
+ getsourcelines (DecoratorClass .test_no_decorator )[- 1 ],
1588
+ ],
1589
+ [
1590
+ "numpydoc.tests.test_validate.DecoratorClass.test_three_decorators" ,
1591
+ getsourcelines (DecoratorClass .test_three_decorators )[- 1 ] + 3 ,
1592
+ ],
1593
+ ],
1594
+ )
1595
+ def test_source_file_def_line_with_decorators (self , decorated_obj , def_line ):
1596
+ doc = numpydoc .validate .Validator (
1597
+ numpydoc .docscrape .get_doc_object (
1598
+ numpydoc .validate .Validator ._load_obj (decorated_obj )
1599
+ )
1600
+ )
1601
+ assert doc .source_file_def_line == def_line
0 commit comments