From 793eaeed6586d0e52fc3671e9f9b329268b0a487 Mon Sep 17 00:00:00 2001 From: Kevin Cathcart Date: Tue, 28 Nov 2017 09:36:32 -0500 Subject: [PATCH] Create a utils file for low level helpers like path utilities --- EntranceRandomizer.py | 7 +++-- Gui.py | 22 ++++++--------- Main.py | 44 ++--------------------------- Rom.py | 3 +- Utils.py | 64 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 59 deletions(-) create mode 100644 Utils.py diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index 80b7e213..7b195486 100644 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -7,6 +7,7 @@ import sys from Main import main from Gui import guiMain +from Utils import is_bundled class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter): @@ -190,9 +191,9 @@ if __name__ == '__main__': ''') args = parser.parse_args() - if hasattr(sys, 'frozen') and len(sys.argv) == 1 : - # for the Precompiled windows build, if we have no arguments, the user - # probably wants the gui. Users of the windows build who want the command line + if is_bundled and len(sys.argv) == 1 : + # for the bundled builds, if we have no arguments, the user + # probably wants the gui. Users of the bundled build who want the command line # interface shouuld specify at least one option, possibly setting a value to a # default if they like all the defaults guiMain() diff --git a/Gui.py b/Gui.py index 6ddc29ca..17214273 100644 --- a/Gui.py +++ b/Gui.py @@ -1,4 +1,5 @@ -from Main import main, __version__ as ESVersion, get_output_path +from Main import main, __version__ as ESVersion +from Utils import is_bundled, local_path, output_path, open_file from argparse import Namespace import random import subprocess @@ -218,13 +219,13 @@ def guiMain(args=None): generateButton = Button(bottomFrame, text='Generate Patched Rom', command=generateRom) def open_output(): - open_file(get_output_path()) + open_file(output_path('')) openOutputButton = Button(farBottomFrame, text='Open Output Directory', command=open_output) - if os.path.exists('README.html'): + if os.path.exists(local_path('README.html')): def open_readme(): - open_file('README.html') + open_file(local_path('README.html')) openReadmeButton = Button(farBottomFrame, text='Open Documentation', command=open_readme) openReadmeButton.pack(side=LEFT) @@ -273,17 +274,10 @@ def guiMain(args=None): mainWindow.mainloop() -def open_file(filename): - if sys.platform == 'win32': - os.startfile(filename) - else: - open_Command = 'open' if sys.plaform == 'darwin' else 'xdg-open' - subprocess.call([open_command, filename]) - def set_icon(window): - er16 = PhotoImage(file='data/ER16.gif') - er32 = PhotoImage(file='data/ER32.gif') - er48 = PhotoImage(file='data/ER32.gif') + er16 = PhotoImage(file=local_path('data/ER16.gif')) + er32 = PhotoImage(file=local_path('data/ER32.gif')) + er48 = PhotoImage(file=local_path('data/ER32.gif')) window.tk.call('wm', 'iconphoto', window._w, er16, er32, er48) if __name__ == '__main__': diff --git a/Main.py b/Main.py index 3cbc8758..e98db109 100644 --- a/Main.py +++ b/Main.py @@ -8,12 +8,11 @@ from Items import ItemFactory from Fill import distribute_items_cutoff, distribute_items_staleness, distribute_items_restrictive, fill_restrictive, flood_items from collections import OrderedDict from ItemList import generate_itempool +from Utils import output_path import random import time import logging import json -import sys -import os __version__ = '0.5.0-dev' @@ -107,53 +106,16 @@ def main(args, seed=None): if args.jsonout: print(json.dumps({'patch': rom.patches, 'spoiler': world.spoiler.to_json()})) else: - rom.write_to_file(args.jsonout or os.path.join(get_output_path(),'%s.sfc' % outfilebase)) + rom.write_to_file(args.jsonout or output_path('%s.sfc' % outfilebase)) if args.create_spoiler and not args.jsonout: - world.spoiler.to_file(os.path.join(get_output_path(),'%s_Spoiler.txt' % outfilebase)) + world.spoiler.to_file(output_path('%s_Spoiler.txt' % outfilebase)) logger.info('Done. Enjoy.') logger.debug('Total Time: %s' % (time.clock() - start)) return world -def get_output_path(): - if get_output_path.cached_path is not None: - return get_output_path.cached_path - - if not hasattr(sys, 'frozen'): - get_output_path.cached_path = '.' - return get_output_path.cached_path - else: - # has been packaged, so cannot use CWD for output. - if sys.platform == 'win32': - #windows - import ctypes.wintypes - CSIDL_PERSONAL = 5 # My Documents - SHGFP_TYPE_CURRENT = 0 # Get current, not default value - - buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) - ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, buf) - - documents = buf.value - - elif sys.platform == 'darwin': - from AppKit import NSSearchPathForDirectoriesInDomains - # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains - NSDocumentDirectory = 9 - NSUserDomainMask = 1 - # True for expanding the tilde into a fully qualified path - documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0] - else: - raise NotImplementedError('Not supported yet') - - get_output_path.cached_path = os.path.join(documents, 'ALttPEntranceRandomizer') - if not os.path.exists(get_output_path.cached_path): - os.mkdir(get_output_path.cached_path) - return get_output_path.cached_path - -get_output_path.cached_path = None - def copy_world(world): # ToDo: Not good yet ret = World(world.shuffle, world.logic, world.mode, world.difficulty, world.timer, world.progressive, world.goal, world.algorithm, world.place_dungeon_items, world.check_beatable_only, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.keysanity) diff --git a/Rom.py b/Rom.py index bc27fa32..24fda4a6 100644 --- a/Rom.py +++ b/Rom.py @@ -2,6 +2,7 @@ from Dungeons import dungeon_music_addresses from Text import string_to_alttp_text, text_addresses, Credits from Text import Uncle_texts, Ganon1_texts, PyramidFairy_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts +from Utils import local_path import random import json import hashlib @@ -66,7 +67,7 @@ class LocalRom(object): self.buffer.extend(bytearray([0x00] * (2097152 - len(self.buffer)))) # load randomizer patches - patches = json.load(open('data/base2current.json', 'r')) + patches = json.load(open(local_path('data/base2current.json'), 'r')) for patch in patches: if isinstance(patch, dict): for baseaddress, values in patch.items(): diff --git a/Utils.py b/Utils.py new file mode 100644 index 00000000..cfc53aa0 --- /dev/null +++ b/Utils.py @@ -0,0 +1,64 @@ +import os +import sys + +def is_bundled(): + return getattr(sys, 'frozen', False) + +def local_path(path): + if local_path.cached_path is not None: + return os.path.join(local_path.cached_path, path) + + if is_bundled(): + # we are running in a bundle + local_path.cached_path = sys._MEIPASS + else: + # we are running in a normal Python environment + local_path.cached_path = os.path.dirname(os.path.abspath(__file__)) + + return os.path.join(local_path.cached_path, path) + +local_path.cached_path = None + +def output_path(path): + if output_path.cached_path is not None: + return os.path.join(output_path.cached_path, path) + + if not is_bundled(): + output_path.cached_path = '.' + return os.path.join(output_path.cached_path, path) + else: + # has been packaged, so cannot use CWD for output. + if sys.platform == 'win32': + #windows + import ctypes.wintypes + CSIDL_PERSONAL = 5 # My Documents + SHGFP_TYPE_CURRENT = 0 # Get current, not default value + + buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) + ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, buf) + + documents = buf.value + + elif sys.platform == 'darwin': + from AppKit import NSSearchPathForDirectoriesInDomains + # http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains + NSDocumentDirectory = 9 + NSUserDomainMask = 1 + # True for expanding the tilde into a fully qualified path + documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0] + else: + raise NotImplementedError('Not supported yet') + + output_path.cached_path = os.path.join(documents, 'ALttPEntranceRandomizer') + if not os.path.exists(output_path.cached_path): + os.mkdir(output_path.cached_path) + return os.path.join(output_path.cached_path, path) + +output_path.cached_path = None + +def open_file(filename): + if sys.platform == 'win32': + os.startfile(filename) + else: + open_Command = 'open' if sys.platform == 'darwin' else 'xdg-open' + subprocess.call([open_command, filename])