mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-13 07:47: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:
parent
c5df83eb32
commit
218c068ee5
@ -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)
|
||||
|
||||
@ -378,10 +383,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):
|
||||
@ -480,7 +485,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
|
||||
@ -488,14 +493,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
|
||||
@ -510,7 +515,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
|
||||
@ -577,7 +582,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:
|
||||
@ -606,10 +611,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
|
||||
@ -677,7 +682,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'),
|
||||
@ -689,7 +694,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
|
||||
@ -797,7 +802,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
|
||||
|
||||
|
72
companion.py
72
companion.py
@ -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',
|
||||
|
21
config.py
21
config.py
@ -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)
|
||||
|
@ -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
35
l10n.py
@ -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))
|
||||
|
17
monitor.py
17
monitor.py
@ -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 }
|
||||
|
||||
|
@ -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
|
||||
|
2
plug.py
2
plug.py
@ -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
|
||||
|
6
prefs.py
6
prefs.py
@ -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
|
||||
|
||||
|
18
protocol.py
18
protocol.py
@ -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)
|
||||
|
4
stats.py
4
stats.py
@ -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
|
||||
|
16
theme.py
16
theme.py
@ -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
|
||||
@ -95,7 +101,7 @@ elif platform == 'linux2':
|
||||
dpy = None
|
||||
|
||||
|
||||
class _Theme:
|
||||
class _Theme(object):
|
||||
|
||||
def __init__(self):
|
||||
self.active = None # Starts out with no theme
|
||||
@ -207,7 +213,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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user