1# -*- coding: utf-8 -*- 2""" 3Decides if vendor bundles are used or not. 4Setup python path accordingly. 5""" 6 7from __future__ import absolute_import, print_function 8import os.path 9import sys 10 11# ----------------------------------------------------------------------------- 12# DEFINES: 13# ----------------------------------------------------------------------------- 14HERE = os.path.dirname(__file__) 15TASKS_VENDOR_DIR = os.path.join(HERE, "_vendor") 16INVOKE_BUNDLE = os.path.join(TASKS_VENDOR_DIR, "invoke.zip") 17INVOKE_BUNDLE_VERSION = "1.2.0" 18 19DEBUG_SYSPATH = False 20 21 22# ----------------------------------------------------------------------------- 23# EXCEPTIONS: 24# ----------------------------------------------------------------------------- 25class VersionRequirementError(SystemExit): 26 pass 27 28 29# ----------------------------------------------------------------------------- 30# FUNCTIONS: 31# ----------------------------------------------------------------------------- 32def setup_path(invoke_minversion=None): 33 """Setup python search and add ``TASKS_VENDOR_DIR`` (if available).""" 34 # print("INVOKE.tasks: setup_path") 35 if not os.path.isdir(TASKS_VENDOR_DIR): 36 print("SKIP: TASKS_VENDOR_DIR=%s is missing" % TASKS_VENDOR_DIR) 37 return 38 elif os.path.abspath(TASKS_VENDOR_DIR) in sys.path: 39 # -- SETUP ALREADY DONE: 40 # return 41 pass 42 43 use_vendor_bundles = os.environ.get("INVOKE_TASKS_USE_VENDOR_BUNDLES", "no") 44 if need_vendor_bundles(invoke_minversion): 45 use_vendor_bundles = "yes" 46 47 if use_vendor_bundles == "yes": 48 syspath_insert(0, os.path.abspath(TASKS_VENDOR_DIR)) 49 if setup_path_for_bundle(INVOKE_BUNDLE, pos=1): 50 import invoke 51 bundle_path = os.path.relpath(INVOKE_BUNDLE, os.getcwd()) 52 print("USING: %s (version: %s)" % (bundle_path, invoke.__version__)) 53 else: 54 # -- BEST-EFFORT: May rescue something 55 syspath_append(os.path.abspath(TASKS_VENDOR_DIR)) 56 setup_path_for_bundle(INVOKE_BUNDLE, pos=len(sys.path)) 57 58 if DEBUG_SYSPATH: 59 for index, p in enumerate(sys.path): 60 print(" %d. %s" % (index, p)) 61 62 63def require_invoke_minversion(min_version, verbose=False): 64 """Ensures that :mod:`invoke` has at the least the :param:`min_version`. 65 Otherwise, 66 67 :param min_version: Minimal acceptable invoke version (as string). 68 :param verbose: Indicates if invoke.version should be shown. 69 :raises: VersionRequirementError=SystemExit if requirement fails. 70 """ 71 # -- REQUIRES: sys.path is setup and contains invoke 72 try: 73 import invoke 74 invoke_version = invoke.__version__ 75 except ImportError: 76 invoke_version = "__NOT_INSTALLED" 77 78 if invoke_version < min_version: 79 message = "REQUIRE: invoke.version >= %s (but was: %s)" % \ 80 (min_version, invoke_version) 81 message += "\nUSE: pip install invoke>=%s" % min_version 82 raise VersionRequirementError(message) 83 84 # pylint: disable=invalid-name 85 INVOKE_VERSION = os.environ.get("INVOKE_VERSION", None) 86 if verbose and not INVOKE_VERSION: 87 os.environ["INVOKE_VERSION"] = invoke_version 88 print("USING: invoke.version=%s" % invoke_version) 89 90 91def need_vendor_bundles(invoke_minversion=None): 92 invoke_minversion = invoke_minversion or "0.0.0" 93 need_vendor_answers = [] 94 need_vendor_answers.append(need_vendor_bundle_invoke(invoke_minversion)) 95 # -- REQUIRE: path.py 96 try: 97 import path 98 need_bundle = False 99 except ImportError: 100 need_bundle = True 101 need_vendor_answers.append(need_bundle) 102 103 # -- DIAG: print("INVOKE: need_bundle=%s" % need_bundle1) 104 # return need_bundle1 or need_bundle2 105 return any(need_vendor_answers) 106 107 108def need_vendor_bundle_invoke(invoke_minversion="0.0.0"): 109 # -- REQUIRE: invoke 110 try: 111 import invoke 112 need_bundle = invoke.__version__ < invoke_minversion 113 if need_bundle: 114 del sys.modules["invoke"] 115 del invoke 116 except ImportError: 117 need_bundle = True 118 except Exception: # pylint: disable=broad-except 119 need_bundle = True 120 return need_bundle 121 122 123# ----------------------------------------------------------------------------- 124# UTILITY FUNCTIONS: 125# ----------------------------------------------------------------------------- 126def setup_path_for_bundle(bundle_path, pos=0): 127 if os.path.exists(bundle_path): 128 syspath_insert(pos, os.path.abspath(bundle_path)) 129 return True 130 return False 131 132 133def syspath_insert(pos, path): 134 if path in sys.path: 135 sys.path.remove(path) 136 sys.path.insert(pos, path) 137 138 139def syspath_append(path): 140 if path in sys.path: 141 sys.path.remove(path) 142 sys.path.append(path) 143 144