mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-05-20 17:11:32 +03:00
Merge branch 'stable' into releases
This commit is contained in:
commit
3019cea52e
45
ChangeLog.md
45
ChangeLog.md
@ -27,6 +27,51 @@ produce the Windows executables and installer.
|
||||
|
||||
---
|
||||
|
||||
Release 5.3.1
|
||||
===
|
||||
|
||||
This release addresses some issues with newer EDDN code which could cause
|
||||
erroneous alerts to the player, or sending of bad messages.
|
||||
|
||||
* EDDN: Cope with `ApproachSettlement` on login occurring before `Location`,
|
||||
such that we don't yet know the name of the star system the player is in.
|
||||
|
||||
Closes [#1484](https://github.com/EDCD/EDMarketConnector/pull/1484)
|
||||
|
||||
* EDDN: Cope with `ApproachSettlement` missing planetary coordinates on login
|
||||
at/near a settlement in Horizons.
|
||||
|
||||
Closes [#1476](https://github.com/EDCD/EDMarketConnector/pull/1476)
|
||||
|
||||
* EDDN: Change the `CodexEntry` "empty string" checks to only apply to those
|
||||
values where the schema enforces "must be at least one character".
|
||||
|
||||
This prevents the big 'CodexEntry had empty string, PLEASE ALERT THE EDMC
|
||||
DEVELOPERS' message from triggering on, e.g. `NearestDestination` being
|
||||
empty, which the schema allows.
|
||||
|
||||
Closes [#1481](https://github.com/EDCD/EDMarketConnector/issues/1481)
|
||||
|
||||
Plugin Developers
|
||||
---
|
||||
|
||||
* If you use a sub-class for a widget the core code will no longer break if
|
||||
your code raises an exception. e.g. a plugin was failing due to Python
|
||||
3.10 using `collections.abc` instead of `collections`, and the plugin's
|
||||
custom widget had a `configure()` method which was called by the core
|
||||
theme code on startup or theme change. This then caused the whole
|
||||
application UI to never show up on startup.
|
||||
|
||||
This also applies if you set up a button such that enter/leave on it, i.e.
|
||||
mouse in/out, causes the `theme.py` code for that to trigger.
|
||||
|
||||
So, now in such cases the main UI should actually show up, although your
|
||||
plugin's UI might look weird due to theming not being properly applied.
|
||||
|
||||
The plugin exception **WILL** be logged, at ERROR level.
|
||||
|
||||
---
|
||||
|
||||
Release 5.3.0
|
||||
===
|
||||
|
||||
|
@ -38,6 +38,8 @@ Please be sure to read the [Avoiding potential pitfalls](#avoiding-potential-pit
|
||||
section, else you might inadvertently cause issues for the core
|
||||
EDMarketConnector code including whole application crashes.
|
||||
|
||||
## Being aware of core application changes
|
||||
|
||||
It is highly advisable to ensure you are aware of all EDMarketConnector
|
||||
releases, including the pre-releases. The -beta and -rc changelogs will
|
||||
contain valuable information about any forthcoming changes that affect plugins.
|
||||
@ -55,6 +57,11 @@ The easiest way is:
|
||||
And, of course, either ensure you check your GitHub messages regularly, or
|
||||
have it set up to email you such notifications.
|
||||
|
||||
You should also keep an eye on [our GitHub Discussions](https://github.com/EDCD/EDMarketConnector/discussions)
|
||||
in case there are any proposed changes to EDMC plugin functionality. You can
|
||||
do this by ensuring 'Discussions' is also ticked when following the steps
|
||||
above to set up a 'Custom' watch on this repository.
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
@ -52,7 +52,7 @@ appcmdname = 'EDMC'
|
||||
# <https://semver.org/#semantic-versioning-specification-semver>
|
||||
# Major.Minor.Patch(-prerelease)(+buildmetadata)
|
||||
# NB: Do *not* import this, use the functions appversion() and appversion_nobuild()
|
||||
_static_appversion = '5.3.0'
|
||||
_static_appversion = '5.3.1'
|
||||
_cached_version: Optional[semantic_version.Version] = None
|
||||
copyright = '© 2015-2019 Jonathan Harris, 2020-2022 EDCD'
|
||||
|
||||
|
@ -829,7 +829,7 @@ class EDDN:
|
||||
|
||||
else:
|
||||
logger.warning("Neither this_coordinates or this.coordinates set, can't add StarPos")
|
||||
return 'No source for adding StarPos to approachsettlement/1 !'
|
||||
return 'No source for adding StarPos to EDDN message !'
|
||||
|
||||
return entry
|
||||
|
||||
@ -970,7 +970,9 @@ class EDDN:
|
||||
logger.warning(f'this.body_id was not set properly: "{this.body_id}" ({type(this.body_id)})')
|
||||
#######################################################################
|
||||
|
||||
for k, v in entry.items():
|
||||
# Check just the top-level strings with minLength=1 in the schema
|
||||
for k in ('System', 'Name', 'Region', 'Category', 'SubCategory'):
|
||||
v = entry[k]
|
||||
if v is None or isinstance(v, str) and v == '':
|
||||
logger.warning(f'post-processing entry contains entry["{k}"] = {v} {(type(v))}')
|
||||
# We should drop this message and VERY LOUDLY inform the
|
||||
@ -978,6 +980,13 @@ class EDDN:
|
||||
# raw Journal event that caused this.
|
||||
return 'CodexEntry had empty string, PLEASE ALERT THE EDMC DEVELOPERS'
|
||||
|
||||
# Also check traits
|
||||
if 'Traits' in entry:
|
||||
for v in entry['Traits']:
|
||||
if v is None or isinstance(v, str) and v == '':
|
||||
logger.warning(f'post-processing entry[\'Traits\'] contains {v} {(type(v))}\n{entry["Traits"]}\n')
|
||||
return 'CodexEntry Trait had empty string, PLEASE ALERT THE EDMC DEVELOPERS'
|
||||
|
||||
msg = {
|
||||
'$schemaRef': f'https://eddn.edcd.io/schemas/codexentry/1{"/test" if is_beta else ""}',
|
||||
'message': entry
|
||||
@ -1126,6 +1135,27 @@ class EDDN:
|
||||
# "event": "ApproachSettlement",
|
||||
# "timestamp": "2021-10-14T12:37:54Z"
|
||||
# }
|
||||
|
||||
#######################################################################
|
||||
# Bugs
|
||||
#######################################################################
|
||||
# WORKAROUND 3.8.0.404 | 2022-02-18: ApproachSettlement missing coords
|
||||
# As of Horizons ("gameversion":"3.8.0.404", "build":"r280105/r0 ")
|
||||
# if you log back in (certainly a game client restart) at a
|
||||
# Planetary Port, then the ApproachSettlement event written will be
|
||||
# missing the Latitude and Longitude.
|
||||
# Ref: https://github.com/EDCD/EDMarketConnector/issues/1476
|
||||
if any(
|
||||
k not in entry for k in ('Latitude', 'Longitude')
|
||||
):
|
||||
logger.debug(
|
||||
f'ApproachSettlement without at least one of Latitude or Longitude:\n{entry}\n'
|
||||
)
|
||||
# No need to alert the user, it will only annoy them
|
||||
return ""
|
||||
# WORKAROUND END
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
# Augmentations
|
||||
#######################################################################
|
||||
@ -1499,6 +1529,12 @@ def journal_entry( # noqa: C901, CCR001
|
||||
return this.eddn.export_journal_navroute(cmdr, is_beta, entry)
|
||||
|
||||
elif event_name == 'approachsettlement':
|
||||
# An `ApproachSettlement` can appear *before* `Location` if you
|
||||
# logged at one. We won't have necessary augmentation data
|
||||
# at this point, so bail.
|
||||
if system is None:
|
||||
return ""
|
||||
|
||||
return this.eddn.export_journal_approachsettlement(
|
||||
cmdr,
|
||||
system,
|
||||
@ -1507,6 +1543,14 @@ def journal_entry( # noqa: C901, CCR001
|
||||
entry
|
||||
)
|
||||
|
||||
# NB: If adding FSSSignalDiscovered these absolutely come in at login
|
||||
# time **BEFORE** the `Location` event, so we won't yet know things
|
||||
# like SystemNane, or StarPos.
|
||||
# We can either have the "now send the batch" code add such (but
|
||||
# that has corner cases around changing systems in the meantime),
|
||||
# drop those events, or if the schema allows, send without those
|
||||
# augmentations.
|
||||
|
||||
elif event_name == 'fssallbodiesfound':
|
||||
return this.eddn.export_journal_fssallbodiesfound(
|
||||
cmdr,
|
||||
|
@ -5,7 +5,7 @@ wheel
|
||||
# We can't rely on just picking this up from either the base (not venv),
|
||||
# or venv-init-time version. Specify here so that dependabot will prod us
|
||||
# about new versions.
|
||||
setuptools==60.8.2
|
||||
setuptools==60.9.3
|
||||
|
||||
# Static analysis tools
|
||||
flake8==4.0.1
|
||||
@ -23,7 +23,7 @@ flake8-use-fstring==1.3
|
||||
mypy==0.931
|
||||
pep8-naming==0.12.1
|
||||
safety==1.10.3
|
||||
types-requests==2.27.9
|
||||
types-requests==2.27.10
|
||||
|
||||
# Code formatting tools
|
||||
autopep8==1.6.0
|
||||
@ -33,14 +33,14 @@ grip==4.6.0
|
||||
|
||||
# Packaging
|
||||
# Used to put together a WiX configuration from template/auto-gen
|
||||
lxml==4.7.1
|
||||
lxml==4.8.0
|
||||
# We only need py2exe on windows.
|
||||
# Pre-release version addressing semantic_version 2.9.0+ issues:
|
||||
# <https://github.com/py2exe/py2exe/issues/126>
|
||||
py2exe==0.11.1.0; sys_platform == 'win32'
|
||||
|
||||
# Testing
|
||||
pytest==7.0.0
|
||||
pytest==7.0.1
|
||||
pytest-cov==3.0.0 # Pytest code coverage support
|
||||
coverage[toml]==6.3.1 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs
|
||||
# For manipulating folder permissions and the like.
|
||||
|
133
theme.py
133
theme.py
@ -14,6 +14,9 @@ from tkinter import ttk
|
||||
|
||||
from config import config
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
from EDMCLogging import get_main_logger
|
||||
|
||||
logger = get_main_logger()
|
||||
|
||||
if __debug__:
|
||||
from traceback import print_exc
|
||||
@ -192,17 +195,35 @@ class _Theme(object):
|
||||
def _enter(self, event, image):
|
||||
widget = event.widget
|
||||
if widget and widget['state'] != tk.DISABLED:
|
||||
widget.configure(state=tk.ACTIVE)
|
||||
try:
|
||||
widget.configure(state=tk.ACTIVE)
|
||||
|
||||
except Exception:
|
||||
logger.exception(f'Failure setting widget active: {widget=}')
|
||||
|
||||
if image:
|
||||
image.configure(foreground=self.current['activeforeground'],
|
||||
background=self.current['activebackground'])
|
||||
try:
|
||||
image.configure(foreground=self.current['activeforeground'],
|
||||
background=self.current['activebackground'])
|
||||
|
||||
except Exception:
|
||||
logger.exception(f'Failure configuring image: {image=}')
|
||||
|
||||
def _leave(self, event, image):
|
||||
widget = event.widget
|
||||
if widget and widget['state'] != tk.DISABLED:
|
||||
widget.configure(state=tk.NORMAL)
|
||||
try:
|
||||
widget.configure(state=tk.NORMAL)
|
||||
|
||||
except Exception:
|
||||
logger.exception(f'Failure setting widget normal: {widget=}')
|
||||
|
||||
if image:
|
||||
image.configure(foreground=self.current['foreground'], background=self.current['background'])
|
||||
try:
|
||||
image.configure(foreground=self.current['foreground'], background=self.current['background'])
|
||||
|
||||
except Exception:
|
||||
logger.exception(f'Failure configuring image: {image=}')
|
||||
|
||||
# Set up colors
|
||||
def _colors(self, root, theme):
|
||||
@ -266,50 +287,64 @@ class _Theme(object):
|
||||
widget.winfo_class(), widget, 'text' in widget.keys() and widget['text'])
|
||||
attribs = self.widgets.get(widget, [])
|
||||
|
||||
if isinstance(widget, tk.BitmapImage):
|
||||
# not a widget
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['foreground']),
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'])
|
||||
elif 'cursor' in widget.keys() and str(widget['cursor']) not in ['', 'arrow']:
|
||||
# Hack - highlight widgets like HyperlinkLabel with a non-default cursor
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['highlight']),
|
||||
if 'insertbackground' in widget.keys(): # tk.Entry
|
||||
widget.configure(insertbackground=self.current['foreground']),
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'])
|
||||
if 'highlightbackground' in widget.keys(): # tk.Entry
|
||||
widget.configure(highlightbackground=self.current['background'])
|
||||
if 'font' not in attribs:
|
||||
widget.configure(font=self.current['font'])
|
||||
elif 'activeforeground' in widget.keys():
|
||||
# e.g. tk.Button, tk.Label, tk.Menu
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['foreground'],
|
||||
activeforeground=self.current['activeforeground'],
|
||||
disabledforeground=self.current['disabledforeground'])
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'],
|
||||
activebackground=self.current['activebackground'])
|
||||
if sys.platform == 'darwin' and isinstance(widget, tk.Button):
|
||||
widget.configure(highlightbackground=self.current['background'])
|
||||
if 'font' not in attribs:
|
||||
widget.configure(font=self.current['font'])
|
||||
elif 'foreground' in widget.keys():
|
||||
# e.g. ttk.Label
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['foreground']),
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'])
|
||||
if 'font' not in attribs:
|
||||
widget.configure(font=self.current['font'])
|
||||
elif 'background' in widget.keys() or isinstance(widget, tk.Canvas):
|
||||
# e.g. Frame, Canvas
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'],
|
||||
highlightbackground=self.current['disabledforeground'])
|
||||
try:
|
||||
if isinstance(widget, tk.BitmapImage):
|
||||
# not a widget
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['foreground']),
|
||||
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'])
|
||||
|
||||
elif 'cursor' in widget.keys() and str(widget['cursor']) not in ['', 'arrow']:
|
||||
# Hack - highlight widgets like HyperlinkLabel with a non-default cursor
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['highlight']),
|
||||
if 'insertbackground' in widget.keys(): # tk.Entry
|
||||
widget.configure(insertbackground=self.current['foreground']),
|
||||
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'])
|
||||
if 'highlightbackground' in widget.keys(): # tk.Entry
|
||||
widget.configure(highlightbackground=self.current['background'])
|
||||
|
||||
if 'font' not in attribs:
|
||||
widget.configure(font=self.current['font'])
|
||||
|
||||
elif 'activeforeground' in widget.keys():
|
||||
# e.g. tk.Button, tk.Label, tk.Menu
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['foreground'],
|
||||
activeforeground=self.current['activeforeground'],
|
||||
disabledforeground=self.current['disabledforeground'])
|
||||
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'],
|
||||
activebackground=self.current['activebackground'])
|
||||
if sys.platform == 'darwin' and isinstance(widget, tk.Button):
|
||||
widget.configure(highlightbackground=self.current['background'])
|
||||
|
||||
if 'font' not in attribs:
|
||||
widget.configure(font=self.current['font'])
|
||||
elif 'foreground' in widget.keys():
|
||||
# e.g. ttk.Label
|
||||
if 'fg' not in attribs:
|
||||
widget.configure(foreground=self.current['foreground']),
|
||||
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'])
|
||||
|
||||
if 'font' not in attribs:
|
||||
widget.configure(font=self.current['font'])
|
||||
|
||||
elif 'background' in widget.keys() or isinstance(widget, tk.Canvas):
|
||||
# e.g. Frame, Canvas
|
||||
if 'bg' not in attribs:
|
||||
widget.configure(background=self.current['background'],
|
||||
highlightbackground=self.current['disabledforeground'])
|
||||
|
||||
except Exception:
|
||||
logger.exception(f'Plugin widget issue ? {widget=}')
|
||||
|
||||
# Apply configured theme
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user