From 5c01ecb2d1ae4e926c29e2f19686de1631d65b0f Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sat, 28 Feb 2026 20:47:53 +0100 Subject: [PATCH] Fix the server docker image build --- Dockerfile | 4 +-- build.sh | 10 ++++++- config.py | 43 ++++++++++++++++++---------- gui/builtinMarketBrowser/itemView.py | 4 +-- gui/builtinViews/fittingView.py | 8 +++--- release.sh | 16 +++++++++-- requirements-server.txt | 14 +++++++++ service/character.py | 15 ++++++---- service/fit.py | 2 +- service/port/port.py | 4 +-- service/settings.py | 2 +- 11 files changed, 87 insertions(+), 35 deletions(-) create mode 100644 requirements-server.txt diff --git a/Dockerfile b/Dockerfile index a8c30ff94..0fa07596e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,8 @@ FROM python:3.12-slim WORKDIR /app -COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +COPY requirements-server.txt . +RUN pip install --no-cache-dir -r requirements-server.txt COPY . . EXPOSE 9123 diff --git a/build.sh b/build.sh index 2ede71aa8..7c9ce1235 100644 --- a/build.sh +++ b/build.sh @@ -49,4 +49,12 @@ fi echo "" echo "Build complete! dist/pyfa/pyfa.exe (GUI), dist/pyfa/pyfa-server.exe (POST /simulate :9123)" -echo "Docker image: ${IMAGE_BASE}:${COMMIT_SHA} (and :latest)" +echo "" +echo "Docker image built as:" +echo " - ${IMAGE_BASE}:${COMMIT_SHA}" +echo " - ${IMAGE_BASE}:latest" +if [ -n "$TAGS" ]; then + while IFS= read -r tag; do + [ -n "$tag" ] && echo " - ${IMAGE_BASE}:${tag}" + done <<< "$TAGS" +fi diff --git a/config.py b/config.py index ddfd1324f..971231544 100644 --- a/config.py +++ b/config.py @@ -1,7 +1,6 @@ import os import sys import yaml -import wx from logbook import CRITICAL, DEBUG, ERROR, FingersCrossedHandler, INFO, Logger, NestedSetup, NullHandler, \ StreamHandler, TimedRotatingFileHandler, WARNING @@ -67,20 +66,34 @@ LOGLEVEL_MAP = { CATALOG = 'lang' -slotColourMapDark = { - FittingSlot.LOW: wx.Colour(44, 36, 19), # yellow = low slots 24/13 - FittingSlot.MED: wx.Colour(28, 39, 51), # blue = mid slots 8.1/9.5 - FittingSlot.HIGH: wx.Colour(53, 31, 34), # red = high slots 6.5/11.5 - FittingSlot.RIG: '', - FittingSlot.SUBSYSTEM: ''} -errColorDark = wx.Colour(70, 20, 20) -slotColourMap = { - FittingSlot.LOW: wx.Colour(250, 235, 204), # yellow = low slots - FittingSlot.MED: wx.Colour(188, 215, 241), # blue = mid slots - FittingSlot.HIGH: wx.Colour(235, 204, 209), # red = high slots - FittingSlot.RIG: '', - FittingSlot.SUBSYSTEM: ''} -errColor = wx.Colour(204, 51, 51) +def get_slotColourMapDark(): + import wx + return { + FittingSlot.LOW: wx.Colour(44, 36, 19), # yellow = low slots 24/13 + FittingSlot.MED: wx.Colour(28, 39, 51), # blue = mid slots 8.1/9.5 + FittingSlot.HIGH: wx.Colour(53, 31, 34), # red = high slots 6.5/11.5 + FittingSlot.RIG: '', + FittingSlot.SUBSYSTEM: ''} + + +def get_errColorDark(): + import wx + return wx.Colour(70, 20, 20) + + +def get_slotColourMap(): + import wx + return { + FittingSlot.LOW: wx.Colour(250, 235, 204), # yellow = low slots + FittingSlot.MED: wx.Colour(188, 215, 241), # blue = mid slots + FittingSlot.HIGH: wx.Colour(235, 204, 209), # red = high slots + FittingSlot.RIG: '', + FittingSlot.SUBSYSTEM: ''} + + +def get_errColor(): + import wx + return wx.Colour(204, 51, 51) def getClientSecret(): diff --git a/gui/builtinMarketBrowser/itemView.py b/gui/builtinMarketBrowser/itemView.py index bc6f1648b..99d770aa5 100644 --- a/gui/builtinMarketBrowser/itemView.py +++ b/gui/builtinMarketBrowser/itemView.py @@ -3,7 +3,7 @@ from logbook import Logger import gui.builtinMarketBrowser.pfSearchBox as SBox import gui.globalEvents as GE -from config import slotColourMap, slotColourMapDark +from config import get_slotColourMap, get_slotColourMapDark from eos.saveddata.module import Module from eos.const import FittingSlot from gui.builtinMarketBrowser.events import ItemSelected, RECENTLY_USED_MODULES, CHARGES_FOR_FIT @@ -412,7 +412,7 @@ class ItemView(Display): def columnBackground(self, colItem, item): if self.sFit.serviceFittingOptions["colorFitBySlot"]: - colorMap = slotColourMapDark if isDark() else slotColourMap + colorMap = get_slotColourMapDark() if isDark() else get_slotColourMap() return colorMap.get(Module.calculateSlot(item)) or self.GetBackgroundColour() else: return self.GetBackgroundColour() diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 6b28ed6e6..b93fdf908 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -42,7 +42,7 @@ from gui.utils.staticHelpers import DragDropHelper from gui.utils.dark import isDark from service.fit import Fit from service.market import Market -from config import slotColourMap, slotColourMapDark, errColor, errColorDark +from config import get_slotColourMap, get_slotColourMapDark, get_errColor, get_errColorDark from gui.fitCommands.helpers import getSimilarModPositions pyfalog = Logger(__name__) @@ -766,9 +766,9 @@ class FittingView(d.Display): def slotColour(self, slot): if isDark(): - return slotColourMapDark.get(slot) or self.GetBackgroundColour() + return get_slotColourMapDark().get(slot) or self.GetBackgroundColour() else: - return slotColourMap.get(slot) or self.GetBackgroundColour() + return get_slotColourMap().get(slot) or self.GetBackgroundColour() def refresh(self, stuff): """ @@ -812,7 +812,7 @@ class FittingView(d.Display): hasRestrictionOverriden = not hasRestrictionOverriden if slotMap[mod.slot] or hasRestrictionOverriden: # Color too many modules as red - self.SetItemBackgroundColour(i, errColorDark if isDark() else errColor) + self.SetItemBackgroundColour(i, get_errColorDark() if isDark() else get_errColor()) elif sFit.serviceFittingOptions["colorFitBySlot"]: # Color by slot it enabled self.SetItemBackgroundColour(i, self.slotColour(mod.slot)) diff --git a/release.sh b/release.sh index 54b2c9bdb..e40ac3a4f 100644 --- a/release.sh +++ b/release.sh @@ -63,7 +63,8 @@ IMAGE_NAME="${IMAGE_NAME:-pyfa-server}" COMMIT_SHA=$(git rev-parse --short HEAD) IMAGE_BASE="${DOCKER_REPO}/${IMAGE_NAME}" -echo "Pushing Docker image..." +echo "" +echo "Pushing Docker images..." docker push "${IMAGE_BASE}:${COMMIT_SHA}" docker push "${IMAGE_BASE}:latest" TAGS=$(git tag --points-at HEAD 2>/dev/null || true) @@ -73,4 +74,15 @@ if [ -n "$TAGS" ]; then done <<< "$TAGS" fi -echo "Release complete! ${ZIP} uploaded to ${TAG}, Docker image pushed" +echo "" +echo "Docker image pushed as:" +echo " - ${IMAGE_BASE}:${COMMIT_SHA}" +echo " - ${IMAGE_BASE}:latest" +if [ -n "$TAGS" ]; then + while IFS= read -r tag; do + [ -n "$tag" ] && echo " - ${IMAGE_BASE}:${tag}" + done <<< "$TAGS" +fi + +echo "" +echo "Release complete! ${ZIP} uploaded to ${TAG}" diff --git a/requirements-server.txt b/requirements-server.txt new file mode 100644 index 000000000..138903c96 --- /dev/null +++ b/requirements-server.txt @@ -0,0 +1,14 @@ +logbook==1.7.0.post0 +numpy==1.26.2 +matplotlib==3.8.2 +python-dateutil==2.8.2 +requests==2.31.0 +sqlalchemy==1.4.50 +cryptography==42.0.4 +markdown2==2.4.11 +packaging==23.2 +roman==4.1 +beautifulsoup4==4.12.2 +pyyaml==6.0.1 +python-jose==3.3.0 +requests-cache==1.1.1 diff --git a/service/character.py b/service/character.py index 130d63884..9f1628360 100644 --- a/service/character.py +++ b/service/character.py @@ -28,12 +28,8 @@ from xml.etree import ElementTree from xml.dom import minidom import gzip -# noinspection PyPackageRequirements -import wx - import config import eos.db -from service.esi import Esi from eos.saveddata.implant import Implant as es_Implant from eos.saveddata.character import Character as es_Character, Skill @@ -42,7 +38,12 @@ from eos.const import FittingSlot as es_Slot from eos.saveddata.fighter import Fighter as es_Fighter pyfalog = Logger(__name__) -_t = wx.GetTranslation + + +def _t(s): + import wx + return wx.GetTranslation(s) + class CharacterImportThread(threading.Thread): @@ -97,6 +98,7 @@ class CharacterImportThread(threading.Thread): pyfalog.error(e) continue + import wx wx.CallAfter(self.callback) def stop(self): @@ -132,6 +134,7 @@ class SkillBackupThread(threading.Thread): with open(path, mode='w', encoding='utf-8') as backupFile: backupFile.write(backupData) + import wx wx.CallAfter(self.callback) def stop(self): @@ -386,6 +389,7 @@ class Character: def apiFetchCallback(self, guiCallback, e=None): eos.db.commit() + import wx wx.CallAfter(guiCallback, e) @staticmethod @@ -501,6 +505,7 @@ class UpdateAPIThread(threading.Thread): try: char = eos.db.getCharacter(self.charID) + from service.esi import Esi sEsi = Esi.getInstance() sChar = Character.getInstance() ssoChar = sChar.getSsoCharacter(char.ID) diff --git a/service/fit.py b/service/fit.py index 4e3a1aa7b..60f1f252d 100644 --- a/service/fit.py +++ b/service/fit.py @@ -22,7 +22,6 @@ import datetime from time import time from weakref import WeakSet -import wx from logbook import Logger import eos.db @@ -235,6 +234,7 @@ class Fit: @classmethod def getCommandProcessor(cls, fitID): if fitID not in cls.processors: + import wx cls.processors[fitID] = wx.CommandProcessor(maxCommands=100) return cls.processors[fitID] diff --git a/service/port/port.py b/service/port/port.py index c8353db86..cb7e3b87b 100644 --- a/service/port/port.py +++ b/service/port/port.py @@ -38,7 +38,6 @@ from service.port.eft import ( isValidImplantImport, isValidBoosterImport) from service.port.esi import exportESI, importESI from service.port.multibuy import exportMultiBuy -from service.port.shipstats import exportFitStats from service.port.xml import importXml, exportXml from service.port.muta import parseMutant, parseDynamicItemString, fetchDynamicItem @@ -346,4 +345,5 @@ class Port: @staticmethod def exportFitStats(fit, callback=None): - return exportFitStats(fit, callback=callback) + from service.port.shipstats import exportFitStats as _exportFitStats + return _exportFitStats(fit, callback=callback) diff --git a/service/settings.py b/service/settings.py index e80b2f6ff..66da89c91 100644 --- a/service/settings.py +++ b/service/settings.py @@ -24,7 +24,6 @@ import urllib.error import urllib.parse import json from collections import namedtuple -import wx from logbook import Logger @@ -582,6 +581,7 @@ class LocaleSettings: @classmethod def supported_languages(cls): """Requires the application to be initialized, otherwise wx.Translation isn't set.""" + import wx pyfalog.info(f'using "{config.CATALOG}" to fetch languages, relatively base path "{os.getcwd()}"') return {x: wx.Locale.FindLanguageInfo(x) for x in wx.Translations.Get().GetAvailableTranslations(config.CATALOG)}