Fail gracefully if config lacks the mandatory main section#1190
Fail gracefully if config lacks the mandatory main section#1190Hi-Angel wants to merge 1 commit intoGothenburgBitFactory:developfrom
Conversation
0b5f8e7 to
0457696
Compare
50ff230 to
b205677
Compare
|
Oh, I thought Btw, while at it — I haven't found a way to test |
80cf187 to
3b10984
Compare
|
@Lotram do you want to review this one? I would have thought this would be caught by the schema but that doesn't appear to be the case even in 2.0.0.
Have you seen the contributing docs? |
Thanks, I see, so the only way to do this is to create a venv. Gotcha. |
Sure. The problem is I tested the proper error message is returned inside @Hi-Angel We already have a function validating evertyhing ( IMO, we need to add two tests:
The quickest way to enforce both tests is to replace the faulty line by something like Another solution could be to pass |
Or you could use |
|
Thank you for review, FTR, I'll probably look at it on the weekend |
@Lotram thank you! I'm looking at it and I'm a bit confused — do you want me to move the logic inside
|
|
Yes, that's why I suggested two possible solutions:
to avoid the
|
|
IMO it's a bit more consistent with the current separation of concerns to take the first approach of iterating over the |
Ah, sorry, your suggestions were in context of tests, so I thought you were suggesting about how to implement tests which I did not yet look into.
In essence, this just bypasses setting How about being explicit about not setting the interactive like this:
|
|
@Hi-Angel I agree that it isn't ideal to set I don't think iterating over the actually existing flavors is all that hacky, and if I'm not mistaken we should also be able to remove the default value from schema.py: # added during configuration loading
#: Interactive status.
interactive: bool = False |
|
Alrighty, you folks know the code better, will do the for-cycle then 😊 |
|
So, I'm attempting to run tests on the current But this is running Details╰─λ pytest tests/config/test_load.py 2 ↵
============================================================================================================================= test session starts =============================================================================================================================
platform linux -- Python 3.14.3, pytest-8.4.2, pluggy-1.6.0
benchmark: 5.0.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/constantine/Projects/bugwarrior
configfile: pyproject.toml
plugins: anyio-4.12.1, asyncio-1.3.0, flaky-3.8.1, benchmark-5.0.1, typeguard-4.5.1
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 18 items
tests/config/test_load.py F................. [100%]
================================================================================================================================== FAILURES ===================================================================================================================================
__________________________________________________________________________________________________________________________ ExampleTest.test_example ___________________________________________________________________________________________________________________________
self = <tests.config.test_load.ExampleTest testMethod=test_example>
def test_example(self):
for rcfile in ('example-bugwarriorrc', 'example-bugwarrior.toml'):
with self.subTest(rcfile=rcfile):
os.environ['BUGWARRIORRC'] = str(self.basedir / rcfile)
> load.load_config('general', False, False)
tests/config/test_load.py:40:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
bugwarrior/config/load.py:124: in load_config
config = validate_config(rawconfig, main_section, configpath)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bugwarrior/config/validation.py:166: in validate_config
ServiceConfigType = get_service_config_union_type(raw_service_configs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bugwarrior/config/validation.py:130: in get_service_config_union_type
service_config_classes = tuple(
^^^^^
bugwarrior/config/validation.py:131: in <genexpr>
get_service(service["service"]).CONFIG_SCHEMA
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bugwarrior/collect.py:40: in get_service
return service.load()
^^^^^^^^^^^^^^
/usr/lib/python3.14/importlib/metadata/__init__.py:179: in load
module = import_module(match.group('module'))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1398: in _gcd_import
???
<frozen importlib._bootstrap>:1371: in _find_and_load
???
<frozen importlib._bootstrap>:1342: in _find_and_load_unlocked
???
<frozen importlib._bootstrap>:938: in _load_unlocked
???
<frozen importlib._bootstrap_external>:759: in exec_module
???
<frozen importlib._bootstrap>:491: in _call_with_frames_removed
???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
import csv
import io as StringIO
import logging
import typing
import urllib.parse
> import offtrac
E ModuleNotFoundError: No module named 'offtrac'
bugwarrior/services/trac.py:7: ModuleNotFoundError
============================================================================================================================== warnings summary ===============================================================================================================================
../../../../usr/lib/python3.14/site-packages/taskw/fields/commaseparateduuid.py:9
/usr/lib/python3.14/site-packages/taskw/fields/commaseparateduuid.py:9: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
version = LooseVersion('2.4')
../../../../usr/lib/python3.14/site-packages/taskw/warrior.py:573
/usr/lib/python3.14/site-packages/taskw/warrior.py:573: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
return LooseVersion(taskwarrior_version.decode())
../../../../usr/lib/python3.14/site-packages/taskw/warrior.py:556
/usr/lib/python3.14/site-packages/taskw/warrior.py:556: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
return cls.get_version() > LooseVersion('2')
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================================================================================================================== short test summary info ===========================================================================================================================
FAILED tests/config/test_load.py::ExampleTest::test_example - ModuleNotFoundError: No module named 'offtrac'
================================================================================================================== 1 failed, 17 passed, 3 warnings in 0.42s ===================================================================================================================and this is running plain Details╰─λ pytest
============================================================================================================================= test session starts =============================================================================================================================
platform linux -- Python 3.14.3, pytest-8.4.2, pluggy-1.6.0
benchmark: 5.0.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/constantine/Projects/bugwarrior
configfile: pyproject.toml
plugins: anyio-4.12.1, asyncio-1.3.0, flaky-3.8.1, benchmark-5.0.1, typeguard-4.5.1
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 240 items / 8 errors
=================================================================================================================================== ERRORS ====================================================================================================================================
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_bts.py ______________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_bts.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_bts.py:4: in <module>
from bugwarrior.services import bts
bugwarrior/services/bts.py:4: in <module>
import debianbts
E ModuleNotFoundError: No module named 'debianbts'
___________________________________________________________________________________________________________________ ERROR collecting tests/test_bugzilla.py ___________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_bugzilla.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_bugzilla.py:6: in <module>
from bugwarrior.services.bz import BugzillaService
bugwarrior/services/bz.py:9: in <module>
import bugzilla
E ModuleNotFoundError: No module named 'bugzilla'
____________________________________________________________________________________________________________________ ERROR collecting tests/test_gmail.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_gmail.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_gmail.py:8: in <module>
from google.oauth2.credentials import Credentials
E ModuleNotFoundError: No module named 'google.oauth2'
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_jira.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_jira.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_jira.py:8: in <module>
from bugwarrior.services.jira import JiraExtraFields, JiraService
bugwarrior/services/jira.py:7: in <module>
from jira.client import JIRA as BaseJIRA
E ModuleNotFoundError: No module named 'jira'
___________________________________________________________________________________________________________________ ERROR collecting tests/test_kanboard.py ___________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_kanboard.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_kanboard.py:5: in <module>
from bugwarrior.services.kanboard import KanboardService
bugwarrior/services/kanboard.py:7: in <module>
from kanboard import Client
E ModuleNotFoundError: No module named 'kanboard'
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_phab.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_phab.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_phab.py:4: in <module>
from bugwarrior.services.phab import PhabricatorService
bugwarrior/services/phab.py:4: in <module>
import phabricator
E ModuleNotFoundError: No module named 'phabricator'
___________________________________________________________________________________________________________________ ERROR collecting tests/test_todoist.py ____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_todoist.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_todoist.py:5: in <module>
from todoist_api_python.models import (
E ModuleNotFoundError: No module named 'todoist_api_python'
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_trac.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_trac.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_trac.py:2: in <module>
from bugwarrior.services.trac import TracService
bugwarrior/services/trac.py:7: in <module>
import offtrac
E ModuleNotFoundError: No module named 'offtrac'
============================================================================================================================== warnings summary ===============================================================================================================================
../../../../usr/lib/python3.14/site-packages/taskw/fields/commaseparateduuid.py:9
/usr/lib/python3.14/site-packages/taskw/fields/commaseparateduuid.py:9: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
version = LooseVersion('2.4')
../../../../usr/lib/python3.14/site-packages/taskw/warrior.py:573
/usr/lib/python3.14/site-packages/taskw/warrior.py:573: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
return LooseVersion(taskwarrior_version.decode())
../../../../usr/lib/python3.14/site-packages/taskw/warrior.py:556
/usr/lib/python3.14/site-packages/taskw/warrior.py:556: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
return cls.get_version() > LooseVersion('2')
tests/test_clickup.py:11
/home/constantine/Projects/bugwarrior/tests/test_clickup.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_clickup.py)
class TestData:
tests/test_deck.py:11
/home/constantine/Projects/bugwarrior/tests/test_deck.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_deck.py)
@dataclasses.dataclass
tests/test_gitbug.py:11
/home/constantine/Projects/bugwarrior/tests/test_gitbug.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_gitbug.py)
@dataclasses.dataclass
tests/test_gitlab.py:11
/home/constantine/Projects/bugwarrior/tests/test_gitlab.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_gitlab.py)
class TestData:
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================================================================================================================== short test summary info ===========================================================================================================================
ERROR tests/test_bts.py
ERROR tests/test_bugzilla.py
ERROR tests/test_gmail.py
ERROR tests/test_jira.py
ERROR tests/test_kanboard.py
ERROR tests/test_phab.py
ERROR tests/test_todoist.py
ERROR tests/test_trac.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 8 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
======================================================================================================================== 7 warnings, 8 errors in 1.62s ======================================================================================================================== |
|
You're looking at the "stable" docs. You need the "latest" docs for this purpose: https://bugwarrior.readthedocs.io/en/latest/contributing.html |
I see, so, compared to stable docs the only new thing to do is Now I did this too, but running |
|
The message clearly shows that the optional dependencies were not installed. Are you sure the |
|
@Lotram same here, I too am using zsh, and I also used the double quotes to bypass the error. Here's the output from both the command and the pytest combined: Details╰─λ pip install -e ".[all]"
Obtaining file:///home/constantine/Projects/bugwarrior
Installing build dependencies ... done
Checking if build backend supports build_editable ... done
Getting requirements to build editable ... done
Preparing editable metadata (pyproject.toml) ... done
Requirement already satisfied: click in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (8.3.1)
Requirement already satisfied: dogpile.cache>=0.5.3 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (1.5.0)
Requirement already satisfied: jinja2>=2.7.2 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (3.1.6)
Requirement already satisfied: lockfile>=0.9.1 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (0.12.2)
Requirement already satisfied: pydantic>=2 in ./.venv/lib/python3.14/site-packages (from pydantic[email]>=2->bugwarrior==2.1.0.post0) (2.12.5)
Requirement already satisfied: python-dateutil in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (2.9.0.post0)
Requirement already satisfied: requests in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (2.33.0)
Requirement already satisfied: setuptools in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (82.0.1)
Requirement already satisfied: taskw>=0.8 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (2.0.0)
Requirement already satisfied: decorator>=4.0.0 in ./.venv/lib/python3.14/site-packages (from dogpile.cache>=0.5.3->bugwarrior==2.1.0.post0) (5.2.1)
Requirement already satisfied: stevedore>=3.0.0 in ./.venv/lib/python3.14/site-packages (from dogpile.cache>=0.5.3->bugwarrior==2.1.0.post0) (5.7.0)
Requirement already satisfied: MarkupSafe>=2.0 in ./.venv/lib/python3.14/site-packages (from jinja2>=2.7.2->bugwarrior==2.1.0.post0) (3.0.3)
Requirement already satisfied: annotated-types>=0.6.0 in ./.venv/lib/python3.14/site-packages (from pydantic>=2->pydantic[email]>=2->bugwarrior==2.1.0.post0) (0.7.0)
Requirement already satisfied: pydantic-core==2.41.5 in ./.venv/lib/python3.14/site-packages (from pydantic>=2->pydantic[email]>=2->bugwarrior==2.1.0.post0) (2.41.5)
Requirement already satisfied: typing-extensions>=4.14.1 in ./.venv/lib/python3.14/site-packages (from pydantic>=2->pydantic[email]>=2->bugwarrior==2.1.0.post0) (4.15.0)
Requirement already satisfied: typing-inspection>=0.4.2 in ./.venv/lib/python3.14/site-packages (from pydantic>=2->pydantic[email]>=2->bugwarrior==2.1.0.post0) (0.4.2)
Requirement already satisfied: email-validator>=2.0.0 in ./.venv/lib/python3.14/site-packages (from pydantic[email]>=2->bugwarrior==2.1.0.post0) (2.3.0)
Requirement already satisfied: dnspython>=2.0.0 in ./.venv/lib/python3.14/site-packages (from email-validator>=2.0.0->pydantic[email]>=2->bugwarrior==2.1.0.post0) (2.8.0)
Requirement already satisfied: idna>=2.0.0 in ./.venv/lib/python3.14/site-packages (from email-validator>=2.0.0->pydantic[email]>=2->bugwarrior==2.1.0.post0) (3.11)
Requirement already satisfied: kitchen in ./.venv/lib/python3.14/site-packages (from taskw>=0.8->bugwarrior==2.1.0.post0) (1.2.6)
Requirement already satisfied: pytz in ./.venv/lib/python3.14/site-packages (from taskw>=0.8->bugwarrior==2.1.0.post0) (2026.1.post1)
Requirement already satisfied: python-debianbts>=4.1.1 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (4.1.1)
Requirement already satisfied: python-bugzilla>=2.0.0 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (3.3.0)
Requirement already satisfied: google-api-python-client in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (2.193.0)
Requirement already satisfied: google-auth-oauthlib in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (1.3.0)
Requirement already satisfied: ini2toml[full] in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (0.15)
Requirement already satisfied: jira>=3.10.0 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (3.10.5)
Requirement already satisfied: kanboard in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (1.1.8)
Requirement already satisfied: keyring in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (25.7.0)
Requirement already satisfied: phabricator in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (0.9.1)
Requirement already satisfied: todoist_api_python>=3.0.0 in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (4.0.0)
Requirement already satisfied: offtrac in ./.venv/lib/python3.14/site-packages (from bugwarrior==2.1.0.post0) (0.1.0)
Requirement already satisfied: defusedxml in ./.venv/lib/python3.14/site-packages (from jira>=3.10.0->bugwarrior==2.1.0.post0) (0.7.1)
Requirement already satisfied: packaging in ./.venv/lib/python3.14/site-packages (from jira>=3.10.0->bugwarrior==2.1.0.post0) (26.0)
Requirement already satisfied: requests-oauthlib>=1.1.0 in ./.venv/lib/python3.14/site-packages (from jira>=3.10.0->bugwarrior==2.1.0.post0) (2.0.0)
Requirement already satisfied: requests_toolbelt in ./.venv/lib/python3.14/site-packages (from jira>=3.10.0->bugwarrior==2.1.0.post0) (1.0.0)
Requirement already satisfied: charset_normalizer<4,>=2 in ./.venv/lib/python3.14/site-packages (from requests->bugwarrior==2.1.0.post0) (3.4.6)
Requirement already satisfied: urllib3<3,>=1.26 in ./.venv/lib/python3.14/site-packages (from requests->bugwarrior==2.1.0.post0) (2.6.3)
Requirement already satisfied: certifi>=2023.5.7 in ./.venv/lib/python3.14/site-packages (from requests->bugwarrior==2.1.0.post0) (2026.2.25)
Requirement already satisfied: oauthlib>=3.0.0 in ./.venv/lib/python3.14/site-packages (from requests-oauthlib>=1.1.0->jira>=3.10.0->bugwarrior==2.1.0.post0) (3.3.1)
Requirement already satisfied: dataclass-wizard<1.0,>=0.35.4 in ./.venv/lib/python3.14/site-packages (from todoist_api_python>=3.0.0->bugwarrior==2.1.0.post0) (0.39.1)
Requirement already satisfied: httpx<1,>=0.28.1 in ./.venv/lib/python3.14/site-packages (from todoist_api_python>=3.0.0->bugwarrior==2.1.0.post0) (0.28.1)
Requirement already satisfied: anyio in ./.venv/lib/python3.14/site-packages (from httpx<1,>=0.28.1->todoist_api_python>=3.0.0->bugwarrior==2.1.0.post0) (4.13.0)
Requirement already satisfied: httpcore==1.* in ./.venv/lib/python3.14/site-packages (from httpx<1,>=0.28.1->todoist_api_python>=3.0.0->bugwarrior==2.1.0.post0) (1.0.9)
Requirement already satisfied: h11>=0.16 in ./.venv/lib/python3.14/site-packages (from httpcore==1.*->httpx<1,>=0.28.1->todoist_api_python>=3.0.0->bugwarrior==2.1.0.post0) (0.16.0)
Requirement already satisfied: httplib2<1.0.0,>=0.19.0 in ./.venv/lib/python3.14/site-packages (from google-api-python-client->bugwarrior==2.1.0.post0) (0.31.2)
Requirement already satisfied: google-auth!=2.24.0,!=2.25.0,<3.0.0,>=1.32.0 in ./.venv/lib/python3.14/site-packages (from google-api-python-client->bugwarrior==2.1.0.post0) (2.49.1)
Requirement already satisfied: google-auth-httplib2<1.0.0,>=0.2.0 in ./.venv/lib/python3.14/site-packages (from google-api-python-client->bugwarrior==2.1.0.post0) (0.3.0)
Requirement already satisfied: google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0,>=1.31.5 in ./.venv/lib/python3.14/site-packages (from google-api-python-client->bugwarrior==2.1.0.post0) (2.30.0)
Requirement already satisfied: uritemplate<5,>=3.0.1 in ./.venv/lib/python3.14/site-packages (from google-api-python-client->bugwarrior==2.1.0.post0) (4.2.0)
Requirement already satisfied: googleapis-common-protos<2.0.0,>=1.56.3 in ./.venv/lib/python3.14/site-packages (from google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0,>=1.31.5->google-api-python-client->bugwarrior==2.1.0.post0) (1.73.1)
Requirement already satisfied: protobuf<7.0.0,>=4.25.8 in ./.venv/lib/python3.14/site-packages (from google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0,>=1.31.5->google-api-python-client->bugwarrior==2.1.0.post0) (6.33.6)
Requirement already satisfied: proto-plus<2.0.0,>=1.22.3 in ./.venv/lib/python3.14/site-packages (from google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0,>=1.31.5->google-api-python-client->bugwarrior==2.1.0.post0) (1.27.2)
Requirement already satisfied: pyasn1-modules>=0.2.1 in ./.venv/lib/python3.14/site-packages (from google-auth!=2.24.0,!=2.25.0,<3.0.0,>=1.32.0->google-api-python-client->bugwarrior==2.1.0.post0) (0.4.2)
Requirement already satisfied: cryptography>=38.0.3 in ./.venv/lib/python3.14/site-packages (from google-auth!=2.24.0,!=2.25.0,<3.0.0,>=1.32.0->google-api-python-client->bugwarrior==2.1.0.post0) (46.0.6)
Requirement already satisfied: pyparsing<4,>=3.1 in ./.venv/lib/python3.14/site-packages (from httplib2<1.0.0,>=0.19.0->google-api-python-client->bugwarrior==2.1.0.post0) (3.3.2)
Requirement already satisfied: cffi>=2.0.0 in ./.venv/lib/python3.14/site-packages (from cryptography>=38.0.3->google-auth!=2.24.0,!=2.25.0,<3.0.0,>=1.32.0->google-api-python-client->bugwarrior==2.1.0.post0) (2.0.0)
Requirement already satisfied: pycparser in ./.venv/lib/python3.14/site-packages (from cffi>=2.0.0->cryptography>=38.0.3->google-auth!=2.24.0,!=2.25.0,<3.0.0,>=1.32.0->google-api-python-client->bugwarrior==2.1.0.post0) (3.0)
Requirement already satisfied: pyasn1<0.7.0,>=0.6.1 in ./.venv/lib/python3.14/site-packages (from pyasn1-modules>=0.2.1->google-auth!=2.24.0,!=2.25.0,<3.0.0,>=1.32.0->google-api-python-client->bugwarrior==2.1.0.post0) (0.6.3)
Requirement already satisfied: configupdater<4,>=3.0.1 in ./.venv/lib/python3.14/site-packages (from ini2toml[full]; extra == "ini2toml"->bugwarrior==2.1.0.post0) (3.2)
Requirement already satisfied: tomlkit<2,>=0.10.0 in ./.venv/lib/python3.14/site-packages (from ini2toml[full]; extra == "ini2toml"->bugwarrior==2.1.0.post0) (0.14.0)
Requirement already satisfied: SecretStorage>=3.2 in ./.venv/lib/python3.14/site-packages (from keyring->bugwarrior==2.1.0.post0) (3.5.0)
Requirement already satisfied: jeepney>=0.4.2 in ./.venv/lib/python3.14/site-packages (from keyring->bugwarrior==2.1.0.post0) (0.9.0)
Requirement already satisfied: jaraco.classes in ./.venv/lib/python3.14/site-packages (from keyring->bugwarrior==2.1.0.post0) (3.4.0)
Requirement already satisfied: jaraco.functools in ./.venv/lib/python3.14/site-packages (from keyring->bugwarrior==2.1.0.post0) (4.4.0)
Requirement already satisfied: jaraco.context in ./.venv/lib/python3.14/site-packages (from keyring->bugwarrior==2.1.0.post0) (6.1.2)
Requirement already satisfied: more-itertools in ./.venv/lib/python3.14/site-packages (from jaraco.classes->keyring->bugwarrior==2.1.0.post0) (10.8.0)
Requirement already satisfied: six>=1.5 in ./.venv/lib/python3.14/site-packages (from python-dateutil->bugwarrior==2.1.0.post0) (1.17.0)
Building wheels for collected packages: bugwarrior
Building editable for bugwarrior (pyproject.toml) ... done
Created wheel for bugwarrior: filename=bugwarrior-2.1.0.post0-0.editable-py3-none-any.whl size=17714 sha256=e0101746a9755b924312906f7a011688248fa3d69ea6e458ae071a2aaa258cf0
Stored in directory: /tmp/pip-ephem-wheel-cache-mbhwc98b/wheels/10/c5/69/08f0487fd5e3938e8f18f7ce85fdb74ceae30b1c50dc394abb
Successfully built bugwarrior
Installing collected packages: bugwarrior
Attempting uninstall: bugwarrior
Found existing installation: bugwarrior 2.1.0.post0
Uninstalling bugwarrior-2.1.0.post0:
Successfully uninstalled bugwarrior-2.1.0.post0
Successfully installed bugwarrior-2.1.0.post0
[notice] A new release of pip is available: 25.3 -> 26.0.1
[notice] To update, run: pip install --upgrade pip
(.venv) [30.03.2026-00:07:55] constantine@dell-g15 ~/Projects/bugwarrior ‹node-› ‹› (715bec8)
╰─λ pytest
============================================================================================================================= test session starts =============================================================================================================================
platform linux -- Python 3.14.3, pytest-8.4.2, pluggy-1.6.0
benchmark: 5.0.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/constantine/Projects/bugwarrior
configfile: pyproject.toml
plugins: anyio-4.12.1, asyncio-1.3.0, flaky-3.8.1, benchmark-5.0.1, typeguard-4.5.1
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 240 items / 8 errors
=================================================================================================================================== ERRORS ====================================================================================================================================
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_bts.py ______________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_bts.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_bts.py:4: in <module>
from bugwarrior.services import bts
bugwarrior/services/bts.py:4: in <module>
import debianbts
E ModuleNotFoundError: No module named 'debianbts'
___________________________________________________________________________________________________________________ ERROR collecting tests/test_bugzilla.py ___________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_bugzilla.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_bugzilla.py:6: in <module>
from bugwarrior.services.bz import BugzillaService
bugwarrior/services/bz.py:9: in <module>
import bugzilla
E ModuleNotFoundError: No module named 'bugzilla'
____________________________________________________________________________________________________________________ ERROR collecting tests/test_gmail.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_gmail.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_gmail.py:8: in <module>
from google.oauth2.credentials import Credentials
E ModuleNotFoundError: No module named 'google.oauth2'
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_jira.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_jira.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_jira.py:8: in <module>
from bugwarrior.services.jira import JiraExtraFields, JiraService
bugwarrior/services/jira.py:7: in <module>
from jira.client import JIRA as BaseJIRA
E ModuleNotFoundError: No module named 'jira'
___________________________________________________________________________________________________________________ ERROR collecting tests/test_kanboard.py ___________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_kanboard.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_kanboard.py:5: in <module>
from bugwarrior.services.kanboard import KanboardService
bugwarrior/services/kanboard.py:7: in <module>
from kanboard import Client
E ModuleNotFoundError: No module named 'kanboard'
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_phab.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_phab.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_phab.py:4: in <module>
from bugwarrior.services.phab import PhabricatorService
bugwarrior/services/phab.py:4: in <module>
import phabricator
E ModuleNotFoundError: No module named 'phabricator'
___________________________________________________________________________________________________________________ ERROR collecting tests/test_todoist.py ____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_todoist.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_todoist.py:5: in <module>
from todoist_api_python.models import (
E ModuleNotFoundError: No module named 'todoist_api_python'
_____________________________________________________________________________________________________________________ ERROR collecting tests/test_trac.py _____________________________________________________________________________________________________________________
ImportError while importing test module '/home/constantine/Projects/bugwarrior/tests/test_trac.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.14/importlib/__init__.py:88: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_trac.py:2: in <module>
from bugwarrior.services.trac import TracService
bugwarrior/services/trac.py:7: in <module>
import offtrac
E ModuleNotFoundError: No module named 'offtrac'
============================================================================================================================== warnings summary ===============================================================================================================================
../../../../usr/lib/python3.14/site-packages/taskw/fields/commaseparateduuid.py:9
/usr/lib/python3.14/site-packages/taskw/fields/commaseparateduuid.py:9: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
version = LooseVersion('2.4')
../../../../usr/lib/python3.14/site-packages/taskw/warrior.py:573
/usr/lib/python3.14/site-packages/taskw/warrior.py:573: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
return LooseVersion(taskwarrior_version.decode())
../../../../usr/lib/python3.14/site-packages/taskw/warrior.py:556
/usr/lib/python3.14/site-packages/taskw/warrior.py:556: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
return cls.get_version() > LooseVersion('2')
tests/test_clickup.py:11
/home/constantine/Projects/bugwarrior/tests/test_clickup.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_clickup.py)
class TestData:
tests/test_deck.py:11
/home/constantine/Projects/bugwarrior/tests/test_deck.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_deck.py)
@dataclasses.dataclass
tests/test_gitbug.py:11
/home/constantine/Projects/bugwarrior/tests/test_gitbug.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_gitbug.py)
@dataclasses.dataclass
tests/test_gitlab.py:11
/home/constantine/Projects/bugwarrior/tests/test_gitlab.py:11: PytestCollectionWarning: cannot collect test class 'TestData' because it has a __init__ constructor (from: tests/test_gitlab.py)
class TestData:
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================================================================================================================== short test summary info ===========================================================================================================================
ERROR tests/test_bts.py
ERROR tests/test_bugzilla.py
ERROR tests/test_gmail.py
ERROR tests/test_jira.py
ERROR tests/test_kanboard.py
ERROR tests/test_phab.py
ERROR tests/test_todoist.py
ERROR tests/test_trac.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 8 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
======================================================================================================================== 7 warnings, 8 errors in 1.68s ======================================================================================================================== |
|
Your tests apparently use /usr/lib/python, not the one from your venv. Are you sure tou ran the activate command ? |
|
Oh, you were right! This is weird though — I did run this command, and I just pulled it out of my history to execute again, and it certainly was in the same terminal session. But now the tests are passing! Odd. Thank you! |
3a21a67 to
f640fbb
Compare
Currently, if a user didn't put `[general]` section in config file,
bugwarrior fails like this:
Traceback (most recent call last):
File "/usr/bin/bugwarrior", line 8, in <module>
sys.exit(cli())
~~~^^
File "/usr/lib/python3.14/site-packages/click/core.py", line 1485, in __call__
return self.main(*args, **kwargs)
~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/site-packages/click/core.py", line 1406, in main
rv = self.invoke(ctx)
File "/usr/lib/python3.14/site-packages/click/core.py", line 1873, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/site-packages/click/core.py", line 1269, in invoke
return ctx.invoke(self.callback, **ctx.params)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/site-packages/click/core.py", line 824, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3.14/site-packages/click/decorators.py", line 34, in new_func
return f(get_current_context(), *args, **kwargs)
File "/usr/lib/python3.14/site-packages/bugwarrior/command.py", line 62, in wrapped_subcommand_callback
return ctx.invoke(subcommand_callback, *args, **kwargs)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/site-packages/click/core.py", line 824, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3.14/site-packages/bugwarrior/command.py", line 105, in pull
config = _try_load_config(main_section, interactive, quiet)
File "/usr/lib/python3.14/site-packages/bugwarrior/command.py", line 35, in _try_load_config
return load_config(main_section, interactive, quiet)
File "/usr/lib/python3.14/site-packages/bugwarrior/config/load.py", line 122, in load_config
rawconfig['flavor'][main_section]['interactive'] = interactive
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
KeyError: 'general'
This is confusing — it looks more like bugwarrior broke due to some
API change in Python, rather than because of a user mistake.
So handle this case with explicit check. Now it will fail instead like
this:
Validation error found in /home/constantine/.config/bugwarrior/bugwarriorrc
See https://bugwarrior.readthedocs.io
No section: 'general'
f640fbb to
833e60b
Compare
Flavors are a subcategory of sections but refer more specifically to "main section" entries. "Flavor" is more specific and correct.
Seems like this is a bug in our test data and we should fix the test data rather than working around it.
I'm not exactly sure what was intended here either, but maybe we should try removing the default value in this PR? That would demonstrate that it is always set prior to validation. In schema.py: -
- # added during configuration loading
- #: Interactive status.
- interactive: bool = False
+ interactive: bool |
Looked at it quickly — I think it's actually a bug in parser. The tests with the issue are |
What I meant is: The naive solution to our Something simple, looking like: Removing the default value in |
Oh, I see the problem now! We're iterating over the for flavor in rawconfig['flavor'].values():
flavor['interactive'] = interactive |

Currently, if a user didn't put
[general]section in config file, bugwarrior fails like this:This is confusing — it looks more like bugwarrior broke due to some API change in Python, rather than because of a user mistake.
So handle this case with explicit check. Now it will fail instead like this: