PrEditor 0.0.0.dev1__py2.py3-none-any.whl → 0.1.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of PrEditor might be problematic. Click here for more details.
- PrEditor-0.1.0.dist-info/LICENSE +165 -0
- PrEditor-0.1.0.dist-info/METADATA +212 -0
- PrEditor-0.1.0.dist-info/RECORD +149 -0
- {PrEditor-0.0.0.dev1.dist-info → PrEditor-0.1.0.dist-info}/WHEEL +1 -1
- PrEditor-0.1.0.dist-info/entry_points.txt +18 -0
- PrEditor-0.1.0.dist-info/top_level.txt +1 -0
- preditor/__init__.py +301 -0
- {blurdev → preditor}/__main__.py +13 -13
- preditor/about_module.py +166 -0
- preditor/cli.py +192 -0
- {blurdev → preditor}/contexts.py +119 -119
- preditor/cores/core.py +65 -0
- preditor/dccs/maya/PrEditor_maya.mod +2 -0
- preditor/dccs/maya/plug-ins/PrEditor_maya.py +108 -0
- preditor/debug.py +294 -0
- blurdev/scintilla/delayable_engine.py → preditor/delayable_engine/__init__.py +310 -299
- blurdev/scintilla/delayables/base.py → preditor/delayable_engine/delayables.py +85 -85
- {blurdev → preditor}/enum.py +728 -1003
- {blurdev → preditor}/gui/__init__.py +84 -125
- preditor/gui/app.py +159 -0
- {blurdev → preditor}/gui/codehighlighter.py +209 -219
- {blurdev → preditor}/gui/completer.py +226 -236
- {blurdev → preditor}/gui/console.py +801 -858
- {blurdev → preditor}/gui/dialog.py +200 -216
- preditor/gui/drag_tab_bar.py +190 -0
- preditor/gui/editor_chooser.py +57 -0
- {blurdev → preditor}/gui/errordialog.py +100 -97
- preditor/gui/fuzzy_search/fuzzy_search.py +93 -0
- preditor/gui/group_tab_widget/__init__.py +319 -0
- preditor/gui/group_tab_widget/grouped_tab_menu.py +35 -0
- preditor/gui/group_tab_widget/grouped_tab_models.py +108 -0
- preditor/gui/group_tab_widget/grouped_tab_widget.py +75 -0
- preditor/gui/group_tab_widget/one_tab_widget.py +54 -0
- preditor/gui/level_buttons.py +349 -0
- {blurdev → preditor}/gui/logger_window_handler.py +46 -45
- {blurdev → preditor}/gui/loggerwindow.py +1205 -1417
- {blurdev → preditor}/gui/newtabwidget.py +69 -68
- {blurdev → preditor}/gui/redmine_login_dialog.py +63 -61
- {blurdev → preditor}/gui/set_text_editor_path_dialog.py +59 -57
- preditor/gui/ui/editor_chooser.ui +93 -0
- {blurdev → preditor}/gui/ui/errordialog.ui +81 -81
- {blurdev → preditor}/gui/ui/loggerwindow.ui +1030 -864
- {blurdev → preditor}/gui/ui/redmine_login_dialog.ui +124 -124
- {blurdev → preditor}/gui/ui/set_text_editor_path_dialog.ui +149 -149
- {blurdev → preditor}/gui/window.py +183 -199
- preditor/gui/workbox_mixin.py +357 -0
- preditor/gui/workbox_text_edit.py +117 -0
- preditor/gui/workboxwidget.py +276 -0
- preditor/logging_config.py +52 -0
- preditor/osystem.py +401 -0
- preditor/plugins.py +65 -0
- preditor/prefs.py +74 -0
- {blurdev → preditor}/resource/environment_variables.html +26 -38
- {blurdev → preditor}/resource/error_mail.html +85 -85
- {blurdev → preditor}/resource/error_mail_inline.html +41 -41
- preditor/resource/img/README.md +7 -0
- preditor/resource/img/arrow_forward.png +0 -0
- preditor/resource/img/check-bold.png +0 -0
- preditor/resource/img/chevron-down.png +0 -0
- preditor/resource/img/chevron-up.png +0 -0
- preditor/resource/img/close-thick.png +0 -0
- preditor/resource/img/comment-edit.png +0 -0
- preditor/resource/img/content-copy.png +0 -0
- preditor/resource/img/content-cut.png +0 -0
- preditor/resource/img/content-duplicate.png +0 -0
- preditor/resource/img/content-paste.png +0 -0
- preditor/resource/img/content-save.png +0 -0
- preditor/resource/img/debug_disabled.png +0 -0
- preditor/resource/img/eye-check.png +0 -0
- preditor/resource/img/file-plus.png +0 -0
- preditor/resource/img/file-remove.png +0 -0
- preditor/resource/img/format-align-left.png +0 -0
- preditor/resource/img/format-letter-case-lower.png +0 -0
- preditor/resource/img/format-letter-case-upper.png +0 -0
- preditor/resource/img/information.png +0 -0
- preditor/resource/img/logging_critical.png +0 -0
- preditor/resource/img/logging_custom.png +0 -0
- preditor/resource/img/logging_debug.png +0 -0
- preditor/resource/img/logging_error.png +0 -0
- preditor/resource/img/logging_info.png +0 -0
- preditor/resource/img/logging_not_set.png +0 -0
- preditor/resource/img/logging_warning.png +0 -0
- preditor/resource/img/marker.png +0 -0
- preditor/resource/img/play.png +0 -0
- preditor/resource/img/playlist-play.png +0 -0
- preditor/resource/img/plus-minus-variant.png +0 -0
- preditor/resource/img/preditor.ico +0 -0
- preditor/resource/img/preditor.png +0 -0
- preditor/resource/img/preditor.psd +0 -0
- preditor/resource/img/preditor.svg +44 -0
- preditor/resource/img/restart.svg +1 -0
- preditor/resource/img/skip-forward-outline.png +0 -0
- preditor/resource/img/skip-next-outline.png +0 -0
- preditor/resource/img/skip-next.png +0 -0
- preditor/resource/img/skip-previous.png +0 -0
- preditor/resource/img/subdirectory-arrow-right.png +0 -0
- preditor/resource/img/text-search-variant.png +0 -0
- {blurdev → preditor}/resource/lang/python.json +30 -30
- preditor/resource/settings.ini +25 -0
- {blurdev/resource/stylesheet/logger → preditor/resource/stylesheet}/Bright.css +56 -61
- {blurdev → preditor}/resource/stylesheet/Dark.css +190 -132
- {blurdev → preditor}/scintilla/__init__.py +22 -28
- preditor/scintilla/delayables/__init__.py +11 -0
- {blurdev → preditor}/scintilla/delayables/smart_highlight.py +94 -93
- {blurdev → preditor}/scintilla/delayables/spell_check.py +173 -172
- {blurdev → preditor}/scintilla/documenteditor.py +2039 -2115
- {blurdev → preditor}/scintilla/finddialog.py +68 -81
- {blurdev → preditor}/scintilla/lang/__init__.py +80 -93
- {blurdev → preditor}/scintilla/lang/config/bash.ini +15 -15
- {blurdev → preditor}/scintilla/lang/config/batch.ini +14 -14
- {blurdev → preditor}/scintilla/lang/config/cpp.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/css.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/eyeonscript.ini +17 -17
- {blurdev → preditor}/scintilla/lang/config/html.ini +21 -21
- {blurdev → preditor}/scintilla/lang/config/javascript.ini +24 -24
- {blurdev → preditor}/scintilla/lang/config/lua.ini +16 -16
- {blurdev → preditor}/scintilla/lang/config/maxscript.ini +20 -20
- {blurdev → preditor}/scintilla/lang/config/mel.ini +18 -18
- {blurdev → preditor}/scintilla/lang/config/mu.ini +22 -22
- {blurdev → preditor}/scintilla/lang/config/nsi.ini +5 -5
- {blurdev → preditor}/scintilla/lang/config/perl.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/puppet.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/python.ini +28 -28
- {blurdev → preditor}/scintilla/lang/config/ruby.ini +19 -19
- {blurdev → preditor}/scintilla/lang/config/sql.ini +7 -7
- {blurdev → preditor}/scintilla/lang/config/xml.ini +21 -21
- {blurdev → preditor}/scintilla/lang/config/yaml.ini +18 -18
- {blurdev → preditor}/scintilla/lang/language.py +240 -250
- preditor/scintilla/lexers/__init__.py +0 -0
- {blurdev → preditor}/scintilla/lexers/cpplexer.py +21 -30
- {blurdev → preditor}/scintilla/lexers/javascriptlexer.py +25 -34
- {blurdev → preditor}/scintilla/lexers/maxscriptlexer.py +234 -253
- {blurdev → preditor}/scintilla/lexers/mellexer.py +368 -376
- {blurdev → preditor}/scintilla/lexers/mulexer.py +32 -41
- {blurdev → preditor}/scintilla/lexers/pythonlexer.py +41 -50
- {blurdev → preditor}/scintilla/ui/finddialog.ui +160 -160
- preditor/settings.py +71 -0
- preditor/stream/__init__.py +80 -0
- preditor/stream/director.py +56 -0
- preditor/stream/manager.py +74 -0
- preditor/streamhandler_helper.py +46 -0
- preditor/utils/__init__.py +0 -0
- preditor/utils/cute.py +30 -0
- preditor/utils/stylesheets.py +54 -0
- {blurdev → preditor}/version.py +5 -5
- preditor/weakref.py +363 -0
- PrEditor-0.0.0.dev1.dist-info/METADATA +0 -51
- PrEditor-0.0.0.dev1.dist-info/RECORD +0 -279
- PrEditor-0.0.0.dev1.dist-info/top_level.txt +0 -1
- blurdev/__init__.py +0 -356
- blurdev/cores/__init__.py +0 -98
- blurdev/cores/application.py +0 -26
- blurdev/cores/core.py +0 -634
- blurdev/debug.py +0 -593
- blurdev/external.py +0 -391
- blurdev/gui/level_buttons.py +0 -585
- blurdev/gui/workboxwidget.py +0 -205
- blurdev/logger.py +0 -238
- blurdev/osystem.py +0 -813
- blurdev/prefs.py +0 -33
- blurdev/protocols/__init__.py +0 -71
- blurdev/protocols/write_std_output_handler.py +0 -83
- blurdev/resource/designer_plugins.xml +0 -9
- blurdev/resource/error_email_old.html +0 -41
- blurdev/resource/img/add.png +0 -0
- blurdev/resource/img/ajax-loader.gif +0 -0
- blurdev/resource/img/application.png +0 -0
- blurdev/resource/img/applications.png +0 -0
- blurdev/resource/img/assburner.png +0 -0
- blurdev/resource/img/assfreezer.png +0 -0
- blurdev/resource/img/bar.gif +0 -0
- blurdev/resource/img/blank.png +0 -0
- blurdev/resource/img/blurdev.png +0 -0
- blurdev/resource/img/calendar_disabled.png +0 -0
- blurdev/resource/img/calendar_enabled.png +0 -0
- blurdev/resource/img/cancel.png +0 -0
- blurdev/resource/img/custom.png +0 -0
- blurdev/resource/img/debug_high.png +0 -0
- blurdev/resource/img/debug_low.png +0 -0
- blurdev/resource/img/debug_mid.png +0 -0
- blurdev/resource/img/debug_off.png +0 -0
- blurdev/resource/img/django.png +0 -0
- blurdev/resource/img/doc.png +0 -0
- blurdev/resource/img/edit.png +0 -0
- blurdev/resource/img/elemental.png +0 -0
- blurdev/resource/img/explore.png +0 -0
- blurdev/resource/img/favorite.png +0 -0
- blurdev/resource/img/file.png +0 -0
- blurdev/resource/img/folder.png +0 -0
- blurdev/resource/img/ide/add.png +0 -0
- blurdev/resource/img/ide/add_note.png +0 -0
- blurdev/resource/img/ide/arrow_down.png +0 -0
- blurdev/resource/img/ide/arrow_up.png +0 -0
- blurdev/resource/img/ide/check.png +0 -0
- blurdev/resource/img/ide/class.png +0 -0
- blurdev/resource/img/ide/clean.png +0 -0
- blurdev/resource/img/ide/clearlog.png +0 -0
- blurdev/resource/img/ide/close.png +0 -0
- blurdev/resource/img/ide/comment_add.png +0 -0
- blurdev/resource/img/ide/comment_remove.png +0 -0
- blurdev/resource/img/ide/comment_toggle.png +0 -0
- blurdev/resource/img/ide/console.png +0 -0
- blurdev/resource/img/ide/copy.png +0 -0
- blurdev/resource/img/ide/copylstrip.png +0 -0
- blurdev/resource/img/ide/cut.png +0 -0
- blurdev/resource/img/ide/edit.png +0 -0
- blurdev/resource/img/ide/find.png +0 -0
- blurdev/resource/img/ide/find_replace.png +0 -0
- blurdev/resource/img/ide/findnext.png +0 -0
- blurdev/resource/img/ide/findprev.png +0 -0
- blurdev/resource/img/ide/folder_find.png +0 -0
- blurdev/resource/img/ide/function.png +0 -0
- blurdev/resource/img/ide/git-bash.png +0 -0
- blurdev/resource/img/ide/git-gui.png +0 -0
- blurdev/resource/img/ide/gitk.png +0 -0
- blurdev/resource/img/ide/goto.png +0 -0
- blurdev/resource/img/ide/goto_def.png +0 -0
- blurdev/resource/img/ide/help.png +0 -0
- blurdev/resource/img/ide/highlighter.png +0 -0
- blurdev/resource/img/ide/lowercase.png +0 -0
- blurdev/resource/img/ide/newfile.png +0 -0
- blurdev/resource/img/ide/newfolder.png +0 -0
- blurdev/resource/img/ide/newproject.png +0 -0
- blurdev/resource/img/ide/newwizard.png +0 -0
- blurdev/resource/img/ide/open.png +0 -0
- blurdev/resource/img/ide/paste.png +0 -0
- blurdev/resource/img/ide/pdb_continue.png +0 -0
- blurdev/resource/img/ide/pdb_down.png +0 -0
- blurdev/resource/img/ide/pdb_next.png +0 -0
- blurdev/resource/img/ide/pdb_step.png +0 -0
- blurdev/resource/img/ide/pdb_up.png +0 -0
- blurdev/resource/img/ide/plus_minus.png +0 -0
- blurdev/resource/img/ide/preferences.png +0 -0
- blurdev/resource/img/ide/project_find.png +0 -0
- blurdev/resource/img/ide/python.png +0 -0
- blurdev/resource/img/ide/pyular.png +0 -0
- blurdev/resource/img/ide/qt.png +0 -0
- blurdev/resource/img/ide/quit.png +0 -0
- blurdev/resource/img/ide/redo.png +0 -0
- blurdev/resource/img/ide/refresh.png +0 -0
- blurdev/resource/img/ide/remove.png +0 -0
- blurdev/resource/img/ide/ruler.png +0 -0
- blurdev/resource/img/ide/run.png +0 -0
- blurdev/resource/img/ide/runall.png +0 -0
- blurdev/resource/img/ide/runallclear.png +0 -0
- blurdev/resource/img/ide/runselected.png +0 -0
- blurdev/resource/img/ide/runselectedclear.png +0 -0
- blurdev/resource/img/ide/save.png +0 -0
- blurdev/resource/img/ide/saveas.png +0 -0
- blurdev/resource/img/ide/sdk.png +0 -0
- blurdev/resource/img/ide/separator.png +0 -0
- blurdev/resource/img/ide/tabbed.png +0 -0
- blurdev/resource/img/ide/tile.png +0 -0
- blurdev/resource/img/ide/toolbar.png +0 -0
- blurdev/resource/img/ide/undo.png +0 -0
- blurdev/resource/img/ide/uppercase.png +0 -0
- blurdev/resource/img/ide/view_as.png +0 -0
- blurdev/resource/img/ide/windowed.png +0 -0
- blurdev/resource/img/ide.ico +0 -0
- blurdev/resource/img/ide.png +0 -0
- blurdev/resource/img/ide48.png +0 -0
- blurdev/resource/img/info.png +0 -0
- blurdev/resource/img/legacy tool.png +0 -0
- blurdev/resource/img/library.png +0 -0
- blurdev/resource/img/logger/about.png +0 -0
- blurdev/resource/img/logger/arrow_forward.png +0 -0
- blurdev/resource/img/logger/clear.png +0 -0
- blurdev/resource/img/logger/close.png +0 -0
- blurdev/resource/img/logger/debug_disabled.png +0 -0
- blurdev/resource/img/logger/debug_high.png +0 -0
- blurdev/resource/img/logger/debug_low.png +0 -0
- blurdev/resource/img/logger/debug_mid.png +0 -0
- blurdev/resource/img/logger/down.png +0 -0
- blurdev/resource/img/logger/find.png +0 -0
- blurdev/resource/img/logger/logging_critical.png +0 -0
- blurdev/resource/img/logger/logging_debug.png +0 -0
- blurdev/resource/img/logger/logging_error.png +0 -0
- blurdev/resource/img/logger/logging_info.png +0 -0
- blurdev/resource/img/logger/logging_not_set.png +0 -0
- blurdev/resource/img/logger/logging_warning.png +0 -0
- blurdev/resource/img/logger/next.png +0 -0
- blurdev/resource/img/logger/play.png +0 -0
- blurdev/resource/img/logger/playlist_play.png +0 -0
- blurdev/resource/img/logger/previous.png +0 -0
- blurdev/resource/img/logger/return.png +0 -0
- blurdev/resource/img/logger/save.png +0 -0
- blurdev/resource/img/logger/subdirectory_arrow_right.png +0 -0
- blurdev/resource/img/logger/up.png +0 -0
- blurdev/resource/img/lovebar.png +0 -0
- blurdev/resource/img/new.png +0 -0
- blurdev/resource/img/new_selected.png +0 -0
- blurdev/resource/img/node.png +0 -0
- blurdev/resource/img/ok.png +0 -0
- blurdev/resource/img/options.png +0 -0
- blurdev/resource/img/packages.png +0 -0
- blurdev/resource/img/preview/add.png +0 -0
- blurdev/resource/img/preview/brush.png +0 -0
- blurdev/resource/img/preview/delete.png +0 -0
- blurdev/resource/img/preview/delte.png +0 -0
- blurdev/resource/img/preview/fill.png +0 -0
- blurdev/resource/img/preview/layers.png +0 -0
- blurdev/resource/img/preview/media.png +0 -0
- blurdev/resource/img/preview/navigate.png +0 -0
- blurdev/resource/img/preview/pencil.png +0 -0
- blurdev/resource/img/preview/select.png +0 -0
- blurdev/resource/img/preview/type.png +0 -0
- blurdev/resource/img/preview/visible.png +0 -0
- blurdev/resource/img/project.png +0 -0
- blurdev/resource/img/python_logger.ico +0 -0
- blurdev/resource/img/python_logger.png +0 -0
- blurdev/resource/img/refresh.png +0 -0
- blurdev/resource/img/remove.png +0 -0
- blurdev/resource/img/reset.png +0 -0
- blurdev/resource/img/richtext/font_bold.png +0 -0
- blurdev/resource/img/richtext/font_italic.png +0 -0
- blurdev/resource/img/richtext/link_image.png +0 -0
- blurdev/resource/img/richtext/spell_check.png +0 -0
- blurdev/resource/img/richtext/unordered_list.png +0 -0
- blurdev/resource/img/save.png +0 -0
- blurdev/resource/img/savesettings.png +0 -0
- blurdev/resource/img/settings.png +0 -0
- blurdev/resource/img/tool.png +0 -0
- blurdev/resource/img/toolbarHandleHorizontal.png +0 -0
- blurdev/resource/img/toolbarHandleVertical.png +0 -0
- blurdev/resource/img/trash.png +0 -0
- blurdev/resource/img/trax.png +0 -0
- blurdev/resource/img/tree.png +0 -0
- blurdev/resource/img/treegrunt.ico +0 -0
- blurdev/resource/img/treegrunt.png +0 -0
- blurdev/resource/img/treegruntedit.png +0 -0
- blurdev/resource/img/user interface.png +0 -0
- blurdev/resource/img/warning.png +0 -0
- blurdev/resource/img/watermark.png +0 -0
- blurdev/resource/sdk/blurdev.sdk +0 -3
- blurdev/resource/settings.ini +0 -82
- blurdev/resource/softimage/BlurApplication.dll +0 -0
- blurdev/resource/softimage/BlurApplication64.dll +0 -0
- blurdev/resource/stylesheet/Carbon.css +0 -35
- blurdev/resource/stylesheet/logger/Dark.css +0 -62
- blurdev/resource/templ/py_comment.templ +0 -1
- blurdev/resource/templ/py_debug_raise_error.templ +0 -7
- blurdev/resource/templ/py_doc_string.templ +0 -10
- blurdev/resource/templ/py_header.templ +0 -9
- blurdev/resource/templ/py_line_comment.templ +0 -1
- blurdev/resource/templ/py_log_to_file.templ +0 -22
- blurdev/resource/templ/py_module_path.templ +0 -1
- blurdev/resource/templ/py_pyqt_core.templ +0 -1
- blurdev/resource/templ/py_pyqt_gui.templ +0 -1
- blurdev/resource/templ/py_splashscreen.templ +0 -6
- blurdev/resource/templ/py_testing_note.templ +0 -1
- blurdev/resource/templ/py_testing_note_end.templ +0 -1
- blurdev/resource/tools_environments.json +0 -72
- blurdev/resource/tools_environments.xml +0 -11
- blurdev/resource/tools_environments_linux.xml +0 -11
- blurdev/resource/tools_environments_offline.xml +0 -7
- blurdev/runtimes/__init__.py +0 -2
- blurdev/runtimes/logger.py +0 -44
- blurdev/scintilla/delayables/__init__.py +0 -9
- blurdev/settings.py +0 -312
- blurdev/utils/error.py +0 -389
- {blurdev/scintilla/lexers → preditor/cores}/__init__.py +0 -0
- {blurdev/utils → preditor/gui/fuzzy_search}/__init__.py +0 -0
- {blurdev → preditor}/resource/img/warning-big.png +0 -0
blurdev/osystem.py
DELETED
|
@@ -1,813 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module provides additional methods that aren't easily found in existing
|
|
3
|
-
python or Qt modules for cross-platform usage.
|
|
4
|
-
|
|
5
|
-
The osystem module provides a number of functions to make dealing with
|
|
6
|
-
paths and other platform-specific things in a more abstract platform-agnostic
|
|
7
|
-
way.
|
|
8
|
-
|
|
9
|
-
.. data:: EXTENSION_MAP
|
|
10
|
-
|
|
11
|
-
Dictionary of (extension: blurdev_enviroment_variable) pairs used by
|
|
12
|
-
:func:`startfile` to execute scripts and other files.
|
|
13
|
-
This allows blurdev to associate filetypes with executable targets outside
|
|
14
|
-
of the normal windows file association mechanism.
|
|
15
|
-
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
from __future__ import print_function
|
|
19
|
-
from __future__ import absolute_import
|
|
20
|
-
import os
|
|
21
|
-
import sys
|
|
22
|
-
import types
|
|
23
|
-
import subprocess
|
|
24
|
-
from builtins import str as text
|
|
25
|
-
|
|
26
|
-
import blurdev
|
|
27
|
-
from . import settings
|
|
28
|
-
from blurdev.enum import Enum, EnumGroup
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def getPointerSize():
|
|
32
|
-
import struct
|
|
33
|
-
|
|
34
|
-
try:
|
|
35
|
-
size = struct.calcsize('P')
|
|
36
|
-
except struct.error:
|
|
37
|
-
# Older installations can only query longs
|
|
38
|
-
size = struct.calcsize('l')
|
|
39
|
-
size *= 8
|
|
40
|
-
global getPointerSize
|
|
41
|
-
|
|
42
|
-
def getPointerSize():
|
|
43
|
-
return size
|
|
44
|
-
|
|
45
|
-
return size
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# Get the active version of python, not a hard coded value.
|
|
49
|
-
def pythonPath(pyw=False, architecture=None):
|
|
50
|
-
if settings.OS_TYPE != 'Windows':
|
|
51
|
-
return 'python'
|
|
52
|
-
from distutils.sysconfig import get_python_inc
|
|
53
|
-
|
|
54
|
-
# Unable to pull the path from the registry just use the current python path
|
|
55
|
-
basepath = os.path.split(get_python_inc())[0]
|
|
56
|
-
# build the path to the python executable. If requested use pythonw instead of
|
|
57
|
-
# python
|
|
58
|
-
return os.path.join(basepath, 'python{w}.exe'.format(w=pyw and 'w' or ''))
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
EXTENSION_MAP = {}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def app_id_for_shortcut(shortcut):
|
|
65
|
-
"""Gets the AppUserModel.ID for the given shortcut.
|
|
66
|
-
|
|
67
|
-
This will allow windows to group windows with the same app id on a shortcut pinned
|
|
68
|
-
to the taskbar. Use :py:meth:`blurdev.setAppUserModelID` to set the app id for a
|
|
69
|
-
running application.
|
|
70
|
-
"""
|
|
71
|
-
if os.path.exists(shortcut):
|
|
72
|
-
# These imports won't work inside python 2 DCC's
|
|
73
|
-
from win32com.propsys import propsys
|
|
74
|
-
|
|
75
|
-
# Original info from https://stackoverflow.com/a/61714895
|
|
76
|
-
key = propsys.PSGetPropertyKeyFromName("System.AppUserModel.ID")
|
|
77
|
-
store = propsys.SHGetPropertyStoreFromParsingName(shortcut)
|
|
78
|
-
return store.GetValue(key).GetValue()
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def defaultLogFile(filename='blurdevProtocol.log'):
|
|
82
|
-
"""Returns a default log file path often used for redirecting stdout/err to.
|
|
83
|
-
Uses the `BDEV_PATH_BLUR` environment variable as the basepath.
|
|
84
|
-
|
|
85
|
-
Args:
|
|
86
|
-
filename (str, optional): filename to log to.
|
|
87
|
-
"""
|
|
88
|
-
basepath = blurdev.osystem.expandvars(os.environ['BDEV_PATH_BLUR'])
|
|
89
|
-
return os.path.join(basepath, filename)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def expandvars(text, cache=None):
|
|
93
|
-
"""
|
|
94
|
-
Recursively expands the text variables, vs. the os.path.expandvars
|
|
95
|
-
method which only works at one level.
|
|
96
|
-
|
|
97
|
-
:param text: text string to expand
|
|
98
|
-
:type text: str
|
|
99
|
-
:param cache: used internally during recursion to prevent infinite loop
|
|
100
|
-
:type cache: dict
|
|
101
|
-
:rtype: str
|
|
102
|
-
|
|
103
|
-
"""
|
|
104
|
-
# make sure we have data
|
|
105
|
-
if not text:
|
|
106
|
-
return ''
|
|
107
|
-
|
|
108
|
-
import re
|
|
109
|
-
|
|
110
|
-
# check for circular dependencies
|
|
111
|
-
if cache is None:
|
|
112
|
-
cache = {}
|
|
113
|
-
|
|
114
|
-
# return the cleaned variable
|
|
115
|
-
output = str(text)
|
|
116
|
-
keys = re.findall(r'\$(\w+)|\${(\w+)\}|\%(\w+)\%', text)
|
|
117
|
-
|
|
118
|
-
for first, second, third in keys:
|
|
119
|
-
repl = ''
|
|
120
|
-
key = ''
|
|
121
|
-
if first:
|
|
122
|
-
repl = '$%s' % first
|
|
123
|
-
key = first
|
|
124
|
-
elif second:
|
|
125
|
-
repl = '${%s}' % second
|
|
126
|
-
key = second
|
|
127
|
-
elif third:
|
|
128
|
-
repl = '%%%s%%' % third
|
|
129
|
-
key = third
|
|
130
|
-
else:
|
|
131
|
-
continue
|
|
132
|
-
|
|
133
|
-
value = os.environ.get(key)
|
|
134
|
-
if value:
|
|
135
|
-
if key not in cache:
|
|
136
|
-
cache[key] = value
|
|
137
|
-
value = expandvars(value, cache)
|
|
138
|
-
else:
|
|
139
|
-
print(
|
|
140
|
-
'WARNING! %s environ variable contains a circular dependency' % key
|
|
141
|
-
)
|
|
142
|
-
value = cache[key]
|
|
143
|
-
else:
|
|
144
|
-
value = repl
|
|
145
|
-
|
|
146
|
-
output = output.replace(repl, value)
|
|
147
|
-
|
|
148
|
-
return output
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def createShortcut(
|
|
152
|
-
title,
|
|
153
|
-
args,
|
|
154
|
-
startin=None,
|
|
155
|
-
target=None,
|
|
156
|
-
icon=None,
|
|
157
|
-
iconFilename=None,
|
|
158
|
-
path=None,
|
|
159
|
-
description='',
|
|
160
|
-
common=1,
|
|
161
|
-
app_id=None,
|
|
162
|
-
):
|
|
163
|
-
"""Creates a shortcut.
|
|
164
|
-
|
|
165
|
-
Windows: If icon is provided it looks for a .ico file with the same name
|
|
166
|
-
as the provided icon. If it can't find a .ico file it will attempt to
|
|
167
|
-
create one using ImageMagick(http://www.imagemagick.org/). ImageMagick
|
|
168
|
-
should be installed to the 32bit program files
|
|
169
|
-
(64Bit Windows: C:\\Program Files (x86)\\ImageMagick,
|
|
170
|
-
32Bit Windows: C:\\Program Files\\ImageMagick)
|
|
171
|
-
|
|
172
|
-
Args:
|
|
173
|
-
title (str): the title for the shortcut
|
|
174
|
-
args (str): argument string to pass to target command
|
|
175
|
-
startin (str, optional): path where the shortcut should run target command.
|
|
176
|
-
If None(default) then the dirname for the first argument in args is used.
|
|
177
|
-
If args is empty, then the dirname of target is used.
|
|
178
|
-
target (str or None, optional): the target for the shortcut. If None(default)
|
|
179
|
-
this will default to sys.executable.
|
|
180
|
-
icon (str or None, optional): path to the icon the shortcut should use
|
|
181
|
-
path (str or list, optional): path where the shortcut should be created. On
|
|
182
|
-
windows, if a list is passed it must have at least one string in it and the
|
|
183
|
-
list will be passed to os.path.join. The first string in the list will be
|
|
184
|
-
replaced if a key is used. `start menu` is replaced with the path to the
|
|
185
|
-
start menu. `desktop` is replaced with the path to the desktop. If None the
|
|
186
|
-
desktop path is used.
|
|
187
|
-
description (str, optional): helpful description for the shortcut
|
|
188
|
-
common (int, optional): If auto generating the path, this controls if the path
|
|
189
|
-
is generated for the user or shared. 1(default) is the public shared folde,
|
|
190
|
-
while 0 is the users folder. See path to control if the auto-generated path
|
|
191
|
-
is for the desktop or start menu.
|
|
192
|
-
app_id (bool, str or None): whether to set app ID on shortcut or not
|
|
193
|
-
"""
|
|
194
|
-
if settings.OS_TYPE == 'Windows':
|
|
195
|
-
import winshell
|
|
196
|
-
|
|
197
|
-
if isinstance(path, (list, tuple)):
|
|
198
|
-
base = path[0]
|
|
199
|
-
if base == 'start menu':
|
|
200
|
-
base = os.path.join(winshell.start_menu(common), 'Programs')
|
|
201
|
-
elif base == 'desktop':
|
|
202
|
-
base = winshell.desktop(common)
|
|
203
|
-
# Add the remaining path structure
|
|
204
|
-
path = os.path.join(base, *path[1:])
|
|
205
|
-
elif not path:
|
|
206
|
-
path = winshell.desktop(common)
|
|
207
|
-
# Create any missing folders in the path structure
|
|
208
|
-
if path and not os.path.exists(path):
|
|
209
|
-
os.makedirs(path)
|
|
210
|
-
|
|
211
|
-
if not target:
|
|
212
|
-
target = sys.executable
|
|
213
|
-
if not startin:
|
|
214
|
-
# Set the start in directory to the directory of the first args if passed
|
|
215
|
-
# otherwise use the target directory
|
|
216
|
-
if args:
|
|
217
|
-
if isinstance(args, (list, tuple)):
|
|
218
|
-
startin = os.path.dirname(args[0])
|
|
219
|
-
else:
|
|
220
|
-
startin = os.path.dirname(args)
|
|
221
|
-
else:
|
|
222
|
-
startin = os.path.dirname(target)
|
|
223
|
-
|
|
224
|
-
if icon:
|
|
225
|
-
# On Windows "PROGRAMDATA" for all users, "APPDATA" for per user.
|
|
226
|
-
# See: https://www.microsoft.com/en-us/wdsi/help/folder-variables
|
|
227
|
-
dirname = 'PROGRAMDATA' if 1 == common else 'APPDATA'
|
|
228
|
-
dirname = os.getenv(dirname)
|
|
229
|
-
dirname = os.path.join(dirname, 'blur', 'icons')
|
|
230
|
-
if not os.path.exists(dirname):
|
|
231
|
-
os.makedirs(dirname)
|
|
232
|
-
|
|
233
|
-
output = os.path.abspath(
|
|
234
|
-
os.path.join(dirname, (iconFilename or title) + '.ico')
|
|
235
|
-
)
|
|
236
|
-
basename, extension = os.path.splitext(icon)
|
|
237
|
-
ico = basename + '.ico'
|
|
238
|
-
if os.path.exists(ico):
|
|
239
|
-
import shutil
|
|
240
|
-
|
|
241
|
-
shutil.copyfile(ico, output)
|
|
242
|
-
else:
|
|
243
|
-
from PIL import Image
|
|
244
|
-
|
|
245
|
-
Image.open(icon).save(output)
|
|
246
|
-
icon = output if os.path.exists(output) else None
|
|
247
|
-
|
|
248
|
-
shortcut = os.path.join(path, title + '.lnk')
|
|
249
|
-
# If the shortcut description is longer than 260 characters, the target may end
|
|
250
|
-
# up with random unicode characters, and the icon is not set properly. The
|
|
251
|
-
# Properties dialog only shows 259 characters in the description, so we limit
|
|
252
|
-
# the description to 259 characters.
|
|
253
|
-
description = description[:259]
|
|
254
|
-
|
|
255
|
-
# If args is a list, convert it to a string using subprocess
|
|
256
|
-
if not isinstance(args, types.StringTypes):
|
|
257
|
-
args = subprocess.list2cmdline(args)
|
|
258
|
-
if icon:
|
|
259
|
-
winshell.CreateShortcut(
|
|
260
|
-
shortcut,
|
|
261
|
-
target,
|
|
262
|
-
Arguments=args,
|
|
263
|
-
StartIn=startin,
|
|
264
|
-
Icon=(icon, 0),
|
|
265
|
-
Description=description,
|
|
266
|
-
)
|
|
267
|
-
else:
|
|
268
|
-
winshell.CreateShortcut(
|
|
269
|
-
shortcut,
|
|
270
|
-
target,
|
|
271
|
-
Arguments=args,
|
|
272
|
-
StartIn=startin,
|
|
273
|
-
Description=description,
|
|
274
|
-
)
|
|
275
|
-
if app_id is True:
|
|
276
|
-
app_id = 'Blur.%s' % title.replace(' ', '')
|
|
277
|
-
if app_id:
|
|
278
|
-
set_app_id_for_shortcut(shortcut, app_id)
|
|
279
|
-
|
|
280
|
-
# Attempt to clear the windows icon cache so icon changes are displayed now
|
|
281
|
-
subprocess.Popen(
|
|
282
|
-
['ie4uinit.exe', '-ClearIconCache'], env=subprocessEnvironment()
|
|
283
|
-
)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
def explore(filename, dirFallback=False):
|
|
287
|
-
"""Launches the provided filename in the prefered editor for the specific platform.
|
|
288
|
-
|
|
289
|
-
Args:
|
|
290
|
-
filename (str): The file path to explore to.
|
|
291
|
-
dirFallback (bool): If True, and the file path does not exist, explore to
|
|
292
|
-
the deepest folder that does exist.
|
|
293
|
-
|
|
294
|
-
Returns:
|
|
295
|
-
bool: If it was able to explore the filename.
|
|
296
|
-
"""
|
|
297
|
-
# pull the file path from the inputed filename
|
|
298
|
-
fpath = os.path.normpath(filename)
|
|
299
|
-
|
|
300
|
-
if dirFallback:
|
|
301
|
-
# If the provided filename does not exist, recursively check each parent folder
|
|
302
|
-
# for existence.
|
|
303
|
-
while not os.path.exists(fpath) and not os.path.ismount(fpath):
|
|
304
|
-
fpath = os.path.split(fpath)[0]
|
|
305
|
-
|
|
306
|
-
# run the file in windows
|
|
307
|
-
if settings.OS_TYPE == 'Windows':
|
|
308
|
-
env = subprocessEnvironment()
|
|
309
|
-
if os.path.isfile(fpath):
|
|
310
|
-
subprocess.Popen(r'explorer.exe /select, "{}"'.format(fpath), env=env)
|
|
311
|
-
return True
|
|
312
|
-
subprocess.Popen(r'explorer.exe "{}"'.format(fpath), env=env)
|
|
313
|
-
return True
|
|
314
|
-
|
|
315
|
-
# run the file in linux
|
|
316
|
-
elif settings.OS_TYPE == 'Linux':
|
|
317
|
-
cmd = expandvars(os.environ.get('BDEV_CMD_BROWSE', ''))
|
|
318
|
-
if not cmd:
|
|
319
|
-
return False
|
|
320
|
-
subprocess.Popen(cmd % {'filepath': fpath}, shell=True)
|
|
321
|
-
return True
|
|
322
|
-
return False
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
def set_app_id_for_shortcut(shortcut, app_id):
|
|
326
|
-
"""Sets AppUserModel.ID info for a windows shortcut.
|
|
327
|
-
|
|
328
|
-
Note: This doesn't seem to work on a pinned taskbar shortcut. Set it on a desktop
|
|
329
|
-
shortcut then pin that shortcut.
|
|
330
|
-
|
|
331
|
-
This will allow windows to group windows with the same app id on a shortcut pinned
|
|
332
|
-
to the taskbar. Use :py:meth:`blurdev.setAppUserModelID` to set the app id for a
|
|
333
|
-
running application.
|
|
334
|
-
|
|
335
|
-
Args:
|
|
336
|
-
shortcut (str): The .lnk filename to set the app id on.
|
|
337
|
-
app_id (str): The app id to set on the shortcut
|
|
338
|
-
"""
|
|
339
|
-
if os.path.exists(shortcut):
|
|
340
|
-
# Original info from https://stackoverflow.com/a/61714895
|
|
341
|
-
|
|
342
|
-
# These imports won't work inside python 2 DCC's
|
|
343
|
-
import pythoncom
|
|
344
|
-
from win32com.propsys import propsys
|
|
345
|
-
from win32com.shell import shellcon
|
|
346
|
-
|
|
347
|
-
key = propsys.PSGetPropertyKeyFromName("System.AppUserModel.ID")
|
|
348
|
-
store = propsys.SHGetPropertyStoreFromParsingName(
|
|
349
|
-
shortcut, None, shellcon.GPS_READWRITE, propsys.IID_IPropertyStore
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
newValue = propsys.PROPVARIANTType(app_id, pythoncom.VT_BSTR)
|
|
353
|
-
store.SetValue(key, newValue)
|
|
354
|
-
store.Commit()
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
def subprocessEnvironment(env=None):
|
|
358
|
-
"""Returns a copy of the environment that will restore a new python instance to
|
|
359
|
-
current state.
|
|
360
|
-
|
|
361
|
-
Provides a environment dict that can be passed to subprocess.Popen that will restore
|
|
362
|
-
the current treegrunt environment settings, and blurdev stylesheet. It also resets
|
|
363
|
-
any environment variables set by a dcc that may cause problems when running a
|
|
364
|
-
subprocess.
|
|
365
|
-
|
|
366
|
-
Args:
|
|
367
|
-
|
|
368
|
-
env (dict, Optional): The base dictionary that is modified with blurdev
|
|
369
|
-
variables. if None(default) it will be populated with a copy of os.environ.
|
|
370
|
-
|
|
371
|
-
Returns:
|
|
372
|
-
dict: A list of environment variables to be passed to subprocess's env argument.
|
|
373
|
-
"""
|
|
374
|
-
if env is None:
|
|
375
|
-
env = os.environ.copy()
|
|
376
|
-
|
|
377
|
-
# Sets the stylesheet env variable so that launched applications can use it.
|
|
378
|
-
stylesheet = blurdev.core.styleSheet()
|
|
379
|
-
if stylesheet:
|
|
380
|
-
env['BDEV_STYLESHEET'] = str(stylesheet)
|
|
381
|
-
|
|
382
|
-
# By default libstone adds "C:\Windows\System32\blur64" or "C:\blur\common" to
|
|
383
|
-
# QApplication.libraryPaths(), setting this env var to a invalid path disables that.
|
|
384
|
-
# Leaving this set likely will cause the subprocess to not be configured correctly.
|
|
385
|
-
# The subprocess should be responsible for setting this variable
|
|
386
|
-
if 'LIBSTONE_QT_LIBRARY_PATH' in env:
|
|
387
|
-
del env['LIBSTONE_QT_LIBRARY_PATH']
|
|
388
|
-
|
|
389
|
-
# If PYTHONPATH is being used, attempt to reset it to the system value.
|
|
390
|
-
# Applications like maya add PYTHONPATH, and this breaks subprocesses.
|
|
391
|
-
if env.get('PYTHONPATH'):
|
|
392
|
-
if settings.OS_TYPE == 'Windows':
|
|
393
|
-
try:
|
|
394
|
-
# Store the 'PYTHONPATH' from the system registry if set
|
|
395
|
-
env['PYTHONPATH'] = getEnvironmentVariable('PYTHONPATH')
|
|
396
|
-
except WindowsError:
|
|
397
|
-
# If the registry is not set, then remove the variable
|
|
398
|
-
del env['PYTHONPATH']
|
|
399
|
-
|
|
400
|
-
# If PYTHONHOME is used, just remove it. This variable is supposed to point
|
|
401
|
-
# to a folder relative to the python stdlib
|
|
402
|
-
# Applications like Houdini add PYTHONHOME, and it breaks the subprocesses
|
|
403
|
-
if env.get('PYTHONHOME'):
|
|
404
|
-
if settings.OS_TYPE == 'Windows':
|
|
405
|
-
try:
|
|
406
|
-
# Store the 'PYTHONHOME' from the system registry if set
|
|
407
|
-
env['PYTHONHOME'] = getEnvironmentVariable('PYTHONHOME')
|
|
408
|
-
except WindowsError:
|
|
409
|
-
# If the registry is not set, then remove the variable
|
|
410
|
-
del env['PYTHONHOME']
|
|
411
|
-
|
|
412
|
-
# Some DCC's require inserting or appending path variables. When using subprocess
|
|
413
|
-
# these path variables may cause problems with the target application. This allows
|
|
414
|
-
# removing those path variables from the environment being passed to subprocess.
|
|
415
|
-
def normalize(i):
|
|
416
|
-
return os.path.normpath(os.path.normcase(i))
|
|
417
|
-
|
|
418
|
-
removePaths = set([normalize(x) for x in blurdev.core._removeFromPATHEnv])
|
|
419
|
-
|
|
420
|
-
# blurpath records any paths it adds to the PATH variable and other env variable
|
|
421
|
-
# modifications it makes, revert these changes.
|
|
422
|
-
try:
|
|
423
|
-
import blurpath
|
|
424
|
-
|
|
425
|
-
# Restore the original environment variables stored by blurpath.
|
|
426
|
-
blurpath.resetEnvVars(env) # blurpath v0.0.16 or newer
|
|
427
|
-
except ImportError:
|
|
428
|
-
pass
|
|
429
|
-
except AttributeError:
|
|
430
|
-
# TODO: Once blurpath v0.0.16 or newer is passed out, remove the
|
|
431
|
-
# outter AttributeError except block. Its just for backwards compatibility.
|
|
432
|
-
try:
|
|
433
|
-
removePaths.update([normalize(x) for x in blurpath.addedToPathEnv])
|
|
434
|
-
except AttributeError:
|
|
435
|
-
pass
|
|
436
|
-
|
|
437
|
-
# TODO: This is now tracked by blurpath v0.0.16, remove it This environment
|
|
438
|
-
# variable needs to be set on most dcc's to allow them to import the correct
|
|
439
|
-
# trax using blurpath. Removing this resets the subprocess to its default method
|
|
440
|
-
# of finding trax.
|
|
441
|
-
if 'BDEV_INCLUDE_TRAX' in env:
|
|
442
|
-
del env['BDEV_INCLUDE_TRAX']
|
|
443
|
-
|
|
444
|
-
path = env.get('PATH')
|
|
445
|
-
if path:
|
|
446
|
-
paths = [
|
|
447
|
-
x for x in path.split(os.path.pathsep) if normalize(x) not in removePaths
|
|
448
|
-
]
|
|
449
|
-
path = os.path.pathsep.join(paths)
|
|
450
|
-
# subprocess does not accept unicode in python 2
|
|
451
|
-
if sys.version_info[0] == 2 and isinstance(path, text):
|
|
452
|
-
path = path.encode('utf8')
|
|
453
|
-
env['PATH'] = path
|
|
454
|
-
|
|
455
|
-
# blurdev.settings.environStr does nothing in python3, so this code only needs
|
|
456
|
-
# to run in python2
|
|
457
|
-
if sys.version_info[0] < 3:
|
|
458
|
-
# subprocess explodes if it receives unicode in Python2 and in Python3,
|
|
459
|
-
# it explodes if it *doesn't* receive unicode.
|
|
460
|
-
temp = {}
|
|
461
|
-
for k, v in env.items():
|
|
462
|
-
# Attempt to remove any unicode objects. Ignore any conversion failures
|
|
463
|
-
try:
|
|
464
|
-
k = blurdev.settings.environStr(k)
|
|
465
|
-
except Exception:
|
|
466
|
-
pass
|
|
467
|
-
try:
|
|
468
|
-
v = blurdev.settings.environStr(v)
|
|
469
|
-
except AttributeError:
|
|
470
|
-
pass
|
|
471
|
-
temp[k] = v
|
|
472
|
-
env = temp
|
|
473
|
-
|
|
474
|
-
return env
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
def startfile(
|
|
478
|
-
filename, debugLevel=None, basePath='', cmd=None, architecture=None, env=None
|
|
479
|
-
):
|
|
480
|
-
"""Runs the filename.
|
|
481
|
-
|
|
482
|
-
Runs the filename in a shell with proper commands given, or passes the command to
|
|
483
|
-
the shell. (CMD in windows) the current platform
|
|
484
|
-
|
|
485
|
-
Args:
|
|
486
|
-
filename (str): path to the file to execute
|
|
487
|
-
|
|
488
|
-
debugLevel (blurdev.debug.DebugLevel or None, optional): If not None(default),
|
|
489
|
-
override for the current value of blurdev.debug.debugLevel(). If
|
|
490
|
-
DebugLevel.High, a persistent terminal will be opened allowing you see the
|
|
491
|
-
output in case of a crash.
|
|
492
|
-
|
|
493
|
-
basePath (str, optional): working directory where the command should be called
|
|
494
|
-
from. If None(default), the current working directory is used.
|
|
495
|
-
|
|
496
|
-
cmd (str or list or None, optional): This will be passed to subprocess if
|
|
497
|
-
defined. You can use a couple of % formatting keywords. "%(filepath)s" will
|
|
498
|
-
be filled with filename. "%(basepath)s" will be filled with basePath.
|
|
499
|
-
|
|
500
|
-
architecture (int or None, optional): 32 or 64 bit. If None use system default.
|
|
501
|
-
Defaults to None
|
|
502
|
-
|
|
503
|
-
env (dict, optional): a copy of the environment variables passed to subprocess.
|
|
504
|
-
If not passed subprocessEnvironment is used.
|
|
505
|
-
|
|
506
|
-
Returns: bool or subprocess.Popen: In most cases it should return a Popen object.
|
|
507
|
-
However if it can't run filename for some reason it will return False. On
|
|
508
|
-
Windows if it has to resort to calling os.startfile it will return the state of
|
|
509
|
-
that command.
|
|
510
|
-
"""
|
|
511
|
-
# determine the debug level
|
|
512
|
-
debug = blurdev.debug
|
|
513
|
-
|
|
514
|
-
success = False
|
|
515
|
-
filename = str(filename)
|
|
516
|
-
|
|
517
|
-
# make sure that the code we're running
|
|
518
|
-
if not (os.path.isfile(filename) or filename.startswith('http://')):
|
|
519
|
-
return False
|
|
520
|
-
|
|
521
|
-
if debugLevel is None:
|
|
522
|
-
debugLevel = debug.debugLevel()
|
|
523
|
-
|
|
524
|
-
# determine the base path for the system
|
|
525
|
-
filename = str(filename)
|
|
526
|
-
if not basePath:
|
|
527
|
-
basePath = os.path.split(filename)[0]
|
|
528
|
-
|
|
529
|
-
# strip out the information we need
|
|
530
|
-
ext = os.path.splitext(filename)[1]
|
|
531
|
-
if cmd is None:
|
|
532
|
-
if ext in (".py", ".pyw"):
|
|
533
|
-
cmd = (
|
|
534
|
-
pythonPath(pyw=ext == ".pyw", architecture=architecture)
|
|
535
|
-
+ ' "%(filepath)s"'
|
|
536
|
-
)
|
|
537
|
-
else:
|
|
538
|
-
cmd = expandvars(os.environ.get(EXTENSION_MAP.get(ext, ''), ''))
|
|
539
|
-
|
|
540
|
-
options = {'filepath': filename, 'basepath': basePath}
|
|
541
|
-
|
|
542
|
-
def formatCmd(cmd, options, prefix=None):
|
|
543
|
-
if isinstance(cmd, list):
|
|
544
|
-
if prefix:
|
|
545
|
-
cmd = prefix + cmd
|
|
546
|
-
# Do a string format on all items in the list in case they are present.
|
|
547
|
-
return [c % options for c in cmd]
|
|
548
|
-
if prefix:
|
|
549
|
-
cmd = ' '.join(prefix) + ' ' + cmd
|
|
550
|
-
return cmd % options
|
|
551
|
-
|
|
552
|
-
# Pass along the current env and blurdev settings
|
|
553
|
-
if env is None:
|
|
554
|
-
env = subprocessEnvironment()
|
|
555
|
-
|
|
556
|
-
# if the debug level is high, run the command with a shell in the background
|
|
557
|
-
if ext == '.sh' or debugLevel == debug.DebugLevel.High:
|
|
558
|
-
# run it in debug mode for windows
|
|
559
|
-
if settings.OS_TYPE == 'Windows':
|
|
560
|
-
if ext == '.pyw':
|
|
561
|
-
# make sure .pyw files are opened with python.exe, not pythonw.exe so we
|
|
562
|
-
# can actually debug problems.
|
|
563
|
-
if isinstance(cmd, list):
|
|
564
|
-
cmd[0] = cmd[0].replace('pythonw.exe', 'python.exe', 1)
|
|
565
|
-
else:
|
|
566
|
-
cmd = cmd.replace('pythonw.exe', 'python.exe', 1)
|
|
567
|
-
if cmd:
|
|
568
|
-
# NOTE: cmd.exe ignores anything after a newline character.
|
|
569
|
-
cmd = formatCmd(cmd, options, prefix=['cmd.exe', '/k'])
|
|
570
|
-
success = subprocess.Popen(cmd, env=env, cwd=basePath)
|
|
571
|
-
else:
|
|
572
|
-
success = subprocess.Popen(
|
|
573
|
-
'cmd.exe /k "%s"' % filename, env=env, cwd=basePath
|
|
574
|
-
)
|
|
575
|
-
|
|
576
|
-
# run it for Linux systems
|
|
577
|
-
elif settings.OS_TYPE == 'Linux':
|
|
578
|
-
debugcmd = expandvars(os.environ.get('BDEV_CMD_SHELL_DEBUG', ''))
|
|
579
|
-
|
|
580
|
-
# if there is a command associated with the inputed file, use that
|
|
581
|
-
if not cmd:
|
|
582
|
-
cmd = expandvars(os.environ.get('BDEV_CMD_SHELL_EXECFILE', ''))
|
|
583
|
-
|
|
584
|
-
# create a temp shell file
|
|
585
|
-
temppath = os.environ.get('BDEV_PATH_TEMP', '')
|
|
586
|
-
if not temppath:
|
|
587
|
-
return False
|
|
588
|
-
|
|
589
|
-
if not os.path.exists(temppath):
|
|
590
|
-
os.mkdir(temppath)
|
|
591
|
-
|
|
592
|
-
# write a temp shell command
|
|
593
|
-
tempfilename = os.path.join(temppath, 'debug.sh')
|
|
594
|
-
tempfile = open(tempfilename, 'w')
|
|
595
|
-
cmd = formatCmd(cmd, options)
|
|
596
|
-
if isinstance(cmd, list):
|
|
597
|
-
cmd = ' '.join(cmd)
|
|
598
|
-
tempfile.write('echo "running command: %s"\n' % cmd)
|
|
599
|
-
tempfile.write(cmd)
|
|
600
|
-
tempfile.close()
|
|
601
|
-
|
|
602
|
-
# make sure the system can run the file
|
|
603
|
-
os.system('chmod 0755 %s' % tempfilename)
|
|
604
|
-
|
|
605
|
-
# run the file
|
|
606
|
-
options['filepath'] = tempfilename
|
|
607
|
-
# TODO: I don't think this successfully passses the env var to the final
|
|
608
|
-
# command we should probably debug this
|
|
609
|
-
success = subprocess.Popen(debugcmd % options, env=env, shell=True)
|
|
610
|
-
|
|
611
|
-
return success
|
|
612
|
-
# otherwise run it directly
|
|
613
|
-
else:
|
|
614
|
-
# run the command in windows
|
|
615
|
-
if settings.OS_TYPE == 'Windows':
|
|
616
|
-
if cmd:
|
|
617
|
-
success = subprocess.Popen(
|
|
618
|
-
formatCmd(cmd, options), shell=True, cwd=basePath, env=env
|
|
619
|
-
)
|
|
620
|
-
else:
|
|
621
|
-
success = subprocess.Popen(
|
|
622
|
-
'"%s"' % filename, cwd=basePath, env=env, shell=True
|
|
623
|
-
)
|
|
624
|
-
if not success:
|
|
625
|
-
try:
|
|
626
|
-
success = os.startfile(filename)
|
|
627
|
-
except Exception:
|
|
628
|
-
pass
|
|
629
|
-
|
|
630
|
-
# in other platforms, we'll use subprocess.Popen
|
|
631
|
-
else:
|
|
632
|
-
if cmd:
|
|
633
|
-
success = subprocess.Popen(formatCmd(cmd, options), env=env, shell=True)
|
|
634
|
-
else:
|
|
635
|
-
# If the provided file is marked as executable just run it.
|
|
636
|
-
if os.access(filename, os.X_OK):
|
|
637
|
-
success = subprocess.Popen(filename, env=env, shell=True)
|
|
638
|
-
else:
|
|
639
|
-
cmd = expandvars(os.environ.get('BDEV_CMD_SHELL_EXECFILE', ''))
|
|
640
|
-
if not cmd:
|
|
641
|
-
return False
|
|
642
|
-
success = subprocess.Popen(
|
|
643
|
-
formatCmd(cmd, options), env=env, shell=True
|
|
644
|
-
)
|
|
645
|
-
return success
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
class FlashTime(Enum):
|
|
649
|
-
pass
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
class FlashTimes(EnumGroup):
|
|
653
|
-
"""Windows arguments for blurdev.core.flashWindow().
|
|
654
|
-
|
|
655
|
-
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-flashwinfo
|
|
656
|
-
"""
|
|
657
|
-
|
|
658
|
-
description = 'Stop flashing. The system restores the window to its original state.'
|
|
659
|
-
FLASHW_STOP = FlashTime(0, description=description)
|
|
660
|
-
FLASHW_CAPTION = FlashTime(0x00000001, description='Flash the window caption.')
|
|
661
|
-
FLASHW_TRAY = FlashTime(0x00000002, description='Flash the taskbar button.')
|
|
662
|
-
FLASHW_ALL = FlashTime(
|
|
663
|
-
0x00000003,
|
|
664
|
-
description=(
|
|
665
|
-
'Flash both the window caption and taskbar button. '
|
|
666
|
-
'This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.'
|
|
667
|
-
),
|
|
668
|
-
)
|
|
669
|
-
FLASHW_TIMER = FlashTime(
|
|
670
|
-
0x00000004, description='Flash continuously, until the FLASHW_STOP flag is set.'
|
|
671
|
-
)
|
|
672
|
-
FLASHW_TIMERNOFG = FlashTime(
|
|
673
|
-
0x0000000C,
|
|
674
|
-
description='Flash continuously until the window comes to the foreground.',
|
|
675
|
-
)
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
# --------------------------------------------------------------------------------
|
|
679
|
-
# Read registy values
|
|
680
|
-
# --------------------------------------------------------------------------------
|
|
681
|
-
def getRegKey(registry, key, architecture=None, write=False):
|
|
682
|
-
"""Returns a winreg hkey or none.
|
|
683
|
-
|
|
684
|
-
Args: registry (str): The registry to look in. 'HKEY_LOCAL_MACHINE' for example
|
|
685
|
-
|
|
686
|
-
key (str): The key to open. r'Software\\Autodesk\\Softimage\\InstallPaths' for
|
|
687
|
-
example
|
|
688
|
-
|
|
689
|
-
architecture (int | None): 32 or 64 bit. If None use system default.
|
|
690
|
-
Defaults to None
|
|
691
|
-
|
|
692
|
-
Returns:
|
|
693
|
-
A winreg handle object
|
|
694
|
-
"""
|
|
695
|
-
# Do not want to import winreg unless it is neccissary
|
|
696
|
-
regKey = None
|
|
697
|
-
import winreg
|
|
698
|
-
|
|
699
|
-
aReg = winreg.ConnectRegistry(None, getattr(winreg, registry))
|
|
700
|
-
if architecture == 32:
|
|
701
|
-
sam = winreg.KEY_WOW64_32KEY
|
|
702
|
-
elif architecture == 64:
|
|
703
|
-
sam = winreg.KEY_WOW64_64KEY
|
|
704
|
-
else:
|
|
705
|
-
sam = 0
|
|
706
|
-
access = winreg.KEY_READ
|
|
707
|
-
if write:
|
|
708
|
-
access = winreg.KEY_WRITE
|
|
709
|
-
try:
|
|
710
|
-
regKey = winreg.OpenKey(aReg, key, 0, access | sam)
|
|
711
|
-
except WindowsError:
|
|
712
|
-
pass
|
|
713
|
-
return regKey
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
def registryValue(registry, key, value_name, architecture=None):
|
|
717
|
-
"""Returns the value and type of the provided registry key's value name.
|
|
718
|
-
|
|
719
|
-
Args:
|
|
720
|
-
|
|
721
|
-
registry (str): The registry to look in. 'HKEY_LOCAL_MACHINE' for example
|
|
722
|
-
|
|
723
|
-
key (str): The key to open. r'Software\\Autodesk\\Softimage\\InstallPaths' for
|
|
724
|
-
example
|
|
725
|
-
|
|
726
|
-
value_name (str): The name of the value to read. To read the '(Default)' key
|
|
727
|
-
pass a empty string.
|
|
728
|
-
|
|
729
|
-
architecture (int | None): 32 or 64 bit. If None use system default.
|
|
730
|
-
Defaults to None.
|
|
731
|
-
|
|
732
|
-
Returns:
|
|
733
|
-
object: Value stored in key
|
|
734
|
-
int: registry type for value. See winreg's Value Types
|
|
735
|
-
"""
|
|
736
|
-
# Do not want to import winreg unless it is neccissary
|
|
737
|
-
regKey = getRegKey(registry, key, architecture=architecture)
|
|
738
|
-
if regKey:
|
|
739
|
-
import winreg
|
|
740
|
-
|
|
741
|
-
return winreg.QueryValueEx(regKey, value_name)
|
|
742
|
-
return '', 0
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
def getEnvironmentRegKey(machine=False):
|
|
746
|
-
"""Get the Registry Path and Key for the environment, either of the current
|
|
747
|
-
user or the system.
|
|
748
|
-
|
|
749
|
-
Args:
|
|
750
|
-
machine (bool, optional): If True, the system Environment location will
|
|
751
|
-
be returned. Otherwise, the Environment location for the current
|
|
752
|
-
user will be returned. Defaults to False.
|
|
753
|
-
|
|
754
|
-
Returns:
|
|
755
|
-
tuple: Returns a tuple of two strings (registry path, key).
|
|
756
|
-
"""
|
|
757
|
-
registry = 'HKEY_CURRENT_USER'
|
|
758
|
-
key = r'Environment'
|
|
759
|
-
# Replace {PATH} with the existing path variable.
|
|
760
|
-
if machine:
|
|
761
|
-
registry = 'HKEY_LOCAL_MACHINE'
|
|
762
|
-
key = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
|
|
763
|
-
return registry, key
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
def getEnvironmentVariable(value_name, system=None, default=None, architecture=None):
|
|
767
|
-
"""Returns the environment variable stored in the windows registry.
|
|
768
|
-
|
|
769
|
-
Args:
|
|
770
|
-
value_name (str): The name of the environment variable to get the value of.
|
|
771
|
-
system (bool or None, optional): If True, then only look in the system
|
|
772
|
-
environment variables. If False, then only look at the user
|
|
773
|
-
environment variables. If None(default), then return the user value
|
|
774
|
-
if set, otherwise return the system value.
|
|
775
|
-
default: If the variable is not set, return this value.
|
|
776
|
-
If None(default) then a WindowsError is raised.
|
|
777
|
-
architecture (int or None): 32 or 64 bit. If None use system default.
|
|
778
|
-
Defaults to None.
|
|
779
|
-
|
|
780
|
-
Raises:
|
|
781
|
-
WindowsError: [Error 2] is returned if the environment variable is not
|
|
782
|
-
stored in the requested registry. If you pass a default value other
|
|
783
|
-
than None this will not be raised.
|
|
784
|
-
"""
|
|
785
|
-
if system is None and value_name.lower() == 'path':
|
|
786
|
-
msg = "PATH is a special environment variable, set system to True or False."
|
|
787
|
-
raise ValueError(msg)
|
|
788
|
-
|
|
789
|
-
if not system:
|
|
790
|
-
# system is None or False, so check user variables.
|
|
791
|
-
registry, key = getEnvironmentRegKey(False)
|
|
792
|
-
try:
|
|
793
|
-
return blurdev.osystem.registryValue(
|
|
794
|
-
registry, key, value_name, architecture=architecture
|
|
795
|
-
)[0]
|
|
796
|
-
except WindowsError:
|
|
797
|
-
pass
|
|
798
|
-
if system is False:
|
|
799
|
-
# If system is False, then return the default.
|
|
800
|
-
# If None, then check the system.
|
|
801
|
-
if default is None:
|
|
802
|
-
raise
|
|
803
|
-
return default
|
|
804
|
-
|
|
805
|
-
registry, key = getEnvironmentRegKey(True)
|
|
806
|
-
try:
|
|
807
|
-
return blurdev.osystem.registryValue(
|
|
808
|
-
registry, key, value_name, architecture=architecture
|
|
809
|
-
)[0]
|
|
810
|
-
except WindowsError:
|
|
811
|
-
if default is None:
|
|
812
|
-
raise
|
|
813
|
-
return default
|