Twisted min version upped to 15.2.1 due to a change in the LoopingCall infrastructure that Evennia relies on. This resolves #744 by updating the Evennia implementation accordingly.
This commit is contained in:
parent
ff4013a58a
commit
97e04ee710
6 changed files with 61 additions and 83 deletions
|
|
@ -8,7 +8,6 @@ ability to run timers.
|
||||||
from twisted.internet.defer import Deferred, maybeDeferred
|
from twisted.internet.defer import Deferred, maybeDeferred
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.conf import settings
|
|
||||||
from evennia.typeclasses.models import TypeclassBase
|
from evennia.typeclasses.models import TypeclassBase
|
||||||
from evennia.scripts.models import ScriptDB
|
from evennia.scripts.models import ScriptDB
|
||||||
from evennia.scripts.manager import ScriptManager
|
from evennia.scripts.manager import ScriptManager
|
||||||
|
|
@ -40,7 +39,7 @@ class ExtendedLoopingCall(LoopingCall):
|
||||||
interval (int): Repeat interval in seconds.
|
interval (int): Repeat interval in seconds.
|
||||||
now (bool, optional): Whether to start immediately or after
|
now (bool, optional): Whether to start immediately or after
|
||||||
`start_delay` seconds.
|
`start_delay` seconds.
|
||||||
start_delay (bool: The number of seconds before starting.
|
start_delay (int): The number of seconds before starting.
|
||||||
If None, wait interval seconds. Only valid if `now` is `False`.
|
If None, wait interval seconds. Only valid if `now` is `False`.
|
||||||
It is used as a way to start with a variable start time
|
It is used as a way to start with a variable start time
|
||||||
after a pause.
|
after a pause.
|
||||||
|
|
@ -64,44 +63,40 @@ class ExtendedLoopingCall(LoopingCall):
|
||||||
"ExtendedLoopingCall.")
|
"ExtendedLoopingCall.")
|
||||||
if interval < 0:
|
if interval < 0:
|
||||||
raise ValueError, "interval must be >= 0"
|
raise ValueError, "interval must be >= 0"
|
||||||
|
|
||||||
self.running = True
|
self.running = True
|
||||||
d = self.deferred = Deferred()
|
d = self.deferred = Deferred()
|
||||||
self.starttime = self.clock.seconds()
|
self.starttime = self.clock.seconds()
|
||||||
self._expectNextCallAt = self.starttime
|
|
||||||
self.interval = interval
|
self.interval = interval
|
||||||
self._runAtStart = now
|
self._runAtStart = now
|
||||||
self.callcount = max(0, count_start)
|
self.callcount = max(0, count_start)
|
||||||
|
self.start_delay = start_delay if start_delay is None else max(0, start_delay)
|
||||||
|
|
||||||
if now:
|
if now:
|
||||||
|
# run immediately
|
||||||
self()
|
self()
|
||||||
|
elif start_delay is not None and start_delay >= 0:
|
||||||
|
# start after some time: for this to work we need to
|
||||||
|
# trick _scheduleFrom by temporarily setting a different
|
||||||
|
# self.interval for it to check.
|
||||||
|
real_interval, self.interval = self.interval, start_delay
|
||||||
|
self._scheduleFrom(self.starttime)
|
||||||
|
# re-set the actual interval (this will be picked up
|
||||||
|
# next time it runs
|
||||||
|
self.interval = real_interval
|
||||||
else:
|
else:
|
||||||
if start_delay is not None and start_delay >= 0:
|
self._scheduleFrom(self.starttime)
|
||||||
# we set `start_delay` after the `_reschedule` call to make
|
|
||||||
# next_call_time() find it until next reschedule.
|
|
||||||
self.interval = start_delay
|
|
||||||
self._reschedule()
|
|
||||||
self.interval = interval
|
|
||||||
self.start_delay = start_delay
|
|
||||||
else:
|
|
||||||
self._reschedule()
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
"""
|
"""
|
||||||
Tick one step
|
Tick one step. We update callcount (tracks number of calls) as
|
||||||
|
well as null start_delay (needed in order to correctly
|
||||||
|
estimate next_call_time at all times).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.callcount += 1
|
self.callcount += 1
|
||||||
super(ExtendedLoopingCall, self).__call__()
|
|
||||||
|
|
||||||
def _reschedule(self):
|
|
||||||
"""
|
|
||||||
Handle call rescheduling including nulling `start_delay` and
|
|
||||||
stopping if number of repeats is reached.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.start_delay = None
|
self.start_delay = None
|
||||||
super(ExtendedLoopingCall, self)._reschedule()
|
super(ExtendedLoopingCall, self).__call__()
|
||||||
|
|
||||||
def force_repeat(self):
|
def force_repeat(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -116,22 +111,24 @@ class ExtendedLoopingCall(LoopingCall):
|
||||||
"that was not running.")
|
"that was not running.")
|
||||||
if self.call is not None:
|
if self.call is not None:
|
||||||
self.call.cancel()
|
self.call.cancel()
|
||||||
self._expectNextCallAt = self.clock.seconds()
|
self.call.callback()
|
||||||
self()
|
self()
|
||||||
|
|
||||||
def next_call_time(self):
|
def next_call_time(self):
|
||||||
"""
|
"""
|
||||||
Get the next call time.
|
Get the next call time. This also takes the eventual effect
|
||||||
|
of start_delay into account.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
next (int): The time in seconds until the next call. This
|
next (int or None): The time in seconds until the next call. This
|
||||||
takes `start_delay` into account. Returns `None` if
|
takes `start_delay` into account. Returns `None` if
|
||||||
the task is not running.
|
the task is not running.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self.running:
|
if self.running:
|
||||||
currentTime = self.clock.seconds()
|
total_runtime = self.clock.seconds() - self.starttime
|
||||||
return self._expectNextCallAt - currentTime
|
interval = self.start_delay or self.interval
|
||||||
|
return interval - (total_runtime % self.interval)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class ScriptBase(ScriptDB):
|
class ScriptBase(ScriptDB):
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,10 @@ class TickerHandler(object):
|
||||||
|
|
||||||
def restore(self):
|
def restore(self):
|
||||||
"""
|
"""
|
||||||
Restore ticker_storage from database and re-initialize the handler from storage. This is triggered by the server at restart.
|
Restore ticker_storage from database and re-initialize the
|
||||||
|
handler from storage. This is triggered by the server at
|
||||||
|
restart.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# load stored command instructions and use them to re-initialize handler
|
# load stored command instructions and use them to re-initialize handler
|
||||||
ticker_storage = ServerConfig.objects.conf(key=self.save_name)
|
ticker_storage = ServerConfig.objects.conf(key=self.save_name)
|
||||||
|
|
@ -353,7 +356,9 @@ class TickerHandler(object):
|
||||||
"""
|
"""
|
||||||
self.ticker_pool.stop(interval)
|
self.ticker_pool.stop(interval)
|
||||||
if interval:
|
if interval:
|
||||||
self.ticker_storage = dict((store_key, store_key) for store_key in self.ticker_storage if store_key[1] != interval)
|
self.ticker_storage = dict((store_key, store_key)
|
||||||
|
for store_key in self.ticker_storage
|
||||||
|
if store_key[1] != interval)
|
||||||
else:
|
else:
|
||||||
self.ticker_storage = {}
|
self.ticker_storage = {}
|
||||||
self.save()
|
self.save()
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,9 @@ PORTAL_RESTART = None
|
||||||
SERVER_PY_FILE = None
|
SERVER_PY_FILE = None
|
||||||
PORTAL_PY_FILE = None
|
PORTAL_PY_FILE = None
|
||||||
|
|
||||||
|
|
||||||
PYTHON_MIN = '2.7'
|
PYTHON_MIN = '2.7'
|
||||||
TWISTED_MIN = '12.0'
|
TWISTED_MIN = '15.2.1'
|
||||||
DJANGO_MIN = '1.8'
|
DJANGO_MIN = '1.8'
|
||||||
DJANGO_REC = '1.8'
|
DJANGO_REC = '1.8'
|
||||||
|
|
||||||
|
|
@ -265,10 +266,10 @@ ERROR_PYTHON_VERSION = \
|
||||||
{python_min} or higher (but not 3.x).
|
{python_min} or higher (but not 3.x).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
WARNING_TWISTED_VERSION = \
|
ERROR_TWISTED_VERSION = \
|
||||||
"""
|
"""
|
||||||
WARNING: Twisted {tversion} found. Evennia recommends
|
ERROR: Twisted {tversion} found. Evennia requires
|
||||||
v{twisted_min} or higher."
|
version {twisted_min} or higher.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ERROR_NOTWISTED = \
|
ERROR_NOTWISTED = \
|
||||||
|
|
@ -334,6 +335,9 @@ def check_main_evennia_dependencies():
|
||||||
"""
|
"""
|
||||||
Checks and imports the Evennia dependencies. This must be done
|
Checks and imports the Evennia dependencies. This must be done
|
||||||
already before the paths are set up.
|
already before the paths are set up.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
not_error (bool): True if no dependency error was found.
|
||||||
"""
|
"""
|
||||||
error = False
|
error = False
|
||||||
|
|
||||||
|
|
@ -347,7 +351,8 @@ def check_main_evennia_dependencies():
|
||||||
import twisted
|
import twisted
|
||||||
tversion = twisted.version.short()
|
tversion = twisted.version.short()
|
||||||
if tversion < TWISTED_MIN:
|
if tversion < TWISTED_MIN:
|
||||||
print WARNING_TWISTED_VERSION.format(tversion=tversion, twisted_min=TWISTED_MIN)
|
print ERROR_TWISTED_VERSION.format(tversion=tversion, twisted_min=TWISTED_MIN)
|
||||||
|
error = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print ERROR_NOTWISTED
|
print ERROR_NOTWISTED
|
||||||
error = True
|
error = True
|
||||||
|
|
@ -368,6 +373,8 @@ def check_main_evennia_dependencies():
|
||||||
error = True
|
error = True
|
||||||
if error:
|
if error:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
# return True/False if error was reported or not
|
||||||
|
return not error
|
||||||
|
|
||||||
|
|
||||||
def set_gamedir(path):
|
def set_gamedir(path):
|
||||||
|
|
|
||||||
|
|
@ -672,68 +672,37 @@ def run_async(to_execute, *args, **kwargs):
|
||||||
|
|
||||||
def check_evennia_dependencies():
|
def check_evennia_dependencies():
|
||||||
"""
|
"""
|
||||||
Checks the versions of Evennia's dependencies.
|
Checks the versions of Evennia's dependencies including making
|
||||||
|
some checks for runtime libraries
|
||||||
|
|
||||||
Returns False if a show-stopping version mismatch is found.
|
Returns False if a show-stopping version mismatch is found.
|
||||||
"""
|
"""
|
||||||
# defining the requirements
|
|
||||||
python_min = '2.7'
|
# check main dependencies
|
||||||
twisted_min = '12.0'
|
from evennia.server.evennia_launcher import check_main_evennia_dependencies
|
||||||
django_min = '1.8'
|
not_error = check_main_evennia_dependencies()
|
||||||
django_rec = '1.8'
|
|
||||||
|
|
||||||
errstring = ""
|
errstring = ""
|
||||||
no_error = True
|
# South is no longer used ...
|
||||||
|
|
||||||
# Python
|
|
||||||
pversion = ".".join(str(num) for num in sys.version_info if type(num) == int)
|
|
||||||
if pversion < python_min:
|
|
||||||
errstring += "\n ERROR: Python %s used. Evennia requires version %s or higher (but not 3.x)." % (pversion, python_min)
|
|
||||||
no_error = False
|
|
||||||
# Twisted
|
|
||||||
try:
|
|
||||||
import twisted
|
|
||||||
tversion = twisted.version.short()
|
|
||||||
if tversion < twisted_min:
|
|
||||||
errstring += "\n WARNING: Twisted %s found. Evennia recommends v%s or higher." % (twisted.version.short(), twisted_min)
|
|
||||||
except ImportError:
|
|
||||||
errstring += "\n ERROR: Twisted does not seem to be installed."
|
|
||||||
no_error = False
|
|
||||||
# Django
|
|
||||||
try:
|
|
||||||
import django
|
|
||||||
dversion = ".".join(str(num) for num in django.VERSION if type(num) == int)
|
|
||||||
dversion_main = ".".join(dversion.split(".")[:2]) # only the main version (1.5, not 1.5.4.0)
|
|
||||||
if dversion < django_min:
|
|
||||||
errstring += "\n ERROR: Django %s found. Evennia requires version %s or higher." % (dversion, django_min)
|
|
||||||
no_error = False
|
|
||||||
elif django_min <= dversion < django_rec:
|
|
||||||
errstring += "\n NOTE: Django %s found. This will work, but v%s is recommended for production." % (dversion, django_rec)
|
|
||||||
elif django_rec < dversion_main:
|
|
||||||
errstring += "\n NOTE: Django %s found. This is newer than Evennia's recommended version (v%s). It will"
|
|
||||||
errstring += "\n probably work, but may be new enough not to be fully tested yet. Report any issues." % (dversion, django_rec)
|
|
||||||
except ImportError:
|
|
||||||
errstring += "\n ERROR: Django does not seem to be installed."
|
|
||||||
no_error = False
|
|
||||||
# South
|
|
||||||
if 'south' in settings.INSTALLED_APPS:
|
if 'south' in settings.INSTALLED_APPS:
|
||||||
errstring += "\n ERROR: 'south' found in settings.INSTALLED_APPS. South is no longer used. If this was added manually, remove it."
|
errstring += "\n ERROR: 'south' found in settings.INSTALLED_APPS. " \
|
||||||
no_error = False
|
"\n South is no longer used. If this was added manually, remove it."
|
||||||
|
not_error = False
|
||||||
# IRC support
|
# IRC support
|
||||||
if settings.IRC_ENABLED:
|
if settings.IRC_ENABLED:
|
||||||
try:
|
try:
|
||||||
import twisted.words
|
import twisted.words
|
||||||
twisted.words # set to avoid debug info about not-used import
|
twisted.words # set to avoid debug info about not-used import
|
||||||
except ImportError:
|
except ImportError:
|
||||||
errstring += "\n ERROR: IRC is enabled, but twisted.words is not installed. Please install it."
|
errstring += "\n ERROR: IRC is enabled, but twisted.words is not installed. Please install it." \
|
||||||
errstring += "\n Linux Debian/Ubuntu users should install package 'python-twisted-words', others"
|
"\n Linux Debian/Ubuntu users should install package 'python-twisted-words', others" \
|
||||||
errstring += "\n can get it from http://twistedmatrix.com/trac/wiki/TwistedWords."
|
"\n can get it from http://twistedmatrix.com/trac/wiki/TwistedWords."
|
||||||
no_error = False
|
not_error = False
|
||||||
errstring = errstring.strip()
|
errstring = errstring.strip()
|
||||||
if errstring:
|
if errstring:
|
||||||
mlen = max(len(line) for line in errstring.split("\n"))
|
mlen = max(len(line) for line in errstring.split("\n"))
|
||||||
print "%s\n%s\n%s" % ("-"*mlen, errstring, '-'*mlen)
|
print "%s\n%s\n%s" % ("-"*mlen, errstring, '-'*mlen)
|
||||||
return no_error
|
return not_error
|
||||||
|
|
||||||
|
|
||||||
def has_parent(basepath, obj):
|
def has_parent(basepath, obj):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Evennia dependencies, for Linux/Mac platforms
|
# Evennia dependencies, for Linux/Mac platforms
|
||||||
|
|
||||||
django >= 1.8, < 1.9
|
django >= 1.8, < 1.9
|
||||||
twisted >= 12.0
|
twisted >= 15.2.1
|
||||||
mock >= 1.0.1
|
mock >= 1.0.1
|
||||||
pillow
|
pillow
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,6 @@
|
||||||
pypiwin32
|
pypiwin32
|
||||||
# general
|
# general
|
||||||
django >= 1.8, < 1.9
|
django >= 1.8, < 1.9
|
||||||
twisted >= 12.0
|
twisted >= 15.2.1
|
||||||
mock >= 1.0.1
|
mock >= 1.0.1
|
||||||
pillow
|
pillow
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue