From 6124bf436ebb4c20cd03113e7e5830a419049238 Mon Sep 17 00:00:00 2001 From: Joey Payne Date: Wed, 11 Nov 2015 09:10:41 -0700 Subject: [PATCH] Added preliminary export script functionality for python scripts. --- build_mac.bash | 2 +- command_line.py | 129 +++++++++++++++++++++++++++++++++------------ files/env_vars.py | 4 ++ files/settings.cfg | 3 ++ icns_info.py | 2 +- main.py | 70 ++++++++++++++++++++++-- 6 files changed, 171 insertions(+), 39 deletions(-) create mode 100644 files/env_vars.py diff --git a/build_mac.bash b/build_mac.bash index 231a4d9..9fb9a06 100755 --- a/build_mac.bash +++ b/build_mac.bash @@ -8,7 +8,7 @@ cp -rf files Web2ExeMac-CMD/files/ rm -rf build dist Web2Executable.app #sudo python build_mac_setup.py py2app --iconfile icon.icns -pyinstaller -w --hidden-import PIL.Jpeg2KImagePlugin --hidden-import PyQt4 --hidden-import configobj --hidden-import pkg_resources --distpath Web2ExeMac --onefile -n Web2Executable main.py +pyinstaller -w --hidden-import PIL.Jpeg2KImagePlugin --hidden-import PyQt4 --hidden-import PIL --hidden-import configobj --hidden-import pkg_resources --distpath Web2ExeMac --onefile -n Web2Executable main.py #sudo chown -R joey dist/Web2Executable.app #sudo chown -R joey dist/ build/ diff --git a/command_line.py b/command_line.py index 4662396..04ef655 100644 --- a/command_line.py +++ b/command_line.py @@ -117,6 +117,7 @@ class Setting(object): self.required = required self.type = type self.file_types = file_types + self.scope = kwargs.pop('scope', 'local') self.default_value = kwargs.pop('default_value', None) self.button = kwargs.pop('button', None) @@ -443,8 +444,11 @@ class CommandBase(object): setting_list = [] if p_json: json_str = '' - with codecs.open(p_json[0], 'r', encoding='utf-8') as f: - json_str = f.read() + try: + with codecs.open(p_json[0], 'r', encoding='utf-8') as f: + json_str = f.read() + except IOError: + return setting_list try: setting_list = self.load_from_json(json_str) except ValueError as e: # Json file is invalid @@ -452,41 +456,44 @@ class CommandBase(object): self.progress_text = u'{}\n'.format(e) return setting_list - def generate_json(self): + def generate_json(self, global_json=False): self.logger.info('Generating package.json...') - if 'webkit' not in self.original_packagejson: - self.original_packagejson['webkit'] = {} - if 'window' not in self.original_packagejson: - self.original_packagejson['window'] = {} - if 'webexe_settings' not in self.original_packagejson: - self.original_packagejson['webexe_settings'] = {} - dic = self.original_packagejson + dic = {'webexe_settings': {}} - for setting_name, setting in self.settings['app_settings'].items(): - if setting.value is not None: - dic[setting_name] = setting.value - if setting_name == 'keywords': - dic[setting_name] = re.findall("\w+", setting.value) + if not global_json: + dic.update({'webkit': {}, 'window': {}}) + dic.update(self.original_packagejson) + for setting_name, setting in self.settings['app_settings'].items(): + if setting.value is not None: + dic[setting_name] = setting.value + if setting_name == 'keywords': + dic[setting_name] = re.findall("\w+", setting.value) - for setting_name, setting in self.settings['window_settings'].items(): - if setting.value is not None: - if 'height' in setting.name or 'width' in setting.name: - try: - dic['window'][setting_name] = int(setting.value) - except ValueError: - pass - else: - dic['window'][setting_name] = setting.value + for setting_name, setting in self.settings['window_settings'].items(): + if setting.value is not None: + if 'height' in setting.name or 'width' in setting.name: + try: + dic['window'][setting_name] = int(setting.value) + except ValueError: + pass + else: + dic['window'][setting_name] = setting.value - for setting_name, setting in self.settings['webkit_settings'].items(): - if setting.value is not None: - dic['webkit'][setting_name] = setting.value + for setting_name, setting in self.settings['webkit_settings'].items(): + if setting.value is not None: + dic['webkit'][setting_name] = setting.value + + if not global_json: + dl_export_items = (self.settings['download_settings'].items() + + self.settings['export_settings'].items() + + self.settings['compression'].items() + + self.settings['web2exe_settings'].items()) + else: + dl_export_items = (self.settings['download_settings'].items() + + self.settings['export_settings'].items() + + self.settings['compression'].items()) - dl_export_items = (self.settings['download_settings'].items() + - self.settings['export_settings'].items() + - self.settings['compression'].items() + - self.settings['web2exe_settings'].items()) for setting_name, setting in dl_export_items: if setting.value is not None: dic['webexe_settings'][setting_name] = setting.value @@ -530,7 +537,7 @@ class CommandBase(object): def load_from_json(self, json_str): dic = json.loads(json_str) - self.original_packagejson = dic + self.original_packagejson.update(dic) setting_list = [] stack = [('root', dic)] while stack: @@ -642,10 +649,16 @@ class CommandBase(object): json_file = utils.path_join(self.project_dir(), 'package.json') + global_json = utils.get_data_file_path('files/global.json') + if self.output_package_json: with codecs.open(json_file, 'w+', encoding='utf-8') as f: f.write(self.generate_json()) + + with codecs.open(global_json, 'w+', encoding='utf-8') as f: + f.write(self.generate_json(global_json=True)) + zip_file = utils.path_join(temp_dir, self.project_name()+'.nw') app_nw_folder = utils.path_join(temp_dir, self.project_name()+'.nwf') @@ -861,16 +874,64 @@ class CommandBase(object): return ', '.join(val) return unicode(val).replace(self.project_dir()+os.path.sep, '') + + def run_script(self, script): + if not script: + return + + if os.path.exists(script): + self.progress_text = 'Executing script {}...'.format(script) + contents = '' + with codecs.open(script, 'r', encoding='utf-8') as f: + contents = f.read() + + filename, ext = os.path.splitext(script) + + export_opts = self.get_export_options() + export_dir = '{}{}{}'.format(self.output_dir(), + os.path.sep, + self.project_name()) + export_dirs = [] + for opt in export_opts: + export_dirs.append('{}{}{}'.format(export_dir, os.path.sep, opt)) + + if ext == '.py': + env_file = get_file('files/env_vars.py') + env_contents = codecs.open(env_file, 'r', encoding='utf-8').read() + env_vars = env_contents.format(proj_dir=self.project_dir(), + proj_name=self.project_name(), + export_dir=export_dir, + export_dirs=str(export_dirs)) + pycontents = '{}\n{}'.format(env_vars, contents) + exec(pycontents) + self.progress_text = 'Done executing script.' + else: + pass + + else: + self.progress_text = '\nThe script {} does not exist. Not running.'.format(script) + + def export(self): self.get_files_to_download() res = self.try_to_download_files() if res: self.make_output_dirs() + script = self.get_setting('custom_script').value + self.run_script(script) self.progress_text = '\nDone!\n' - self.progress_text = u'Output directory is {}/{}.\n'.format(self.output_dir(), - self.project_name()) + self.progress_text = u'Output directory is {}{}{}.\n'.format(self.output_dir(), + os.path.sep, + self.project_name()) self.delete_files() + def get_export_options(self): + options = [] + for setting_name, setting in self.settings['export_settings'].items(): + if setting.value is True: + options.append(setting_name) + return options + def get_files_to_download(self): self.files_to_download = [] for setting_name, setting in self.settings['export_settings'].items(): diff --git a/files/env_vars.py b/files/env_vars.py new file mode 100644 index 0000000..16172cb --- /dev/null +++ b/files/env_vars.py @@ -0,0 +1,4 @@ +PROJECT_DIR='{proj_dir}' +PROJECT_NAME='{proj_name}' +EXPORT_DIR='{export_dir}' +EXPORT_DIRS={export_dirs} diff --git a/files/settings.cfg b/files/settings.cfg index 3401eb3..ac498e8 100644 --- a/files/settings.cfg +++ b/files/settings.cfg @@ -112,6 +112,9 @@ linux_64_dir_prefix = 'node-webkit-v{}-linux-x64' [[[export_dir]]] default_value='' type='string' + [[[custom_script]]] + default_value='' + type='string' [[window_settings]] [[[title]]] diff --git a/icns_info.py b/icns_info.py index ccddeb8..6c47f8a 100644 --- a/icns_info.py +++ b/icns_info.py @@ -1115,8 +1115,8 @@ class ICNSElement(Structure): image = Image.open(StringIO(data)) mode_to_bpp = {'1':1, 'L':8, 'P':8, 'RGB':24, 'RGBA':32, 'CMYK':32, 'YCbCr':24, 'I':32, 'F':32} output = StringIO() - bpp = mode_to_bpp[image.mode] image.save(output, format='PNG') + bpp = mode_to_bpp[image.mode] png_data = bytearray(output.getvalue()) icns_info = ICNSInfo() diff --git a/main.py b/main.py index bf382d5..329b012 100644 --- a/main.py +++ b/main.py @@ -547,14 +547,26 @@ class MainWindow(QtGui.QMainWindow, CommandBase): self.ex_button.setEnabled(False) self.run_in_background('make_output_dirs', self.done_making_files) + def run_custom_script(self): + script = self.get_setting('custom_script').value + self.run_script(script) + + def script_done(self): + self.ex_button.setEnabled(self.required_settings_filled()) + self.enable_ui() + def done_making_files(self): self.ex_button.setEnabled(self.required_settings_filled()) self.progress_text = 'Done Exporting.' - self.enable_ui() self.delete_files() + if self.output_err: self.show_error(self.output_err) self.enable_ui_after_error() + else: + self.progress_text = 'Running custom script...' + self.ex_button.setEnabled(False) + self.run_in_background('run_custom_script', self.script_done) def extract_files_in_background(self): self.progress_text = 'Extracting.' @@ -815,6 +827,7 @@ class MainWindow(QtGui.QMainWindow, CommandBase): if not title_input.text(): title_input.setText(proj_name) + self.load_package_json(utils.get_data_file_path('files/global.json')) self.load_package_json() default_dir = 'output' @@ -822,6 +835,9 @@ class MainWindow(QtGui.QMainWindow, CommandBase): default_dir = export_dir_setting.value or default_dir self.output_line.setText(default_dir) + script_setting = self.get_setting('custom_script') + self.script_line.setText(script_setting.value) + self.set_window_icon() self.open_export_button.setEnabled(True) self.update_json = True @@ -848,6 +864,18 @@ class MainWindow(QtGui.QMainWindow, CommandBase): text_obj.setText(file_path) setting.last_value = file_path + def get_file_reg(self, obj, text_obj, setting, file_types, *args, **kwargs): + file_path, _ = QtGui.QFileDialog.getOpenFileName(self, 'Choose File', + (setting.last_value or + self.project_dir() or + QtCore.QDir.currentPath()), + file_types) + if file_path: + file_path = os.path.abspath(file_path) # fixes an issue with windows paths + file_path = file_path.replace(self.project_dir()+os.path.sep, '') + text_obj.setText(file_path) + setting.last_value = file_path + def get_folder(self, obj, text_obj, setting, *args, **kwargs): folder = QtGui.QFileDialog.getExistingDirectory(self, 'Choose Folder', (setting.last_value or @@ -916,9 +944,40 @@ class MainWindow(QtGui.QMainWindow, CommandBase): output_layout.addWidget(output_label) output_layout.addWidget(self.output_line) output_layout.addWidget(output_button) + + script_layout = QtGui.QHBoxLayout() + + script_label = QtGui.QLabel('Execute Script:') + + self.script_line = QtGui.QLineEdit() + self.script_line.setReadOnly(True) + + script_setting = self.get_setting('custom_script') + + self.script_line.textChanged.connect(self.call_with_object('setting_changed', + self.script_line, + script_setting)) + self.script_line.setStatusTip('The script to execute after a project was successfully exported.') + script_button = QtGui.QPushButton('...') + + file_types = ['*.py'] + + if platform.system() == 'Windows': + file_types.append('*.bat') + else: + file_types.extend(['*.bash', '*.sh', '*.zsh']) + + script_button.clicked.connect(self.call_with_object('get_file_reg', script_button, + self.script_line, script_setting, + ' '.join(file_types))) + script_layout.addWidget(script_label) + script_layout.addWidget(self.script_line) + script_layout.addWidget(script_button) + vbox = QtGui.QVBoxLayout() vbox.addLayout(vlayout) vbox.addLayout(output_layout) + vbox.addLayout(script_layout) group_box.setLayout(vbox) return group_box @@ -1127,9 +1186,14 @@ class MainWindow(QtGui.QMainWindow, CommandBase): if self.update_json: json_file = utils.path_join(self.project_dir(), 'package.json') + global_json = utils.get_data_file_path('files/global.json') + with codecs.open(json_file, 'w+', encoding='utf-8') as f: f.write(self.generate_json()) + with codecs.open(global_json, 'w+', encoding='utf-8') as f: + f.write(self.generate_json(global_json=True)) + self.ex_button.setEnabled(self.required_settings_filled()) def project_path_changed(self, text): @@ -1235,8 +1299,8 @@ class MainWindow(QtGui.QMainWindow, CommandBase): def _update_range_label(self, label, value): label.setText(unicode(value)) - def load_package_json(self): - setting_list = super(MainWindow, self).load_package_json() + def load_package_json(self, json_path=None): + setting_list = super(MainWindow, self).load_package_json(json_path) for setting in setting_list: setting_field = self.find_child_by_name(setting.name) if setting_field: