diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..0d1917c4e4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing to Evennia + +Evennia utilizes GitHub for issue tracking and contributions: + + - Reporting Issues issues/bugs and making feature requests can be done [in the issue tracker](https://github.com/evennia/evennia/issues). + - Evennia's documentation is a [wiki](https://github.com/evennia/evennia/wiki) that everyone can contribute to. Further + instructions and details about contributing is found [here](https://github.com/evennia/evennia/wiki/Contributing). diff --git a/evennia/server/portal/irc.py b/evennia/server/portal/irc.py index d74fbaa86e..2b616f2ce1 100644 --- a/evennia/server/portal/irc.py +++ b/evennia/server/portal/irc.py @@ -421,7 +421,7 @@ class IRCBotFactory(protocol.ReconnectingClientFactory): def clientConnectionLost(self, connector, reason): """ - Called when Client looses connection. + Called when Client loses connection. Args: connector (Connection): Represents the connection. diff --git a/evennia/settings_default.py b/evennia/settings_default.py index 09a8371cd9..1b761c1bdf 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -139,7 +139,7 @@ HTTP_LOG_FILE = os.path.join(LOG_DIR, 'http_requests.log') LOCKWARNING_LOG_FILE = os.path.join(LOG_DIR, 'lockwarnings.log') # Rotate log files when server and/or portal stops. This will keep log # file sizes down. Turn off to get ever growing log files and never -# loose log info. +# lose log info. CYCLE_LOGFILES = True # Number of lines to append to rotating channel logs when they rotate CHANNEL_LOG_NUM_TAIL_LINES = 20 diff --git a/evennia/utils/create.py b/evennia/utils/create.py index 36db7e5a60..ae7e867f27 100644 --- a/evennia/utils/create.py +++ b/evennia/utils/create.py @@ -229,6 +229,12 @@ def create_script(typeclass=None, key=None, obj=None, account=None, locks=None, # at_first_save hook on the typeclass, where the _createdict # can be used. new_script.save() + + if not new_script.id: + # this happens in the case of having a repeating script with `repeats=1` and + # `start_delay=False` - the script will run once and immediately stop before save is over. + return None + return new_script diff --git a/evennia/utils/idmapper/models.py b/evennia/utils/idmapper/models.py index fcda53cdfd..54b0ac33d2 100644 --- a/evennia/utils/idmapper/models.py +++ b/evennia/utils/idmapper/models.py @@ -397,6 +397,11 @@ class SharedMemoryModel(with_metaclass(SharedMemoryModelBase, Model)): super(SharedMemoryModel, cls).save(*args, **kwargs) callFromThread(_save_callback, self, *args, **kwargs) + if not self.pk: + # this can happen if some of the startup methods immediately + # delete the object (an example are Scripts that start and die immediately) + return + # update field-update hooks and eventual OOB watchers new = False if "update_fields" in kwargs and kwargs["update_fields"]: @@ -421,6 +426,7 @@ class SharedMemoryModel(with_metaclass(SharedMemoryModelBase, Model)): # fieldtracker = "_oob_at_%s_postsave" % fieldname # if hasattr(self, fieldtracker): # _GA(self, fieldtracker)(fieldname) + pass class WeakSharedMemoryModelBase(SharedMemoryModelBase): diff --git a/evennia/utils/tests/test_create_functions.py b/evennia/utils/tests/test_create_functions.py new file mode 100644 index 0000000000..2d5b1eeaf0 --- /dev/null +++ b/evennia/utils/tests/test_create_functions.py @@ -0,0 +1,79 @@ +""" +Tests of create functions + +""" + +from evennia.utils.test_resources import EvenniaTest +from evennia.scripts.scripts import DefaultScript +from evennia.utils import create + + +class TestCreateScript(EvenniaTest): + + def test_create_script(self): + class TestScriptA(DefaultScript): + def at_script_creation(self): + self.key = 'test_script' + self.interval = 10 + self.persistent = False + + script = create.create_script(TestScriptA, key='test_script') + assert script is not None + assert script.interval == 10 + assert script.key == 'test_script' + script.stop() + + def test_create_script_w_repeats_equal_1(self): + class TestScriptB(DefaultScript): + def at_script_creation(self): + self.key = 'test_script' + self.interval = 10 + self.repeats = 1 + self.persistent = False + + # script is already stopped (interval=1, start_delay=False) + script = create.create_script(TestScriptB, key='test_script') + assert script is None + + def test_create_script_w_repeats_equal_1_persisted(self): + class TestScriptB1(DefaultScript): + def at_script_creation(self): + self.key = 'test_script' + self.interval = 10 + self.repeats = 1 + self.persistent = True + + # script is already stopped (interval=1, start_delay=False) + script = create.create_script(TestScriptB1, key='test_script') + assert script is None + + def test_create_script_w_repeats_equal_2(self): + class TestScriptC(DefaultScript): + def at_script_creation(self): + self.key = 'test_script' + self.interval = 10 + self.repeats = 2 + self.persistent = False + + script = create.create_script(TestScriptC, key='test_script') + assert script is not None + assert script.interval == 10 + assert script.repeats == 2 + assert script.key == 'test_script' + script.stop() + + def test_create_script_w_repeats_equal_1_and_delayed(self): + class TestScriptD(DefaultScript): + def at_script_creation(self): + self.key = 'test_script' + self.interval = 10 + self.start_delay = True + self.repeats = 1 + self.persistent = False + + script = create.create_script(TestScriptD, key='test_script') + assert script is not None + assert script.interval == 10 + assert script.repeats == 1 + assert script.key == 'test_script' + script.stop()