refactoring some code and added docstring
added stopwatch.py(modify from utils.timer.py) for test
This commit is contained in:
@@ -877,19 +877,19 @@ class MainFrame(wx.Frame, IPortUser):
|
||||
else:
|
||||
self.progressDialog.Update(info)
|
||||
|
||||
def onPortProcessStart(self):
|
||||
def on_port_process_start(self):
|
||||
# flag for progress dialog.
|
||||
self.__progress_flag = True
|
||||
|
||||
def onPortProcessing(self, action, data=None):
|
||||
def on_port_processing(self, action, data=None):
|
||||
# 2017/03/29 NOTE: implementation like interface
|
||||
wx.CallAfter(
|
||||
self._onPortProcessing, action, data
|
||||
self._on_port_processing, action, data
|
||||
)
|
||||
|
||||
return self.__progress_flag
|
||||
|
||||
def _onPortProcessing(self, action, data):
|
||||
def _on_port_processing(self, action, data):
|
||||
"""
|
||||
While importing fits from file, the logic calls back to this function to
|
||||
update progress bar to show activity. XML files can contain multiple
|
||||
|
||||
121
service/port.py
121
service/port.py
@@ -47,7 +47,7 @@ from eos.saveddata.ship import Ship
|
||||
from eos.saveddata.citadel import Citadel
|
||||
from eos.saveddata.fit import Fit
|
||||
from service.market import Market
|
||||
from utils.strfunctions import sequential_rep, replaceLTGT
|
||||
from utils.strfunctions import sequential_rep, replace_ltgt
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
|
||||
@@ -73,25 +73,39 @@ INV_FLAG_CARGOBAY = 5
|
||||
INV_FLAG_DRONEBAY = 87
|
||||
INV_FLAG_FIGHTER = 158
|
||||
|
||||
# 2017/04/05 NOTE: simple validation, for xml file
|
||||
RE_XML_START = r'<\?xml\s+version="1.0"\s+\?>'
|
||||
|
||||
# -- 170327 Ignored description --
|
||||
localized_pattern = re.compile(r'<localized hint="([^"]+)">([^\*]+)\*</localized>')
|
||||
RE_LTGT = "&(lt|gt);"
|
||||
L_MARK = "<localized hint=""
|
||||
LOCALIZED_PATTERN = re.compile(r'<localized hint="([^"]+)">([^\*]+)\*</localized>')
|
||||
|
||||
|
||||
def _resolveShip(fitting, sMkt):
|
||||
def _extract_matche(t):
|
||||
m = LOCALIZED_PATTERN.match(t)
|
||||
# hint attribute, text content
|
||||
return m.group(1), m.group(2)
|
||||
|
||||
|
||||
def _resolve_ship(fitting, sMkt, b_localized):
|
||||
# type: (xml.dom.minidom.Element, Market, bool) -> eos.saveddata.fit.Fit
|
||||
|
||||
fitobj = Fit()
|
||||
fitobj.name = fitting.getAttribute("name")
|
||||
# 2017/03/29 NOTE:
|
||||
# if fit name contained "<" or ">" then reprace to named html entity by EVE client
|
||||
fitobj.name = replaceLTGT(fitting.getAttribute("name"))
|
||||
# if re.search(RE_LTGT, fitobj.name):
|
||||
if "<" in fitobj.name or ">" in fitobj.name:
|
||||
fitobj.name = replace_ltgt(fitobj.name)
|
||||
|
||||
# <localized hint="Maelstrom">Maelstrom</localized>
|
||||
shipType = fitting.getElementsByTagName("shipType").item(0).getAttribute("value")
|
||||
emergency = None
|
||||
matches = localized_pattern.match(shipType)
|
||||
if matches:
|
||||
# emergency cache
|
||||
emergency = matches.group(2)
|
||||
# expect an official name
|
||||
shipType = matches.group(1)
|
||||
# emergency = None
|
||||
if b_localized:
|
||||
# expect an official name, emergency cache
|
||||
shipType, emergency = _extract_matche(shipType)
|
||||
|
||||
limit = 2
|
||||
while True:
|
||||
must_retry = False
|
||||
@@ -101,24 +115,28 @@ def _resolveShip(fitting, sMkt):
|
||||
except ValueError:
|
||||
fitobj.ship = Citadel(sMkt.getItem(shipType))
|
||||
except Exception as e:
|
||||
pyfalog.warning("Caught exception on _resolveShip")
|
||||
pyfalog.warning("Caught exception on _resolve_ship")
|
||||
pyfalog.error(e)
|
||||
limit -= 1
|
||||
if limit is 0:
|
||||
break
|
||||
shipType = emergency
|
||||
must_retry = True
|
||||
limit -= 1
|
||||
if not must_retry or limit is 0:
|
||||
if not must_retry:
|
||||
break
|
||||
# True means localized
|
||||
return matches is not None, fitobj
|
||||
|
||||
return fitobj
|
||||
|
||||
|
||||
def _resolveModule(hardware, sMkt, b_localized):
|
||||
def _resolve_module(hardware, sMkt, b_localized):
|
||||
# type: (xml.dom.minidom.Element, Market, bool) -> eos.saveddata.module.Module
|
||||
|
||||
moduleName = hardware.getAttribute("type")
|
||||
emergency = None
|
||||
# emergency = None
|
||||
if b_localized:
|
||||
emergency = localized_pattern.sub("\g<2>", moduleName)
|
||||
# expect an official name
|
||||
moduleName = localized_pattern.sub("\g<1>", moduleName)
|
||||
# expect an official name, emergency cache
|
||||
moduleName, emergency = _extract_matche(moduleName)
|
||||
|
||||
item = None
|
||||
limit = 2
|
||||
while True:
|
||||
@@ -126,12 +144,14 @@ def _resolveModule(hardware, sMkt, b_localized):
|
||||
try:
|
||||
item = sMkt.getItem(moduleName, eager="group.category")
|
||||
except Exception as e:
|
||||
pyfalog.warning("Caught exception on _resolveModule")
|
||||
pyfalog.warning("Caught exception on _resolve_module")
|
||||
pyfalog.error(e)
|
||||
limit -= 1
|
||||
if limit is 0:
|
||||
break
|
||||
moduleName = emergency
|
||||
must_retry = True
|
||||
limit -= 1
|
||||
if not must_retry or limit is 0:
|
||||
if not must_retry:
|
||||
break
|
||||
return item
|
||||
|
||||
@@ -160,7 +180,7 @@ class IPortUser:
|
||||
# means import process.
|
||||
|
||||
@abstractmethod
|
||||
def onPortProcessing(self, action, data=None):
|
||||
def on_port_processing(self, action, data=None):
|
||||
"""
|
||||
While importing fits from file, the logic calls back to this function to
|
||||
update progress bar to show activity. XML files can contain multiple
|
||||
@@ -178,7 +198,7 @@ class IPortUser:
|
||||
"""return: True is continue process, False is cancel."""
|
||||
pass
|
||||
|
||||
def onPortProcessStart(self):
|
||||
def on_port_process_start(self):
|
||||
pass
|
||||
|
||||
|
||||
@@ -189,6 +209,7 @@ class Port(object):
|
||||
2. i think should not write wx.CallAfter in here
|
||||
"""
|
||||
instance = None
|
||||
__tag_replace_flag = True
|
||||
|
||||
@classmethod
|
||||
def getInstance(cls):
|
||||
@@ -197,6 +218,16 @@ class Port(object):
|
||||
|
||||
return cls.instance
|
||||
|
||||
@classmethod
|
||||
def set_tag_replace(cls, b):
|
||||
cls.__tag_replace_flag = b
|
||||
|
||||
@classmethod
|
||||
def is_tag_replace(cls):
|
||||
# might there is a person who wants to hold tags.
|
||||
# (item link in EVE client etc. When importing again to EVE)
|
||||
return cls.__tag_replace_flag
|
||||
|
||||
@staticmethod
|
||||
def backupFits(path, iportuser):
|
||||
pyfalog.debug("Starting backup fits thread.")
|
||||
@@ -209,7 +240,12 @@ class Port(object):
|
||||
|
||||
@staticmethod
|
||||
def importFitsThreaded(paths, iportuser):
|
||||
"""param iportuser: IPortUser implemented class"""
|
||||
# type: (tuple, IPortUser) -> None
|
||||
"""
|
||||
:param paths: fits data file path list.
|
||||
:param iportuser: IPortUser implemented class.
|
||||
:rtype: None
|
||||
"""
|
||||
pyfalog.debug("Starting import fits thread.")
|
||||
# thread = FitImportThread(paths, iportuser)
|
||||
# thread.start()
|
||||
@@ -238,8 +274,8 @@ class Port(object):
|
||||
PortProcessing.notify(iportuser, IPortUser.PROCESS_IMPORT | IPortUser.ID_UPDATE, msg)
|
||||
# wx.CallAfter(callback, 1, msg)
|
||||
|
||||
file_ = open(path, "r")
|
||||
srcString = file_.read()
|
||||
with open(path, "r") as file_:
|
||||
srcString = file_.read()
|
||||
|
||||
if len(srcString) == 0: # ignore blank files
|
||||
pyfalog.debug("File is blank.")
|
||||
@@ -442,7 +478,7 @@ class Port(object):
|
||||
firstLine = firstLine.strip()
|
||||
|
||||
# If XML-style start of tag encountered, detect as XML
|
||||
if re.match("<", firstLine):
|
||||
if re.match(RE_XML_START, firstLine):
|
||||
if encoding:
|
||||
return "XML", cls.importXml(string, iportuser, encoding)
|
||||
else:
|
||||
@@ -975,12 +1011,16 @@ class Port(object):
|
||||
|
||||
sMkt = Market.getInstance()
|
||||
doc = xml.dom.minidom.parseString(text.encode(encoding))
|
||||
# NOTE:
|
||||
# When L_MARK is included at this point,
|
||||
# Decided to be localized data
|
||||
b_localized = L_MARK in text
|
||||
fittings = doc.getElementsByTagName("fittings").item(0)
|
||||
fittings = fittings.getElementsByTagName("fitting")
|
||||
fit_list = []
|
||||
|
||||
for fitting in (fittings):
|
||||
b_localized, fitobj = _resolveShip(fitting, sMkt)
|
||||
fitobj = _resolve_ship(fitting, sMkt, b_localized)
|
||||
# -- 170327 Ignored description --
|
||||
# read description from exported xml. (EVE client, EFT)
|
||||
description = fitting.getElementsByTagName("description").item(0).getAttribute("value")
|
||||
@@ -988,16 +1028,17 @@ class Port(object):
|
||||
description = ""
|
||||
elif len(description):
|
||||
# convert <br> to "\n" and remove html tags.
|
||||
description = sequential_rep(description, r"<(br|BR)>", "\n", r"<[^<>]+>", "")
|
||||
# description = re.sub(r"<(br|BR)>", "\n", description)
|
||||
# description = re.sub(r"<[^<>]+>", "", description)
|
||||
if Port.is_tag_replace():
|
||||
description = replace_ltgt(
|
||||
sequential_rep(description, r"<(br|BR)>", "\n", r"<[^<>]+>", "")
|
||||
)
|
||||
fitobj.notes = description
|
||||
|
||||
hardwares = fitting.getElementsByTagName("hardware")
|
||||
moduleList = []
|
||||
for hardware in hardwares:
|
||||
try:
|
||||
item = _resolveModule(hardware, sMkt, b_localized)
|
||||
item = _resolve_module(hardware, sMkt, b_localized)
|
||||
if not item:
|
||||
continue
|
||||
|
||||
@@ -1340,7 +1381,7 @@ class PortProcessing(object):
|
||||
def backupFits(path, iportuser):
|
||||
success = True
|
||||
try:
|
||||
iportuser.onPortProcessStart()
|
||||
iportuser.on_port_process_start()
|
||||
backedUpFits = Port.exportXml(iportuser, *svcFit.getInstance().getAllFits())
|
||||
backupFile = open(path, "w", encoding="utf-8")
|
||||
backupFile.write(backedUpFits)
|
||||
@@ -1350,17 +1391,17 @@ class PortProcessing(object):
|
||||
# Send done signal to GUI
|
||||
# wx.CallAfter(callback, -1, "Done.")
|
||||
flag = IPortUser.ID_ERROR if not success else IPortUser.ID_DONE
|
||||
iportuser.onPortProcessing(IPortUser.PROCESS_EXPORT | flag,
|
||||
iportuser.on_port_processing(IPortUser.PROCESS_EXPORT | flag,
|
||||
"User canceled or some error occurrence." if not success else "Done.")
|
||||
|
||||
@staticmethod
|
||||
def importFitsFromFile(paths, iportuser):
|
||||
iportuser.onPortProcessStart()
|
||||
iportuser.on_port_process_start()
|
||||
success, result = Port.importFitFromFiles(paths, iportuser)
|
||||
flag = IPortUser.ID_ERROR if not success else IPortUser.ID_DONE
|
||||
iportuser.onPortProcessing(IPortUser.PROCESS_IMPORT | flag, result)
|
||||
iportuser.on_port_processing(IPortUser.PROCESS_IMPORT | flag, result)
|
||||
|
||||
@staticmethod
|
||||
def notify(iportuser, flag, data):
|
||||
if not iportuser.onPortProcessing(flag, data):
|
||||
if not iportuser.on_port_processing(flag, data):
|
||||
raise UserCancelException
|
||||
|
||||
107
utils/stopwatch.py
Normal file
107
utils/stopwatch.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# coding: utf-8
|
||||
|
||||
import time
|
||||
import os
|
||||
|
||||
# 2017/04/05:
|
||||
class Stopwatch(object):
|
||||
"""
|
||||
--- on python console ---
|
||||
import re
|
||||
from utils.stopwatch import Stopwatch
|
||||
# measurement re.sub
|
||||
def m_re_sub(t, set_count, executes, texts):
|
||||
t.reset()
|
||||
while set_count:
|
||||
set_count -= 1
|
||||
with t:
|
||||
while executes:
|
||||
executes -= 1
|
||||
ret = re.sub("[a|s]+", "-", texts)
|
||||
# stat string
|
||||
return str(t)
|
||||
|
||||
# measurementor
|
||||
stpwth = Stopwatch("test")
|
||||
# statistics loop: 1000(exec re.sub: 100000)
|
||||
m_re_sub(stpwth, 1000, 100000, "asdfadsasdaasdfadsasda")
|
||||
|
||||
----------- records -----------
|
||||
text: "asdfadsasda"
|
||||
'elapsed record(ms): min=0.000602411446948, max=220.85578571'
|
||||
'elapsed record(ms): min=0.000602411446948, max=217.331377504'
|
||||
|
||||
text: "asdfadsasdaasdfadsasda"
|
||||
'elapsed record(ms): min=0.000602411446948, max=287.784902967'
|
||||
'elapsed record(ms): min=0.000602411432737, max=283.653264016'
|
||||
|
||||
NOTE: about max
|
||||
The value is large only at the first execution,
|
||||
Will it be optimized, after that it will be significantly smaller
|
||||
"""
|
||||
|
||||
# time.clock() is μs? 1/1000ms
|
||||
# https://docs.python.jp/2.7/library/time.html#time.clock
|
||||
_tfunc = time.clock if os.name == "nt" else time.time
|
||||
|
||||
def __init__(self, name='', logger=None):
|
||||
self.name = name
|
||||
self.start = Stopwatch._tfunc()
|
||||
self.__last = self.start
|
||||
# __last field is means last checkpoint system clock value?
|
||||
self.logger = logger
|
||||
self.reset()
|
||||
|
||||
@property
|
||||
def stat(self):
|
||||
# :return: (float, float)
|
||||
return (self.min, self.max)
|
||||
|
||||
@property
|
||||
def elapsed(self):
|
||||
# :return: time as ms
|
||||
return (Stopwatch._tfunc() - self.start) * 1000
|
||||
|
||||
@property
|
||||
def last(self):
|
||||
return self.__last * 1000
|
||||
|
||||
def __update_stat(self, v):
|
||||
# :param v: unit of ms
|
||||
if self.min == 0.0: self.min = v
|
||||
if self.max < v: self.max = v
|
||||
if self.min > v: self.min = v
|
||||
|
||||
def checkpoint(self, name=''):
|
||||
span = self.elapsed
|
||||
self.__update_stat(span)
|
||||
text = u'Stopwatch("{tname}") - {checkpoint} - {last:.6f}ms ({elapsed:.12f}ms elapsed)'.format(
|
||||
tname=self.name,
|
||||
checkpoint=unicode(name, "utf-8"),
|
||||
last=self.last,
|
||||
elapsed=span
|
||||
).strip()
|
||||
self.__last = Stopwatch._tfunc()
|
||||
if self.logger:
|
||||
self.logger.debug(text)
|
||||
else:
|
||||
print(text)
|
||||
|
||||
def reset(self):
|
||||
self.min = 0.0
|
||||
self.max = 0.0
|
||||
|
||||
def __enter__(self):
|
||||
self.start = Stopwatch._tfunc()
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
# https://docs.python.org/2.7/reference/datamodel.html?highlight=__enter__#object.__exit__
|
||||
# If the context was exited without an exception, all three arguments will be None
|
||||
self.checkpoint('finished')
|
||||
# ex: "type=None, value=None, traceback=None"
|
||||
# print "type=%s, value=%s, traceback=%s" % (type, value, traceback)
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
return "elapsed record(ms): min=%s, max=%s" % self.stat
|
||||
@@ -5,30 +5,26 @@ import re
|
||||
|
||||
|
||||
def sequential_rep(text_, *args):
|
||||
# type: (basestring, *list) -> basestring
|
||||
"""
|
||||
params
|
||||
text_: string content
|
||||
args : <pattern>, <replacement>, <pattern>, <replacement>, ...
|
||||
|
||||
return
|
||||
empty string when text_ length was zero or invalid.
|
||||
:param text_: string content
|
||||
:param args: like <pattern>, <replacement>, <pattern>, <replacement>, ...
|
||||
:return: if text_ length was zero or invalid parameters then no manipulation to text_
|
||||
"""
|
||||
|
||||
if not text_ or not len(text_):
|
||||
return ""
|
||||
|
||||
arg_len = len(args)
|
||||
i = 0
|
||||
while i < arg_len:
|
||||
text_ = re.sub(args[i], args[i + 1], text_)
|
||||
i += 2
|
||||
if arg_len % 2 == 0 and isinstance(text_, basestring) and len(text_) > 0:
|
||||
i = 0
|
||||
while i < arg_len:
|
||||
text_ = re.sub(args[i], args[i + 1], text_)
|
||||
i += 2
|
||||
|
||||
return text_
|
||||
|
||||
|
||||
def replaceLTGT(text_):
|
||||
def replace_ltgt(text_):
|
||||
# type: (basestring) -> basestring
|
||||
"""if fit name contained "<" or ">" then reprace to named html entity by EVE client.
|
||||
|
||||
for fit name.
|
||||
:param text_: string content of fit name from exported by EVE client.
|
||||
:return: if text_ is not instance of basestring then no manipulation to text_.
|
||||
"""
|
||||
return text_.replace("<", "<").replace(">", ">") if isinstance(text_, unicode) else text_
|
||||
return text_.replace("<", "<").replace(">", ">") if isinstance(text_, basestring) else text_
|
||||
|
||||
Reference in New Issue
Block a user