Repository: qtile/qtile

Issue:
Set version using importlib.metadata
<!--
Please do not ask general questions here! There are [community
contact](https://github.com/qtile/qtile#community) options for that.

If you are suggesting a new feature/enhancement please instead post it on the
discussions board as an idea: https://github.com/qtile/qtile/discussions/categories/ideas
-->

# Issue description

Currently, if setuptools is not installed on the system running qtile, it will run into issues upon start.
An Arch user reported this downstream: https://bugs.archlinux.org/task/71804

Apart from also guarding against `ModuleNotFoundError` I think it could be a great idea to [use importlib.metadata to provide qtile's version](https://docs.python.org/3.9/library/importlib.metadata.html?highlight=importlib%20metadata#distribution-versions) instead for newer python versions.
<!--
A brief discussion of what failed and how it failed. A description of
what you tried is helpful, i.e. "When I use lazy.kill() on a window I get
the following stack trace" instead of "Closing windows doesn't work".
-->

# Qtile version

0.18.1

# Stack traces

Copied verbatim from the issue reported downstream:

```
Traceback (most recent call last):
File "/usr/lib/python3.9/site-packages/libqtile/scripts/main.py", line 9, in <module>
import pkg_resources
ModuleNotFoundError: No module named 'pkg_resources'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/bin/qtile", line 33, in <module>
sys.exit(load_entry_point('qtile==0.18.1.dev0+g8e7ecc0a.d20210719', 'console_scripts', 'qtile')())
File "/usr/bin/qtile", line 25, in importlib_load_entry_point
return next(matches).load()
File "/usr/lib/python3.9/importlib/metadata.py", line 77, in load
module = import_module(match.group('module'))
File "/usr/lib/python3.9/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/usr/lib/python3.9/site-packages/libqtile/scripts/main.py", line 11, in <module>
except (pkg_resources.DistributionNotFound, ImportError):
NameError: name 'pkg_resources' is not defined
```

# Configuration

not important for this issue


Discussion:

Resolving patch:
diff --git a/libqtile/scripts/main.py b/libqtile/scripts/main.py
--- a/libqtile/scripts/main.py
+++ b/libqtile/scripts/main.py
@@ -6,10 +6,16 @@
 from libqtile.scripts import check, cmd_obj, migrate, run_cmd, shell, start, top
 
 try:
-    import pkg_resources
-    VERSION = pkg_resources.require("qtile")[0].version
-except (pkg_resources.DistributionNotFound, ImportError):
-    VERSION = 'dev'
+    # Python>3.7 can get the version from importlib
+    from importlib.metadata import distribution
+    VERSION = distribution("qtile").version
+except ModuleNotFoundError:
+    try:
+        # pkg_resources is required for 3.7
+        import pkg_resources
+        VERSION = pkg_resources.require("qtile")[0].version
+    except (pkg_resources.DistributionNotFound, ModuleNotFoundError):
+        VERSION = 'dev'
 
 
 def main():


Test patch: