mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-12 15:27:14 +03:00
Trace: Add support to EDMC.py & misc cleanups
* 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.
This commit is contained in:
parent
46e3b3aff8
commit
3c0ac76f90
69
EDMC.py
69
EDMC.py
@ -1,19 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Command-line interface. Requires prior setup through the GUI.
|
||||
#
|
||||
"""Command-line interface. Requires prior setup through the GUI."""
|
||||
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from os.path import getmtime, join
|
||||
from time import sleep, time
|
||||
from typing import Any, Optional
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
|
||||
# isort: off
|
||||
from EDMCLogging import edmclogger, logger, logging
|
||||
if TYPE_CHECKING:
|
||||
from logging import trace, TRACE # type: ignore # noqa: F401
|
||||
# isort: on
|
||||
edmclogger.set_channels_loglevel(logging.INFO)
|
||||
|
||||
# workaround for https://github.com/EDCD/EDMarketConnector/issues/568
|
||||
os.environ["EDMC_NO_UI"] = "1"
|
||||
@ -21,7 +25,6 @@ os.environ["EDMC_NO_UI"] = "1"
|
||||
import collate
|
||||
import commodity
|
||||
import companion
|
||||
import EDMCLogging
|
||||
import edshipyard
|
||||
import l10n
|
||||
import loadout
|
||||
@ -40,11 +43,9 @@ sys.path.append(config.internal_plugin_dir)
|
||||
import eddn # noqa: E402
|
||||
# isort: on
|
||||
|
||||
logger = EDMCLogging.Logger(appcmdname).get_logger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
|
||||
def log_locale(prefix: str) -> None:
|
||||
"""Log the current state of locale settings."""
|
||||
logger.debug(f'''Locale: {prefix}
|
||||
Locale LC_COLLATE: {locale.getlocale(locale.LC_COLLATE)}
|
||||
Locale LC_CTYPE: {locale.getlocale(locale.LC_CTYPE)}
|
||||
@ -62,12 +63,30 @@ EXIT_SUCCESS, EXIT_SERVER, EXIT_CREDENTIALS, EXIT_VERIFICATION, EXIT_LAGGING, EX
|
||||
JOURNAL_RE = re.compile(r'^Journal(Beta)?\.[0-9]{12}\.[0-9]{2}\.log$')
|
||||
|
||||
|
||||
# quick and dirty version comparison assuming "strict" numeric only version numbers
|
||||
def versioncmp(versionstring):
|
||||
"""Quick and dirty version comparison assuming "strict" numeric only version numbers."""
|
||||
return list(map(int, versionstring.split('.')))
|
||||
|
||||
|
||||
def deep_get(target: dict, *args: str, default=None) -> Any:
|
||||
"""
|
||||
Walk into a dict and return the specified deep value.
|
||||
|
||||
Example usage:
|
||||
|
||||
>>> thing = {'a': {'b': {'c': 'foo'} } }
|
||||
>>> deep_get(thing, ('a', 'b', 'c'), None)
|
||||
'foo'
|
||||
>>> deep_get(thing, ('a', 'b'), None)
|
||||
{'c': 'foo'}
|
||||
>>> deep_get(thing, ('a', 'd'), None)
|
||||
None
|
||||
|
||||
:param target: The dict to walk into for the desired value.
|
||||
:param args: The list of keys to walk down through.
|
||||
:param default: What to return if the target has no value.
|
||||
:return: The value at the target deep key.
|
||||
"""
|
||||
if not hasattr(target, 'get'):
|
||||
raise ValueError(f"Cannot call get on {target} ({type(target)})")
|
||||
|
||||
@ -83,6 +102,7 @@ def deep_get(target: dict, *args: str, default=None) -> Any:
|
||||
|
||||
|
||||
def main():
|
||||
"""Run the main code of the program."""
|
||||
try:
|
||||
# arg parsing
|
||||
parser = argparse.ArgumentParser(
|
||||
@ -93,7 +113,16 @@ def main():
|
||||
)
|
||||
|
||||
parser.add_argument('-v', '--version', help='print program version and exit', action='store_const', const=True)
|
||||
parser.add_argument('--loglevel', metavar='loglevel', help='Set the logging loglevel to one of: CRITICAL, ERROR, WARNING, INFO, DEBUG') # noqa: E501
|
||||
group_loglevel = parser.add_mutually_exclusive_group()
|
||||
group_loglevel.add_argument('--loglevel',
|
||||
metavar='loglevel',
|
||||
help='Set the logging loglevel to one of: '
|
||||
'CRITICAL, ERROR, WARNING, INFO, DEBUG, TRACE',
|
||||
)
|
||||
group_loglevel.add_argument('--trace',
|
||||
help='Set the Debug logging loglevel to TRACE',
|
||||
action='store_true',
|
||||
)
|
||||
parser.add_argument('-a', metavar='FILE', help='write ship loadout to FILE in Companion API json format')
|
||||
parser.add_argument('-e', metavar='FILE', help='write ship loadout to FILE in E:D Shipyard plain text format')
|
||||
parser.add_argument('-l', metavar='FILE', help='write ship locations to FILE in CSV format')
|
||||
@ -117,11 +146,14 @@ def main():
|
||||
|
||||
return
|
||||
|
||||
if args.loglevel:
|
||||
if args.loglevel not in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'):
|
||||
print('loglevel must be one of: CRITICAL, ERROR, WARNING, INFO, DEBUG', file=sys.stderr)
|
||||
if args.trace:
|
||||
edmclogger.set_channels_loglevel(logging.TRACE)
|
||||
|
||||
elif args.loglevel:
|
||||
if args.loglevel not in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'TRACE'):
|
||||
print('loglevel must be one of: CRITICAL, ERROR, WARNING, INFO, DEBUG, TRACE', file=sys.stderr)
|
||||
sys.exit(EXIT_ARGS)
|
||||
logger.setLevel(args.loglevel)
|
||||
edmclogger.set_channels_loglevel(args.loglevel)
|
||||
|
||||
logger.debug(f'Startup v{appversion} : Running on Python v{sys.version}')
|
||||
logger.debug(f'''Platform: {sys.platform}
|
||||
@ -250,10 +282,9 @@ sys.path: {sys.path}'''
|
||||
stats.export_status(data, args.t)
|
||||
|
||||
if data['commander'].get('docked'):
|
||||
print('{},{}'.format(
|
||||
deep_get(data, 'lastSystem', 'name', default='Unknown'),
|
||||
deep_get(data, 'lastStarport', 'name', default='Unknown')
|
||||
))
|
||||
print(f'{deep_get(data, "lastSystem", "name", default="Unknown")},'
|
||||
f'{deep_get(data, "lastStarport", "name", default="Unknown")}'
|
||||
)
|
||||
|
||||
else:
|
||||
print(deep_get(data, 'lastSystem', 'name', default='Unknown'))
|
||||
|
@ -381,5 +381,11 @@ def get_main_logger() -> logging.Logger:
|
||||
loglevel = config.get('loglevel')
|
||||
if not loglevel:
|
||||
loglevel = logging.INFO
|
||||
edmclogger = Logger(appname, loglevel=loglevel)
|
||||
|
||||
if not os.getenv('EDMC_NO_UI'):
|
||||
base_logger_name = appname
|
||||
else:
|
||||
base_logger_name = appcmdname
|
||||
|
||||
edmclogger = Logger(base_logger_name, loglevel=loglevel)
|
||||
logger = edmclogger.get_logger()
|
||||
|
@ -2,20 +2,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
from builtins import str
|
||||
from builtins import object
|
||||
import sys
|
||||
from sys import platform
|
||||
import html
|
||||
import json
|
||||
import locale
|
||||
import re
|
||||
import sys
|
||||
import webbrowser
|
||||
from builtins import object, str
|
||||
from os import chdir, environ
|
||||
from os.path import dirname, isdir, join
|
||||
import re
|
||||
import html
|
||||
from time import time, localtime, strftime
|
||||
import webbrowser
|
||||
from sys import platform
|
||||
from time import localtime, strftime, time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from config import appname, applongname, appversion, appversion_nobuild, copyright, config
|
||||
from EDMCLogging import edmclogger, logger, logging
|
||||
|
||||
# isort: off
|
||||
if TYPE_CHECKING:
|
||||
from logging import trace, TRACE # type: ignore # noqa: F401
|
||||
# isort: on
|
||||
|
||||
from config import applongname, appname, appversion, appversion_nobuild, config, copyright
|
||||
|
||||
# TODO: Test: Make *sure* this redirect is working, else py2exe is going to cause an exit popup
|
||||
if __name__ == "__main__":
|
||||
@ -37,10 +44,11 @@ if getattr(sys, 'frozen', False):
|
||||
environ['TK_LIBRARY'] = join(dirname(sys.path[0]), 'lib', 'tk')
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import tkinter.filedialog
|
||||
import tkinter.font
|
||||
import tkinter.messagebox
|
||||
from tkinter import ttk
|
||||
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
|
||||
if __debug__:
|
||||
@ -50,18 +58,18 @@ if __debug__:
|
||||
|
||||
signal.signal(signal.SIGTERM, lambda sig, frame: pdb.Pdb().set_trace(frame))
|
||||
|
||||
import companion
|
||||
import commodity
|
||||
from commodity import COMMODITY_CSV
|
||||
import td
|
||||
import stats
|
||||
import prefs
|
||||
import companion
|
||||
import plug
|
||||
import prefs
|
||||
import stats
|
||||
import td
|
||||
from commodity import COMMODITY_CSV
|
||||
from dashboard import dashboard
|
||||
from hotkey import hotkeymgr
|
||||
from l10n import Translations
|
||||
from monitor import monitor
|
||||
from protocol import protocolhandler
|
||||
from dashboard import dashboard
|
||||
from theme import theme
|
||||
|
||||
SERVER_RETRY = 5 # retry pause for Companion servers [s]
|
||||
@ -614,11 +622,11 @@ class AppWindow(object):
|
||||
def crewroletext(role):
|
||||
# Return translated crew role. Needs to be dynamic to allow for changing language.
|
||||
return {
|
||||
None : '',
|
||||
'Idle' : '',
|
||||
None: '',
|
||||
'Idle': '',
|
||||
'FighterCon': _('Fighter'), # Multicrew role
|
||||
'FireCon' : _('Gunner'), # Multicrew role
|
||||
'FlightCon' : _('Helm'), # Multicrew role
|
||||
'FireCon': _('Gunner'), # Multicrew role
|
||||
'FlightCon': _('Helm'), # Multicrew role
|
||||
}.get(role, role)
|
||||
|
||||
while True:
|
||||
@ -641,8 +649,8 @@ class AppWindow(object):
|
||||
self.ship_label['text'] = _('Ship') + ':' # Main window
|
||||
self.ship.configure(
|
||||
text=monitor.state['ShipName']
|
||||
or companion.ship_map.get(monitor.state['ShipType'], monitor.state['ShipType'])
|
||||
or '',
|
||||
or companion.ship_map.get(monitor.state['ShipType'], monitor.state['ShipType'])
|
||||
or '',
|
||||
url=self.shipyard_url)
|
||||
else:
|
||||
self.cmdr['text'] = ''
|
||||
@ -935,7 +943,8 @@ class AppWindow(object):
|
||||
def onexit(self, event=None):
|
||||
# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
|
||||
if platform != 'darwin' or self.w.winfo_rooty() > 0:
|
||||
config.set('geometry', '+{1}+{2}'.format(*self.w.geometry().split('+')))
|
||||
x, y = self.w.geometry().split('+')[1:3] # e.g. '212x170+2881+1267'
|
||||
config.set('geometry', f'+{x}+{y}')
|
||||
self.w.withdraw() # Following items can take a few seconds, so hide the main window while they happen
|
||||
protocolhandler.close()
|
||||
hotkeymgr.unregister()
|
||||
@ -987,13 +996,13 @@ def enforce_single_instance() -> None:
|
||||
# Ensure only one copy of the app is running under this user account. OSX does this automatically. Linux TODO.
|
||||
if platform == 'win32':
|
||||
import ctypes
|
||||
from ctypes.wintypes import HWND, LPWSTR, LPCWSTR, INT, BOOL, LPARAM
|
||||
from ctypes.wintypes import BOOL, HWND, INT, LPARAM, LPCWSTR, LPWSTR
|
||||
|
||||
EnumWindows = ctypes.windll.user32.EnumWindows # noqa: N806
|
||||
GetClassName = ctypes.windll.user32.GetClassNameW # noqa: N806
|
||||
GetClassName.argtypes = [HWND, LPWSTR, ctypes.c_int] # noqa: N806
|
||||
GetClassName.argtypes = [HWND, LPWSTR, ctypes.c_int]
|
||||
GetWindowText = ctypes.windll.user32.GetWindowTextW # noqa: N806
|
||||
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int] # noqa: N806
|
||||
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int]
|
||||
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW # noqa: N806
|
||||
GetProcessHandleFromHwnd = ctypes.windll.oleacc.GetProcessHandleFromHwnd # noqa: N806
|
||||
|
||||
@ -1076,11 +1085,6 @@ if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
from EDMCLogging import edmclogger, logger, logging
|
||||
# isort: off
|
||||
from logging import trace, TRACE # type: ignore # noqa: F401
|
||||
# isort: on
|
||||
|
||||
if args.trace:
|
||||
logger.setLevel(logging.TRACE)
|
||||
edmclogger.set_channels_loglevel(logging.TRACE)
|
||||
|
Loading…
x
Reference in New Issue
Block a user