pytest-api-cov 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl

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.
pytest_api_cov/cli.py CHANGED
@@ -63,7 +63,7 @@ from {module_path} import {app_variable}
63
63
  @pytest.fixture
64
64
  def app():
65
65
  """Provide the {framework} app for API coverage testing.
66
-
66
+
67
67
  You can import from any location - just change the import path above
68
68
  to match your project structure.
69
69
  """
@@ -117,6 +117,9 @@ show_excluded_endpoints = false
117
117
 
118
118
  # Wrap an existing custom test client fixture with coverage tracking (optional)
119
119
  # client_fixture_name = "my_custom_client"
120
+
121
+ # Group HTTP methods by endpoint for legacy behavior (optional)
122
+ # group_methods_by_endpoint = false
120
123
  """
121
124
 
122
125
 
pytest_api_cov/config.py CHANGED
@@ -21,6 +21,7 @@ class ApiCoverageReportConfig(BaseModel):
21
21
  force_sugar: bool = Field(False, alias="api-cov-force-sugar")
22
22
  force_sugar_disabled: bool = Field(False, alias="api-cov-force-sugar-disabled")
23
23
  client_fixture_name: str = Field("coverage_client", alias="api-cov-client-fixture-name")
24
+ group_methods_by_endpoint: bool = Field(False, alias="api-cov-group-methods-by-endpoint")
24
25
 
25
26
 
26
27
  def read_toml_config() -> Dict[str, Any]:
@@ -45,6 +46,7 @@ def read_session_config(session_config: Any) -> Dict[str, Any]:
45
46
  "api-cov-force-sugar": "force_sugar",
46
47
  "api-cov-force-sugar-disabled": "force_sugar_disabled",
47
48
  "api-cov-client-fixture-name": "client_fixture_name",
49
+ "api-cov-group-methods-by-endpoint": "group_methods_by_endpoint",
48
50
  }
49
51
  config = {}
50
52
  for opt, key in cli_options.items():
@@ -21,8 +21,17 @@ class BaseAdapter:
21
21
 
22
22
  class FlaskAdapter(BaseAdapter):
23
23
  def get_endpoints(self) -> List[str]:
24
+ """Return list of 'METHOD /path' strings."""
24
25
  excluded_rules = ("/static/<path:filename>",)
25
- return sorted([rule.rule for rule in self.app.url_map.iter_rules() if rule.rule not in excluded_rules])
26
+ endpoints = []
27
+
28
+ for rule in self.app.url_map.iter_rules():
29
+ if rule.rule not in excluded_rules:
30
+ for method in rule.methods:
31
+ if method not in ("HEAD", "OPTIONS"): # Skip automatic methods
32
+ endpoints.append(f"{method} {rule.rule}")
33
+
34
+ return sorted(endpoints)
26
35
 
27
36
  def get_tracked_client(self, recorder: Optional["ApiCallRecorder"], test_name: str) -> Any:
28
37
  from flask.testing import FlaskClient
@@ -33,11 +42,13 @@ class FlaskAdapter(BaseAdapter):
33
42
  class TrackingFlaskClient(FlaskClient):
34
43
  def open(self, *args: Any, **kwargs: Any) -> Any:
35
44
  path = kwargs.get("path") or (args[0] if args else None)
45
+ method = kwargs.get("method", "GET").upper()
46
+
36
47
  if path and hasattr(self.application.url_map, "bind"):
37
48
  try:
38
- endpoint_name, _ = self.application.url_map.bind("").match(path, method=kwargs.get("method"))
49
+ endpoint_name, _ = self.application.url_map.bind("").match(path, method=method)
39
50
  endpoint_rule_string = next(self.application.url_map.iter_rules(endpoint_name)).rule
40
- recorder.record_call(endpoint_rule_string, test_name) # type: ignore[union-attr]
51
+ recorder.record_call(endpoint_rule_string, test_name, method) # type: ignore[union-attr]
41
52
  except Exception:
42
53
  pass
43
54
  return super().open(*args, **kwargs)
@@ -47,9 +58,17 @@ class FlaskAdapter(BaseAdapter):
47
58
 
48
59
  class FastAPIAdapter(BaseAdapter):
49
60
  def get_endpoints(self) -> List[str]:
61
+ """Return list of 'METHOD /path' strings."""
50
62
  from fastapi.routing import APIRoute
51
63
 
52
- return sorted([route.path for route in self.app.routes if isinstance(route, APIRoute)])
64
+ endpoints = []
65
+ for route in self.app.routes:
66
+ if isinstance(route, APIRoute):
67
+ for method in route.methods:
68
+ if method not in ("HEAD", "OPTIONS"):
69
+ endpoints.append(f"{method} {route.path}")
70
+
71
+ return sorted(endpoints)
53
72
 
54
73
  def get_tracked_client(self, recorder: Optional["ApiCallRecorder"], test_name: str) -> Any:
55
74
  from starlette.testclient import TestClient
@@ -61,7 +80,9 @@ class FastAPIAdapter(BaseAdapter):
61
80
  def send(self, *args: Any, **kwargs: Any) -> Any:
62
81
  request = args[0]
63
82
  if recorder is not None:
64
- recorder.record_call(request.url.path, test_name)
83
+ method = request.method.upper()
84
+ path = request.url.path
85
+ recorder.record_call(path, test_name, method)
65
86
  return super().send(*args, **kwargs)
66
87
 
67
88
  return TrackingFastAPIClient(self.app)
pytest_api_cov/models.py CHANGED
@@ -12,19 +12,27 @@ class ApiCallRecorder(BaseModel):
12
12
 
13
13
  calls: Dict[str, Set[str]] = Field(default_factory=dict)
14
14
 
15
- def record_call(self, endpoint: str, test_name: str) -> None:
16
- """Record that a test called an endpoint."""
17
- if endpoint not in self.calls:
18
- self.calls[endpoint] = set()
19
- self.calls[endpoint].add(test_name)
20
-
21
- def get_called_endpoints(self) -> List[str]:
22
- """Get list of all endpoints that have been called."""
23
- return list(self.calls.keys())
24
-
25
- def get_callers(self, endpoint: str) -> Set[str]:
26
- """Get the set of test names that called a specific endpoint."""
27
- return self.calls.get(endpoint, set())
15
+ def record_call(self, endpoint: str, test_name: str, method: str = "GET") -> None:
16
+ """Record that a test called a specific method on an endpoint."""
17
+ endpoint_method = self._format_endpoint_key(method, endpoint)
18
+ if endpoint_method not in self.calls:
19
+ self.calls[endpoint_method] = set()
20
+ self.calls[endpoint_method].add(test_name)
21
+
22
+ @staticmethod
23
+ def _format_endpoint_key(method: str, endpoint: str) -> str:
24
+ """Format method and endpoint into a consistent key format."""
25
+ return f"{method.upper()} {endpoint}"
26
+
27
+ @staticmethod
28
+ def _parse_endpoint_key(endpoint_key: str) -> tuple[str, str]:
29
+ """Parse an endpoint key back into method and endpoint parts."""
30
+ if " " in endpoint_key:
31
+ method, endpoint = endpoint_key.split(" ", 1)
32
+ return method, endpoint
33
+ else:
34
+ # Handle legacy format without method
35
+ return "GET", endpoint_key
28
36
 
29
37
  def merge(self, other: "ApiCallRecorder") -> None:
30
38
  """Merge another recorder's data into this one."""
@@ -70,15 +78,17 @@ class EndpointDiscovery(BaseModel):
70
78
  endpoints: List[str] = Field(default_factory=list)
71
79
  discovery_source: str = Field(default="unknown")
72
80
 
73
- def add_endpoint(self, endpoint: str) -> None:
74
- """Add a discovered endpoint."""
75
- if endpoint not in self.endpoints:
76
- self.endpoints.append(endpoint)
81
+ def add_endpoint(self, endpoint: str, method: str = "GET") -> None:
82
+ """Add a discovered endpoint method."""
83
+ endpoint_method = ApiCallRecorder._format_endpoint_key(method, endpoint)
84
+ if endpoint_method not in self.endpoints:
85
+ self.endpoints.append(endpoint_method)
77
86
 
78
87
  def merge(self, other: "EndpointDiscovery") -> None:
79
88
  """Merge another discovery's endpoints into this one."""
80
89
  for endpoint in other.endpoints:
81
- self.add_endpoint(endpoint)
90
+ if endpoint not in self.endpoints:
91
+ self.endpoints.append(endpoint)
82
92
 
83
93
  def __len__(self) -> int:
84
94
  """Return number of discovered endpoints."""
@@ -95,15 +105,24 @@ class SessionData(BaseModel):
95
105
  recorder: ApiCallRecorder = Field(default_factory=ApiCallRecorder)
96
106
  discovered_endpoints: EndpointDiscovery = Field(default_factory=EndpointDiscovery)
97
107
 
98
- def record_call(self, endpoint: str, test_name: str) -> None:
108
+ def record_call(self, endpoint: str, test_name: str, method: str = "GET") -> None:
99
109
  """Record an API call."""
100
- self.recorder.record_call(endpoint, test_name)
110
+ self.recorder.record_call(endpoint, test_name, method)
111
+
112
+ def add_discovered_endpoint(self, endpoint: str, method_or_source: str = "GET", source: str = "unknown") -> None:
113
+ """Add a discovered endpoint method."""
114
+ # Handle both old and new method signatures for backward compatibility
115
+ if method_or_source in ["flask_adapter", "fastapi_adapter", "worker", "unknown"]:
116
+ # Old signature: add_discovered_endpoint(endpoint, source)
117
+ method = "GET"
118
+ source = method_or_source
119
+ else:
120
+ # New signature: add_discovered_endpoint(endpoint, method, source)
121
+ method = method_or_source
101
122
 
102
- def add_discovered_endpoint(self, endpoint: str, source: str = "unknown") -> None:
103
- """Add a discovered endpoint."""
104
123
  if not self.discovered_endpoints.endpoints:
105
124
  self.discovered_endpoints.discovery_source = source
106
- self.discovered_endpoints.add_endpoint(endpoint)
125
+ self.discovered_endpoints.add_endpoint(endpoint, method)
107
126
 
108
127
  def merge_worker_data(self, worker_recorder: Dict[str, Any], worker_endpoints: List[str]) -> None:
109
128
  """Merge data from a worker process."""
pytest_api_cov/plugin.py CHANGED
@@ -65,10 +65,21 @@ def auto_discover_app() -> Optional[Any]:
65
65
  f"✅ Auto-discovered {type(app).__name__} app in {filename} as '{attr_name}'"
66
66
  )
67
67
  # Check if there are more files to scan
68
- remaining_files = [f for f in [p[0] for p in common_patterns[common_patterns.index((filename, attr_names)):]] if os.path.exists(f) and f != filename]
68
+ remaining_files = [
69
+ f
70
+ for f in [
71
+ p[0]
72
+ for p in common_patterns[common_patterns.index((filename, attr_names)) :]
73
+ ]
74
+ if os.path.exists(f) and f != filename
75
+ ]
69
76
  if remaining_files:
70
- logger.debug(f"> Note: Also found files {remaining_files} but using first discovered app")
71
- logger.debug(f"> To use a different app, create a conftest.py with an 'app' fixture")
77
+ logger.debug(
78
+ f"> Note: Also found files {remaining_files} but using first discovered app"
79
+ )
80
+ logger.debug(
81
+ "> To use a different app, create a conftest.py with an 'app' fixture"
82
+ )
72
83
  return app
73
84
  else:
74
85
  logger.debug(f"> Found '{attr_name}' in {filename} but it's not a supported framework")
@@ -80,9 +91,9 @@ def auto_discover_app() -> Optional[Any]:
80
91
  # If we get here, no apps were found
81
92
  if found_files:
82
93
  logger.debug(f"> Found files {found_files} but no supported Flask/FastAPI apps in them")
83
- logger.debug(f"> If your app is in one of these files with a different variable name,")
84
- logger.debug(f"> create a conftest.py with an 'app' fixture to specify it")
85
-
94
+ logger.debug("> If your app is in one of these files with a different variable name,")
95
+ logger.debug("> create a conftest.py with an 'app' fixture to specify it")
96
+
86
97
  logger.debug("> No app auto-discovered")
87
98
  return None
88
99
 
@@ -178,14 +189,15 @@ def wrap_client_with_coverage(client: Any, recorder: Any, test_name: str) -> Any
178
189
 
179
190
  def tracked_method(*args: Any, **kwargs: Any) -> Any:
180
191
  response = attr(*args, **kwargs)
181
- # Extract path from args[0]
192
+ # Extract path from args[0] and method from function name
182
193
  if args and recorder is not None:
183
194
  path = args[0]
184
195
  # Clean up the path to match endpoint format
185
196
  if isinstance(path, str):
186
197
  # Remove query parameters
187
198
  path = path.partition("?")[0]
188
- recorder.record_call(path, test_name)
199
+ method = name.upper() # get -> GET, post -> POST, etc.
200
+ recorder.record_call(path, test_name, method)
189
201
  return response
190
202
 
191
203
  return tracked_method
@@ -239,8 +251,10 @@ def coverage_client(request: pytest.FixtureRequest) -> Any:
239
251
  if not coverage_data.discovered_endpoints.endpoints:
240
252
  endpoints = adapter.get_endpoints()
241
253
  framework_name = type(app).__name__
242
- for endpoint in endpoints:
243
- coverage_data.add_discovered_endpoint(endpoint, f"{framework_name.lower()}_adapter")
254
+ for endpoint_method in endpoints:
255
+ # endpoint_method is now in "METHOD /path" format
256
+ method, path = endpoint_method.split(" ", 1)
257
+ coverage_data.add_discovered_endpoint(path, method, f"{framework_name.lower()}_adapter")
244
258
  logger.info(f"> pytest-api-coverage: Discovered {len(endpoints)} endpoints.")
245
259
  logger.debug(f"> Discovered endpoints: {endpoints}")
246
260
  except Exception as e:
@@ -274,8 +288,10 @@ def coverage_client(request: pytest.FixtureRequest) -> Any:
274
288
  try:
275
289
  endpoints = adapter.get_endpoints()
276
290
  framework_name = type(app).__name__
277
- for endpoint in endpoints:
278
- coverage_data.add_discovered_endpoint(endpoint, f"{framework_name.lower()}_adapter")
291
+ for endpoint_method in endpoints:
292
+ # endpoint_method is now in "METHOD /path" format
293
+ method, path = endpoint_method.split(" ", 1)
294
+ coverage_data.add_discovered_endpoint(path, method, f"{framework_name.lower()}_adapter")
279
295
  logger.info(f"> pytest-api-coverage: Discovered {len(endpoints)} endpoints.")
280
296
  logger.debug(f"> Discovered endpoints: {endpoints}")
281
297
  except Exception as e:
@@ -74,3 +74,9 @@ def add_pytest_api_cov_flags(parser: pytest.Parser) -> None:
74
74
  default=None,
75
75
  help="Name of existing test client fixture to wrap with coverage tracking",
76
76
  )
77
+ parser.addoption(
78
+ "--api-cov-group-methods-by-endpoint",
79
+ action="store_true",
80
+ default=False,
81
+ help="Group HTTP methods by endpoint for legacy behavior (default: method-aware coverage)",
82
+ )
pytest_api_cov/report.py CHANGED
@@ -44,7 +44,19 @@ def categorise_endpoints(
44
44
  )
45
45
 
46
46
  for endpoint in endpoints:
47
- if compiled_patterns and any(p.match(endpoint) for p in compiled_patterns):
47
+ # Check exclusion patterns against both full "METHOD /path" and just "/path"
48
+ is_excluded = False
49
+ if compiled_patterns:
50
+ # Extract path from "METHOD /path" format for pattern matching
51
+ if " " in endpoint:
52
+ _, path_only = endpoint.split(" ", 1)
53
+ is_excluded = any(p.match(endpoint) for p in compiled_patterns) or any(
54
+ p.match(path_only) for p in compiled_patterns
55
+ )
56
+ else:
57
+ is_excluded = any(p.match(endpoint) for p in compiled_patterns)
58
+
59
+ if is_excluded:
48
60
  excluded.append(endpoint)
49
61
  continue
50
62
  elif contains_escape_characters(endpoint):
@@ -67,7 +79,15 @@ def print_endpoints(
67
79
  if endpoints:
68
80
  console.print(f"[{style}]{label}[/]:")
69
81
  for endpoint in endpoints:
70
- console.print(f" {symbol} [{style}]{endpoint}[/]")
82
+ # Format endpoint with consistent spacing for HTTP methods
83
+ if " " in endpoint:
84
+ method, path = endpoint.split(" ", 1)
85
+ # Pad method to 6 characters (longest common method is DELETE)
86
+ formatted_endpoint = f"{method:<6} {path}"
87
+ else:
88
+ # Handle legacy format without method
89
+ formatted_endpoint = endpoint
90
+ console.print(f" {symbol} [{style}]{formatted_endpoint}[/]")
71
91
 
72
92
 
73
93
  def compute_coverage(covered_count: int, uncovered_count: int) -> float:
@@ -1,19 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-api-cov
3
- Version: 1.0.1
4
- Summary: Api Coverage Report Pytest Plugin
3
+ Version: 1.1.0
4
+ Summary: Pytest Plugin to provide API Coverage statistics for Python Web Frameworks
5
5
  Author-email: Barnaby Gill <barnabasgill@gmail.com>
6
6
  License: Apache-2.0
7
7
  License-File: LICENSE
8
8
  Requires-Python: >=3.10
9
- Requires-Dist: fastapi>=0.116.1
10
- Requires-Dist: flask>=3.1.1
11
- Requires-Dist: httpx>=0.28.1
12
- Requires-Dist: pydantic>=2.11.7
13
- Requires-Dist: pytest>=8.4.1
14
- Requires-Dist: rich>=14.0.0
15
- Requires-Dist: starlette>=0.47.1
16
- Requires-Dist: tomli>=2.2.1
9
+ Requires-Dist: fastapi>=0.68.0
10
+ Requires-Dist: flask>=2.0.0
11
+ Requires-Dist: httpx>=0.20.0
12
+ Requires-Dist: pydantic>=2.0.0
13
+ Requires-Dist: pytest>=6.0.0
14
+ Requires-Dist: rich>=10.0.0
15
+ Requires-Dist: starlette>=0.14.0
16
+ Requires-Dist: tomli>=1.2.0
17
17
  Description-Content-Type: text/markdown
18
18
 
19
19
  # pytest-api-cov
@@ -83,6 +83,10 @@ def read_root():
83
83
  def get_user(user_id: int):
84
84
  return {"user_id": user_id}
85
85
 
86
+ @app.post("/users")
87
+ def create_user(user: dict):
88
+ return {"message": "User created", "user": user}
89
+
86
90
  @app.get("/health")
87
91
  def health_check():
88
92
  return {"status": "ok"}
@@ -98,6 +102,10 @@ def test_root_endpoint(coverage_client):
98
102
  def test_get_user(coverage_client):
99
103
  response = coverage_client.get("/users/123")
100
104
  assert response.status_code == 200
105
+
106
+ def test_create_user(coverage_client):
107
+ response = coverage_client.post("/users", json={"name": "John"})
108
+ assert response.status_code == 200
101
109
  ```
102
110
 
103
111
  Running `pytest --api-cov-report` produces:
@@ -105,27 +113,69 @@ Running `pytest --api-cov-report` produces:
105
113
  ```
106
114
  API Coverage Report
107
115
  Uncovered Endpoints:
108
- [X] /health
116
+ GET /health
109
117
 
110
118
  Total API Coverage: 66.67%
111
119
  ```
112
120
 
113
- Or running with advanced options `pytest --api-cov-report --api-cov-show-covered-endpoints --api-cov-exclusion-patterns="/users/*" --api-cov-show-excluded-endpoints --api-cov-report-path=api_coverage.json --api-cov-fail-under=49` produces:
121
+ Or running with advanced options:
122
+ ```bash
123
+ pytest --api-cov-report --api-cov-show-covered-endpoints --api-cov-exclusion-patterns="/users*" --api-cov-show-excluded-endpoints --api-cov-report-path=api_coverage.json
124
+ ```
114
125
 
115
126
  ```
116
127
  API Coverage Report
117
128
  Uncovered Endpoints:
118
- [X] /health
129
+ GET /health
119
130
  Covered Endpoints:
120
- [.] /
131
+ GET /
121
132
  Excluded Endpoints:
122
- [-] /users/{user_id}
133
+ 🚫 GET /users/{user_id}
134
+ 🚫 POST /users
123
135
 
124
- SUCCESS: Coverage of 50.0% meets requirement of 49.0%
136
+ Total API Coverage: 50.0%
125
137
 
126
138
  JSON report saved to api_coverage.json
127
139
  ```
128
140
 
141
+ ## HTTP Method-Aware Coverage
142
+
143
+ By default, pytest-api-cov tracks coverage for **each HTTP method separately**. This means `GET /users` and `POST /users` are treated as different endpoints for coverage purposes.
144
+
145
+ ### Method-Aware (Default Behavior)
146
+ ```
147
+ Covered Endpoints:
148
+ ✅ GET /users/{id}
149
+ ✅ POST /users
150
+ Uncovered Endpoints:
151
+ ❌ PUT /users/{id}
152
+ ❌ DELETE /users/{id}
153
+
154
+ Total API Coverage: 50.0% # 2 out of 4 method-endpoint combinations
155
+ ```
156
+
157
+ ### Endpoint Grouping
158
+ To group all methods on an endpoint are together, use:
159
+
160
+ ```bash
161
+ pytest --api-cov-report --api-cov-group-methods-by-endpoint
162
+ ```
163
+
164
+ Or in `pyproject.toml`:
165
+ ```toml
166
+ [tool.pytest_api_cov]
167
+ group_methods_by_endpoint = true
168
+ ```
169
+
170
+ This would show:
171
+ ```
172
+ Covered Endpoints:
173
+ ✅ /users/{id} # Any method tested
174
+ ✅ /users # Any method tested
175
+
176
+ Total API Coverage: 100.0% # All endpoints have at least one method tested
177
+ ```
178
+
129
179
  ## Advanced Configuration
130
180
 
131
181
  ### Setup Wizard
@@ -230,6 +280,11 @@ force_sugar_disabled = true
230
280
 
231
281
  # Wrap an existing custom test client fixture with coverage tracking
232
282
  client_fixture_name = "my_custom_client"
283
+
284
+ # Group HTTP methods by endpoint for legacy behavior (default: false)
285
+ # When true: treats GET /users and POST /users as one "/users" endpoint
286
+ # When false: treats them as separate "GET /users" and "POST /users" endpoints (recommended)
287
+ group_methods_by_endpoint = false
233
288
  ```
234
289
 
235
290
  ### Command Line Options
@@ -261,6 +316,9 @@ pytest --api-cov-report -v
261
316
 
262
317
  # Debug logging (very detailed)
263
318
  pytest --api-cov-report -vv
319
+
320
+ # Group HTTP methods by endpoint (legacy behavior)
321
+ pytest --api-cov-report --api-cov-group-methods-by-endpoint
264
322
  ```
265
323
 
266
324
  ## Framework Support
@@ -0,0 +1,13 @@
1
+ pytest_api_cov/__init__.py,sha256=7ZX-XIlYwdB0AkSSaXG2O6mah3CBCjZGTiBSEf5dTqk,177
2
+ pytest_api_cov/cli.py,sha256=1iDYhWZJ_wDU9nPov7FfNrpT5sIU7PmAGiuVqy4zFM4,7290
3
+ pytest_api_cov/config.py,sha256=m9UsbKKcL5_Wb-lRMCpV-_mMpdYFDo0oV6vxxHKAB7k,3493
4
+ pytest_api_cov/frameworks.py,sha256=0_8ZzVbeZ6U1ZZwuzCn82m-q5NcRlIOTtocV5zeIGd0,3955
5
+ pytest_api_cov/models.py,sha256=AW7X4DzzsY-HtNsQMm5x55x95Q-10B2xhD9_XaXFDBw,5997
6
+ pytest_api_cov/plugin.py,sha256=o2fqQv3M5HzlPYGXm-rDBxbPRHbiMEPpImJ4a5tum0s,16540
7
+ pytest_api_cov/pytest_flags.py,sha256=oGTCv7T_Mj439PFrvB3LawmLFQYppZOOS1f_HOK1cJE,2408
8
+ pytest_api_cov/report.py,sha256=hUBEIjK0TXEnamWV61_w6AZKHLh5mD0eXcrmTs61baQ,7600
9
+ pytest_api_cov-1.1.0.dist-info/METADATA,sha256=uznGlaFxXlXM2FnGtRTtyDqM_nPerAaTMt8ubTQQvxY,12841
10
+ pytest_api_cov-1.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
11
+ pytest_api_cov-1.1.0.dist-info/entry_points.txt,sha256=hWqEhsBKzbwSwcxCzKgSA8NElQxk0K4PKERrYsi3csk,110
12
+ pytest_api_cov-1.1.0.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
13
+ pytest_api_cov-1.1.0.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- pytest_api_cov/__init__.py,sha256=7ZX-XIlYwdB0AkSSaXG2O6mah3CBCjZGTiBSEf5dTqk,177
2
- pytest_api_cov/cli.py,sha256=-ZLRVIjhakJel5tzn1zTTIEox230xGRrnl3ne1VT2tU,7190
3
- pytest_api_cov/config.py,sha256=51GaJgAtctAcNb2F-7Q65qZuNusf3_s1-4bE-AWv5QE,3323
4
- pytest_api_cov/frameworks.py,sha256=5d6wnEsb2BykPtpnpkv98GMPuyoG4elXRJ7vtGHF06A,3228
5
- pytest_api_cov/models.py,sha256=YiXLiEEyNREiodzn1pGqSNIHrm3zV6kFn0XgyN8_8Rs,4893
6
- pytest_api_cov/plugin.py,sha256=jBNggRYFZqVwUGDyhMC58nV8A_zz7vZ3YlH2XRN1mzc,15664
7
- pytest_api_cov/pytest_flags.py,sha256=OX1NMcQHfI9uyPrZXj0Q_VG1daU8uKKB4sY-4JLm220,2175
8
- pytest_api_cov/report.py,sha256=VxfWag20V8o9ArbxOkR_gWQ2TE-sthrS0PCJvn4YCSU,6642
9
- pytest_api_cov-1.0.1.dist-info/METADATA,sha256=F5F1pOVB7rmCFhcMs369WvG1K5KJe1FdkHf7YlfhwVc,11264
10
- pytest_api_cov-1.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
11
- pytest_api_cov-1.0.1.dist-info/entry_points.txt,sha256=hWqEhsBKzbwSwcxCzKgSA8NElQxk0K4PKERrYsi3csk,110
12
- pytest_api_cov-1.0.1.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
13
- pytest_api_cov-1.0.1.dist-info/RECORD,,