Merge branch 'test-3'

This commit is contained in:
blitzmann
2018-05-07 21:54:51 -04:00
253 changed files with 6145 additions and 8936 deletions

3
.gitignore vendored
View File

@@ -118,4 +118,7 @@ ENV/
.idea
eos.iml
gitversion
.version
/.version
*.swp

14
.mailmap Normal file
View File

@@ -0,0 +1,14 @@
cncfanatics <diego.duclos@gmail.com> cncfanatics <cncfanatics@titanium.(none)>
blitzmann <holmes.ryan.90@gmail.com>
blitzmann <holmes.ryan.90@gmail.com> blitzmann <ryan.xgamer99@gmail.com>
blitzmann <holmes.ryan.90@gmail.com>
blitzmann <holmes.ryan.90@gmail.com> blitzman <ryan.xgamer99@gmail.com>
blitzmann <holmes.ryan.90@gmail.com> Ryan Holmes <ryan.holmes.90@gmail.com>
blitzmann <holmes.ryan.90@gmail.com>
Corollax <corollax@gmail.com> Corollax <corollax@corollax-laptop.(none)>
Corollax <corollax@gmail.com> Corollax <corollax@corollax-N76VM.(none)>
Mr. Nukealizer <mr.nukealizer@gmail.com> Mr. Nukealizer <MrNukealizer@users.noreply.github.com>
DarkPhoenix <phoenix@mail.ru>
Sakari Orisi <sakari@evefit.org>
Will Wykeham <will@wykeham.net> Will Wykeham <will.wykeham@paconsulting.com>
OISumeko <camerongrout@gmail.com> OISumeko <cameron@sporadic.co.nz>

View File

@@ -36,13 +36,8 @@ The following is a list of pyfa packages available for certain distributions. Pl
### Dependencies
If you wish to help with development or simply need to run pyfa through a Python interpreter, the following software is required:
* Python 2.7
* `wxPython` 2.8/3.0
* `sqlalchemy` >= 1.0.5
* `dateutil`
* `matplotlib` (for some Linux distributions you may need to install separate wxPython bindings such as `python-matplotlib-wx`)
* `requests`
* `logbook` >= 1.0.0
* Python 3.6
* Requirements as listed in `requirements.txt`
## Bug Reporting
The preferred method of reporting bugs is through the project's [GitHub Issues interface](https://github.com/pyfa-org/Pyfa/issues). Alternatively, posting a report in the [pyfa thread](http://forums.eveonline.com/default.aspx?g=posts&t=247609) on the official EVE Online forums is acceptable. Guidelines for bug reporting can be found on [this wiki page](https://github.com/DarkFenX/Pyfa/wiki/Bug-Reporting).

View File

@@ -28,7 +28,7 @@ def DBInMemory_test():
gamedataCache = True
saveddataCache = True
gamedata_version = ""
gamedata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(unicode(__file__))), "..", "eve.db"))
gamedata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(str(__file__))), "..", "eve.db"))
saveddata_connectionstring = 'sqlite:///:memory:'
class ReadOnlyException(Exception):
@@ -100,8 +100,8 @@ def DBInMemory():
import eos.db
# Output debug info to help us troubleshoot Travis
print(eos.db.saveddata_engine)
print(eos.db.gamedata_engine)
print((eos.db.saveddata_engine))
print((eos.db.gamedata_engine))
helper = {
'config': eos.config,

View File

@@ -41,7 +41,7 @@ def CurseFit(DB, Gamedata, Saveddata):
mod.state = Saveddata['State'].ONLINE
# Add 5 neuts
for _ in xrange(5):
for _ in range(5):
fit.modules.append(mod)
return fit
@@ -60,7 +60,7 @@ def HeronFit(DB, Gamedata, Saveddata):
mod.state = Saveddata['State'].ONLINE
# Add 5 neuts
for _ in xrange(4):
for _ in range(4):
fit.modules.append(mod)
return fit

View File

@@ -94,8 +94,8 @@ def GetUnicodePath(root, file=None, codec=None):
path = os.path.join(path, file)
if codec:
path = unicode(path, codec)
path = str(path, codec)
else:
path = unicode(path)
path = str(path)
return path

173
config.py
View File

@@ -1,7 +1,11 @@
import os
import sys
from logbook import Logger
from logbook import CRITICAL, DEBUG, ERROR, FingersCrossedHandler, INFO, Logger, NestedSetup, NullHandler, \
StreamHandler, TimedRotatingFileHandler, WARNING
import hashlib
from cryptography.fernet import Fernet
pyfalog = Logger(__name__)
@@ -19,17 +23,39 @@ debug = False
saveInRoot = False
# Version data
version = "1.36.0"
tag = "Stable"
version = "2.0.0b5"
tag = "git"
expansionName = "YC120.3"
expansionVersion = "1.8"
evemonMinVersion = "4081"
minItemSearchLength = 3
pyfaPath = None
savePath = None
saveDB = None
gameDB = None
logPath = None
loggingLevel = None
logging_setup = None
cipher = None
clientHash = None
ESI_AUTH_PROXY = "https://www.pyfa.io" # "http://localhost:5015"
ESI_CACHE = 'esi_cache'
LOGLEVEL_MAP = {
"critical": CRITICAL,
"error": ERROR,
"warning": WARNING,
"info": INFO,
"debug": DEBUG,
}
def getClientSecret():
return clientHash
def isFrozen():
@@ -45,23 +71,37 @@ def __createDirs(path):
def getPyfaRoot():
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
if hasattr(sys, '_MEIPASS'):
return sys._MEIPASS
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else __file__
root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
root = unicode(root, sys.getfilesystemencoding())
root = root
return root
def getVersion():
if os.path.isfile(os.path.join(pyfaPath, '.version')):
with open(os.path.join(pyfaPath, '.version')) as f:
gitVersion = f.readline()
return gitVersion
# if no version file exists, then user is running from source or not an official build
return version + " (git)"
def getDefaultSave():
return unicode(os.path.expanduser(os.path.join("~", ".pyfa")), sys.getfilesystemencoding())
return os.path.expanduser(os.path.join("~", ".pyfa"))
def defPaths(customSavePath):
def defPaths(customSavePath=None):
global debug
global pyfaPath
global savePath
global saveDB
global gameDB
global saveInRoot
global logPath
global cipher
global clientHash
pyfalog.debug("Configuring Pyfa")
@@ -86,12 +126,22 @@ def defPaths(customSavePath):
__createDirs(savePath)
if isFrozen():
os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8')
os.environ["SSL_CERT_FILE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8')
secret_file = os.path.join(savePath, ".secret")
if not os.path.exists(secret_file):
with open(secret_file, "wb") as _file:
_file.write(Fernet.generate_key())
with open(secret_file, 'rb') as fp:
key = fp.read()
clientHash = hashlib.sha3_256(key).hexdigest()
cipher = Fernet(key)
# if isFrozen():
# os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(pyfaPath, "cacert.pem")
# os.environ["SSL_CERT_FILE"] = os.path.join(pyfaPath, "cacert.pem")
# The database where we store all the fits etc
saveDB = os.path.join(savePath, "saveddata.db")
saveDB = os.path.join(savePath, "saveddata-py3-dev.db")
# The database where the static EVE data from the datadump is kept.
# This is not the standard sqlite datadump but a modified version created by eos
@@ -100,6 +150,13 @@ def defPaths(customSavePath):
if not gameDB:
gameDB = os.path.join(pyfaPath, "eve.db")
if debug:
logFile = "pyfa_debug.log"
else:
logFile = "pyfa.log"
logPath = os.path.join(savePath, logFile)
# DON'T MODIFY ANYTHING BELOW
import eos.config
@@ -109,6 +166,100 @@ def defPaths(customSavePath):
eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False"
eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False"
print(eos.config.saveddata_connectionstring)
print(eos.config.gamedata_connectionstring)
# initialize the settings
from service.settings import EOSSettings
eos.config.settings = EOSSettings.getInstance().EOSSettings # this is kind of confusing, but whatever
def defLogging():
global debug
global logPath
global loggingLevel
global logging_setup
try:
if debug:
logging_setup = NestedSetup([
# make sure we never bubble up to the stderr handler
# if we run out of setup handling
NullHandler(),
StreamHandler(
sys.stdout,
bubble=False,
level=loggingLevel
),
TimedRotatingFileHandler(
logPath,
level=0,
backup_count=3,
bubble=True,
date_format='%Y-%m-%d',
),
])
else:
logging_setup = NestedSetup([
# make sure we never bubble up to the stderr handler
# if we run out of setup handling
NullHandler(),
FingersCrossedHandler(
TimedRotatingFileHandler(
logPath,
level=0,
backup_count=3,
bubble=False,
date_format='%Y-%m-%d',
),
action_level=ERROR,
buffer_size=1000,
# pull_information=True,
# reset=False,
)
])
except:
print("Critical error attempting to setup logging. Falling back to console only.")
logging_setup = NestedSetup([
# make sure we never bubble up to the stderr handler
# if we run out of setup handling
NullHandler(),
StreamHandler(
sys.stdout,
bubble=False
)
])
with logging_setup.threadbound():
# Output all stdout (print) messages as warnings
try:
sys.stdout = LoggerWriter(pyfalog.warning)
except:
pyfalog.critical("Cannot redirect. Continuing without writing stdout to log.")
# Output all stderr (stacktrace) messages as critical
try:
sys.stderr = LoggerWriter(pyfalog.critical)
except:
pyfalog.critical("Cannot redirect. Continuing without writing stderr to log.")
class LoggerWriter(object):
def __init__(self, level):
# self.level is really like using log.debug(message)
# at least in my case
self.level = level
def write(self, message):
# if statement reduces the amount of newlines that are
# printed to the logger
if message.strip() != '':
self.level(message.replace("\n", ""))
def flush(self):
# create a flush method so things can be flushed when
# the system wants to. Not sure if simply 'printing'
# sys.stderr is the correct way to do it, but it seemed
# to work properly for me.
self.level(sys.stderr)

View File

@@ -0,0 +1,70 @@
# -*- mode: python -*-
import os
from itertools import chain
import subprocess
label = subprocess.check_output([
"git", "describe", "--tags"]).strip()
with open('gitversion', 'w+') as f:
f.write(label.decode())
block_cipher = None
added_files = [
( 'imgs/gui/*.png', 'imgs/gui' ),
( 'imgs/gui/*.gif', 'imgs/gui' ),
( 'imgs/icons/*.png', 'imgs/icons' ),
( 'imgs/renders/*.png', 'imgs/renders' ),
( 'dist_assets/win/pyfa.ico', '.' ),
( 'dist_assets/cacert.pem', '.' ),
( 'eve.db', '.' ),
( 'README.md', '.' ),
( 'LICENSE', '.' ),
( 'gitversion', '.' ),
]
import_these = []
# Walk directories that do dynamic importing
paths = ('eos/effects', 'eos/db/migrations', 'service/conversions')
for root, folders, files in chain.from_iterable(os.walk(path) for path in paths):
for file_ in files:
if file_.endswith(".py") and not file_.startswith("_"):
mod_name = "{}.{}".format(
root.replace("/", "."),
file_.split(".py")[0],
)
import_these.append(mod_name)
a = Analysis(['pyfa.py'],
pathex=[],
binaries=[],
datas=added_files,
hiddenimports=import_these,
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='pyfa',
debug=False,
strip=False,
upx=True,
console=True )
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='pyfa')

74
dist_assets/mac/pyfa.spec Normal file
View File

@@ -0,0 +1,74 @@
# -*- mode: python -*-
import os
from itertools import chain
import subprocess
import requests.certs
label = subprocess.check_output([
"git", "describe", "--tags"]).strip()
with open('.version', 'w+') as f:
f.write(label.decode())
block_cipher = None
added_files = [
('../../imgs/gui/*.png', 'imgs/gui'),
('../../imgs/gui/*.gif', 'imgs/gui'),
('../../imgs/icons/*.png', 'imgs/icons'),
('../../imgs/renders/*.png', 'imgs/renders'),
('../../dist_assets/win/pyfa.ico', '.'),
('../../service/jargon/*.yaml', 'service/jargon'),
(requests.certs.where(), '.'), # is this needed anymore?
('../../eve.db', '.'),
('../../README.md', '.'),
('../../LICENSE', '.'),
('../../.version', '.'),
]
import_these = []
# Walk directories that do dynamic importing
paths = ('eos/effects', 'eos/db/migrations', 'service/conversions')
for root, folders, files in chain.from_iterable(os.walk(path) for path in paths):
for file_ in files:
if file_.endswith(".py") and not file_.startswith("_"):
mod_name = "{}.{}".format(
root.replace("/", "."),
file_.split(".py")[0],
)
import_these.append(mod_name)
a = Analysis([r'../../pyfa.py'],
pathex=[],
binaries=[],
datas=added_files,
hiddenimports=import_these,
hookspath=['dist_assets/pyinstaller_hooks'],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='pyfa',
debug=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=False ,
icon='dist_assets/mac/pyfa.icns',
)
app = BUNDLE(exe,
name='pyfa.app',
icon=None,
bundle_identifier=None)

View File

@@ -0,0 +1,78 @@
# This apes hook-matplotlib.backends.py, but REMOVES backends, all but
# the ones in the list below.
# Courtesy of https://github.com/bpteague/cytoflow/blob/70f9291/packaging/hook-matplotlib.backends.py
KEEP = ["WXAgg", "WX", "agg"]
from PyInstaller.compat import is_darwin
from PyInstaller.utils.hooks import (
eval_statement, exec_statement, logger)
def get_matplotlib_backend_module_names():
"""
List the names of all matplotlib backend modules importable under the
current Python installation.
Returns
----------
list
List of the fully-qualified names of all such modules.
"""
# Statement safely importing a single backend module.
import_statement = """
import os, sys
# Preserve stdout.
sys_stdout = sys.stdout
try:
# Redirect output printed by this importation to "/dev/null", preventing
# such output from being erroneously interpreted as an error.
with open(os.devnull, 'w') as dev_null:
sys.stdout = dev_null
__import__('%s')
# If this is an ImportError, print this exception's message without a traceback.
# ImportError messages are human-readable and require no additional context.
except ImportError as exc:
sys.stdout = sys_stdout
print(exc)
# Else, print this exception preceded by a traceback. traceback.print_exc()
# prints to stderr rather than stdout and must not be called here!
except Exception:
sys.stdout = sys_stdout
import traceback
print(traceback.format_exc())
"""
# List of the human-readable names of all available backends.
backend_names = eval_statement(
'import matplotlib; print(matplotlib.rcsetup.all_backends)')
# List of the fully-qualified names of all importable backend modules.
module_names = []
# If the current system is not OS X and the "CocoaAgg" backend is available,
# remove this backend from consideration. Attempting to import this backend
# on non-OS X systems halts the current subprocess without printing output
# or raising exceptions, preventing its reliable detection.
if not is_darwin and 'CocoaAgg' in backend_names:
backend_names.remove('CocoaAgg')
# For safety, attempt to import each backend in a unique subprocess.
for backend_name in backend_names:
if backend_name in KEEP:
continue
module_name = 'matplotlib.backends.backend_%s' % backend_name.lower()
stdout = exec_statement(import_statement % module_name)
# If no output was printed, this backend is importable.
if not stdout:
module_names.append(module_name)
logger.info(' Matplotlib backend "%s": removed' % backend_name)
return module_names
# Freeze all importable backends, as PyInstaller is unable to determine exactly
# which backends are required by the current program.
e=get_matplotlib_backend_module_names()
print(e)
excludedimports = e

View File

@@ -1,35 +1,37 @@
# -*- mode: python -*-
# Note: This script is provided AS-IS for those that may be interested.
# pyfa does not currently support pyInstaller (or any other build process) 100% at the moment
# Command line to build:
# (Run from directory where pyfa.py and pyfa.spec lives.)
# c:\Python27\scripts\pyinstaller.exe --clean --noconfirm --windowed --upx-dir=.\scripts\upx.exe pyfa.spec
# Don't forget to change the path to where your pyfa.py and pyfa.spec lives
# pathex=['C:\\Users\\Ebag333\\Documents\\GitHub\\Ebag333\\Pyfa'],
import os
from itertools import chain
import subprocess
import requests.certs
label = subprocess.check_output([
"git", "describe", "--tags"]).strip()
with open('.version', 'w+') as f:
f.write(label.decode())
block_cipher = None
added_files = [
( 'imgs/gui/*.png', 'imgs/gui' ),
( 'imgs/gui/*.gif', 'imgs/gui' ),
( 'imgs/icons/*.png', 'imgs/icons' ),
( 'imgs/renders/*.png', 'imgs/renders' ),
( 'dist_assets/win/pyfa.ico', '.' ),
( 'dist_assets/cacert.pem', '.' ),
( 'eve.db', '.' ),
( 'README.md', '.' ),
( 'LICENSE', '.' ),
('../../imgs/gui/*.png', 'imgs/gui'),
('../../imgs/gui/*.gif', 'imgs/gui'),
('../../imgs/icons/*.png', 'imgs/icons'),
('../../imgs/renders/*.png', 'imgs/renders'),
('../../service/jargon/*.yaml', 'service/jargon'),
('../../dist_assets/win/pyfa.ico', '.'),
(requests.certs.where(), '.'), # is this needed anymore?
('../../eve.db', '.'),
('../../README.md', '.'),
('../../LICENSE', '.'),
('../../.version', '.'),
]
import_these = []
# Walk eos.effects and add all effects so we can import them properly
for root, folders, files in os.walk("eos/effects"):
# Walk directories that do dynamic importing
paths = ('eos/effects', 'eos/db/migrations', 'service/conversions')
for root, folders, files in chain.from_iterable(os.walk(path) for path in paths):
for file_ in files:
if file_.endswith(".py") and not file_.startswith("_"):
mod_name = "{}.{}".format(
@@ -38,25 +40,24 @@ for root, folders, files in os.walk("eos/effects"):
)
import_these.append(mod_name)
a = Analysis(
['pyfa.py'],
pathex=['C:\\projects\\pyfa\\'],
a = Analysis(['../../pyfa.py'],
pathex=[
# Need this, see https://github.com/pyinstaller/pyinstaller/issues/1566
# To get this, download and install windows 10 SDK
# If not building on Windows 10, this might be optional
r'C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86'],
binaries=[],
datas=added_files,
hiddenimports=import_these,
hookspath=[],
hookspath=['dist_assets/pyinstaller_hooks'],
runtime_hooks=[],
excludes=[],
excludes=['Tkinter'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
)
cipher=block_cipher)
pyz = PYZ(
a.pure,
a.zipped_data,
cipher=block_cipher,
)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
@@ -67,7 +68,6 @@ exe = EXE(pyz,
upx=True,
name='pyfa',
icon='dist_assets/win/pyfa.ico',
onefile=False,
)
coll = COLLECT(
@@ -77,7 +77,6 @@ coll = COLLECT(
a.datas,
strip=False,
upx=True,
onefile=False,
name='pyfa',
icon='dist_assets/win/pyfa.ico',
)
)

View File

@@ -0,0 +1,45 @@
# UTF-8
#
# For more details about fixed file info 'ffi' see:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0.
filevers=(1, 15, 1, 0),
prodvers=(1, 15, 1, 0),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file.
flags=0x0,
# The operating system for which this file was designed.
# 0x4 - NT and there is no need to change it.
OS=0x40004,
# The general type of file.
# 0x1 - the file is an application.
fileType=0x1,
# The function of the file.
# 0x0 - the function is not defined for this fileType
subtype=0x0,
# Creation date and time stamp.
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
u'040904E4',
[StringStruct(u'LegalCopyright', u''),
StringStruct(u'InternalName', u'pyfa.exe'),
StringStruct(u'FileVersion', u'1.15.1.0'),
StringStruct(u'CompanyName', u''),
StringStruct(u'OriginalFilename', u'pyfa.exe'),
StringStruct(u'ProductVersion', u'1.15.1.0'),
StringStruct(u'FileDescription', u'Python fitting assistant'),
StringStruct(u'LegalTrademarks', u''),
StringStruct(u'Comments', u''),
StringStruct(u'ProductName', u'pyfa')])
]),
VarFileInfo([VarStruct(u'Translation', [1033, 1252])])
]
)

View File

@@ -1,6 +1,7 @@
import heapq
import time
from math import sqrt, exp
from functools import reduce
DAY = 24 * 60 * 60 * 1000
@@ -88,7 +89,7 @@ class CapSimulator(object):
mods[(duration, capNeed, clipSize, disableStagger, reloadTime)] = 1
# Loop over grouped modules, configure staggering and push to the simulation state
for (duration, capNeed, clipSize, disableStagger, reloadTime), amount in mods.iteritems():
for (duration, capNeed, clipSize, disableStagger, reloadTime), amount in mods.items():
if self.stagger and not disableStagger:
if clipSize == 0:
duration = int(duration / amount)
@@ -193,7 +194,7 @@ class CapSimulator(object):
# calculate EVE's stability value
try:
avgDrain = reduce(float.__add__, map(lambda x: x[2] / x[1], self.state), 0.0)
avgDrain = reduce(float.__add__, [x[2] / x[1] for x in self.state], 0.0)
self.cap_stable_eve = 0.25 * (1.0 + sqrt(-(2.0 * avgDrain * tau - capCapacity) / capCapacity)) ** 2
except ValueError:
self.cap_stable_eve = 0.0

View File

@@ -11,14 +11,14 @@ debug = False
gamedataCache = True
saveddataCache = True
gamedata_version = ""
gamedata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "eve.db")), sys.getfilesystemencoding())
gamedata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "eve.db"))
pyfalog.debug("Gamedata connection string: {0}", gamedata_connectionstring)
if istravis is True or hasattr(sys, '_called_from_test'):
# Running in Travis. Run saveddata database in memory.
saveddata_connectionstring = 'sqlite:///:memory:'
else:
saveddata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata.db")), sys.getfilesystemencoding())
saveddata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata-py3-db.db"))
pyfalog.debug("Saveddata connection string: {0}", saveddata_connectionstring)
@@ -28,4 +28,4 @@ settings = {
}
# Autodetect path, only change if the autodetection bugs out.
path = dirname(unicode(__file__, sys.getfilesystemencoding()))
path = dirname(__file__)

View File

@@ -22,7 +22,7 @@ import threading
from sqlalchemy import MetaData, create_engine
from sqlalchemy.orm import sessionmaker
import migration
from . import migration
from eos import config
from logbook import Logger
@@ -76,7 +76,7 @@ sd_lock = threading.RLock()
# noinspection PyPep8
from eos.db.gamedata import alphaClones, attribute, category, effect, group, icon, item, marketGroup, metaData, metaGroup, queries, traits, unit
# noinspection PyPep8
from eos.db.saveddata import booster, cargo, character, crest, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, loadDefaultDatabaseValues, \
from eos.db.saveddata import booster, cargo, character, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, loadDefaultDatabaseValues, \
miscData, module, override, price, queries, skill, targetResists, user
# Import queries

View File

@@ -81,7 +81,7 @@ def getItem(lookfor, eager=None):
item = gamedata_session.query(Item).get(lookfor)
else:
item = gamedata_session.query(Item).options(*processEager(eager)).filter(Item.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in itemNameMap:
id = itemNameMap[lookfor]
if eager is None:
@@ -154,7 +154,7 @@ def getGroup(lookfor, eager=None):
group = gamedata_session.query(Group).get(lookfor)
else:
group = gamedata_session.query(Group).options(*processEager(eager)).filter(Group.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in groupNameMap:
id = groupNameMap[lookfor]
if eager is None:
@@ -181,7 +181,7 @@ def getCategory(lookfor, eager=None):
else:
category = gamedata_session.query(Category).options(*processEager(eager)).filter(
Category.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in categoryNameMap:
id = categoryNameMap[lookfor]
if eager is None:
@@ -210,7 +210,7 @@ def getMetaGroup(lookfor, eager=None):
else:
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(
MetaGroup.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in metaGroupNameMap:
id = metaGroupNameMap[lookfor]
if eager is None:
@@ -245,7 +245,7 @@ def getMarketGroup(lookfor, eager=None):
def getItemsByCategory(filter, where=None, eager=None):
if isinstance(filter, int):
filter = Category.ID == filter
elif isinstance(filter, basestring):
elif isinstance(filter, str):
filter = Category.name == filter
else:
raise TypeError("Need integer or string as argument")
@@ -257,7 +257,7 @@ def getItemsByCategory(filter, where=None, eager=None):
@cachedQuery(3, "where", "nameLike", "join")
def searchItems(nameLike, where=None, join=None, eager=None):
if not isinstance(nameLike, basestring):
if not isinstance(nameLike, str):
raise TypeError("Need string as argument")
if join is None:
@@ -268,7 +268,7 @@ def searchItems(nameLike, where=None, join=None, eager=None):
items = gamedata_session.query(Item).options(*processEager(eager)).join(*join)
for token in nameLike.split(' '):
token_safe = u"%{0}%".format(sqlizeString(token))
token_safe = "%{0}%".format(sqlizeString(token))
if where is not None:
items = items.filter(and_(Item.name.like(token_safe, escape="\\"), where))
else:
@@ -279,12 +279,12 @@ def searchItems(nameLike, where=None, join=None, eager=None):
@cachedQuery(3, "where", "nameLike", "join")
def searchSkills(nameLike, where=None, eager=None):
if not isinstance(nameLike, basestring):
if not isinstance(nameLike, str):
raise TypeError("Need string as argument")
items = gamedata_session.query(Item).options(*processEager(eager)).join(Item.group, Group.category)
for token in nameLike.split(' '):
token_safe = u"%{0}%".format(sqlizeString(token))
token_safe = "%{0}%".format(sqlizeString(token))
if where is not None:
items = items.filter(and_(Item.name.like(token_safe, escape="\\"), Category.ID == 16, where))
else:
@@ -322,7 +322,7 @@ def getVariations(itemids, groupIDs=None, where=None, eager=None):
@cachedQuery(1, "attr")
def getAttributeInfo(attr, eager=None):
if isinstance(attr, basestring):
if isinstance(attr, str):
filter = AttributeInfo.name == attr
elif isinstance(attr, int):
filter = AttributeInfo.ID == attr
@@ -337,7 +337,7 @@ def getAttributeInfo(attr, eager=None):
@cachedQuery(1, "field")
def getMetaData(field):
if isinstance(field, basestring):
if isinstance(field, str):
data = gamedata_session.query(MetaData).get(field)
else:
raise TypeError("Need string as argument")
@@ -367,7 +367,7 @@ def getRequiredFor(itemID, attrMapping):
skillToLevelClauses = []
for attrSkill, attrLevel in attrMapping.iteritems():
for attrSkill, attrLevel in attrMapping.items():
skillToLevelClauses.append(and_(Attribute1.attributeID == attrSkill, Attribute2.attributeID == attrLevel))
queryOr = or_(*skillToLevelClauses)

View File

@@ -3,7 +3,7 @@ import shutil
import time
import config
import migrations
from . import migrations
pyfalog = Logger(__name__)
@@ -34,7 +34,7 @@ def update(saveddata_engine):
shutil.copyfile(config.saveDB, toFile)
for version in xrange(dbVersion, appVersion):
for version in range(dbVersion, appVersion):
func = migrations.updates[version + 1]
if func:
pyfalog.info("Applying database update: {0}", version + 1)

View File

@@ -15,7 +15,27 @@ updates = {}
appVersion = 0
prefix = __name__ + "."
for importer, modname, ispkg in pkgutil.iter_modules(__path__, prefix):
# load modules to work based with and without pyinstaller
# from: https://github.com/webcomics/dosage/blob/master/dosagelib/loader.py
# see: https://github.com/pyinstaller/pyinstaller/issues/1905
# load modules using iter_modules()
# (should find all filters in normal build, but not pyinstaller)
module_names = [m[1] for m in pkgutil.iter_modules(__path__, prefix)]
# special handling for PyInstaller
importers = map(pkgutil.get_importer, __path__)
toc = set()
for i in importers:
if hasattr(i, 'toc'):
toc |= i.toc
for elm in toc:
if elm.startswith(prefix):
module_names.append(elm)
for modname in module_names:
# loop through python files, extracting update number and function, and
# adding it to a list
modname_tail = modname.rsplit('.', 1)[-1]

View File

@@ -91,7 +91,7 @@ def upgrade(saveddata_engine):
saveddata_engine.execute("ALTER TABLE fits ADD COLUMN targetResistsID INTEGER;")
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -108,7 +108,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -332,7 +332,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -60,7 +60,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -29,7 +29,7 @@ def upgrade(saveddata_engine):
"targetResists": 2
}
for table in tables.keys():
for table in list(tables.keys()):
# midnight brain, there's probably a much more simple way to do this, but fuck it
if tables[table] > 0:

View File

@@ -4204,7 +4204,7 @@ conversion2 = {
def upgrade(saveddata_engine):
# First we want to get a list of fittings that are completely fitted out with subsystems
oldItems = [str(x) for x in conversion2.iterkeys()]
oldItems = [str(x) for x in conversion2.keys()]
# I can't figure out a way to get IN operator to work when supplying a list using a parameterized query. So I'm
# doing it the shitty way by formatting the SQL string. Don't do this kids!
@@ -4239,7 +4239,7 @@ def upgrade(saveddata_engine):
# if something fails, fuck it, we tried. It'll default to the generic conversion below
continue
for oldItem, newItem in conversion2.iteritems():
for oldItem, newItem in conversion2.items():
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(newItem, oldItem))
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',

View File

@@ -133,7 +133,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -17,7 +17,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert ships
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "fits" SET "shipID" = ? WHERE "shipID" = ?',
(replacement_item, retired_item))

View File

@@ -77,7 +77,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -12,7 +12,6 @@ __all__ = [
"miscData",
"targetResists",
"override",
"crest",
"implantSet",
"loadDefaultDatabaseValues"
]

View File

@@ -17,24 +17,24 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Float
from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Float, UniqueConstraint
from sqlalchemy.orm import relation, mapper
import datetime
from eos.db import saveddata_meta
from eos.db.saveddata.implant import charImplants_table
from eos.effectHandlerHelpers import HandledImplantBoosterList
from eos.effectHandlerHelpers import HandledImplantBoosterList, HandledSsoCharacterList
from eos.saveddata.implant import Implant
from eos.saveddata.user import User
from eos.saveddata.character import Character, Skill
from eos.saveddata.ssocharacter import SsoCharacter
characters_table = Table("characters", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("name", String, nullable=False),
Column("apiID", Integer),
Column("apiKey", String),
Column("defaultChar", Integer),
Column("chars", String, nullable=True),
Column("defaultLevel", Integer, nullable=True),
Column("alphaCloneID", Integer, nullable=True),
Column("ownerID", ForeignKey("users.ID"), nullable=True),
@@ -42,6 +42,28 @@ characters_table = Table("characters", saveddata_meta,
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
sso_table = Table("ssoCharacter", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("client", String, nullable=False),
Column("characterID", Integer, nullable=False),
Column("characterName", String, nullable=False),
Column("refreshToken", String, nullable=False),
Column("accessToken", String, nullable=False),
Column("accessTokenExpires", DateTime, nullable=False),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
UniqueConstraint('client', 'characterID', name='uix_client_characterID'),
UniqueConstraint('client', 'characterName', name='uix_client_characterName')
)
sso_character_map_table = Table("ssoCharacterMap", saveddata_meta,
Column("characterID", ForeignKey("characters.ID"), primary_key=True),
Column("ssoCharacterID", ForeignKey("ssoCharacter.ID"), primary_key=True),
)
mapper(SsoCharacter, sso_table)
mapper(Character, characters_table,
properties={
"_Character__alphaCloneID": characters_table.c.alphaCloneID,
@@ -63,5 +85,10 @@ mapper(Character, characters_table,
primaryjoin=charImplants_table.c.charID == characters_table.c.ID,
secondaryjoin=charImplants_table.c.implantID == Implant.ID,
secondary=charImplants_table),
"_Character__ssoCharacters" : relation(
SsoCharacter,
collection_class=HandledSsoCharacterList,
backref='characters',
secondary=sso_character_map_table)
}
)

View File

@@ -1,34 +0,0 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from sqlalchemy import Table, Column, Integer, String, DateTime
from sqlalchemy.orm import mapper
import datetime
from eos.db import saveddata_meta
from eos.saveddata.crestchar import CrestChar
crest_table = Table("crest", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("name", String, nullable=False, unique=True),
Column("refresh_token", String, nullable=False),
# These records aren't updated. Instead, they are dropped and created, hence we don't have a modified field
Column("created", DateTime, nullable=True, default=datetime.datetime.now))
mapper(CrestChar, crest_table)

View File

@@ -27,7 +27,7 @@ from eos.db.saveddata.fit import projectedFits_table
from eos.db.util import processEager, processWhere
from eos.saveddata.price import Price
from eos.saveddata.user import User
from eos.saveddata.crestchar import CrestChar
from eos.saveddata.ssocharacter import SsoCharacter
from eos.saveddata.damagePattern import DamagePattern
from eos.saveddata.targetResists import TargetResists
from eos.saveddata.character import Character
@@ -109,9 +109,9 @@ if configVal is True:
if type not in queryCache:
return
functionCache = queryCache[type]
for _, localCache in functionCache.iteritems():
for _, localCache in functionCache.items():
toDelete = set()
for cacheKey, info in localCache.iteritems():
for cacheKey, info in localCache.items():
IDs = info[1]
if ID in IDs:
toDelete.add(cacheKey)
@@ -156,7 +156,7 @@ def getUser(lookfor, eager=None):
eager = processEager(eager)
with sd_lock:
user = saveddata_session.query(User).options(*eager).filter(User.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
user = saveddata_session.query(User).options(*eager).filter(User.username == lookfor).first()
@@ -175,7 +175,7 @@ def getCharacter(lookfor, eager=None):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(Character).options(*eager).filter(Character.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(Character).options(*eager).filter(
@@ -337,7 +337,7 @@ def clearPrices():
def getMiscData(field):
if isinstance(field, basestring):
if isinstance(field, str):
with sd_lock:
data = saveddata_session.query(MiscData).get(field)
else:
@@ -391,7 +391,7 @@ def getDamagePattern(lookfor, eager=None):
with sd_lock:
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
DamagePattern.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
@@ -412,7 +412,7 @@ def getTargetResists(lookfor, eager=None):
with sd_lock:
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
TargetResists.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
@@ -433,7 +433,7 @@ def getImplantSet(lookfor, eager=None):
with sd_lock:
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(
TargetResists.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(TargetResists.name == lookfor).first()
@@ -443,10 +443,10 @@ def getImplantSet(lookfor, eager=None):
def searchFits(nameLike, where=None, eager=None):
if not isinstance(nameLike, basestring):
if not isinstance(nameLike, str):
raise TypeError("Need string as argument")
# Prepare our string for request
nameLike = u"%{0}%".format(sqlizeString(nameLike))
nameLike = "%{0}%".format(sqlizeString(nameLike))
# Add any extra components to the search to our where clause
filter = processWhere(Fit.name.like(nameLike, escape="\\"), where)
@@ -467,29 +467,28 @@ def getProjectedFits(fitID):
raise TypeError("Need integer as argument")
def getCrestCharacters(eager=None):
def getSsoCharacters(clientHash, eager=None):
eager = processEager(eager)
with sd_lock:
characters = saveddata_session.query(CrestChar).options(*eager).all()
characters = saveddata_session.query(SsoCharacter).filter(SsoCharacter.client == clientHash).options(*eager).all()
return characters
@cachedQuery(CrestChar, 1, "lookfor")
def getCrestCharacter(lookfor, eager=None):
@cachedQuery(SsoCharacter, 1, "lookfor", "clientHash")
def getSsoCharacter(lookfor, clientHash, eager=None):
filter = SsoCharacter.client == clientHash
if isinstance(lookfor, int):
if eager is None:
with sd_lock:
character = saveddata_session.query(CrestChar).get(lookfor)
else:
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(CrestChar).options(*eager).filter(CrestChar.ID == lookfor).first()
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(CrestChar).options(*eager).filter(CrestChar.name == lookfor).first()
filter = and_(filter, SsoCharacter.ID == lookfor)
elif isinstance(lookfor, str):
filter = and_(filter, SsoCharacter.characterName == lookfor)
else:
raise TypeError("Need integer or string as argument")
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(SsoCharacter).options(*eager).filter(filter).first()
return character
@@ -515,8 +514,8 @@ def removeInvalid(fits):
invalids = [f for f in fits if f.isInvalid]
if invalids:
map(fits.remove, invalids)
map(saveddata_session.delete, invalids)
list(map(fits.remove, invalids))
list(map(saveddata_session.delete, invalids))
saveddata_session.commit()
return fits
@@ -544,7 +543,7 @@ def commit():
try:
saveddata_session.commit()
saveddata_session.flush()
except Exception:
except Exception as ex:
saveddata_session.rollback()
exc_info = sys.exc_info()
raise exc_info[0], exc_info[1], exc_info[2]
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])

View File

@@ -39,7 +39,7 @@ def processEager(eager):
return tuple()
else:
l = []
if isinstance(eager, basestring):
if isinstance(eager, str):
eager = (eager,)
for e in eager:
@@ -50,7 +50,7 @@ def processEager(eager):
def _replacements(eagerString):
splitEager = eagerString.split(".")
for i in xrange(len(splitEager)):
for i in range(len(splitEager)):
part = splitEager[i]
replacement = replace.get(part)
if replacement:

View File

@@ -115,7 +115,7 @@ class HandledList(list):
class HandledModuleList(HandledList):
def append(self, mod):
emptyPosition = float("Inf")
for i in xrange(len(self)):
for i in range(len(self)):
currMod = self[i]
if currMod.isEmpty and not mod.isEmpty and currMod.slot == mod.slot:
currPos = mod.position or i
@@ -149,7 +149,7 @@ class HandledModuleList(HandledList):
oldPos = mod.position
mod.position = None
for i in xrange(oldPos, len(self)):
for i in range(oldPos, len(self)):
self[i].position -= 1
def toDummy(self, index):
@@ -205,6 +205,16 @@ class HandledImplantBoosterList(HandledList):
HandledList.append(self, thing)
class HandledSsoCharacterList(list):
def append(self, character):
old = next((x for x in self if x.client == character.client), None)
if old is not None:
pyfalog.warning("Removing SSO Character with same hash: {}".format(repr(old)))
list.remove(self, old)
list.append(self, character)
class HandledProjectedModList(HandledList):
def append(self, proj):
if proj.isInvalid:

View File

@@ -10,4 +10,6 @@ type = "passive"
def handler(fit, module, context):
fit.ship.multiplyItemAttr("capacitorCapacity", module.getModifiedItemAttr("capacitorCapacityMultiplier"))
# We default this to None as there are times when the source attribute doesn't exist (for example, Cap Power Relay).
# It will return 0 as it doesn't exist, which would nullify whatever the target attribute is
fit.ship.multiplyItemAttr("capacitorCapacity", module.getModifiedItemAttr("capacitorCapacityMultiplier", None))

View File

@@ -6,6 +6,6 @@ type = "active"
def handler(fit, module, context):
for x in xrange(1, 4):
for x in range(1, 4):
value = module.getModifiedChargeAttr("warfareBuff{}Multiplier".format(x))
module.multiplyItemAttr("warfareBuff{}Value".format(x), value)

View File

@@ -8,7 +8,7 @@ type = "passive"
def handler(fit, container, context):
level = container.level if "skill" in context else 1
for i in xrange(5):
for i in range(5):
attr = "boosterEffectChance{0}".format(i + 1)
fit.boosters.filteredItemBoost(lambda booster: attr in booster.itemModifiedAttributes,
attr, container.getModifiedItemAttr("boosterChanceBonus") * level)

View File

@@ -16,7 +16,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -6,7 +6,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedItemAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedItemAttr("warfareBuff{}ID".format(x))

View File

@@ -9,4 +9,6 @@ type = "passive"
def handler(fit, module, context):
fit.ship.multiplyItemAttr("powerOutput", module.getModifiedItemAttr("powerOutputMultiplier"))
# We default this to None as there are times when the source attribute doesn't exist (for example, Cap Power Relay).
# It will return 0 as it doesn't exist, which would nullify whatever the target attribute is
fit.ship.multiplyItemAttr("powerOutput", module.getModifiedItemAttr("powerOutputMultiplier", None))

View File

@@ -9,4 +9,6 @@ type = "passive"
def handler(fit, module, context):
fit.ship.multiplyItemAttr("shieldCapacity", module.getModifiedItemAttr("shieldCapacityMultiplier"))
# We default this to None as there are times when the source attribute doesn't exist (for example, Cap Power Relay).
# It will return 0 as it doesn't exist, which would nullify whatever the target attribute is
fit.ship.multiplyItemAttr("shieldCapacity", module.getModifiedItemAttr("shieldCapacityMultiplier", None))

View File

@@ -4,5 +4,5 @@ runTime = "late"
def handler(fit, module, context):
for x in xrange(1, 4):
for x in range(1, 4):
module.boostChargeAttr("warfareBuff{}Multiplier".format(x), module.getModifiedItemAttr("commandBurstStrengthBonus"))

View File

@@ -1,7 +1,3 @@
# warpDisruptSphere
#
# Used by:
# Modules from group: Warp Disrupt Field Generator (7 of 7)
# warpDisruptSphere
#

View File

@@ -16,7 +16,10 @@ def handler(fit, module, context):
# this is such a dirty hack
for mod in fit.modules:
if not mod.isEmpty and mod.item.requiresSkill("High Speed Maneuvering") and mod.state > State.ONLINE:
if not mod.isEmpty and mod.state > State.ONLINE and (
mod.item.requiresSkill("Micro Jump Drive Operation")
or mod.item.requiresSkill("High Speed Maneuvering")
):
mod.state = State.ONLINE
if not mod.isEmpty and mod.item.requiresSkill("Micro Jump Drive Operation") and mod.state > State.ONLINE:
mod.state = State.ONLINE

View File

@@ -58,7 +58,7 @@ def rel_listener(target, value, initiator):
if not target or (isinstance(value, Module) and value.isEmpty):
return
print "{} has had a relationship change :D".format(target)
print("{} has had a relationship change :D".format(target))
target.modified = datetime.datetime.now()

View File

@@ -22,13 +22,10 @@ import re
from sqlalchemy.orm import reconstructor
import eos.db
from eqBase import EqBase
from .eqBase import EqBase
from eos.saveddata.price import Price as types_Price
from collections import OrderedDict
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
from logbook import Logger
@@ -160,8 +157,6 @@ class Effect(EqBase):
if it doesn't, set dummy values and add a dummy handler
"""
pyfalog.debug("Generate effect handler for {}".format(self.name))
try:
self.__effectModule = effectModule = __import__('eos.effects.' + self.handlerName, fromlist=True)
self.__handler = getattr(effectModule, "handler", effectDummy)
@@ -258,7 +253,7 @@ class Item(EqBase):
return default
def isType(self, type):
for effect in self.effects.itervalues():
for effect in self.effects.values():
if effect.isType(type):
return True
@@ -299,7 +294,7 @@ class Item(EqBase):
self.__requiredSkills = requiredSkills
# Map containing attribute IDs we may need for required skills
# { requiredSkillX : requiredSkillXLevel }
combinedAttrIDs = set(self.srqIDMap.iterkeys()).union(set(self.srqIDMap.itervalues()))
combinedAttrIDs = set(self.srqIDMap.keys()).union(set(self.srqIDMap.values()))
# Map containing result of the request
# { attributeID : attributeValue }
skillAttrs = {}
@@ -309,7 +304,7 @@ class Item(EqBase):
attrVal = attrInfo[2]
skillAttrs[attrID] = attrVal
# Go through all attributeID pairs
for srqIDAtrr, srqLvlAttr in self.srqIDMap.iteritems():
for srqIDAtrr, srqLvlAttr in self.srqIDMap.items():
# Check if we have both in returned result
if srqIDAtrr in skillAttrs and srqLvlAttr in skillAttrs:
skillID = int(skillAttrs[srqIDAtrr])
@@ -383,7 +378,7 @@ class Item(EqBase):
race = None
# Check primary and secondary required skills' races
if race is None:
skillRaces = tuple(filter(lambda rid: rid, (s.raceID for s in tuple(self.requiredSkills.keys()))))
skillRaces = tuple([rid for rid in (s.raceID for s in tuple(self.requiredSkills.keys())) if rid])
if sum(skillRaces) in map:
race = map[sum(skillRaces)]
if race == "angelserp":
@@ -405,7 +400,7 @@ class Item(EqBase):
if self.__assistive is None:
assistive = False
# Go through all effects and find first assistive
for effect in self.effects.itervalues():
for effect in self.effects.values():
if effect.isAssistance is True:
# If we find one, stop and mark item as assistive
assistive = True
@@ -420,7 +415,7 @@ class Item(EqBase):
if self.__offensive is None:
offensive = False
# Go through all effects and find first offensive
for effect in self.effects.itervalues():
for effect in self.effects.values():
if effect.isOffensive is True:
# If we find one, stop and mark item as offensive
offensive = True
@@ -429,8 +424,8 @@ class Item(EqBase):
return self.__offensive
def requiresSkill(self, skill, level=None):
for s, l in self.requiredSkills.iteritems():
if isinstance(skill, basestring):
for s, l in self.requiredSkills.items():
if isinstance(skill, str):
if s.name == skill and (level is None or l == level):
return True
@@ -468,7 +463,7 @@ class Item(EqBase):
return self.__price
def __repr__(self):
return u"Item(ID={}, name={}) at {}".format(
return "Item(ID={}, name={}) at {}".format(
self.ID, self.name, hex(id(self))
)
@@ -522,9 +517,9 @@ class Icon(EqBase):
class MarketGroup(EqBase):
def __repr__(self):
return u"MarketGroup(ID={}, name={}, parent={}) at {}".format(
return "MarketGroup(ID={}, name={}, parent={}) at {}".format(
self.ID, self.name, getattr(self.parent, "name", None), self.name, hex(id(self))
).encode('utf8')
)
class MetaGroup(EqBase):

View File

@@ -25,7 +25,7 @@ class Graph(object):
self.fit = fit
self.data = {}
if data is not None:
for name, d in data.iteritems():
for name, d in data.items():
self.setData(Data(name, d))
self.function = function
@@ -39,7 +39,7 @@ class Graph(object):
def getIterator(self):
pointNames = []
pointIterators = []
for data in self.data.itervalues():
for data in self.data.values():
pointNames.append(data.name)
pointIterators.append(data)
@@ -48,7 +48,7 @@ class Graph(object):
def _iterator(self, pointNames, pointIterators):
for pointValues in itertools.product(*pointIterators):
point = {}
for i in xrange(len(pointValues)):
for i in range(len(pointValues)):
point[pointNames[i]] = pointValues[i]
yield point, self.function(point)
@@ -61,12 +61,12 @@ class Data(object):
self.data = self.parseString(dataString)
def parseString(self, dataString):
if not isinstance(dataString, basestring):
if not isinstance(dataString, str):
return Constant(dataString),
dataList = []
for data in dataString.split(";"):
if isinstance(data, basestring) and "-" in data:
if isinstance(data, str) and "-" in data:
# Dealing with a range
dataList.append(Range(data, self.step))
else:
@@ -85,7 +85,7 @@ class Data(object):
class Constant(object):
def __init__(self, const):
if isinstance(const, basestring):
if isinstance(const, str):
self.value = None if const == "" else float(const)
else:
self.value = const

View File

@@ -63,10 +63,10 @@ class FitDpsGraph(Graph):
ew['signatureRadius'].sort(key=abssort)
ew['velocity'].sort(key=abssort)
for attr, values in ew.iteritems():
for attr, values in ew.items():
val = data[attr]
try:
for i in xrange(len(values)):
for i in range(len(values)):
bonus = values[i]
val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
data[attr] = val
@@ -81,7 +81,7 @@ class FitDpsGraph(Graph):
total += dps * self.calculateTurretMultiplier(mod, data)
elif mod.hardpoint == Hardpoint.MISSILE:
if mod.state >= State.ACTIVE and mod.maxRange >= distance:
if mod.state >= State.ACTIVE and mod.maxRange is not None and mod.maxRange >= distance:
total += dps * self.calculateMissileMultiplier(mod, data)
if distance <= fit.extraAttributes["droneControlRange"]:

View File

@@ -28,23 +28,17 @@ cappingAttrKeyCache = {}
class ItemAttrShortcut(object):
def getModifiedItemAttr(self, key, default=None):
def getModifiedItemAttr(self, key, default=0):
return_value = self.itemModifiedAttributes.get(key)
if return_value is None and default is not None:
return_value = default
return return_value
return return_value or default
class ChargeAttrShortcut(object):
def getModifiedChargeAttr(self, key, default=None):
def getModifiedChargeAttr(self, key, default=0):
return_value = self.chargeModifiedAttributes.get(key)
if return_value is None and default is not None:
return_value = default
return return_value
return return_value or default
class ModifiedAttributeDict(collections.MutableMapping):
@@ -165,9 +159,9 @@ class ModifiedAttributeDict(collections.MutableMapping):
def __len__(self):
keys = set()
keys.update(self.original.iterkeys())
keys.update(self.__modified.iterkeys())
keys.update(self.__intermediary.iterkeys())
keys.update(iter(self.original.keys()))
keys.update(iter(self.__modified.keys()))
keys.update(iter(self.__intermediary.keys()))
return len(keys)
def __calculateValue(self, key):
@@ -231,11 +225,11 @@ class ModifiedAttributeDict(collections.MutableMapping):
val *= multiplier
# Each group is penalized independently
# Things in different groups will not be stack penalized between each other
for penalizedMultipliers in penalizedMultiplierGroups.itervalues():
for penalizedMultipliers in penalizedMultiplierGroups.values():
# A quick explanation of how this works:
# 1: Bonuses and penalties are calculated seperately, so we'll have to filter each of them
l1 = filter(lambda _val: _val > 1, penalizedMultipliers)
l2 = filter(lambda _val: _val < 1, penalizedMultipliers)
l1 = [_val for _val in penalizedMultipliers if _val > 1]
l2 = [_val for _val in penalizedMultipliers if _val < 1]
# 2: The most significant bonuses take the smallest penalty,
# This means we'll have to sort
abssort = lambda _val: -abs(_val - 1)
@@ -245,7 +239,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
# Any module after the first takes penalties according to:
# 1 + (multiplier - 1) * math.exp(- math.pow(i, 2) / 7.1289)
for l in (l1, l2):
for i in xrange(len(l)):
for i in range(len(l)):
bonus = l[i]
val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
val += postIncrease
@@ -388,7 +382,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
"""Force value to attribute and prohibit any changes to it"""
self.__forced[attributeName] = value
self.__placehold(attributeName)
self.__afflict(attributeName, u"\u2263", value)
self.__afflict(attributeName, "\u2263", value)
@staticmethod
def getResistance(fit, effect):

View File

@@ -116,7 +116,7 @@ class Booster(HandledItem, ItemAttrShortcut):
if not self.active:
return
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
(effect.isType("passive") or effect.isType("boosterSideEffect")):
if effect.isType("boosterSideEffect") and effect not in self.activeSideEffectEffects:

View File

@@ -39,7 +39,7 @@ class BoosterSideEffect(object):
self.__effect = None
if self.effectID:
self.__effect = next((x for x in self.booster.item.effects.itervalues() if x.ID == self.effectID), None)
self.__effect = next((x for x in self.booster.item.effects.values() if x.ID == self.effectID), None)
if self.__effect is None:
pyfalog.error("Effect (id: {0}) does not exist", self.effectID)
return

View File

@@ -77,8 +77,8 @@ class Cargo(HandledItem, ItemAttrShortcut):
"amount": lambda _val: isinstance(_val, int)
}
if key == "amount" and val > sys.maxint:
val = sys.maxint
if key == "amount" and val > sys.maxsize:
val = sys.maxsize
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -119,16 +119,9 @@ class Character(object):
return all0
def apiUpdateCharSheet(self, skills, secStatus=0):
for skillRow in skills:
try:
skill = self.getSkill(int(skillRow["typeID"]))
skill.setLevel(int(skillRow["level"]), persist=True, ignoreRestrict=True)
except:
# if setting a skill doesn't work, it's not the end of the world, just quietly pass
pass
self.secStatus = secStatus
def clearSkills(self):
del self.__skills[:]
self.__skillIdMap.clear()
@property
def ro(self):
@@ -162,7 +155,7 @@ class Character(object):
name += " *"
if self.alphaCloneID:
name += u' (\u03B1)'
name += ' (\u03B1)'
return name
@@ -170,6 +163,18 @@ class Character(object):
def name(self, name):
self.savedName = name
def setSsoCharacter(self, character, clientHash):
if character is not None:
self.__ssoCharacters.append(character)
else:
for x in self.__ssoCharacters:
if x.client == clientHash:
self.__ssoCharacters.remove(x)
def getSsoCharacter(self, clientHash):
return next((x for x in self.__ssoCharacters if x.client == clientHash), None)
@property
def alphaCloneID(self):
return self.__alphaCloneID
@@ -199,7 +204,7 @@ class Character(object):
del self.__skillIdMap[skill.itemID]
def getSkill(self, item):
if isinstance(item, basestring):
if isinstance(item, str):
item = self.getSkillNameMap()[item]
elif isinstance(item, int):
item = self.getSkillIDMap()[item]
@@ -282,7 +287,7 @@ class Character(object):
map = {
"ID" : lambda _val: isinstance(_val, int),
"name" : lambda _val: True,
"apiKey" : lambda _val: _val is None or (isinstance(_val, basestring) and len(_val) > 0),
"apiKey" : lambda _val: _val is None or (isinstance(_val, str) and len(_val) > 0),
"ownerID": lambda _val: isinstance(_val, int) or _val is None
}
@@ -344,13 +349,13 @@ class Skill(HandledItem):
elif self.character.name == "All 0":
self.activeLevel = self.__level = 0
elif self.character.alphaClone:
return min(self.activeLevel, self.character.alphaClone.getSkillLevel(self)) or 0
return min(self.activeLevel or 0, self.character.alphaClone.getSkillLevel(self) or 0)
return self.activeLevel or 0
def setLevel(self, level, persist=False, ignoreRestrict=False):
if (level < 0 or level > 5) and level is not None:
if level is not None and (level < 0 or level > 5):
raise ValueError(str(level) + " is not a valid value for level")
if hasattr(self, "_Skill__ro") and self.__ro is True:
@@ -362,9 +367,9 @@ class Skill(HandledItem):
# which affects performance. Should have a checkSkillLevels() or something that is more efficient for bulk.
if not ignoreRestrict and eos.config.settings['strictSkillLevels']:
start = time.time()
for item, rlevel in self.item.requiredFor.iteritems():
for item, rlevel in self.item.requiredFor.items():
if item.group.category.ID == 16: # Skill category
if level < rlevel:
if level is None or level < rlevel:
skill = self.character.getSkill(item.ID)
# print "Removing skill: {}, Dependant level: {}, Required level: {}".format(skill, level, rlevel)
skill.setLevel(None, persist)
@@ -392,7 +397,7 @@ class Skill(HandledItem):
if key in self.item.attributes:
return self.item.attributes[key].value
else:
return None
return 0
def calculateModifiedAttributes(self, fit, runTime):
if self.__suppressed: # or not self.learned - removed for GH issue 101
@@ -402,7 +407,7 @@ class Skill(HandledItem):
if item is None:
return
for effect in item.effects.itervalues():
for effect in item.effects.values():
if effect.runTime == runTime and \
effect.isType("passive") and \
(not fit.isStructure or effect.isType("structure")) and \

View File

@@ -73,7 +73,8 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.__itemModifiedAttributes.overrides = self.__item.overrides
self.__chargeModifiedAttributes = ModifiedAttributeDict()
chargeID = self.getModifiedItemAttr("entityMissileTypeID")
# pheonix todo: check the attribute itself, not the modified. this will always return 0 now.
chargeID = self.getModifiedItemAttr("entityMissileTypeID", None)
if chargeID is not None:
charge = eos.db.getItem(int(chargeID))
self.__charge = charge
@@ -102,7 +103,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@property
def cycleTime(self):
return max(self.getModifiedItemAttr("duration"), 0)
return max(self.getModifiedItemAttr("duration", 0), 0)
@property
def dealsDamage(self):
@@ -138,8 +139,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
cycleTime = self.getModifiedItemAttr(attr)
volley = sum(
map(lambda d: (getter("%sDamage" % d) or 0) * (1 - getattr(targetResists, "%sAmount" % d, 0)),
self.DAMAGE_TYPES))
[(getter("%sDamage" % d) or 0) * (1 - getattr(targetResists, "%sAmount" % d, 0)) for d in self.DAMAGE_TYPES])
volley *= self.amountActive
volley *= self.getModifiedItemAttr("damageMultiplier") or 1
self.__volley = volley
@@ -155,7 +155,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
getter = self.getModifiedItemAttr
cycleTime = self.getModifiedItemAttr(attr)
volley = sum(map(lambda d: getter(d), self.MINING_ATTRIBUTES)) * self.amountActive
volley = sum([getter(d) for d in self.MINING_ATTRIBUTES]) * self.amountActive
self.__miningyield = volley / (cycleTime / 1000.0)
else:
self.__miningyield = 0
@@ -168,7 +168,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"energyDestabilizationRange", "empFieldRange",
"ecmBurstRange", "maxRange")
for attr in attrs:
maxRange = self.getModifiedItemAttr(attr)
maxRange = self.getModifiedItemAttr(attr, None)
if maxRange is not None:
return maxRange
if self.charge is not None:
@@ -184,7 +184,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def falloff(self):
attrs = ("falloff", "falloffEffectiveness")
for attr in attrs:
falloff = self.getModifiedItemAttr(attr)
falloff = self.getModifiedItemAttr(attr, None)
if falloff is not None:
return falloff
@@ -236,7 +236,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
context = ("drone",)
projected = False
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.activeByDefault and \
((projected is True and effect.isType("projected")) or
@@ -251,7 +251,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
i += 1
if self.charge:
for effect in self.charge.effects.itervalues():
for effect in self.charge.effects.values():
if effect.runTime == runTime and effect.activeByDefault:
effect.handler(fit, self, ("droneCharge",))
@@ -263,8 +263,8 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def fits(self, fit):
fitDroneGroupLimits = set()
for i in xrange(1, 3):
groneGrp = fit.ship.getModifiedItemAttr("allowedDroneGroup%d" % i)
for i in range(1, 3):
groneGrp = fit.ship.getModifiedItemAttr("allowedDroneGroup%d" % i, None)
if groneGrp is not None:
fitDroneGroupLimits.add(int(groneGrp))
if len(fitDroneGroupLimits) == 0:

View File

@@ -98,7 +98,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def __getAbilities(self):
"""Returns list of FighterAbilities that are loaded with data"""
return [FighterAbility(effect) for effect in self.item.effects.values()]
return [FighterAbility(effect) for effect in list(self.item.effects.values())]
def __calculateSlot(self, item):
types = {
@@ -110,7 +110,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"StandupHeavy": Slot.FS_HEAVY
}
for t, slot in types.iteritems():
for t, slot in types.items():
if self.getModifiedItemAttr("fighterSquadronIs{}".format(t)):
return slot
@@ -202,12 +202,12 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"energyDestabilizationRange", "empFieldRange",
"ecmBurstRange", "maxRange")
for attr in attrs:
maxRange = self.getModifiedItemAttr(attr)
maxRange = self.getModifiedItemAttr(attr, None)
if maxRange is not None:
return maxRange
if self.charge is not None:
delay = self.getModifiedChargeAttr("explosionDelay")
speed = self.getModifiedChargeAttr("maxVelocity")
delay = self.getModifiedChargeAttr("explosionDelay", None)
speed = self.getModifiedChargeAttr("maxVelocity", None)
if delay is not None and speed is not None:
return delay / 1000.0 * speed
@@ -218,7 +218,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def falloff(self):
attrs = ("falloff", "falloffEffectiveness")
for attr in attrs:
falloff = self.getModifiedItemAttr(attr)
falloff = self.getModifiedItemAttr(attr, None)
if falloff is not None:
return falloff

View File

@@ -57,7 +57,7 @@ class FighterAbility(object):
self.__effect = None
if self.effectID:
self.__effect = next((x for x in self.fighter.item.effects.itervalues() if x.ID == self.effectID), None)
self.__effect = next((x for x in self.fighter.item.effects.values() if x.ID == self.effectID), None)
if self.__effect is None:
pyfalog.error("Effect (id: {0}) does not exist", self.effectID)
return
@@ -127,8 +127,8 @@ class FighterAbility(object):
if self.attrPrefix == "fighterAbilityLaunchBomb":
# bomb calcs
volley = sum(map(lambda attr: (self.fighter.getModifiedChargeAttr("%sDamage" % attr) or 0) * (
1 - getattr(targetResists, "%sAmount" % attr, 0)), self.DAMAGE_TYPES))
volley = sum([(self.fighter.getModifiedChargeAttr("%sDamage" % attr) or 0) * (
1 - getattr(targetResists, "%sAmount" % attr, 0)) for attr in self.DAMAGE_TYPES])
else:
volley = sum(map(lambda d2, d:
(self.fighter.getModifiedItemAttr(

View File

@@ -258,11 +258,11 @@ class Fit(object):
def projectedFits(self):
# only in extreme edge cases will the fit be invalid, but to be sure do
# not return them.
return [fit for fit in self.__projectedFits.values() if not fit.isInvalid]
return [fit for fit in list(self.__projectedFits.values()) if not fit.isInvalid]
@property
def commandFits(self):
return [fit for fit in self.__commandFits.values() if not fit.isInvalid]
return [fit for fit in list(self.__commandFits.values()) if not fit.isInvalid]
def getProjectionInfo(self, fitID):
return self.projectedOnto.get(fitID, None)
@@ -492,7 +492,7 @@ class Fit(object):
def __runCommandBoosts(self, runTime="normal"):
pyfalog.debug("Applying gang boosts for {0}", repr(self))
for warfareBuffID in self.commandBonuses.keys():
for warfareBuffID in list(self.commandBonuses.keys()):
# Unpack all data required to run effect properly
effect_runTime, value, thing, effect = self.commandBonuses[warfareBuffID]
@@ -676,7 +676,7 @@ class Fit(object):
def __resetDependentCalcs(self):
self.calculated = False
for value in self.projectedOnto.values():
for value in list(self.projectedOnto.values()):
if value.victim_fit: # removing a self-projected fit causes victim fit to be None. @todo: look into why. :3
value.victim_fit.calculated = False
@@ -707,14 +707,14 @@ class Fit(object):
self.__resetDependentCalcs()
# For fits that are under local's Command, we do the same thing
for value in self.boostedOnto.values():
for value in list(self.boostedOnto.values()):
# apparently this is a thing that happens when removing a command fit from a fit and then switching to
# that command fit. Same as projected clears, figure out why.
if value.boosted_fit:
value.boosted_fit.__resetDependentCalcs()
if targetFit and type == CalcType.PROJECTED:
pyfalog.debug(u"Calculating projections from {0} to target {1}", repr(self), repr(targetFit))
pyfalog.debug("Calculating projections from {0} to target {1}", repr(self), repr(targetFit))
projectionInfo = self.getProjectionInfo(targetFit.ID)
# Start applying any command fits that we may have.
@@ -756,7 +756,7 @@ class Fit(object):
# Loop through our run times here. These determine which effects are run in which order.
for runTime in ("early", "normal", "late"):
pyfalog.debug("Run time: {0}", runTime)
# pyfalog.debug("Run time: {0}", runTime)
# Items that are unrestricted. These items are run on the local fit
# first and then projected onto the target fit it one is designated
u = [
@@ -795,7 +795,7 @@ class Fit(object):
# targetFit.register(item, origin=self)
item.calculateModifiedAttributes(targetFit, runTime, False, True)
pyfalog.debug("Command Bonuses: {}".format(self.commandBonuses))
# pyfalog.debug("Command Bonuses: {}".format(self.commandBonuses))
# If we are calculating our local or projected fit and have command bonuses, apply them
if type != CalcType.COMMAND and self.commandBonuses:
@@ -838,7 +838,7 @@ class Fit(object):
for item in c:
if item is not None:
# apply effects onto target fit x amount of times
for _ in xrange(projectionInfo.amount):
for _ in range(projectionInfo.amount):
targetFit.register(item, origin=self)
item.calculateModifiedAttributes(targetFit, runTime, True)
@@ -854,7 +854,7 @@ class Fit(object):
for slotType in (Slot.LOW, Slot.MED, Slot.HIGH, Slot.RIG, Slot.SUBSYSTEM, Slot.SERVICE):
amount = self.getSlotsFree(slotType, True)
if amount > 0:
for _ in xrange(int(amount)):
for _ in range(int(amount)):
self.modules.append(Module.buildEmpty(slotType))
if amount < 0:
@@ -870,7 +870,7 @@ class Fit(object):
self.modules.remove(mod)
def unfill(self):
for i in xrange(len(self.modules) - 1, -1, -1):
for i in range(len(self.modules) - 1, -1, -1):
mod = self.modules[i]
if mod.isEmpty:
del self.modules[i]
@@ -878,7 +878,7 @@ class Fit(object):
@property
def modCount(self):
x = 0
for i in xrange(len(self.modules) - 1, -1, -1):
for i in range(len(self.modules) - 1, -1, -1):
mod = self.modules[i]
if not mod.isEmpty:
x += 1
@@ -1531,11 +1531,11 @@ class Fit(object):
return copy_ship
def __repr__(self):
return u"Fit(ID={}, ship={}, name={}) at {}".format(
return "Fit(ID={}, ship={}, name={}) at {}".format(
self.ID, self.ship.item.name, self.name, hex(id(self))
).encode('utf8')
)
def __str__(self):
return u"{} ({})".format(
return "{} ({})".format(
self.name, self.ship.item.name
).encode('utf8')
)

View File

@@ -93,7 +93,7 @@ class Implant(HandledItem, ItemAttrShortcut):
return
if not self.active:
return
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and effect.isType("passive") and effect.activeByDefault:
effect.handler(fit, self, ("implant",))

View File

@@ -50,6 +50,6 @@ class Mode(ItemAttrShortcut, HandledItem):
def calculateModifiedAttributes(self, fit, runTime, forceProjected=False):
if self.item:
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and effect.activeByDefault:
effect.handler(fit, self, context=("module",))

View File

@@ -182,7 +182,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@property
def numShots(self):
if self.charge is None:
return None
return 0
if self.__chargeCycles is None and self.charge:
numCharges = self.numCharges
# Usual ammo like projectiles and missiles
@@ -217,7 +217,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
armorRep = self.getModifiedItemAttr("armorDamageAmount") or 0
shieldRep = self.getModifiedItemAttr("shieldBonus") or 0
if not cycles or (not armorRep and not shieldRep):
return None
return 0
hp = round((armorRep + shieldRep) * cycles)
return hp
@@ -255,7 +255,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"ecmBurstRange", "warpScrambleRange", "cargoScanRange",
"shipScanRange", "surveyScanRange")
for attr in attrs:
maxRange = self.getModifiedItemAttr(attr)
maxRange = self.getModifiedItemAttr(attr, None)
if maxRange is not None:
return maxRange
if self.charge is not None:
@@ -284,7 +284,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def falloff(self):
attrs = ("falloffEffectiveness", "falloff", "shipScanFalloff")
for attr in attrs:
falloff = self.getModifiedItemAttr(attr)
falloff = self.getModifiedItemAttr(attr, None)
if falloff is not None:
return falloff
@@ -333,9 +333,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
else:
func = self.getModifiedItemAttr
volley = sum(map(
lambda attr: (func("%sDamage" % attr) or 0) * (1 - getattr(targetResists, "%sAmount" % attr, 0)),
self.DAMAGE_TYPES))
volley = sum([(func("%sDamage" % attr) or 0) * (1 - getattr(targetResists, "%sAmount" % attr, 0)) for attr in self.DAMAGE_TYPES])
volley *= self.getModifiedItemAttr("damageMultiplier") or 1
if volley:
cycleTime = self.cycleTime
@@ -422,19 +420,19 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
fitsOnType = set()
fitsOnGroup = set()
shipType = self.getModifiedItemAttr("fitsToShipType")
shipType = self.getModifiedItemAttr("fitsToShipType", None)
if shipType is not None:
fitsOnType.add(shipType)
for attr in self.itemModifiedAttributes.keys():
for attr in list(self.itemModifiedAttributes.keys()):
if attr.startswith("canFitShipType"):
shipType = self.getModifiedItemAttr(attr)
shipType = self.getModifiedItemAttr(attr, None)
if shipType is not None:
fitsOnType.add(shipType)
for attr in self.itemModifiedAttributes.keys():
for attr in list(self.itemModifiedAttributes.keys()):
if attr.startswith("canFitShipGroup"):
shipGroup = self.getModifiedItemAttr(attr)
shipGroup = self.getModifiedItemAttr(attr, None)
if shipGroup is not None:
fitsOnGroup.add(shipGroup)
@@ -466,7 +464,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return False
# Check max group fitted
max = self.getModifiedItemAttr("maxGroupFitted")
max = self.getModifiedItemAttr("maxGroupFitted", None)
if max is not None:
current = 0 # if self.owner != fit else -1 # Disabled, see #1278
for mod in fit.modules:
@@ -479,11 +477,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
# Check this only if we're told to do so
if hardpointLimit:
if self.hardpoint == Hardpoint.TURRET:
if (fit.ship.getModifiedItemAttr('turretSlotsLeft') or 0) - fit.getHardpointsUsed(Hardpoint.TURRET) < 1:
if fit.ship.getModifiedItemAttr('turretSlotsLeft') - fit.getHardpointsUsed(Hardpoint.TURRET) < 1:
return False
elif self.hardpoint == Hardpoint.MISSILE:
if (fit.ship.getModifiedItemAttr('launcherSlotsLeft') or 0) - fit.getHardpointsUsed(
Hardpoint.MISSILE) < 1:
if fit.ship.getModifiedItemAttr('launcherSlotsLeft') - fit.getHardpointsUsed(Hardpoint.MISSILE) < 1:
return False
return True
@@ -513,7 +510,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return True
# Check if the local module is over it's max limit; if it's not, we're fine
maxGroupActive = self.getModifiedItemAttr("maxGroupActive")
maxGroupActive = self.getModifiedItemAttr("maxGroupActive", None)
if maxGroupActive is None and projectedOnto is None:
return True
@@ -561,7 +558,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
chargeGroup = charge.groupID
for i in range(5):
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i))
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i), None)
if itemChargeGroup is None:
continue
if itemChargeGroup == chargeGroup:
@@ -572,7 +569,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def getValidCharges(self):
validCharges = set()
for i in range(5):
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i))
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i), None)
if itemChargeGroup is not None:
g = eos.db.getGroup(int(itemChargeGroup), eager=("items.icon", "items.attributes"))
if g is None:
@@ -593,7 +590,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if item is None:
return Hardpoint.NONE
for effectName, slot in effectHardpointMap.iteritems():
for effectName, slot in effectHardpointMap.items():
if effectName in item.effects:
return slot
@@ -611,7 +608,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
}
if item is None:
return None
for effectName, slot in effectSlotMap.iteritems():
for effectName, slot in effectSlotMap.items():
if effectName in item.effects:
return slot
if item.group.name == "Effect Beacon":
@@ -665,7 +662,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if self.charge is not None:
# fix for #82 and it's regression #106
if not projected or (self.projected and not forceProjected) or gang:
for effect in self.charge.effects.itervalues():
for effect in self.charge.effects.values():
if effect.runTime == runTime and \
effect.activeByDefault and \
(effect.isType("offline") or
@@ -684,7 +681,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if self.item:
if self.state >= State.OVERHEATED:
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.isType("overheat") \
and not forceProjected \
@@ -692,7 +689,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
and ((gang and effect.isType("gang")) or not gang):
effect.handler(fit, self, context)
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.activeByDefault and \
(effect.isType("offline") or
@@ -752,13 +749,12 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@property
def rawCycleTime(self):
speed = max(
self.getModifiedItemAttr("speed"), # Most weapons
self.getModifiedItemAttr("duration"), # Most average modules
self.getModifiedItemAttr("durationSensorDampeningBurstProjector"),
self.getModifiedItemAttr("durationTargetIlluminationBurstProjector"),
self.getModifiedItemAttr("durationECMJammerBurstProjector"),
self.getModifiedItemAttr("durationWeaponDisruptionBurstProjector"),
0, # Return 0 if none of the above are valid
self.getModifiedItemAttr("speed", 0), # Most weapons
self.getModifiedItemAttr("duration", 0), # Most average modules
self.getModifiedItemAttr("durationSensorDampeningBurstProjector", 0),
self.getModifiedItemAttr("durationTargetIlluminationBurstProjector", 0),
self.getModifiedItemAttr("durationECMJammerBurstProjector", 0),
self.getModifiedItemAttr("durationWeaponDisruptionBurstProjector", 0)
)
return speed
@@ -793,7 +789,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def __repr__(self):
if self.item:
return u"Module(ID={}, name={}) at {}".format(
return "Module(ID={}, name={}) at {}".format(
self.item.ID, self.item.name, hex(id(self))
)
else:

View File

@@ -87,7 +87,7 @@ class Ship(ItemAttrShortcut, HandledItem):
def calculateModifiedAttributes(self, fit, runTime, forceProjected=False):
if forceProjected:
return
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.isType("passive") and \
effect.activeByDefault:

View File

@@ -18,17 +18,40 @@
# ===============================================================================
from sqlalchemy.orm import reconstructor
import datetime
import time
# from tomorrow import threads
class CrestChar(object):
def __init__(self, id, name, refresh_token=None):
self.ID = id
self.name = name
self.refresh_token = refresh_token
class SsoCharacter(object):
def __init__(self, charID, name, client, accessToken=None, refreshToken=None):
self.characterID = charID
self.characterName = name
self.client = client
self.accessToken = accessToken
self.refreshToken = refreshToken
self.accessTokenExpires = None
self.esi_client = None
@reconstructor
def init(self):
pass
self.esi_client = None
def get_sso_data(self):
""" Little "helper" function to get formated data for esipy security
"""
return {
'access_token': self.accessToken,
'refresh_token': self.refreshToken,
'expires_in': (
self.accessTokenExpires - datetime.datetime.utcnow()
).total_seconds()
}
def __repr__(self):
return "SsoCharacter(ID={}, name={}, client={}) at {}".format(
self.ID, self.characterName, self.client, hex(id(self))
)

View File

@@ -33,7 +33,7 @@ class User(object):
def encodeAndSetPassword(self, pw):
h = hashlib.new("sha256")
salt = "".join([random.choice(string.letters) for _ in xrange(32)])
salt = "".join([random.choice(string.letters) for _ in range(32)])
h.update(pw)
h.update(salt)
self.password = ("%s%s" % (h.hexdigest(), salt))
@@ -45,14 +45,14 @@ class User(object):
h = hashlib.new("sha256")
h.update(pw)
h.update(salt)
return self.password == (u"%s%s" % (h.hexdigest(), salt))
return self.password == ("%s%s" % (h.hexdigest(), salt))
@validates("ID", "username", "password", "admin")
def validator(self, key, val):
map = {
"ID" : lambda _val: isinstance(_val, int),
"username": lambda _val: isinstance(_val, basestring),
"password": lambda _val: isinstance(_val, basestring) and len(_val) == 96,
"username": lambda _val: isinstance(_val, str),
"password": lambda _val: isinstance(_val, str) and len(_val) == 96,
"admin" : lambda _val: isinstance(_val, bool)
}

View File

@@ -20,7 +20,7 @@
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from gui.builtinAdditionPanes.boosterView import BoosterView
from gui.builtinAdditionPanes.cargoView import CargoView
from gui.builtinAdditionPanes.commandView import CommandView
@@ -29,22 +29,22 @@ from gui.builtinAdditionPanes.fighterView import FighterView
from gui.builtinAdditionPanes.implantView import ImplantView
from gui.builtinAdditionPanes.notesView import NotesView
from gui.builtinAdditionPanes.projectedView import ProjectedView
from gui.chromeTabs import PFNotebook
from gui.pyfatogglepanel import TogglePanel
from gui.chrome_tabs import ChromeNotebook
from gui.toggle_panel import TogglePanel
class AdditionsPane(TogglePanel):
def __init__(self, parent):
TogglePanel.__init__(self, parent, forceLayout=1)
TogglePanel.__init__(self, parent, force_layout=1)
self.SetLabel("Additions")
pane = self.GetContentPane()
pane = self.GetContentPanel()
baseSizer = wx.BoxSizer(wx.HORIZONTAL)
pane.SetSizer(baseSizer)
self.notebook = PFNotebook(pane, False)
self.notebook = ChromeNotebook(pane, False)
self.notebook.SetMinSize((-1, 1000))
baseSizer.Add(self.notebook, 1, wx.EXPAND)
@@ -59,28 +59,28 @@ class AdditionsPane(TogglePanel):
notesImg = BitmapLoader.getImage("skill_small", "gui")
self.drone = DroneView(self.notebook)
self.notebook.AddPage(self.drone, "Drones", tabImage=droneImg, showClose=False)
self.notebook.AddPage(self.drone, "Drones", image=droneImg, closeable=False)
self.fighter = FighterView(self.notebook)
self.notebook.AddPage(self.fighter, "Fighters", tabImage=fighterImg, showClose=False)
self.notebook.AddPage(self.fighter, "Fighters", image=fighterImg, closeable=False)
self.cargo = CargoView(self.notebook)
self.notebook.AddPage(self.cargo, "Cargo", tabImage=cargoImg, showClose=False)
self.notebook.AddPage(self.cargo, "Cargo", image=cargoImg, closeable=False)
self.implant = ImplantView(self.notebook)
self.notebook.AddPage(self.implant, "Implants", tabImage=implantImg, showClose=False)
self.notebook.AddPage(self.implant, "Implants", image=implantImg, closeable=False)
self.booster = BoosterView(self.notebook)
self.notebook.AddPage(self.booster, "Boosters", tabImage=boosterImg, showClose=False)
self.notebook.AddPage(self.booster, "Boosters", image=boosterImg, closeable=False)
self.projectedPage = ProjectedView(self.notebook)
self.notebook.AddPage(self.projectedPage, "Projected", tabImage=projectedImg, showClose=False)
self.notebook.AddPage(self.projectedPage, "Projected", image=projectedImg, closeable=False)
self.gangPage = CommandView(self.notebook)
self.notebook.AddPage(self.gangPage, "Command", tabImage=gangImg, showClose=False)
self.notebook.AddPage(self.gangPage, "Command", image=gangImg, closeable=False)
self.notes = NotesView(self.notebook)
self.notebook.AddPage(self.notes, "Notes", tabImage=notesImg, showClose=False)
self.notebook.AddPage(self.notes, "Notes", image=notesImg, closeable=False)
self.notebook.SetSelection(0)
@@ -92,19 +92,16 @@ class AdditionsPane(TogglePanel):
def getName(self, idx):
return self.PANES[idx]
def toggleContent(self, event):
TogglePanel.toggleContent(self, event)
h = self.headerPanel.GetSize()[1] + 4
def ToggleContent(self, event):
TogglePanel.ToggleContent(self, event)
h = self.header_panel.GetSize()[1] + 4
if self.IsCollapsed():
self.old_pos = self.parent.GetSashPosition()
self.parent.SetMinimumPaneSize(h)
self.parent.SetSashPosition(h * -1, True)
# only available in >= wx2.9
if getattr(self.parent, "SetSashInvisible", None):
self.parent.SetSashInvisible(True)
self.parent.SetSashInvisible(True)
else:
if getattr(self.parent, "SetSashInvisible", None):
self.parent.SetSashInvisible(False)
self.parent.SetSashInvisible(False)
self.parent.SetMinimumPaneSize(200)
self.parent.SetSashPosition(self.old_pos, True)

View File

@@ -17,9 +17,10 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import cStringIO
import io
import os.path
import zipfile
from collections import OrderedDict
# noinspection PyPackageRequirements
import wx
@@ -29,23 +30,18 @@ import config
from logbook import Logger
logging = Logger(__name__)
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
class BitmapLoader(object):
try:
archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r')
logging.info("Using zipped image files.")
except IOError:
except (IOError, TypeError):
logging.info("Using local image files.")
archive = None
cachedBitmaps = OrderedDict()
dontUseCachedBitmaps = False
max_bmps = 500
cached_bitmaps = OrderedDict()
dont_use_cached_bitmaps = False
max_cached_bitmaps = 500
@classmethod
def getStaticBitmap(cls, name, parent, location):
@@ -55,25 +51,25 @@ class BitmapLoader(object):
@classmethod
def getBitmap(cls, name, location):
if cls.dontUseCachedBitmaps:
if cls.dont_use_cached_bitmaps:
img = cls.getImage(name, location)
if img is not None:
return img.ConvertToBitmap()
path = "%s%s" % (name, location)
if len(cls.cachedBitmaps) == cls.max_bmps:
cls.cachedBitmaps.popitem(False)
if len(cls.cached_bitmaps) == cls.max_cached_bitmaps:
cls.cached_bitmaps.popitem(False)
if path not in cls.cachedBitmaps:
if path not in cls.cached_bitmaps:
img = cls.getImage(name, location)
if img is not None:
bmp = img.ConvertToBitmap()
else:
bmp = None
cls.cachedBitmaps[path] = bmp
cls.cached_bitmaps[path] = bmp
else:
bmp = cls.cachedBitmaps[path]
bmp = cls.cached_bitmaps[path]
return bmp
@@ -88,14 +84,14 @@ class BitmapLoader(object):
try:
img_data = cls.archive.read(path)
sbuf = cStringIO.StringIO(img_data)
sbuf = io.StringIO(img_data)
return wx.ImageFromStream(sbuf)
except KeyError:
print("Missing icon file from zip: {0}".format(path))
print(("Missing icon file from zip: {0}".format(path)))
else:
path = os.path.join(config.pyfaPath, 'imgs' + os.sep + location + os.sep + filename)
if os.path.exists(path):
return wx.Image(path)
else:
print("Missing icon file: {0}".format(path))
print(("Missing icon file: {0}".format(path)))

View File

@@ -28,12 +28,12 @@ from gui.utils.staticHelpers import DragDropHelper
from service.fit import Fit
class BoosterViewDrop(wx.PyDropTarget):
class BoosterViewDrop(wx.DropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(BoosterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.dropData = wx.TextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
@@ -131,6 +131,7 @@ class BoosterView(d.Display):
fit = sFit.getFit(fitID)
if not fit or fit.isStructure:
event.Skip()
return
trigger = sFit.addBooster(fitID, event.itemID)

View File

@@ -28,12 +28,12 @@ from service.fit import Fit
from service.market import Market
class CargoViewDrop(wx.PyDropTarget):
class CargoViewDrop(wx.DropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(CargoViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.dropData = wx.TextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
@@ -88,7 +88,7 @@ class CargoView(d.Display):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
data = wx.TextDataObject()
dataStr = "cargo:" + str(row)
data.SetText(dataStr)
@@ -119,14 +119,14 @@ class CargoView(d.Display):
module = fit.modules[modIdx]
if dstRow != -1: # we're swapping with cargo
if mstate.CmdDown(): # if copying, append to cargo
if mstate.cmdDown: # if copying, append to cargo
sFit.addCargo(self.mainFrame.getActiveFit(), module.item.ID)
else: # else, move / swap
sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.position, dstRow)
else: # dragging to blank spot, append
sFit.addCargo(self.mainFrame.getActiveFit(), module.item.ID)
if not mstate.CmdDown(): # if not copying, remove module
if not mstate.cmdDown: # if not copying, remove module
sFit.removeModule(self.mainFrame.getActiveFit(), module.position)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit(), action="moddel", typeID=module.item.ID))

View File

@@ -43,12 +43,12 @@ class DummyEntry(object):
self.item = DummyItem(txt)
class CommandViewDrop(wx.PyDropTarget):
class CommandViewDrop(wx.DropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(CommandViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.dropData = wx.TextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
@@ -119,7 +119,7 @@ class CommandView(d.Display):
def startDrag(self, event):
row = event.GetIndex()
if row != -1 and isinstance(self.get(row), es_Drone):
data = wx.PyTextDataObject()
data = wx.TextDataObject()
dataStr = "command:" + str(self.GetItemData(row))
data.SetText(dataStr)
@@ -136,6 +136,8 @@ class CommandView(d.Display):
sFit = Fit.getInstance()
fit = sFit.getFit(event.fitID)
CommandFits.populateFits(event)
self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)
# Clear list and get out if current fitId is None
@@ -167,6 +169,8 @@ class CommandView(d.Display):
self.update(stuff)
event.Skip()
def get(self, row):
if row == -1:
return None

View File

@@ -21,6 +21,7 @@
import wx
import gui.globalEvents as GE
import gui.mainFrame
from gui.builtinMarketBrowser.events import ItemSelected, ITEM_SELECTED
from gui.display import Display
from gui.builtinViewColumns.state import State
@@ -30,12 +31,12 @@ from service.fit import Fit
from service.market import Market
class DroneViewDrop(wx.PyDropTarget):
class DroneViewDrop(wx.DropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(DroneViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.dropData = wx.TextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
@@ -66,6 +67,8 @@ class DroneView(Display):
self.hoveredRow = None
self.hoveredColumn = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
@@ -101,7 +104,7 @@ class DroneView(Display):
if self.DEFAULT_COLS[col] == "Miscellanea":
tooltip = self.activeColumns[col].getToolTip(mod)
if tooltip is not None:
self.SetToolTipString(tooltip)
self.SetToolTip(tooltip)
else:
self.SetToolTip(None)
else:
@@ -123,7 +126,7 @@ class DroneView(Display):
def startDrag(self, event):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
data = wx.TextDataObject()
dataStr = "drone:" + str(row)
data.SetText(dataStr)
@@ -207,6 +210,7 @@ class DroneView(Display):
fit = sFit.getFit(fitID)
if not fit or fit.isStructure:
event.Skip()
return
trigger = sFit.addDrone(fitID, event.itemID)

View File

@@ -32,12 +32,12 @@ from service.fit import Fit
from service.market import Market
class FighterViewDrop(wx.PyDropTarget):
class FighterViewDrop(wx.DropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(FighterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.dropData = wx.TextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
@@ -60,7 +60,7 @@ class FighterView(wx.Panel):
mainSizer.Add(self.fighterDisplay, 1, wx.EXPAND, 0)
textSizer = wx.BoxSizer(wx.HORIZONTAL)
textSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
textSizer.AddStretchSpacer()
for x in self.labels:
lbl = wx.StaticText(self, wx.ID_ANY, x.capitalize())
@@ -75,7 +75,7 @@ class FighterView(wx.Panel):
lbl = wx.StaticText(self, wx.ID_ANY, "0")
setattr(self, "label%sTotal" % (x.capitalize()), lbl)
textSizer.Add(lbl, 0, wx.ALIGN_CENTER)
textSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
textSizer.AddStretchSpacer()
mainSizer.Add(textSizer, 0, wx.EXPAND, 5)
@@ -97,7 +97,7 @@ class FighterView(wx.Panel):
slot = getattr(Slot, "F_{}".format(x.upper()))
used = fit.getSlotsUsed(slot)
total = fit.getNumSlots(slot)
color = wx.Colour(204, 51, 51) if used > total else wx.SystemSettings_GetColour(
color = wx.Colour(204, 51, 51) if used > total else wx.SystemSettings.GetColour(
wx.SYS_COLOUR_WINDOWTEXT)
lbl = getattr(self, "label%sUsed" % x.capitalize())
@@ -110,6 +110,8 @@ class FighterView(wx.Panel):
self.Refresh()
event.Skip()
class FighterDisplay(d.Display):
DEFAULT_COLS = ["State",
@@ -166,7 +168,7 @@ class FighterDisplay(d.Display):
if self.DEFAULT_COLS[col] == "Miscellanea":
tooltip = self.activeColumns[col].getToolTip(mod)
if tooltip is not None:
self.SetToolTipString(tooltip)
self.SetToolTip(tooltip)
else:
self.SetToolTip(None)
else:
@@ -188,7 +190,7 @@ class FighterDisplay(d.Display):
def startDrag(self, event):
row = event.GetIndex()
if row != -1:
data = wx.PyTextDataObject()
data = wx.TextDataObject()
dataStr = "fighter:" + str(row)
data.SetText(dataStr)

View File

@@ -41,12 +41,12 @@ class ImplantView(wx.Panel):
mainSizer.Add(self.implantDisplay, 1, wx.EXPAND, 0)
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
radioSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
radioSizer.AddStretchSpacer()
self.rbFit = wx.RadioButton(self, id=wx.ID_ANY, label="Use Fit-specific Implants", style=wx.RB_GROUP)
self.rbChar = wx.RadioButton(self, id=wx.ID_ANY, label="Use Character Implants")
radioSizer.Add(self.rbFit, 0, wx.ALL, 5)
radioSizer.Add(self.rbChar, 0, wx.ALL, 5)
radioSizer.AddSpacer((0, 0), 1, wx.EXPAND, 5)
radioSizer.AddStretchSpacer()
mainSizer.Add(radioSizer, 0, wx.EXPAND, 5)
@@ -71,6 +71,8 @@ class ImplantView(wx.Panel):
self.rbFit.Enable(fit is not None)
self.rbChar.Enable(fit is not None)
event.Skip()
def OnRadioSelect(self, event):
fitID = self.mainFrame.getActiveFit()
sFit = Fit.getInstance()
@@ -150,6 +152,7 @@ class ImplantDisplay(d.Display):
fit = sFit.getFit(fitID)
if not fit or fit.isStructure:
event.Skip()
return
trigger = sFit.addImplant(fitID, event.itemID)

View File

@@ -40,6 +40,8 @@ class NotesView(wx.Panel):
self.lastFitId = event.fitID
self.editNotes.SetValue(fit.notes or "")
event.Skip()
def onText(self, event):
# delay the save so we're not writing to sqlite on every keystroke
self.saveTimer.Stop() # cancel the existing timer

View File

@@ -47,12 +47,12 @@ class DummyEntry(object):
self.item = DummyItem(txt)
class ProjectedViewDrop(wx.PyDropTarget):
class ProjectedViewDrop(wx.DropTarget):
def __init__(self, dropFn, *args, **kwargs):
super(ProjectedViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
self.dropData = wx.TextDataObject()
self.SetDataObject(self.dropData)
def OnData(self, x, y, t):
@@ -139,7 +139,7 @@ class ProjectedView(d.Display):
def startDrag(self, event):
row = event.GetIndex()
if row != -1 and isinstance(self.get(row), es_Drone):
data = wx.PyTextDataObject()
data = wx.TextDataObject()
dataStr = "projected:" + str(self.GetItemData(row))
data.SetText(dataStr)
@@ -229,6 +229,8 @@ class ProjectedView(d.Display):
self.update(stuff)
event.Skip()
def get(self, row):
if row == -1:
return None

View File

@@ -3,7 +3,7 @@ from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from eos.saveddata.character import Skill
import gui.globalEvents as GE
from service.fit import Fit
@@ -49,7 +49,7 @@ class ChangeAffectingSkills(ContextMenu):
if cont[attrName] == 0:
continue
for fit, afflictors in cont.getAfflictions(attrName).iteritems():
for fit, afflictors in cont.getAfflictions(attrName).items():
for afflictor, modifier, amount, used in afflictors:
# only add Skills
if not isinstance(afflictor, Skill):
@@ -89,12 +89,12 @@ class ChangeAffectingSkills(ContextMenu):
if bitmap is not None:
skillItem.SetBitmap(bitmap)
for i in xrange(-1, 6):
for i in range(-1, 6):
levelItem = self.addSkill(rootMenu if msw else grandSub, skill, i)
grandSub.AppendItem(levelItem)
grandSub.Append(levelItem)
if (not skill.learned and i == -1) or (skill.learned and skill.level == i):
levelItem.Check(True)
sub.AppendItem(skillItem)
sub.Append(skillItem)
return sub

View File

@@ -30,6 +30,7 @@ class CommandFits(ContextMenu):
if evt is None or not ids.isdisjoint(cls.commandTypeIDs):
# we are adding or removing an item that defines a command fit. Need to refresh fit list
cls.populateFits(evt)
evt.Skip()
@classmethod
def populateFits(cls, evt):
@@ -50,7 +51,7 @@ class CommandFits(ContextMenu):
return "Command Fits"
def addFit(self, menu, fit, includeShip=False):
label = fit.name if not includeShip else u"({}) {}".format(fit.ship.item.name, fit.name)
label = fit.name if not includeShip else "({}) {}".format(fit.ship.item.name, fit.name)
id = ContextMenu.nextID()
self.fitMenuItemIds[id] = fit
menuItem = wx.MenuItem(menu, id, label)
@@ -67,7 +68,7 @@ class CommandFits(ContextMenu):
if len(self.__class__.commandFits) < 15:
for fit in sorted(self.__class__.commandFits, key=lambda x: x.name):
menuItem = self.addFit(rootMenu if msw else sub, fit, True)
sub.AppendItem(menuItem)
sub.Append(menuItem)
else:
typeDict = {}
@@ -84,9 +85,9 @@ class CommandFits(ContextMenu):
for fit in sorted(typeDict[ship], key=lambda x: x.name):
fitItem = self.addFit(rootMenu if msw else grandSub, fit, False)
grandSub.AppendItem(fitItem)
grandSub.Append(fitItem)
sub.AppendItem(shipItem)
sub.Append(shipItem)
return sub

View File

@@ -3,15 +3,12 @@ import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from service.fit import Fit
from service.damagePattern import DamagePattern as import_DamagePattern
from service.settings import ContextMenuSettings
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
from collections import OrderedDict
class DamagePattern(ContextMenu):
@@ -52,7 +49,7 @@ class DamagePattern(ContextMenu):
self.singles.append(pattern)
# return list of names, with singles first followed by submenu names
self.m = map(lambda p: p.name, self.singles) + self.subMenus.keys()
self.m = [p.name for p in self.singles] + list(self.subMenus.keys())
return self.m
def addPattern(self, rootMenu, pattern):
@@ -96,7 +93,7 @@ class DamagePattern(ContextMenu):
# Items that have a parent
for pattern in self.subMenus[self.m[i]]:
sub.AppendItem(self.addPattern(rootMenu if msw else sub, pattern))
sub.Append(self.addPattern(rootMenu if msw else sub, pattern))
return sub

View File

@@ -45,7 +45,7 @@ class DroneSpinner(wx.Dialog):
bSizer1.Add(self.spinner, 1, wx.ALL, 5)
self.button = wx.Button(self, wx.ID_OK, u"Split")
self.button = wx.Button(self, wx.ID_OK, "Split")
bSizer1.Add(self.button, 0, wx.ALL, 5)
self.SetSizer(bSizer1)

View File

@@ -3,7 +3,7 @@ import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from service.fit import Fit
from service.settings import ContextMenuSettings
@@ -31,9 +31,7 @@ class FactorReload(ContextMenu):
def getBitmap(self, context, selection):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = sFit.getFit(fitID)
if fit.factorReload:
if sFit.serviceFittingOptions["useGlobalForceReload"]:
return BitmapLoader.getBitmap("state_active_small", "gui")
else:
return None

View File

@@ -44,7 +44,7 @@ class FighterAbility(ContextMenu):
if not ability.effect.isImplemented:
continue
menuItem = self.addAbility(rootMenu if msw else sub, ability)
sub.AppendItem(menuItem)
sub.Append(menuItem)
menuItem.Check(ability.active)
return sub

View File

@@ -61,7 +61,7 @@ class ImplantSets(ContextMenu):
mitem = wx.MenuItem(rootMenu, id, set.name)
bindmenu.Bind(wx.EVT_MENU, self.handleSelection, mitem)
self.idmap[id] = set
m.AppendItem(mitem)
m.Append(mitem)
return m

View File

@@ -47,7 +47,7 @@ class ItemStats(ContextMenu):
mstate = wx.GetMouseState()
reuse = False
if mstate.CmdDown():
if mstate.cmdDown:
reuse = True
if self.mainFrame.GetActiveStatsWindow() is None and reuse:

View File

@@ -91,7 +91,7 @@ class MetaSwap(ContextMenu):
# Sort items by metalevel, and group within that metalevel
items = list(self.variations)
print context
print(context)
if "implantItem" in context:
# sort implants based on name
items.sort(key=lambda x: x.name)
@@ -116,14 +116,14 @@ class MetaSwap(ContextMenu):
if thisgroup != group and context not in ("implantItem", "boosterItem"):
group = thisgroup
id = ContextMenu.nextID()
m.Append(id, u'%s' % group)
m.Append(id, '%s' % group)
m.Enable(id, False)
id = ContextMenu.nextID()
mitem = wx.MenuItem(rootMenu, id, item.name)
bindmenu.Bind(wx.EVT_MENU, self.handleModule, mitem)
self.moduleLookup[id] = item
m.AppendItem(mitem)
m.Append(mitem)
return m
def handleModule(self, event):

View File

@@ -9,7 +9,7 @@ from eos.saveddata.module import Hardpoint
import gui.mainFrame
import gui.globalEvents as GE
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from service.settings import ContextMenuSettings
@@ -50,7 +50,7 @@ class ModuleAmmoPicker(ContextMenu):
return False
self.modules = modules
self.charges = list(filter(lambda charge: Market.getInstance().getPublicityByItem(charge), validCharges))
self.charges = list([charge for charge in validCharges if Market.getInstance().getPublicityByItem(charge)])
return len(self.charges) > 0
def getText(self, itmContext, selection):
@@ -58,9 +58,9 @@ class ModuleAmmoPicker(ContextMenu):
def turretSorter(self, charge):
damage = 0
range_ = (self.module.getModifiedItemAttr("maxRange") or 0) * \
range_ = (self.module.getModifiedItemAttr("maxRange")) * \
(charge.getAttribute("weaponRangeMultiplier") or 1)
falloff = (self.module.getModifiedItemAttr("falloff") or 0) * \
falloff = (self.module.getModifiedItemAttr("falloff")) * \
(charge.getAttribute("fallofMultiplier") or 1)
for type_ in self.DAMAGE_TYPES:
d = charge.getAttribute("%sDamage" % type_)
@@ -108,7 +108,7 @@ class ModuleAmmoPicker(ContextMenu):
def nameSorter(self, charge):
parts = charge.name.split(" ")
return map(self.numericConverter, parts)
return list(map(self.numericConverter, parts))
def addCharge(self, menu, charge):
id_ = ContextMenu.nextID()
@@ -127,7 +127,7 @@ class ModuleAmmoPicker(ContextMenu):
@staticmethod
def addSeperator(m, text):
id_ = ContextMenu.nextID()
m.Append(id_, u'%s' % text)
m.Append(id_, '%s' % text)
m.Enable(id_, False)
def getSubMenu(self, context, selection, rootMenu, i, pitem):
@@ -137,7 +137,7 @@ class ModuleAmmoPicker(ContextMenu):
hardpoint = self.module.hardpoint
moduleName = self.module.item.name
# Make sure we do not consider mining turrets as combat turrets
if hardpoint == Hardpoint.TURRET and self.module.getModifiedItemAttr("miningAmount") is None:
if hardpoint == Hardpoint.TURRET and self.module.getModifiedItemAttr("miningAmount", None) is None:
self.addSeperator(m, "Long Range")
items = []
range_ = None
@@ -170,15 +170,15 @@ class ModuleAmmoPicker(ContextMenu):
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")
item.SetSubMenu(sub)
sub.AppendItem(self.addCharge(rootMenu if msw else sub, base))
sub.Append(self.addCharge(rootMenu if msw else sub, base))
sub.AppendItem(self.addCharge(rootMenu if msw else sub, charge))
sub.Append(self.addCharge(rootMenu if msw else sub, charge))
if sub is not None:
self.addSeperator(sub, "More Damage")
for item in items:
m.AppendItem(item)
m.Append(item)
self.addSeperator(m, "Short Range")
elif hardpoint == Hardpoint.MISSILE and moduleName != 'Festival Launcher':
@@ -203,23 +203,23 @@ class ModuleAmmoPicker(ContextMenu):
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")
item.SetSubMenu(sub)
m.AppendItem(item)
m.Append(item)
if charge.name not in ("Light Defender Missile I", "Heavy Defender Missile I"):
sub.AppendItem(self.addCharge(rootMenu if msw else sub, charge))
sub.Append(self.addCharge(rootMenu if msw else sub, charge))
else:
defender = charge
if defender is not None:
m.AppendItem(self.addCharge(rootMenu if msw else m, defender))
m.Append(self.addCharge(rootMenu if msw else m, defender))
if sub is not None:
self.addSeperator(sub, "More Damage")
else:
self.charges.sort(key=self.nameSorter)
for charge in self.charges:
m.AppendItem(self.addCharge(rootMenu if msw else m, charge))
m.Append(self.addCharge(rootMenu if msw else m, charge))
m.AppendItem(self.addCharge(rootMenu if msw else m, None))
m.Append(self.addCharge(rootMenu if msw else m, None))
return m
def handleAmmoSwitch(self, event):

View File

@@ -35,7 +35,7 @@ class PriceOptions(ContextMenu):
for option in self.optionList:
menuItem = self.addOption(rootMenu if msw else sub, option)
sub.AppendItem(menuItem)
sub.Append(menuItem)
menuItem.Check(self.settings.get(option.lower()))
return sub

View File

@@ -38,15 +38,15 @@ class TabbedFits(ContextMenu):
else:
bindmenu = m
for page in self.mainFrame.fitMultiSwitch.pages:
for page in self.mainFrame.fitMultiSwitch._pages:
if isinstance(page, BlankPage):
continue
fit = sFit.getFit(page.activeFitID, basic=True)
id = ContextMenu.nextID()
mitem = wx.MenuItem(rootMenu, id, u"{}: {}".format(fit.ship.item.name, fit.name))
mitem = wx.MenuItem(rootMenu, id, "{}: {}".format(fit.ship.item.name, fit.name))
bindmenu.Bind(wx.EVT_MENU, self.handleSelection, mitem)
self.fitLookup[id] = fit
m.AppendItem(mitem)
m.Append(mitem)
return m

View File

@@ -49,7 +49,7 @@ class TacticalMode(ContextMenu):
for mode in self.modes:
menuItem = self.addMode(rootMenu if msw else sub, mode)
sub.AppendItem(menuItem)
sub.Append(menuItem)
menuItem.Check(self.currMode.item == mode.item)
return sub

View File

@@ -3,15 +3,11 @@ import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from service.targetResists import TargetResists as svc_TargetResists
from service.fit import Fit
from service.settings import ContextMenuSettings
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
from collections import OrderedDict
class TargetResists(ContextMenu):
@@ -87,15 +83,15 @@ class TargetResists(ContextMenu):
else:
self.singles.append(pattern)
sub.AppendItem(self.addPattern(rootMenu if msw else sub, None)) # Add reset
sub.Append(self.addPattern(rootMenu if msw else sub, None)) # Add reset
sub.AppendSeparator()
# Single items, no parent
for pattern in self.singles:
sub.AppendItem(self.addPattern(rootMenu if msw else sub, pattern))
sub.Append(self.addPattern(rootMenu if msw else sub, pattern))
# Items that have a parent
for menuName, patterns in self.subMenus.items():
for menuName, patterns in list(self.subMenus.items()):
# Create parent item for root menu that is simply name of parent
item = wx.MenuItem(rootMenu, ContextMenu.nextID(), menuName)
@@ -108,8 +104,8 @@ class TargetResists(ContextMenu):
# Append child items to child menu
for pattern in patterns:
grandSub.AppendItem(self.addPattern(rootMenu if msw else grandSub, pattern))
sub.AppendItem(item) # finally, append parent item to root menu
grandSub.Append(self.addPattern(rootMenu if msw else grandSub, pattern))
sub.Append(item) # finally, append parent item to root menu
return sub

View File

@@ -34,7 +34,7 @@ class WhProjector(ContextMenu):
subItem = wx.MenuItem(sub, wx.ID_ANY, swType)
grandSub = wx.Menu()
subItem.SetSubMenu(grandSub)
sub.AppendItem(subItem)
sub.Append(subItem)
for swData in sorted(effdata[swType], key=lambda tpl: tpl[2]):
wxid = ContextMenu.nextID()
@@ -45,7 +45,7 @@ class WhProjector(ContextMenu):
rootMenu.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem)
else:
grandSub.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem)
grandSub.AppendItem(grandSubItem)
grandSub.Append(grandSubItem)
return sub
def handleSelection(self, event):

View File

@@ -18,7 +18,7 @@
# =============================================================================
from gui.graph import Graph
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from eos.graph.fitDps import FitDpsGraph as FitDps
from eos.graph import Data
import gui.mainFrame
@@ -54,7 +54,7 @@ class FitDpsGraph(Graph):
def getIcons(self):
icons = {}
sAttr = Attribute.getInstance()
for key, attrName in self.propertyAttributeMap.iteritems():
for key, attrName in self.propertyAttributeMap.items():
iconFile = sAttr.getAttributeInfo(attrName).icon.iconFile
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
if bitmap:
@@ -69,7 +69,7 @@ class FitDpsGraph(Graph):
fitDps.clearData()
variable = None
for fieldName, value in fields.iteritems():
for fieldName, value in fields.items():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:

View File

@@ -14,7 +14,7 @@ from eos.saveddata.fit import Fit
import gui.mainFrame
from gui.contextMenu import ContextMenu
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
class ItemAffectedBy(wx.Panel):
@@ -43,17 +43,17 @@ class ItemAffectedBy(wx.Panel):
mainSizer.Add(self.m_staticline, 0, wx.EXPAND)
bSizer = wx.BoxSizer(wx.HORIZONTAL)
self.toggleExpandBtn = wx.ToggleButton(self, wx.ID_ANY, u"Expand All", wx.DefaultPosition, wx.DefaultSize, 0)
self.toggleExpandBtn = wx.ToggleButton(self, wx.ID_ANY, "Expand All", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.toggleExpandBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.toggleNameBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle Names", wx.DefaultPosition, wx.DefaultSize, 0)
self.toggleNameBtn = wx.ToggleButton(self, wx.ID_ANY, "Toggle Names", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.toggleNameBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle View", wx.DefaultPosition, wx.DefaultSize, 0)
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, "Toggle View", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL)
if stuff is not None:
self.refreshBtn = wx.Button(self, wx.ID_ANY, u"Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT)
self.refreshBtn = wx.Button(self, wx.ID_ANY, "Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT)
bSizer.Add(self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.refreshBtn.Bind(wx.EVT_BUTTON, self.RefreshTree)
@@ -74,9 +74,9 @@ class ItemAffectedBy(wx.Panel):
def spawnMenu(self, item):
self.affectedBy.SelectItem(item)
stuff = self.affectedBy.GetPyData(item)
stuff = self.affectedBy.GetItemData(item)
# String is set as data when we are dealing with attributes, not stuff containers
if stuff is None or isinstance(stuff, basestring):
if stuff is None or isinstance(stuff, str):
return
contexts = []
@@ -109,10 +109,10 @@ class ItemAffectedBy(wx.Panel):
self.Freeze()
for item in self.treeItems:
change = self.affectedBy.GetPyData(item)
change = self.affectedBy.GetItemData(item)
display = self.affectedBy.GetItemText(item)
self.affectedBy.SetItemText(item, change)
self.affectedBy.SetPyData(item, display)
self.affectedBy.SetItemData(item, display)
self.Thaw()
@@ -141,7 +141,7 @@ class ItemAffectedBy(wx.Panel):
# sheri was here
del self.treeItems[:]
root = self.affectedBy.AddRoot("WINPWNZ0R")
self.affectedBy.SetPyData(root, None)
self.affectedBy.SetItemData(root, None)
self.imageList = wx.ImageList(16, 16)
self.affectedBy.SetImageList(self.imageList)
@@ -185,7 +185,7 @@ class ItemAffectedBy(wx.Panel):
if attributes[attrName] == (attributes.getOriginal(attrName, 0)):
continue
for fit, afflictors in attributes.getAfflictions(attrName).iteritems():
for fit, afflictors in attributes.getAfflictions(attrName).items():
for afflictor, modifier, amount, used in afflictors:
if not used or afflictor.item is None:
@@ -216,7 +216,7 @@ class ItemAffectedBy(wx.Panel):
(type(afflictor), afflictor, item, modifier, amount, getattr(afflictor, "projected", False)))
# Make sure projected fits are on top
rootOrder = container.keys()
rootOrder = list(container.keys())
rootOrder.sort(key=lambda x: self.ORDER.index(type(x)))
# Now, we take our created dictionary and start adding stuff to our tree
@@ -230,7 +230,7 @@ class ItemAffectedBy(wx.Panel):
parent = child
attributes = container[thing]
attrOrder = sorted(attributes.keys(), key=self.sortAttrDisplayName)
attrOrder = sorted(list(attributes.keys()), key=self.sortAttrDisplayName)
for attrName in attrOrder:
attrInfo = self.stuff.item.attributes.get(attrName)
@@ -257,7 +257,7 @@ class ItemAffectedBy(wx.Panel):
# this is the attribute node
child = self.affectedBy.AppendItem(parent, display, attrIcon)
self.affectedBy.SetPyData(child, saved)
self.affectedBy.SetItemData(child, saved)
self.treeItems.append(child)
items = attributes[attrName]
@@ -284,12 +284,12 @@ class ItemAffectedBy(wx.Panel):
penalized += "(penalized)"
if 'r' in attrModifier:
penalized += "(resisted)"
attrModifier = "*"
attrModifier = "*"
# this is the Module node, the attribute will be attached to this
display = "%s %s %.2f %s" % (displayStr, attrModifier, attrAmount, penalized)
treeItem = self.affectedBy.AppendItem(child, display, itemIcon)
self.affectedBy.SetPyData(treeItem, afflictor)
self.affectedBy.SetItemData(treeItem, afflictor)
def buildModuleView(self, root):
"""
@@ -314,7 +314,7 @@ class ItemAffectedBy(wx.Panel):
if attributes[attrName] == (attributes.getOriginal(attrName, 0)):
continue
for fit, afflictors in attributes.getAfflictions(attrName).iteritems():
for fit, afflictors in attributes.getAfflictions(attrName).items():
for afflictor, modifier, amount, used in afflictors:
if not used or getattr(afflictor, 'item', None) is None:
continue
@@ -350,7 +350,7 @@ class ItemAffectedBy(wx.Panel):
info[2].append((attrName, modifier, amount))
# Make sure projected fits are on top
rootOrder = container.keys()
rootOrder = list(container.keys())
rootOrder.sort(key=lambda x: self.ORDER.index(type(x)))
# Now, we take our created dictionary and start adding stuff to our tree
@@ -364,7 +364,7 @@ class ItemAffectedBy(wx.Panel):
parent = child
items = container[thing]
order = items.keys()
order = list(items.keys())
order.sort(key=lambda x: (self.ORDER.index(items[x][0]), x))
for itemName in order:
@@ -389,7 +389,7 @@ class ItemAffectedBy(wx.Panel):
# this is the Module node, the attribute will be attached to this
child = self.affectedBy.AppendItem(parent, displayStr, itemIcon)
self.affectedBy.SetPyData(child, afflictors.pop())
self.affectedBy.SetItemData(child, afflictors.pop())
if counter > 0:
attributes = []
@@ -416,7 +416,7 @@ class ItemAffectedBy(wx.Panel):
penalized += "(penalized)"
if 'r' in attrModifier:
penalized += "(resisted)"
attrModifier = "*"
attrModifier = "*"
attributes.append((attrName, (displayName if displayName != "" else attrName), attrModifier,
attrAmount, penalized, attrIcon))
@@ -443,5 +443,5 @@ class ItemAffectedBy(wx.Panel):
saved = "%s %s %.2f %s" % (attrName, attrModifier, attrAmount, penalized)
treeitem = self.affectedBy.AppendItem(child, display, attrIcon)
self.affectedBy.SetPyData(treeitem, saved)
self.affectedBy.SetItemData(treeitem, saved)
self.treeItems.append(treeitem)

View File

@@ -1,13 +1,12 @@
import sys
import csv
import config
# noinspection PyPackageRequirements
import wx
from helpers import AutoListCtrl
from .helpers import AutoListCtrl
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
from service.market import Market
from service.attribute import Attribute
from gui.utils.numberFormatter import formatAmount
@@ -34,19 +33,19 @@ class ItemParams(wx.Panel):
mainSizer.Add(self.m_staticline, 0, wx.EXPAND)
bSizer = wx.BoxSizer(wx.HORIZONTAL)
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, u" ", wx.DefaultPosition, wx.DefaultSize, 0)
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, " ", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.totalAttrsLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT)
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle view mode", wx.DefaultPosition, wx.DefaultSize,
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, "Toggle view mode", wx.DefaultPosition, wx.DefaultSize,
0)
bSizer.Add(self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.exportStatsBtn = wx.ToggleButton(self, wx.ID_ANY, u"Export Item Stats", wx.DefaultPosition, wx.DefaultSize,
self.exportStatsBtn = wx.ToggleButton(self, wx.ID_ANY, "Export Item Stats", wx.DefaultPosition, wx.DefaultSize,
0)
bSizer.Add(self.exportStatsBtn, 0, wx.ALIGN_CENTER_VERTICAL)
if stuff is not None:
self.refreshBtn = wx.Button(self, wx.ID_ANY, u"Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT)
self.refreshBtn = wx.Button(self, wx.ID_ANY, "Refresh", wx.DefaultPosition, wx.DefaultSize, wx.BU_EXACTFIT)
bSizer.Add(self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.refreshBtn.Bind(wx.EVT_BUTTON, self.RefreshValues)
@@ -166,7 +165,7 @@ class ItemParams(wx.Panel):
self.imageList = wx.ImageList(16, 16)
self.paramList.SetImageList(self.imageList, wx.IMAGE_LIST_SMALL)
names = list(self.attrValues.iterkeys())
names = list(self.attrValues.keys())
names.sort()
idNameMap = {}
@@ -203,7 +202,7 @@ class ItemParams(wx.Panel):
else:
attrIcon = self.imageList.Add(BitmapLoader.getBitmap("7_15", "icons"))
index = self.paramList.InsertImageStringItem(sys.maxint, attrName, attrIcon)
index = self.paramList.InsertItem(self.paramList.GetItemCount(), attrName, attrIcon)
idNameMap[idCount] = attrName
self.paramList.SetItemData(index, idCount)
idCount += 1
@@ -222,11 +221,12 @@ class ItemParams(wx.Panel):
else:
valueUnitDefault = formatAmount(valueDefault, 3, 0, 0)
self.paramList.SetStringItem(index, 1, valueUnit)
self.paramList.SetItem(index, 1, valueUnit)
if self.stuff is not None:
self.paramList.SetStringItem(index, 2, valueUnitDefault)
self.paramList.SortItems(lambda id1, id2: cmp(idNameMap[id1], idNameMap[id2]))
self.paramList.SetItem(index, 2, valueUnitDefault)
# @todo: pheonix, this lamda used cmp() which no longer exists in py3. Probably a better way to do this in the
# long run, take a look
self.paramList.SortItems(lambda id1, id2: (idNameMap[id1] > idNameMap[id2]) - (idNameMap[id1] < idNameMap[id2]))
self.paramList.RefreshRows()
self.totalAttrsLabel.SetLabel("%d attributes. " % idCount)
self.Layout()
@@ -252,7 +252,7 @@ class ItemParams(wx.Panel):
"Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName),
"Modifier Percent" : (
lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
"Volume" : (lambda: value, u"m\u00B3"),
"Volume" : (lambda: value, "m\u00B3"),
"Sizeclass" : (lambda: value, ""),
"Absolute Percent" : (lambda: (value * 100), unitName),
"Milliseconds" : (lambda: value / 1000.0, unitName),
@@ -266,7 +266,7 @@ class ItemParams(wx.Panel):
v = override[0]()
if isinstance(v, str):
fvalue = v
elif isinstance(v, (int, float, long)):
elif isinstance(v, (int, float)):
fvalue = formatAmount(v, 3, 0, 0)
else:
fvalue = v

View File

@@ -1,9 +1,7 @@
import sys
# noinspection PyPackageRequirements
import wx
from helpers import AutoListCtrl
from .helpers import AutoListCtrl
from service.price import Price as ServicePrice
from service.market import Market
from service.attribute import Attribute
@@ -30,17 +28,17 @@ class ItemCompare(wx.Panel):
self.sortReverse = False
self.item = item
self.items = sorted(items,
key=lambda x: x.attributes['metaLevel'].value if 'metaLevel' in x.attributes else None)
key=lambda x: x.attributes['metaLevel'].value if 'metaLevel' in x.attributes else 0)
self.attrs = {}
# get a dict of attrName: attrInfo of all unique attributes across all items
for item in self.items:
for attr in item.attributes.keys():
for attr in list(item.attributes.keys()):
if item.attributes[attr].info.displayName:
self.attrs[attr] = item.attributes[attr].info
# Process attributes for items and find ones that differ
for attr in self.attrs.keys():
for attr in list(self.attrs.keys()):
value = None
for item in self.items:
@@ -65,14 +63,14 @@ class ItemCompare(wx.Panel):
mainSizer.Add(self.m_staticline, 0, wx.EXPAND)
bSizer = wx.BoxSizer(wx.HORIZONTAL)
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, u" ", wx.DefaultPosition, wx.DefaultSize, 0)
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, " ", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.totalAttrsLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT)
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, u"Toggle view mode", wx.DefaultPosition,
self.toggleViewBtn = wx.ToggleButton(self, wx.ID_ANY, "Toggle view mode", wx.DefaultPosition,
wx.DefaultSize, 0)
bSizer.Add(self.toggleViewBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.refreshBtn = wx.Button(self, wx.ID_ANY, u"Refresh", wx.DefaultPosition, wx.DefaultSize,
self.refreshBtn = wx.Button(self, wx.ID_ANY, "Refresh", wx.DefaultPosition, wx.DefaultSize,
wx.BU_EXACTFIT)
bSizer.Add(self.refreshBtn, 0, wx.ALIGN_CENTER_VERTICAL)
self.refreshBtn.Bind(wx.EVT_BUTTON, self.RefreshValues)
@@ -109,7 +107,7 @@ class ItemCompare(wx.Panel):
def processPrices(self, prices):
for i, price in enumerate(prices):
self.paramList.SetStringItem(i, len(self.attrs) + 1, formatAmount(price.value, 3, 3, 9, currency=True))
self.paramList.SetItem(i, len(self.attrs) + 1, formatAmount(price.value, 3, 3, 9, currency=True))
def PopulateList(self, sort=None):
@@ -126,7 +124,7 @@ class ItemCompare(wx.Panel):
try:
# Remember to reduce by 1, because the attrs array
# starts at 0 while the list has the item name as column 0.
attr = str(self.attrs.keys()[sort - 1])
attr = str(list(self.attrs.keys())[sort - 1])
func = lambda _val: _val.attributes[attr].value if attr in _val.attributes else None
except IndexError:
# Clicked on a column that's not part of our array (price most likely)
@@ -147,7 +145,7 @@ class ItemCompare(wx.Panel):
self.paramList.SetColumnWidth(len(self.attrs) + 1, 60)
for item in self.items:
i = self.paramList.InsertStringItem(sys.maxint, 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]
@@ -159,10 +157,10 @@ class ItemCompare(wx.Panel):
else:
valueUnit = formatAmount(value, 3, 0, 0)
self.paramList.SetStringItem(i, x + 1, valueUnit)
self.paramList.SetItem(i, x + 1, valueUnit)
# Add prices
self.paramList.SetStringItem(i, len(self.attrs) + 1, formatAmount(item.price.price, 3, 3, 9, currency=True))
self.paramList.SetItem(i, len(self.attrs) + 1, formatAmount(item.price.price, 3, 3, 9, currency=True))
self.paramList.RefreshRows()
self.Layout()
@@ -185,7 +183,7 @@ class ItemCompare(wx.Panel):
"Inverse Absolute Percent" : (lambda: (1 - value) * 100, unitName),
"Inversed Modifier Percent": (lambda: (1 - value) * 100, unitName),
"Modifier Percent" : (lambda: ("%+.2f" if ((value - 1) * 100) % 1 else "%+d") % ((value - 1) * 100), unitName),
"Volume" : (lambda: value, u"m\u00B3"),
"Volume" : (lambda: value, "m\u00B3"),
"Sizeclass" : (lambda: value, ""),
"Absolute Percent" : (lambda: (value * 100), unitName),
"Milliseconds" : (lambda: value / 1000.0, unitName),
@@ -199,7 +197,7 @@ class ItemCompare(wx.Panel):
v = override[0]()
if isinstance(v, str):
fvalue = v
elif isinstance(v, (int, float, long)):
elif isinstance(v, (int, float)):
fvalue = formatAmount(v, 3, 0, 0)
else:
fvalue = v

View File

@@ -1,7 +1,7 @@
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
class ItemDependents(wx.Panel):
@@ -19,7 +19,7 @@ class ItemDependents(wx.Panel):
self.SetSizer(mainSizer)
self.root = self.reqTree.AddRoot("WINRARZOR")
self.reqTree.SetPyData(self.root, None)
self.reqTree.SetItemData(self.root, None)
self.imageList = wx.ImageList(16, 16)
self.reqTree.SetImageList(self.imageList)
@@ -32,7 +32,7 @@ class ItemDependents(wx.Panel):
def getFullSkillTree(self, parentSkill, parent, sbIconId):
levelToItems = {}
for item, level in parentSkill.requiredFor.iteritems():
for item, level in parentSkill.requiredFor.items():
if level not in levelToItems:
levelToItems[level] = []
levelToItems[level].append(item)

View File

@@ -11,8 +11,8 @@ class ItemDescription(wx.Panel):
mainSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(mainSizer)
bgcolor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
fgcolor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
bgcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
fgcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
self.description = wx.html.HtmlWindow(self)

View File

@@ -1,4 +1,3 @@
import sys
import os
import subprocess
import config
@@ -6,7 +5,7 @@ import config
# noinspection PyPackageRequirements
import wx
from helpers import AutoListCtrl
from .helpers import AutoListCtrl
class ItemEffects(wx.Panel):
@@ -47,11 +46,11 @@ class ItemEffects(wx.Panel):
item = self.item
effects = item.effects
names = list(effects.iterkeys())
names = list(effects.keys())
names.sort()
for name in names:
index = self.effectList.InsertStringItem(sys.maxint, name)
index = self.effectList.InsertItem(self.effectList.GetItemCount(), name)
if effects[name].isImplemented:
if effects[name].activeByDefault:
@@ -72,11 +71,11 @@ class ItemEffects(wx.Panel):
else:
effectRunTime = ""
self.effectList.SetStringItem(index, 1, activeByDefault)
self.effectList.SetStringItem(index, 2, effectTypeText)
self.effectList.SetItem(index, 1, activeByDefault)
self.effectList.SetItem(index, 2, effectTypeText)
if config.debug:
self.effectList.SetStringItem(index, 3, effectRunTime)
self.effectList.SetStringItem(index, 4, str(effects[name].ID))
self.effectList.SetItem(index, 3, effectRunTime)
self.effectList.SetItem(index, 4, str(effects[name].ID))
self.effectList.RefreshRows()
self.Layout()

View File

@@ -1,9 +1,7 @@
import sys
# noinspection PyPackageRequirements
import wx
from helpers import AutoListCtrl
from .helpers import AutoListCtrl
class ItemProperties(wx.Panel):
@@ -27,7 +25,7 @@ class ItemProperties(wx.Panel):
mainSizer.Add(self.m_staticline, 0, wx.EXPAND)
bSizer = wx.BoxSizer(wx.HORIZONTAL)
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, u" ", wx.DefaultPosition, wx.DefaultSize, 0)
self.totalAttrsLabel = wx.StaticText(self, wx.ID_ANY, " ", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer.Add(self.totalAttrsLabel, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT)
mainSizer.Add(bSizer, 0, wx.ALIGN_RIGHT)
@@ -79,7 +77,7 @@ class ItemProperties(wx.Panel):
attrName = name.title()
value = getattr(self.item, name)
index = self.paramList.InsertStringItem(sys.maxint, attrName)
index = self.paramList.InsertItem(self.paramList.GetItemCount(), attrName)
# index = self.paramList.InsertImageStringItem(sys.maxint, attrName)
idNameMap[idCount] = attrName
self.paramList.SetItemData(index, idCount)
@@ -87,13 +85,13 @@ class ItemProperties(wx.Panel):
valueUnit = str(value)
self.paramList.SetStringItem(index, 1, valueUnit)
self.paramList.SetItem(index, 1, valueUnit)
except:
# TODO: Add logging to this.
# We couldn't get a property for some reason. Skip it for now.
continue
self.paramList.SortItems(lambda id1, id2: cmp(idNameMap[id1], idNameMap[id2]))
self.paramList.SortItems(lambda id1, id2: (idNameMap[id1] > idNameMap[id2]) - (idNameMap[id1] < idNameMap[id2]))
self.paramList.RefreshRows()
self.totalAttrsLabel.SetLabel("%d attributes. " % idCount)
self.Layout()

View File

@@ -1,7 +1,7 @@
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from gui.bitmap_loader import BitmapLoader
class ItemRequirements(wx.Panel):
@@ -19,7 +19,7 @@ class ItemRequirements(wx.Panel):
self.SetSizer(mainSizer)
self.root = self.reqTree.AddRoot("WINRARZOR")
self.reqTree.SetPyData(self.root, None)
self.reqTree.SetItemData(self.root, None)
self.imageList = wx.ImageList(16, 16)
self.reqTree.SetImageList(self.imageList)
@@ -32,7 +32,7 @@ class ItemRequirements(wx.Panel):
self.Layout()
def getFullSkillTree(self, parentSkill, parent, sbIconId):
for skill, level in parentSkill.requiredSkills.iteritems():
for skill, level in parentSkill.requiredSkills.items():
child = self.reqTree.AppendItem(parent, "%s %s" % (skill.name, self.romanNb[int(level)]), sbIconId)
if skill.ID not in self.skillIdHistory:
self.getFullSkillTree(skill, child, sbIconId)

Some files were not shown because too many files have changed in this diff Show More