Repository: pyinstaller/pyinstaller

Issue:
Log level `DEPRECATION` is documented but not working
## Description of the issue

Log level `DEPRECATION` is documented but not working.

### Context information (for bug reports)

* Output of `pyinstaller --version`: ```5.7.0```
* Version of Python: 3.10.6
* Platform: Ubuntu 22.04
* How you installed Python: apt
* Did you also try this on another platform? Does it work there? yes, same thing
* try the latest development version, using the following command: yes, same thing

### A minimal example program which shows the error

```
$ pyinstaller --help | grep -U1 DEPREC
  --log-level LEVEL     Amount of detail in build-time console messages. LEVEL
                        may be one of TRACE, DEBUG, INFO, WARN, DEPRECATION,
                        ERROR, CRITICAL (default: INFO). Also settable via and
$ pyinstaller --log-level DEPRECATION .
[...]
pyinstaller: error: Unknown log level `DEPRECATION`
```



Discussion:
Indeed. Looks like the problem lies in the fact that `logging.addLevelName()` does not add the level name as a module-level attribute, but only registers it with its internal dictionaries. Thus `getattr(logging, 'DEPRECATION')` raises an error.

Either we'll need to use the `logging`'s internal dictionary for the lookup, or create our own.
Now I understand why this line existed:

https://github.com/pyinstaller/pyinstaller/blob/d6ff0802dd6f2fbeccb4a6c47e1cf24c61c31205/PyInstaller/log.py#L21

Let's just create our own dict for them - I didn't like the `getattr(logging, ...)` stuff even before seeing this issue.

Resolving patch:
diff --git a/PyInstaller/log.py b/PyInstaller/log.py
--- a/PyInstaller/log.py
+++ b/PyInstaller/log.py
@@ -18,18 +18,26 @@
 import logging
 from logging import DEBUG, ERROR, FATAL, INFO, WARN, getLogger
 
-TRACE = logging.TRACE = DEBUG - 5
+TRACE = DEBUG - 5
 logging.addLevelName(TRACE, 'TRACE')
 DEPRECATION = WARN + 5
 logging.addLevelName(DEPRECATION, 'DEPRECATION')
-LEVELS = ('TRACE', 'DEBUG', 'INFO', 'WARN', 'DEPRECATION', 'ERROR', 'CRITICAL')
+LEVELS = {
+    'TRACE': TRACE,
+    'DEBUG': DEBUG,
+    'INFO': INFO,
+    'WARN': WARN,
+    'DEPRECATION': DEPRECATION,
+    'ERROR': ERROR,
+    'FATAL': FATAL,
+}
 
 FORMAT = '%(relativeCreated)d %(levelname)s: %(message)s'
 _env_level = os.environ.get("PYI_LOG_LEVEL", "INFO")
 try:
-    level = getattr(logging, _env_level.upper())
-except AttributeError:
-    raise SystemExit(f"Invalid PYI_LOG_LEVEL value '{_env_level}'. Should be one of {LEVELS}.")
+    level = LEVELS[_env_level.upper()]
+except KeyError:
+    raise SystemExit(f"Invalid PYI_LOG_LEVEL value '{_env_level}'. Should be one of {list(LEVELS)}.")
 logging.basicConfig(format=FORMAT, level=level)
 logger = getLogger('PyInstaller')
 
@@ -49,8 +57,8 @@ def __process_options(parser, opts):
     if opts.loglevel:
         try:
             level = opts.loglevel.upper()
-            _level = getattr(logging, level)
-        except AttributeError:
+            _level = LEVELS[level]
+        except KeyError:
             parser.error('Unknown log level `%s`' % opts.loglevel)
         logger.setLevel(_level)
         os.environ["PYI_LOG_LEVEL"] = level


Test patch: