py-api-dumper 4.1__tar.gz → 4.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. py_api_dumper-4.2.0/LICENSES/CC0-1.0.txt +121 -0
  2. {py_api_dumper-4.1/src/py_api_dumper.egg-info → py_api_dumper-4.2.0}/PKG-INFO +31 -1
  3. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/README.md +29 -0
  4. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/pyproject.toml +2 -1
  5. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/src/py_api_dumper/__init__.py +102 -2
  6. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/src/py_api_dumper/cli.py +9 -2
  7. {py_api_dumper-4.1 → py_api_dumper-4.2.0/src/py_api_dumper.egg-info}/PKG-INFO +31 -1
  8. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/src/py_api_dumper.egg-info/SOURCES.txt +1 -0
  9. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/test_diff.py +10 -1
  10. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/test_dump.py +34 -1
  11. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/LICENSES/MIT.txt +0 -0
  12. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/MANIFEST.in +0 -0
  13. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/setup.cfg +0 -0
  14. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/src/py_api_dumper.egg-info/dependency_links.txt +0 -0
  15. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/src/py_api_dumper.egg-info/entry_points.txt +0 -0
  16. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/src/py_api_dumper.egg-info/top_level.txt +0 -0
  17. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/api_ref/__init__.py +0 -0
  18. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/api_ref/_priv_mod.py +0 -0
  19. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/api_ref/api_ref.txt +0 -0
  20. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/api_ref/ext_mod.c +0 -0
  21. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/api_ref/pub_mod.py +0 -0
  22. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/conftest.py +0 -0
  23. {py_api_dumper-4.1 → py_api_dumper-4.2.0}/test/setup.py +0 -0
@@ -0,0 +1,121 @@
1
+ Creative Commons Legal Code
2
+
3
+ CC0 1.0 Universal
4
+
5
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12
+ HEREUNDER.
13
+
14
+ Statement of Purpose
15
+
16
+ The laws of most jurisdictions throughout the world automatically confer
17
+ exclusive Copyright and Related Rights (defined below) upon the creator
18
+ and subsequent owner(s) (each and all, an "owner") of an original work of
19
+ authorship and/or a database (each, a "Work").
20
+
21
+ Certain owners wish to permanently relinquish those rights to a Work for
22
+ the purpose of contributing to a commons of creative, cultural and
23
+ scientific works ("Commons") that the public can reliably and without fear
24
+ of later claims of infringement build upon, modify, incorporate in other
25
+ works, reuse and redistribute as freely as possible in any form whatsoever
26
+ and for any purposes, including without limitation commercial purposes.
27
+ These owners may contribute to the Commons to promote the ideal of a free
28
+ culture and the further production of creative, cultural and scientific
29
+ works, or to gain reputation or greater distribution for their Work in
30
+ part through the use and efforts of others.
31
+
32
+ For these and/or other purposes and motivations, and without any
33
+ expectation of additional consideration or compensation, the person
34
+ associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35
+ is an owner of Copyright and Related Rights in the Work, voluntarily
36
+ elects to apply CC0 to the Work and publicly distribute the Work under its
37
+ terms, with knowledge of his or her Copyright and Related Rights in the
38
+ Work and the meaning and intended legal effect of CC0 on those rights.
39
+
40
+ 1. Copyright and Related Rights. A Work made available under CC0 may be
41
+ protected by copyright and related or neighboring rights ("Copyright and
42
+ Related Rights"). Copyright and Related Rights include, but are not
43
+ limited to, the following:
44
+
45
+ i. the right to reproduce, adapt, distribute, perform, display,
46
+ communicate, and translate a Work;
47
+ ii. moral rights retained by the original author(s) and/or performer(s);
48
+ iii. publicity and privacy rights pertaining to a person's image or
49
+ likeness depicted in a Work;
50
+ iv. rights protecting against unfair competition in regards to a Work,
51
+ subject to the limitations in paragraph 4(a), below;
52
+ v. rights protecting the extraction, dissemination, use and reuse of data
53
+ in a Work;
54
+ vi. database rights (such as those arising under Directive 96/9/EC of the
55
+ European Parliament and of the Council of 11 March 1996 on the legal
56
+ protection of databases, and under any national implementation
57
+ thereof, including any amended or successor version of such
58
+ directive); and
59
+ vii. other similar, equivalent or corresponding rights throughout the
60
+ world based on applicable law or treaty, and any national
61
+ implementations thereof.
62
+
63
+ 2. Waiver. To the greatest extent permitted by, but not in contravention
64
+ of, applicable law, Affirmer hereby overtly, fully, permanently,
65
+ irrevocably and unconditionally waives, abandons, and surrenders all of
66
+ Affirmer's Copyright and Related Rights and associated claims and causes
67
+ of action, whether now known or unknown (including existing as well as
68
+ future claims and causes of action), in the Work (i) in all territories
69
+ worldwide, (ii) for the maximum duration provided by applicable law or
70
+ treaty (including future time extensions), (iii) in any current or future
71
+ medium and for any number of copies, and (iv) for any purpose whatsoever,
72
+ including without limitation commercial, advertising or promotional
73
+ purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74
+ member of the public at large and to the detriment of Affirmer's heirs and
75
+ successors, fully intending that such Waiver shall not be subject to
76
+ revocation, rescission, cancellation, termination, or any other legal or
77
+ equitable action to disrupt the quiet enjoyment of the Work by the public
78
+ as contemplated by Affirmer's express Statement of Purpose.
79
+
80
+ 3. Public License Fallback. Should any part of the Waiver for any reason
81
+ be judged legally invalid or ineffective under applicable law, then the
82
+ Waiver shall be preserved to the maximum extent permitted taking into
83
+ account Affirmer's express Statement of Purpose. In addition, to the
84
+ extent the Waiver is so judged Affirmer hereby grants to each affected
85
+ person a royalty-free, non transferable, non sublicensable, non exclusive,
86
+ irrevocable and unconditional license to exercise Affirmer's Copyright and
87
+ Related Rights in the Work (i) in all territories worldwide, (ii) for the
88
+ maximum duration provided by applicable law or treaty (including future
89
+ time extensions), (iii) in any current or future medium and for any number
90
+ of copies, and (iv) for any purpose whatsoever, including without
91
+ limitation commercial, advertising or promotional purposes (the
92
+ "License"). The License shall be deemed effective as of the date CC0 was
93
+ applied by Affirmer to the Work. Should any part of the License for any
94
+ reason be judged legally invalid or ineffective under applicable law, such
95
+ partial invalidity or ineffectiveness shall not invalidate the remainder
96
+ of the License, and in such case Affirmer hereby affirms that he or she
97
+ will not (i) exercise any of his or her remaining Copyright and Related
98
+ Rights in the Work or (ii) assert any associated claims and causes of
99
+ action with respect to the Work, in either case contrary to Affirmer's
100
+ express Statement of Purpose.
101
+
102
+ 4. Limitations and Disclaimers.
103
+
104
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
105
+ surrendered, licensed or otherwise affected by this document.
106
+ b. Affirmer offers the Work as-is and makes no representations or
107
+ warranties of any kind concerning the Work, express, implied,
108
+ statutory or otherwise, including without limitation warranties of
109
+ title, merchantability, fitness for a particular purpose, non
110
+ infringement, or the absence of latent or other defects, accuracy, or
111
+ the present or absence of errors, whether or not discoverable, all to
112
+ the greatest extent permissible under applicable law.
113
+ c. Affirmer disclaims responsibility for clearing rights of other persons
114
+ that may apply to the Work or any use thereof, including without
115
+ limitation any person's Copyright and Related Rights in the Work.
116
+ Further, Affirmer disclaims responsibility for obtaining any necessary
117
+ consents, permissions or other rights required for any use of the
118
+ Work.
119
+ d. Affirmer understands and acknowledges that Creative Commons is not a
120
+ party to this document and has no duty or obligation with respect to
121
+ this CC0 or use of the Work.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-api-dumper
3
- Version: 4.1
3
+ Version: 4.2.0
4
4
  Summary: Python API dumping and comparison tool
5
5
  Author-email: Karl Wette <karl.wette@anu.edu.au>
6
6
  License-Expression: MIT
@@ -11,6 +11,7 @@ Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSES/MIT.txt
14
+ License-File: LICENSES/CC0-1.0.txt
14
15
  Dynamic: license-file
15
16
 
16
17
  # Python API dumping and comparison tool
@@ -76,6 +77,29 @@ $ py-api-dumper --help
76
77
  * API entries which have been *added*, i.e. present in the new API but not in
77
78
  the old API (e.g. the `b` argument in the above example).
78
79
 
80
+ * To filter out undesired entries from API dumps before comparison:
81
+ ```
82
+ $ py-api-dumper diff mymod-old.dump mymod-new.dump -i <filter>
83
+ ```
84
+ Given the following API:
85
+ ```
86
+ MODULE : mymod
87
+ CLASS : myclass
88
+ FUNCTION : __init__ : no-return-type
89
+ REQUIRED : 0 : x : int
90
+ ```
91
+ the following filters would ignore the given entries:
92
+ | `<filter>` | Ignore entries |
93
+ | ---------------------------- | ------------------------------------------ |
94
+ | `MODULE` | All modules |
95
+ | `MODULE:mymod` | All modules named `mymod` |
96
+ | `CLASS` | All classes |
97
+ | `CLASS:myclass` | All classes named `myclass` |
98
+ | `MODULE:mymod;CLASS` | All classes in modules named `mymod` |
99
+ | `MODULE:mymod;CLASS:myclass` | Class `myclass` in module `mymod` |
100
+ | `FUNCTION:__init__` | All functions named `__init__` |
101
+ | `CLASS;FUNCTION:__init__` | All functioned named `__init__` in classes |
102
+
79
103
  ## Python interface
80
104
 
81
105
  ```python
@@ -100,3 +124,9 @@ from py_api_dumper import APIDump, APIDiff
100
124
  diff.print_as_text()
101
125
  diff.save_as_json("mymod.diff")
102
126
  ```
127
+
128
+ * To filter out undesired entries from API dumps before comparison:
129
+ ```python
130
+ filter = APIFilter(("CLASS", "myclass")) # OR: APIFilter.from_str("CLASS:myclass")
131
+ diff = APIDiff.from_files("mymod-old.dump", "mymod-new.dump", filter)
132
+ ```
@@ -61,6 +61,29 @@ $ py-api-dumper --help
61
61
  * API entries which have been *added*, i.e. present in the new API but not in
62
62
  the old API (e.g. the `b` argument in the above example).
63
63
 
64
+ * To filter out undesired entries from API dumps before comparison:
65
+ ```
66
+ $ py-api-dumper diff mymod-old.dump mymod-new.dump -i <filter>
67
+ ```
68
+ Given the following API:
69
+ ```
70
+ MODULE : mymod
71
+ CLASS : myclass
72
+ FUNCTION : __init__ : no-return-type
73
+ REQUIRED : 0 : x : int
74
+ ```
75
+ the following filters would ignore the given entries:
76
+ | `<filter>` | Ignore entries |
77
+ | ---------------------------- | ------------------------------------------ |
78
+ | `MODULE` | All modules |
79
+ | `MODULE:mymod` | All modules named `mymod` |
80
+ | `CLASS` | All classes |
81
+ | `CLASS:myclass` | All classes named `myclass` |
82
+ | `MODULE:mymod;CLASS` | All classes in modules named `mymod` |
83
+ | `MODULE:mymod;CLASS:myclass` | Class `myclass` in module `mymod` |
84
+ | `FUNCTION:__init__` | All functions named `__init__` |
85
+ | `CLASS;FUNCTION:__init__` | All functioned named `__init__` in classes |
86
+
64
87
  ## Python interface
65
88
 
66
89
  ```python
@@ -85,3 +108,9 @@ from py_api_dumper import APIDump, APIDiff
85
108
  diff.print_as_text()
86
109
  diff.save_as_json("mymod.diff")
87
110
  ```
111
+
112
+ * To filter out undesired entries from API dumps before comparison:
113
+ ```python
114
+ filter = APIFilter(("CLASS", "myclass")) # OR: APIFilter.from_str("CLASS:myclass")
115
+ diff = APIDiff.from_files("mymod-old.dump", "mymod-new.dump", filter)
116
+ ```
@@ -11,7 +11,7 @@ authors = [
11
11
  requires-python = ">=3.10"
12
12
  readme = "README.md"
13
13
  license = "MIT"
14
- license-files = ["LICENSES/MIT.txt"]
14
+ license-files = ["LICENSES/MIT.txt", "LICENSES/CC0-1.0.txt"]
15
15
  classifiers = [
16
16
  "Programming Language :: Python :: 3",
17
17
  "Operating System :: OS Independent",
@@ -54,6 +54,7 @@ skip-checking-raises = true
54
54
 
55
55
  [tool.pytest.ini_options]
56
56
  minversion = "6.0"
57
+ pythonpath = ["src"]
57
58
  addopts = "--cov=py_api_dumper --cov-report=term-missing --cov-fail-under=100"
58
59
  testpaths = ["test"]
59
60
 
@@ -30,9 +30,85 @@ from typing import (
30
30
  )
31
31
 
32
32
  __author__ = "Karl Wette"
33
- __version__ = "4.1"
33
+ __version__ = "4.2.0"
34
34
 
35
+ APIFilterType = TypeVar("APIFilterType", bound="APIFilter")
35
36
  APIDumpType = TypeVar("APIDumpType", bound="APIDump")
37
+ APIDiffType = TypeVar("APIDiffType", bound="APIDiff")
38
+
39
+
40
+ class APIFilter:
41
+ """Filter out API entries before comparing API dumps."""
42
+
43
+ def __init__(self, *patt: tuple):
44
+ """API entry filter.
45
+
46
+ Args:
47
+ *patt (tuple): Partial tuples to match to API entry.
48
+ """
49
+ self._patt = patt
50
+
51
+ @classmethod
52
+ def from_str(cls: Type[APIFilterType], filter_str: str) -> APIFilterType:
53
+ """Create an API filter from a string.
54
+
55
+ Args:
56
+ filter_str (str):
57
+ String to parse into filter.
58
+
59
+ Returns:
60
+ APIFilterType: APIFilter instance.
61
+ """
62
+
63
+ def _to_int_or_str(c):
64
+ try:
65
+ return int(c)
66
+ except ValueError:
67
+ return c
68
+
69
+ return cls(
70
+ *tuple(
71
+ tuple(_to_int_or_str(c) for c in s.split(":"))
72
+ for s in filter_str.split(";")
73
+ )
74
+ )
75
+
76
+ def match(self, entry: tuple) -> bool:
77
+ """Return if the API filter matches the given entry.
78
+
79
+ Args:
80
+ entry (tuple):
81
+ API entry to match.
82
+
83
+ Returns:
84
+ bool: True for a match, False otherwise.
85
+ """
86
+
87
+ # Match fails if pattern is longer than entry
88
+ if len(self._patt) > len(entry):
89
+ return False
90
+
91
+ # Shift filter pattern across entry
92
+ for i in range(len(entry) - len(self._patt) + 1):
93
+
94
+ # Assume found unless determined otherwise
95
+ found = True
96
+ for j in range(len(self._patt)):
97
+
98
+ # Match fails if pattern element is longer than entry element
99
+ if len(self._patt[j]) > len(entry[i + j]):
100
+ found = False
101
+ break
102
+
103
+ # Match fails if first entry elements do not match patterm
104
+ if entry[i + j][0 : len(self._patt[j])] != self._patt[j]:
105
+ found = False
106
+ break
107
+
108
+ if found:
109
+ return True
110
+
111
+ return False
36
112
 
37
113
 
38
114
  class APIDump:
@@ -408,8 +484,24 @@ class APIDump:
408
484
 
409
485
  return inst
410
486
 
487
+ def apply_ignore_filter(self, ignore_filters: List[APIFilterType]) -> "APIDump":
488
+ """Remove API entries that match filters.
411
489
 
412
- APIDiffType = TypeVar("APIDiffType", bound="APIDiff")
490
+ Args:
491
+ ignore_filters (List[APIFilterType]):
492
+ List of filters to apply.
493
+
494
+ Returns:
495
+ APIDump: filtered APIDump instance.
496
+ """
497
+
498
+ filtered_api = self._api
499
+ for f in ignore_filters:
500
+ filtered_api = set(e for e in filtered_api if not f.match(e))
501
+
502
+ return self.__class__(
503
+ dump_file=self.dump_file, modules=self.modules, api=filtered_api
504
+ )
413
505
 
414
506
 
415
507
  class APIDiff:
@@ -470,6 +562,7 @@ class APIDiff:
470
562
  cls: Type[APIDiffType],
471
563
  old_dump_file: Union[Path, str],
472
564
  new_dump_file: Union[Path, str],
565
+ ignore_filters: Optional[List[APIFilterType]] = None,
473
566
  ) -> APIDiffType:
474
567
  """Differences between two Python public API dumps loaded from files.
475
568
 
@@ -478,6 +571,8 @@ class APIDiff:
478
571
  Name of file containing dump of the old public API.
479
572
  new_dump_file (Union[Path, str]):
480
573
  Name of file containing dump of the new public API.
574
+ ignore_filters (Optional[List[APIFilterType]]):
575
+ Remove API entries that match filters.
481
576
 
482
577
  Returns:
483
578
  APIDiffType: APIDiff instance.
@@ -487,6 +582,11 @@ class APIDiff:
487
582
  old = APIDump.load_from_file(old_dump_file)
488
583
  new = APIDump.load_from_file(new_dump_file)
489
584
 
585
+ # Apply filters
586
+ if ignore_filters and len(ignore_filters) > 0:
587
+ old = old.apply_ignore_filter(ignore_filters)
588
+ new = new.apply_ignore_filter(ignore_filters)
589
+
490
590
  # Create instance
491
591
  inst = cls(old, new)
492
592
 
@@ -8,7 +8,7 @@ import argparse
8
8
  import sys
9
9
  from pathlib import Path
10
10
 
11
- from . import APIDiff, APIDump
11
+ from . import APIDiff, APIDump, APIFilter
12
12
 
13
13
 
14
14
  def _dump(args):
@@ -35,7 +35,7 @@ def _dump(args):
35
35
  def _diff(args):
36
36
 
37
37
  # Load API diff
38
- diff = APIDiff.from_files(args.old_dump, args.new_dump)
38
+ diff = APIDiff.from_files(args.old_dump, args.new_dump, args.ignore)
39
39
 
40
40
  if args.output is None:
41
41
 
@@ -84,6 +84,13 @@ def cli(*argv):
84
84
  parser_diff.add_argument(
85
85
  "-t", "--text", action="store_true", help="Output API diff in text format"
86
86
  )
87
+ parser_diff.add_argument(
88
+ "-i",
89
+ "--ignore",
90
+ action="append",
91
+ type=APIFilter.from_str,
92
+ help="Use filter to ignore API dump entries before comparison",
93
+ )
87
94
  parser_diff.add_argument(
88
95
  "old_dump", type=Path, help="File containing dump of old API"
89
96
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-api-dumper
3
- Version: 4.1
3
+ Version: 4.2.0
4
4
  Summary: Python API dumping and comparison tool
5
5
  Author-email: Karl Wette <karl.wette@anu.edu.au>
6
6
  License-Expression: MIT
@@ -11,6 +11,7 @@ Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSES/MIT.txt
14
+ License-File: LICENSES/CC0-1.0.txt
14
15
  Dynamic: license-file
15
16
 
16
17
  # Python API dumping and comparison tool
@@ -76,6 +77,29 @@ $ py-api-dumper --help
76
77
  * API entries which have been *added*, i.e. present in the new API but not in
77
78
  the old API (e.g. the `b` argument in the above example).
78
79
 
80
+ * To filter out undesired entries from API dumps before comparison:
81
+ ```
82
+ $ py-api-dumper diff mymod-old.dump mymod-new.dump -i <filter>
83
+ ```
84
+ Given the following API:
85
+ ```
86
+ MODULE : mymod
87
+ CLASS : myclass
88
+ FUNCTION : __init__ : no-return-type
89
+ REQUIRED : 0 : x : int
90
+ ```
91
+ the following filters would ignore the given entries:
92
+ | `<filter>` | Ignore entries |
93
+ | ---------------------------- | ------------------------------------------ |
94
+ | `MODULE` | All modules |
95
+ | `MODULE:mymod` | All modules named `mymod` |
96
+ | `CLASS` | All classes |
97
+ | `CLASS:myclass` | All classes named `myclass` |
98
+ | `MODULE:mymod;CLASS` | All classes in modules named `mymod` |
99
+ | `MODULE:mymod;CLASS:myclass` | Class `myclass` in module `mymod` |
100
+ | `FUNCTION:__init__` | All functions named `__init__` |
101
+ | `CLASS;FUNCTION:__init__` | All functioned named `__init__` in classes |
102
+
79
103
  ## Python interface
80
104
 
81
105
  ```python
@@ -100,3 +124,9 @@ from py_api_dumper import APIDump, APIDiff
100
124
  diff.print_as_text()
101
125
  diff.save_as_json("mymod.diff")
102
126
  ```
127
+
128
+ * To filter out undesired entries from API dumps before comparison:
129
+ ```python
130
+ filter = APIFilter(("CLASS", "myclass")) # OR: APIFilter.from_str("CLASS:myclass")
131
+ diff = APIDiff.from_files("mymod-old.dump", "mymod-new.dump", filter)
132
+ ```
@@ -1,6 +1,7 @@
1
1
  MANIFEST.in
2
2
  README.md
3
3
  pyproject.toml
4
+ LICENSES/CC0-1.0.txt
4
5
  LICENSES/MIT.txt
5
6
  src/py_api_dumper/__init__.py
6
7
  src/py_api_dumper/cli.py
@@ -12,7 +12,7 @@ from pathlib import Path
12
12
  import api_ref
13
13
  import pytest
14
14
 
15
- from py_api_dumper import APIDiff, APIDump
15
+ from py_api_dumper import APIDiff, APIDump, APIFilter
16
16
  from py_api_dumper.cli import cli
17
17
 
18
18
 
@@ -387,3 +387,12 @@ def test_diff_cli_json(api_dump_file, api_dump_new_file, request):
387
387
  assert api_diff.added == set(
388
388
  tuple(tuple(e) for e in entry) for entry in api_diff_json["added"]
389
389
  )
390
+
391
+
392
+ def test_diff_ignore_filter(api_dump_file, api_dump_new_file, request):
393
+ """Test comparing API dumps with ignore filter."""
394
+ api_diff = APIDiff.from_files(
395
+ api_dump_file, api_dump_new_file, [APIFilter.from_str("CLASS:C1")]
396
+ )
397
+ assert len(api_diff.removed) == 4
398
+ assert len(api_diff.added) == 10
@@ -9,7 +9,7 @@ from pathlib import Path
9
9
  import api_ref
10
10
  import pytest
11
11
 
12
- from py_api_dumper import APIDump
12
+ from py_api_dumper import APIDump, APIFilter
13
13
  from py_api_dumper.cli import cli
14
14
 
15
15
 
@@ -46,6 +46,39 @@ def test_dump_module_cli(request):
46
46
  _compare_dumps(api_dump_text)
47
47
 
48
48
 
49
+ @pytest.mark.parametrize(
50
+ "patt,n_filtered_entries",
51
+ [
52
+ [[("MEMBER", "d1")], 1],
53
+ [[("CLASS", "C1"), ("MEMBER", "f1")], 1],
54
+ [[("CLASS", "C1")], 35],
55
+ [[("MEMBER", "does-not-exist", "just-to-test", "long-filter")], 0],
56
+ ],
57
+ )
58
+ def test_dump_module_filter(request, patt, n_filtered_entries):
59
+ """Create API dump from module and apply filter."""
60
+ api_dump = APIDump.from_modules(api_ref)
61
+ n_api_entries_before = len(api_dump._api)
62
+ api_dump = api_dump.apply_ignore_filter([APIFilter(*patt)])
63
+ assert len(api_dump._api) == n_api_entries_before - n_filtered_entries
64
+
65
+
66
+ @pytest.mark.parametrize(
67
+ "filter_str,n_filtered_entries",
68
+ [
69
+ ["MEMBER:d1", 1],
70
+ ["CLASS:C1;MEMBER:f1", 1],
71
+ ["CLASS:C1", 35],
72
+ ],
73
+ )
74
+ def test_dump_module_filter_str(request, filter_str, n_filtered_entries):
75
+ """Create API dump from module and apply filter created from string."""
76
+ api_dump = APIDump.from_modules(api_ref)
77
+ n_api_entries_before = len(api_dump._api)
78
+ api_dump = api_dump.apply_ignore_filter([APIFilter.from_str(filter_str)])
79
+ assert len(api_dump._api) == n_api_entries_before - n_filtered_entries
80
+
81
+
49
82
  def test_dump_file(request):
50
83
  """Test save and loading API dumps."""
51
84
  api_dump = APIDump.from_modules(api_ref)
File without changes
File without changes
File without changes