Пример #1
0
    def _check_pip_setup(self, pip_command):
        pip_command_str = pip_command
        if isinstance(pip_command_str, list):
            pip_command_str = " ".join(pip_command_str)

        if not self.ignore_cache and pip_command_str in _cache["setup"]:
            self._logger.debug(
                "Using cached pip setup information for {}".format(
                    pip_command_str))
            return _cache["setup"][pip_command_str]

        # This is horribly ugly and I'm sorry...
        #
        # While we can figure out the install directory, if that's writable and if a virtual environment
        # is active for pip that belongs to our sys.executable python instance by just checking some
        # variables, we can't for stuff like third party software we allow to update via the software
        # update plugin.
        #
        # What we do instead for these situations is try to install (and of course uninstall) the
        # testballoon dummy package, which collects that information for us. For pip <= 7 we could
        # have the testballoon provide us with the info needed through stdout, if pip was called
        # with --verbose anything printed to stdout within setup.py would be output. Pip 8 managed
        # to break this mechanism. Any (!) output within setup.py appears to be suppressed now, and
        # no combination of --log and multiple --verbose or -v arguments could get it to bring the
        # output back.
        #
        # So here's what we do now instead. Our sarge call sets an environment variable
        # "TESTBALLOON_OUTPUT" that points to a temporary file. If the testballoon sees that
        # variable set, it opens the file and writes to it the output it so far printed on stdout.
        # We then open the file and read in the data that way.
        #
        # Yeah, I'm not happy with that either. But as long as there's no way to otherwise figure
        # out for a generic pip command whether OctoPrint can even install anything with that
        # and if so how, well, that's how we'll have to do things.

        import os
        testballoon = os.path.join(os.path.realpath(os.path.dirname(__file__)),
                                   "piptestballoon")

        from octoprint.util import temppath
        with temppath() as testballoon_output_file:
            sarge_command = self.to_sarge_command(pip_command, "install", ".")
            try:
                # our testballoon is no real package, so this command will fail - that's ok though,
                # we only need the output produced within the pip environment
                sarge.run(sarge_command,
                          stdout=sarge.Capture(),
                          stderr=sarge.Capture(),
                          cwd=testballoon,
                          env=dict(TESTBALLOON_OUTPUT=testballoon_output_file))
            except:
                self._logger.exception(
                    "Error while trying to install testballoon to figure out pip setup"
                )
                return False, False, False, None

            data = dict()
            with open(testballoon_output_file) as f:
                for line in f:
                    key, value = line.split("=", 2)
                    data[key] = value

        install_dir_str = data.get("PIP_INSTALL_DIR", None)
        virtual_env_str = data.get("PIP_VIRTUAL_ENV", None)
        writable_str = data.get("PIP_WRITABLE", None)

        if install_dir_str is not None and virtual_env_str is not None and writable_str is not None:
            install_dir = install_dir_str.strip()
            virtual_env = virtual_env_str.strip() == "True"
            writable = writable_str.strip() == "True"

            can_use_user_flag = not virtual_env and site.ENABLE_USER_SITE

            # ok, enable user flag, virtual env yes/no, installation dir
            result = writable or can_use_user_flag, \
                     not writable and can_use_user_flag, \
                     virtual_env, \
                     install_dir
            _cache["setup"][pip_command_str] = result
            return result
        else:
            self._logger.debug(
                "Could not detect desired output from testballoon install, got this instead: {!r}"
                .format(data))
            return False, False, False, None
Пример #2
0
	def _check_pip_setup(self, pip_command):
		pip_command_str = pip_command
		if isinstance(pip_command_str, list):
			pip_command_str = " ".join(pip_command_str)

		with _cache_mutex:
			if not self.ignore_cache and pip_command_str in _cache["setup"]:
				self._logger.debug("Using cached pip setup information for {}".format(pip_command_str))
				return _cache["setup"][pip_command_str]

			# This is horribly ugly and I'm sorry...
			#
			# While we can figure out the install directory, if that's writable and if a virtual environment
			# is active for pip that belongs to our sys.executable python instance by just checking some
			# variables, we can't for stuff like third party software we allow to update via the software
			# update plugin.
			#
			# What we do instead for these situations is try to install (and of course uninstall) the
			# testballoon dummy package, which collects that information for us. For pip <= 7 we could
			# have the testballoon provide us with the info needed through stdout, if pip was called
			# with --verbose anything printed to stdout within setup.py would be output. Pip 8 managed
			# to break this mechanism. Any (!) output within setup.py appears to be suppressed now, and
			# no combination of --log and multiple --verbose or -v arguments could get it to bring the
			# output back.
			#
			# So here's what we do now instead. Our sarge call sets an environment variable
			# "TESTBALLOON_OUTPUT" that points to a temporary file. If the testballoon sees that
			# variable set, it opens the file and writes to it the output it so far printed on stdout.
			# We then open the file and read in the data that way.
			#
			# Yeah, I'm not happy with that either. But as long as there's no way to otherwise figure
			# out for a generic pip command whether OctoPrint can even install anything with that
			# and if so how, well, that's how we'll have to do things.

			import os
			testballoon = os.path.join(os.path.realpath(os.path.dirname(__file__)), "piptestballoon")

			from octoprint.util import temppath
			with temppath() as testballoon_output_file:
				sarge_command = self.to_sarge_command(pip_command, "install", ".")
				try:
					# our testballoon is no real package, so this command will fail - that's ok though,
					# we only need the output produced within the pip environment
					sarge.run(sarge_command,
					          stdout=sarge.Capture(),
					          stderr=sarge.Capture(),
					          cwd=testballoon,
					          env=dict(TESTBALLOON_OUTPUT=testballoon_output_file))
				except:
					self._logger.exception("Error while trying to install testballoon to figure out pip setup")
					return False, False, False, None

				data = dict()
				with open(testballoon_output_file) as f:
					for line in f:
						key, value = line.split("=", 2)
						data[key] = value

			install_dir_str = data.get("PIP_INSTALL_DIR", None)
			virtual_env_str = data.get("PIP_VIRTUAL_ENV", None)
			writable_str = data.get("PIP_WRITABLE", None)

			if install_dir_str is not None and virtual_env_str is not None and writable_str is not None:
				install_dir = install_dir_str.strip()
				virtual_env = virtual_env_str.strip() == "True"
				writable = writable_str.strip() == "True"

				can_use_user_flag = not virtual_env and site.ENABLE_USER_SITE

				ok = writable or can_use_user_flag
				user_flag = not writable and can_use_user_flag

				self._logger.info("pip installs to {}, --user flag needed => {}, "
				                  "virtual env => {}".format(install_dir,
				                                             "yes" if user_flag else "no",
				                                             "yes" if virtual_env else "no"))

				# ok, enable user flag, virtual env yes/no, installation dir
				result = ok, user_flag, virtual_env, install_dir
				_cache["setup"][pip_command_str] = result
				return result
			else:
				self._logger.debug("Could not detect desired output from testballoon install, got this instead: {!r}".format(data))
				return False, False, False, None