Repository: qtile/qtile

Issue:
pyproject.toml deprecated syntax
### Issue description

Does this mean that the line in `pyproject.toml` is deprecated ? 

Please use a simple string containing a SPDX expression for `project.license`. You can also use `project.license-files`. (Both options available on setuptools>=77.0.0).

 so, in the `pyproject.toml` file under [project] there is a line : 
license = {text = "MIT"}
 if this is it. what should it look like ?


### Version

0.31.1.dev19+gf8040baf

### Backend

Wayland (experimental)

### Config

```python

```

### Logs

```text
pip install --config-setting backend=wayland .
Processing /home/cjoke/dev/qtile
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... error
  error: subprocess-exited-with-error
  
  × pip subprocess to install backend dependencies did not run successfully.
  │ exit code: 1
  ╰─> [184 lines of output]
      Collecting pywlroots<0.18.0,>=0.17.0
        Using cached pywlroots-0.17.0.tar.gz (99 kB)
        Installing build dependencies: started
        Installing build dependencies: finished with status 'done'
        Getting requirements to build wheel: started
        Getting requirements to build wheel: finished with status 'done'
        Installing backend dependencies: started
        Installing backend dependencies: finished with status 'done'
        Preparing metadata (pyproject.toml): started
        Preparing metadata (pyproject.toml): finished with status 'error'
        error: subprocess-exited-with-error
      
        × Preparing metadata (pyproject.toml) did not run successfully.
        │ exit code: 1
        ╰─> [159 lines of output]
            /tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/config/_apply_pyprojecttoml.py:82: SetuptoolsDeprecationWarning: `project.license` as a TOML table is deprecated
            !!
      
                    ********************************************************************************
                    Please use a simple string containing a SPDX expression for `project.license`. You can also use `project.license-files`. (Both options available on setuptools>=77.0.0).
      
                    By 2026-Feb-18, you need to update your project and remove deprecated calls
                    or your builds will no longer be supported.
      
                    See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details.
                    ********************************************************************************
      
            !!
              corresp(dist, value, root_dir)
            wlroots/__pycache__/_cffi__x58fcf130x93e86b51.c:269:10: fatal error: wlr/version.h: No such file or directory
              269 | #include <wlr/version.h>
                  |          ^~~~~~~~~~~~~~~
            compilation terminated.
            Traceback (most recent call last):
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/spawn.py", line 87, in spawn
                subprocess.check_call(cmd, env=_inject_macos_ver(env))
                ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/subprocess.py", line 421, in check_call
                raise CalledProcessError(retcode, cmd)
            subprocess.CalledProcessError: Command '['/usr/bin/gcc', '-fno-strict-overflow', '-Wsign-compare', '-DNDEBUG', '-g', '-O3', '-Wall', '-fPIC', '-I/home/cjoke/.pyenv/versions/3.13.2/include/python3.13', '-c', 'wlroots/__pycache__/_cffi__x58fcf130x93e86b51.c', '-o', '/tmp/pip-install-7gcbd_t0/pywlroots_336e7e95f93548fca9df4d1c75baeccd/wlroots/__pycache__/wlroots/__pycache__/_cffi__x58fcf130x93e86b51.o']' returned non-zero exit status 1.
      
            The above exception was the direct cause of the following exception:
      
            Traceback (most recent call last):
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/compilers/C/unix.py", line 221, in _compile
                self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs)
                ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/compilers/C/base.py", line 1158, in spawn
                spawn(cmd, dry_run=self.dry_run, **kwargs)
                ~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/spawn.py", line 93, in spawn
                raise DistutilsExecError(
                    f"command {_debug(cmd)!r} failed with exit code {err.returncode}"
                ) from err
            distutils.errors.DistutilsExecError: command '/usr/bin/gcc' failed with exit code 1
      
            During handling of the above exception, another exception occurred:
      
            Traceback (most recent call last):
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/ffiplatform.py", line 48, in _build
                dist.run_command('build_ext')
                ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/dist.py", line 1104, in run_command
                super().run_command(command)
                ~~~~~~~~~~~~~~~~~~~^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/dist.py", line 1021, in run_command
                cmd_obj.run()
                ~~~~~~~~~~~^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/command/build_ext.py", line 99, in run
                _build_ext.run(self)
                ~~~~~~~~~~~~~~^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 368, in run
                self.build_extensions()
                ~~~~~~~~~~~~~~~~~~~~~^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 484, in build_extensions
                self._build_extensions_serial()
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 510, in _build_extensions_serial
                self.build_extension(ext)
                ~~~~~~~~~~~~~~~~~~~~^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/command/build_ext.py", line 264, in build_extension
                _build_ext.build_extension(self, ext)
                ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/command/build_ext.py", line 565, in build_extension
                objects = self.compiler.compile(
                    sources,
                ...<5 lines>...
                    depends=ext.depends,
                )
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/compilers/C/base.py", line 655, in compile
                self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
                ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/compilers/C/unix.py", line 223, in _compile
                raise CompileError(msg)
            distutils.compilers.C.errors.CompileError: command '/usr/bin/gcc' failed with exit code 1
      
            During handling of the above exception, another exception occurred:
      
            Traceback (most recent call last):
              File "wlroots/ffi_build.py", line 36, in load_wlroots_version
                lib = ffi.verify("#include <wlr/version.h>")
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/api.py", line 468, in verify
                lib = self.verifier.load_library()
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/verifier.py", line 105, in load_library
                self._compile_module()
                ~~~~~~~~~~~~~~~~~~~~^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/verifier.py", line 201, in _compile_module
                outputfilename = ffiplatform.compile(tmpdir, self.get_extension())
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/ffiplatform.py", line 20, in compile
                outputfilename = _build(tmpdir, ext, compiler_verbose, debug)
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/ffiplatform.py", line 54, in _build
                raise VerificationError('%s: %s' % (e.__class__.__name__, e))
            cffi.VerificationError: CompileError: command '/usr/bin/gcc' failed with exit code 1
      
            During handling of the above exception, another exception occurred:
      
            Traceback (most recent call last):
              File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 389, in <module>
                main()
                ~~~~^^
              File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 373, in main
                json_out["return_val"] = hook(**hook_input["kwargs"])
                                         ~~~~^^^^^^^^^^^^^^^^^^^^^^^^
              File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 175, in prepare_metadata_for_build_wheel
                return hook(metadata_directory, config_settings)
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 374, in prepare_metadata_for_build_wheel
                self.run_setup()
                ~~~~~~~~~~~~~~^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 317, in run_setup
                exec(code, locals())
                ~~~~^^^^^^^^^^^^^^^^
              File "<string>", line 34, in <module>
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/__init__.py", line 117, in setup
                return distutils.core.setup(**attrs)
                       ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/core.py", line 148, in setup
                _setup_distribution = dist = klass(attrs)
                                             ~~~~~^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/dist.py", line 323, in __init__
                _Distribution.__init__(self, dist_attrs)
                ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/_distutils/dist.py", line 309, in __init__
                self.finalize_options()
                ~~~~~~~~~~~~~~~~~~~~~^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/dist.py", line 786, in finalize_options
                ep(self)
                ~~^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/setuptools/dist.py", line 806, in _finalize_setup_keywords
                ep.load()(self, ep.name, value)
                ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/setuptools_ext.py", line 216, in cffi_modules
                add_cffi_module(dist, cffi_module)
                ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/setuptools_ext.py", line 49, in add_cffi_module
                execfile(build_file_name, mod_vars)
                ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/tmp/pip-build-env-a962oak3/overlay/lib/python3.13/site-packages/cffi/setuptools_ext.py", line 25, in execfile
                exec(code, glob, glob)
                ~~~~^^^^^^^^^^^^^^^^^^
              File "wlroots/ffi_build.py", line 3132, in <module>
                check_version()
                ~~~~~~~~~~~~~^^
              File "wlroots/ffi_build.py", line 49, in check_version
                wlroots_version = load_wlroots_version()
              File "wlroots/ffi_build.py", line 38, in load_wlroots_version
                lib = importlib.import_module("wlroots").lib
                      ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
              File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/importlib/__init__.py", line 88, in import_module
                return _bootstrap._gcd_import(name[level:], package, level)
                       ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
              File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
              File "<frozen importlib._bootstrap>", line 1324, in _find_and_load_unlocked
            ModuleNotFoundError: No module named 'wlroots'
            [end of output]
      
        note: This error originates from a subprocess, and is likely not a problem with pip.
      error: metadata-generation-failed
      
      × Encountered error while generating package metadata.
      ╰─> See above for output.
      
      note: This is an issue with the package mentioned above, not pip.
      hint: See above for details.
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× pip subprocess to install backend dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.
```

### Required

- [x] I have searched past issues to see if this bug has already been reported, and it hasn't been.
- [x] I understand that people give their precious time for free, and thus I've done my very best to make this problem as easy as possible to investigate.

Hints from issue comments:
@cjoke: I did some further investigations firstly I did as in pyproject.toml specification(official).

- changed the license from a table to a string.
where I got a new error that I cant figure out, since my python is low level. 

If you look at `ERROR setuptools==0.31*`

in my setup I have
```
setuptools          79.0.0
setuptools-scm      8.2.0
```
I run `pyenv global 3.13.2 system` and have installed qtile in 3.13.2 

in system environment, version of setuptools is 75.8.0

I dont understand where version 0.31 from ERROR message comes from. 

```
pip install --config-setting backend=wayland .
Processing /home/cjoke/dev/qtile
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  error: subprocess-exited-with-error
  
  × Getting requirements to build wheel did not run successfully.
  │ exit code: 1
  ╰─> [57 lines of output]
      /tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools_scm/_integration/setuptools.py:31: RuntimeWarning:
      ERROR: setuptools==0.31.1.dev22+gac2dfdcc.d20250421 is used in combination with setuptools-scm>=8.x
      
      Your build configuration is incomplete and previously worked by accident!
      setuptools-scm requires setuptools>=61
      
      Suggested workaround if applicable:
       - migrating from the deprecated setup_requires mechanism to pep517/518
         and using a pyproject.toml to declare build dependencies
         which are reliably pre-installed before running the build tools
      
        warnings.warn(
      /tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools_scm/_integration/setuptools.py:92: UserWarning: version of None already set
        warnings.warn(f"version of {dist_name} already set")
      Failed to find pywlroots. Wayland backend dependencies not built.
      Traceback (most recent call last):
        File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 389, in <module>
          main()
          ~~~~^^
        File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 373, in main
          json_out["return_val"] = hook(**hook_input["kwargs"])
                                   ~~~~^^^^^^^^^^^^^^^^^^^^^^^^
        File "/home/cjoke/.pyenv/versions/3.13.2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 143, in get_requires_for_build_wheel
          return hook(config_settings)
        File "/home/cjoke/dev/qtile/builder.py", line 39, in get_requires_for_build_wheel
          reqs = _orig.get_requires_for_build_wheel(config_settings)
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 331, in get_requires_for_build_wheel
          return self._get_build_requires(config_settings, requirements=[])
                 ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 301, in _get_build_requires
          self.run_setup()
          ~~~~~~~~~~~~~~^^
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 317, in run_setup
          exec(code, locals())
          ~~~~^^^^^^^^^^^^^^^^
        File "<string>", line 64, in <module>
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/__init__.py", line 117, in setup
          return distutils.core.setup(**attrs)
                 ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/_distutils/core.py", line 160, in setup
          dist.parse_config_files()
          ~~~~~~~~~~~~~~~~~~~~~~~^^
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/dist.py", line 756, in parse_config_files
          pyprojecttoml.apply_configuration(self, filename, ignore_option_errors)
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/config/pyprojecttoml.py", line 73, in apply_configuration
          return _apply(dist, config, filepath)
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/config/_apply_pyprojecttoml.py", line 61, in apply
          dist._finalize_license_expression()
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
        File "/tmp/pip-build-env-cbbgomh2/overlay/lib/python3.13/site-packages/setuptools/dist.py", line 432, in _finalize_license_expression
          raise InvalidConfigError(
          ...<3 lines>...
          )
      setuptools.errors.InvalidConfigError: License classifiers have been superseded by license expressions (see https://peps.python.org/pep-0639/). Please remove:
      
      License :: OSI Approved :: MIT License
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.
```@tych0: Can you try the above branch? I think that should fix it.@cjoke: It's still not running. I did some research and committed a bug to debian. some version differences in wayland-server.pc config and debian package version. so pkg-config tells builder that version is too old? something like that. I guess Ill get some answeres later.@tych0: Hmm, ok. But at least this error went away?@cjoke: I did not run the branch, but I did change the lines from the diff. and It went further. I had the same problem installing with pip install qtile[wayland], I dont think this is a qtile bug. but nice to have updated the deprecated toml syntax :D. I am determent to test out wayland and qtile. It was so complex that I needed a break. I'll keep on pushing the maintainers of package and dig deeper in near future. I keep you posted. 
Thanks for respond! :)@tych0: Sure - I would try uv. It makes things much simpler.

Solution patch:
diff --git a/libqtile/widget/imapwidget.py b/libqtile/widget/imapwidget.py
index f6b0e43f..b8036480 100644
--- a/libqtile/widget/imapwidget.py
+++ b/libqtile/widget/imapwidget.py
@@ -33,7 +33,7 @@ class ImapWidget(base.ThreadPoolText):
 
     This widget will scan one of your imap email boxes and report the number of
     unseen messages present.  I've configured it to only work with imap with
-    ssl. Your password is obtained from the Gnome Keyring.
+    ssl. Your password can be obtained from the Gnome Keyring.
 
     Writing your password to the keyring initially is as simple as (changing
     out <userid> and <password> for your userid and password):
@@ -60,6 +60,9 @@ class ImapWidget(base.ThreadPoolText):
     ``mbox="~/Maildir/HomeMail/fred"``.  Note the nested sets of quotes! Labels
     can be whatever you choose, of course.
 
+    If you want you can give password directly then Gnome Keyring will not be
+    used.
+
     Widget requirements: keyring_.
 
     .. _keyring: https://pypi.org/project/keyring/
@@ -67,9 +70,11 @@ class ImapWidget(base.ThreadPoolText):
 
     defaults = [
         ("mbox", '"INBOX"', "mailbox to fetch"),
-        ("label", "INBOX", "label for display"),
+        ("label", "INBOX: ", "label for display"),
         ("user", None, "email username"),
+        ("password", None, "email password"),
         ("server", None, "email server name"),
+        ("hide_no_unseen", False, "hide when there are no unseen messages"),
     ]
 
     def __init__(self, **config):
@@ -77,20 +82,26 @@ class ImapWidget(base.ThreadPoolText):
         self.add_defaults(ImapWidget.defaults)
         if self.user is None:
             raise ConfigError("You must set the 'user' parameter for the IMAP widget.")
-        password = keyring.get_password("imapwidget", self.user)
-        if password is not None:
-            self.password = password
-        else:
-            logger.critical("Gnome Keyring Error")
+
+        if self.password is None:
+            password = keyring.get_password("imapwidget", self.user)
+            if password is not None:
+                self.password = password
+            else:
+                logger.critical("Gnome Keyring Error")
 
     def poll(self):
         im = imaplib.IMAP4_SSL(self.server, 993)
-        if self.password == "Gnome Keyring Error":
-            text = "Gnome Keyring Error"
+        if self.password is None:
+            text = "No password error"
         else:
             im.login(self.user, self.password)
             status, response = im.status(self.mbox, "(UNSEEN)")
-            text = response[0].decode()
-            text = self.label + ": " + re.sub(r"\).*$", "", re.sub(r"^.*N\s", "", text))
             im.logout()
+            text = response[0].decode()
+            count = re.sub(r"\).*$", "", re.sub(r"^.*N\s", "", text))
+            if count == "0" and self.hide_no_unseen:
+                return ""
+
+            text = self.label + count
         return text
diff --git a/pyproject.toml b/pyproject.toml
index fefc6a5a..effb594a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -13,10 +13,10 @@ build-backend = "builder"
 name = "qtile"
 description = "A pure-Python tiling window manager."
 dynamic = ["version", "readme", "dependencies", "optional-dependencies"]
-license = {text = "MIT"}
+license = "MIT"
+license-files = [ "LICENSE" ]
 classifiers = [
     "Intended Audience :: End Users/Desktop",
-    "License :: OSI Approved :: MIT License",
     "Operating System :: POSIX :: BSD :: FreeBSD",
     "Operating System :: POSIX :: Linux",
     "Programming Language :: Python :: 3 :: Only",


Test patch:
diff --git a/test/widgets/test_imapwidget.py b/test/widgets/test_imapwidget.py
index fee5c8c9..566ea614 100644
--- a/test/widgets/test_imapwidget.py
+++ b/test/widgets/test_imapwidget.py
@@ -50,16 +50,11 @@ class FakeIMAP(ModuleType):
 
 class FakeKeyring(ModuleType):
     valid = True
-    error = True
 
     def get_password(self, _app, user):
         if self.valid:
             return "password"
-
-        else:
-            if self.error:
-                return "Gnome Keyring Error"
-            return None
+        return None
 
 
 @pytest.fixture()
@@ -82,27 +77,21 @@ def test_imapwidget(fake_qtile, monkeypatch, fake_window, patched_imap):
     assert text == "INBOX: 2"
 
 
-def test_imapwidget_keyring_error(fake_qtile, monkeypatch, fake_window, patched_imap):
+def test_imapwidget_with_password(fake_qtile, monkeypatch, fake_window, patched_imap):
+    # keyring should not be called
     patched_imap.keyring.valid = False
-    imap = patched_imap.ImapWidget(user="qtile")
+    imap = patched_imap.ImapWidget(user="qtile", password="password")
     fakebar = FakeBar([imap], window=fake_window)
     imap._configure(fake_qtile, fakebar)
     text = imap.poll()
-    assert text == "Gnome Keyring Error"
+    assert text == "INBOX: 2"
 
 
-# Widget does not handle "password = None" elegantly.
-# It logs a message but doesn't set self.password.
-# The widget will then fail when it looks up this attribute and then
-# fail again when it tries to return self.text.
-# TO DO: Fix widget's handling of this scenario.
 def test_imapwidget_password_none(fake_qtile, monkeypatch, fake_window, patched_imap):
     patched_imap.keyring.valid = False
-    patched_imap.keyring.error = False
 
     imap = patched_imap.ImapWidget(user="qtile")
     fakebar = FakeBar([imap], window=fake_window)
     imap._configure(fake_qtile, fakebar)
-    with pytest.raises(AttributeError):
-        with pytest.raises(UnboundLocalError):
-            imap.poll()
+    text = imap.poll()
+    assert text == "No password error"