diff --git a/EDMCLogging.py b/EDMCLogging.py index 6d9f8d28..d4836ad6 100644 --- a/EDMCLogging.py +++ b/EDMCLogging.py @@ -325,8 +325,11 @@ class EDMCContextFilter(logging.Filter): if frame_class: # See https://en.wikipedia.org/wiki/Name_mangling#Python for how name mangling works. - if (name := frame_info.function).startswith("__") and not name.endswith("__"): - name = f'_{frame_class.__class__.__name__}{frame_info.function}' + # For more detail, see _Py_Mangle in CPython's Python/compile.c. + name = frame_info.function + class_name = frame_class.__class__.__name__.lstrip("_") + if name.startswith("__") and not name.endswith("__") and class_name: + name = f'_{class_name}{frame_info.function}' # Find __qualname__ of the caller fn = inspect.getattr_static(frame_class, name, None) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 233c9d22..de1c526a 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -73,6 +73,11 @@ if __name__ == '__main__': # noqa: C901 action='store_true' ) + parser.add_argument('edmc', + help='Callback from Frontier Auth', + nargs='*' + ) + args = parser.parse_args() if args.trace: @@ -171,9 +176,7 @@ if __name__ == '__main__': # noqa: C901 # Ref: EnumWindows(enumwindowsproc, 0) - return False # Another instance is running - - return True + return def already_running_popup(): """Create the "already running" popup.""" @@ -201,17 +204,19 @@ if __name__ == '__main__': # noqa: C901 journal_lock = JournalLock() locked = journal_lock.obtain_lock() - if journal_lock.journal_dir_lockfile: - if not no_other_instance_running(): - # There's a copy already running. + handle_edmc_callback_or_foregrounding() - logger.info("An EDMarketConnector.exe process was already running, exiting.") + if locked == JournalLockResult.ALREADY_LOCKED: + # There's a copy already running. - # To be sure the user knows, we need a popup + logger.info("An EDMarketConnector.exe process was already running, exiting.") + + # To be sure the user knows, we need a popup + if not args.edmc: already_running_popup() - # If the user closes the popup with the 'X', not the 'OK' button we'll - # reach here. - sys.exit(0) + # If the user closes the popup with the 'X', not the 'OK' button we'll + # reach here. + sys.exit(0) if getattr(sys, 'frozen', False): # Now that we're sure we're the only instance running we can truncate the logfile @@ -1238,31 +1243,40 @@ class AppWindow(object): config.set('geometry', f'+{x}+{y}') # Let the user know we're shutting down. - self.status['text'] = 'Shutting down...' + self.status['text'] = _('Shutting down...') self.w.update_idletasks() logger.info('Starting shutdown procedures...') - logger.info('Closing protocol handler...') - protocolhandler.close() + # First so it doesn't interrupt us + logger.info('Closing update checker...') + self.updater.close() + # Earlier than anything else so plugin code can't interfere *and* it + # won't still be running in a manner that might rely on something + # we'd otherwise have already stopped. + logger.info('Notifying plugins to stop...') + plug.notify_stop() + + # Handling of application hotkeys now so the user can't possible cause + # an issue via triggering one. logger.info('Unregistering hotkey manager...') hotkeymgr.unregister() + # Now the main programmatic input methods logger.info('Closing dashboard...') dashboard.close() logger.info('Closing journal monitor...') monitor.close() - logger.info('Notifying plugins to stop...') - plug.notify_stop() - - logger.info('Closing update checker...') - self.updater.close() + # Frontier auth/CAPI handling + logger.info('Closing protocol handler...') + protocolhandler.close() logger.info('Closing Frontier CAPI sessions...') companion.session.close() + # Now anything else. logger.info('Closing config...') config.close() diff --git a/journal_lock.py b/journal_lock.py index a5f72187..bfb6ee85 100644 --- a/journal_lock.py +++ b/journal_lock.py @@ -39,6 +39,7 @@ class JournalLock: self.journal_dir_lockfile_name: Optional[pathlib.Path] = None # We never test truthiness of this, so let it be defined when first assigned. Avoids type hint issues. # self.journal_dir_lockfile: Optional[IO] = None + self.locked = False def set_path_from_journaldir(self): """Set self.journal_dir_path from seld.journal_dir.""" @@ -108,6 +109,8 @@ class JournalLock: self.journal_dir_lockfile.flush() logger.trace('Done') + self.locked = True + return JournalLockResult.LOCKED def release_lock(self) -> bool: @@ -116,6 +119,9 @@ class JournalLock: :return: bool - Whether we're now unlocked. """ + if not self.locked: + return True # We weren't locked, and still aren't + unlocked = False if platform == 'win32': logger.trace('win32, using msvcrt') diff --git a/plugins/eddn.py b/plugins/eddn.py index bbcd5b35..46a893db 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -809,15 +809,27 @@ def is_horizons(economies: MAP_STR_ANY, modules: MAP_STR_ANY, ships: MAP_STR_ANY modules_horizons = False ship_horizons = False - if isinstance(dict, economies): + if isinstance(economies, dict): economies_colony = any(economy['name'] == 'Colony' for economy in economies.values()) - if isinstance(dict, modules): + else: + logger.error(f'economies type is {type(economies)}') + + if isinstance(modules, dict): modules_horizons = any(module.get('sku') == HORIZ_SKU for module in modules.values()) - if isinstance(dict, ships): + else: + logger.error(f'modules type is {type(modules)}') + + if isinstance(ships, dict): if ships.get('shipyard_list') is not None: ship_horizons = any(ship.get('sku') == HORIZ_SKU for ship in ships['shipyard_list'].values()) + else: + logger.debug('No ships["shipyard_list"] - Damaged station or FC ?') + + else: + logger.error(f'ships type is {type(ships)}') + return economies_colony or modules_horizons or ship_horizons diff --git a/setup.py b/setup.py index c39c9553..51f0d1f9 100755 --- a/setup.py +++ b/setup.py @@ -177,7 +177,14 @@ elif sys.platform=='win32': 'timeout_session', 'zipfile', # Included for plugins ], - 'excludes': [ 'distutils', '_markerlib', 'optparse', 'PIL', 'pkg_resources', 'simplejson', 'unittest' ], + 'excludes': [ + 'distutils', + '_markerlib', + 'optparse', + 'PIL', + 'pkg_resources', + 'simplejson', + 'unittest' ], } }