mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-16 09:10:35 +03:00
EDMarketConnector: Pass on docstrings & Misc.
* Removed a couple of E501 ignores tagged as now un-necessary.
This commit is contained in:
parent
3e6998cfbe
commit
8a3fa50c97
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Entry point for the main GUI application."""
|
||||
|
||||
import argparse
|
||||
import html
|
||||
@ -271,6 +272,8 @@ SHIPYARD_HTML_TEMPLATE = """
|
||||
|
||||
|
||||
class AppWindow(object):
|
||||
"""Define the main application window."""
|
||||
|
||||
# Tkinter Event types
|
||||
EVENT_KEYPRESS = 2
|
||||
EVENT_BUTTON = 4
|
||||
@ -294,7 +297,7 @@ class AppWindow(object):
|
||||
self.w.wm_iconbitmap(default='EDMarketConnector.ico')
|
||||
else:
|
||||
self.w.tk.call('wm', 'iconphoto', self.w, '-default',
|
||||
tk.PhotoImage(file=join(config.respath, 'EDMarketConnector.png'))) # noqa: E501
|
||||
tk.PhotoImage(file=join(config.respath, 'EDMarketConnector.png')))
|
||||
self.theme_icon = tk.PhotoImage(
|
||||
data='R0lGODlhFAAQAMZQAAoKCQoKCgsKCQwKCQsLCgwLCg4LCQ4LCg0MCg8MCRAMCRANChINCREOChIOChQPChgQChgRCxwTCyYVCSoXCS0YCTkdCTseCT0fCTsjDU0jB0EnDU8lB1ElB1MnCFIoCFMoCEkrDlkqCFwrCGEuCWIuCGQvCFs0D1w1D2wyCG0yCF82D182EHE0CHM0CHQ1CGQ5EHU2CHc3CHs4CH45CIA6CIE7CJdECIdLEolMEohQE5BQE41SFJBTE5lUE5pVE5RXFKNaFKVbFLVjFbZkFrxnFr9oFsNqFsVrF8RsFshtF89xF9NzGNh1GNl2GP+KG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH5BAEKAH8ALAAAAAAUABAAAAeegAGCgiGDhoeIRDiIjIZGKzmNiAQBQxkRTU6am0tPCJSGShuSAUcLoIIbRYMFra4FAUgQAQCGJz6CDQ67vAFJJBi0hjBBD0w9PMnJOkAiJhaIKEI7HRoc19ceNAolwbWDLD8uAQnl5ga1I9CHEjEBAvDxAoMtFIYCBy+kFDKHAgM3ZtgYSLAGgwkp3pEyBOJCC2ELB31QATGioAoVAwEAOw==') # noqa: E501
|
||||
self.theme_minimize = tk.BitmapImage(
|
||||
@ -346,7 +349,7 @@ class AppWindow(object):
|
||||
self.button.grid(row=row, columnspan=2, sticky=tk.NSEW)
|
||||
self.theme_button.grid(row=row, columnspan=2, sticky=tk.NSEW)
|
||||
theme.register_alternate((self.button, self.theme_button, self.theme_button),
|
||||
{'row': row, 'columnspan': 2, 'sticky': tk.NSEW}) # noqa: E501
|
||||
{'row': row, 'columnspan': 2, 'sticky': tk.NSEW})
|
||||
self.status.grid(columnspan=2, sticky=tk.EW)
|
||||
self.button.bind('<Button-1>', self.getandsend)
|
||||
theme.button_bind(self.theme_button, self.getandsend)
|
||||
@ -540,8 +543,8 @@ class AppWindow(object):
|
||||
|
||||
self.postprefs(False) # Companion login happens in callback from monitor
|
||||
|
||||
# callback after the Preferences dialog is applied
|
||||
def postprefs(self, dologin=True):
|
||||
"""Perform necessary actions after the Preferences dialog is applied."""
|
||||
self.prefsdialog = None
|
||||
self.set_labels() # in case language has changed
|
||||
|
||||
@ -563,8 +566,8 @@ class AppWindow(object):
|
||||
if dologin and monitor.cmdr:
|
||||
self.login() # Login if not already logged in with this Cmdr
|
||||
|
||||
# set main window labels, e.g. after language change
|
||||
def set_labels(self):
|
||||
"""Set main window labels, e.g. after language change."""
|
||||
self.cmdr_label['text'] = _('Cmdr') + ':' # Main window
|
||||
# Multicrew role label in main window
|
||||
self.ship_label['text'] = (monitor.state['Captain'] and _('Role') or _('Ship')) + ':' # Main window
|
||||
@ -608,35 +611,50 @@ class AppWindow(object):
|
||||
self.edit_menu.entryconfigure(0, label=_('Copy')) # As in Copy and Paste
|
||||
|
||||
def login(self):
|
||||
"""Initiate CAPI/Frontier login and set other necessary state."""
|
||||
if not self.status['text']:
|
||||
self.status['text'] = _('Logging in...')
|
||||
|
||||
self.button['state'] = self.theme_button['state'] = tk.DISABLED
|
||||
|
||||
if platform == 'darwin':
|
||||
self.view_menu.entryconfigure(0, state=tk.DISABLED) # Status
|
||||
self.file_menu.entryconfigure(0, state=tk.DISABLED) # Save Raw Data
|
||||
|
||||
else:
|
||||
self.file_menu.entryconfigure(0, state=tk.DISABLED) # Status
|
||||
self.file_menu.entryconfigure(1, state=tk.DISABLED) # Save Raw Data
|
||||
|
||||
self.w.update_idletasks()
|
||||
try:
|
||||
if companion.session.login(monitor.cmdr, monitor.is_beta):
|
||||
# Successfully authenticated with the Frontier website
|
||||
self.status['text'] = _('Authentication successful')
|
||||
|
||||
if platform == 'darwin':
|
||||
self.view_menu.entryconfigure(0, state=tk.NORMAL) # Status
|
||||
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Save Raw Data
|
||||
|
||||
else:
|
||||
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Status
|
||||
self.file_menu.entryconfigure(1, state=tk.NORMAL) # Save Raw Data
|
||||
|
||||
except (companion.CredentialsError, companion.ServerError, companion.ServerLagging) as e:
|
||||
self.status['text'] = str(e)
|
||||
|
||||
except Exception as e:
|
||||
logger.debug('Frontier CAPI Auth', exc_info=e)
|
||||
self.status['text'] = str(e)
|
||||
|
||||
self.cooldown()
|
||||
|
||||
def getandsend(self, event=None, retrying=False): # noqa: C901
|
||||
def getandsend(self, event=None, retrying=False):
|
||||
"""
|
||||
Perform CAPI data retrieval and associated actions.
|
||||
|
||||
This can be triggered by hitting the main UI 'Update' button,
|
||||
automatically on docking, or due to a retry.
|
||||
"""
|
||||
auto_update = not event
|
||||
play_sound = (auto_update or int(event.type) == self.EVENT_VIRTUAL) and not config.getint('hotkey_mute')
|
||||
play_bad = False
|
||||
@ -695,7 +713,6 @@ class AppWindow(object):
|
||||
raise companion.ServerLagging()
|
||||
|
||||
else:
|
||||
|
||||
if __debug__: # Recording
|
||||
if isdir('dump'):
|
||||
with open('dump/{system}{station}.{timestamp}.json'.format(
|
||||
@ -731,19 +748,23 @@ class AppWindow(object):
|
||||
# but the server hosting the Companion API hasn't caught up
|
||||
self.status['text'] = _("You're not docked at a station!")
|
||||
play_bad = True
|
||||
|
||||
# Ignore possibly missing shipyard info
|
||||
elif (config.getint('output') & config.OUT_MKT_EDDN) \
|
||||
and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')):
|
||||
if not self.status['text']:
|
||||
self.status['text'] = _("Station doesn't have anything!")
|
||||
|
||||
elif not data['lastStarport'].get('commodities'):
|
||||
if not self.status['text']:
|
||||
self.status['text'] = _("Station doesn't have a market!")
|
||||
|
||||
elif config.getint('output') & (config.OUT_MKT_CSV | config.OUT_MKT_TD):
|
||||
# Fixup anomalies in the commodity data
|
||||
fixed = companion.fixup(data)
|
||||
if config.getint('output') & config.OUT_MKT_CSV:
|
||||
commodity.export(fixed, COMMODITY_CSV)
|
||||
|
||||
if config.getint('output') & config.OUT_MKT_TD:
|
||||
td.export(fixed)
|
||||
|
||||
@ -754,6 +775,7 @@ class AppWindow(object):
|
||||
if retrying:
|
||||
self.status['text'] = str(e)
|
||||
play_bad = True
|
||||
|
||||
else:
|
||||
# Retry once if Companion server is unresponsive
|
||||
self.w.after(int(SERVER_RETRY * 1000), lambda: self.getandsend(event, True))
|
||||
@ -772,32 +794,44 @@ class AppWindow(object):
|
||||
|
||||
if not self.status['text']: # no errors
|
||||
self.status['text'] = strftime(_('Last updated at %H:%M:%S'), localtime(querytime))
|
||||
|
||||
if play_sound and play_bad:
|
||||
hotkeymgr.play_bad()
|
||||
|
||||
self.cooldown()
|
||||
|
||||
# TODO: This has no users other than itself.
|
||||
def retry_for_shipyard(self, tries):
|
||||
# Try again to get shipyard data and send to EDDN. Don't report errors if can't get or send the data.
|
||||
"""
|
||||
Try again to get shipyard data and send to EDDN.
|
||||
|
||||
Don't report errors if can't get or send the data.
|
||||
"""
|
||||
try:
|
||||
data = companion.session.station()
|
||||
if data['commander'].get('docked'):
|
||||
if data.get('lastStarport', {}).get('ships'):
|
||||
report = 'Success'
|
||||
|
||||
else:
|
||||
report = 'Failure'
|
||||
|
||||
else:
|
||||
report = 'Undocked!'
|
||||
|
||||
logger.debug(f'Retry for shipyard - {report}')
|
||||
if not data['commander'].get('docked'):
|
||||
# might have un-docked while we were waiting for retry in which case station data is unreliable
|
||||
pass
|
||||
|
||||
elif (data.get('lastSystem', {}).get('name') == monitor.system and
|
||||
data.get('lastStarport', {}).get('name') == monitor.station and
|
||||
data.get('lastStarport', {}).get('ships', {}).get('shipyard_list')):
|
||||
self.eddn.export_shipyard(data, monitor.is_beta)
|
||||
|
||||
elif tries > 1: # bogus data - retry
|
||||
self.w.after(int(SERVER_RETRY * 1000), lambda: self.retry_for_shipyard(tries - 1))
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@ -925,7 +959,13 @@ class AppWindow(object):
|
||||
|
||||
# cAPI auth
|
||||
def auth(self, event=None):
|
||||
logger.debug('Received "<<CompanionAuthEvent>>')
|
||||
"""
|
||||
Handle Frontier auth callback.
|
||||
|
||||
This is the callback function for the CompanionAuthEvent Tk event.
|
||||
It is triggered by the event() function of class GenericProtocolHandler
|
||||
in protocol.py.
|
||||
"""
|
||||
try:
|
||||
companion.session.auth_callback()
|
||||
# Successfully authenticated with the Frontier website
|
||||
@ -947,8 +987,12 @@ class AppWindow(object):
|
||||
|
||||
self.cooldown()
|
||||
|
||||
# Handle Status event
|
||||
def dashboard_event(self, event):
|
||||
"""
|
||||
Handle DashBoardEvent tk event.
|
||||
|
||||
Event is sent by code in dashboard.py.
|
||||
"""
|
||||
entry = dashboard.status
|
||||
if entry:
|
||||
# Currently we don't do anything with these events
|
||||
@ -958,8 +1002,8 @@ class AppWindow(object):
|
||||
if not config.getint('hotkey_mute'):
|
||||
hotkeymgr.play_bad()
|
||||
|
||||
# Display asynchronous error from plugin
|
||||
def plugin_error(self, event=None):
|
||||
"""Display asynchronous error from plugin."""
|
||||
if plug.last_error.get('msg'):
|
||||
self.status['text'] = plug.last_error['msg']
|
||||
self.w.update_idletasks()
|
||||
@ -967,6 +1011,7 @@ class AppWindow(object):
|
||||
hotkeymgr.play_bad()
|
||||
|
||||
def shipyard_url(self, shipname):
|
||||
"""Despatch a ship URL to the configured handler."""
|
||||
if not bool(config.getint("use_alt_shipyard_open")):
|
||||
return plug.invoke(config.get('shipyard_provider'), 'EDSY', 'shipyard_url', monitor.ship(), monitor.is_beta)
|
||||
|
||||
@ -985,17 +1030,21 @@ class AppWindow(object):
|
||||
return f'file://localhost/{file_name}'
|
||||
|
||||
def system_url(self, system):
|
||||
"""Despatch a system URL to the configured handler."""
|
||||
return plug.invoke(config.get('system_provider'), 'EDSM', 'system_url', monitor.system)
|
||||
|
||||
def station_url(self, station):
|
||||
"""Despatch a station URL to the configured handler."""
|
||||
return plug.invoke(config.get('station_provider'), 'eddb', 'station_url', monitor.system, monitor.station)
|
||||
|
||||
def cooldown(self):
|
||||
"""Display and update the cooldown timer for 'Update' button."""
|
||||
if time() < self.holdofftime:
|
||||
# Update button in main window
|
||||
self.button['text'] = self.theme_button['text'] \
|
||||
= _('cooldown {SS}s').format(SS=int(self.holdofftime - time()))
|
||||
self.w.after(1000, self.cooldown)
|
||||
|
||||
else:
|
||||
self.button['text'] = self.theme_button['text'] = _('Update') # Update button in main window
|
||||
self.button['state'] = self.theme_button['state'] = (monitor.cmdr and
|
||||
@ -1005,29 +1054,37 @@ class AppWindow(object):
|
||||
tk.NORMAL or tk.DISABLED)
|
||||
|
||||
def ontop_changed(self, event=None):
|
||||
"""Set main window 'on top' state as appropriate."""
|
||||
config.set('always_ontop', self.always_ontop.get())
|
||||
self.w.wm_attributes('-topmost', self.always_ontop.get())
|
||||
|
||||
def copy(self, event=None):
|
||||
"""Copy system, and possible station, name to clipboard."""
|
||||
if monitor.system:
|
||||
self.w.clipboard_clear()
|
||||
self.w.clipboard_append(monitor.station and f'{monitor.system},{monitor.station}' or monitor.system)
|
||||
|
||||
def help_general(self, event=None):
|
||||
"""Open Wiki Help page in browser."""
|
||||
webbrowser.open('https://github.com/EDCD/EDMarketConnector/wiki')
|
||||
|
||||
def help_privacy(self, event=None):
|
||||
"""Open Wiki Privacy page in browser."""
|
||||
webbrowser.open('https://github.com/EDCD/EDMarketConnector/wiki/Privacy-Policy')
|
||||
|
||||
def help_releases(self, event=None):
|
||||
"""Open Releases page in browser."""
|
||||
webbrowser.open('https://github.com/EDCD/EDMarketConnector/releases')
|
||||
|
||||
class HelpAbout(tk.Toplevel):
|
||||
"""The applications Help > About popup."""
|
||||
|
||||
showing = False
|
||||
|
||||
def __init__(self, parent):
|
||||
if self.__class__.showing:
|
||||
return
|
||||
|
||||
self.__class__.showing = True
|
||||
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
@ -1100,14 +1157,17 @@ class AppWindow(object):
|
||||
logger.info(f'Current version is {appversion}')
|
||||
|
||||
def apply(self):
|
||||
"""Close the window."""
|
||||
self._destroy()
|
||||
|
||||
def _destroy(self):
|
||||
"""Set parent window's topmost appropriately as we close."""
|
||||
self.parent.wm_attributes('-topmost', config.getint('always_ontop') and 1 or 0)
|
||||
self.destroy()
|
||||
self.__class__.showing = False
|
||||
|
||||
def save_raw(self):
|
||||
"""Save newly acquired CAPI data in the configured file."""
|
||||
self.status['text'] = _('Fetching data...')
|
||||
self.w.update_idletasks()
|
||||
|
||||
@ -1115,12 +1175,16 @@ class AppWindow(object):
|
||||
data = companion.session.station()
|
||||
self.status['text'] = ''
|
||||
default_extension: str = ''
|
||||
|
||||
if platform == 'darwin':
|
||||
default_extension = '.json'
|
||||
|
||||
last_system: str = data.get("lastSystem", {}).get("name", "Unknown")
|
||||
last_starport: str = ''
|
||||
|
||||
if data['commander'].get('docked'):
|
||||
last_starport = '.' + data.get('lastStarport', {}).get('name', 'Unknown')
|
||||
|
||||
timestamp: str = strftime('%Y-%m-%dT%H.%M.%S', localtime())
|
||||
f = tkinter.filedialog.asksaveasfilename(parent=self.w,
|
||||
defaultextension=default_extension,
|
||||
@ -1134,15 +1198,16 @@ class AppWindow(object):
|
||||
indent=2,
|
||||
sort_keys=True,
|
||||
separators=(',', ': ')).encode('utf-8'))
|
||||
|
||||
except companion.ServerError as e:
|
||||
self.status['text'] = str(e)
|
||||
|
||||
except Exception as e:
|
||||
logger.debug('"other" exception', exc_info=e)
|
||||
self.status['text'] = str(e)
|
||||
|
||||
def onexit(self, event=None):
|
||||
config.set_shutdown() # Signal we're in shutdown now.
|
||||
|
||||
"""Application shutdown procedure."""
|
||||
# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
|
||||
if platform != 'darwin' or self.w.winfo_rooty() > 0:
|
||||
x, y = self.w.geometry().split('+')[1:3] # e.g. '212x170+2881+1267'
|
||||
@ -1189,50 +1254,129 @@ class AppWindow(object):
|
||||
logger.info('Destroying app window...')
|
||||
self.w.destroy()
|
||||
|
||||
logger.info('Done.')
|
||||
|
||||
def drag_start(self, event) -> None:
|
||||
def drag_start(self, event):
|
||||
"""Initiate dragging the window."""
|
||||
self.drag_offset = (event.x_root - self.w.winfo_rootx(), event.y_root - self.w.winfo_rooty())
|
||||
|
||||
def drag_continue(self, event):
|
||||
"""Continued handling of window drag."""
|
||||
if self.drag_offset:
|
||||
offset_x = event.x_root - self.drag_offset[0]
|
||||
offset_y = event.y_root - self.drag_offset[1]
|
||||
self.w.geometry(f'+{offset_x:d}+{offset_y:d}')
|
||||
|
||||
def drag_end(self, event):
|
||||
"""Handle end of window dragging."""
|
||||
self.drag_offset = None
|
||||
|
||||
def oniconify(self, event=None):
|
||||
"""Handle iconification of the application."""
|
||||
self.w.overrideredirect(0) # Can't iconize while overrideredirect
|
||||
self.w.iconify()
|
||||
self.w.update_idletasks() # Size and windows styles get recalculated here
|
||||
self.w.wait_visibility() # Need main window to be re-created before returning
|
||||
theme.active = None # So theme will be re-applied on map
|
||||
|
||||
# TODO: Confirm this is unused and remove.
|
||||
def onmap(self, event=None):
|
||||
"""Perform a now unused function."""
|
||||
if event.widget == self.w:
|
||||
theme.apply(self.w)
|
||||
|
||||
def onenter(self, event=None):
|
||||
"""Handle when our window gains focus."""
|
||||
# TODO: This assumes that 1) transparent is at least 2, 2) there are
|
||||
# no new themes added after that.
|
||||
if config.getint('theme') > 1:
|
||||
self.w.attributes("-transparentcolor", '')
|
||||
self.blank_menubar.grid_remove()
|
||||
self.theme_menubar.grid(row=0, columnspan=2, sticky=tk.NSEW)
|
||||
|
||||
def onleave(self, event=None):
|
||||
"""Handle when our window loses focus."""
|
||||
# TODO: This assumes that 1) transparent is at least 2, 2) there are
|
||||
# no new themes added after that.
|
||||
if config.getint('theme') > 1 and event.widget == self.w:
|
||||
self.w.attributes("-transparentcolor", 'grey4')
|
||||
self.theme_menubar.grid_remove()
|
||||
self.blank_menubar.grid(row=0, columnspan=2, sticky=tk.NSEW)
|
||||
|
||||
|
||||
def enforce_single_instance() -> None:
|
||||
"""
|
||||
Ensure only one copy of the app is running under this user account.
|
||||
|
||||
OSX does this automatically.
|
||||
"""
|
||||
# TODO: Linux implementation
|
||||
if platform == 'win32':
|
||||
import ctypes
|
||||
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]
|
||||
GetWindowText = ctypes.windll.user32.GetWindowTextW # noqa: N806
|
||||
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int]
|
||||
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW # noqa: N806
|
||||
GetProcessHandleFromHwnd = ctypes.windll.oleacc.GetProcessHandleFromHwnd # noqa: N806
|
||||
|
||||
SW_RESTORE = 9 # noqa: N806
|
||||
SetForegroundWindow = ctypes.windll.user32.SetForegroundWindow # noqa: N806
|
||||
ShowWindow = ctypes.windll.user32.ShowWindow # noqa: N806
|
||||
ShowWindowAsync = ctypes.windll.user32.ShowWindowAsync # noqa: N806
|
||||
|
||||
COINIT_MULTITHREADED = 0 # noqa: N806,F841
|
||||
COINIT_APARTMENTTHREADED = 0x2 # noqa: N806
|
||||
COINIT_DISABLE_OLE1DDE = 0x4 # noqa: N806
|
||||
CoInitializeEx = ctypes.windll.ole32.CoInitializeEx # noqa: N806
|
||||
|
||||
ShellExecute = ctypes.windll.shell32.ShellExecuteW # noqa: N806
|
||||
ShellExecute.argtypes = [HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT]
|
||||
|
||||
def window_title(h):
|
||||
if h:
|
||||
text_length = GetWindowTextLength(h) + 1
|
||||
buf = ctypes.create_unicode_buffer(text_length)
|
||||
if GetWindowText(h, buf, text_length):
|
||||
return buf.value
|
||||
|
||||
return None
|
||||
|
||||
@ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
|
||||
def enumwindowsproc(window_handle, l_param):
|
||||
# class name limited to 256 - https://msdn.microsoft.com/en-us/library/windows/desktop/ms633576
|
||||
cls = ctypes.create_unicode_buffer(257)
|
||||
if GetClassName(window_handle, cls, 257) \
|
||||
and cls.value == 'TkTopLevel' \
|
||||
and window_title(window_handle) == applongname \
|
||||
and GetProcessHandleFromHwnd(window_handle):
|
||||
# If GetProcessHandleFromHwnd succeeds then the app is already running as this user
|
||||
if len(sys.argv) > 1 and sys.argv[1].startswith(protocolhandler.redirect):
|
||||
# Browser invoked us directly with auth response. Forward the response to the other app instance.
|
||||
CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
|
||||
# Wait for it to be responsive to avoid ShellExecute recursing
|
||||
ShowWindow(window_handle, SW_RESTORE)
|
||||
ShellExecute(0, None, sys.argv[1], None, None, SW_RESTORE)
|
||||
|
||||
else:
|
||||
ShowWindowAsync(window_handle, SW_RESTORE)
|
||||
SetForegroundWindow(window_handle)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
return True
|
||||
|
||||
EnumWindows(enumwindowsproc, 0)
|
||||
|
||||
|
||||
def test_logging():
|
||||
"""Simple test of top level logging."""
|
||||
logger.debug('Test from EDMarketConnector.py top-level test_logging()')
|
||||
|
||||
|
||||
def log_locale(prefix: str) -> None:
|
||||
"""Log all of the current local settings."""
|
||||
logger.debug(f'''Locale: {prefix}
|
||||
Locale LC_COLLATE: {locale.getlocale(locale.LC_COLLATE)}
|
||||
Locale LC_CTYPE: {locale.getlocale(locale.LC_CTYPE)}
|
||||
@ -1311,8 +1455,10 @@ sys.path: {sys.path}'''
|
||||
# test_logging()
|
||||
|
||||
class A(object):
|
||||
"""Simple top-level class."""
|
||||
|
||||
class B(object):
|
||||
"""Simple second-level class."""
|
||||
|
||||
def __init__(self):
|
||||
logger.debug('A call from A.B.__init__')
|
||||
@ -1352,6 +1498,7 @@ sys.path: {sys.path}'''
|
||||
app = AppWindow(root)
|
||||
|
||||
def messagebox_not_py3():
|
||||
"""Display message about plugins not updated for Python 3.x."""
|
||||
plugins_not_py3_last = config.getint('plugins_not_py3_last') or 0
|
||||
if (plugins_not_py3_last + 86400) < int(time()) and len(plug.PLUGINS_not_py3):
|
||||
# Yes, this is horribly hacky so as to be sure we match the key
|
||||
|
Loading…
x
Reference in New Issue
Block a user