Open eranheres opened 9 months ago
1bb67cfe98
)Here are the sandbox execution logs prior to making any changes:
edd9fa1
trunk init
1/5 ✓⡿ Downloading Trunk 1.17.2... ⡿ Downloading Trunk 1.17.2... ⢿ Downloading Trunk 1.17.2... ⣻ Downloading Trunk 1.17.2... ⣽ Downloading Trunk 1.17.2... ⣾ Downloading Trunk 1.17.2... ⣷ Downloading Trunk 1.17.2... ✔ Downloading Trunk 1.17.2... done ⡿ Verifying Trunk sha256... ✔ Verifying Trunk sha256... done ⡿ Unpacking Trunk... ✔ Unpacking Trunk... done ✔ 15 linters were enabled (.trunk/trunk.yaml) actionlint 1.6.26 (1 github-workflow file) bandit 1.7.5 (9 python files) black 23.9.1 (7 python files) checkov 3.1.9 (4 yaml files) git-diff-check (32 files) isort 5.12.0 (9 python files) (created .isort.cfg) markdownlint 0.37.0 (4 markdown files) (created .markdownlint.yaml) osv-scanner 1.4.3 (1 lockfile file) oxipng 9.0.0 (3 png files) prettier 3.1.0 (4 markdown, 4 yaml files) ruff 0.1.6 (9 python files) (created ruff.toml) svgo 3.0.4 (3 svg files) (created svgo.config.js) trivy 0.47.0 (4 yaml files) trufflehog 3.63.2-rc0 (32 files) yamllint 1.33.0 (4 yaml files) (created .yamllint.yaml) Next Steps 1. Read documentation Our documentation can be found at https://docs.trunk.io 2. Get help and give feedback Join the Trunk community at https://slack.trunk.io
pip install -r requirements.txt
2/5 ✓Collecting iniconfig==2.0.0 Downloading iniconfig-2.0.0-py3-none-any.whl (5.9 kB) Requirement already satisfied: packaging==23.2 in /usr/local/lib/python3.10/dist-packages (from -r requirements.txt (line 2)) (23.2) Collecting pluggy==1.3.0 Downloading pluggy-1.3.0-py3-none-any.whl (18 kB) Collecting polyglot==16.7.4 Downloading polyglot-16.7.4.tar.gz (126 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 126.3/126.3 KB 2.2 MB/s eta 0:00:00 Preparing metadata (setup.py): started Preparing metadata (setup.py): finished with status 'done' Collecting pytest==7.4.3 Downloading pytest-7.4.3-py3-none-any.whl (325 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 325.1/325.1 KB 5.4 MB/s eta 0:00:00 Collecting exceptiongroup>=1.0.0rc8 Downloading exceptiongroup-1.2.0-py3-none-any.whl (16 kB) Requirement already satisfied: tomli>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from pytest==7.4.3->-r requirements.txt (line 5)) (2.0.1) Building wheels for collected packages: polyglot Building wheel for polyglot (setup.py): started Building wheel for polyglot (setup.py): finished with status 'done' Created wheel for polyglot: filename=polyglot-16.7.4-py2.py3-none-any.whl size=52577 sha256=1482cbb04f597aca535db4186a58191bd31bf3657aef04467b46f4beb5b5d3de Stored in directory: /root/.cache/pip/wheels/aa/92/4a/b172589446ba537db3bdb9a1f2204f27fe71217981c14ac368 Successfully built polyglot Installing collected packages: polyglot, pluggy, iniconfig, exceptiongroup, pytest Successfully installed exceptiongroup-1.2.0 iniconfig-2.0.0 pluggy-1.3.0 polyglot-16.7.4 pytest-7.4.3 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
trunk fmt sweep.yaml || return 0
3/5 ✓✔ Formatted sweep.yaml Re-checking autofixed files... Checked 1 file ✔ No issues
trunk check --fix --print-failures sweep.yaml
4/5 ✓ISSUES sweep.yaml:6:5 6:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 7:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 8:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 9:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 10:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 11:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 12:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 13:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 14:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 15:5 high string value is redundantly quoted with any quotes yamllint/quoted-strings 18:9 high string value is redundantly quoted with any quotes yamllint/quoted-strings Checked 1 file 11 existing issues Run trunk upgrade to upgrade 1 linter
pytest
5/5 ✓============================= test session starts ============================== platform linux -- Python 3.10.12, pytest-7.4.3, pluggy-1.3.0 rootdir: /repo collected 16 items tests/test_session.py ..... [ 31%] tests/test_typing_practice.py ...... [ 68%] tests/test_user.py ..... [100%] ============================== 16 passed in 1.12s ==============================
Sandbox passed on the latest main
, so sandbox checks will be enabled for this issue.
I found the following snippets in your repository. I will now analyze these snippets and come up with a plan.
tests/test_main.py
✓ https://github.com/eranheres/touch_typing_practice/commit/b760cea00901998138b20b908ef41795c70d117e
Test tests/test_main.py with contents:
• Unit tests for the main.py file, to be written in tests/test_main.py.
• The main() function should be tested with different inputs and scenarios. Since it interacts with the user and other classes, we should use mocking to simulate these interactions.
• Test 1: Test when the user enters a valid username. Mock the User.load() function to return a User object and check if the main() function correctly creates a TypingPractice object with this user.
• Test 2: Test when the user chooses to start a new session. Mock the stdscr.getstr() function to return the choice '1' and a sample text. Check if the main() function correctly calls the start_session() and end_session() functions of the TypingPractice object.
• Test 3: Test when the user chooses to view statistics. Mock the stdscr.getstr() function to return the choice '2'. Check if the main() function correctly calls the get_user_statistics() function of the TypingPractice object and prints the statistics.
• Test 4: Test when the user chooses to exit. Mock the stdscr.getstr() function to return the choice '3'. Check if the main() function breaks the loop and exits.
• Test 5: Test when the user enters an invalid choice. Mock the stdscr.getstr() function to return an invalid choice. Check if the main() function prints an error message and continues the loop.
Test coverage generation failed with error:
======================================================================
ERROR: test_main_invalid_choice (__main__.TestMainFunction)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.10/unittest/mock.py", line 1556, in __enter__
setattr(self.target, self.attribute, new_attr)
TypeError: cannot set 'getstr' attribute of immutable type '_curses.window'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.10/unittest/mock.py", line 1376, in patched
with self.decoration_helper(patched,
File "/usr/lib/python3.10/contextlib.py", line 135, in __enter__
return next(self.gen)
File "/usr/lib/python3.10/unittest/mock.py", line 1358, in decoration_helper
arg = exit_stack.enter_context(patching)
File "/usr/lib/python3.10/contextlib.py", line 492, in enter_context
result = _cm_type.__enter__(cm)
File "/usr/lib/python3.10/unittest/mock.py", line 1569, in __enter__
if not self.__exit__(*sys.exc_info()):
File "/usr/lib/python3.10/unittest/mock.py", line 1575, in __exit__
setattr(self.target, self.attribute, self.temp_original)
TypeError: cannot set 'getstr' attribute of immutable type '_curses.window'
----------------------------------------------------------------------
Ran 2 tests in 0.007s
FAILED (errors=1, skipped=1)
tests/test_main.py
. ✗
Sandbox logs for
trunk fmt tests/test_main.py || return 0
1/3 ✓✔ Formatted tests/test_main.py Re-checking autofixed files... Checked 1 file ✔ No issues Run trunk upgrade to upgrade 1 linter
trunk check --fix --print-failures tests/test_main.py
2/3 ✓Checked 1 file ✔ No issues
pytest
3/3 ❌ (`1`)============================= test session starts ============================== platform linux -- Python 3.10.12, pytest-7.4.3, pluggy-1.3.0 rootdir: /repo collected 18 items tests/test_main.py Fs [ 11%] tests/test_session.py ..... [ 38%] tests/test_typing_practice.py ...... [ 72%] tests/test_user.py ..... [100%] =================================== FAILURES =================================== __________________ TestMainFunction.test_main_invalid_choice ___________________ self =def __enter__(self): """Perform the patch.""" new, spec, spec_set = self.new, self.spec, self.spec_set autospec, kwargs = self.autospec, self.kwargs new_callable = self.new_callable self.target = self.getter() # normalise False to None if spec is False: spec = None if spec_set is False: spec_set = None if autospec is False: autospec = None if spec is not None and autospec is not None: raise TypeError("Can't specify spec and autospec") if ((spec is not None or autospec is not None) and spec_set not in (True, None)): raise TypeError("Can't provide explicit spec_set *and* spec or autospec") original, local = self.get_original() if new is DEFAULT and autospec is None: inherit = False if spec is True: # set spec to the object we are replacing spec = original if spec_set is True: spec_set = original spec = None elif spec is not None: if spec_set is True: spec_set = spec spec = None elif spec_set is True: spec_set = original if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, type): # If we're patching out a class and there is a spec inherit = True if spec is None and _is_async_obj(original): Klass = AsyncMock else: Klass = MagicMock _kwargs = {} if new_callable is not None: Klass = new_callable elif spec is not None or spec_set is not None: this_spec = spec if spec_set is not None: this_spec = spec_set if _is_list(this_spec): not_callable = '__call__' not in this_spec else: not_callable = not callable(this_spec) if _is_async_obj(this_spec): Klass = AsyncMock elif not_callable: Klass = NonCallableMagicMock if spec is not None: _kwargs['spec'] = spec if spec_set is not None: _kwargs['spec_set'] = spec_set # add a name to mocks if (isinstance(Klass, type) and issubclass(Klass, NonCallableMock) and self.attribute): _kwargs['name'] = self.attribute _kwargs.update(kwargs) new = Klass(**_kwargs) if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list this_spec = spec if spec_set is not None: this_spec = spec_set if (not _is_list(this_spec) and not _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? if new is not DEFAULT: raise TypeError( "autospec creates the mock for you. Can't specify " "autospec and new." ) if original is DEFAULT: raise TypeError("Can't use 'autospec' with create=True") spec_set = bool(spec_set) if autospec is True: autospec = original if _is_instance_mock(self.target): raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} as the patch ' f'target has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') if _is_instance_mock(autospec): target_name = getattr(self.target, '__name__', self.target) raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} from target ' f'{target_name!r} as it has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') new = create_autospec(autospec, spec_set=spec_set, _name=self.attribute, **kwargs) elif kwargs: # can't set keyword args when we aren't creating the mock # XXXX If new is a Mock we could call new.configure_mock(**kwargs) raise TypeError("Can't pass kwargs to a mock we aren't creating") new_attr = new self.temp_original = original self.is_local = local self._exit_stack = contextlib.ExitStack() try: > setattr(self.target, self.attribute, new_attr) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1556: TypeError During handling of the above exception, another exception occurred: /usr/lib/python3.10/unittest/mock.py:1376: in patched with self.decoration_helper(patched, /usr/lib/python3.10/contextlib.py:135: in __enter__ return next(self.gen) /usr/lib/python3.10/unittest/mock.py:1358: in decoration_helper arg = exit_stack.enter_context(patching) /usr/lib/python3.10/contextlib.py:492: in enter_context result = _cm_type.__enter__(cm) /usr/lib/python3.10/unittest/mock.py:1569: in __enter__ if not self.__exit__(*sys.exc_info()): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = exc_info = ( , TypeError("cannot set 'getstr' attribute of immutable type '_curses.window'"), ) def __exit__(self, *exc_info): """Undo the patch.""" if self.is_local and self.temp_original is not DEFAULT: > setattr(self.target, self.attribute, self.temp_original) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1575: TypeError =========================== short test summary info ============================ FAILED tests/test_main.py::TestMainFunction::test_main_invalid_choice - TypeE... =================== 1 failed, 16 passed, 1 skipped in 1.69s ====================
tests/test_main.py
✓ https://github.com/eranheres/touch_typing_practice/commit/3a91c8e37977af5e8acc8f160e4d299e5717361a
Modify tests/test_main.py with contents: Instead of using the @patch decorator to mock the 'curses.window.getstr' method directly, use the @patch.object decorator to mock this method on an instance of the 'curses.window' class. This will avoid the TypeError that is currently being raised.
In the test_main_user_interaction and test_main_invalid_choice tests, replace the @patch("curses.window.getstr") decorator with @patch.object(curses.window, "getstr"). This will mock the 'getstr' method on an instance of the 'curses.window' class, rather than trying to replace the method on the class itself.
Also, update the side_effect attribute of the mock_getstr object to return strings instead of bytes, as the 'getstr' method returns strings, not bytes. This will ensure that the mock object behaves in the same way as the method it is replacing.
tests/test_main.py
. ✗
Sandbox logs for
trunk fmt tests/test_main.py || return 0
1/2 ✓✔ Formatted tests/test_main.py Re-checking autofixed files... Checked 1 file ✔ No issues Run trunk upgrade to upgrade 1 linter
trunk check --fix --print-failures tests/test_main.py
2/2 ❌ (`1`)ISSUES tests/test_main.py:11:19 11:19 high Undefined name `curses` ruff/F821 Checked 1 file ✖ 1 new issue
[X] Modify tests/test_main.py
✓ https://github.com/eranheres/touch_typing_practice/commit/e4a16f3f77eb2f4ec333681c3255649b0ed4e7b4
Modify tests/test_main.py with contents: Add an import statement for the 'curses' module at the top of the file. This will allow the 'curses' module to be referenced in the patch.object() decorator.
[X] Ran sandbox for tests/test_main.py
. ✗
Sandbox logs for
trunk fmt tests/test_main.py || return 0
1/3 ✓✔ Formatted tests/test_main.py Re-checking autofixed files... ✔ Formatted tests/test_main.py Re-checking autofixed files... Checked 1 file ✔ No issues Run trunk upgrade to upgrade 1 linter
trunk check --fix --print-failures tests/test_main.py
2/3 ✓Checked 1 file ✔ No issues
pytest
3/3 ❌ (`1`)============================= test session starts ============================== platform linux -- Python 3.10.12, pytest-7.4.3, pluggy-1.3.0 rootdir: /repo collected 18 items tests/test_main.py FF [ 11%] tests/test_session.py ..... [ 38%] tests/test_typing_practice.py ...... [ 72%] tests/test_user.py ..... [100%] =================================== FAILURES =================================== __________________ TestMainFunction.test_main_invalid_choice ___________________ self =def __enter__(self): """Perform the patch.""" new, spec, spec_set = self.new, self.spec, self.spec_set autospec, kwargs = self.autospec, self.kwargs new_callable = self.new_callable self.target = self.getter() # normalise False to None if spec is False: spec = None if spec_set is False: spec_set = None if autospec is False: autospec = None if spec is not None and autospec is not None: raise TypeError("Can't specify spec and autospec") if ((spec is not None or autospec is not None) and spec_set not in (True, None)): raise TypeError("Can't provide explicit spec_set *and* spec or autospec") original, local = self.get_original() if new is DEFAULT and autospec is None: inherit = False if spec is True: # set spec to the object we are replacing spec = original if spec_set is True: spec_set = original spec = None elif spec is not None: if spec_set is True: spec_set = spec spec = None elif spec_set is True: spec_set = original if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, type): # If we're patching out a class and there is a spec inherit = True if spec is None and _is_async_obj(original): Klass = AsyncMock else: Klass = MagicMock _kwargs = {} if new_callable is not None: Klass = new_callable elif spec is not None or spec_set is not None: this_spec = spec if spec_set is not None: this_spec = spec_set if _is_list(this_spec): not_callable = '__call__' not in this_spec else: not_callable = not callable(this_spec) if _is_async_obj(this_spec): Klass = AsyncMock elif not_callable: Klass = NonCallableMagicMock if spec is not None: _kwargs['spec'] = spec if spec_set is not None: _kwargs['spec_set'] = spec_set # add a name to mocks if (isinstance(Klass, type) and issubclass(Klass, NonCallableMock) and self.attribute): _kwargs['name'] = self.attribute _kwargs.update(kwargs) new = Klass(**_kwargs) if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list this_spec = spec if spec_set is not None: this_spec = spec_set if (not _is_list(this_spec) and not _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? if new is not DEFAULT: raise TypeError( "autospec creates the mock for you. Can't specify " "autospec and new." ) if original is DEFAULT: raise TypeError("Can't use 'autospec' with create=True") spec_set = bool(spec_set) if autospec is True: autospec = original if _is_instance_mock(self.target): raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} as the patch ' f'target has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') if _is_instance_mock(autospec): target_name = getattr(self.target, '__name__', self.target) raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} from target ' f'{target_name!r} as it has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') new = create_autospec(autospec, spec_set=spec_set, _name=self.attribute, **kwargs) elif kwargs: # can't set keyword args when we aren't creating the mock # XXXX If new is a Mock we could call new.configure_mock(**kwargs) raise TypeError("Can't pass kwargs to a mock we aren't creating") new_attr = new self.temp_original = original self.is_local = local self._exit_stack = contextlib.ExitStack() try: > setattr(self.target, self.attribute, new_attr) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1556: TypeError During handling of the above exception, another exception occurred: /usr/lib/python3.10/unittest/mock.py:1376: in patched with self.decoration_helper(patched, /usr/lib/python3.10/contextlib.py:135: in __enter__ return next(self.gen) /usr/lib/python3.10/unittest/mock.py:1358: in decoration_helper arg = exit_stack.enter_context(patching) /usr/lib/python3.10/contextlib.py:492: in enter_context result = _cm_type.__enter__(cm) /usr/lib/python3.10/unittest/mock.py:1569: in __enter__ if not self.__exit__(*sys.exc_info()): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = exc_info = ( , TypeError("cannot set 'getstr' attribute of immutable type '_curses.window'"), ) def __exit__(self, *exc_info): """Undo the patch.""" if self.is_local and self.temp_original is not DEFAULT: > setattr(self.target, self.attribute, self.temp_original) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1575: TypeError _________________ TestMainFunction.test_main_user_interaction __________________ self = def __enter__(self): """Perform the patch.""" new, spec, spec_set = self.new, self.spec, self.spec_set autospec, kwargs = self.autospec, self.kwargs new_callable = self.new_callable self.target = self.getter() # normalise False to None if spec is False: spec = None if spec_set is False: spec_set = None if autospec is False: autospec = None if spec is not None and autospec is not None: raise TypeError("Can't specify spec and autospec") if ((spec is not None or autospec is not None) and spec_set not in (True, None)): raise TypeError("Can't provide explicit spec_set *and* spec or autospec") original, local = self.get_original() if new is DEFAULT and autospec is None: inherit = False if spec is True: # set spec to the object we are replacing spec = original if spec_set is True: spec_set = original spec = None elif spec is not None: if spec_set is True: spec_set = spec spec = None elif spec_set is True: spec_set = original if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, type): # If we're patching out a class and there is a spec inherit = True if spec is None and _is_async_obj(original): Klass = AsyncMock else: Klass = MagicMock _kwargs = {} if new_callable is not None: Klass = new_callable elif spec is not None or spec_set is not None: this_spec = spec if spec_set is not None: this_spec = spec_set if _is_list(this_spec): not_callable = '__call__' not in this_spec else: not_callable = not callable(this_spec) if _is_async_obj(this_spec): Klass = AsyncMock elif not_callable: Klass = NonCallableMagicMock if spec is not None: _kwargs['spec'] = spec if spec_set is not None: _kwargs['spec_set'] = spec_set # add a name to mocks if (isinstance(Klass, type) and issubclass(Klass, NonCallableMock) and self.attribute): _kwargs['name'] = self.attribute _kwargs.update(kwargs) new = Klass(**_kwargs) if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list this_spec = spec if spec_set is not None: this_spec = spec_set if (not _is_list(this_spec) and not _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? if new is not DEFAULT: raise TypeError( "autospec creates the mock for you. Can't specify " "autospec and new." ) if original is DEFAULT: raise TypeError("Can't use 'autospec' with create=True") spec_set = bool(spec_set) if autospec is True: autospec = original if _is_instance_mock(self.target): raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} as the patch ' f'target has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') if _is_instance_mock(autospec): target_name = getattr(self.target, '__name__', self.target) raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} from target ' f'{target_name!r} as it has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') new = create_autospec(autospec, spec_set=spec_set, _name=self.attribute, **kwargs) elif kwargs: # can't set keyword args when we aren't creating the mock # XXXX If new is a Mock we could call new.configure_mock(**kwargs) raise TypeError("Can't pass kwargs to a mock we aren't creating") new_attr = new self.temp_original = original self.is_local = local self._exit_stack = contextlib.ExitStack() try: > setattr(self.target, self.attribute, new_attr) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1556: TypeError During handling of the above exception, another exception occurred: /usr/lib/python3.10/unittest/mock.py:1376: in patched with self.decoration_helper(patched, /usr/lib/python3.10/contextlib.py:135: in __enter__ return next(self.gen) /usr/lib/python3.10/unittest/mock.py:1358: in decoration_helper arg = exit_stack.enter_context(patching) /usr/lib/python3.10/contextlib.py:492: in enter_context result = _cm_type.__enter__(cm) /usr/lib/python3.10/unittest/mock.py:1569: in __enter__ if not self.__exit__(*sys.exc_info()): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = exc_info = ( , TypeError("cannot set 'getstr' attribute of immutable type '_curses.window'"), ) def __exit__(self, *exc_info): """Undo the patch.""" if self.is_local and self.temp_original is not DEFAULT: > setattr(self.target, self.attribute, self.temp_original) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1575: TypeError =========================== short test summary info ============================ FAILED tests/test_main.py::TestMainFunction::test_main_invalid_choice - TypeE... FAILED tests/test_main.py::TestMainFunction::test_main_user_interaction - Typ... ========================= 2 failed, 16 passed in 1.87s =========================
tests/test_main.py
⋯
Modify tests/test_main.py with contents: Instead of trying to directly replace the 'getstr' method of the '_curses.window' object, we should mock the 'curses.wrapper' function. This function is the one that calls the 'main' function with the '_curses.window' object as an argument. By mocking 'curses.wrapper', we can control the '_curses.window' object that is passed to the 'main' function and replace its 'getstr' method with a mock object.
To achieve this, we need to replace the '@patch.object(curses.window, "getstr")' decorators with '@patch("curses.wrapper")' and adjust the test methods accordingly. The mock object for 'curses.wrapper' should be set up to call the 'main' function with a mock '_curses.window' object, whose 'getstr' method returns the desired test inputs.
In the 'test_main_user_interaction' method, the 'mock_getstr' mock object should be replaced with a 'mock_wrapper' mock object. The 'mock_wrapper' mock object should be set up to call the 'main' function with a mock '_curses.window' object, whose 'getstr' method returns the test inputs currently returned by 'mock_getstr'.
Similarly, in the 'test_main_invalid_choice' method, the 'mock_getstr' mock object should be replaced with a 'mock_wrapper' mock object. The 'mock_wrapper' mock object should be set up to call the 'main' function with a mock '_curses.window' object, whose 'getstr' method returns the test inputs currently returned by 'mock_getstr'.
[ ] Ran sandbox for tests/test_main.py
. ▶
Run `tests/test_main.py` through the sandbox.
[ ] Ran sandbox for tests/test_main.py
. ▶
Sandbox logs for
trunk fmt tests/test_main.py || return 0
1/3 ✓✔ Formatted tests/test_main.py Re-checking autofixed files... ✔ Formatted tests/test_main.py Re-checking autofixed files... Checked 1 file ✔ No issues Run trunk upgrade to upgrade 1 linter
trunk check --fix --print-failures tests/test_main.py
2/3 ✓Checked 1 file ✔ No issues
pytest
3/3 ❌ (`1`)============================= test session starts ============================== platform linux -- Python 3.10.12, pytest-7.4.3, pluggy-1.3.0 rootdir: /repo collected 18 items tests/test_main.py FF [ 11%] tests/test_session.py ..... [ 38%] tests/test_typing_practice.py ...... [ 72%] tests/test_user.py ..... [100%] =================================== FAILURES =================================== __________________ TestMainFunction.test_main_invalid_choice ___________________ self =def __enter__(self): """Perform the patch.""" new, spec, spec_set = self.new, self.spec, self.spec_set autospec, kwargs = self.autospec, self.kwargs new_callable = self.new_callable self.target = self.getter() # normalise False to None if spec is False: spec = None if spec_set is False: spec_set = None if autospec is False: autospec = None if spec is not None and autospec is not None: raise TypeError("Can't specify spec and autospec") if ((spec is not None or autospec is not None) and spec_set not in (True, None)): raise TypeError("Can't provide explicit spec_set *and* spec or autospec") original, local = self.get_original() if new is DEFAULT and autospec is None: inherit = False if spec is True: # set spec to the object we are replacing spec = original if spec_set is True: spec_set = original spec = None elif spec is not None: if spec_set is True: spec_set = spec spec = None elif spec_set is True: spec_set = original if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, type): # If we're patching out a class and there is a spec inherit = True if spec is None and _is_async_obj(original): Klass = AsyncMock else: Klass = MagicMock _kwargs = {} if new_callable is not None: Klass = new_callable elif spec is not None or spec_set is not None: this_spec = spec if spec_set is not None: this_spec = spec_set if _is_list(this_spec): not_callable = '__call__' not in this_spec else: not_callable = not callable(this_spec) if _is_async_obj(this_spec): Klass = AsyncMock elif not_callable: Klass = NonCallableMagicMock if spec is not None: _kwargs['spec'] = spec if spec_set is not None: _kwargs['spec_set'] = spec_set # add a name to mocks if (isinstance(Klass, type) and issubclass(Klass, NonCallableMock) and self.attribute): _kwargs['name'] = self.attribute _kwargs.update(kwargs) new = Klass(**_kwargs) if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list this_spec = spec if spec_set is not None: this_spec = spec_set if (not _is_list(this_spec) and not _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? if new is not DEFAULT: raise TypeError( "autospec creates the mock for you. Can't specify " "autospec and new." ) if original is DEFAULT: raise TypeError("Can't use 'autospec' with create=True") spec_set = bool(spec_set) if autospec is True: autospec = original if _is_instance_mock(self.target): raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} as the patch ' f'target has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') if _is_instance_mock(autospec): target_name = getattr(self.target, '__name__', self.target) raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} from target ' f'{target_name!r} as it has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') new = create_autospec(autospec, spec_set=spec_set, _name=self.attribute, **kwargs) elif kwargs: # can't set keyword args when we aren't creating the mock # XXXX If new is a Mock we could call new.configure_mock(**kwargs) raise TypeError("Can't pass kwargs to a mock we aren't creating") new_attr = new self.temp_original = original self.is_local = local self._exit_stack = contextlib.ExitStack() try: > setattr(self.target, self.attribute, new_attr) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1556: TypeError During handling of the above exception, another exception occurred: /usr/lib/python3.10/unittest/mock.py:1376: in patched with self.decoration_helper(patched, /usr/lib/python3.10/contextlib.py:135: in __enter__ return next(self.gen) /usr/lib/python3.10/unittest/mock.py:1358: in decoration_helper arg = exit_stack.enter_context(patching) /usr/lib/python3.10/contextlib.py:492: in enter_context result = _cm_type.__enter__(cm) /usr/lib/python3.10/unittest/mock.py:1569: in __enter__ if not self.__exit__(*sys.exc_info()): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = exc_info = ( , TypeError("cannot set 'getstr' attribute of immutable type '_curses.window'"), ) def __exit__(self, *exc_info): """Undo the patch.""" if self.is_local and self.temp_original is not DEFAULT: > setattr(self.target, self.attribute, self.temp_original) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1575: TypeError _________________ TestMainFunction.test_main_user_interaction __________________ self = def __enter__(self): """Perform the patch.""" new, spec, spec_set = self.new, self.spec, self.spec_set autospec, kwargs = self.autospec, self.kwargs new_callable = self.new_callable self.target = self.getter() # normalise False to None if spec is False: spec = None if spec_set is False: spec_set = None if autospec is False: autospec = None if spec is not None and autospec is not None: raise TypeError("Can't specify spec and autospec") if ((spec is not None or autospec is not None) and spec_set not in (True, None)): raise TypeError("Can't provide explicit spec_set *and* spec or autospec") original, local = self.get_original() if new is DEFAULT and autospec is None: inherit = False if spec is True: # set spec to the object we are replacing spec = original if spec_set is True: spec_set = original spec = None elif spec is not None: if spec_set is True: spec_set = spec spec = None elif spec_set is True: spec_set = original if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, type): # If we're patching out a class and there is a spec inherit = True if spec is None and _is_async_obj(original): Klass = AsyncMock else: Klass = MagicMock _kwargs = {} if new_callable is not None: Klass = new_callable elif spec is not None or spec_set is not None: this_spec = spec if spec_set is not None: this_spec = spec_set if _is_list(this_spec): not_callable = '__call__' not in this_spec else: not_callable = not callable(this_spec) if _is_async_obj(this_spec): Klass = AsyncMock elif not_callable: Klass = NonCallableMagicMock if spec is not None: _kwargs['spec'] = spec if spec_set is not None: _kwargs['spec_set'] = spec_set # add a name to mocks if (isinstance(Klass, type) and issubclass(Klass, NonCallableMock) and self.attribute): _kwargs['name'] = self.attribute _kwargs.update(kwargs) new = Klass(**_kwargs) if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list this_spec = spec if spec_set is not None: this_spec = spec_set if (not _is_list(this_spec) and not _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? if new is not DEFAULT: raise TypeError( "autospec creates the mock for you. Can't specify " "autospec and new." ) if original is DEFAULT: raise TypeError("Can't use 'autospec' with create=True") spec_set = bool(spec_set) if autospec is True: autospec = original if _is_instance_mock(self.target): raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} as the patch ' f'target has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') if _is_instance_mock(autospec): target_name = getattr(self.target, '__name__', self.target) raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} from target ' f'{target_name!r} as it has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') new = create_autospec(autospec, spec_set=spec_set, _name=self.attribute, **kwargs) elif kwargs: # can't set keyword args when we aren't creating the mock # XXXX If new is a Mock we could call new.configure_mock(**kwargs) raise TypeError("Can't pass kwargs to a mock we aren't creating") new_attr = new self.temp_original = original self.is_local = local self._exit_stack = contextlib.ExitStack() try: > setattr(self.target, self.attribute, new_attr) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1556: TypeError During handling of the above exception, another exception occurred: /usr/lib/python3.10/unittest/mock.py:1376: in patched with self.decoration_helper(patched, /usr/lib/python3.10/contextlib.py:135: in __enter__ return next(self.gen) /usr/lib/python3.10/unittest/mock.py:1358: in decoration_helper arg = exit_stack.enter_context(patching) /usr/lib/python3.10/contextlib.py:492: in enter_context result = _cm_type.__enter__(cm) /usr/lib/python3.10/unittest/mock.py:1569: in __enter__ if not self.__exit__(*sys.exc_info()): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = exc_info = ( , TypeError("cannot set 'getstr' attribute of immutable type '_curses.window'"), ) def __exit__(self, *exc_info): """Undo the patch.""" if self.is_local and self.temp_original is not DEFAULT: > setattr(self.target, self.attribute, self.temp_original) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1575: TypeError =========================== short test summary info ============================ FAILED tests/test_main.py::TestMainFunction::test_main_invalid_choice - TypeE... FAILED tests/test_main.py::TestMainFunction::test_main_user_interaction - Typ... ========================= 2 failed, 16 passed in 1.87s =========================
tests/test_main.py
. ▶
Sandbox logs for
trunk fmt tests/test_main.py || return 0
1/2 ✓✔ Formatted tests/test_main.py Re-checking autofixed files... Checked 1 file ✔ No issues Run trunk upgrade to upgrade 1 linter
trunk check --fix --print-failures tests/test_main.py
2/2 ❌ (`1`)ISSUES tests/test_main.py:11:19 11:19 high Undefined name `curses` ruff/F821 Checked 1 file ✖ 1 new issue
tests/test_main.py
. ▶
Sandbox logs for
trunk fmt tests/test_main.py || return 0
1/3 ✓✔ Formatted tests/test_main.py Re-checking autofixed files... Checked 1 file ✔ No issues Run trunk upgrade to upgrade 1 linter
trunk check --fix --print-failures tests/test_main.py
2/3 ✓Checked 1 file ✔ No issues
pytest
3/3 ❌ (`1`)============================= test session starts ============================== platform linux -- Python 3.10.12, pytest-7.4.3, pluggy-1.3.0 rootdir: /repo collected 18 items tests/test_main.py Fs [ 11%] tests/test_session.py ..... [ 38%] tests/test_typing_practice.py ...... [ 72%] tests/test_user.py ..... [100%] =================================== FAILURES =================================== __________________ TestMainFunction.test_main_invalid_choice ___________________ self =def __enter__(self): """Perform the patch.""" new, spec, spec_set = self.new, self.spec, self.spec_set autospec, kwargs = self.autospec, self.kwargs new_callable = self.new_callable self.target = self.getter() # normalise False to None if spec is False: spec = None if spec_set is False: spec_set = None if autospec is False: autospec = None if spec is not None and autospec is not None: raise TypeError("Can't specify spec and autospec") if ((spec is not None or autospec is not None) and spec_set not in (True, None)): raise TypeError("Can't provide explicit spec_set *and* spec or autospec") original, local = self.get_original() if new is DEFAULT and autospec is None: inherit = False if spec is True: # set spec to the object we are replacing spec = original if spec_set is True: spec_set = original spec = None elif spec is not None: if spec_set is True: spec_set = spec spec = None elif spec_set is True: spec_set = original if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, type): # If we're patching out a class and there is a spec inherit = True if spec is None and _is_async_obj(original): Klass = AsyncMock else: Klass = MagicMock _kwargs = {} if new_callable is not None: Klass = new_callable elif spec is not None or spec_set is not None: this_spec = spec if spec_set is not None: this_spec = spec_set if _is_list(this_spec): not_callable = '__call__' not in this_spec else: not_callable = not callable(this_spec) if _is_async_obj(this_spec): Klass = AsyncMock elif not_callable: Klass = NonCallableMagicMock if spec is not None: _kwargs['spec'] = spec if spec_set is not None: _kwargs['spec_set'] = spec_set # add a name to mocks if (isinstance(Klass, type) and issubclass(Klass, NonCallableMock) and self.attribute): _kwargs['name'] = self.attribute _kwargs.update(kwargs) new = Klass(**_kwargs) if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list this_spec = spec if spec_set is not None: this_spec = spec_set if (not _is_list(this_spec) and not _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? if new is not DEFAULT: raise TypeError( "autospec creates the mock for you. Can't specify " "autospec and new." ) if original is DEFAULT: raise TypeError("Can't use 'autospec' with create=True") spec_set = bool(spec_set) if autospec is True: autospec = original if _is_instance_mock(self.target): raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} as the patch ' f'target has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') if _is_instance_mock(autospec): target_name = getattr(self.target, '__name__', self.target) raise InvalidSpecError( f'Cannot autospec attr {self.attribute!r} from target ' f'{target_name!r} as it has already been mocked out. ' f'[target={self.target!r}, attr={autospec!r}]') new = create_autospec(autospec, spec_set=spec_set, _name=self.attribute, **kwargs) elif kwargs: # can't set keyword args when we aren't creating the mock # XXXX If new is a Mock we could call new.configure_mock(**kwargs) raise TypeError("Can't pass kwargs to a mock we aren't creating") new_attr = new self.temp_original = original self.is_local = local self._exit_stack = contextlib.ExitStack() try: > setattr(self.target, self.attribute, new_attr) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1556: TypeError During handling of the above exception, another exception occurred: /usr/lib/python3.10/unittest/mock.py:1376: in patched with self.decoration_helper(patched, /usr/lib/python3.10/contextlib.py:135: in __enter__ return next(self.gen) /usr/lib/python3.10/unittest/mock.py:1358: in decoration_helper arg = exit_stack.enter_context(patching) /usr/lib/python3.10/contextlib.py:492: in enter_context result = _cm_type.__enter__(cm) /usr/lib/python3.10/unittest/mock.py:1569: in __enter__ if not self.__exit__(*sys.exc_info()): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = exc_info = ( , TypeError("cannot set 'getstr' attribute of immutable type '_curses.window'"), ) def __exit__(self, *exc_info): """Undo the patch.""" if self.is_local and self.temp_original is not DEFAULT: > setattr(self.target, self.attribute, self.temp_original) E TypeError: cannot set 'getstr' attribute of immutable type '_curses.window' /usr/lib/python3.10/unittest/mock.py:1575: TypeError =========================== short test summary info ============================ FAILED tests/test_main.py::TestMainFunction::test_main_invalid_choice - TypeE... =================== 1 failed, 16 passed, 1 skipped in 1.69s ====================
Working on it...
rope
library to refactor Python! Check out Large Language Models are Bad at Refactoring Code. To have Sweep refactor your code, try sweep: Refactor <your_file>.py
!💡 To recreate the pull request edit the issue title or description. To tweak the pull request, leave a comment on the pull request. Join Our Discord
Details
Use pytest as the unit testing library
Checklist
- [X] Test `tests/test_main.py` ✓ https://github.com/eranheres/touch_typing_practice/commit/b760cea00901998138b20b908ef41795c70d117e - [X] Ran sandbox for `tests/test_main.py`. ✗ - [X] Modify `tests/test_main.py` ✓ https://github.com/eranheres/touch_typing_practice/commit/3a91c8e37977af5e8acc8f160e4d299e5717361a - [X] Ran sandbox for `tests/test_main.py`. ✗ - [X] Modify `tests/test_main.py` ✓ https://github.com/eranheres/touch_typing_practice/commit/e4a16f3f77eb2f4ec333681c3255649b0ed4e7b4 - [X] Ran sandbox for `tests/test_main.py`. ✗ - [ ] Modify `tests/test_main.py` ⋯ - [ ] Ran sandbox for `tests/test_main.py`. ▶ - [ ] Ran sandbox for `tests/test_main.py`. ▶ - [ ] Ran sandbox for `tests/test_main.py`. ▶ ![Flowchart](https://raw.githubusercontent.com/eranheres/touch_typing_practice/sweep/assets/17e015f480529e6e5489d06dba8f163993075ea591ca5efca7167657f3f8568d_12_flowchart.svg)