Skip to content

Commit

Permalink
Merge branch 'develop' into enhancement/806/system-profiler
Browse files Browse the repository at this point in the history
  • Loading branch information
Rixxan authored May 14, 2024
2 parents 2516d7b + 95fa67c commit 99a0cc9
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 77 deletions.
83 changes: 38 additions & 45 deletions EDMarketConnector.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
import argparse
import html
import locale
import os
import pathlib
import queue
import re
import signal
import subprocess
import sys
import threading
import webbrowser
import tempfile
from os import chdir, environ, path
from time import localtime, strftime, time
from typing import TYPE_CHECKING, Any, Literal
Expand Down Expand Up @@ -47,8 +50,6 @@
# output until after this redirect is done, if needed.
if getattr(sys, 'frozen', False):
# By default py2exe tries to write log to dirname(sys.executable) which fails when installed
import tempfile

# unbuffered not allowed for text in python3, so use `1 for line buffering
log_file_path = path.join(tempfile.gettempdir(), f'{appname}.log')
sys.stdout = sys.stderr = open(log_file_path, mode='wt', buffering=1) # Do NOT use WITH here.
Expand Down Expand Up @@ -336,29 +337,13 @@ def enumwindowsproc(window_handle, l_param): # noqa: CCR001

def already_running_popup():
"""Create the "already running" popup."""
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
# Check for CL arg that suppresses this popup.
if args.suppress_dupe_process_popup:
sys.exit(0)

root = tk.Tk(className=appname.lower())

frame = tk.Frame(root)
frame.grid(row=1, column=0, sticky=tk.NSEW)

label = tk.Label(frame, text='An EDMarketConnector.exe process was already running, exiting.')
label.grid(row=1, column=0, sticky=tk.NSEW)

button = ttk.Button(frame, text='OK', command=lambda: sys.exit(0))
button.grid(row=2, column=0, sticky=tk.S)

try:
root.mainloop()
except KeyboardInterrupt:
logger.info("Ctrl+C Detected, Attempting Clean Shutdown")
sys.exit()
logger.info('Exiting')
messagebox.showerror(title=appname, message="An EDMarketConnector process was already running, exiting.")
sys.exit(0)

journal_lock = JournalLock()
locked = journal_lock.obtain_lock()
Expand Down Expand Up @@ -432,25 +417,10 @@ def already_running_popup():
from l10n import translations as tr
from monitor import monitor
from theme import theme
from ttkHyperlinkLabel import HyperlinkLabel
from ttkHyperlinkLabel import HyperlinkLabel, SHIPYARD_HTML_TEMPLATE

SERVER_RETRY = 5 # retry pause for Companion servers [s]

SHIPYARD_HTML_TEMPLATE = """
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="refresh" content="0; url={link}">
<title>Redirecting you to your {ship_name} at {provider_name}...</title>
</head>
<body>
<a href="{link}">
You should be redirected to your {ship_name} at {provider_name} shortly...
</a>
</body>
</html>
"""


class AppWindow:
"""Define the main application window."""
Expand Down Expand Up @@ -515,13 +485,13 @@ def open_window(systray: 'SysTrayIcon') -> None:
self.cmdr_label = tk.Label(frame, name='cmdr_label')
self.cmdr = tk.Label(frame, compound=tk.RIGHT, anchor=tk.W, name='cmdr')
self.ship_label = tk.Label(frame, name='ship_label')
self.ship = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.shipyard_url, name='ship')
self.ship = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.shipyard_url, name='ship', popup_copy=True)
self.suit_label = tk.Label(frame, name='suit_label')
self.suit = tk.Label(frame, compound=tk.RIGHT, anchor=tk.W, name='suit')
self.system_label = tk.Label(frame, name='system_label')
self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.system_url, popup_copy=True, name='system')
self.station_label = tk.Label(frame, name='station_label')
self.station = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.station_url, name='station')
self.station = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.station_url, name='station', popup_copy=True)
# system and station text is set/updated by the 'provider' plugins
# edsm and inara. Look for:
#
Expand Down Expand Up @@ -648,8 +618,9 @@ def open_window(systray: 'SysTrayIcon') -> None:
self.help_menu.add_command(command=lambda: self.updater.check_for_updates()) # Check for Updates...
# About E:D Market Connector
self.help_menu.add_command(command=lambda: not self.HelpAbout.showing and self.HelpAbout(self.w))
self.help_menu.add_command(command=prefs.help_open_log_folder) # Open Log Folder
self.help_menu.add_command(command=prefs.help_open_system_profiler) # Open Log Folder
logfile_loc = pathlib.Path(tempfile.gettempdir()) / appname
self.help_menu.add_command(command=lambda: prefs.open_folder(logfile_loc)) # Open Log Folder
self.help_menu.add_command(command=prefs.help_open_system_profiler) # Open Log Folde

self.menubar.add_cascade(menu=self.help_menu)
if sys.platform == 'win32':
Expand Down Expand Up @@ -1629,7 +1600,7 @@ def plugin_error(self, event=None) -> None:
hotkeymgr.play_bad()

def shipyard_url(self, shipname: str) -> str | None:
"""Despatch a ship URL to the configured handler."""
"""Dispatch a ship URL to the configured handler."""
if not (loadout := monitor.ship()):
logger.warning('No ship loadout, aborting.')
return ''
Expand All @@ -1656,13 +1627,13 @@ def shipyard_url(self, shipname: str) -> str | None:
return f'file://localhost/{file_name}'

def system_url(self, system: str) -> str | None:
"""Despatch a system URL to the configured handler."""
"""Dispatch a system URL to the configured handler."""
return plug.invoke(
config.get_str('system_provider', default='EDSM'), 'EDSM', 'system_url', monitor.state['SystemName']
)

def station_url(self, station: str) -> str | None:
"""Despatch a station URL to the configured handler."""
"""Dispatch a station URL to the configured handler."""
return plug.invoke(
config.get_str('station_provider', default='EDSM'), 'EDSM', 'station_url',
monitor.state['SystemName'], monitor.state['StationName']
Expand Down Expand Up @@ -2228,7 +2199,29 @@ def test_prop(self):
if theme.default_ui_scale is not None:
root.tk.call('tk', 'scaling', theme.default_ui_scale * float(ui_scale) / 100.0)

app = AppWindow(root)
try:
app = AppWindow(root)
except Exception as err:
logger.exception(f"EDMC Critical Error: {err}")
title = tr.tl("Error") # LANG: Generic error prefix
message = tr.tl( # LANG: EDMC Critical Error Notification
"EDSM encountered a critical error, and cannot recover. EDMC is shutting down for its own protection!"
)
err = f"{err.__class__.__name__}: {err}" # type: ignore # hijacking the existing exception detection
detail = tr.tl( # LANG: EDMC Critical Error Details
r"Here's what EDMC Detected:\r\n\r\n{ERR}\r\n\r\nDo you want to file a Bug Report on GitHub?"
).format(ERR=err)
detail = detail.replace('\\n', '\n')
detail = detail.replace('\\r', '\r')
msg = tk.messagebox.askyesno(
title=title, message=message, detail=detail, icon=tkinter.messagebox.ERROR, type=tkinter.messagebox.YESNO
)
if msg:
webbrowser.open(
"https://github.com/EDCD/EDMarketConnector/issues/new?"
"assignees=&labels=bug%2C+unconfirmed&projects=&template=bug_report.md&title="
)
os.kill(os.getpid(), signal.SIGTERM)

def messagebox_broken_plugins():
"""Display message about 'broken' plugins that failed to load."""
Expand Down
9 changes: 9 additions & 0 deletions L10n/en.template
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:508; */
"Error: unable to get token" = "Error: unable to get token";

/* EDMarketConnector.py: EDMC Critical Error Notification; */
"EDSM encountered a critical error, and cannot recover. EDMC is shutting down for its own protection!" = "EDSM encountered a critical error, and cannot recover. EDMC is shutting down for its own protection!";

/* EDMarketConnector.py: EDMC Critical Error Details; */
"Here's what EDMC Detected:\r\n\r\n{ERR}\r\n\r\nDo you want to file a Bug Report on GitHub?" = "Here's what EDMC Detected:\r\n\r\n{ERR}\r\n\r\nDo you want to file a Bug Report on GitHub?";

/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */
"Frontier CAPI down for maintenance" = "Frontier CAPI down for maintenance";

Expand Down Expand Up @@ -785,3 +791,6 @@

/* myNotebook.py: Can't Paste Images or Files in Text; */
"Cannot paste non-text content." = "Cannot paste non-text content.";

/* ttkHyperlinkLabel.py: Open Element In Selected Provider; */
"Open in {URL}" = "Open in {URL}";
6 changes: 3 additions & 3 deletions monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import ctypes
from ctypes.wintypes import BOOL, HWND, LPARAM, LPWSTR

from watchdog.events import FileCreatedEvent, FileSystemEventHandler
from watchdog.events import FileSystemEventHandler, FileSystemEvent
from watchdog.observers import Observer
from watchdog.observers.api import BaseObserver

Expand All @@ -60,7 +60,7 @@
FileSystemEventHandler = object # dummy
if TYPE_CHECKING:
# this isn't ever used, but this will make type checking happy
from watchdog.events import FileCreatedEvent
from watchdog.events import FileSystemEvent
from watchdog.observers import Observer
from watchdog.observers.api import BaseObserver

Expand Down Expand Up @@ -346,7 +346,7 @@ def running(self) -> bool:
"""
return bool(self.thread and self.thread.is_alive())

def on_created(self, event: 'FileCreatedEvent') -> None:
def on_created(self, event: 'FileSystemEvent') -> None:
"""Watchdog callback when, e.g. client (re)started."""
if not event.is_directory and self._RE_LOGFILE.search(basename(event.src_path)):

Expand Down
4 changes: 2 additions & 2 deletions myNotebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def paste(self) -> None:
class Entry(EntryMenu):
"""Custom ttk.Entry class to fix some display issues."""

# DEPRECATED: Migrate to EntryMenu. Will remove in 5.12 or later.
# DEPRECATED: Migrate to EntryMenu. Will remove in 6.0 or later.
def __init__(self, master: ttk.Frame | None = None, **kw):
EntryMenu.__init__(self, master, **kw)

Expand All @@ -139,7 +139,7 @@ def __init__(self, master: ttk.Frame | None = None, **kw):
class ColoredButton(tk.Button):
"""Custom tk.Button class to fix some display issues."""

# DEPRECATED: Migrate to tk.Button. Will remove in 5.12 or later.
# DEPRECATED: Migrate to tk.Button. Will remove in 6.0 or later.
def __init__(self, master: ttk.Frame | None = None, **kw):
tk.Button.__init__(self, master, **kw)

Expand Down
39 changes: 21 additions & 18 deletions plugins/inara.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,23 +550,6 @@ def journal_entry( # noqa: C901, CCR001

# Ship change
if event_name == 'Loadout' and this.shipswap:
cur_ship = {
'shipType': state['ShipType'],
'shipGameID': state['ShipID'],
'shipName': state['ShipName'], # Can be None
'shipIdent': state['ShipIdent'], # Can be None
'isCurrentShip': True,
}

if state['HullValue']:
cur_ship['shipHullValue'] = state['HullValue']

if state['ModulesValue']:
cur_ship['shipModulesValue'] = state['ModulesValue']

cur_ship['shipRebuyCost'] = state['Rebuy']
new_add_event('setCommanderShip', entry['timestamp'], cur_ship)

this.loadout = make_loadout(state)
new_add_event('setCommanderShipLoadout', entry['timestamp'], this.loadout)
this.shipswap = False
Expand Down Expand Up @@ -854,7 +837,7 @@ def journal_entry( # noqa: C901, CCR001
for ship in this.fleet:
new_add_event('setCommanderShip', entry['timestamp'], ship)
# Loadout
if event_name == 'Loadout' and not this.newsession:
if event_name == 'Loadout':
loadout = make_loadout(state)
if this.loadout != loadout:
this.loadout = loadout
Expand All @@ -868,6 +851,26 @@ def journal_entry( # noqa: C901, CCR001

new_add_event('setCommanderShipLoadout', entry['timestamp'], this.loadout)

cur_ship = {
'shipType': state['ShipType'],
'shipGameID': state['ShipID'],
'shipName': state['ShipName'], # Can be None
'shipIdent': state['ShipIdent'], # Can be None
'isCurrentShip': True,
'shipMaxJumpRange': entry['MaxJumpRange'],
'shipCargoCapacity': entry['CargoCapacity']
}
if state['HullValue']:
cur_ship['shipHullValue'] = state['HullValue']

if state['ModulesValue']:
cur_ship['shipModulesValue'] = state['ModulesValue']

if state['Rebuy']:
cur_ship['shipRebuyCost'] = state['Rebuy']

new_add_event('setCommanderShip', entry['timestamp'], cur_ship)

# Stored modules
if event_name == 'StoredModules':
items = {mod['StorageSlot']: mod for mod in entry['Items']} # Impose an order
Expand Down
23 changes: 16 additions & 7 deletions prefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import sys
import tempfile
import tkinter as tk
import webbrowser
from os import system
from os.path import expanduser, expandvars, join, normpath
from tkinter import colorchooser as tkColorChooser # type: ignore # noqa: N812
Expand Down Expand Up @@ -41,14 +40,21 @@

def help_open_log_folder() -> None:
"""Open the folder logs are stored in."""
logfile_loc = pathlib.Path(tempfile.gettempdir())
logfile_loc /= f'{appname}'
logger.warning(
DeprecationWarning("This function is deprecated, use open_log_folder instead. "
"This function will be removed in 6.0 or later")
)
open_folder(pathlib.Path(tempfile.gettempdir()) / appname)


def open_folder(file: pathlib.Path) -> None:
"""Open the given file in the OS file explorer."""
if sys.platform.startswith('win'):
# On Windows, use the "start" command to open the folder
system(f'start "" "{logfile_loc}"')
system(f'start "" "{file}"')
elif sys.platform.startswith('linux'):
# On Linux, use the "xdg-open" command to open the folder
system(f'xdg-open "{logfile_loc}"')
system(f'xdg-open "{file}"')


def help_open_system_profiler() -> None:
Expand Down Expand Up @@ -307,6 +313,9 @@ def __init__(self, parent: tk.Tk, callback: Optional[Callable]):
):
self.geometry(f"+{position.left}+{position.top}")

# Set Log Directory
self.logfile_loc = pathlib.Path(tempfile.gettempdir()) / appname

def __setup_output_tab(self, root_notebook: ttk.Notebook) -> None:
output_frame = nb.Frame(root_notebook)
output_frame.columnconfigure(0, weight=1)
Expand Down Expand Up @@ -634,7 +643,7 @@ def __setup_config_tab(self, notebook: ttk.Notebook) -> None: # noqa: CCR001
config_frame,
# LANG: Label on button used to open a filesystem folder
text=tr.tl('Open Log Folder'), # Button that opens a folder in Explorer/Finder
command=lambda: help_open_log_folder()
command=lambda: open_folder(self.logfile_loc)
).grid(column=2, padx=self.PADX, pady=0, sticky=tk.NSEW, row=cur_row)

# Big spacer
Expand Down Expand Up @@ -895,7 +904,7 @@ def __setup_plugin_tab(self, notebook: ttk.Notebook) -> None: # noqa: CCR001
plugins_frame,
# LANG: Label on button used to open a filesystem folder
text=tr.tl('Open'), # Button that opens a folder in Explorer/Finder
command=lambda: webbrowser.open(f'file:///{config.plugin_dir_path}')
command=lambda: open_folder(config.plugin_dir_path)
).grid(column=1, padx=self.PADX, pady=self.PADY, sticky=tk.N, row=cur_row)

enabled_plugins = list(filter(lambda x: x.folder and x.module, plug.PLUGINS))
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
requests==2.31.0
pillow==10.3.0
watchdog==3.0.0
watchdog==4.0.0
infi.systray==0.1.12; sys_platform == 'win32'
semantic-version==2.10.0
Loading

0 comments on commit 99a0cc9

Please sign in to comment.