mutmut 3.3.1__tar.gz → 3.5.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 (41) hide show
  1. {mutmut-3.3.1 → mutmut-3.5.0}/HISTORY.rst +47 -1
  2. {mutmut-3.3.1/mutmut.egg-info → mutmut-3.5.0}/PKG-INFO +110 -37
  3. mutmut-3.3.1/PKG-INFO → mutmut-3.5.0/README.rst +85 -45
  4. mutmut-3.5.0/pyproject.toml +69 -0
  5. {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/__init__.py +7 -4
  6. {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/__main__.py +403 -125
  7. mutmut-3.5.0/src/mutmut/code_coverage.py +63 -0
  8. {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/file_mutation.py +123 -17
  9. {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/node_mutation.py +3 -0
  10. mutmut-3.5.0/src/mutmut/trampoline_templates.py +56 -0
  11. mutmut-3.5.0/src/mutmut/type_checking.py +98 -0
  12. mutmut-3.3.1/AUTHORS.rst +0 -29
  13. mutmut-3.3.1/MANIFEST.in +0 -6
  14. mutmut-3.3.1/README.rst +0 -216
  15. mutmut-3.3.1/mutmut/.DS_Store +0 -0
  16. mutmut-3.3.1/mutmut/__pycache__/__init__.cpython-311.pyc +0 -0
  17. mutmut-3.3.1/mutmut/__pycache__/__init__.cpython-312.pyc +0 -0
  18. mutmut-3.3.1/mutmut/__pycache__/__main__.cpython-311.pyc +0 -0
  19. mutmut-3.3.1/mutmut/__pycache__/__main__.cpython-312.pyc +0 -0
  20. mutmut-3.3.1/mutmut/__pycache__/file_mutation.cpython-312.pyc +0 -0
  21. mutmut-3.3.1/mutmut/__pycache__/node_mutation.cpython-312.pyc +0 -0
  22. mutmut-3.3.1/mutmut/__pycache__/trampoline_templates.cpython-312.pyc +0 -0
  23. mutmut-3.3.1/mutmut/trampoline_templates.py +0 -73
  24. mutmut-3.3.1/mutmut.egg-info/SOURCES.txt +0 -42
  25. mutmut-3.3.1/mutmut.egg-info/dependency_links.txt +0 -1
  26. mutmut-3.3.1/mutmut.egg-info/entry_points.txt +0 -2
  27. mutmut-3.3.1/mutmut.egg-info/not-zip-safe +0 -1
  28. mutmut-3.3.1/mutmut.egg-info/requires.txt +0 -8
  29. mutmut-3.3.1/mutmut.egg-info/top_level.txt +0 -2
  30. mutmut-3.3.1/requirements.txt +0 -7
  31. mutmut-3.3.1/setup.cfg +0 -19
  32. mutmut-3.3.1/setup.py +0 -112
  33. mutmut-3.3.1/tests/__init__.py +0 -0
  34. mutmut-3.3.1/tests/e2e/__init__.py +0 -0
  35. mutmut-3.3.1/tests/e2e/test_cli_version.py +0 -9
  36. mutmut-3.3.1/tests/e2e/test_e2e_result_snapshots.py +0 -80
  37. mutmut-3.3.1/tests/test_generation_error_handling.py +0 -35
  38. mutmut-3.3.1/tests/test_mutation.py +0 -710
  39. mutmut-3.3.1/tests/test_mutmut3.py +0 -74
  40. {mutmut-3.3.1 → mutmut-3.5.0}/LICENSE +0 -0
  41. {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/result_browser_layout.tcss +0 -0
@@ -1,6 +1,52 @@
1
1
  Changelog
2
2
  ---------
3
3
 
4
+ 3.5.0
5
+ ~~~~~
6
+
7
+ * Filter mutants based on type annotations. This feature needs to be turned on with the `type_check_command` config.
8
+
9
+ * Support running on Windows
10
+
11
+ * Save mutation stats for use with CI/CD pipeline (#460)
12
+
13
+ * Async functions fixed
14
+
15
+ * Fix for functions with positional only arguments
16
+
17
+ * Support signatures with PEP 649 deferred annotations
18
+
19
+
20
+ 3.4.0
21
+ ~~~~~
22
+
23
+ * Add action to view tests for mutant
24
+
25
+ * Add basic description for all results in mutmut browse
26
+
27
+ * Add description for timeout mutants
28
+
29
+ * Early exit when stats find no tests for any mutant
30
+
31
+ * Support python 3.14
32
+
33
+ * Performance improvements
34
+
35
+ * Fix `mutate_only_covered_lines` when files are excluded from test run
36
+
37
+ * Add `pytest_add_cli_args` and `pytest_add_cli_args_test_selection` configs
38
+
39
+ * `mutate_only_covered_lines` added to config to control whether coverage.py is used to filter down mutations
40
+
41
+ * Filter out identical string mutants with different values
42
+
43
+ * Handle more exit codes
44
+
45
+ * Disable common order-randomising pytest plugins, as that can seriously deteriorate mutation testing performance
46
+
47
+ * Fixed packaging issue
48
+
49
+
4
50
  3.3.1
5
51
  ~~~~~
6
52
 
@@ -143,7 +189,7 @@ Changelog
143
189
  3.0.0
144
190
  ~~~~~
145
191
 
146
- * Execution model switched to mutation schemata, which enabled parallell execution.
192
+ * Execution model switched to mutation schemata, which enabled parallel execution.
147
193
 
148
194
  * New terminal UI
149
195
 
@@ -1,26 +1,35 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: mutmut
3
- Version: 3.3.1
3
+ Version: 3.5.0
4
4
  Summary: mutation testing for Python 3
5
- Home-page: https://github.com/boxed/mutmut
5
+ Keywords: mutmut,mutant,mutation,test,testing
6
6
  Author: Anders Hovmöller
7
- Author-email: boxed@killingar.net
8
- License: BSD
9
- Keywords: mutmut mutant mutation test testing
7
+ Author-email: Anders Hovmöller <boxed@killingar.net>
8
+ License-Expression: BSD-3-Clause
9
+ License-File: LICENSE
10
10
  Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: BSD License
13
12
  Classifier: Natural Language :: English
14
13
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.7
16
- License-File: LICENSE
17
- License-File: AUTHORS.rst
18
- Requires-Dist: libcst~=1.7.0
19
- Requires-Dist: click
20
- Requires-Dist: setproctitle
21
- Requires-Dist: textual
22
- Requires-Dist: toml>=0.10.2; python_version < "3.11"
23
- Requires-Dist: pytest
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Dist: click>=8.0.0
20
+ Requires-Dist: coverage>=7.3.0
21
+ Requires-Dist: libcst>=1.8.5
22
+ Requires-Dist: pytest>=6.2.5
23
+ Requires-Dist: setproctitle>=1.1.0
24
+ Requires-Dist: textual>=1.0.0
25
+ Requires-Dist: toml>=0.10.2 ; python_full_version < '3.11'
26
+ Requires-Python: >=3.10
27
+ Project-URL: Changelog, https://github.com/boxed/mutmut/blob/main/HISTORY.rst
28
+ Project-URL: Documentation, https://mutmut.readthedocs.io/en/latest/
29
+ Project-URL: Homepage, https://github.com/boxed/mutmut
30
+ Project-URL: Issues, https://github.com/boxed/mutmut/issues
31
+ Project-URL: Repository, https://github.com/boxed/mutmut
32
+ Description-Content-Type: text/x-rst
24
33
 
25
34
  mutmut - python mutation tester
26
35
  ===============================
@@ -91,6 +100,20 @@ source code control and committed before you apply a mutant!
91
100
  If during the installation you get an error for the `libcst` dependency mentioning the lack of a rust compiler on your system, it is because your architecture does not have a prebuilt binary for `libcst` and it requires both `rustc` and `cargo` from the [rust toolchain](https://www.rust-lang.org/tools/install) to be built. This is known for at least the `x86_64-darwin` architecture.
92
101
 
93
102
 
103
+ Wildcards for testing mutants
104
+ -----------------------------
105
+
106
+ Unix filename pattern matching style on mutants is supported. Example:
107
+
108
+ .. code-block:: console
109
+
110
+ mutmut run "my_module*"
111
+ mutmut run "my_module.my_function*"
112
+
113
+ In the `browse` TUI you can press `f` to retest a function, and `m` to retest
114
+ an entire module.
115
+
116
+
94
117
  Configuration
95
118
  -------------
96
119
 
@@ -100,7 +123,7 @@ In `setup.cfg` in the root of your project you can configure mutmut if you need
100
123
 
101
124
  [mutmut]
102
125
  paths_to_mutate=src/
103
- tests_dir=tests/
126
+ pytest_add_cli_args_test_selection=tests/
104
127
 
105
128
  If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutmut` section:
106
129
 
@@ -108,27 +131,13 @@ If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutm
108
131
 
109
132
  [tool.mutmut]
110
133
  paths_to_mutate = [ "src/" ]
111
- tests_dir = [ "tests/" ]
134
+ pytest_add_cli_args_test_selection= [ "tests/" ]
112
135
 
113
136
  See below for more options for configuring mutmut.
114
137
 
115
138
 
116
- Wildcards for testing mutants
117
- -----------------------------
118
-
119
- Unix filename pattern matching style on mutants is supported. Example:
120
-
121
- .. code-block:: console
122
-
123
- mutmut run "my_module*"
124
- mutmut run "my_module.my_function*"
125
-
126
- In the `browse` TUI you can press `f` to retest a function, and `m` to retest
127
- an entire module.
128
-
129
-
130
139
  "also copy" files
131
- -----------------
140
+ ~~~~~~~~~~~~~~~~~
132
141
 
133
142
  To run the full test suite some files are often needed above the tests and the
134
143
  source. You can configure to copy extra files that you need by adding
@@ -142,7 +151,7 @@ directories and files to `also_copy` in your `setup.cfg`:
142
151
 
143
152
 
144
153
  Limit stack depth
145
- -----------------
154
+ ~~~~~~~~~~~~~~~~~
146
155
 
147
156
  In big code bases some functions are called incidentally by huge swaths of the
148
157
  codebase, but you really don't want tests that hit those executions to count
@@ -166,7 +175,7 @@ caught.
166
175
 
167
176
 
168
177
  Exclude files from mutation
169
- ---------------------------
178
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
170
179
 
171
180
  You can exclude files from mutation in `setup.cfg`:
172
181
 
@@ -176,8 +185,51 @@ You can exclude files from mutation in `setup.cfg`:
176
185
  *__tests.py
177
186
 
178
187
 
188
+ Enable coverage.py filtering of lines to mutate
189
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
190
+
191
+ By default, mutmut will mutate only functions that are called. But, if you would like a finer grained (line-level)
192
+ check for coverage, mutmut can use coverage.py to do that.
193
+
194
+ If you only want to mutate lines that are called (according to coverage.py), you can set
195
+ `mutate_only_covered_lines` to `true` in your configuration. The default value is `false`.
196
+
197
+
198
+ .. code-block::
199
+
200
+ mutate_only_covered_lines=true
201
+
202
+
203
+ Filter generated mutants with type checker
204
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
205
+
206
+ When your project is type checked using `mypy` or `pyrefly`, you can also use it to filter out invalid mutants.
207
+ For instance, mutmut mutates `x: str = 'foo'` to `x: str = None` which can easily caught by type checkers.
208
+
209
+ Using this filter can improve performance and reduce noise, however it can also hide a few relevant mutations:
210
+
211
+ 1. `x: str = None` may not be valid, but if your tests do not detect such a change it indicates that
212
+ the value of `x` is not properly tested (even if your type checker would catch this particular modification)
213
+ 2. In some edge cases with class properties (usually in the `__init__` method), the way `mypy` and `pyrefly` infer types does not work well
214
+ with the way mutmut mutates code. Some valid mutations like changing `self.x = 123` to `self.x = None` can
215
+ be filtered out, even though the may be valid.
216
+
217
+ To enable this filtering, configure the `type_check_command` to output json results as follows:
218
+
219
+ .. code-block::
220
+
221
+ # for pyrefly
222
+ type_check_command = ['pyrefly', 'check', '--output-format=json']
223
+ # for mypy
224
+ type_check_command = ['mypy', 'traces_parser', '--output', 'json']
225
+
226
+ Currently, only `pyrefly` and `mypy` are supported.
227
+ With `pyright` and `ty`, mutating a class method `Foo.bar()` can break the types of all methods of `Foo`,
228
+ and therefore mutmut cannot match the type error with the mutant that caused the type error.
229
+
230
+
179
231
  Enable debug output (increase verbosity)
180
- ----------------------------------------
232
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
181
233
 
182
234
  By default, mutmut "swallows" all the test output etc. so that you get a nice clean output.
183
235
 
@@ -191,7 +243,7 @@ to failing tests.
191
243
 
192
244
 
193
245
  Whitelisting
194
- ------------
246
+ ~~~~~~~~~~~~
195
247
 
196
248
  You can mark lines like this:
197
249
 
@@ -207,6 +259,27 @@ whitelist lines are:
207
259
  to continue, but it's slower.
208
260
 
209
261
 
262
+ Modifying pytest arguments
263
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
264
+
265
+ You can add and override pytest arguments:
266
+
267
+ .. code-block:: python
268
+
269
+ # for CLI args that select or deselect tests, use `pytest_add_cli_args_test_selection`
270
+ pytest_add_cli_args_test_selection = ["-m", "not fail", "-k", "test_include"]
271
+
272
+ # for other CLI args, use `pytest_add_cli_args`
273
+ pytest_add_cli_args = ["-p", "no:some_plugin"] # disable a plugin
274
+ pytest_add_cli_args = ["-o", "xfail_strict=False"] # overrides xfail_strict from your normal config
275
+
276
+ # if you want to ignore the normal pytest configuration
277
+ # you can specify a diferent pytest ini file to be used
278
+ pytest_add_cli_args = ["-c", "mutmut_pytest.ini"]
279
+ also_copy = ["mutmut_pytest.ini"]
280
+
281
+
282
+
210
283
  Example mutations
211
284
  -----------------
212
285
 
@@ -1,27 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: mutmut
3
- Version: 3.3.1
4
- Summary: mutation testing for Python 3
5
- Home-page: https://github.com/boxed/mutmut
6
- Author: Anders Hovmöller
7
- Author-email: boxed@killingar.net
8
- License: BSD
9
- Keywords: mutmut mutant mutation test testing
10
- Classifier: Development Status :: 4 - Beta
11
- Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: BSD License
13
- Classifier: Natural Language :: English
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.7
16
- License-File: LICENSE
17
- License-File: AUTHORS.rst
18
- Requires-Dist: libcst~=1.7.0
19
- Requires-Dist: click
20
- Requires-Dist: setproctitle
21
- Requires-Dist: textual
22
- Requires-Dist: toml>=0.10.2; python_version < "3.11"
23
- Requires-Dist: pytest
24
-
25
1
  mutmut - python mutation tester
26
2
  ===============================
27
3
 
@@ -91,6 +67,20 @@ source code control and committed before you apply a mutant!
91
67
  If during the installation you get an error for the `libcst` dependency mentioning the lack of a rust compiler on your system, it is because your architecture does not have a prebuilt binary for `libcst` and it requires both `rustc` and `cargo` from the [rust toolchain](https://www.rust-lang.org/tools/install) to be built. This is known for at least the `x86_64-darwin` architecture.
92
68
 
93
69
 
70
+ Wildcards for testing mutants
71
+ -----------------------------
72
+
73
+ Unix filename pattern matching style on mutants is supported. Example:
74
+
75
+ .. code-block:: console
76
+
77
+ mutmut run "my_module*"
78
+ mutmut run "my_module.my_function*"
79
+
80
+ In the `browse` TUI you can press `f` to retest a function, and `m` to retest
81
+ an entire module.
82
+
83
+
94
84
  Configuration
95
85
  -------------
96
86
 
@@ -100,7 +90,7 @@ In `setup.cfg` in the root of your project you can configure mutmut if you need
100
90
 
101
91
  [mutmut]
102
92
  paths_to_mutate=src/
103
- tests_dir=tests/
93
+ pytest_add_cli_args_test_selection=tests/
104
94
 
105
95
  If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutmut` section:
106
96
 
@@ -108,27 +98,13 @@ If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutm
108
98
 
109
99
  [tool.mutmut]
110
100
  paths_to_mutate = [ "src/" ]
111
- tests_dir = [ "tests/" ]
101
+ pytest_add_cli_args_test_selection= [ "tests/" ]
112
102
 
113
103
  See below for more options for configuring mutmut.
114
104
 
115
105
 
116
- Wildcards for testing mutants
117
- -----------------------------
118
-
119
- Unix filename pattern matching style on mutants is supported. Example:
120
-
121
- .. code-block:: console
122
-
123
- mutmut run "my_module*"
124
- mutmut run "my_module.my_function*"
125
-
126
- In the `browse` TUI you can press `f` to retest a function, and `m` to retest
127
- an entire module.
128
-
129
-
130
106
  "also copy" files
131
- -----------------
107
+ ~~~~~~~~~~~~~~~~~
132
108
 
133
109
  To run the full test suite some files are often needed above the tests and the
134
110
  source. You can configure to copy extra files that you need by adding
@@ -142,7 +118,7 @@ directories and files to `also_copy` in your `setup.cfg`:
142
118
 
143
119
 
144
120
  Limit stack depth
145
- -----------------
121
+ ~~~~~~~~~~~~~~~~~
146
122
 
147
123
  In big code bases some functions are called incidentally by huge swaths of the
148
124
  codebase, but you really don't want tests that hit those executions to count
@@ -166,7 +142,7 @@ caught.
166
142
 
167
143
 
168
144
  Exclude files from mutation
169
- ---------------------------
145
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
170
146
 
171
147
  You can exclude files from mutation in `setup.cfg`:
172
148
 
@@ -176,8 +152,51 @@ You can exclude files from mutation in `setup.cfg`:
176
152
  *__tests.py
177
153
 
178
154
 
155
+ Enable coverage.py filtering of lines to mutate
156
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
157
+
158
+ By default, mutmut will mutate only functions that are called. But, if you would like a finer grained (line-level)
159
+ check for coverage, mutmut can use coverage.py to do that.
160
+
161
+ If you only want to mutate lines that are called (according to coverage.py), you can set
162
+ `mutate_only_covered_lines` to `true` in your configuration. The default value is `false`.
163
+
164
+
165
+ .. code-block::
166
+
167
+ mutate_only_covered_lines=true
168
+
169
+
170
+ Filter generated mutants with type checker
171
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172
+
173
+ When your project is type checked using `mypy` or `pyrefly`, you can also use it to filter out invalid mutants.
174
+ For instance, mutmut mutates `x: str = 'foo'` to `x: str = None` which can easily caught by type checkers.
175
+
176
+ Using this filter can improve performance and reduce noise, however it can also hide a few relevant mutations:
177
+
178
+ 1. `x: str = None` may not be valid, but if your tests do not detect such a change it indicates that
179
+ the value of `x` is not properly tested (even if your type checker would catch this particular modification)
180
+ 2. In some edge cases with class properties (usually in the `__init__` method), the way `mypy` and `pyrefly` infer types does not work well
181
+ with the way mutmut mutates code. Some valid mutations like changing `self.x = 123` to `self.x = None` can
182
+ be filtered out, even though the may be valid.
183
+
184
+ To enable this filtering, configure the `type_check_command` to output json results as follows:
185
+
186
+ .. code-block::
187
+
188
+ # for pyrefly
189
+ type_check_command = ['pyrefly', 'check', '--output-format=json']
190
+ # for mypy
191
+ type_check_command = ['mypy', 'traces_parser', '--output', 'json']
192
+
193
+ Currently, only `pyrefly` and `mypy` are supported.
194
+ With `pyright` and `ty`, mutating a class method `Foo.bar()` can break the types of all methods of `Foo`,
195
+ and therefore mutmut cannot match the type error with the mutant that caused the type error.
196
+
197
+
179
198
  Enable debug output (increase verbosity)
180
- ----------------------------------------
199
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
181
200
 
182
201
  By default, mutmut "swallows" all the test output etc. so that you get a nice clean output.
183
202
 
@@ -191,7 +210,7 @@ to failing tests.
191
210
 
192
211
 
193
212
  Whitelisting
194
- ------------
213
+ ~~~~~~~~~~~~
195
214
 
196
215
  You can mark lines like this:
197
216
 
@@ -207,6 +226,27 @@ whitelist lines are:
207
226
  to continue, but it's slower.
208
227
 
209
228
 
229
+ Modifying pytest arguments
230
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
231
+
232
+ You can add and override pytest arguments:
233
+
234
+ .. code-block:: python
235
+
236
+ # for CLI args that select or deselect tests, use `pytest_add_cli_args_test_selection`
237
+ pytest_add_cli_args_test_selection = ["-m", "not fail", "-k", "test_include"]
238
+
239
+ # for other CLI args, use `pytest_add_cli_args`
240
+ pytest_add_cli_args = ["-p", "no:some_plugin"] # disable a plugin
241
+ pytest_add_cli_args = ["-o", "xfail_strict=False"] # overrides xfail_strict from your normal config
242
+
243
+ # if you want to ignore the normal pytest configuration
244
+ # you can specify a diferent pytest ini file to be used
245
+ pytest_add_cli_args = ["-c", "mutmut_pytest.ini"]
246
+ also_copy = ["mutmut_pytest.ini"]
247
+
248
+
249
+
210
250
  Example mutations
211
251
  -----------------
212
252
 
@@ -0,0 +1,69 @@
1
+ [project]
2
+ name = "mutmut"
3
+ version = "3.5.0"
4
+ description = "mutation testing for Python 3"
5
+ keywords = ["mutmut", "mutant", "mutation", "test", "testing"]
6
+ authors = [
7
+ { name = "Anders Hovmöller", email = "boxed@killingar.net" },
8
+ ]
9
+ requires-python = ">=3.10"
10
+ readme = "README.rst"
11
+ license = "BSD-3-Clause"
12
+ license-files = ["LICENSE"]
13
+
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "Natural Language :: English",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Programming Language :: Python :: 3.14",
24
+ ]
25
+
26
+ dependencies = [
27
+ "click>=8.0.0",
28
+ "coverage>=7.3.0",
29
+ "libcst>=1.8.5",
30
+ "pytest>=6.2.5",
31
+ "setproctitle>=1.1.0",
32
+ "textual>=1.0.0",
33
+ "toml>=0.10.2 ; python_full_version < '3.11'",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/boxed/mutmut"
38
+ Documentation = "https://mutmut.readthedocs.io/en/latest/"
39
+ Repository = "https://github.com/boxed/mutmut"
40
+ Issues = "https://github.com/boxed/mutmut/issues"
41
+ Changelog = "https://github.com/boxed/mutmut/blob/main/HISTORY.rst"
42
+
43
+
44
+ [project.scripts]
45
+ mutmut = "mutmut.__main__:cli"
46
+
47
+ [build-system]
48
+ requires = ["uv_build>=0.9.5,<0.10.0"]
49
+ build-backend = "uv_build"
50
+
51
+ [tool.uv.build-backend]
52
+ source-include = ["HISTORY.rst"]
53
+
54
+ [dependency-groups]
55
+ dev = [
56
+ "inline-snapshot>=0.32.0",
57
+ "pyrefly>=0.53.0",
58
+ "pytest-asyncio>=1.0.0",
59
+ "ruff>=0.15.1",
60
+ ]
61
+
62
+ [tool.pytest.ini_options]
63
+ testpaths = [
64
+ "tests",
65
+ ]
66
+ asyncio_default_fixture_loop_scope = "function"
67
+
68
+ [tool.inline-snapshot]
69
+ format-command="ruff format --stdin-filename {filename}"
@@ -1,21 +1,24 @@
1
+ import importlib.metadata
1
2
  from collections import defaultdict
2
3
 
3
- __version__ = '3.3.1'
4
+ __version__ = importlib.metadata.version("mutmut")
4
5
 
5
6
 
6
- duration_by_test = {}
7
+ duration_by_test = defaultdict(float)
7
8
  stats_time = None
8
9
  config = None
9
10
 
10
11
  _stats = set()
11
12
  tests_by_mangled_function_name = defaultdict(set)
12
-
13
+ _covered_lines = None
13
14
 
14
15
  def _reset_globals():
15
16
  global duration_by_test, stats_time, config, _stats, tests_by_mangled_function_name
17
+ global _covered_lines
16
18
 
17
- duration_by_test = {}
19
+ duration_by_test.clear()
18
20
  stats_time = None
19
21
  config = None
20
22
  _stats = set()
21
23
  tests_by_mangled_function_name = defaultdict(set)
24
+ _covered_lines = None