diff --git a/bin/evennia.py b/bin/evennia similarity index 93% rename from bin/evennia.py rename to bin/evennia index d902f0d7ff..bd79d76c6c 100755 --- a/bin/evennia.py +++ b/bin/evennia @@ -15,7 +15,7 @@ import signal import shutil import importlib from argparse import ArgumentParser -from subprocess import Popen +from subprocess import Popen, check_output import django # Signal processing @@ -28,7 +28,6 @@ EVENNIA_LIB = os.path.join(EVENNIA_ROOT, "evennia") EVENNIA_RUNNER = os.path.join(EVENNIA_BIN, "evennia_runner.py") EVENNIA_TEMPLATE = os.path.join(EVENNIA_ROOT, "game_template") -EVENNIA_VERSION = "Unknown" TWISTED_BINARY = "twistd" # Game directory structure @@ -57,8 +56,10 @@ DJANGO_MIN = '1.7' DJANGO_REC = '1.7' # add Evennia root and bin dir to PYTHONPATH -sys.path.insert(0, EVENNIA_ROOT) - +# note that we want to remove bin/ (path[0]) from +# pythonpath since there is otherwise a clash over +# the name evennia +sys.path[0] = EVENNIA_ROOT #------------------------------------------------------------ # @@ -66,30 +67,29 @@ sys.path.insert(0, EVENNIA_ROOT) # #------------------------------------------------------------ -WELCOME_MESSAGE = \ - """ - Welcome to Evennia! - - No previous setting file was found so we created a fresh - settings.py file for you. No database was created. You may edit - the settings file now if you like, but you don't have to touch - anything if you just want to quickly get started. - - Once you are ready to continue, run evennia.py again to - initialize the database and a third time to start the server. - - The first time the server starts it will set things up for you. - Make sure to create a superuser when asked. The superuser's - email-address does not have to exist. - """ - CREATED_NEW_GAMEDIR = \ """ - ... Created new Evennia game directory '{gamedir}'. + Welcome to Evennia! + Created a new Evennia game directory '{gamedir}'. + + You can now optionally edit your new settings file + at {settings_path}. If you don't, the defaults + will work out of the box. When ready to continue, 'cd' to your + game directory and run: + + evennia migrate + + This initializes the database. To start the server for the first + time, run: + + evennia -i start + + Make sure to create a superuser when asked for it. You should now + be able to (by default) connect to your server on server + 'localhost', port 4000 using a telnet/mud client or + http://localhost:8000 using your web browser. If things don't + work, check so those ports are open. - Inside your new game directory, you can now optionally edit - {settings_path} to suit your setup. Then run this command again - from inside the game directory to start the server. """ ERROR_NO_GAMEDIR = \ @@ -127,11 +127,11 @@ ERROR_DATABASE = \ Your database does not seem to be set up correctly. (error was '{traceback}') - Try to run + Standing in your game directory, try to run - python evennia.py + evennia migrate - to initialize the database according to your settings. + to initialize/update the database according to your settings. """ ERROR_WINDOWS_WIN32API = \ @@ -169,8 +169,8 @@ CMDLINE_HELP = \ VERSION_INFO = \ """ - Evennia {version} {about} + Evennia {version} OS: {os} Python: {python} Twisted: {twisted} @@ -187,6 +187,8 @@ ABOUT_INFO= \ Forum: http://www.evennia.com/discussions Maintainer (2010-): Griatch (griatch AT gmail DOT com) Maintainer (2006-10): Greg Taylor + + Use -h for command line options. """ HELP_ENTRY = \ @@ -360,11 +362,13 @@ def evennia_version(): with open(os.path.join(EVENNIA_ROOT, "VERSION.txt"), 'r') as f: version = f.read().strip() try: - version = "%s(GIT %s)" % (version, os.popen("git rev-parse --short HEAD").read().strip()) + version = "%s (rev %s)" % (version, check_output("git rev-parse --short HEAD", shell=True, cwd=EVENNIA_ROOT).strip()) except IOError: pass return version +EVENNIA_VERSION = evennia_version() + def create_secret_key(): """ @@ -428,7 +432,7 @@ def init_game_directory(path): set_gamedir(path) # Add gamedir to python path - sys.path.insert(0, GAMEDIR) + sys.path.insert(1, GAMEDIR) # Prepare django; set the settings location os.environ['DJANGO_SETTINGS_MODULE'] = SETTINGS_DOTPATH @@ -449,7 +453,9 @@ def init_game_directory(path): # testing the main library import. If there are errors in importing # the main library, it should show here. evennia = importlib.import_module("evennia") - evennia.init() + + if check_database(automigrate=False, exit_on_error=False): + evennia.init() # check all dependencies from evennia.utils.utils import check_evennia_dependencies @@ -477,10 +483,6 @@ def init_game_directory(path): PORTAL_LOGFILE = settings.PORTAL_LOG_FILE HTTP_LOGFILE = settings.HTTP_LOG_FILE - # This also tests the library access - from evennia.utils.utils import get_evennia_version - EVENNIA_VERSION = get_evennia_version() - # set up twisted if os.name == 'nt': # We need to handle Windows twisted separately. We create a @@ -490,7 +492,7 @@ def init_game_directory(path): TWISTED_BINARY = "twistd.bat" # add path so system can find the batfile - sys.path.insert(0, os.path.join(GAMEDIR, SERVERDIR)) + sys.path.insert(1, os.path.join(GAMEDIR, SERVERDIR)) try: importlib.import_module("win32api") @@ -522,6 +524,16 @@ def init_game_directory(path): print INFO_WINDOWS_BATFILE.format(twistd_path=twistd_path) +def getenv(): + """ + Get current environment and add PYTHONPATH + """ + sep = ";" if os.name == 'nt' else ":" + env = os.environ.copy() + env['PYTHONPATH'] = sep.join(sys.path) + return env + + def create_database(): print "\nCreating a database ...\n" django.core.management.call_command("migrate", interactive=False) @@ -533,7 +545,7 @@ def create_superuser(): django.core.management.call_command("createsuperuser", interactive=True) -def check_database(automigrate=False): +def check_database(automigrate=False, exit_on_error=True): # Check so a database exists and is accessible from django.db import DatabaseError from evennia.players.models import PlayerDB @@ -544,11 +556,14 @@ def check_database(automigrate=False): create_database() create_superuser() else: - print ERROR_DATABASE.format(traceback=e) - sys.exit() + if exit_on_error: + print ERROR_DATABASE.format(traceback=e) + sys.exit() + return False except PlayerDB.DoesNotExist: # no superuser yet. We need to create it. create_superuser() + return True def get_pid(pidfile): @@ -657,7 +672,7 @@ def run_menu(): cmdstr.extend(['--iserver', '--iportal']) # start server cmdstr.append("start") - Popen(cmdstr) + Popen(cmdstr, env=getenv()) return elif inp < 10: if inp == 5: @@ -724,7 +739,7 @@ def server_operation(mode, service, interactive, profiler): django.core.management.call_command('collectstatic', verbosity=1, interactive=False) cmdstr.extend([GAMEDIR, TWISTED_BINARY, SERVER_LOGFILE, PORTAL_LOGFILE, HTTP_LOGFILE]) # start the server - Popen(cmdstr) + Popen(cmdstr, env=getenv()) elif mode == 'reload': # restarting services @@ -828,7 +843,7 @@ def main(): help="Creates a new game directory 'name' at the current location.") parser.add_argument('-p', '--prof', action='store_true', dest='profiler', default=False, help="Start given server component under the Python profiler.") - parser.add_argument("mode", metavar="option", nargs='?', default="menu", + parser.add_argument("mode", metavar="option", nargs='?', default="help", help="Operational mode or management option. Commonly start, stop, reload, migrate, or menu (default).") parser.add_argument("service", metavar="component", nargs='?', choices=["all", "server", "portal"], default="all", help="Which server component to operate on. One of server, portal or all (default).") @@ -837,9 +852,6 @@ def main(): # handle arguments - if args.show_version: - print show_version_info() - mode, service = args.mode, args.service check_main_evennia_dependencies() @@ -847,7 +859,14 @@ def main(): if args.init: create_game_directory(args.init) print CREATED_NEW_GAMEDIR.format(gamedir=args.init, - settings_path=SETTINGS_PATH) + settings_path=os.path.join(args.init, SETTINGS_PATH)) + sys.exit() + + if args.show_version: + print show_version_info(mode=="help") + sys.exit() + if mode == "help": + print ABOUT_INFO sys.exit() # this must be done first - it sets up all the global properties @@ -856,7 +875,6 @@ def main(): if mode == 'menu': # launch menu for operation - check_database(True) run_menu() elif mode in ('start', 'reload', 'stop'): # operate the server directly diff --git a/bin/evennia_runner.py b/bin/evennia_runner.py index d70aa1b745..693eb7ece7 100644 --- a/bin/evennia_runner.py +++ b/bin/evennia_runner.py @@ -82,6 +82,16 @@ def set_restart_mode(restart_file, flag="reload"): f.write(str(flag)) +def getenv(): + """ + Get current environment and add PYTHONPATH + """ + sep = ";" if os.name == "nt" else ":" + env = os.environ.copy() + env['PYTHONPATH'] = sep.join(sys.path) + return env + + def get_restart_mode(restart_file): """ Parse the server/portal restart status @@ -129,7 +139,7 @@ def start_services(server_argv, portal_argv): def server_waiter(queue): try: - rc = Popen(server_argv).wait() + rc = Popen(server_argv, env=getenv()) except Exception, e: print PROCESS_ERROR.format(component="Server", traceback=e) return @@ -138,7 +148,7 @@ def start_services(server_argv, portal_argv): def portal_waiter(queue): try: - rc = Popen(portal_argv).wait() + rc = Popen(portal_argv, env=getenv()) except Exception, e: print PROCESS_ERROR.format(component="Portal", traceback=e) return @@ -153,7 +163,7 @@ def start_services(server_argv, portal_argv): else: # normal operation: start portal as a daemon; # we don't care to monitor it for restart - PORTAL = Popen(portal_argv) + PORTAL = Popen(portal_argv, env=getenv()) except IOError, e: print PROCESS_IOERROR.format(component="Portal", traceback=e) return @@ -223,7 +233,7 @@ def main(): global SERVER_RESTART, PORTAL_RESTART GAMEDIR = args.gamedir - sys.path.insert(0, os.path.join(GAMEDIR, SERVERDIR)) + sys.path.insert(1, os.path.join(GAMEDIR, SERVERDIR)) SERVER_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "server.pid") PORTAL_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "portal.pid") diff --git a/evennia/__init__.py b/evennia/__init__.py index d12b57f5dd..a397577931 100644 --- a/evennia/__init__.py +++ b/evennia/__init__.py @@ -54,7 +54,6 @@ create_message = None lockfuncs = None tickerhandler = None logger = None -utils = None gametime = None ansi = None spawn = None @@ -125,7 +124,6 @@ def init(): from locks import lockfuncs from scripts.tickerhandler import TICKER_HANDLER as tickerhandler from utils import logger - from utils import utils from utils import gametime from utils import ansi from utils.spawner import spawn diff --git a/evennia/commands/default/player.py b/evennia/commands/default/player.py index ac33a00048..05cdfab23a 100644 --- a/evennia/commands/default/player.py +++ b/evennia/commands/default/player.py @@ -25,7 +25,8 @@ from evennia.server.sessionhandler import SESSIONS from evennia.commands.default.muxcommand import MuxPlayerCommand from evennia.utils import utils, create, search, prettytable -from settings import MAX_NR_CHARACTERS, MULTISESSION_MODE +MAX_NR_CHARACTERS = settings.MAX_NR_CHARACTERS +MULTISESSION_MODE = settings.MULTISESSION_MODE # limit symbol import for API __all__ = ("CmdOOCLook", "CmdIC", "CmdOOC", "CmdPassword", "CmdQuit", diff --git a/evennia/server/portal/portal.py b/evennia/server/portal/portal.py index ba6deaf63c..395c89e937 100644 --- a/evennia/server/portal/portal.py +++ b/evennia/server/portal/portal.py @@ -10,21 +10,25 @@ by game/evennia.py). import sys import os -if os.name == 'nt': - # For Windows batchfile we need an extra path insertion here. - sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname( - os.path.dirname(os.path.abspath(__file__)))))) -from evennia.server.webserver import EvenniaReverseProxyResource + +# add core Evennia directory +sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.dirname( + os.path.dirname(os.path.abspath(__file__)))))) +sys.path.insert(1, os.getcwd()) + from twisted.application import internet, service from twisted.internet import protocol, reactor from twisted.web import server import django - django.setup() - from django.conf import settings + +import evennia +evennia.init() + from evennia.utils.utils import get_evennia_version, mod_import, make_iter from evennia.server.portal.portalsessionhandler import PORTAL_SESSIONS +from evennia.server.webserver import EvenniaReverseProxyResource PORTAL_SERVICES_PLUGIN_MODULES = [mod_import(module) for module in make_iter(settings.PORTAL_SERVICES_PLUGIN_MODULES)] diff --git a/evennia/server/server.py b/evennia/server/server.py index 5b277a5efc..01ac9e1d60 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -10,16 +10,20 @@ by game/evennia.py). import time import sys import os -if os.name == 'nt': - # For Windows batchfile we need an extra path insertion here. - sys.path.insert(0, os.path.dirname(os.path.dirname( + +# add core Evennia directory +sys.path.insert(1, os.path.dirname(os.path.dirname( os.path.dirname(os.path.abspath(__file__))))) + from twisted.web import server, static from twisted.application import internet, service from twisted.internet import reactor, defer import django django.setup() +import evennia +evennia.init() + from django.db import connection from django.conf import settings @@ -103,7 +107,7 @@ class Evennia(object): application - an instantiated Twisted application """ - sys.path.append('.') + sys.path.insert(1, '.') # create a store of services self.services = service.IServiceCollection(application) diff --git a/evennia/server/webserver.py b/evennia/server/webserver.py index defde838be..44e6796fbe 100644 --- a/evennia/server/webserver.py +++ b/evennia/server/webserver.py @@ -20,9 +20,10 @@ from twisted.web.proxy import ReverseProxyResource from twisted.web.server import NOT_DONE_YET from twisted.web.wsgi import WSGIResource +from django.conf import settings from django.core.handlers.wsgi import WSGIHandler -from settings import UPSTREAM_IPS +UPSTREAM_IPS = settings.UPSTREAM_IPS # diff --git a/evennia/utils/__init__.py b/evennia/utils/__init__.py index 95c6c4fc23..e9aa243a1a 100644 --- a/evennia/utils/__init__.py +++ b/evennia/utils/__init__.py @@ -3,3 +3,5 @@ try: import __pypy__ as is_pypy except ImportError: is_pypy = False + +from utils import * diff --git a/evennia/utils/dummyrunner/dummyrunner.py b/evennia/utils/dummyrunner/dummyrunner.py index ee757ebc77..8aec9f7607 100644 --- a/evennia/utils/dummyrunner/dummyrunner.py +++ b/evennia/utils/dummyrunner/dummyrunner.py @@ -40,8 +40,11 @@ from twisted.internet import reactor, protocol from twisted.internet.task import LoopingCall # Tack on the root evennia directory to the python path and initialize django settings -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) -os.environ["DJANGO_SETTINGS_MODULE"] = "game.settings" + +#TODO +#sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) +#os.environ["DJANGO_SETTINGS_MODULE"] = "game.settings" + #from game import settings #try: # from django.conf import settings as settings2 diff --git a/evennia/utils/dummyrunner/memplot.py b/evennia/utils/dummyrunner/memplot.py index 796a0689a6..99aff4bbd7 100644 --- a/evennia/utils/dummyrunner/memplot.py +++ b/evennia/utils/dummyrunner/memplot.py @@ -8,8 +8,9 @@ Call this module directly to plot the log (requires matplotlib and numpy). """ import os, sys import time -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) -os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings' +#TODO! +#sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) +#os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings' import ev from evennia.utils.idmapper import base as _idmapper diff --git a/evennia/utils/dummyrunner/test_queries.py b/evennia/utils/dummyrunner/test_queries.py index 8f6c9271b6..d53db20e94 100644 --- a/evennia/utils/dummyrunner/test_queries.py +++ b/evennia/utils/dummyrunner/test_queries.py @@ -4,8 +4,8 @@ query as well as count them for optimization testing. """ import sys, os -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) -os.environ["DJANGO_SETTINGS_MODULE"] = "game.settings" +#sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) +#os.environ["DJANGO_SETTINGS_MODULE"] = "game.settings" from django.db import connection diff --git a/evennia/utils/spawner.py b/evennia/utils/spawner.py index b11411b1dc..2ad71ade57 100644 --- a/evennia/utils/spawner.py +++ b/evennia/utils/spawner.py @@ -70,8 +70,9 @@ many traits with a normal goblin. """ import os, sys, copy -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) -os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings' +#TODO +#sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) +#os.environ['DJANGO_SETTINGS_MODULE'] = 'game.settings' from django.conf import settings from random import randint diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index fa95f9f6da..d2c0896ddc 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -16,6 +16,7 @@ import textwrap import datetime import random import traceback +from subprocess import check_output from importlib import import_module from inspect import ismodule from collections import defaultdict @@ -304,6 +305,17 @@ def host_os_is(osname): def get_evennia_version(): + """ + Get the Evennia version info from the main package. + """ + version = "Unknown" + with open(os.path.join(settings.ROOT_DIR, "VERSION.txt"), 'r') as f: + version = f.read().strip() + try: + version = "%s (rev %s)" % (version, check_output("git rev-parse --short HEAD", shell=True, cwd=settings.ROOT_DIR).strip()) + except IOError: + pass + return version """ Check for the evennia version info. """ diff --git a/game_template/server/conf/portal_services_plugin.py b/game_template/server/conf/portal_services_plugins.py similarity index 100% rename from game_template/server/conf/portal_services_plugin.py rename to game_template/server/conf/portal_services_plugins.py diff --git a/game_template/server/conf/server_services_plugin.py b/game_template/server/conf/server_services_plugins.py similarity index 100% rename from game_template/server/conf/server_services_plugin.py rename to game_template/server/conf/server_services_plugins.py