1. We need the args available at the top.
2. In `develop` we'd renamed `enforce_single_instance()` to
`no_other_instance_running()` so that it's obvious it's a function
returning a boolean, rather than the function that does the
enforcement.
1. So now they're only defined in one place.
2. config.py does an import of them, and `from config import ...` then
chains through, so no need to update other users.
3. No need to ' # noqa E402' the killswitch/config imports now.
1. The updater is in a thread/DLL and we don't want that firing part way
through shutdown, so it gets asked to stop first.
2. Then plugins, so they're out of the way and we won't have already
stopped something they might rely on.
3. Hotkey after that to head off the user triggering something via them.
4. Now stop the programmatic input from Journal files (including
Status.json).
5. Frontier auth handling.
6. And then anything else.
monitor.thread should only be none when there's a <<JournalEvent>> to
process if we're in shutdown, in which case we do *not* want to be
processing journal events.
This is some best effort support for using logging in properties.
This works by using the (as suggested by reporter) inspect
`getattr_static` method, and failing that (as it can possibly fail),
wrapping a `getattr` in a try/catch for a RecursionError--don't want to
catch other things, probably best if that explodes on its own.
From there as the `property` object will not have location information,
we rebuild as best we can to an approximation of what the path would be.
With a healthy dash of defensive programming "Just in case".
I don't think that this will have any adverse effects to other logging
methods, as all the new code should only be touched if we hit a property
object.
Closes#808
Python name mangling is more about name collisions than actually making
things private.
This commit adds a check to resolve mangled names to their runtime
names, and adds a just-in-case default to fetching the attribute.
Fixes#764
* We're using try/except so can just attempt the setting of a UTF-8
encoding. In cases where it doesn't work we'll have some obvious log
output to help diagnose any issues it causes later.
* Cleaned up the comments to be more 'why' than 'what'.
Any running from source, or on a non-win32 platform will attempt to
force UTF-8 encoding.
For frozen win32 we'll rely on the windows manifest setting. On too-old
versions of Windows we'll have to ensure all code works with non-UTF-8
encodings.
* EDMC: Add --trace (to match EDMarketConnector.py) and TRACE as option to
--loglevel.
* EDMC: docstrings added.
* EDMCLogging: Set logger name based on if GUI or CLI.
* EDMarketConnector:
* Re-order imports.
* Misc. formatting cleanups.
* f-strings not .format().
* Removed un-necessary "# noqa: N806" comments.
As we might run into some special cases with users we need to log in
more detail what the locale is around our changes.
NB: Also contains some misc. PyCharm-enacted formatting changes, white
space, wrapping etc.
tkinter ends up calling something where utf8 characters won't work
because of the windows encoding, e.g. cp1252.
We can't set encoding just for the dialogs, as it's not thread safe. So
we'll just set it at startup instead. Utilising:
locale.setlocale(locale.LC_ALL, '')
to get things set up initially, so we can properly retrieve the language
to go with the encoding on the subsequent setlocale() call.
If we use the last configured value then the width of the Scale bar
changes as per the user's last setting, even though they might not have
yet restarted for all the rest of the UI to resize.
So if at startup tk-scaling is 1.33 then a user configured 200(%) will
set it to 2.66 for this run.
* Low end of scale bar set to 10, not 0, because now 0 makes absolutely
no sense.
* In theory the width of the scale bar, in pixels, is now also correctly
scaled.
Using a Tk.DoubleVar() with a locale where a comma is used as the
decimals separator leads to internal tk code recording values with the
comma but then other tk code not accepting that back, so it always
thinks the value is zero and the scale slider can't be moved.
Ref: https://stackoverflow.com/questions/45289237/tkinter-scale-slider-with-float-values-doesnt-work-with-locale-of-language-that
* Change to storing as a REG_DWORD under 'ui_scale' not 'ui_scaling'.
* Change all the code, except the call to *set* the tk scaling to use an
integer, with 100 = 100%, i.e. equivalent to the old 1.0.
* Update strings slightly, so translations will need updating too.
NB: The theme.default_ui_scale value for plugin authors to query is
still the float that tk returns.
If anything does `import logging` it's likely to grab a copy of
sys.stderr before we redirect it meaning things aren't properly
redirected when we start logging.
So put the redirect as early as possible in EDMarketConnector.py.
This will need a test implemented to be sure it's not accidentally
broken by addition of an import before this.
* If no ui_scaling yet set, set it to 'default'.
* 'default' added to dropdown choices.
Note that you still need an application restart for this to take effect.
* EDMCLogging.Logger.get_streamhandler() method to get the
logger_channel so prefs.py can call setLevel() on it.
* The top-level Logger level is always DEBUG.
* The RotatingFileHandler level is always DEBUG.
* The StreamHandler level is as configured by the user.
* EDMCLogging now creates a singleton of EDMCLogging.Logger and its
associated Logger.
* plug.py tweaked to only import EDMCLogging where it's needed for
getting/creating plugin loggers, else `import logging`.
* All logging duplicated into %TEMP%/{appname}/{logger_name}.log
* These are handled by the RotatingFileHandler, currently set to 1MiB
per file and 10 backup files.
* Do *NOT* setLevel() on the handlers, as we want to control the level
up at the logger instead. This would have caused the CL and GUI
selection of loglevel to NOT have any effect (hidden by default having
been DEBUG).
* EDMarketConnector.py now INFO logs its startup and exit.
* <module> works.
* top-level function in <module> works, presumably also any other file.
* Call from within classes works.
* Extra, commented out, test cases in EDMarketConnector.py