Compare commits

...

59 Commits

Author SHA1 Message Date
DarkPhoenix
7c88fa477f Bump version 2020-02-13 12:20:03 +03:00
DarkPhoenix
f8df540fad Use newer wxpython version once again 2020-02-13 12:19:37 +03:00
DarkPhoenix
61a01805cc Reset locale and remove resolution data from all the images (wxpython phoenix issue #1515) 2020-02-13 12:14:26 +03:00
DarkPhoenix
0f74c97fbf Temporarily revert python version to 3.7 2020-02-12 18:31:44 +03:00
DarkPhoenix
29713b69dc Fix the hack 2020-02-12 18:25:17 +03:00
DarkPhoenix
cc3c2cb9c8 Add hack to build wx on windows 2020-02-12 18:22:31 +03:00
DarkPhoenix
b36a3959da Revert wxpython version to 4.0.6 2020-02-12 18:18:18 +03:00
DarkPhoenix
3b26bfc0e9 Add missing entries to migration 2020-02-11 17:02:00 +03:00
DarkPhoenix
c59b621963 Add capacitor transfer tiericide conversion entries 2020-02-11 16:52:15 +03:00
DarkPhoenix
977a8fa329 Update staticdata to 1663997 2020-02-11 16:20:08 +03:00
DarkPhoenix
a5226fee83 Merge branch 'singularity' 2020-02-11 16:08:46 +03:00
DarkPhoenix
e4069a3988 Update AppVeyor deploy oauth key after repo transfer 2020-02-04 00:41:03 +03:00
DarkPhoenix
6527f9e11e Attempt to terminate threads when pyfa is closed 2020-02-03 17:12:23 +03:00
DarkPhoenix
9ddfcc894f Make sure not to catch keyboard interrupts and system exits 2020-02-03 16:12:41 +03:00
DarkPhoenix
f22a4f13e5 Allow pasting non-mutated modules via ctrl-v 2020-02-03 15:54:22 +03:00
DarkPhoenix
fc9337df67 Add more info prints to mac os packaging scripts 2020-02-03 13:37:27 +03:00
DarkPhoenix
98a8332cfa Change the way we update pip for mac os builds 2020-02-03 13:33:26 +03:00
DarkPhoenix
a78eedad48 Remove unused files 2020-02-03 13:30:04 +03:00
DarkPhoenix
85e1a1bd06 Use newer image version for mac builds 2020-02-03 13:25:51 +03:00
DarkPhoenix
25b2c04309 Do not set environment variable as it's not used anymore 2020-02-03 13:23:56 +03:00
DarkPhoenix
54a84d0e42 Do not attempt to install custom python version, just use system default 2020-02-03 13:23:13 +03:00
DarkPhoenix
af0a4d1def Update travis deployment key 2020-02-03 13:11:48 +03:00
DarkPhoenix
97cdde84ce Uninstall not when setup just begins, but right before install begins 2020-02-03 06:17:28 +03:00
DarkPhoenix
a65129b277 Fix function definition order in inno setup script 2020-02-03 06:06:25 +03:00
DarkPhoenix
3b40a49918 Uninstall previous pyfa version unconditionally 2020-02-03 05:59:29 +03:00
DarkPhoenix
d95345b476 Insist on uninstalling old pyfa versions when next one is about to be installed 2020-02-02 23:48:06 +03:00
DarkPhoenix
2ba2d95017 Change clone depth to 400 on appveyor 2020-02-02 14:46:26 +03:00
DarkPhoenix
4d0ffedcc8 Install in 64 bit mode on Windows 2020-02-02 11:07:20 +03:00
DarkPhoenix
84abde4fc5 Some OCD in echoes + testing if build is started after webhook removal 2020-02-02 04:22:41 +03:00
DarkPhoenix
8897f1e4b1 Use my credentials when uploading builds to releases 2020-02-02 04:08:10 +03:00
DarkPhoenix
6f33cacb7a Clean up appveyor file 2020-02-02 03:54:52 +03:00
DarkPhoenix
b1a8c0ad09 Disable appveyor's RDP setup as it's a security hole 2020-02-02 03:40:20 +03:00
DarkPhoenix
13ed635803 We do not care if all PR builds will be built 2020-02-02 03:38:43 +03:00
DarkPhoenix
5a44909ebf Remove appveyor environment preparation which is not needed anymore 2020-02-02 03:13:57 +03:00
DarkPhoenix
6cbb80693d Switch to powershell echo 2020-02-02 03:04:53 +03:00
DarkPhoenix
0b90d254f9 Try another approach in echo'ing 2020-02-02 02:53:18 +03:00
DarkPhoenix
641d36205c Remove quotes from echo commands 2020-02-02 02:47:14 +03:00
DarkPhoenix
6e38b6ea4d Fix path to windows SDK once again 2020-02-02 02:38:26 +03:00
DarkPhoenix
84b4d8fabb Change windows SDK location 2020-02-02 02:03:23 +03:00
DarkPhoenix
c0e1f7e746 Fix mistype 2020-02-01 15:36:33 +03:00
DarkPhoenix
d734c12168 Try to find out when listing windows SDKs fails 2020-02-01 15:34:14 +03:00
DarkPhoenix
340d94eb3e Specify image in apprveyor file 2020-02-01 15:09:47 +03:00
DarkPhoenix
9b0b31648c Add debugging prints to see appveyor's OS version 2020-02-01 02:38:00 +03:00
DarkPhoenix
8346358c37 Fix appveyor script slashes 2020-02-01 02:24:09 +03:00
DarkPhoenix
b935700a12 Bump INNO setup version 2020-02-01 01:56:26 +03:00
DarkPhoenix
2f4a5a4830 Fix improper use of operator "is" when comparing to literal values 2020-01-31 18:16:36 +03:00
DarkPhoenix
4d4680961e Bump versions of multiple packages 2020-01-31 16:08:24 +03:00
DarkPhoenix
1cae99b812 Remove VC 9.0 tools manifest
We're using newer version now, and we will see later if dependency section in manifest is needed
2020-01-31 16:07:26 +03:00
DarkPhoenix
3727d19311 In attribute editor what is you see is what you get now 2020-01-31 10:32:18 +03:00
DarkPhoenix
c45c093f4f Return search results as list to avoid various issues 2020-01-31 10:04:35 +03:00
DarkPhoenix
b613d3e312 Use market sorting in attribute override editor 2020-01-31 00:37:35 +03:00
DarkPhoenix
4cff9247b0 Always include ships and citadels in override editor output 2020-01-31 00:13:40 +03:00
DarkPhoenix
b9a26ec28d Do not return items from all the categories in overrides editor searches 2020-01-31 00:00:05 +03:00
DarkPhoenix
245f81e888 Actually make appveyor to use 64 bit python 2020-01-30 13:55:30 +03:00
DarkPhoenix
204c1ba9f2 Switch windows build to be 64 bits 2020-01-30 13:45:49 +03:00
DarkPhoenix
a7a4be133c Bump pyinstaller version once again 2020-01-30 13:04:49 +03:00
DarkPhoenix
14f9a46d7a Remove MPL hook 2020-01-30 11:59:04 +03:00
DarkPhoenix
003dd040dc Bump matplotlib version 2020-01-30 11:51:27 +03:00
DarkPhoenix
97cf53217e Bump python version to 3.8 2020-01-30 11:09:11 +03:00
116 changed files with 6847 additions and 8971 deletions

View File

@@ -1,126 +1,76 @@
image: Visual Studio 2019
clone_depth: 400
environment:
global:
# SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
# /E:ON and /V:ON options are not enabled in the batch script intepreter
# See: http://stackoverflow.com/a/13751649/163740
CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
matrix:
- PYTHON: "C:\\Python36"
PYTHON_VERSION: "3.6.x"
PYTHON_ARCH: "32"
init:
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
- PYTHON: "C:\\Python38-x64"
# Should be enabled only for build process debugging
# init:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
install:
# If there is a newer build queued for the same PR, cancel this one.
# The AppVeyor 'rollout builds' option is supposed to serve the same
# purpose but it is problematic because it tends to cancel builds pushed
# directly to master instead of just PR builds (or the converse).
# credits: JuliaLang developers.
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
- ps: echo("OS version:")
- ps: "[System.Environment]::OSVersion.Version"
- ECHO "Filesystem root:"
- ps: "ls \"C:/\""
- ps: echo("Filesystem - root:")
- ps: "ls \"C:\\\""
- ECHO "Filesystem projects root:"
- ps: echo("Filesystem - projects root:")
- ps: "ls \"C:\\projects\\\""
- ECHO "Filesystem pyfa root:"
- ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\""
- ps: echo("Filesystem - pyfa root:")
- ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\\\""
- ECHO "Installed SDKs:"
- ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\""
- ps: echo("Filesystem - installed SDKs:")
- ps: "ls \"C:\\Program Files (x86)\\Windows Kits\\\""
# Prepend newly installed Python to the PATH of this build (this cannot be
# done from inside the powershell script as it would require to restart
# the parent CMD process).
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- cmd: "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- "python --version"
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
- cmd: "python --version"
- cmd: "python -c \"import struct; print(struct.calcsize('P') * 8)\""
# Upgrade to the latest version of pip to avoid it displaying warnings
# about it being out of date.
- "python -m pip install --disable-pip-version-check --user --upgrade pip"
- cmd: "python -m pip install --upgrade pip"
# Install the build dependencies of the project. If some dependencies contain
# compiled extensions and are not provided as pre-built wheel packages,
# pip will build them from source using the MSVC compiler matching the
# target Python version and architecture
- ECHO "Install pip requirements:"
- "python -m pip install -r requirements.txt"
- "python -m pip install PyInstaller==3.3"
- ps: echo("Install pip requirements:")
- cmd: "python -m pip install -r requirements.txt"
- cmd: "python -m pip install PyInstaller==3.6"
before_build:
# directory that will contain the built files
- ps: $env:PYFA_DIST_DIR = "c:\projects\$env:APPVEYOR_PROJECT_SLUG\dist"
- ps: $env:PYFA_VERSION = (python ./scripts/dump_version.py)
- ps: echo("pyfa version ")
- ps: echo ($env:PYFA_VERSION)
- ps: echo("pyfa version $env:PYFA_VERSION")
build_script:
- ECHO "Build pyfa:"
- ps: echo("Build pyfa:")
# Build gamedata DB
- "python db_update.py"
##########
# PyInstaller - create binaries for pyfa
##########
- cmd: "python db_update.py"
# Build command for PyInstaller
- "python -m PyInstaller --noupx --clean --windowed --noconsole -y pyfa.spec"
- cmd: "python -m PyInstaller --noupx --clean --windowed --noconsole -y pyfa.spec"
# Copy over manifest (See pyfa-org/pyfa#1622)
- ps: xcopy /y dist_assets\win\pyfa.exe.manifest $env:PYFA_DIST_DIR\pyfa\
# Not really sure if this is needed, but why not
- ps: xcopy /y dist_assets\win\Microsoft.VC90.CRT.manifest $env:PYFA_DIST_DIR\pyfa\
##########
# InnoScript EXE building
# This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
##########
- "python dist_assets/win/dist.py"
# InnoScript EXE building. This is in a separate script because I don't feel like copying over the logic to AppVeyor script right now...
- cmd: "python dist_assets/win/dist.py"
- ps: dir $env:PYFA_DIST_DIR/
#- ECHO "Build pyfa (Debug):"
#- copy C:\projects\pyfa\dist_assets\win\pyfa_debug.spec C:\projects\pyfa\pyfa_debug.spec
#- "pyinstaller.exe --clean --noconfirm --windowed --upx-dir=C:\\projects\\pyfa\\scripts\\upx.exe C:\\projects\\pyfa\\pyfa_debug.spec"
build: on
after_build:
- ps: "ls \"./\""
#- ps: "ls \"C:\\projects\\pyfa\\build\\pyfa\\\""
# - ps: "ls \"C:\\projects\\$env:APPVEYOR_PROJECT_SLUG\\build\\exe.win32-2.7\\\""
# Zip
# APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER
#- 7z a build.zip -r C:\projects\pyfa\build\pyfa\*.*
- ps: 7z a "pyfa-$env:PYFA_VERSION-win.zip" -r "$env:PYFA_DIST_DIR\pyfa\*.*"
#- 7z a pyfa_debug.zip -r C:\projects\pyfa\dist\pyfa_debug\*.*
on_success:
# Do nothing right now
test_script:
#- tox
#- "py.test --cov=./"
# Run the project tests
# - "%CMD_IN_ENV% python C:/projects/eve-gnosis/setup.py nosetests"
after_test:
# If tests are successful, create binary packages for the project.
# - "%CMD_IN_ENV% python setup.py bdist_wheel"
# - "%CMD_IN_ENV% python setup.py bdist_wininst"
# - "%CMD_IN_ENV% python setup.py bdist_msi"
# - ps: "ls dist"
# Ha... we're just building
artifacts:
# Archive the generated packages in the ci.appveyor.com build report.
- path: pyfa*-win.zip
- path: pyfa*-win.exe
#- path: pyfa_debug.zip
# name: Pyfa_debug
deploy:
tag: $(pyfa_version)
@@ -128,10 +78,9 @@ deploy:
description: 'Release description'
provider: GitHub
auth_token:
secure: BfNHO66ff5hVx2O2ORbl49X0U/5h2V2T0IuRZDwm7fd1HvsVluF0wRCbl29oRp1M
secure: X+U3hOAMTt7HGXCR/LXaGNF6qyhUXetrjz5+xlWiNJQ3XEdzhZZmHK75m0Hm6qre
draft: true
force_update: false
# deploy on tag push only
on:
APPVEYOR_REPO_TAG: true # deploy on tag push only
#on_success:
# - TODO: upload the content of dist/*.whl to a public wheelhouse
#
APPVEYOR_REPO_TAG: true

View File

@@ -3,13 +3,12 @@ language: python
git:
depth: 400
python:
- 3.6
- 3.8
matrix:
include:
- os: osx
osx_image: xcode7.3
osx_image: xcode11.3
language: generic
env: PYTHON=3.6.1
before_install:
- bash scripts/setup-osx.sh
install:
@@ -22,7 +21,7 @@ before_deploy:
deploy:
provider: releases
api_key:
secure: Xfu0xApoB0zUPLXl29aYUulVC3iA4/3bXQwwADKCfAKZwxgNon4dLbO7Rie5/7Ukf2POL0KwmRaQGN3kOr+XSoIVTE4M5sXxnhiaaLGKQ+48hDizLE6JuXcZGJvkxUaghaTzIdCwHsG7VGBsPfQgfGsjJcfBp8tFNLmRyM/Jpsr8T6BR2MxtBIEUVy8zrOWFNZqnmWrY2pWMsB9fYt3JFNdpqeIgRAYqbBsBcZQ1MngLTi3ztuYS5IaF+lk06RrnBlHmUsJu/5nCvIpvPvD0i2BLZ3Uu0+Fn+8QWUgjJEL9MNseXZMXynu05xd8YRk7Ajc9CUrzQIIbAktyteYp85kE3pUJHmrMLcXhh7nqkwttR5/47Zwa3OLJLJFKBxMx6wY5jFkJjkV08850B7aWrmTFl/Eqc3Q5nZMuiEt3wFRbjxHi9h1mTN/fkxfRRHg8u3ENGPR+ZPiFC3J18qtks/B/hsKjjHvZP1i79OYlET4V/zyLyyQkCbpDaARQANuotLYJyZ7tH+KWEyRsvTi0M9Yev9mNNw6aI4vzh4HfkEhvcvnWnYwckPj1dnjQ573Qpw0Z9wsconoWfHAn+hBDt3+YLMrrFZl++mCRskHH1mZChX3aGMDi49zD0kfxBUkYPOAhguc6PwudBxHUZP+O6T/SoHylff6EizCE/k5dGeAk=
secure: D8tBW0kyHlKf/sXS69aIuexsYTx9auY2DzudKFlfcvdzqat4N2XZqZbZCTVd7YVvptQ8Dj0oZ/p3KUxEGpnJZmlTeJL142rpM/qaNd6wOIMy2yUde/aZl+W9JLFNQp7KHutM+MxObYLzJGihx/8YsupmFx6lxgdngGDXtXYZe/ruDIWDs92ShoKJ4vlce9Csm7eGKv7wv6Z6V9sD5FS3E9J8xdWStHxsbrkPBOflmG+uHU09dpEqzUm+ZYROIoTwig1Xbw3fw+gfjmNrfdSU4fAJcVZI1hrgoenZyJbMfhI2Ej/nZdbZgaXcZNF/eUpqOGgbPe1JljqFnHTbexcE+LPBVyAToScsGMpByHhig67DrZ0nk9gSZoC6CPNl5YS6xub+5dncMJ3P5L03DOGYRu4SL9NczbeuQyKuea7+JPP/8VLwfFDSEqbNEAmgzABAzrdfano+VXtuBuE/Tiy5eE7le9hJu6aSQoKW1SA3cUhMsmr2amzdO96sh+PN8FA1oNr45Yuy0pqOj4SUIkb8JUy4th7vgdhljEkSxrHDK1UcHpxUTp+IIUZkZVVk50aH68dQZxGwSTVOeRxpjrTcEf7VCGaM98qxi/ZK4RW6Ewiq0eo0AxwEeB2Zm841lycGPR/406vM9/ZBzv5IhELIdDdVWTk+dGjJBXB8z5hPJOg=
file_glob: true
file: "dist/pyfa-*.zip"
skip_cleanup: true

View File

@@ -49,6 +49,8 @@ def DBInMemory_test():
gamedata_version = gamedata_session.execute(
"SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'client_build'"
).fetchone()[0]
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
print("Missing gamedata version.")
gamedata_version = None

View File

@@ -233,6 +233,8 @@ def defLogging():
# reset=False,
)
])
except (KeyboardInterrupt, SystemExit):
raise
except:
print("Critical error attempting to setup logging. Falling back to console only.")
logging_setup = NestedSetup([

View File

@@ -40,7 +40,7 @@ def db_needs_update():
try:
with open(os.path.join(JSON_DIR, 'phobos', 'metadata.json')) as f:
data_version = next((r['field_value'] for r in json.load(f) if r['field_name'] == 'client_build'))
except KeyboardInterrupt:
except (KeyboardInterrupt, SystemExit):
raise
# If we have no source data - return None; should not update in this case
except:
@@ -61,7 +61,7 @@ def db_needs_update():
db_schema_version = int(row[0])
cursor.close()
db.close()
except KeyboardInterrupt:
except (KeyboardInterrupt, SystemExit):
raise
except:
print('Error when fetching gamedata DB metadata')

View File

@@ -1,78 +0,0 @@
# 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,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<noInheritable/>
<assemblyIdentity
type="win32"
name="Microsoft.VC90.CRT"
version="9.0.21022.8"
processorArchitecture="x86"
publicKeyToken="1fc8b3b9a1e18e3b"/>
<file name="MSVCR90.DLL"/>
<file name="MSVCM90.DLL"/>
<file name="MSVCP90.DLL"/>
</assembly>

View File

@@ -14,7 +14,7 @@ with open("version.yml", 'r') as file:
os.environ["PYFA_DIST_DIR"] = os.path.join(os.getcwd(), 'dist')
os.environ["PYFA_VERSION"] = version
iscc = "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" # inno script location via wine
iscc = "C:\Program Files (x86)\Inno Setup 6\ISCC.exe"
source = os.path.join(os.environ["PYFA_DIST_DIR"], "pyfa")

View File

@@ -15,10 +15,6 @@
#define MyAppURL "https://github.com/pyfa-org/Pyfa/"
#define MyAppExeName "pyfa.exe"
; What version starts with the new structure (1.x.0). This is used to determine if we run directory structure cleanup
#define MajorVersionFlag 2
#define MinorVersionFlag 0
#ifndef MyOutputFile
#define MyOutputFile LowerCase(StringChange(MyAppName+'-'+MyAppVersion+'-win', " ", "-"))
#endif
@@ -30,7 +26,6 @@
#endif
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
@@ -41,6 +36,9 @@ AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
CloseApplications=yes
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
@@ -49,7 +47,6 @@ OutputDir={#MyOutputDir}
OutputBaseFilename={#MyOutputFile}
SetupIconFile={#MyAppDir}\pyfa.ico
SolidCompression=yes
CloseApplications=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -83,6 +80,7 @@ Type: files; Name: "{app}\*.pyc"
[Code]
/////////////////////////////////////////////////////////////////////
function IsAppRunning(const FileName : string): Boolean;
var
FSWbemLocator: Variant;
@@ -99,6 +97,7 @@ begin
FSWbemLocator := Unassigned;
end;
/////////////////////////////////////////////////////////////////////
procedure RemoveFromVirtualStore;
var
VirtualStore,FileName,FilePath:String;
@@ -115,6 +114,7 @@ begin
end;
end;
/////////////////////////////////////////////////////////////////////
function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
if(IsAppRunning( 'pyfa.exe' )) then
@@ -127,54 +127,61 @@ begin
end
end;
function GetUninstallString: string;
/////////////////////////////////////////////////////////////////////
function GetUninstallString(): String;
var
sUnInstPath: string;
sUnInstPath: String;
sUnInstallString: String;
begin
Result := '';
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1'); //Your App GUID/ID
sUnInstallString := '';
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
if not RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString) then
if not RegQueryStringValue(HKLM32, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU32, sUnInstPath, 'UninstallString', sUnInstallString);
Result := sUnInstallString;
end;
function IsUpgrade: Boolean;
/////////////////////////////////////////////////////////////////////
function UnInstallOldVersion(): Integer;
var
sUnInstallString: String;
iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString
// default return value
Result := 0;
// get the uninstall string of the old app
sUnInstallString := GetUninstallString();
if sUnInstallString <> '' then begin
sUnInstallString := RemoveQuotes(sUnInstallString);
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
Result := 3
else
Result := 2;
end else
Result := 1;
end;
/////////////////////////////////////////////////////////////////////
function IsUpgrade(): Boolean;
begin
Result := (GetUninstallString() <> '');
end;
function InitializeSetup: Boolean;
var
V: Integer;
iResultCode: Integer;
sUnInstallString: string;
iOldVersionMajor: Cardinal;
iOldVersionMinor: Cardinal;
/////////////////////////////////////////////////////////////////////
procedure CurStepChanged(CurStep: TSetupStep);
begin
Result := True; // in case when no previous version is found
if RegValueExists(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1', 'UninstallString') then //Your App GUID/ID
if (CurStep=ssInstall) then
begin
RegQueryDWordValue(HKEY_LOCAL_MACHINE,
'Software\Microsoft\Windows\CurrentVersion\Uninstall\{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1',
'MajorVersion', iOldVersionMajor);
RegQueryDWordValue(HKEY_LOCAL_MACHINE,
'Software\Microsoft\Windows\CurrentVersion\Uninstall\{3DA39096-C08D-49CD-90E0-1D177F32C8AA}_is1',
'MinorVersion', iOldVersionMinor);
if (iOldVersionMajor < {#MajorVersionFlag}) or ((iOldVersionMajor = {#MajorVersionFlag}) and (iOldVersionMinor < {#MinorVersionFlag})) then // If old version with old structure is installed.
if (IsUpgrade()) then
begin
V := MsgBox(ExpandConstant('An old version of pyfa was detected. Due to recent changes in the application structure, you must uninstall the previous version first. This will not affect your user data (saved fittings, characters, etc.). Do you want to uninstall now?'), mbInformation, MB_YESNO); //Custom Message if App installed
if V = IDYES then
begin
sUnInstallString := GetUninstallString();
sUnInstallString := RemoveQuotes(sUnInstallString);
Exec(ExpandConstant(sUnInstallString), '', '', SW_SHOW, ewWaitUntilTerminated, iResultCode);
Result := True; //if you want to proceed after uninstall
//Exit; //if you want to quit after uninstall
end
else
Result := False; //when older version present and not uninstalled
UnInstallOldVersion();
end;
end;
end;

View File

@@ -8,11 +8,6 @@
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>

View File

@@ -20,7 +20,6 @@ added_files = [
('../../service/jargon/*.yaml', 'service/jargon'),
('../../dist_assets/win/pyfa.ico', '.'),
('../../dist_assets/win/pyfa.exe.manifest', '.'),
('../../dist_assets/win/Microsoft.VC90.CRT.manifest', '.'),
(requests.certs.where(), '.'), # is this needed anymore?
('../../eve.db', '.'),
('../../README.md', '.'),

View File

@@ -1,83 +0,0 @@
# -*- 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
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', '.' ),
]
import_these = []
# Walk eos.effects and add all effects so we can import them properly
for root, folders, files in os.walk("eos/effects"):
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=['C:\\projects\\pyfa\\'],
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,
debug=True,
console=True,
strip=False,
upx=True,
name='pyfa_debug',
icon='dist_assets/win/pyfa.ico',
onefile=False,
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
onefile=False,
name='pyfa_debug',
icon='dist_assets/win/pyfa.ico',
)

View File

@@ -56,6 +56,8 @@ try:
config.gamedata_date = gamedata_session.execute(
"SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'dump_time'"
).fetchone()[0]
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.warning("Missing gamedata version.")
pyfalog.critical(e)

View File

@@ -33,9 +33,13 @@ def upgrade(saveddata_engine):
try:
saveddata_session.execute(commandFits_table.insert(),
{"boosterID": value, "boostedID": boosted, "active": 1})
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
pass
saveddata_session.commit()
except (KeyboardInterrupt, SystemExit):
raise
except:
# Shouldn't fail unless you have updated database without the old fleet schema and manually modify the database version
# If it does, simply fail. Fleet data migration isn't critically important here

View File

@@ -4235,6 +4235,8 @@ def upgrade(saveddata_engine):
# And last but not least, delete the last subsystem
saveddata_engine.execute("DELETE FROM modules WHERE ID = ?", (oldModules[4][0],))
except (KeyboardInterrupt, SystemExit):
raise
except:
# if something fails, fuck it, we tried. It'll default to the generic conversion below
continue

View File

@@ -0,0 +1,84 @@
"""
Migration 36
- Shield Booster, Armor Repairer and Capacitor Transfer tiericide
"""
CONVERSIONS = {
6441: ( # Small Clarity Ward Enduring Shield Booster
6443, # Small Converse Deflection Catalyzer
),
6437: ( # Small C5-L Compact Shield Booster
6439, # Small Neutron Saturation Injector I
),
10868: ( # Medium Clarity Ward Enduring Shield Booster
10870, # Medium Converse Deflection Catalyzer
),
10872: ( # Medium C5-L Compact Shield Booster
10866, # Medium Neutron Saturation Injector I
),
10876: ( # Large Clarity Ward Enduring Shield Booster
10878, # Large Converse Deflection Catalyzer
),
10880: ( # Large C5-L Compact Shield Booster
10874, # Large Neutron Saturation Injector I
),
10884: ( # X-Large Clarity Ward Enduring Shield Booster
10886, # X-Large Converse Deflection Catalyzer
),
10888: ( # X-Large C5-L Compact Shield Booster
10882, # X-Large Neutron Saturation Injector I
),
4533: ( # Small ACM Compact Armor Repairer
4531, # Small Inefficient Armor Repair Unit
),
4529: ( # Small I-a Enduring Armor Repairer
4535, # Small Automated Carapace Restoration
),
4573: ( # Medium ACM Compact Armor Repairer
4571, # Medium Inefficient Armor Repair Unit
),
4569: ( # Medium I-a Enduring Armor Repairer
4575, # Medium Automated Carapace Restoration
),
22889: ( # 'Meditation' Medium Armor Repairer I
4579, # Medium Nano Armor Repair Unit I
),
4613: ( # Large ACM Compact Armor Repairer
4611, # Large Inefficient Armor Repair Unit
),
4609: ( # Large I-a Enduring Armor Repairer
4615, # Large Automated Carapace Restoration
),
22891: ( # 'Protest' Large Armor Repairer I
4621, # Large 'Reprieve' Vestment Reconstructer I
),
5093: ( # Small Radiative Scoped Remote Capacitor Transmitter
5087, # Small Partial E95a Remote Capacitor Transmitter
),
5091: ( # Small Inductive Compact Remote Capacitor Transmitter
5089, # Small Murky Remote Capacitor Transmitter
),
16489: ( # Medium Radiative Scoped Remote Capacitor Transmitter
16493, # Medium Partial E95b Remote Capacitor Transmitter
),
16495: ( # Medium Inductive Compact Remote Capacitor Transmitter
16491, # Medium Murky Remote Capacitor Transmitter
),
16481: ( # Large Radiative Scoped Remote Capacitor Transmitter
16485, # Large Partial E95c Remote Capacitor Transmitter
),
16487: ( # Large Inductive Compact Remote Capacitor Transmitter
16483, # Large Murky Remote Capacitor Transmitter
)
}
def upgrade(saveddata_engine):
# Convert modules
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))
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -560,6 +560,8 @@ def commit():
with sd_lock:
try:
saveddata_session.commit()
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
saveddata_session.rollback()
exc_info = sys.exc_info()
@@ -570,6 +572,8 @@ def flush():
with sd_lock:
try:
saveddata_session.flush()
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
saveddata_session.rollback()
exc_info = sys.exc_info()

View File

@@ -9194,7 +9194,7 @@ class Effect3002(BaseEffect):
Modules from group: Energy Nosferatu (54 of 54)
Modules from group: Hull Repair Unit (25 of 25)
Modules from group: Remote Armor Repairer (39 of 39)
Modules from group: Remote Capacitor Transmitter (41 of 41)
Modules from group: Remote Capacitor Transmitter (35 of 35)
Modules from group: Remote Shield Booster (38 of 38)
Modules from group: Smart Bomb (118 of 118)
Modules from group: Warp Disrupt Field Generator (7 of 7)
@@ -25036,7 +25036,7 @@ class Effect6184(BaseEffect):
shipModuleRemoteCapacitorTransmitter
Used by:
Modules from group: Remote Capacitor Transmitter (41 of 41)
Modules from group: Remote Capacitor Transmitter (35 of 35)
"""
runTime = 'late'
@@ -32660,6 +32660,8 @@ class Effect6871(BaseEffect):
# via https://forums.eveonline.com/default.aspx?g=posts&t=515826
try:
bonus = max(0, min(50.0, (src.owner.character.secStatus * 10)))
except (KeyboardInterrupt, SystemExit):
raise
except:
bonus = None

View File

@@ -184,6 +184,8 @@ class Effect(EqBase):
self.__activeByDefault = True
self.__type = None
pyfalog.error("AttributeError generating handler: {0}", e)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
self.__handler = eos.effects.DummyEffect.handler
self.__runTime = "normal"
@@ -200,6 +202,8 @@ class Effect(EqBase):
try:
return self.__effectDef.get(key, None)
except (KeyboardInterrupt, SystemExit):
raise
except:
return getattr(self.__effectDef, key, None)

View File

@@ -260,6 +260,8 @@ class DamagePattern:
line = line.split('#', 1)[0] # allows for comments
type, data = line.rsplit('=', 1)
type, data = type.strip(), data.split(',')
except (KeyboardInterrupt, SystemExit):
raise
except:
# Data isn't in correct format, continue to next line
continue
@@ -274,6 +276,8 @@ class DamagePattern:
for index, val in enumerate(data):
try:
fields["%sAmount" % cls.DAMAGE_TYPES[index]] = int(val)
except (KeyboardInterrupt, SystemExit):
raise
except:
continue

View File

@@ -73,6 +73,8 @@ class Mutator(EqBase):
self.dynamicAttribute = next(a for a in self.module.mutaplasmid.attributes if a.attributeID == self.attrID)
# base attribute links to the base ite's attribute for this mutated definition (contains original, base value)
self.baseAttribute = self.module.item.attributes[self.dynamicAttribute.name]
except (KeyboardInterrupt, SystemExit):
raise
except:
self.module = None

View File

@@ -294,6 +294,8 @@ class TargetProfile:
line = line.split('#', 1)[0] # allows for comments
type, data = line.rsplit('=', 1)
type, data = type.strip(), [d.strip() for d in data.split(',')]
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.warning("Data isn't in correct format, continue to next line.")
continue
@@ -312,6 +314,8 @@ class TargetProfile:
try:
assert 0 <= val <= 100
fields["%sAmount" % cls.DAMAGE_TYPES[index]] = val / 100
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.warning("Caught unhandled exception in import patterns.")
continue

View File

@@ -54,6 +54,8 @@ try:
except ImportError as e:
pyfalog.warning('Matplotlib failed to import. Likely missing or incompatible version.')
graphFrame_enabled = False
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
# We can get exceptions deep within matplotlib. Catch those. See GH #1046
tb = traceback.format_exc()
@@ -71,6 +73,8 @@ class GraphCanvasPanel(wx.Panel):
# Remove matplotlib font cache, see #234
try:
cache_dir = mpl._get_cachedir()
except (KeyboardInterrupt, SystemExit):
raise
except:
cache_dir = os.path.expanduser(os.path.join('~', '.matplotlib'))
cache_file = os.path.join(cache_dir, 'fontList.cache')
@@ -168,6 +172,8 @@ class GraphCanvasPanel(wx.Panel):
legendData.append((color, lineStyle, source.shortName))
else:
legendData.append((color, lineStyle, '{} vs {}'.format(source.shortName, target.shortName)))
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
pyfalog.warning('Failed to plot "{}" vs "{}"'.format(source.name, '' if target is None else target.name))
self.canvas.draw()
@@ -241,6 +247,8 @@ class GraphCanvasPanel(wx.Panel):
src=source,
tgt=target)
addYMark(y)
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
pyfalog.warning('Failed to get X mark for "{}" vs "{}"'.format(source.name, '' if target is None else target.name))
# Silently skip this mark, otherwise other marks and legend display will fail

View File

@@ -112,6 +112,8 @@ class ItemAffectedBy(wx.Panel):
else:
try:
self.affectedBy.CollapseAll()
except (KeyboardInterrupt, SystemExit):
raise
except:
pass

View File

@@ -86,6 +86,8 @@ class ItemProperties(wx.Panel):
valueUnit = str(value)
self.paramList.SetItem(index, 1, valueUnit)
except (KeyboardInterrupt, SystemExit):
raise
except:
# TODO: Add logging to this.
# We couldn't get a property for some reason. Skip it for now.

View File

@@ -49,8 +49,6 @@ class ItemView(Display):
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.itemActivated)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
# Make reverse map, used by sorter
self.metaMap = self.makeReverseMetaMap()
self.active = []
def delaySearch(self, evt):
@@ -180,7 +178,7 @@ class ItemView(Display):
return
self.marketBrowser.mode = 'search'
self.sMkt.searchItems(search, self.populateSearch)
self.sMkt.searchItems(search, self.populateSearch, 'market')
def clearSearch(self, event=None):
# Wipe item store and update everything to accomodate with it
@@ -214,7 +212,7 @@ class ItemView(Display):
parentname = sMkt.getParentItemByItem(item).name
# Get position of market group
metagrpid = sMkt.getMetaGroupIdByItem(item)
metatab = self.metaMap.get(metagrpid)
metatab = sMkt.META_MAP_REVERSE_INDICES.get(metagrpid)
metalvl = item.metaLevel or 0
return catname, mktgrpid, parentname, metatab, metalvl, item.name
@@ -259,18 +257,6 @@ class ItemView(Display):
Display.refresh(self, items)
def makeReverseMetaMap(self):
"""
Form map which tells in which tab items of given metagroup are located
"""
revmap = {}
i = 0
for mgids in self.sMkt.META_MAP.values():
for mgid in mgids:
revmap[mgid] = i
i += 1
return revmap
def columnBackground(self, colItem, item):
if self.sFit.serviceFittingOptions["colorFitBySlot"]:
return slotColourMap.get(Module.calculateSlot(item)) or self.GetBackgroundColour()

View File

@@ -63,6 +63,8 @@ class MarketTree(wx.TreeCtrl):
iconId = self.addImage(sMkt.getIconByMarketGroup(childMktGrp))
try:
childId = self.AppendItem(root, childMktGrp.name, iconId, data=childMktGrp.ID)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.debug("Error appending item.")
pyfalog.debug(e)

View File

@@ -66,6 +66,8 @@ class FitSpawner(gui.multiSwitch.TabSpawner):
self.multiSwitch.SetSelection(index)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(event.fitID,)))
break
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.critical("Caught exception in fitSelected")
pyfalog.critical(e)
@@ -812,6 +814,8 @@ class FittingView(d.Display):
if self and not self.IsShown():
try:
self.MakeSnapshot()
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.critical("Failed to make snapshot")
pyfalog.critical(e)
@@ -837,6 +841,8 @@ class FittingView(d.Display):
sFit = Fit.getInstance()
try:
fit = sFit.getFit(self.activeFitID)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.critical("Failed to get fit")
pyfalog.critical(e)

View File

@@ -309,7 +309,7 @@ class ItemView(d.Display):
self.clearSearch()
return
sMkt.searchItems(search, self.populateSearch, ["Implant"])
sMkt.searchItems(search, self.populateSearch, 'implants')
def populateSearch(self, items):
if not self.IsShown():

View File

@@ -475,6 +475,8 @@ class SkillTreeView(wx.Panel):
if skill:
skill.setLevel(level, ignoreRestrict=True)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.error(e)
with wx.MessageDialog(self, "There was an error importing skills, please see log file", "Error", wx.ICON_ERROR) as dlg:
@@ -839,7 +841,7 @@ class APIView(wx.Panel):
def getActiveCharacter(self):
selection = self.charChoice.GetCurrentSelection()
return self.charChoice.GetClientData(selection) if selection is not -1 else None
return self.charChoice.GetClientData(selection) if selection != -1 else None
def ssoListChanged(self, event):
if not self: # todo: fix event not unbinding properly

View File

@@ -122,7 +122,7 @@ class CharacterSelection(wx.Panel):
def getActiveCharacter(self):
selection = self.charChoice.GetCurrentSelection()
return self.charChoice.GetClientData(selection) if selection is not -1 else None
return self.charChoice.GetClientData(selection) if selection != -1 else None
def refreshCharacterList(self, event=None):
choice = self.charChoice

View File

@@ -1138,6 +1138,8 @@ class _TabsContainer(wx.Panel):
self.preview_tab = tab
self.preview_timer.Start(500, True)
break
except (KeyboardInterrupt, SystemExit):
raise
except:
pass

View File

@@ -125,6 +125,8 @@ class EveFittings(AuxiliaryFrame):
# Can't do this in a finally because then it obscures the message dialog
del waitDialog # noqa: F821
ESIExceptionHandler(self, ex)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
del waitDialog # noqa: F821
raise ex
@@ -302,6 +304,8 @@ class ExportToEve(AuxiliaryFrame):
except APIException as ex:
try:
ESIExceptionHandler(self, ex)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
self.statusbar.SetStatusText("ERROR", 0)
self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1)
@@ -381,6 +385,8 @@ class SsoCharacterMgmt(AuxiliaryFrame):
try:
sEsi = Esi.getInstance()
sEsi.login()
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
ESIServerExceptionHandler(self, ex)
@@ -457,6 +463,8 @@ class FittingsTreeView(wx.Panel):
cargo = Cargo(getItem(item['type_id']))
cargo.amount = item['quantity']
list.append(cargo)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.critical("Exception caught in displayFit")
pyfalog.critical(e)

View File

@@ -99,12 +99,14 @@ class PFPanel(wx.Panel):
class OpenFitsThread(threading.Thread):
def __init__(self, fits, callback):
threading.Thread.__init__(self)
self.name = "LoadingOpenFits"
self.mainFrame = MainFrame.getInstance()
self.callback = callback
self.fits = fits
self.running = True
self.start()
def run(self):
@@ -118,10 +120,15 @@ class OpenFitsThread(threading.Thread):
# We use 1 for all fits except the last one where we use 2 so that we
# have correct calculations displayed at startup
for fitID in self.fits[:-1]:
wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID, startup=1))
if self.running:
wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID, startup=1))
wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[-1], startup=2))
wx.CallAfter(self.callback)
if self.running:
wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fits[-1], startup=2))
wx.CallAfter(self.callback)
def stop(self):
self.running = False
# todo: include IPortUser again
@@ -251,10 +258,12 @@ class MainFrame(wx.Frame):
fit = sFit.getFit(id, basic=True)
if fit is None:
fits.remove(id)
except (KeyboardInterrupt, SystemExit):
raise
except:
fits.remove(id)
if not self.prevOpenFits['enabled'] or len(fits) is 0:
if not self.prevOpenFits['enabled'] or len(fits) == 0:
# add blank page if there are no fits to be loaded
self.fitMultiSwitch.AddPage()
return
@@ -747,9 +756,12 @@ class MainFrame(wx.Frame):
activeFit = self.getActiveFit()
try:
importType, importData = Port().importFitFromBuffer(clipboard, activeFit)
if importType == "MutatedItem":
# we've imported an Abyssal module, need to fire off the command to add it to the fit
self.command.Submit(cmd.GuiImportLocalMutatedModuleCommand(activeFit, *importData[0]))
if importType == "FittingItem":
baseItem, mutaplasmidItem, mutations = importData[0]
if mutaplasmidItem:
self.command.Submit(cmd.GuiImportLocalMutatedModuleCommand(activeFit, baseItem, mutaplasmidItem, mutations))
else:
self.command.Submit(cmd.GuiAddLocalModuleCommand(activeFit, baseItem.ID))
return
if importType == "AdditionsDrones":
if self.command.Submit(cmd.GuiImportLocalDronesCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
@@ -771,6 +783,8 @@ class MainFrame(wx.Frame):
if self.command.Submit(cmd.GuiImportCargosCommand(activeFit, [(i.ID, a) for i, a in importData[0]])):
self.additionsPane.select("Cargo")
return
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.error("Attempt to import failed:\n{0}", clipboard)
else:

View File

@@ -265,6 +265,8 @@ class DmgPatternEditor(AuxiliaryFrame):
except ImportError as e:
pyfalog.error(e)
self.stNotice.SetLabel(str(e))
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
msg = "Could not import from clipboard: unknown errors"
pyfalog.warning(msg)

View File

@@ -168,10 +168,7 @@ class ItemView(d.Display):
def __init__(self, parent):
d.Display.__init__(self, parent)
sMkt = Market.getInstance()
self.things = sMkt.getItemsWithOverrides()
self.items = self.things
self.activeItems = []
self.searchBox = parent.Parent.Parent.searchBox
# Bind search actions
@@ -180,20 +177,16 @@ class ItemView(d.Display):
self.searchBox.Bind(SBox.EVT_CANCEL_BTN, self.clearSearch)
self.searchBox.Bind(SBox.EVT_TEXT, self.scheduleSearch)
self.update(self.items)
self.update(Market.getInstance().getItemsWithOverrides())
def clearSearch(self, event=None):
if event:
self.searchBox.Clear()
self.items = self.things
self.update(self.items)
self.update(Market.getInstance().getItemsWithOverrides())
def updateItems(self, updateDisplay=False):
sMkt = Market.getInstance()
self.things = sMkt.getItemsWithOverrides()
self.items = self.things
if updateDisplay:
self.update(self.things)
self.update(Market.getInstance().getItemsWithOverrides())
def scheduleSearch(self, event=None):
sMkt = Market.getInstance()
@@ -206,12 +199,40 @@ class ItemView(d.Display):
self.clearSearch()
return
sMkt.searchItems(search, self.populateSearch, False)
sMkt.searchItems(search, self.populateSearch, 'everything')
def itemSort(self, item):
sMkt = Market.getInstance()
isFittable = item.group.name in sMkt.FIT_GROUPS or item.category.name in sMkt.FIT_CATEGORIES
catname = sMkt.getCategoryByItem(item).name
try:
mktgrpid = sMkt.getMarketGroupByItem(item).ID
except AttributeError:
mktgrpid = -1
pyfalog.warning("unable to find market group for {}".format(item.name))
parentname = sMkt.getParentItemByItem(item).name
# Get position of market group
metagrpid = sMkt.getMetaGroupIdByItem(item)
metatab = sMkt.META_MAP_REVERSE_INDICES.get(metagrpid)
metalvl = item.metaLevel or 0
return not isFittable, catname, mktgrpid, parentname, metatab, metalvl, item.name
def populateSearch(self, items):
self.items = list(items)
self.update(items)
def populate(self, items):
if len(items) > 0:
self.unselectAll()
items.sort(key=self.itemSort)
self.activeItems = items
d.Display.populate(self, items)
def refresh(self, items):
if len(items) > 1:
items.sort(key=self.itemSort)
d.Display.refresh(self, items)
class AttributeGrid(wxpg.PropertyGrid):
def __init__(self, parent):
@@ -236,7 +257,7 @@ class AttributeGrid(wxpg.PropertyGrid):
self.Clear()
self.btn.Enable(True)
sel = event.EventObject.GetFirstSelected()
self.item = item = self.itemView.items[sel]
self.item = item = self.itemView.activeItems[sel]
for key in sorted(item.attributes.keys()):
override = item.overrides.get(key, None)

View File

@@ -211,6 +211,8 @@ class ImplantSetEditor(AuxiliaryFrame):
except ImportError as e:
pyfalog.error(e)
self.stNotice.SetLabel(str(e))
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.error(e)
self.stNotice.SetLabel("Could not import from clipboard: unknown errors")

View File

@@ -352,6 +352,8 @@ class TargetProfileEditor(AuxiliaryFrame):
except ImportError as e:
pyfalog.error(e)
self.stNotice.SetLabel(str(e))
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
msg = "Could not import from clipboard:"
pyfalog.warning(msg)

View File

@@ -70,6 +70,8 @@ class exportHtmlThread(threading.Thread):
except IOError as ex:
pyfalog.warning("Failed to write to " + settings.getPath())
pass
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
pass
@@ -226,6 +228,8 @@ class exportHtmlThread(threading.Thread):
HTMLfit += ' </ul>\n </li>\n'
HTMLship += HTMLfit
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.warning("Failed to export line")
continue
@@ -281,6 +285,8 @@ class exportHtmlThread(threading.Thread):
HTML += '<a class="outOfGameBrowserLink" target="_blank" href="' + dnaUrl + dnaFit + '">' \
+ ship.name + ': ' + \
fit[1] + '</a><br> \n'
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.error("Failed to export line")
continue

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 957 B

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1018 B

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 879 B

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 587 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 B

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 B

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 B

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 935 B

After

Width:  |  Height:  |  Size: 2.1 KiB

16
pyfa.py
View File

@@ -140,6 +140,7 @@ if __name__ == "__main__":
options.title = "pyfa %s - Python Fitting Assistant" % (config.getVersion())
pyfa = wx.App(False)
pyfa.ResetLocale()
mf = MainFrame(options.title)
ErrorHandler.SetParent(mf)
@@ -151,5 +152,18 @@ if __name__ == "__main__":
else:
pyfa.MainLoop()
# TODO: Add some thread cleanup code here. Right now we bail, and that can lead to orphaned threads or threads not properly exiting.
# When main loop is over, threads have 5 seconds to comply...
import threading
from utils.timer import CountdownTimer
timer = CountdownTimer(5)
stoppableThreads = []
for t in threading.enumerate():
if t is not threading.main_thread() and hasattr(t, 'stop'):
stoppableThreads.append(t)
t.stop()
for t in stoppableThreads:
t.join(timeout=timer.remainder())
# Nah, just kidding, no way to terminate threads - just try to exit
sys.exit()

View File

@@ -31,7 +31,6 @@ if os_name == 'Windows':
added_files.extend([
('dist_assets/win/pyfa.ico', '.'),
('dist_assets/win/pyfa.exe.manifest', '.'),
('dist_assets/win/Microsoft.VC90.CRT.manifest', '.')
])
icon = 'dist_assets/win/pyfa.ico'

View File

@@ -1,13 +1,12 @@
wxPython == 4.0.7.post2
logbook >= 1.0.0
matplotlib == 3.0.3
numpy==1.16.4
matplotlib >= 3.1.2
python-dateutil
requests >= 2.0.0
sqlalchemy >= 1.3.0
cryptography >= 2.3
markdown2 == 2.3.5
packaging == 16.8
roman == 2.0.0
beautifulsoup4 == 4.6.0
markdown2 >= 2.3.5
packaging >= 16.8
roman >= 2.0.0
beautifulsoup4 >= 4.6.0
pyyaml >= 5.1

View File

@@ -7,255 +7,28 @@ import sqlite3
import sys
# Add eos root path to sys.path so we can import ourselves
path = os.path.dirname(str(__file__, sys.getfilesystemencoding()))
path = os.path.dirname(__file__)
sys.path.append(os.path.realpath(os.path.join(path, "..")))
# change to correct conversion
rename_phrase = " is now known as "
conversion_phrase = " is being converted to "
rename_phrase = " renamed to "
conversion_phrase = " converted to "
text = """Partial Weapon Navigation is being converted to Phased Scoped Target Painter
Indirect Scanning Dampening Unit I is being converted to Phased Muon Scoped Sensor Dampener
'Broker' Remote Sensor Dampener I is being converted to 'Executive' Remote Sensor Dampener
Initiated Ion Field ECM I is being converted to Hypnos Scoped Magnetometric ECM
FZ-3 Subversive Spatial Destabilizer ECM is being converted to BZ-5 Scoped Gravimetric ECM
'Penumbra' White Noise ECM is being converted to Umbra Scoped Radar ECM
Faint Phase Inversion ECM I is being converted to Enfeebling Scoped Ladar ECM
'Hypnos' Multispectral ECM I is being converted to Compulsive Scoped Multispectral ECM
1Z-3 Subversive ECM Eruption is being converted to Cetus Scoped Burst Jammer
'Prayer' Remote Tracking Computer is being converted to P-S Compact Remote Tracking Computer
'Tycoon' Remote Tracking Computer is being converted to 'Enterprise' Remote Tracking Computer
Monopulse Tracking Mechanism I is being converted to F-12 Enduring Tracking Computer
'Orion' Tracking CPU I is being converted to Optical Compact Tracking Computer
'Economist' Tracking Computer I is being converted to 'Marketeer' Tracking Computer
Beta-Nought Tracking Mode is being converted to 'Basic' Tracking Enhancer
Azimuth Descalloping Tracking Enhancer is being converted to 'Basic' Tracking Enhancer
F-AQ Delay-Line Scan Tracking Subroutines is being converted to 'Basic' Tracking Enhancer
Beam Parallax Tracking Program is being converted to 'Basic' Tracking Enhancer
Sigma-Nought Tracking Mode I is being converted to Fourier Compact Tracking Enhancer
Auto-Gain Control Tracking Enhancer I is being converted to Fourier Compact Tracking Enhancer
F-aQ Phase Code Tracking Subroutines is being converted to Fourier Compact Tracking Enhancer
Lateral Gyrostabilizer is being converted to 'Basic' Gyrostabilizer
F-M2 Weapon Inertial Suspensor is being converted to 'Basic' Gyrostabilizer
Hydraulic Stabilization Actuator is being converted to 'Basic' Gyrostabilizer
Stabilized Weapon Mounts is being converted to 'Basic' Gyrostabilizer
Cross-Lateral Gyrostabilizer I is being converted to Counterbalanced Compact Gyrostabilizer
F-M3 Munition Inertial Suspensor is being converted to Counterbalanced Compact Gyrostabilizer
Pneumatic Stabilization Actuator I is being converted to Counterbalanced Compact Gyrostabilizer
Monophonic Stabilization Actuator I is being converted to 'Kindred' Gyrostabilizer
Monophonic Stabilization Actuator I Blueprint is being converted to 'Kindred' Gyrostabilizer Blueprint
Heat Exhaust System is being converted to 'Basic' Heat Sink
C3S Convection Thermal Radiator is being converted to 'Basic' Heat Sink
'Boreas' Coolant System is being converted to 'Basic' Heat Sink
Stamped Heat Sink is being converted to 'Basic' Heat Sink
Thermal Exhaust System I is being converted to Extruded Compact Heat Sink
C4S Coiled Circuit Thermal Radiator is being converted to Extruded Compact Heat Sink
'Skadi' Coolant System I is being converted to Extruded Compact Heat Sink
'Mangonel' Heat Sink I is being converted to 'Trebuchet' Heat Sink I
'Mangonel' Heat Sink I Blueprint is being converted to 'Trebuchet' Heat Sink Blueprint
Insulated Stabilizer Array is being converted to 'Basic' Magnetic Field Stabilizer
Linear Flux Stabilizer is being converted to 'Basic' Magnetic Field Stabilizer
Gauss Field Balancer is being converted to 'Basic' Magnetic Field Stabilizer
Magnetic Vortex Stabilizer is being converted to 'Basic' Magnetic Field Stabilizer
Insulated Stabilizer Array I is being converted to Vortex Compact Magnetic Field Stabilizer
Linear Flux Stabilizer I is being converted to Vortex Compact Magnetic Field Stabilizer
Gauss Field Balancer I is being converted to Vortex Compact Magnetic Field Stabilizer
'Capitalist' Magnetic Field Stabilizer I is being converted to 'Monopoly' Magnetic Field Stabilizer
'Capitalist' Magnetic Field Stabilizer I Blueprint is being converted to 'Monopoly' Magnetic Field Stabilizer Blueprint
Muon Coil Bolt Array I is being converted to Crosslink Compact Ballistic Control System
Multiphasic Bolt Array I is being converted to Crosslink Compact Ballistic Control System
'Pandemonium' Ballistic Enhancement is being converted to Crosslink Compact Ballistic Control System
Ballistic 'Purge' Targeting System I is being converted to 'Full Duplex' Ballistic Control System
Ballistic 'Purge' Targeting System I Blueprint is being converted to 'Full Duplex' Ballistic Control System Blueprint
'Langour' Drive Disruptor I is being converted to X5 Enduring Stasis Webifier
Patterned Stasis Web I is being converted to Fleeting Compact Stasis Webifier
Fleeting Progressive Warp Scrambler I is being converted to Faint Epsilon Scoped Warp Scrambler
Fleeting Warp Disruptor I is being converted to Faint Scoped Warp Disruptor
GLFF Containment Field is being converted to 'Basic' Damage Control
Interior Force Field Array is being converted to 'Basic' Damage Control
F84 Local Damage System is being converted to 'Basic' Damage Control
Systematic Damage Control is being converted to 'Basic' Damage Control
'Gonzo' Damage Control I is being converted to 'Radical' Damage Control
'Gonzo' Damage Control I Blueprint is being converted to 'Radical' Damage Control Blueprint
Emergency Damage Control I is being converted to IFFA Compact Damage Control
F85 Peripheral Damage System I is being converted to IFFA Compact Damage Control
Pseudoelectron Containment Field I is being converted to IFFA Compact Damage Control
Micro Ld-Acid Capacitor Battery I is being converted to 'Micro' Cap Battery
Micro Ohm Capacitor Reserve I is being converted to 'Micro' Cap Battery
Micro F-4a Ld-Sulfate Capacitor Charge Unit is being converted to 'Micro' Cap Battery
Micro Peroxide Capacitor Power Cell is being converted to 'Micro' Cap Battery
Micro Capacitor Battery II is being converted to 'Micro' Cap Battery
Small Ohm Capacitor Reserve I is being converted to Small Compact Pb-Acid Cap Battery
Small F-4a Ld-Sulfate Capacitor Charge Unit is being converted to Small Compact Pb-Acid Cap Battery
Small Peroxide Capacitor Power Cell is being converted to Small Compact Pb-Acid Cap Battery
Medium Ohm Capacitor Reserve I is being converted to Medium Compact Pb-Acid Cap Battery
Medium F-4a Ld-Sulfate Capacitor Charge Unit is being converted to Medium Compact Pb-Acid Cap Battery
Medium Peroxide Capacitor Power Cell is being converted to Medium Compact Pb-Acid Cap Battery
Large Ohm Capacitor Reserve I is being converted to Large Compact Pb-Acid Cap Battery
Large F-4a Ld-Sulfate Capacitor Charge Unit is being converted to Large Compact Pb-Acid Cap Battery
Large Peroxide Capacitor Power Cell is being converted to Large Compact Pb-Acid Cap Battery
ECCM - Radar I is being converted to Sensor Booster I
ECCM - Ladar I is being converted to Sensor Booster I
ECCM - Magnetometric I is being converted to Sensor Booster I
ECCM - Gravimetric I is being converted to Sensor Booster I
ECCM - Omni I is being converted to Sensor Booster I
ECCM - Radar I Blueprint is being converted to Sensor Booster I Blueprint
ECCM - Ladar I Blueprint is being converted to Sensor Booster I Blueprint
ECCM - Magnetometric I Blueprint is being converted to Sensor Booster I Blueprint
ECCM - Gravimetric I Blueprint is being converted to Sensor Booster I Blueprint
ECCM - Omni I Blueprint is being converted to Sensor Booster I Blueprint
Alumel Radar ECCM Sensor Array I is being converted to Alumel-Wired Enduring Sensor Booster
Alumel Ladar ECCM Sensor Array I is being converted to Alumel-Wired Enduring Sensor Booster
Alumel Gravimetric ECCM Sensor Array I is being converted to Alumel-Wired Enduring Sensor Booster
Alumel Omni ECCM Sensor Array I is being converted to Alumel-Wired Enduring Sensor Booster
Alumel Magnetometric ECCM Sensor Array I is being converted to Alumel-Wired Enduring Sensor Booster
Supplemental Ladar ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Supplemental Gravimetric ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Supplemental Omni ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Supplemental Radar ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Supplemental Magnetometric ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Extra Radar ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
Extra Ladar ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
Extra Gravimetric ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
Extra Magnetometric ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
Gravimetric Positional ECCM Sensor System I is being converted to F-90 Compact Sensor Booster
Radar Positional ECCM Sensor System I is being converted to F-90 Compact Sensor Booster
Omni Positional ECCM Sensor System I is being converted to F-90 Compact Sensor Booster
Ladar Positional ECCM Sensor System I is being converted to F-90 Compact Sensor Booster
Magnetometric Positional ECCM Sensor System I is being converted to F-90 Compact Sensor Booster
Incremental Radar ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Incremental Ladar ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Incremental Gravimetric ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Incremental Magnetometric ECCM Scanning Array I is being converted to Alumel-Wired Enduring Sensor Booster
Prototype ECCM Radar Sensor Cluster is being converted to Alumel-Wired Enduring Sensor Booster
Prototype ECCM Ladar Sensor Cluster is being converted to Alumel-Wired Enduring Sensor Booster
Prototype ECCM Gravimetric Sensor Cluster is being converted to Alumel-Wired Enduring Sensor Booster
Prototype ECCM Omni Sensor Cluster is being converted to Alumel-Wired Enduring Sensor Booster
Prototype ECCM Magnetometric Sensor Cluster is being converted to Alumel-Wired Enduring Sensor Booster
Conjunctive Radar ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
Conjunctive Ladar ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
Conjunctive Gravimetric ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
Conjunctive Magnetometric ECCM Scanning Array I is being converted to F-90 Compact Sensor Booster
ECCM - Omni II is being converted to Sensor Booster II
ECCM - Gravimetric II is being converted to Sensor Booster II
ECCM - Ladar II is being converted to Sensor Booster II
ECCM - Magnetometric II is being converted to Sensor Booster II
ECCM - Radar II is being converted to Sensor Booster II
ECCM - Omni II Blueprint is being converted to Sensor Booster II Blueprint
ECCM - Gravimetric II Blueprint is being converted to Sensor Booster II Blueprint
ECCM - Ladar II Blueprint is being converted to Sensor Booster II Blueprint
ECCM - Magnetometric II Blueprint is being converted to Sensor Booster II Blueprint
ECCM - Radar II Blueprint is being converted to Sensor Booster II Blueprint
'Forger' ECCM - Magnetometric I is being converted to 'Shady' Sensor Booster
'Forger' ECCM - Magnetometric I Blueprint is being converted to 'Shady' Sensor Booster Blueprint
Basic RADAR Backup Array is being converted to 'Basic' Signal Amplifier
Basic Ladar Backup Array is being converted to 'Basic' Signal Amplifier
Basic Gravimetric Backup Array is being converted to 'Basic' Signal Amplifier
Basic Magnetometric Backup Array is being converted to 'Basic' Signal Amplifier
Basic Multi Sensor Backup Array is being converted to 'Basic' Signal Amplifier
Emergency Magnetometric Scanners is being converted to 'Basic' Signal Amplifier
Emergency Multi-Frequency Scanners is being converted to 'Basic' Signal Amplifier
Emergency RADAR Scanners is being converted to 'Basic' Signal Amplifier
Emergency Ladar Scanners is being converted to 'Basic' Signal Amplifier
Emergency Gravimetric Scanners is being converted to 'Basic' Signal Amplifier
Sealed RADAR Backup Cluster is being converted to 'Basic' Signal Amplifier
Sealed Magnetometric Backup Cluster is being converted to 'Basic' Signal Amplifier
Sealed Multi-Frequency Backup Cluster is being converted to 'Basic' Signal Amplifier
Sealed Ladar Backup Cluster is being converted to 'Basic' Signal Amplifier
Sealed Gravimetric Backup Cluster is being converted to 'Basic' Signal Amplifier
Surplus RADAR Reserve Array is being converted to 'Basic' Signal Amplifier
F-42 Reiterative RADAR Backup Sensors is being converted to 'Basic' Signal Amplifier
Surplus Magnetometric Reserve Array is being converted to 'Basic' Signal Amplifier
F-42 Reiterative Magnetometric Backup Sensors is being converted to 'Basic' Signal Amplifier
Surplus Multi-Frequency Reserve Array is being converted to 'Basic' Signal Amplifier
F-42 Reiterative Multi-Frequency Backup Sensors is being converted to 'Basic' Signal Amplifier
Surplus Ladar Reserve Array is being converted to 'Basic' Signal Amplifier
F-42 Reiterative Ladar Backup Sensors is being converted to 'Basic' Signal Amplifier
Surplus Gravimetric Reserve Array is being converted to 'Basic' Signal Amplifier
F-42 Reiterative Gravimetric Backup Sensors is being converted to 'Basic' Signal Amplifier
Gravimetric Backup Array I is being converted to Signal Amplifier I
Ladar Backup Array I is being converted to Signal Amplifier I
Magnetometric Backup Array I is being converted to Signal Amplifier I
Multi Sensor Backup Array I is being converted to Signal Amplifier I
RADAR Backup Array I is being converted to Signal Amplifier I
Gravimetric Backup Array I Blueprint is being converted to Signal Amplifier I Blueprint
Ladar Backup Array I Blueprint is being converted to Signal Amplifier I Blueprint
Magnetometric Backup Array I Blueprint is being converted to Signal Amplifier I Blueprint
Multi Sensor Backup Array I Blueprint is being converted to Signal Amplifier I Blueprint
RADAR Backup Array I Blueprint is being converted to Signal Amplifier I Blueprint
Protected Gravimetric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Protected Ladar Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Protected Magnetometric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Protected Multi-Frequency Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Protected RADAR Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Reserve Gravimetric Scanners is being converted to F-89 Compact Signal Amplifier
Reserve Ladar Scanners is being converted to F-89 Compact Signal Amplifier
Reserve Magnetometric Scanners is being converted to F-89 Compact Signal Amplifier
Reserve Multi-Frequency Scanners is being converted to F-89 Compact Signal Amplifier
Reserve RADAR Scanners is being converted to F-89 Compact Signal Amplifier
Secure Gravimetric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Secure Ladar Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Secure Magnetometric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Secure Radar Backup Cluster I is being converted to F-89 Compact Signal Amplifier
F-43 Repetitive Gravimetric Backup Sensors is being converted to F-89 Compact Signal Amplifier
F-43 Repetitive Ladar Backup Sensors is being converted to F-89 Compact Signal Amplifier
F-43 Repetitive Magnetometric Backup Sensors is being converted to F-89 Compact Signal Amplifier
F-43 Repetitive Multi-Frequency Backup Sensors is being converted to F-89 Compact Signal Amplifier
F-43 Repetitive RADAR Backup Sensors is being converted to F-89 Compact Signal Amplifier
Shielded Gravimetric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Shielded Ladar Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Shielded Magnetometric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Shielded Radar Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Surrogate Gravimetric Reserve Array I is being converted to F-89 Compact Signal Amplifier
Surrogate Ladar Reserve Array I is being converted to F-89 Compact Signal Amplifier
Surrogate Magnetometric Reserve Array I is being converted to F-89 Compact Signal Amplifier
Surrogate Multi-Frequency Reserve Array I is being converted to F-89 Compact Signal Amplifier
Surrogate RADAR Reserve Array I is being converted to F-89 Compact Signal Amplifier
Warded Gravimetric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Warded Ladar Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Warded Magnetometric Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Warded Radar Backup Cluster I is being converted to F-89 Compact Signal Amplifier
Gravimetric Backup Array II is being converted to Signal Amplifier II
Ladar Backup Array II is being converted to Signal Amplifier II
Magnetometric Backup Array II is being converted to Signal Amplifier II
Multi Sensor Backup Array II is being converted to Signal Amplifier II
RADAR Backup Array II is being converted to Signal Amplifier II
Gravimetric Backup Array II Blueprint is being converted to Signal Amplifier II Blueprint
Ladar Backup Array II Blueprint is being converted to Signal Amplifier II Blueprint
Magnetometric Backup Array II Blueprint is being converted to Signal Amplifier II Blueprint
Multi Sensor Backup Array II Blueprint is being converted to Signal Amplifier II Blueprint
RADAR Backup Array II Blueprint is being converted to Signal Amplifier II Blueprint
Gravimetric Firewall is being converted to 'Firewall' Signal Amplifier
Ladar Firewall is being converted to 'Firewall' Signal Amplifier
Magnetometric Firewall is being converted to 'Firewall' Signal Amplifier
Multi Sensor Firewall is being converted to 'Firewall' Signal Amplifier
RADAR Firewall is being converted to 'Firewall' Signal Amplifier
ECCM Projector I is being converted to Remote Sensor Booster I
ECCM Projector I Blueprint is being converted to Remote Sensor Booster I Blueprint
Scattering ECCM Projector I is being converted to Linked Enduring Sensor Booster
Piercing ECCM Emitter I is being converted to Coadjunct Scoped Remote Sensor Booster
Spot Pulsing ECCM I is being converted to F-23 Compact Remote Sensor Booster
Phased Muon ECCM Caster I is being converted to F-23 Compact Remote Sensor Booster
ECCM Projector II is being converted to Remote Sensor Booster II
ECCM Projector II Blueprint is being converted to Remote Sensor Booster II Blueprint
Prototype Sensor Booster is being converted to Alumel-Wired Enduring Sensor Booster
Supplemental Scanning CPU I is being converted to F-90 Compact Sensor Booster
Amplitude Signal Enhancer is being converted to 'Basic' Signal Amplifier
'Acolyth' Signal Booster is being converted to 'Basic' Signal Amplifier
Type-E Discriminative Signal Augmentation is being converted to 'Basic' Signal Amplifier
F-90 Positional Signal Amplifier is being converted to 'Basic' Signal Amplifier
'Mendicant' Signal Booster I is being converted to F-89 Compact Signal Amplifier
Wavelength Signal Enhancer I is being converted to F-89 Compact Signal Amplifier
Type-D Attenuation Signal Augmentation is being converted to F-89 Compact Signal Amplifier
Connected Remote Sensor Booster is being converted to F-23 Compact Remote Sensor Booster
'Boss' Remote Sensor Booster is being converted to 'Bootleg' Remote Sensor Booster
'Entrepreneur' Remote Sensor Booster is being converted to 'Bootleg' Remote Sensor Booster
'Pacifier' Large Remote Armor Repairer is being converted to 'Peace' Large Remote Armor Repairer
'Pacifier' Large Remote Armor Repairer Blueprint is being converted to 'Peace' Large Remote Armor Repairer Blueprint
'Broker' Remote Sensor Dampener I Blueprint is being converted to 'Executive' Remote Sensor Dampener Blueprint
'Tycoon' Remote Tracking Computer Blueprint is being converted to 'Enterprise' Remote Tracking Computer Blueprint
'Economist' Tracking Computer I Blueprint is being converted to 'Marketeer' Tracking Computer Blueprint"""
text = """
Small Asymmetric Remote Capacitor Transmitter renamed to Small Radiative Scoped Remote Capacitor Transmitter
Small 'Regard' Remote Capacitor Transmitter renamed to Small Inductive Compact Remote Capacitor Transmitter
Medium Asymmetric Remote Capacitor Transmitter renamed to Medium Radiative Scoped Remote Capacitor Transmitter
Medium 'Regard' Remote Capacitor Transmitter renamed to Medium Inductive Compact Remote Capacitor Transmitter
Large Asymmetric Remote Capacitor Transmitter renamed to Large Radiative Scoped Remote Capacitor Transmitter
Large 'Regard' Remote Capacitor Transmitter renamed to Large Inductive Compact Remote Capacitor Transmitter
Small Partial E95a Remote Capacitor Transmitter converted to Small Radiative Scoped Remote Capacitor Transmitter
Small Murky Remote Capacitor Transmitter converted to Small Inductive Compact Remote Capacitor Transmitter
Medium Partial E95b Remote Capacitor Transmitter converted to Medium Radiative Scoped Remote Capacitor Transmitter
Medium Murky Remote Capacitor Transmitter converted to Medium Inductive Compact Remote Capacitor Transmitter
Large Partial E95c Remote Capacitor Transmitter converted to Large Radiative Scoped Remote Capacitor Transmitter
Large Murky Remote Capacitor Transmitter converted to Large Inductive Compact Remote Capacitor Transmitter
"""
def main(old, new):
# Open both databases and get their cursors
@@ -268,6 +41,9 @@ def main(old, new):
conversions = {}
for x in text.splitlines():
x = x.strip()
if not x:
continue
if conversion_phrase in x:
c = x.split(conversion_phrase)
container = conversions

View File

@@ -119,7 +119,7 @@ def calc_outerscore(innerscore_dict, pereffect_totalaffected, weight):
def validate_string(s):
try:
s.encode('ascii')
except KeyboardInterrupt:
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
return False

View File

@@ -394,6 +394,8 @@ def main(old, new, groups=True, effects=True, attributes=True, renames=True):
new_cursor.execute(query)
for row in new_cursor:
new_meta[row[0]] = row[1]
except (KeyboardInterrupt, SystemExit):
raise
except:
pass
# Print jobs

View File

@@ -1,11 +1,14 @@
#!/usr/bin/env bash
echo "Pyfa version (ENV):"
echo "${PYFA_VERSION}"
echo "Pyfa version (YAML):"
cat version.yml
echo "Building distributive..."
python3 -m PyInstaller -y --clean --windowed dist_assets/mac/pyfa.spec
echo "Compressing distributive..."
cd dist
zip -r "pyfa-$PYFA_VERSION-mac.zip" pyfa.app
echo "Uploading distributive to transfer.sh..."
curl --connect-timeout 30 --max-time 300 --upload-file "pyfa-$PYFA_VERSION-mac.zip" https://transfer.sh/ || echo 'upload to transfer.sh failed'
echo -e "\n"
md5 -r "pyfa-$PYFA_VERSION-mac.zip"

View File

@@ -1,8 +1,9 @@
#!/usr/bin/env bash
wget "https://www.python.org/ftp/python/${PYTHON}/python-${PYTHON}-macosx10.6.pkg"
sudo installer -pkg python-${PYTHON}-macosx10.6.pkg -target /
sudo python3 -m ensurepip --upgrade
# A manual check that the correct version of Python is running.
echo "Python version:"
python3 --version
echo "Upgrading pip..."
python3 -m pip install --upgrade pip
echo "Installing app requirements..."
python3 -m pip install -r requirements.txt
python3 -m pip install PyInstaller==3.3
echo "Installing packaging tools..."
python3 -m pip install PyInstaller==3.6

File diff suppressed because it is too large Load Diff

View File

@@ -1,89 +0,0 @@
Electronic Subsystem Technology,Core Subsystem Technology
Amarr Electronic Systems,Amarr Core Systems
Gallente Electronic Systems,Gallente Core Systems
Caldari Electronic Systems,Caldari Core Systems
Minmatar Electronic Systems,Minmatar Core Systems
Datacore - Electronic Subsystems Engineering,Datacore - Core Subsystems Engineering
Malfunctioning Electromechanical Component,Malfunctioning Power Cores
Wrecked Electromechanical Component,Wrecked Power Cores
Intact Electromechanical Component,Intact Power Cores
Legion Electronics - Energy Parasitic Complex,Legion Core - Energy Parasitic Complex
Legion Electronics - Tactical Targeting Network,Legion Core - Dissolution Sequencer
Legion Electronics - Dissolution Sequencer,Legion Core - Dissolution Sequencer
Legion Electronics - Emergent Locus Analyzer,Legion Core - Dissolution Sequencer
Tengu Electronics - Obfuscation Manifold,Tengu Core - Obfuscation Manifold
Tengu Electronics - CPU Efficiency Gate,Tengu Core - Electronic Efficiency Gate
Tengu Electronics - Dissolution Sequencer,Tengu Core - Electronic Efficiency Gate
Tengu Electronics - Emergent Locus Analyzer,Tengu Core - Electronic Efficiency Gate
Proteus Electronics - Friction Extension Processor,Proteus Core - Friction Extension Processor
Proteus Electronics - CPU Efficiency Gate,Proteus Core - Electronic Efficiency Gate
Proteus Electronics - Dissolution Sequencer,Proteus Core - Electronic Efficiency Gate
Proteus Electronics - Emergent Locus Analyzer,Proteus Core - Electronic Efficiency Gate
Loki Electronics - Immobility Drivers,Loki Core - Immobility Drivers
Loki Electronics - Tactical Targeting Network,Loki Core - Dissolution Sequencer
Loki Electronics - Dissolution Sequencer,Loki Core - Dissolution Sequencer
Loki Electronics - Emergent Locus Analyzer,Loki Core - Dissolution Sequencer
Tengu Engineering - Power Core Multiplier,Tengu Core - Augmented Graviton Reactor
Tengu Engineering - Augmented Capacitor Reservoir,Tengu Core - Augmented Graviton Reactor
Tengu Engineering - Capacitor Regeneration Matrix,Tengu Core - Augmented Graviton Reactor
Tengu Engineering - Supplemental Coolant Injector,Tengu Core - Obfuscation Manifold
Proteus Engineering - Power Core Multiplier,Proteus Core - Augmented Fusion Reactor
Proteus Engineering - Augmented Capacitor Reservoir,Proteus Core - Augmented Fusion Reactor
Proteus Engineering - Capacitor Regeneration Matrix,Proteus Core - Augmented Fusion Reactor
Proteus Engineering - Supplemental Coolant Injector,Proteus Core - Friction Extension Processor
Loki Engineering - Power Core Multiplier,Loki Core - Augmented Nuclear Reactor
Loki Engineering - Augmented Capacitor Reservoir,Loki Core - Augmented Nuclear Reactor
Loki Engineering - Capacitor Regeneration Matrix,Loki Core - Augmented Nuclear Reactor
Loki Engineering - Supplemental Coolant Injector,Loki Core - Immobility Drivers
Legion Engineering - Power Core Multiplier,Legion Core - Augmented Antimatter Reactor
Legion Engineering - Augmented Capacitor Reservoir,Legion Core - Augmented Antimatter Reactor
Legion Engineering - Capacitor Regeneration Matrix,Legion Core - Augmented Antimatter Reactor
Legion Engineering - Supplemental Coolant Injector,Legion Core - Energy Parasitic Complex
Legion Propulsion - Chassis Optimization,Legion Propulsion - Intercalated Nanofibers
Legion Propulsion - Fuel Catalyst,Legion Propulsion - Wake Limiter
Legion Propulsion - Wake Limiter,Legion Propulsion - Wake Limiter
Legion Propulsion - Interdiction Nullifier,Legion Propulsion - Interdiction Nullifier
Tengu Propulsion - Intercalated Nanofibers,Tengu Propulsion - Chassis Optimization
Tengu Propulsion - Gravitational Capacitor,Tengu Propulsion - Chassis Optimization
Tengu Propulsion - Fuel Catalyst,Tengu Propulsion - Fuel Catalyst
Tengu Propulsion - Interdiction Nullifier,Tengu Propulsion - Interdiction Nullifier
Proteus Propulsion - Wake Limiter,Proteus Propulsion - Localized Injectors
Proteus Propulsion - Localized Injectors,Proteus Propulsion - Localized Injectors
Proteus Propulsion - Gravitational Capacitor,Proteus Propulsion - Hyperspatial Optimization
Proteus Propulsion - Interdiction Nullifier,Proteus Propulsion - Interdiction Nullifier
Loki Propulsion - Chassis Optimization,Loki Propulsion - Intercalated Nanofibers
Loki Propulsion - Intercalated Nanofibers,Loki Propulsion - Intercalated Nanofibers
Loki Propulsion - Fuel Catalyst,Loki Propulsion - Wake Limiter
Loki Propulsion - Interdiction Nullifier,Loki Propulsion - Interdiction Nullifier
Legion Defensive - Adaptive Augmenter,Legion Defensive - Augmented Plating
Legion Defensive - Nanobot Injector,Legion Defensive - Nanobot Injector
Legion Defensive - Augmented Plating,Legion Defensive - Augmented Plating
Legion Defensive - Warfare Processor,Legion Defensive - Augmented Plating
Tengu Defensive - Adaptive Shielding,Tengu Defensive - Supplemental Screening
Tengu Defensive - Amplification Node,Tengu Defensive - Amplification Node
Tengu Defensive - Supplemental Screening,Tengu Defensive - Supplemental Screening
Tengu Defensive - Warfare Processor,Tengu Defensive - Supplemental Screening
Loki Defensive - Adaptive Shielding,Loki Defensive - Augmented Durability
Loki Defensive - Adaptive Augmenter,Loki Defensive - Augmented Durability
Loki Defensive - Amplification Node,Loki Defensive - Adaptive Defense Node
Loki Defensive - Warfare Processor,Loki Defensive - Augmented Durability
Proteus Defensive - Adaptive Augmenter,Proteus Defensive - Augmented Plating
Proteus Defensive - Nanobot Injector,Proteus Defensive - Nanobot Injector
Proteus Defensive - Augmented Plating,Proteus Defensive - Augmented Plating
Proteus Defensive - Warfare Processor,Proteus Defensive - Augmented Plating
Legion Offensive - Drone Synthesis Projector,Legion Offensive - Assault Optimization
Legion Offensive - Assault Optimization,Legion Offensive - Assault Optimization
Legion Offensive - Liquid Crystal Magnifiers,Legion Offensive - Liquid Crystal Magnifiers
Legion Offensive - Covert Reconfiguration,Legion Offensive - Liquid Crystal Magnifiers
Tengu Offensive - Accelerated Ejection Bay,Tengu Offensive - Accelerated Ejection Bay
Tengu Offensive - Rifling Launcher Pattern,Tengu Offensive - Accelerated Ejection Bay
Tengu Offensive - Magnetic Infusion Basin,Tengu Offensive - Magnetic Infusion Basin
Tengu Offensive - Covert Reconfiguration,Tengu Offensive - Accelerated Ejection Bay
Proteus Offensive - Dissonic Encoding Platform,Proteus Offensive - Hybrid Encoding Platform
Proteus Offensive - Hybrid Propulsion Armature,Proteus Offensive - Hybrid Encoding Platform
Proteus Offensive - Drone Synthesis Projector,Proteus Offensive - Drone Synthesis Projector
Proteus Offensive - Covert Reconfiguration,Proteus Offensive - Hybrid Encoding Platform
Loki Offensive - Turret Concurrence Registry,Loki Offensive - Projectile Scoping Array
Loki Offensive - Projectile Scoping Array,Loki Offensive - Projectile Scoping Array
Loki Offensive - Hardpoint Efficiency Configuration,Loki Offensive - Launcher Efficiency Configuration
Loki Offensive - Covert Reconfiguration,Loki Offensive - Projectile Scoping Array
1 Electronic Subsystem Technology Core Subsystem Technology
2 Amarr Electronic Systems Amarr Core Systems
3 Gallente Electronic Systems Gallente Core Systems
4 Caldari Electronic Systems Caldari Core Systems
5 Minmatar Electronic Systems Minmatar Core Systems
6 Datacore - Electronic Subsystems Engineering Datacore - Core Subsystems Engineering
7 Malfunctioning Electromechanical Component Malfunctioning Power Cores
8 Wrecked Electromechanical Component Wrecked Power Cores
9 Intact Electromechanical Component Intact Power Cores
10 Legion Electronics - Energy Parasitic Complex Legion Core - Energy Parasitic Complex
11 Legion Electronics - Tactical Targeting Network Legion Core - Dissolution Sequencer
12 Legion Electronics - Dissolution Sequencer Legion Core - Dissolution Sequencer
13 Legion Electronics - Emergent Locus Analyzer Legion Core - Dissolution Sequencer
14 Tengu Electronics - Obfuscation Manifold Tengu Core - Obfuscation Manifold
15 Tengu Electronics - CPU Efficiency Gate Tengu Core - Electronic Efficiency Gate
16 Tengu Electronics - Dissolution Sequencer Tengu Core - Electronic Efficiency Gate
17 Tengu Electronics - Emergent Locus Analyzer Tengu Core - Electronic Efficiency Gate
18 Proteus Electronics - Friction Extension Processor Proteus Core - Friction Extension Processor
19 Proteus Electronics - CPU Efficiency Gate Proteus Core - Electronic Efficiency Gate
20 Proteus Electronics - Dissolution Sequencer Proteus Core - Electronic Efficiency Gate
21 Proteus Electronics - Emergent Locus Analyzer Proteus Core - Electronic Efficiency Gate
22 Loki Electronics - Immobility Drivers Loki Core - Immobility Drivers
23 Loki Electronics - Tactical Targeting Network Loki Core - Dissolution Sequencer
24 Loki Electronics - Dissolution Sequencer Loki Core - Dissolution Sequencer
25 Loki Electronics - Emergent Locus Analyzer Loki Core - Dissolution Sequencer
26 Tengu Engineering - Power Core Multiplier Tengu Core - Augmented Graviton Reactor
27 Tengu Engineering - Augmented Capacitor Reservoir Tengu Core - Augmented Graviton Reactor
28 Tengu Engineering - Capacitor Regeneration Matrix Tengu Core - Augmented Graviton Reactor
29 Tengu Engineering - Supplemental Coolant Injector Tengu Core - Obfuscation Manifold
30 Proteus Engineering - Power Core Multiplier Proteus Core - Augmented Fusion Reactor
31 Proteus Engineering - Augmented Capacitor Reservoir Proteus Core - Augmented Fusion Reactor
32 Proteus Engineering - Capacitor Regeneration Matrix Proteus Core - Augmented Fusion Reactor
33 Proteus Engineering - Supplemental Coolant Injector Proteus Core - Friction Extension Processor
34 Loki Engineering - Power Core Multiplier Loki Core - Augmented Nuclear Reactor
35 Loki Engineering - Augmented Capacitor Reservoir Loki Core - Augmented Nuclear Reactor
36 Loki Engineering - Capacitor Regeneration Matrix Loki Core - Augmented Nuclear Reactor
37 Loki Engineering - Supplemental Coolant Injector Loki Core - Immobility Drivers
38 Legion Engineering - Power Core Multiplier Legion Core - Augmented Antimatter Reactor
39 Legion Engineering - Augmented Capacitor Reservoir Legion Core - Augmented Antimatter Reactor
40 Legion Engineering - Capacitor Regeneration Matrix Legion Core - Augmented Antimatter Reactor
41 Legion Engineering - Supplemental Coolant Injector Legion Core - Energy Parasitic Complex
42 Legion Propulsion - Chassis Optimization Legion Propulsion - Intercalated Nanofibers
43 Legion Propulsion - Fuel Catalyst Legion Propulsion - Wake Limiter
44 Legion Propulsion - Wake Limiter Legion Propulsion - Wake Limiter
45 Legion Propulsion - Interdiction Nullifier Legion Propulsion - Interdiction Nullifier
46 Tengu Propulsion - Intercalated Nanofibers Tengu Propulsion - Chassis Optimization
47 Tengu Propulsion - Gravitational Capacitor Tengu Propulsion - Chassis Optimization
48 Tengu Propulsion - Fuel Catalyst Tengu Propulsion - Fuel Catalyst
49 Tengu Propulsion - Interdiction Nullifier Tengu Propulsion - Interdiction Nullifier
50 Proteus Propulsion - Wake Limiter Proteus Propulsion - Localized Injectors
51 Proteus Propulsion - Localized Injectors Proteus Propulsion - Localized Injectors
52 Proteus Propulsion - Gravitational Capacitor Proteus Propulsion - Hyperspatial Optimization
53 Proteus Propulsion - Interdiction Nullifier Proteus Propulsion - Interdiction Nullifier
54 Loki Propulsion - Chassis Optimization Loki Propulsion - Intercalated Nanofibers
55 Loki Propulsion - Intercalated Nanofibers Loki Propulsion - Intercalated Nanofibers
56 Loki Propulsion - Fuel Catalyst Loki Propulsion - Wake Limiter
57 Loki Propulsion - Interdiction Nullifier Loki Propulsion - Interdiction Nullifier
58 Legion Defensive - Adaptive Augmenter Legion Defensive - Augmented Plating
59 Legion Defensive - Nanobot Injector Legion Defensive - Nanobot Injector
60 Legion Defensive - Augmented Plating Legion Defensive - Augmented Plating
61 Legion Defensive - Warfare Processor Legion Defensive - Augmented Plating
62 Tengu Defensive - Adaptive Shielding Tengu Defensive - Supplemental Screening
63 Tengu Defensive - Amplification Node Tengu Defensive - Amplification Node
64 Tengu Defensive - Supplemental Screening Tengu Defensive - Supplemental Screening
65 Tengu Defensive - Warfare Processor Tengu Defensive - Supplemental Screening
66 Loki Defensive - Adaptive Shielding Loki Defensive - Augmented Durability
67 Loki Defensive - Adaptive Augmenter Loki Defensive - Augmented Durability
68 Loki Defensive - Amplification Node Loki Defensive - Adaptive Defense Node
69 Loki Defensive - Warfare Processor Loki Defensive - Augmented Durability
70 Proteus Defensive - Adaptive Augmenter Proteus Defensive - Augmented Plating
71 Proteus Defensive - Nanobot Injector Proteus Defensive - Nanobot Injector
72 Proteus Defensive - Augmented Plating Proteus Defensive - Augmented Plating
73 Proteus Defensive - Warfare Processor Proteus Defensive - Augmented Plating
74 Legion Offensive - Drone Synthesis Projector Legion Offensive - Assault Optimization
75 Legion Offensive - Assault Optimization Legion Offensive - Assault Optimization
76 Legion Offensive - Liquid Crystal Magnifiers Legion Offensive - Liquid Crystal Magnifiers
77 Legion Offensive - Covert Reconfiguration Legion Offensive - Liquid Crystal Magnifiers
78 Tengu Offensive - Accelerated Ejection Bay Tengu Offensive - Accelerated Ejection Bay
79 Tengu Offensive - Rifling Launcher Pattern Tengu Offensive - Accelerated Ejection Bay
80 Tengu Offensive - Magnetic Infusion Basin Tengu Offensive - Magnetic Infusion Basin
81 Tengu Offensive - Covert Reconfiguration Tengu Offensive - Accelerated Ejection Bay
82 Proteus Offensive - Dissonic Encoding Platform Proteus Offensive - Hybrid Encoding Platform
83 Proteus Offensive - Hybrid Propulsion Armature Proteus Offensive - Hybrid Encoding Platform
84 Proteus Offensive - Drone Synthesis Projector Proteus Offensive - Drone Synthesis Projector
85 Proteus Offensive - Covert Reconfiguration Proteus Offensive - Hybrid Encoding Platform
86 Loki Offensive - Turret Concurrence Registry Loki Offensive - Projectile Scoping Array
87 Loki Offensive - Projectile Scoping Array Loki Offensive - Projectile Scoping Array
88 Loki Offensive - Hardpoint Efficiency Configuration Loki Offensive - Launcher Efficiency Configuration
89 Loki Offensive - Covert Reconfiguration Loki Offensive - Projectile Scoping Array

View File

@@ -1,48 +0,0 @@
# Prints out a fucking large python dictionary for use with the t3c conversion migration.\
# Requires eve-old.db file (which is the previous releases database so that we can lookup the old items)
# See https://community.eveonline.com/news/patch-notes/patch-notes-for-july-2017-release
import csv
import sys
from os.path import abspath, dirname, join, realpath
from sqlalchemy import create_engine
newDB = create_engine('sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "eve.db")), sys.getfilesystemencoding()))
oldDB = create_engine('sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "eve-old.db")), sys.getfilesystemencoding()))
oldItemMapping = {}
newItemMapping = {}
with open('t3conversionSheet.csv', 'r') as f:
reader = csv.reader(f)
print "conversion = {"
for row in reader:
fromList = []
toList = []
for x in xrange(1, 6):
try:
if (row[0], row[x]) not in oldItemMapping:
item = oldDB.execute("SELECT * FROM invtypes WHERE typeName LIKE ?", ("{}%{}".format(row[0], row[x]),)).first()
oldItemMapping[(row[0], row[x])] = item['typeID']
fromList.append(str(oldItemMapping[(row[0], row[x])]))
except:
pass
for x in xrange(6, 10):
if row[x] not in newItemMapping:
item = newDB.execute("SELECT * FROM invtypes WHERE typeName = ?",
(row[x],)).first()
newItemMapping[row[x]] = item['typeID']
toList.append(str(newItemMapping[row[x]]))
print "\tfrozenset([{}]): ({}),".format(','.join(fromList), ','.join(toList))
print "}"
with open('t3conversionSheetLoose.csv', 'r') as f:
reader = csv.reader(f)
print "conversion2 = {"
for row in reader:
oldItem = oldDB.execute("SELECT typeID FROM invtypes WHERE typeName = ?", (row[0],)).scalar()
newItem = newDB.execute("SELECT typeID FROM invtypes WHERE typeName = ?", (row[1],)).scalar()
print "\t{}: {},".format(oldItem, newItem)
print "}"

Binary file not shown.

View File

@@ -45,11 +45,13 @@ pyfalog = Logger(__name__)
class CharacterImportThread(threading.Thread):
def __init__(self, paths, callback):
threading.Thread.__init__(self)
self.name = "CharacterImport"
self.paths = paths
self.callback = callback
self.running = True
def run(self):
paths = self.paths
@@ -61,6 +63,8 @@ class CharacterImportThread(threading.Thread):
all_skill_ids.append(skill.itemID)
for path in paths:
if not self.running:
break
try:
charFile = open(path, mode='r').read()
doc = minidom.parseString(charFile)
@@ -86,6 +90,8 @@ class CharacterImportThread(threading.Thread):
)
char = sCharacter.new(name + " (EVEMon)")
sCharacter.apiUpdateCharSheet(char.ID, skills, securitystatus)
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.error("Exception on character import:")
pyfalog.error(e)
@@ -93,6 +99,9 @@ class CharacterImportThread(threading.Thread):
wx.CallAfter(self.callback)
def stop(self):
self.running = False
class SkillBackupThread(threading.Thread):
def __init__(self, path, saveFmt, activeFit, callback):
@@ -102,25 +111,32 @@ class SkillBackupThread(threading.Thread):
self.saveFmt = saveFmt
self.activeFit = activeFit
self.callback = callback
self.running = True
def run(self):
path = self.path
sCharacter = Character.getInstance()
if self.saveFmt == "xml" or self.saveFmt == "emp":
backupData = sCharacter.exportXml()
else:
backupData = sCharacter.exportText()
backupData = None
if self.running:
if self.saveFmt == "xml" or self.saveFmt == "emp":
backupData = sCharacter.exportXml()
else:
backupData = sCharacter.exportText()
if self.saveFmt == "emp":
with gzip.open(path, mode='wb') as backupFile:
backupFile.write(backupData.encode())
else:
with open(path, mode='w', encoding='utf-8') as backupFile:
backupFile.write(backupData)
if self.running and backupData is not None:
if self.saveFmt == "emp":
with gzip.open(path, mode='wb') as backupFile:
backupFile.write(backupData.encode())
else:
with open(path, mode='w', encoding='utf-8') as backupFile:
backupFile.write(backupData)
wx.CallAfter(self.callback)
def stop(self):
self.running = False
class Character:
instance = None
@@ -151,6 +167,8 @@ class Character:
data += "Skills required for {}:\n".format(item)
data += "{}{}: {}\n".format(" " * s["indent"], s["skill"], int(s["level"]))
data += "-" * 79 + "\n"
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
pass
@@ -470,12 +488,14 @@ class Character:
class UpdateAPIThread(threading.Thread):
def __init__(self, charID, callback):
threading.Thread.__init__(self)
self.name = "CheckUpdate"
self.callback = callback
self.charID = charID
self.running = True
def run(self):
try:
@@ -484,18 +504,31 @@ class UpdateAPIThread(threading.Thread):
sEsi = Esi.getInstance()
sChar = Character.getInstance()
ssoChar = sChar.getSsoCharacter(char.ID)
if not self.running:
self.callback[0](self.callback[1])
return
resp = sEsi.getSkills(ssoChar.ID)
if not self.running:
self.callback[0](self.callback[1])
return
# todo: check if alpha. if so, pop up a question if they want to apply it as alpha. Use threading events to set the answer?
char.clearSkills()
for skillRow in resp["skills"]:
char.addSkill(Skill(char, skillRow["skill_id"], skillRow["trained_skill_level"]))
if not self.running:
self.callback[0](self.callback[1])
return
resp = sEsi.getSecStatus(ssoChar.ID)
char.secStatus = resp['security_status']
self.callback[0](self.callback[1])
except (KeyboardInterrupt, SystemExit):
raise
except Exception as ex:
pyfalog.warn(ex)
self.callback[0](self.callback[1], sys.exc_info())
def stop(self):
self.running = False

View File

@@ -0,0 +1,20 @@
"""
Conversion pack for February 2020 release
"""
CONVERSIONS = {
# Renamed items
"Small Asymmetric Remote Capacitor Transmitter": "Small Radiative Scoped Remote Capacitor Transmitter",
"Small 'Regard' Remote Capacitor Transmitter": "Small Inductive Compact Remote Capacitor Transmitter",
"Medium Asymmetric Remote Capacitor Transmitter": "Medium Radiative Scoped Remote Capacitor Transmitter",
"Medium 'Regard' Remote Capacitor Transmitter": "Medium Inductive Compact Remote Capacitor Transmitter",
"Large Asymmetric Remote Capacitor Transmitter": "Large Radiative Scoped Remote Capacitor Transmitter",
"Large 'Regard' Remote Capacitor Transmitter": "Large Inductive Compact Remote Capacitor Transmitter",
# Converted items
"Small Partial E95a Remote Capacitor Transmitter": "Small Radiative Scoped Remote Capacitor Transmitter",
"Small Murky Remote Capacitor Transmitter": "Small Inductive Compact Remote Capacitor Transmitter",
"Medium Partial E95b Remote Capacitor Transmitter": "Medium Radiative Scoped Remote Capacitor Transmitter",
"Medium Murky Remote Capacitor Transmitter": "Medium Inductive Compact Remote Capacitor Transmitter",
"Large Partial E95c Remote Capacitor Transmitter": "Large Radiative Scoped Remote Capacitor Transmitter",
"Large Murky Remote Capacitor Transmitter": "Large Inductive Compact Remote Capacitor Transmitter"
}

View File

@@ -110,6 +110,8 @@ class ImplantSets:
else:
item = sMkt.getItem(line)
current.implants.append(es_Implant(item))
except (KeyboardInterrupt, SystemExit):
raise
except:
errors += 1
continue

View File

@@ -46,6 +46,7 @@ class ShipBrowserWorkerThread(threading.Thread):
threading.Thread.__init__(self)
pyfalog.debug("Initialize ShipBrowserWorkerThread.")
self.name = "ShipBrowser"
self.running = True
def run(self):
self.queue = queue.Queue()
@@ -60,6 +61,8 @@ class ShipBrowserWorkerThread(threading.Thread):
cache = self.cache
sMkt = Market.getInstance()
while True:
if not self.running:
break
try:
id_, callback = queue.get()
set_ = cache.get(id_)
@@ -68,16 +71,23 @@ class ShipBrowserWorkerThread(threading.Thread):
cache[id_] = set_
wx.CallAfter(callback, (id_, set_))
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.critical("Callback failed.")
pyfalog.critical(e)
finally:
try:
queue.task_done()
except (KeyboardInterrupt, SystemExit):
raise
except Exception as e:
pyfalog.critical("Queue task done failed.")
pyfalog.critical(e)
def stop(self):
self.running = False
class SearchWorkerThread(threading.Thread):
def __init__(self):
@@ -87,6 +97,7 @@ class SearchWorkerThread(threading.Thread):
# load the jargon while in an out-of-thread context, to spot any problems while in the main thread
self.jargonLoader.get_jargon()
self.jargonLoader.get_jargon().apply('test string')
self.running = True
def run(self):
self.cv = threading.Condition()
@@ -97,49 +108,70 @@ class SearchWorkerThread(threading.Thread):
cv = self.cv
while True:
if not self.running:
break
cv.acquire()
while self.searchRequest is None:
cv.wait()
request, callback, filterOn = self.searchRequest
request, callback, filterName = self.searchRequest
self.searchRequest = None
cv.release()
sMkt = Market.getInstance()
if filterOn is True:
if filterName == 'market':
# Rely on category data provided by eos as we don't hardcode them much in service
filter_ = or_(types_Category.name.in_(sMkt.SEARCH_CATEGORIES), types_Group.name.in_(sMkt.SEARCH_GROUPS))
elif filterOn: # filter by selected categories
filter_ = types_Category.name.in_(filterOn)
filters = [or_(
types_Category.name.in_(sMkt.SEARCH_CATEGORIES),
types_Group.name.in_(sMkt.SEARCH_GROUPS))]
# Used in implant editor
elif filterName == 'implants':
filters = [types_Category.name == 'Implant']
# Actually not everything, just market search + ships
elif filterName == 'everything':
filters = [
or_(
types_Category.name.in_(sMkt.FIT_CATEGORIES),
types_Group.name.in_(sMkt.FIT_GROUPS)),
or_(
types_Category.name.in_(sMkt.SEARCH_CATEGORIES),
types_Group.name.in_(sMkt.SEARCH_GROUPS))]
else:
filter_ = None
filters = [None]
jargon_request = self.jargonLoader.get_jargon().apply(request)
results = []
all_results = set()
if len(request) >= config.minItemSearchLength:
results = eos.db.searchItems(request, where=filter_,
join=(types_Item.group, types_Group.category),
eager=("group.category", "metaGroup"))
for filter_ in filters:
regular_results = eos.db.searchItems(
request, where=filter_,
join=(types_Item.group, types_Group.category),
eager=("group.category", "metaGroup"))
all_results.update(regular_results)
jargon_results = []
if len(jargon_request) >= config.minItemSearchLength:
jargon_results = eos.db.searchItems(jargon_request, where=filter_,
join=(types_Item.group, types_Group.category),
eager=("group.category", "metaGroup"))
for filter_ in filters:
jargon_results = eos.db.searchItems(
jargon_request, where=filter_,
join=(types_Item.group, types_Group.category),
eager=("group.category", "metaGroup"))
all_results.update(jargon_results)
items = set()
# Return only published items, consult with Market service this time
for item in [*results, *jargon_results]:
for item in all_results:
if sMkt.getPublicityByItem(item):
items.add(item)
wx.CallAfter(callback, items)
wx.CallAfter(callback, list(items))
def scheduleSearch(self, text, callback, filterOn=True):
def scheduleSearch(self, text, callback, filterName=None):
self.cv.acquire()
self.searchRequest = (text, callback, filterOn)
self.searchRequest = (text, callback, filterName)
self.cv.notify()
self.cv.release()
def stop(self):
self.running = False
class Market:
instance = None
@@ -313,6 +345,7 @@ class Market:
self.META_MAP["normal"] = frozenset((0, *(mg.ID for mg in eos.db.getMetaGroups() if mg.ID not in nonNormalMetas)))
self.META_MAP.move_to_end("normal", last=False)
self.META_MAP_REVERSE = {sv: k for k, v in self.META_MAP.items() for sv in v}
self.META_MAP_REVERSE_INDICES = self.__makeReverseMetaMapIndices()
self.SEARCH_CATEGORIES = (
"Drone",
"Module",
@@ -336,6 +369,8 @@ class Market:
2203 # Structure Modifications
)
self.SHOWN_MARKET_GROUPS = eos.db.getMarketTreeNodeIds(self.ROOT_MARKET_GROUPS)
self.FIT_CATEGORIES = ['Ship']
self.FIT_GROUPS = ['Citadel', 'Engineering Complex', 'Refinery']
# Tell other threads that Market is at their service
mktRdy.set()
@@ -355,6 +390,15 @@ class Market:
rev[value].add(item)
return rev
def __makeReverseMetaMapIndices(self):
revmap = {}
i = 0
for mgids in self.META_MAP.values():
for mgid in mgids:
revmap[mgid] = i
i += 1
return revmap
@staticmethod
def getItem(identity, *args, **kwargs):
"""Get item by its ID or name"""
@@ -374,6 +418,8 @@ class Market:
item = eos.db.getItem(id_, *args, **kwargs)
else:
raise TypeError("Need Item object, integer, float or string as argument")
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.error("Could not get item: {0}", identity)
raise
@@ -748,9 +794,9 @@ class Market:
ships.add(item)
return ships
def searchItems(self, name, callback, filterOn=True):
def searchItems(self, name, callback, filterName=None):
"""Find items according to given text pattern"""
self.searchWorkerThread.scheduleSearch(name, callback, filterOn)
self.searchWorkerThread.scheduleSearch(name, callback, filterName)
@staticmethod
def getItemsWithOverrides():

View File

@@ -92,6 +92,8 @@ class Network:
raise Error(error)
except requests.exceptions.Timeout:
raise TimeoutError()
except (KeyboardInterrupt, SystemExit):
raise
except Exception as error:
raise Error(error)
@@ -117,6 +119,8 @@ class Network:
raise Error(error)
except requests.exceptions.Timeout:
raise TimeoutError()
except (KeyboardInterrupt, SystemExit):
raise
except Exception as error:
raise Error(error)

View File

@@ -59,6 +59,8 @@ def importDna(string, fitName=None):
Citadel(sMkt.getItem(id_))
string = string[string.index(str(id_)):]
break
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.warning("Exception caught in importDna")
pass
@@ -107,6 +109,8 @@ def importDna(string, fitName=None):
for i in range(int(amount)):
try:
m = Module(item)
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.warning("Exception caught in importDna")
continue

View File

@@ -269,6 +269,8 @@ class EfsPort:
else:
modTypeIDSets[mod.slot].append(0)
moduleNameSets[mod.slot].append("Empty Slot")
except (KeyboardInterrupt, SystemExit):
raise
except:
pyfalog.error("Could not find name for module {0}".format(vars(mod)))

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