From 1a96b89e78dae0a0d47f3947e063ff17ff0e9e41 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Tue, 22 Nov 2011 11:30:48 -0500 Subject: [PATCH 1/9] Properly set exceptions, instead of simply returning NULL --- overviewer_core/src/iterate.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 0fc1109..30625c0 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -45,44 +45,44 @@ PyObject *init_chunk_render(PyObject *self, PyObject *args) { textures = PyImport_ImportModule("overviewer_core.textures"); /* ensure none of these pointers are NULL */ if ((!textures)) { - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to import overviewer_core.textures"); } chunk_mod = PyImport_ImportModule("overviewer_core.chunk"); /* ensure none of these pointers are NULL */ if ((!chunk_mod)) { - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to import overviewer_core.chunk"); } blockmap = PyObject_GetAttrString(textures, "blockmap"); if (!blockmap) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.blockmap"); tmp = PyObject_GetAttrString(textures, "max_blockid"); if (!tmp) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.max_blockid"); max_blockid = PyInt_AsLong(tmp); tmp = PyObject_GetAttrString(textures, "max_data"); if (!tmp) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.max_blockid"); max_data = PyInt_AsLong(tmp); /* assemble the property table */ known_blocks = PyObject_GetAttrString(textures, "known_blocks"); if (!known_blocks) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.known_blocks"); transparent_blocks = PyObject_GetAttrString(textures, "transparent_blocks"); if (!transparent_blocks) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.transparent_blocks"); solid_blocks = PyObject_GetAttrString(textures, "solid_blocks"); if (!solid_blocks) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.solid_blocks"); fluid_blocks = PyObject_GetAttrString(textures, "fluid_blocks"); if (!fluid_blocks) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.fluid_blocks"); nospawn_blocks = PyObject_GetAttrString(textures, "nospawn_blocks"); if (!nospawn_blocks) - return NULL; + return PyErr_Format(PyExc_ImportError, "Failed to get textures.nospawn_blocks"); block_properties = calloc(max_blockid, sizeof(unsigned char)); for (i = 0; i < max_blockid; i++) { @@ -359,7 +359,7 @@ chunk_render(PyObject *self, PyObject *args) { PyObject *t = NULL; if (!PyArg_ParseTuple(args, "OOiiO", &state.self, &state.img, &xoff, &yoff, &state.blockdata_expanded)) - return NULL; + return PyErr_Format(PyExc_ValueError, "Failed to ParseTuple"); /* fill in important modules */ state.textures = textures; @@ -370,7 +370,7 @@ chunk_render(PyObject *self, PyObject *args) { state.rendermode = rendermode = render_mode_create(PyString_AsString(rendermode_py), &state); Py_DECREF(rendermode_py); if (rendermode == NULL) { - return NULL; + return PyErr_Format(PyExc_ValueError, "Failed to create render mode"); } /* get the image size */ From 9b36dfc237d428db65e8839868067926f8c50502 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Tue, 22 Nov 2011 11:33:11 -0500 Subject: [PATCH 2/9] Fix reference leak --- overviewer_core/src/iterate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 30625c0..c6d8652 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -62,10 +62,13 @@ PyObject *init_chunk_render(PyObject *self, PyObject *args) { if (!tmp) return PyErr_Format(PyExc_ImportError, "Failed to get textures.max_blockid"); max_blockid = PyInt_AsLong(tmp); + Py_DECREF(tmp); + tmp = PyObject_GetAttrString(textures, "max_data"); if (!tmp) return PyErr_Format(PyExc_ImportError, "Failed to get textures.max_blockid"); max_data = PyInt_AsLong(tmp); + Py_DECREF(tmp); /* assemble the property table */ known_blocks = PyObject_GetAttrString(textures, "known_blocks"); From 4739f4af93347ed0fb9c4cc0032129fc559bd08c Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Tue, 22 Nov 2011 12:25:02 -0500 Subject: [PATCH 3/9] More specific rendermode error messages --- overviewer_core/src/iterate.c | 3 ++- overviewer_core/src/rendermodes.c | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index c6d8652..5b62941 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -373,7 +373,8 @@ chunk_render(PyObject *self, PyObject *args) { state.rendermode = rendermode = render_mode_create(PyString_AsString(rendermode_py), &state); Py_DECREF(rendermode_py); if (rendermode == NULL) { - return PyErr_Format(PyExc_ValueError, "Failed to create render mode"); + return NULL; // note that render_mode_create will + // set PyErr. No need to set it here } /* get the image size */ diff --git a/overviewer_core/src/rendermodes.c b/overviewer_core/src/rendermodes.c index dd0848f..ceaf9d4 100644 --- a/overviewer_core/src/rendermodes.c +++ b/overviewer_core/src/rendermodes.c @@ -124,23 +124,23 @@ RenderMode *render_mode_create(const char *mode, RenderState *state) { iface = render_mode_find_interface(mode); if (iface == NULL) - return NULL; + return PyErr_Format(PyExc_RuntimeError, "Failed to find rendermode interface"); options = render_mode_create_options(mode); if (options == NULL) - return NULL; + return PyErr_Format(PyExc_RuntimeError, "Failed to create rendermode options"); ret = calloc(1, sizeof(RenderMode)); if (ret == NULL) { Py_DECREF(options); - return NULL; + return PyErr_Format(PyExc_RuntimeError, "Failed to alloc a rendermode"); } ret->mode = calloc(1, iface->data_size); if (ret->mode == NULL) { Py_DECREF(options); free(ret); - return NULL; + return PyErr_Format(PyExc_RuntimeError, "Failed to alloc rendermode data"); } ret->iface = iface; @@ -150,7 +150,7 @@ RenderMode *render_mode_create(const char *mode, RenderState *state) { Py_DECREF(options); free(ret->mode); free(ret); - return NULL; + return PyErr_Format(PyExc_RuntimeError, "Failed to start rendermode interface"); } Py_DECREF(options); From bca7867b866f031ddadb4f4c87c15bf56421932d Mon Sep 17 00:00:00 2001 From: Aaron Griffith Date: Tue, 22 Nov 2011 17:32:47 -0500 Subject: [PATCH 4/9] pushed exception setting into the relevant function, removed redundant exceptions The following functions set exceptions automatically: PyImport_ImportModule, PyObject_GetAttrString, PyArg_ParseTuple. All the exception setting functions in c_overviewer should act the same way and set their own exceptions before returning. Notably, PyDict_GetItemString does *not* set exceptions, so it is handled specially in render_mode_find_interface. --- overviewer_core/src/iterate.c | 26 +++++++++++++------------- overviewer_core/src/rendermodes.c | 14 +++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 5b62941..adc790d 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -45,47 +45,47 @@ PyObject *init_chunk_render(PyObject *self, PyObject *args) { textures = PyImport_ImportModule("overviewer_core.textures"); /* ensure none of these pointers are NULL */ if ((!textures)) { - return PyErr_Format(PyExc_ImportError, "Failed to import overviewer_core.textures"); + return NULL; } - + chunk_mod = PyImport_ImportModule("overviewer_core.chunk"); /* ensure none of these pointers are NULL */ if ((!chunk_mod)) { - return PyErr_Format(PyExc_ImportError, "Failed to import overviewer_core.chunk"); + return NULL; } blockmap = PyObject_GetAttrString(textures, "blockmap"); if (!blockmap) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.blockmap"); + return NULL; tmp = PyObject_GetAttrString(textures, "max_blockid"); if (!tmp) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.max_blockid"); + return NULL; max_blockid = PyInt_AsLong(tmp); Py_DECREF(tmp); tmp = PyObject_GetAttrString(textures, "max_data"); if (!tmp) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.max_blockid"); + return NULL; max_data = PyInt_AsLong(tmp); Py_DECREF(tmp); /* assemble the property table */ known_blocks = PyObject_GetAttrString(textures, "known_blocks"); if (!known_blocks) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.known_blocks"); + return NULL; transparent_blocks = PyObject_GetAttrString(textures, "transparent_blocks"); if (!transparent_blocks) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.transparent_blocks"); + return NULL; solid_blocks = PyObject_GetAttrString(textures, "solid_blocks"); if (!solid_blocks) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.solid_blocks"); + return NULL; fluid_blocks = PyObject_GetAttrString(textures, "fluid_blocks"); if (!fluid_blocks) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.fluid_blocks"); + return NULL; nospawn_blocks = PyObject_GetAttrString(textures, "nospawn_blocks"); if (!nospawn_blocks) - return PyErr_Format(PyExc_ImportError, "Failed to get textures.nospawn_blocks"); + return NULL; block_properties = calloc(max_blockid, sizeof(unsigned char)); for (i = 0; i < max_blockid; i++) { @@ -104,7 +104,7 @@ PyObject *init_chunk_render(PyObject *self, PyObject *args) { Py_DECREF(block); } - + Py_RETURN_NONE; } @@ -362,7 +362,7 @@ chunk_render(PyObject *self, PyObject *args) { PyObject *t = NULL; if (!PyArg_ParseTuple(args, "OOiiO", &state.self, &state.img, &xoff, &yoff, &state.blockdata_expanded)) - return PyErr_Format(PyExc_ValueError, "Failed to ParseTuple"); + return NULL; /* fill in important modules */ state.textures = textures; diff --git a/overviewer_core/src/rendermodes.c b/overviewer_core/src/rendermodes.c index ceaf9d4..fb523fb 100644 --- a/overviewer_core/src/rendermodes.c +++ b/overviewer_core/src/rendermodes.c @@ -106,13 +106,13 @@ render_mode_find_interface(const char *mode) { /* check for custom modes */ custom = PyDict_GetItemString(custom_render_modes, mode); if (custom == NULL) - return NULL; + return PyErr_Format(PyExc_RuntimeError, "Failed to find rendermode interface (custom not found)"); custom = PyDict_GetItemString(custom, "parent"); if (custom == NULL) - return NULL; + return PyErr_Format(PyExc_RuntimeError, "Failed to find rendermode interface (parent not found)"); custom_parent = PyString_AsString(custom); if (custom_parent == NULL) - return NULL; + return NULL; // PyString_AsString sets an exception return render_mode_find_interface(custom_parent); } @@ -124,11 +124,11 @@ RenderMode *render_mode_create(const char *mode, RenderState *state) { iface = render_mode_find_interface(mode); if (iface == NULL) - return PyErr_Format(PyExc_RuntimeError, "Failed to find rendermode interface"); + return NULL; options = render_mode_create_options(mode); if (options == NULL) - return PyErr_Format(PyExc_RuntimeError, "Failed to create rendermode options"); + return NULL; ret = calloc(1, sizeof(RenderMode)); if (ret == NULL) { @@ -150,13 +150,13 @@ RenderMode *render_mode_create(const char *mode, RenderState *state) { Py_DECREF(options); free(ret->mode); free(ret); - return PyErr_Format(PyExc_RuntimeError, "Failed to start rendermode interface"); + return NULL; } Py_DECREF(options); return ret; } - + void render_mode_destroy(RenderMode *self) { self->iface->finish(self->mode, self->state); free(self->mode); From 82864a1622c668410beeae716dbcca8c8deed7ca Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Thu, 24 Nov 2011 23:30:33 -0500 Subject: [PATCH 5/9] added an faq entry on copying tiles to another destionation also added a link to the faq under help on the index page also clarified the faq entry about adding new features or changing texture packs also fixed a typo --- docs/faq.rst | 38 ++++++++++++++++++++++++++++++++++--- docs/index.rst | 5 ++++- overviewer_core/quadtree.py | 2 +- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 213d1d9..a034821 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -8,6 +8,36 @@ Frequently Asked Questions General Questions ================= +When my map expands, I see remnants of another zoom level +--------------------------------------------------------- + +When your map expands ("Your map seems to have expanded beyond its previous +bounds") you may see tiles at a zoom level that shouldn't be there, usually +around the borders. This is probably not a bug, but is typically caused by +copying the map tiles from their render destination to another location (such as +a web server). + +When you're copying the rendered map, you need to be sure files that *don't* +exist in the source are *deleted* in the destination. + +Explanation: When Overviewer re-arranges tiles for another zoom level, it moves +some tiles tiles at a particular zoom level and placed them at a higher zoom +level. The tiles that used to be at that zoom level should no longer exist +there, but if you're copying tiles, there is no mechanism to *delete* those +files at the destination. + +If that explanation doesn't make full sense, then just know that you must do one +of the following: + +* Render the tiles directly to the destination + +* Copy the tiles from the render destination in a way that deletes extra files, + such as using ``rsync`` with ``--delete`` + +* Erase and re-copy the files at the final destination when the map expands. + Map expansions double the width and height of the map, so you will eventually + hit a map size that is unlikely to need another level. + The full map doesn't display even when fully zoomed out! -------------------------------------------------------- @@ -16,11 +46,13 @@ commandline or in settings.py? If so, try removing it, or increasing the value you set. It's quite likely you don't need it at all. See the documentation for the :option:`zoom <-z>` option. -You've added a few feature, but it's not showing up on my map! --------------------------------------------------------------- +You've added a few feature or changed textures, but it's not showing up on my map! +---------------------------------------------------------------------------------- Some new features will only show up in newly-rendered areas. Use the -:option:`--forcerender` option to update the entire map. +:option:`--forcerender` option to update the entire map. If you have a really +large map and don't want to re-render everything, take a look at +the :option:`--stochastic-render` option. How do I use this on CentOS 5? ------------------------------ diff --git a/docs/index.rst b/docs/index.rst index b471a14..853f5e4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -86,7 +86,10 @@ Help **IF YOU NEED HELP COMPILING OR RUNNING THE OVERVIEWER** feel free to chat with us live in IRC: #overviewer on Freenode. There's usually someone on there that can help you out. Not familiar with IRC? `Use the web client -`_. +`_. (If there's no response, +try a different time of day; we have to sleep sometime) + +Also check our :doc:`Frequently Asked Questions ` page. If you think you've found a bug or other issue, file an issue on our `Issue Tracker `_. Filing or diff --git a/overviewer_core/quadtree.py b/overviewer_core/quadtree.py index a8da76d..5f2aa27 100644 --- a/overviewer_core/quadtree.py +++ b/overviewer_core/quadtree.py @@ -196,7 +196,7 @@ class QuadtreeGen(object): curdepth = self._get_cur_depth() if curdepth != -1: if self.p > curdepth: - logging.warning("Your map seemes to have expanded beyond its previous bounds.") + logging.warning("Your map seems to have expanded beyond its previous bounds.") logging.warning( "Doing some tile re-arrangements... just a sec...") for _ in xrange(self.p-curdepth): self._increase_depth() From 35890bb52c51b9128185ff2c9f4a5bcbd2cf30ec Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Fri, 25 Nov 2011 00:46:50 -0500 Subject: [PATCH 6/9] minor wording change (forgot to save for the last commit) --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 853f5e4..e335aed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -86,8 +86,8 @@ Help **IF YOU NEED HELP COMPILING OR RUNNING THE OVERVIEWER** feel free to chat with us live in IRC: #overviewer on Freenode. There's usually someone on there that can help you out. Not familiar with IRC? `Use the web client -`_. (If there's no response, -try a different time of day; we have to sleep sometime) +`_. (If there's no immediate +response, wait around or try a different time of day; we have to sleep sometime) Also check our :doc:`Frequently Asked Questions ` page. From a9bef297e72a0c3c5b8946f59c2da85a3f0174c3 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Fri, 25 Nov 2011 09:52:39 -0500 Subject: [PATCH 7/9] added note about python3 compatibility --- docs/faq.rst | 10 +++++----- docs/index.rst | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index a034821..1fc9130 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -20,11 +20,11 @@ a web server). When you're copying the rendered map, you need to be sure files that *don't* exist in the source are *deleted* in the destination. -Explanation: When Overviewer re-arranges tiles for another zoom level, it moves -some tiles tiles at a particular zoom level and placed them at a higher zoom -level. The tiles that used to be at that zoom level should no longer exist -there, but if you're copying tiles, there is no mechanism to *delete* those -files at the destination. +Explanation: When Overviewer re-arranges tiles to make room for another zoom +level, it moves some tiles tiles at a particular zoom level and places them at a +higher zoom level. The tiles that used to be at that zoom level should no longer +exist there, but if you're copying tiles, there is no mechanism to *delete* +those files at the copy destination. If that explanation doesn't make full sense, then just know that you must do one of the following: diff --git a/docs/index.rst b/docs/index.rst index e335aed..d2c717c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -50,7 +50,7 @@ Requirements This is a quick list of what's required to run The Overviewer. It runs on Windows, Mac, and Linux as long as you have these software packages installed: -* Python 2.6 or 2.7 +* Python 2.6 or 2.7 (we are *not* yet compatible with Python 3.x) * PIL (Python Imaging Library) From 2dcf22294f8d81b5666633ca224ed59870d26f63 Mon Sep 17 00:00:00 2001 From: Thomas Lake Date: Fri, 25 Nov 2011 16:30:56 +0000 Subject: [PATCH 8/9] Rearrange version checks in Overviewer.py --- overviewer.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/overviewer.py b/overviewer.py index acf48e3..6d9d6c5 100755 --- a/overviewer.py +++ b/overviewer.py @@ -18,6 +18,12 @@ import platform import sys +if not (sys.version_info[0] == 2 and sys.version_info[1] >= 6): + print "Sorry, the Overviewer requires at least Python 2.6 to run" + if sys.version_info[0] >= 3: + print "and will not run on Python 3.0 or later" + sys.exit(1) + if platform.system() == 'Windows': try: import ctypes @@ -34,12 +40,6 @@ if platform.system() == 'Windows': except Exception: pass -if not (sys.version_info[0] == 2 and sys.version_info[1] >= 6): - print "Sorry, the Overviewer requires at least Python 2.6 to run" - if sys.version_info[0] >= 3: - print "and will not run on Python 3.0 or later" - sys.exit(1) - import os import os.path import re From 59c18121542056307d6cb2d0ac7ddb75051b3f34 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Fri, 25 Nov 2011 16:13:36 -0500 Subject: [PATCH 9/9] Reworked handling of bare consoles Now the "Please run overviewer from the command line" message will only be displayed in select cases. This supports cases when users want to give all the correct arguments to overviewer via a shortcut or something similar. In these cases, a 'Press [enter] to close this window' message will still be displayed. --- overviewer.py | 87 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/overviewer.py b/overviewer.py index 6d9d6c5..333c5ed 100755 --- a/overviewer.py +++ b/overviewer.py @@ -24,18 +24,15 @@ if not (sys.version_info[0] == 2 and sys.version_info[1] >= 6): print "and will not run on Python 3.0 or later" sys.exit(1) +isBareConsole = False + if platform.system() == 'Windows': try: import ctypes GetConsoleProcessList = ctypes.windll.kernel32.GetConsoleProcessList num = GetConsoleProcessList(ctypes.byref(ctypes.c_int(0)), ctypes.c_int(1)) if (num == 1): - print "The Overviewer is a console program. Please open a Windows command prompt" - print "first and run Overviewer from there. Further documentation is available at" - print "http://docs.overviewer.org/\n" - print "Press [Enter] to close this window." - raw_input() - sys.exit(1) + isBareConsole = True except Exception: pass @@ -49,6 +46,35 @@ import time import logging from overviewer_core import util +def doExit(msg=None, code=1, wait=None, consoleMsg=True): + '''Exits Overviewer. If `wait` is None, the default + will be true is 'isBareConsole' is true''' + global isBareConsole + if msg: + print msg + + if wait == None: + if isBareConsole: + if consoleMsg: + print "\n" + print "The Overviewer is a console program. Please open a Windows command prompt" + print "first and run Overviewer from there. Further documentation is available at" + print "http://docs.overviewer.org/\n" + print "Press [Enter] to close this window." + raw_input() + else: + if wait: + if consoleMsg: + print "\n" + print "The Overviewer is a console program. Please open a Windows command prompt" + print "first and run Overviewer from there. Further documentation is available at" + print "http://docs.overviewer.org/\n" + print "Press [Enter] to close this window." + raw_input() + + sys.exit(code) + + this_dir = util.get_program_path() # make sure the c_overviewer extension is available @@ -61,7 +87,7 @@ except ImportError: print "Something has gone wrong importing the c_overviewer extension. Please" print "make sure the 2008 and 2010 redistributable packages from Microsoft" print "are installed." - sys.exit(1) + doExit() ## try to find the build extension @@ -69,7 +95,7 @@ except ImportError: if os.path.exists(ext): print "Something has gone wrong importing the c_overviewer extension. Please" print "make sure it is up-to-date (clean and rebuild)" - sys.exit(1) + doExit() import traceback traceback.print_exc() @@ -77,7 +103,7 @@ except ImportError: print "" print "You need to compile the c_overviewer module to run Minecraft Overviewer." print "Run `python setup.py build`, or see the README for details." - sys.exit(1) + doExit() from overviewer_core import textures @@ -93,10 +119,10 @@ elif "extension_version" in dir(c_overviewer): l = lines[0] if int(l.split()[2].strip()) != c_overviewer.extension_version(): print "Please rebuild your c_overviewer module. It is out of date!" - sys.exit(1) + doExit(code=1, consoleMsg=True) else: print "Please rebuild your c_overviewer module. It is out of date!" - sys.exit(1) + doExit() from overviewer_core.configParser import ConfigOptionParser from overviewer_core import optimizeimages, world, quadtree @@ -225,7 +251,7 @@ def main(): except Exception: print "version info not found" pass - sys.exit(0) + doExit(code=0, consoleMsg=False) # setup c_overviewer rendermode customs / options for mode in builtin_custom_rendermodes: @@ -245,7 +271,7 @@ def main(): if options.list_rendermodes: list_rendermodes() - sys.exit(0) + doExit(code=0, consoleMsg=False) if options.check_terrain: import hashlib @@ -257,22 +283,22 @@ def main(): f = _find_file("terrain.png", verbose=True) except IOError: logging.error("Could not find the file terrain.png") - sys.exit(1) + doExit(code=1, consoleMsg=False) h = hashlib.sha1() h.update(f.read()) logging.info("Hash of terrain.png file is: `%s`", h.hexdigest()) - sys.exit(0) + doExit(code=0, consoleMsg=False) if options.advanced_help: parser.advanced_help() - sys.exit(0) + doExit(code=0, consoleMsg=False) if len(args) < 1: logging.error("You need to give me your world number or directory") parser.print_help() list_worlds() - sys.exit(1) + doExit(code=1, consoleMsg=True) worlddir = os.path.expanduser(args[0]) if len(args) > 2: @@ -284,7 +310,7 @@ def main(): if os.path.exists(" ".join(args[start:end])): logging.warning("It looks like you meant to specify \"%s\" as your world dir or your output\n\ dir but you forgot to put quotes around the directory, since it contains spaces." % " ".join(args[start:end])) - sys.exit(1) + doExit(code=1, consoleMsg=False) if not os.path.exists(worlddir): # world given is either world number, or name @@ -294,7 +320,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces. if not worlds: parser.print_help() logging.error("Invalid world path") - sys.exit(1) + doExit(code=1, consoleMsg=False) try: worldnum = int(worlddir) @@ -307,32 +333,32 @@ dir but you forgot to put quotes around the directory, since it contains spaces. # it's not a number, name, or path parser.print_help() logging.error("Invalid world name or path") - sys.exit(1) + doExit(code=1, consoleMsg=False) except KeyError: # it was an invalid number parser.print_help() logging.error("Invalid world number") - sys.exit(1) + doExit(code=1, consoleMsg=False) # final sanity check for worlddir if not os.path.exists(os.path.join(worlddir, 'level.dat')): logging.error("Invalid world path -- does not contain level.dat") - sys.exit(1) + doExit(code=1, consoleMsg=False) if len(args) < 2: logging.error("Where do you want to save the tiles?") - sys.exit(1) + doExit(code=1, consoleMsg=False) elif len(args) > 2: parser.print_help() logging.error("Sorry, you specified too many arguments") - sys.exit(1) + doExit(code=1, consoleMsg=False) destdir = os.path.expanduser(args[1]) if options.display_config: # just display the config file and exit parser.display_config() - sys.exit(0) + doExit(code=0, consoleMsg=False) if options.regionlist: @@ -365,11 +391,11 @@ dir but you forgot to put quotes around the directory, since it contains spaces. except IOError as e: logging.error("Unable to open file %s to use for changelist." % options.changelist) logging.error("I/O Error: %s" % e.strerror) - sys.exit(1) + doExit(code=1, consoleMsg=False) if options.changelist_format != "auto" and not options.changelist: logging.error("changelist_format specified without changelist.") - sys.exit(1) + doExit(code=1, consoleMsg=False) if options.changelist_format == "auto": options.changelist_format = "relative" @@ -385,7 +411,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces. textures.generate(path=options.textures_path) except IOError, e: logging.error(str(e)) - sys.exit(1) + doExit(code=1, consoleMsg=False) # First do world-level preprocessing w = world.World(worlddir, destdir, useBiomeData=useBiomeData, regionlist=regionlist, north_direction=north_direction) @@ -397,7 +423,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces. logging.error("Overviewer.dat gives previous north-direction as "+w.persistentData['north_direction']) logging.error("Requested north-direction was "+north_direction) logging.error("To change north-direction of an existing render, --forcerender must be specified") - sys.exit(1) + doExit(code=1, consoleMsg=False) w.go(options.procs) @@ -529,8 +555,9 @@ if __name__ == "__main__": except Exception, e: if e.message == "Exiting": logging.info("Exiting...") - sys.exit(0) + doExit(code=0, wait=False) logging.exception("""An error has occurred. This may be a bug. Please let us know! See http://docs.overviewer.org/en/latest/index.html#help This is the error that occurred:""") + doExit(code=1, consoleMsg=False)