diff --git a/docker-compose.yml b/docker-compose.yml index 717346420..5ff20bccb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ services: pyfa-server: - build: . + image: docker.site.quack-lab.dev/pyfa-server:latest ports: - "9123:9123" diff --git a/gui/fitCommands/helpers.py b/gui/fitCommands/helpers.py index 58a48b935..547f53cf5 100644 --- a/gui/fitCommands/helpers.py +++ b/gui/fitCommands/helpers.py @@ -346,20 +346,7 @@ class CargoInfo: return makeReprStr(self, ['itemID', 'amount']) -def activeStateLimit(itemIdentity): - item = Market.getInstance().getItem(itemIdentity) - if { - 'moduleBonusAssaultDamageControl', 'moduleBonusIndustrialInvulnerability', - 'microJumpDrive', 'microJumpPortalDrive', 'emergencyHullEnergizer', - 'cynosuralGeneration', 'jumpPortalGeneration', 'jumpPortalGenerationBO', - 'cloneJumpAccepting', 'cloakingWarpSafe', 'cloakingPrototype', 'cloaking', - 'massEntanglerEffect5', 'electronicAttributeModifyOnline', 'targetPassively', - 'cargoScan', 'shipScan', 'surveyScan', 'targetSpectrumBreakerBonus', - 'interdictionNullifierBonus', 'warpCoreStabilizerActive', - 'industrialItemCompression' - }.intersection(item.effects): - return FittingModuleState.ONLINE - return FittingModuleState.ACTIVE +from service.port.active_state import activeStateLimit def droneStackLimit(fit, itemIdentity): diff --git a/scripts/pyfa_sim.py b/scripts/pyfa_sim.py index 3770f320e..4b630848d 100644 --- a/scripts/pyfa_sim.py +++ b/scripts/pyfa_sim.py @@ -394,10 +394,14 @@ def _run_http_server(port: int, savepath: str | None) -> None: self.wfile.write(str(e).encode("utf-8")) return except Exception as e: + import traceback + tb = traceback.format_exc() + sys.stderr.write(tb) + sys.stderr.flush() self.send_response(500) self.send_header("Content-Type", "text/plain; charset=utf-8") self.end_headers() - self.wfile.write(str(e).encode("utf-8")) + self.wfile.write((str(e) + "\n\n" + tb).encode("utf-8")) return self.send_response(200) self.send_header("Content-Type", "application/json; charset=utf-8") diff --git a/service/market.py b/service/market.py index a779ed965..19e5e7684 100644 --- a/service/market.py +++ b/service/market.py @@ -23,8 +23,6 @@ import threading from collections import OrderedDict from itertools import chain -# noinspection PyPackageRequirements -import wx from logbook import Logger from sqlalchemy.sql import or_ @@ -38,7 +36,12 @@ from service.settings import SettingsProvider from utils.cjk import isStringCjk pyfalog = Logger(__name__) -_t = wx.GetTranslation + + +def _t(s): + import wx + return wx.GetTranslation(s) + # Event which tells threads dependent on Market that it's initialized mktRdy = threading.Event() @@ -77,6 +80,7 @@ class ShipBrowserWorkerThread(threading.Thread): set_ = sMkt.getShipList(id_) cache[id_] = set_ + import wx wx.CallAfter(callback, (id_, set_)) except (KeyboardInterrupt, SystemExit): raise @@ -170,6 +174,7 @@ class SearchWorkerThread(threading.Thread): for item in all_results: if sMkt.getPublicityByItem(item): item_IDs.add(item.ID) + import wx wx.CallAfter(callback, sorted(item_IDs)) def scheduleSearch(self, text, callback, filterName=None): @@ -268,7 +273,7 @@ class Market: self.les_grp = types_Group() self.les_grp.ID = -1 self.les_grp.name = "Limited Issue Ships" - self.les_grp.displayName = _t("Limited Issue Ships") + self.les_grp.displayName = "Limited Issue Ships" self.les_grp.published = True ships = self.getCategory("Ship") self.les_grp.category = ships diff --git a/service/port/active_state.py b/service/port/active_state.py new file mode 100644 index 000000000..1fa6801ad --- /dev/null +++ b/service/port/active_state.py @@ -0,0 +1,12 @@ +# Module-state logic shared by port (EFT import) and gui (fit commands). +# Uses gamedata (item type + attributes), no hardcoded effect names. + +from eos.const import FittingModuleState +from service.market import Market + + +def activeStateLimit(itemIdentity): + item = Market.getInstance().getItem(itemIdentity) + if not item.isType("active") or item.getAttribute("activationBlocked", 0) > 0: + return FittingModuleState.ONLINE + return FittingModuleState.ACTIVE diff --git a/service/port/eft.py b/service/port/eft.py index 84b50fbe1..f6838d232 100644 --- a/service/port/eft.py +++ b/service/port/eft.py @@ -47,6 +47,8 @@ SLOT_ORDER = (FittingSlot.LOW, FittingSlot.MED, FittingSlot.HIGH, FittingSlot.RI OFFLINE_SUFFIX = '/offline' NAME_CHARS = r'[^,/\[\]]' # Characters which are allowed to be used in name +from service.port.active_state import activeStateLimit + class MutationExportData: @@ -240,7 +242,6 @@ def exportCargo(cargos): def importEft(lines): - from gui.fitCommands.helpers import activeStateLimit lines = _importPrepare(lines) try: fit = _importCreateFit(lines) @@ -877,7 +878,6 @@ class AbstractFit: self.getContainerBySlot(m.slot).append(m) def __makeModule(self, itemSpec): - from gui.fitCommands.helpers import activeStateLimit # Mutate item if needed m = None if itemSpec.mutationIdx in self.mutations: diff --git a/service/price.py b/service/price.py index 5a4fe0a1a..5ea39f872 100644 --- a/service/price.py +++ b/service/price.py @@ -24,7 +24,6 @@ import timeit from itertools import chain import math -import wx from logbook import Logger from eos import db @@ -51,6 +50,8 @@ class Price: sources = {} def __init__(self): + # Import market sources so they register; avoid at module level so server path never loads them + from service.marketSources import evemarketdata, fuzzwork, cevemarket, evetycoon # noqa: F401 # Start price fetcher self.priceWorkerThread = PriceWorkerThread() self.priceWorkerThread.daemon = True @@ -253,6 +254,7 @@ class PriceWorkerThread(threading.Thread): if len(requests) > 0: Price.fetchPrices(requests, fetchTimeout, validityOverride) + import wx wx.CallAfter(callback) queue.task_done() @@ -273,7 +275,3 @@ class PriceWorkerThread(threading.Thread): def stop(self): self.running = False - - -# Import market sources only to initialize price source modules, they register on their own -from service.marketSources import evemarketdata, fuzzwork, cevemarket, evetycoon # noqa: E402