Make a subprocess call, collect its output and returncode.
        Returns CommandResult instance as ValueObject.

def run(cls, command, cwd=".", **kwargs):
        """
        Make a subprocess call, collect its output and returncode.
        Returns CommandResult instance as ValueObject.
        """
        assert isinstance(command, six.string_types)
        command_result = CommandResult()
        command_result.command = command
        use_shell = cls.USE_SHELL
        if "shell" in kwargs:
            use_shell = kwargs.pop("shell")

        # -- BUILD COMMAND ARGS:
        if six.PY2 and isinstance(command, six.text_type):
            # -- PREPARE-FOR: shlex.split()
            # In PY2, shlex.split() requires bytes string (non-unicode).
            # In PY3, shlex.split() accepts unicode string.
            command = codecs.encode(command, "utf-8")
        cmdargs = shlex.split(command)

        # -- TRANSFORM COMMAND (optional)
        command0 = cmdargs[0]
        real_command = cls.COMMAND_MAP.get(command0, None)
        if real_command:
            cmdargs0 = real_command.split()
            cmdargs = cmdargs0 + cmdargs[1:]
        preprocessors = cls.PREPROCESSOR_MAP.get(command0)
        if preprocessors:
            cmdargs = cls.preprocess_command(preprocessors, cmdargs, command, cwd)


        # -- RUN COMMAND:
        try:
            process = subprocess.Popen(cmdargs,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            universal_newlines=True,
                            shell=use_shell,
                            cwd=cwd, **kwargs)
            out, err = process.communicate()
            if six.PY2: # py3: we get unicode strings, py2 not
                default_encoding = 'UTF-8'
                out = six.text_type(out, process.stdout.encoding or default_encoding)
                err = six.text_type(err, process.stderr.encoding or default_encoding)
            process.poll()
            assert process.returncode is not None
            command_result.stdout = out
            command_result.stderr = err
            command_result.returncode = process.returncode
            if cls.DEBUG:
                print("shell.cwd={0}".format(kwargs.get("cwd", None)))
                print("shell.command: {0}".format(" ".join(cmdargs)))
                print("shell.command.output:\n{0};".format(command_result.output))
        except OSError as e:
            command_result.stderr = u"OSError: %s" % e
            command_result.returncode = e.errno
            assert e.errno != 0

        postprocessors = cls.POSTPROCESSOR_MAP.get(command0)
        if postprocessors:
            command_result = cls.postprocess_command(postprocessors, command_result)
        return command_result