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:
Griatch 2015-05-27 22:35:05 +02:00
parent ff4013a58a
commit 97e04ee710
6 changed files with 61 additions and 83 deletions

View file

@ -8,7 +8,6 @@ ability to run timers.
from twisted.internet.defer import Deferred, maybeDeferred
from twisted.internet.task import LoopingCall
from django.utils.translation import ugettext as _
from django.conf import settings
from evennia.typeclasses.models import TypeclassBase
from evennia.scripts.models import ScriptDB
from evennia.scripts.manager import ScriptManager
@ -40,7 +39,7 @@ class ExtendedLoopingCall(LoopingCall):
interval (int): Repeat interval in seconds.
now (bool, optional): Whether to start immediately or after
`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`.
It is used as a way to start with a variable start time
after a pause.
@ -64,44 +63,40 @@ class ExtendedLoopingCall(LoopingCall):
"ExtendedLoopingCall.")
if interval < 0:
raise ValueError, "interval must be >= 0"
self.running = True
d = self.deferred = Deferred()
self.starttime = self.clock.seconds()
self._expectNextCallAt = self.starttime
self.interval = interval
self._runAtStart = now
self.callcount = max(0, count_start)
self.start_delay = start_delay if start_delay is None else max(0, start_delay)
if now:
# run immediately
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:
if start_delay is not None and start_delay >= 0:
# 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()
self._scheduleFrom(self.starttime)
return d
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
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
super(ExtendedLoopingCall, self)._reschedule()
super(ExtendedLoopingCall, self).__call__()
def force_repeat(self):
"""
@ -116,22 +111,24 @@ class ExtendedLoopingCall(LoopingCall):
"that was not running.")
if self.call is not None:
self.call.cancel()
self._expectNextCallAt = self.clock.seconds()
self.call.callback()
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:
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
the task is not running.
"""
if self.running:
currentTime = self.clock.seconds()
return self._expectNextCallAt - currentTime
total_runtime = self.clock.seconds() - self.starttime
interval = self.start_delay or self.interval
return interval - (total_runtime % self.interval)
return None
class ScriptBase(ScriptDB):

View file

@ -264,7 +264,10 @@ class TickerHandler(object):
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
ticker_storage = ServerConfig.objects.conf(key=self.save_name)
@ -353,7 +356,9 @@ class TickerHandler(object):
"""
self.ticker_pool.stop(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:
self.ticker_storage = {}
self.save()

View file

@ -54,8 +54,9 @@ PORTAL_RESTART = None
SERVER_PY_FILE = None
PORTAL_PY_FILE = None
PYTHON_MIN = '2.7'
TWISTED_MIN = '12.0'
TWISTED_MIN = '15.2.1'
DJANGO_MIN = '1.8'
DJANGO_REC = '1.8'
@ -265,10 +266,10 @@ ERROR_PYTHON_VERSION = \
{python_min} or higher (but not 3.x).
"""
WARNING_TWISTED_VERSION = \
ERROR_TWISTED_VERSION = \
"""
WARNING: Twisted {tversion} found. Evennia recommends
v{twisted_min} or higher."
ERROR: Twisted {tversion} found. Evennia requires
version {twisted_min} or higher.
"""
ERROR_NOTWISTED = \
@ -334,6 +335,9 @@ def check_main_evennia_dependencies():
"""
Checks and imports the Evennia dependencies. This must be done
already before the paths are set up.
Returns:
not_error (bool): True if no dependency error was found.
"""
error = False
@ -347,7 +351,8 @@ def check_main_evennia_dependencies():
import twisted
tversion = twisted.version.short()
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:
print ERROR_NOTWISTED
error = True
@ -368,6 +373,8 @@ def check_main_evennia_dependencies():
error = True
if error:
sys.exit()
# return True/False if error was reported or not
return not error
def set_gamedir(path):

View file

@ -672,68 +672,37 @@ def run_async(to_execute, *args, **kwargs):
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.
"""
# defining the requirements
python_min = '2.7'
twisted_min = '12.0'
django_min = '1.8'
django_rec = '1.8'
# check main dependencies
from evennia.server.evennia_launcher import check_main_evennia_dependencies
not_error = check_main_evennia_dependencies()
errstring = ""
no_error = True
# 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
# South is no longer used ...
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."
no_error = False
errstring += "\n ERROR: 'south' found in settings.INSTALLED_APPS. " \
"\n South is no longer used. If this was added manually, remove it."
not_error = False
# IRC support
if settings.IRC_ENABLED:
try:
import twisted.words
twisted.words # set to avoid debug info about not-used import
except ImportError:
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"
errstring += "\n can get it from http://twistedmatrix.com/trac/wiki/TwistedWords."
no_error = False
errstring += "\n ERROR: IRC is enabled, but twisted.words is not installed. Please install it." \
"\n Linux Debian/Ubuntu users should install package 'python-twisted-words', others" \
"\n can get it from http://twistedmatrix.com/trac/wiki/TwistedWords."
not_error = False
errstring = errstring.strip()
if errstring:
mlen = max(len(line) for line in errstring.split("\n"))
print "%s\n%s\n%s" % ("-"*mlen, errstring, '-'*mlen)
return no_error
return not_error
def has_parent(basepath, obj):

View file

@ -1,6 +1,6 @@
# Evennia dependencies, for Linux/Mac platforms
django >= 1.8, < 1.9
twisted >= 12.0
twisted >= 15.2.1
mock >= 1.0.1
pillow

View file

@ -4,6 +4,6 @@
pypiwin32
# general
django >= 1.8, < 1.9
twisted >= 12.0
twisted >= 15.2.1
mock >= 1.0.1
pillow