Merge branch 'py3' of https://github.com/pyfa-org/Pyfa into test-3

This commit is contained in:
blitzmann
2018-04-28 20:35:26 -04:00
15 changed files with 308 additions and 24 deletions

View File

@@ -30,6 +30,8 @@ expansionName = "YC120.3"
expansionVersion = "1.8"
evemonMinVersion = "4081"
minItemSearchLength = 3
pyfaPath = None
savePath = None
saveDB = None

View File

@@ -1,4 +1,3 @@
import sys
import csv
import config
@@ -203,7 +202,7 @@ class ItemParams(wx.Panel):
else:
attrIcon = self.imageList.Add(BitmapLoader.getBitmap("7_15", "icons"))
index = self.paramList.InsertItem(sys.maxsize, attrName, attrIcon)
index = self.paramList.InsertItem(self.paramList.GetItemCount(), attrName, attrIcon)
idNameMap[idCount] = attrName
self.paramList.SetItemData(index, idCount)
idCount += 1

View File

@@ -1,5 +1,3 @@
import sys
# noinspection PyPackageRequirements
import wx
@@ -147,7 +145,7 @@ class ItemCompare(wx.Panel):
self.paramList.SetColumnWidth(len(self.attrs) + 1, 60)
for item in self.items:
i = self.paramList.InsertItem(sys.maxsize, item.name)
i = self.paramList.InsertItem(self.paramList.GetItemCount(), item.name)
for x, attr in enumerate(self.attrs.keys()):
if attr in item.attributes:
info = self.attrs[attr]

View File

@@ -1,4 +1,3 @@
import sys
import os
import subprocess
import config
@@ -51,7 +50,7 @@ class ItemEffects(wx.Panel):
names.sort()
for name in names:
index = self.effectList.InsertItem(sys.maxsize, name)
index = self.effectList.InsertItem(self.effectList.GetItemCount(), name)
if effects[name].isImplemented:
if effects[name].activeByDefault:

View File

@@ -1,5 +1,3 @@
import sys
# noinspection PyPackageRequirements
import wx
@@ -79,7 +77,7 @@ class ItemProperties(wx.Panel):
attrName = name.title()
value = getattr(self.item, name)
index = self.paramList.InsertItem(sys.maxsize, attrName)
index = self.paramList.InsertItem(self.paramList.GetItemCount(), attrName)
# index = self.paramList.InsertImageStringItem(sys.maxint, attrName)
idNameMap[idCount] = attrName
self.paramList.SetItemData(index, idCount)

View File

@@ -1,5 +1,6 @@
import wx
import config
import gui.builtinMarketBrowser.pfSearchBox as SBox
from gui.contextMenu import ContextMenu
from gui.display import Display
@@ -170,10 +171,6 @@ class ItemView(Display):
if len(realsearch) == 0:
self.selectionMade()
return
# Show nothing if query is too short
elif len(realsearch) < 3:
self.clearSearch()
return
self.marketBrowser.searchMode = True
self.sMkt.searchItems(search, self.populateSearch)

View File

@@ -17,7 +17,6 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import sys
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
@@ -182,13 +181,13 @@ class Display(wx.ListCtrl):
if listItemCount < stuffItemCount:
for i in range(stuffItemCount - listItemCount):
self.InsertItem(sys.maxsize, "")
self.InsertItem(self.GetItemCount(), "")
if listItemCount > stuffItemCount:
if listItemCount - stuffItemCount > 20 > stuffItemCount:
self.DeleteAllItems()
for i in range(stuffItemCount):
self.InsertItem(sys.maxsize, "")
self.InsertItem(self.GetItemCount(), "")
else:
for i in range(listItemCount - stuffItemCount):
self.DeleteItem(self.getLastItem())

View File

@@ -8,4 +8,5 @@ esipy == 0.3.3
markdown2
packaging
roman
beautifulsoup4
beautifulsoup4
PyYAML

View File

@@ -0,0 +1,21 @@
# =============================================================================
# Copyright (C) 2018 Filip Sufitchi
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
from .jargon import Jargon
from .loader import JargonLoader

View File

@@ -0,0 +1,90 @@
1: I
2: II
aar: Ancillary Armor Repairer
ab: Afterburner
ac: Autocannon
am: Antimatter
anp: Adaptive Nano Plating
acr: Ancillary Current Router
arty: Artillery
asb: Ancillary Shield Booster
bcs: Ballistic Control System
bcu: Ballistic Control System
boosh: Micro Jump Field Generator
ccc: Capacitor Control Circuit
cn: Caldari Navy
cnam: Caldari Navy Antimatter
cpr: Capacitor Power Relay
cpu: Co-Processor
coproc: Co-Processor
dc: Damage Control
dcu: Damage Control
disco: Smartbomb
eanm: Energized Adaptive Nano Membrane
enam: Energized Adaptive Nano Membrane
eccm: Sensor Booster
fn: Federation Navy
fnam: Federation Navy Antimatter
gd: Guidance Disruptor
ham: Heavy Assault Missile
haml: Heavy Assault Missile Launcher
hm: Heavy Missile
hml: Heavy Missile Launcher
istab: Inertial Stabilizer
in: Imperial Navy
inmf: Imperial Navy Multifrequency
jam: ECM
lar: Large Armor Repairer
laar: Large Ancillary Armor Repairer
lasb: Large Ancillary Shield Booster
lm: Light Missile
lmjd: Large Micro Jump Drive
lml: Light Missile Launcher
lo: Liquid Ozone
lse: Large Shield Extender
maar: Medium Ancillary Armor Repairer
masb: Medium Ancillary Shield Booster
mf: Multifrequency
md: Guidance Disruptor
mjfg: Micro Jump Field Generator
mar: Medium Armor Repairer
mfs: Magnetic Field Stabilizer
mmjd: Medium Micro Jump Drive
mjd: Micro Jump Drive
mlu: Mining Laser Upgrade
msb: Medium Shield Booster
mse: Medium Shield Extender
mwd: Microwarpdrive
odi: Overdrive Injector
point: Warp Disruptor
pdu: Power Diagnostic Unit
pp: Phased Plasma
rcu: Reactor Control Unit
rf: Republic Fleet
rhml: Rapid Heavy Missile Launcher
rl: Rocket Launcher
rlml: Rapid Light Missile Launcher
rr: Remote # Hacky, for shield, armor, and cap
rtc: Remote Tracking Computer
rtl: Rapid Torpedo Launcher
sar: Small Armor Repairer
saar: Small Ancillary Armor Repairer
sasb: Small Ancillary Shield Booster
sb: Sensor Booster # Or smartbomb? :/
sebo: Sensor Booster
sd: Sensor Dampener
sg: Stasis Grappler
ssb: Small Shield Booster
sse: Small Shield Extender
spr: Shield Power Relay
sw: Stasis Webifier
tc: Tracking Computer
td: Tracking Disruptor
te: Tracking enhancer
tl: Remote Tracking Computer
tp: Target Painter
wcs: Warp Core Stabilizer
web: stasis
xl: X-Large
xlasb: X-Large Ancillary Shield Booster
xlsb: X-Large Shield Booster

View File

@@ -0,0 +1,14 @@
# This is the default Pyfa jargon file.
#
# It is essentially a giant set of find/replace statements in order to translate
# abbreviated Eve community terms into more useful full terms. It is intended
# for translation of strings such as "haml 2" "into "Heavy Assault Missile Launcher II"..
#
# These abbreviations are not case-sensitive. If abbreviations collide, the
# later one is used.
#
# Abbreviations with spaces are not supported.
#
# Syntax:
#
# abbreviation: full name

47
service/jargon/jargon.py Normal file
View File

@@ -0,0 +1,47 @@
# =============================================================================
# Copyright (C) 2018 Filip Sufitchi
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import config
import pkg_resources
class Jargon(object):
def __init__(self, rawdata: dict):
self._rawdata = rawdata
# copy the data to lowercase keys, ignore blank keys
self._data = {str(k).lower():v for k,v in rawdata.items() if k}
def get(self, term: str) -> str:
return self._data.get(term.lower())
def get_rawdata() -> dict:
return self._rawdata
def apply(self, query):
query_words = query.split()
parts = []
for word in query_words:
replacement = self.get(word)
if replacement:
parts.append(replacement)
else:
parts.append(word)
return ' '.join(parts)

81
service/jargon/loader.py Normal file
View File

@@ -0,0 +1,81 @@
# =============================================================================
# Copyright (C) 2018 Filip Sufitchi
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import os
import config
import yaml
from .jargon import Jargon
from .resources import DEFAULT_DATA, DEFAULT_HEADER
JARGON_PATH = os.path.join(config.savePath, 'jargon.yaml')
class JargonLoader(object):
def __init__(self, jargon_path: str):
self.jargon_path = jargon_path
self._jargon_mtime = 0 # type: int
self._jargon = None # type: Jargon
def save_jargon(self, data: Jargon):
rawdata = data.get_rawdata()
with open(JARGON_PATH, 'w') as f:
yaml.dump(rawdata, stream=f, default_flow_style=False)
def get_jargon(self) -> Jargon:
if self._is_stale():
self._load_jargon()
return self._jargon
def _is_stale(self):
return (not self._jargon or not self._jargon_mtime or
self.jargon_mtime != self._get_jargon_file_mtime())
def _load_jargon(self):
with open(JARGON_PATH) as f:
rawdata = yaml.load(f)
self.jargon_mtime = self._get_jargon_file_mtime()
self._jargon = Jargon(rawdata)
def _get_jargon_file_mtime(self) -> int:
if not os.path.exists(self.jargon_path):
return 0
return os.stat(self.jargon_path).st_mtime
@staticmethod
def init_user_jargon(jargon_path):
values = yaml.load(DEFAULT_DATA)
if os.path.exists(jargon_path):
with open(jargon_path) as f:
custom_values = yaml.load(f)
if custom_values:
values.update(custom_values)
with open(jargon_path, 'w') as f:
f.write(DEFAULT_HEADER)
f.write('\n\n')
yaml.dump(values, stream=f, default_flow_style=False)
_instance = None
@staticmethod
def instance(jargon_path=None):
if not JargonLoader._instance:
jargon_path = jargon_path or JARGON_PATH
JargonLoader._instance = JargonLoader(jargon_path)
return JargonLoader._instance
JargonLoader.init_user_jargon(JARGON_PATH)

View File

@@ -0,0 +1,23 @@
# =============================================================================
# Copyright (C) 2018 Filip Sufitchi
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import pkg_resources
DEFAULT_DATA = pkg_resources.resource_string(__name__, 'defaults.yaml').decode()
DEFAULT_HEADER = pkg_resources.resource_string(__name__, 'header.yaml').decode()

View File

@@ -30,6 +30,7 @@ import config
import eos.db
from service import conversions
from service.settings import SettingsProvider
from service.jargon import JargonLoader
from eos.gamedata import Category as types_Category, Group as types_Group, Item as types_Item, MarketGroup as types_MarketGroup, \
MetaGroup as types_MetaGroup, MetaType as types_MetaType
@@ -40,7 +41,6 @@ pyfalog = Logger(__name__)
# Event which tells threads dependent on Market that it's initialized
mktRdy = threading.Event()
class ShipBrowserWorkerThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
@@ -83,7 +83,10 @@ class SearchWorkerThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.name = "SearchWorker"
pyfalog.debug("Initialize SearchWorkerThread.")
self.jargonLoader = JargonLoader.instance()
# load the jargon while in an out-of-thread context, to spot any problems while in the main thread
self.jargonLoader.get_jargon()
self.jargonLoader.get_jargon().apply('test string')
def run(self):
self.cv = threading.Condition()
@@ -110,13 +113,25 @@ class SearchWorkerThread(threading.Thread):
else:
filter_ = None
results = eos.db.searchItems(request, where=filter_,
join=(types_Item.group, types_Group.category),
eager=("icon", "group.category", "metaGroup", "metaGroup.parent"))
jargon_request = self.jargonLoader.get_jargon().apply(request)
results = []
if len(request) >= config.minItemSearchLength:
results = eos.db.searchItems(request, where=filter_,
join=(types_Item.group, types_Group.category),
eager=("icon", "group.category", "metaGroup", "metaGroup.parent"))
jargon_results = []
if len(jargon_request) >= config.minItemSearchLength:
jargon_results = eos.db.searchItems(jargon_request, where=filter_,
join=(types_Item.group, types_Group.category),
eager=("icon", "group.category", "metaGroup", "metaGroup.parent"))
items = set()
# Return only published items, consult with Market service this time
for item in results:
for item in [*results, *jargon_results]:
if sMkt.getPublicityByItem(item):
items.add(item)
wx.CallAfter(callback, items)