1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-13 15:57:14 +03:00

Running EDMarketConnector.py 'works'.

First pass utilising 'futurize' to do most of the work.

  There's an issue with ur'\"' in l10n.py which I'm not sure how to
properly fix.

  This now has errors when hitting the 'Update' button.
This commit is contained in:
Athanasius 2019-09-10 17:14:49 +01:00
parent a8631e5bb8
commit d0ae621387
13 changed files with 145 additions and 110 deletions

View File

@ -1,6 +1,11 @@
#!/usr/bin/env python2
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import object
import sys
from sys import platform
from collections import OrderedDict
@ -26,11 +31,11 @@ if getattr(sys, 'frozen', False):
if 'TCL_LIBRARY' in environ:
environ.pop('TCL_LIBRARY')
import Tkinter as tk
import ttk
import tkFileDialog
import tkFont
import tkMessageBox
import tkinter as tk
import tkinter.ttk
import tkinter.filedialog
import tkinter.font
import tkinter.messagebox
from ttkHyperlinkLabel import HyperlinkLabel
if __debug__:
@ -58,7 +63,7 @@ from theme import theme
SERVER_RETRY = 5 # retry pause for Companion servers [s]
class AppWindow:
class AppWindow(object):
# Tkinter Event types
EVENT_KEYPRESS = 2
@ -125,7 +130,7 @@ class AppWindow:
else:
appitem.grid(columnspan=2, sticky=tk.EW)
self.button = ttk.Button(frame, text=_('Update'), width=28, default=tk.ACTIVE, state=tk.DISABLED) # Update button in main window
self.button = tkinter.ttk.Button(frame, text=_('Update'), width=28, default=tk.ACTIVE, state=tk.DISABLED) # Update button in main window
self.theme_button = tk.Label(frame, width = platform == 'darwin' and 32 or 28, state=tk.DISABLED)
self.status = tk.Label(frame, name='status', anchor=tk.W)
@ -377,10 +382,10 @@ class AppWindow:
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Status
self.file_menu.entryconfigure(1, state=tk.NORMAL) # Save Raw Data
except (companion.CredentialsError, companion.ServerError, companion.ServerLagging) as e:
self.status['text'] = unicode(e)
self.status['text'] = str(e)
except Exception as e:
if __debug__: print_exc()
self.status['text'] = unicode(e)
self.status['text'] = str(e)
self.cooldown()
def getandsend(self, event=None, retrying=False):
@ -479,7 +484,7 @@ class AppWindow:
# Companion API problem
except companion.ServerLagging as e:
if retrying:
self.status['text'] = unicode(e)
self.status['text'] = str(e)
play_bad = True
else:
# Retry once if Companion server is unresponsive
@ -487,14 +492,14 @@ class AppWindow:
return # early exit to avoid starting cooldown count
except companion.CmdrError as e: # Companion API return doesn't match Journal
self.status['text'] = unicode(e)
self.status['text'] = str(e)
play_bad = True
companion.session.invalidate()
self.login()
except Exception as e: # Including CredentialsError, ServerError
if __debug__: print_exc()
self.status['text'] = unicode(e)
self.status['text'] = str(e)
play_bad = True
if not self.status['text']: # no errors
@ -509,7 +514,7 @@ class AppWindow:
try:
data = companion.session.station()
if __debug__:
print 'Retry for shipyard - ' + (data['commander'].get('docked') and (data.get('lastStarport', {}).get('ships') and 'Success' or 'Failure') or 'Undocked!')
print('Retry for shipyard - ' + (data['commander'].get('docked') and (data.get('lastStarport', {}).get('ships') and 'Success' or 'Failure') or 'Undocked!'))
if not data['commander'].get('docked'):
pass # might have undocked while we were waiting for retry in which case station data is unreliable
elif (data.get('lastSystem', {}).get('name') == monitor.system and
@ -576,7 +581,7 @@ class AppWindow:
if entry['event'] in ['StartUp', 'LoadGame'] and monitor.started:
# Can start dashboard monitoring
if not dashboard.start(self.w, monitor.started):
print "Can't start Status monitoring"
print("Can't start Status monitoring")
# Export loadout
if entry['event'] == 'Loadout' and not monitor.state['Captain'] and config.getint('output') & config.OUT_SHIP:
@ -605,10 +610,10 @@ class AppWindow:
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Status
self.file_menu.entryconfigure(1, state=tk.NORMAL) # Save Raw Data
except companion.ServerError as e:
self.status['text'] = unicode(e)
self.status['text'] = str(e)
except Exception as e:
if __debug__: print_exc()
self.status['text'] = unicode(e)
self.status['text'] = str(e)
self.cooldown()
# Handle Status event
@ -676,7 +681,7 @@ class AppWindow:
try:
data = companion.session.station()
self.status['text'] = ''
f = tkFileDialog.asksaveasfilename(parent = self.w,
f = tkinter.filedialog.asksaveasfilename(parent = self.w,
defaultextension = platform=='darwin' and '.json' or '',
filetypes = [('JSON', '.json'), ('All Files', '*')],
initialdir = config.get('outdir'),
@ -688,7 +693,7 @@ class AppWindow:
self.status['text'] = str(e)
except Exception as e:
if __debug__: print_exc()
self.status['text'] = unicode(e)
self.status['text'] = str(e)
def onexit(self, event=None):
if platform!='darwin' or self.w.winfo_rooty()>0: # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
@ -796,7 +801,7 @@ if __name__ == "__main__":
# By default py2exe tries to write log to dirname(sys.executable) which fails when installed
import tempfile
sys.stdout = sys.stderr = open(join(tempfile.gettempdir(), '%s.log' % appname), 'wt', 0) # unbuffered
print '%s %s %s' % (applongname, appversion, strftime('%Y-%m-%dT%H:%M:%S', localtime()))
print('%s %s %s' % (applongname, appversion, strftime('%Y-%m-%dT%H:%M:%S', localtime())))
Translations.install(config.get('language') or None) # Can generate errors so wait til log set up

View File

@ -1,7 +1,13 @@
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import range
from builtins import object
import base64
import csv
import requests
from cookielib import LWPCookieJar # No longer needed but retained in case plugins use it
from http.cookiejar import LWPCookieJar # No longer needed but retained in case plugins use it
from email.utils import parsedate
import hashlib
import json
@ -11,7 +17,7 @@ from os.path import dirname, isfile, join
import sys
import time
from traceback import print_exc
import urlparse
import urllib.parse
import webbrowser
import zlib
@ -104,7 +110,7 @@ def listify(thing):
return list(thing) # array is not sparse
elif isinstance(thing, dict):
retval = []
for k,v in thing.iteritems():
for k,v in thing.items():
idx = int(k)
if idx >= len(retval):
retval.extend([None] * (idx - len(retval)))
@ -121,36 +127,36 @@ class ServerError(Exception):
def __unicode__(self):
return _('Error: Frontier server is down') # Raised when cannot contact the Companion API server
def __str__(self):
return unicode(self).encode('utf-8')
return str(self).encode('utf-8')
class ServerLagging(Exception):
def __unicode__(self):
return _('Error: Frontier server is lagging') # Raised when Companion API server is returning old data, e.g. when the servers are too busy
def __str__(self):
return unicode(self).encode('utf-8')
return str(self).encode('utf-8')
class SKUError(Exception):
def __unicode__(self):
return _('Error: Frontier server SKU problem') # Raised when the Companion API server thinks that the user has not purchased E:D. i.e. doesn't have the correct 'SKU'
def __str__(self):
return unicode(self).encode('utf-8')
return str(self).encode('utf-8')
class CredentialsError(Exception):
def __init__(self, message=None):
self.message = message and unicode(message) or _('Error: Invalid Credentials')
self.message = message and str(message) or _('Error: Invalid Credentials')
def __unicode__(self):
return self.message
def __str__(self):
return unicode(self).encode('utf-8')
return str(self).encode('utf-8')
class CmdrError(Exception):
def __unicode__(self):
return _('Error: Wrong Cmdr') # Raised when the user has multiple accounts and the username/password setting is not for the account they're currently playing OR the user has reset their Cmdr and the Companion API server is still returning data for the old Cmdr
def __str__(self):
return unicode(self).encode('utf-8')
return str(self).encode('utf-8')
class Auth:
class Auth(object):
def __init__(self, cmdr):
self.cmdr = cmdr
@ -180,16 +186,16 @@ class Auth:
config.save() # Save settings now for use by command-line app
return data.get('access_token')
else:
print 'Auth\tCan\'t refresh token for %s' % self.cmdr.encode('utf-8')
print('Auth\tCan\'t refresh token for %s' % self.cmdr.encode('utf-8'))
self.dump(r)
except:
print 'Auth\tCan\'t refresh token for %s' % self.cmdr.encode('utf-8')
print('Auth\tCan\'t refresh token for %s' % self.cmdr.encode('utf-8'))
print_exc()
else:
print 'Auth\tNo token for %s' % self.cmdr.encode('utf-8')
print('Auth\tNo token for %s' % self.cmdr.encode('utf-8'))
# New request
print 'Auth\tNew authorization request'
print('Auth\tNew authorization request')
self.verifier = self.base64URLEncode(os.urandom(32))
self.state = self.base64URLEncode(os.urandom(8))
# Won't work under IE: https://blogs.msdn.microsoft.com/ieinternals/2011/07/13/understanding-protocols/
@ -198,16 +204,16 @@ class Auth:
def authorize(self, payload):
# Handle OAuth authorization code callback. Returns access token if successful, otherwise raises CredentialsError
if not '?' in payload:
print 'Auth\tMalformed response "%s"' % payload.encode('utf-8')
print('Auth\tMalformed response "%s"' % payload.encode('utf-8'))
raise CredentialsError() # Not well formed
data = urlparse.parse_qs(payload[payload.index('?')+1:])
data = urllib.parse.parse_qs(payload[payload.index('?')+1:])
if not self.state or not data.get('state') or data['state'][0] != self.state:
print 'Auth\tUnexpected response "%s"' % payload.encode('utf-8')
print('Auth\tUnexpected response "%s"' % payload.encode('utf-8'))
raise CredentialsError() # Unexpected reply
if not data.get('code'):
print 'Auth\tNegative response "%s"' % payload.encode('utf-8')
print('Auth\tNegative response "%s"' % payload.encode('utf-8'))
if data.get('error_description'):
raise CredentialsError('Error: %s' % data['error_description'][0])
elif data.get('error'):
@ -229,7 +235,7 @@ class Auth:
r = self.session.post(SERVER_AUTH + URL_TOKEN, data=data, timeout=auth_timeout)
data = r.json()
if r.status_code == requests.codes.ok:
print 'Auth\tNew token for %s' % self.cmdr.encode('utf-8')
print('Auth\tNew token for %s' % self.cmdr.encode('utf-8'))
cmdrs = config.get('cmdrs')
idx = cmdrs.index(self.cmdr)
tokens = config.get('fdev_apikeys') or []
@ -239,12 +245,12 @@ class Auth:
config.save() # Save settings now for use by command-line app
return data.get('access_token')
except:
print 'Auth\tCan\'t get token for %s' % self.cmdr.encode('utf-8')
print('Auth\tCan\'t get token for %s' % self.cmdr.encode('utf-8'))
print_exc()
if r: self.dump(r)
raise CredentialsError()
print 'Auth\tCan\'t get token for %s' % self.cmdr.encode('utf-8')
print('Auth\tCan\'t get token for %s' % self.cmdr.encode('utf-8'))
self.dump(r)
if data.get('error_description'):
raise CredentialsError('Error: %s' % data['error_description'])
@ -257,7 +263,7 @@ class Auth:
@staticmethod
def invalidate(cmdr):
print 'Auth\tInvalidated token for %s' % cmdr.encode('utf-8')
print('Auth\tInvalidated token for %s' % cmdr.encode('utf-8'))
cmdrs = config.get('cmdrs')
idx = cmdrs.index(cmdr)
tokens = config.get('fdev_apikeys') or []
@ -267,15 +273,15 @@ class Auth:
config.save() # Save settings now for use by command-line app
def dump(self, r):
print 'Auth\t' + r.url, r.status_code, r.reason and r.reason.decode('utf-8') or 'None', r.text.encode('utf-8')
print('Auth\t' + r.url, r.status_code, r.reason and r.reason.decode('utf-8') or 'None', r.text.encode('utf-8'))
def base64URLEncode(self, text):
return base64.urlsafe_b64encode(text).replace('=', '')
class Session:
class Session(object):
STATE_INIT, STATE_AUTH, STATE_OK = range(3)
STATE_INIT, STATE_AUTH, STATE_OK = list(range(3))
def __init__(self):
self.state = Session.STATE_INIT
@ -429,7 +435,7 @@ class Session:
Auth.invalidate(self.credentials['cmdr'])
def dump(self, r):
print 'cAPI\t' + r.url, r.status_code, r.reason and r.reason.encode('utf-8') or 'None', r.text.encode('utf-8')
print('cAPI\t' + r.url, r.status_code, r.reason and r.reason.encode('utf-8') or 'None', r.text.encode('utf-8'))
# Returns a shallow copy of the received data suitable for export to older tools - English commodity names and anomalies fixed up
@ -451,7 +457,7 @@ def fixup(data):
# But also see https://github.com/Marginal/EDMarketConnector/issues/32
for thing in ['buyPrice', 'sellPrice', 'demand', 'demandBracket', 'stock', 'stockBracket']:
if not isinstance(commodity.get(thing), numbers.Number):
if __debug__: print 'Invalid "%s":"%s" (%s) for "%s"' % (thing, commodity.get(thing), type(commodity.get(thing)), commodity.get('name', ''))
if __debug__: print('Invalid "%s":"%s" (%s) for "%s"' % (thing, commodity.get(thing), type(commodity.get(thing)), commodity.get('name', '')))
break
else:
if not category_map.get(commodity['categoryname'], True): # Check not marketable i.e. Limpets
@ -461,13 +467,13 @@ def fixup(data):
elif commodity.get('legality'): # Check not prohibited
pass
elif not commodity.get('categoryname'):
if __debug__: print 'Missing "categoryname" for "%s"' % commodity.get('name', '')
if __debug__: print('Missing "categoryname" for "%s"' % commodity.get('name', ''))
elif not commodity.get('name'):
if __debug__: print 'Missing "name" for a commodity in "%s"' % commodity.get('categoryname', '')
if __debug__: print('Missing "name" for a commodity in "%s"' % commodity.get('categoryname', ''))
elif not commodity['demandBracket'] in range(4):
if __debug__: print 'Invalid "demandBracket":"%s" for "%s"' % (commodity['demandBracket'], commodity['name'])
if __debug__: print('Invalid "demandBracket":"%s" for "%s"' % (commodity['demandBracket'], commodity['name']))
elif not commodity['stockBracket'] in range(4):
if __debug__: print 'Invalid "stockBracket":"%s" for "%s"' % (commodity['stockBracket'], commodity['name'])
if __debug__: print('Invalid "stockBracket":"%s" for "%s"' % (commodity['stockBracket'], commodity['name']))
else:
# Rewrite text fields
new = dict(commodity) # shallow copy
@ -498,7 +504,7 @@ def ship(data):
def filter_ship(d):
filtered = {}
for k, v in d.iteritems():
for k, v in d.items():
if v == []:
pass # just skip empty fields for brevity
elif k in ['alive', 'cargo', 'cockpitBreached', 'health', 'oxygenRemaining', 'rebuilds', 'starsystem', 'station']:
@ -519,7 +525,7 @@ def ship(data):
# Ship name suitable for writing to a file
def ship_file_name(ship_name, ship_type):
name = unicode(ship_name or ship_map.get(ship_type.lower(), ship_type)).strip()
name = str(ship_name or ship_map.get(ship_type.lower(), ship_type)).strip()
if name.endswith('.'):
name = name[:-1]
if name.lower() in ['con', 'prn', 'aux', 'nul',

View File

@ -1,3 +1,8 @@
from __future__ import division
from builtins import str
from past.builtins import basestring
from builtins import object
from past.utils import old_div
import numbers
import sys
from os import getenv, makedirs, mkdir, pardir
@ -89,7 +94,7 @@ elif platform=='linux2':
from iniparse import RawConfigParser
class Config:
class Config(object):
OUT_MKT_EDDN = 1
# OUT_MKT_BPC = 2 # No longer supported
@ -146,7 +151,7 @@ class Config:
elif hasattr(val, '__iter__'):
return list(val) # make writeable
else:
return unicode(val)
return str(val)
def getint(self, key):
try:
@ -212,7 +217,7 @@ class Config:
if disposition.value == REG_CREATED_NEW_KEY:
buf = ctypes.create_unicode_buffer('1')
RegSetValueEx(sparklekey, 'CheckForUpdates', 0, 1, buf, len(buf)*2)
buf = ctypes.create_unicode_buffer(unicode(update_interval))
buf = ctypes.create_unicode_buffer(str(update_interval))
RegSetValueEx(sparklekey, 'UpdateInterval', 0, 1, buf, len(buf)*2)
RegCloseKey(sparklekey)
@ -224,13 +229,13 @@ class Config:
size = DWORD()
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), None, ctypes.byref(size)) or typ.value not in [REG_SZ, REG_MULTI_SZ]:
return None
buf = ctypes.create_unicode_buffer(size.value / 2)
buf = ctypes.create_unicode_buffer(old_div(size.value, 2))
if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), buf, ctypes.byref(size)):
return None
elif typ.value == REG_MULTI_SZ:
return [x for x in ctypes.wstring_at(buf, len(buf)-2).split(u'\x00')]
else:
return unicode(buf.value)
return str(buf.value)
def getint(self, key):
typ = DWORD()
@ -248,7 +253,7 @@ class Config:
elif isinstance(val, numbers.Integral):
RegSetValueEx(self.hkey, key, 0, REG_DWORD, ctypes.byref(DWORD(val)), 4)
elif hasattr(val, '__iter__'): # iterable
stringval = u'\x00'.join([unicode(x) or u' ' for x in val] + [u'']) # null terminated non-empty strings
stringval = u'\x00'.join([str(x) or u' ' for x in val] + [u'']) # null terminated non-empty strings
buf = ctypes.create_unicode_buffer(stringval)
RegSetValueEx(self.hkey, key, 0, REG_MULTI_SZ, buf, len(buf)*2)
else:
@ -333,14 +338,14 @@ class Config:
def save(self):
with codecs.open(self.filename, 'w', 'utf-8') as h:
h.write(unicode(self.config.data))
h.write(str(self.config.data))
def close(self):
self.save()
self.config = None
def _escape(self, val):
return unicode(val).replace(u'\\', u'\\\\').replace(u'\n', u'\\n').replace(u';', u'\\;')
return str(val).replace(u'\\', u'\\\\').replace(u'\n', u'\\n').replace(u';', u'\\;')
def _unescape(self, val):
chars = list(val)

View File

@ -1,3 +1,6 @@
from __future__ import division
from __future__ import print_function
from past.utils import old_div
import json
from calendar import timegm
from operator import itemgetter
@ -68,18 +71,18 @@ class Dashboard(FileSystemEventHandler):
self.observed = self.observer.schedule(self, self.currentdir)
if __debug__:
print '%s Dashboard "%s"' % (polling and 'Polling' or 'Monitoring', self.currentdir)
print('%s Dashboard "%s"' % (polling and 'Polling' or 'Monitoring', self.currentdir))
# Even if we're not intending to poll, poll at least once to process pre-existing
# data and to check whether the watchdog thread has crashed due to events not
# being supported on this filesystem.
self.root.after(self._POLL * 1000/2, self.poll, True)
self.root.after(old_div(self._POLL * 1000,2), self.poll, True)
return True
def stop(self):
if __debug__:
print 'Stopping monitoring Dashboard'
print('Stopping monitoring Dashboard')
self.currentdir = None
if self.observed:
self.observed = None

35
l10n.py
View File

@ -3,6 +3,11 @@
# Localization with gettext is a pain on non-Unix systems. Use OSX-style strings files instead.
#
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import object
import codecs
from collections import OrderedDict
import numbers
@ -12,14 +17,14 @@ import re
import sys
from sys import platform
from traceback import print_exc
import __builtin__
import builtins
import locale
try:
locale.setlocale(locale.LC_ALL, '')
except:
# Locale env variables incorrect or locale package not installed/configured on Linux, mysterious reasons on Windows
print "Can't set locale!"
print("Can't set locale!")
from config import config
@ -48,7 +53,7 @@ elif platform == 'win32':
GetNumberFormatEx.restype = ctypes.c_int
class Translations:
class Translations(object):
FALLBACK = 'en' # strings in this code are in English
FALLBACK_NAME = 'English'
@ -63,7 +68,7 @@ class Translations:
def install_dummy(self):
# For when translation is not desired or not available
self.translations = { None: {} }
__builtin__.__dict__['_'] = lambda x: unicode(x).replace(ur'\"', u'"').replace(u'{CR}', u'\n') # Promote strings to Unicode for consistency
builtins.__dict__['_'] = lambda x: str(x).replace(r'\"', u'"').replace(u'{CR}', u'\n') # Promote strings to Unicode for consistency
def install(self, lang=None):
available = self.available()
@ -91,11 +96,11 @@ class Translations:
if isdir(plugin_path):
try:
self.translations[plugin] = self.contents(lang, plugin_path)
except UnicodeDecodeError, e:
print 'Malformed file %s.strings in plugin %s: %s' % (lang, plugin, e)
except UnicodeDecodeError as e:
print('Malformed file %s.strings in plugin %s: %s' % (lang, plugin, e))
except:
print_exc()
__builtin__.__dict__['_'] = self.translate
builtins.__dict__['_'] = self.translate
def contents(self, lang, plugin_path=None):
assert lang in self.available()
@ -108,11 +113,11 @@ class Translations:
if line.strip():
match = Translations.TRANS_RE.match(line)
if match:
translations[match.group(1).replace(ur'\"', u'"')] = match.group(2).replace(ur'\"', u'"').replace(u'{CR}', u'\n')
translations[match.group(1).replace(r'\"', u'"')] = match.group(2).replace(r'\"', u'"').replace(u'{CR}', u'\n')
elif __debug__ and not Translations.COMMENT_RE.match(line):
print 'Bad translation: %s' % line.strip()
print('Bad translation: %s' % line.strip())
if translations.get(LANGUAGE_ID, LANGUAGE_ID) == LANGUAGE_ID:
translations[LANGUAGE_ID] = unicode(lang) # Replace language name with code if missing
translations[LANGUAGE_ID] = str(lang) # Replace language name with code if missing
return translations
def translate(self, x, context=None):
@ -120,13 +125,13 @@ class Translations:
context = context[len(config.plugin_dir)+1:].split(os.sep)[0]
if __debug__:
if self.translations[None] and context not in self.translations:
print 'No translations for "%s"' % context
print('No translations for "%s"' % context)
return self.translations.get(context, {}).get(x) or self.translate(x)
else:
if __debug__:
if self.translations[None] and x not in self.translations[None]:
print 'Missing translation: "%s"' % x
return self.translations[None].get(x) or unicode(x).replace(ur'\"', u'"').replace(u'{CR}', u'\n')
print('Missing translation: "%s"' % x)
return self.translations[None].get(x) or str(x).replace(r'\"', u'"').replace(u'{CR}', u'\n')
# Returns list of available language codes
def available(self):
@ -173,7 +178,7 @@ class Translations:
return codecs.open(join(self.respath(), '%s.strings' % lang), 'r', 'utf-8')
class Locale:
class Locale(object):
def __init__(self):
if platform=='darwin':
@ -274,7 +279,7 @@ if __name__ == "__main__":
os.mkdir(LOCALISATION_DIR)
template = codecs.open(join(LOCALISATION_DIR, 'en.template'), 'w', 'utf-8')
template.write('/* Language name */\n"%s" = "%s";\n\n' % (LANGUAGE_ID, 'English'))
for thing in sorted(seen, key=unicode.lower):
for thing in sorted(seen, key=str.lower):
if seen[thing]:
template.write('/* %s */\n' % (seen[thing]))
template.write('"%s" = "%s";\n\n' % (thing, thing))

View File

@ -1,3 +1,4 @@
from __future__ import print_function
from collections import defaultdict, OrderedDict
import json
import re
@ -152,8 +153,8 @@ class EDLogs(FileSystemEventHandler):
self.observed = self.observer.schedule(self, self.currentdir)
if __debug__:
print '%s Journal "%s"' % (polling and 'Polling' or 'Monitoring', self.currentdir)
print 'Start logfile "%s"' % self.logfile
print('%s Journal "%s"' % (polling and 'Polling' or 'Monitoring', self.currentdir))
print('Start logfile "%s"' % self.logfile)
if not self.running():
self.thread = threading.Thread(target = self.worker, name = 'Journal worker')
@ -164,7 +165,7 @@ class EDLogs(FileSystemEventHandler):
def stop(self):
if __debug__:
print 'Stopping monitoring Journal'
print('Stopping monitoring Journal')
self.currentdir = None
self.version = self.mode = self.group = self.cmdr = self.planet = self.system = self.station = self.stationtype = self.stationservices = self.coordinates = self.systemaddress = None
self.is_beta = False
@ -206,7 +207,7 @@ class EDLogs(FileSystemEventHandler):
self.parse_entry(line) # Some events are of interest even in the past
except:
if __debug__:
print 'Invalid journal entry "%s"' % repr(line)
print('Invalid journal entry "%s"' % repr(line))
logpos = loghandle.tell()
else:
loghandle = None
@ -262,7 +263,7 @@ class EDLogs(FileSystemEventHandler):
fcntl(loghandle, F_GLOBAL_NOCACHE, -1) # required to avoid corruption on macOS over SMB
logpos = 0
if __debug__:
print 'New logfile "%s"' % logfile
print('New logfile "%s"' % logfile)
if logfile:
loghandle.seek(0, SEEK_END) # required to make macOS notice log change over SMB
@ -454,10 +455,10 @@ class EDLogs(FileSystemEventHandler):
payload = dict(entry)
payload.pop('event')
payload.pop('timestamp')
for k,v in payload.iteritems():
for k,v in payload.items():
self.state['Rank'][k] = (v,0)
elif entry['event'] == 'Progress':
for k,v in entry.iteritems():
for k,v in entry.items():
if k in self.state['Rank']:
self.state['Rank'][k] = (self.state['Rank'][k][0], min(v, 100)) # perhaps not taken promotion mission yet
elif entry['event'] in ['Reputation', 'Statistics']:
@ -621,7 +622,7 @@ class EDLogs(FileSystemEventHandler):
return entry
except:
if __debug__:
print 'Invalid journal entry "%s"' % repr(line)
print('Invalid journal entry "%s"' % repr(line))
print_exc()
return { 'event': None }

View File

@ -7,8 +7,8 @@
from sys import platform
import Tkinter as tk
import ttk
import tkinter as tk
from tkinter import ttk
# Can't do this with styles on OSX - http://www.tkdocs.com/tutorial/styles.html#whydifficult

View File

@ -8,7 +8,7 @@ import operator
import threading # We don't use it, but plugins might
from traceback import print_exc
import Tkinter as tk
import tkinter as tk
import myNotebook as nb
from config import config

View File

@ -5,9 +5,9 @@ from os.path import dirname, expanduser, expandvars, exists, isdir, join, normpa
from sys import platform
import webbrowser
import Tkinter as tk
import ttk
import tkColorChooser
import tkinter as tk
from tkinter import ttk
from tkinter import colorchooser as tkColorChooser
from ttkHyperlinkLabel import HyperlinkLabel
import myNotebook as nb

View File

@ -1,8 +1,12 @@
from __future__ import print_function
# edmc: protocol handler for cAPI authorisation
from future import standard_library
standard_library.install_aliases()
from builtins import object
import threading
import urllib2
import urllib.request, urllib.error, urllib.parse
import sys
from config import appname
@ -17,7 +21,7 @@ if sys.platform == 'win32':
is_wine = False
class GenericProtocolHandler:
class GenericProtocolHandler(object):
def __init__(self):
self.redirect = 'edmc://auth' # Base redirection URL
@ -67,7 +71,7 @@ if sys.platform == 'darwin' and getattr(sys, 'frozen', False):
return self
def handleEvent_withReplyEvent_(self, event, replyEvent):
protocolhandler.lasturl = urllib2.unquote(event.paramDescriptorForKeyword_(keyDirectObject).stringValue()).strip()
protocolhandler.lasturl = urllib.parse.unquote(event.paramDescriptorForKeyword_(keyDirectObject).stringValue()).strip()
protocolhandler.master.after(ProtocolHandler.POLL, protocolhandler.poll)
@ -189,7 +193,7 @@ elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine:
args = wstring_at(GlobalLock(msg.lParam)).strip()
GlobalUnlock(msg.lParam)
if args.lower().startswith('open("') and args.endswith('")'):
url = urllib2.unquote(args[6:-2]).strip()
url = urllib.parse.unquote(args[6:-2]).strip()
if url.startswith(self.redirect):
self.event(url)
SetForegroundWindow(GetParent(self.master.winfo_id())) # raise app window
@ -202,11 +206,11 @@ elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine:
TranslateMessage(byref(msg))
DispatchMessage(byref(msg))
else:
print 'Failed to register DDE for cAPI'
print('Failed to register DDE for cAPI')
else: # Linux / Run from source
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from http.server import HTTPServer, BaseHTTPRequestHandler
class ProtocolHandler(GenericProtocolHandler):
@ -236,7 +240,7 @@ else: # Linux / Run from source
class HTTPRequestHandler(BaseHTTPRequestHandler):
def parse(self):
url = urllib2.unquote(self.path)
url = urllib.parse.unquote(self.path)
if url.startswith('/auth'):
protocolhandler.event(url)
self.send_response(200)

View File

@ -6,8 +6,8 @@ import time
if __debug__:
from traceback import print_exc
import Tkinter as tk
import ttk
import tkinter as tk
from tkinter import ttk
import myNotebook as nb
import companion

View File

@ -1,3 +1,4 @@
from __future__ import division
#
# Theme support
#
@ -5,12 +6,17 @@
# So can't use ttk's theme support. So have to change colors manually.
#
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import object
from past.utils import old_div
from sys import platform
from os.path import join
import Tkinter as tk
import ttk
import tkFont
import tkinter as tk
from tkinter import ttk
from tkinter import font as tkFont
from ttkHyperlinkLabel import HyperlinkLabel
from config import appname, applongname, config
@ -98,7 +104,7 @@ elif platform == 'linux2':
dpy = None
class _Theme:
class _Theme(object):
def __init__(self):
self.active = None # Starts out with no theme
@ -210,7 +216,7 @@ class _Theme:
'foreground' : config.get('dark_text'),
'activebackground' : config.get('dark_text'),
'activeforeground' : 'grey4',
'disabledforeground' : '#%02x%02x%02x' % (r/384, g/384, b/384),
'disabledforeground' : '#%02x%02x%02x' % (old_div(r,384), old_div(g,384), old_div(b,384)),
'highlight' : config.get('dark_highlight'),
# Font only supports Latin 1 / Supplement / Extended, and a few General Punctuation and Mathematical Operators
'font' : (theme > 1 and not 0x250 < ord(_('Cmdr')[0]) < 0x3000 and

View File

@ -1,9 +1,9 @@
from sys import platform
import webbrowser
import Tkinter as tk
import ttk
import tkFont
import tkinter as tk
from tkinter import ttk
from tkinter import font as tkFont
if platform == 'win32':
import subprocess