Beispiel #1
0
    def test_build_go_missing(self):
        ensure_not_ui_thread()

        shell, _ = shellenv.get_env()
        search_path = path.expanduser('~')
        with GolangBuildMock(shell=shell, env={'PATH': search_path}):

            file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')

            def _run_build(view, result_queue):
                notify_user(
                    'Press the "Open Documentation" button when prompted about go not being found in the PATH'
                )

                view.window().run_command('golang_build')

            open_file(file_path, VIEW_SETTINGS, _run_build)
            time.sleep(0.5)
            self.assertTrue(
                confirm_user(
                    'Were you prompted that go could not be found in the PATH?'
                ))
            self.assertTrue(
                confirm_user(
                    'When you pressed "Open Documentation", was it opened in your browser?'
                ))
def run_os_command(cmd):
    shell = os.name == 'nt'

    try:
    
        options = {
            'shell': shell, 
            'stdout': subprocess.PIPE,
            'stderr': subprocess.STDOUT,
            'universal_newlines': False,
        }
        
        if not shell:
            options['env'] = {}
            options['env'].update({'PATH': shellenv.get_env()[1]['PATH']})
    
        proc = subprocess.Popen(cmd, **options)
        output = proc.communicate()[0].decode()
        
        debug('run_os_command: output', output)

        return output

    except Exception as e:
        debug('run_os_command: exception', str(e))
        return "ERROR: run_os_command: {0}".format(e)
Beispiel #3
0
def check_and_install_dependencies():
    """
    The function is dosen't check whether npm/node is installed or not.
    """
    # check if already installed
    if os.path.exists(PLUGIN_PACKAGE_LOCK):
        return

    # merge /usr/local/{bin,sbin}
    cmd = ['npm', 'install', '-s']
    exec_options = {
        'quiet': True,
        'working_dir': PLUGIN_PATH
    }

    if os.name != 'nt':
        # update paths for searching executables
        exec_options['cmd'] = cmd
        exec_options['env'] = {}
        exec_options['env'].update({'PATH': shellenv.get_env()[1]['PATH']})
    else:
        exec_options['shell_cmd'] = ' '.join(cmd)

    info('Running `npm install` to install plugin dependencies')

    sublime.active_window().run_command('exec', exec_options)
    def get_env(self, shell):
        shell, env = shellenv.get_env(shell)

        self.assertEqual(str_cls, type(shell))

        if sys.platform == 'win32':
            home_var = 'HOMEPATH'
        else:
            home_var = 'HOME'

        home_val = os.environ[home_var]
        if sys.version_info < (3, ):
            home_val = home_val.decode('mbcs' if sys.platform ==
                                       'win32' else 'utf-8')

        self.assertEqual(home_val, env[home_var])

        if sys.platform == 'win32':
            user_var = 'USERNAME'
        else:
            user_var = 'USER'

        user_val = os.environ[user_var]
        if sys.version_info < (3, ):
            user_val = user_val.decode(locale.getpreferredencoding() if sys.
                                       platform == 'win32' else 'utf-8')

        self.assertEqual(user_val, env[user_var])

        self.assertTrue(len(env) > 5)

        for key in env:
            self.assertEqual(str_cls, type(key))
            self.assertEqual(str_cls, type(env[key]))
Beispiel #5
0
    def test_build_no_gopath(self):
        ensure_not_ui_thread()

        shell, env = shellenv.get_env()
        if 'GOPATH' in env:
            del env['GOPATH']
        with GolangBuildMock(shell=shell, env=env):

            file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')

            def _run_build(view, result_queue):
                notify_user(
                    'Press the "Open Documentation" button when prompted about GOPATH not being set'
                )

                view.window().run_command('golang_build')

            custom_view_settings = VIEW_SETTINGS.copy()
            del custom_view_settings['GOPATH']
            open_file(file_path, custom_view_settings, _run_build)
            time.sleep(0.5)
            self.assertTrue(
                confirm_user('Were you prompted that GOPATH was not set?'))
            self.assertTrue(
                confirm_user(
                    'When you pressed "Open Documentation", was it opened in your browser?'
                ))
Beispiel #6
0
    def get_env(self, shell):
        shell, env = shellenv.get_env(shell)

        self.assertEqual(str_cls, type(shell))

        if sys.platform == 'win32':
            home_var = 'HOMEPATH'
        else:
            home_var = 'HOME'

        home_val = os.environ[home_var]
        if sys.version_info < (3,):
            home_val = home_val.decode('mbcs' if sys.platform == 'win32' else 'utf-8')

        self.assertEqual(home_val, env[home_var])

        if sys.platform == 'win32':
            user_var = 'USERNAME'
        else:
            user_var = 'USER'

        user_val = os.environ[user_var]
        if sys.version_info < (3,):
            user_val = user_val.decode(locale.getpreferredencoding() if sys.platform == 'win32' else 'utf-8')

        self.assertEqual(user_val, env[user_var])

        self.assertTrue(len(env) > 5)

        for key in env:
            self.assertEqual(str_cls, type(key))
            self.assertEqual(str_cls, type(env[key]))
Beispiel #7
0
    def run(self):
        """
        Runs the "golang_build_terminal" command - invoked by Sublime Text via
        the command palette or sublime.Window.run_command()
        """

        working_dir = _determine_working_dir(self.window)
        if working_dir is None:
            return

        relevant_sources = set([
            'project file', 'project file (os-specific)',
            'golang.sublime-settings', 'golang.sublime-settings (os-specific)'
        ])

        env_overrides = {}
        for var_name in GO_ENV_VARS:
            value, source = golangconfig.setting_value(var_name,
                                                       window=self.window)
            # Only set overrides that are not coming from the user's shell
            if source in relevant_sources:
                env_overrides[var_name] = value

        # Get the PATH from the shell environment and then prepend any custom
        # value so the user's terminal searches all locations
        value, source = golangconfig.setting_value('PATH', window=self.window)
        if source in relevant_sources:
            shell, env = shellenv.get_env()
            env_overrides['PATH'] = value + os.pathsep + env.get('PATH', '')

        newterm.launch_terminal(working_dir, env=env_overrides)
def git_commit_info(package_dir):
    """
    Get the git SHA1 hash, commit date and summary for the current git commit

    :param package_dir:
        A unicode string of the filesystem path to the folder containing the
        package

    :return:
        A tuple containing:
        [0] A unicode string of the short commit hash
        [1] A datetime.datetime object of the commit date
        [2] A unicode string of the commit message summary
    """

    startupinfo = None
    if sys.platform == 'win32':
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

    _, env = shellenv.get_env(for_subprocess=True)
    proc = subprocess.Popen(
        ['git', 'log', '-n', '1', "--pretty=format:%h %at %s", 'HEAD'],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        env=env,
        cwd=package_dir,
        startupinfo=startupinfo
    )
    stdout, stderr = proc.communicate()
    if stderr:
        raise OSError(stderr.decode('utf-8').strip())
    parts = stdout.decode('utf-8').strip().split(' ', 2)
    return (parts[0], datetime.utcfromtimestamp(int(parts[1])), parts[2])
def is_git_clean(package_dir):
    """
    Detects if the git repository is currently all committed

    :param package_dir:
        A unicode string of the filesystem path to the folder containing the
        package

    :return:
        A boolean - if the repository is clean
    """

    startupinfo = None
    if sys.platform == 'win32':
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

    _, env = shellenv.get_env(for_subprocess=True)
    proc = subprocess.Popen(
        ['git', 'status', '--porcelain'],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        env=env,
        cwd=package_dir,
        startupinfo=startupinfo
    )
    stdout, stderr = proc.communicate()
    if stderr:
        raise OSError(stderr.decode('utf-8').strip())
    return len(stdout.decode('utf-8').strip()) == 0
def run_os_command(cmd):
    shell = os.name == 'nt'

    try:

        options = {
            'shell': shell,
            'stdout': subprocess.PIPE,
            'stderr': subprocess.STDOUT,
            'universal_newlines': False,
        }

        if not shell:
            options['env'] = {}
            options['env'].update({'PATH': shellenv.get_env()[1]['PATH']})

        proc = subprocess.Popen(cmd, **options)
        output = proc.communicate()[0].decode()

        debug('run_os_command: output', output)

        return output

    except Exception as e:
        debug('run_os_command: exception', str(e))
        return "ERROR: run_os_command: {0}".format(e)
    def run(self):
        """
        Runs the "golang_build_terminal" command - invoked by Sublime Text via
        the command palette or sublime.Window.run_command()
        """

        working_dir = _determine_working_dir(self.window)
        if working_dir is None:
            return

        relevant_sources = set([
            'project file',
            'project file (os-specific)',
            'golang.sublime-settings',
            'golang.sublime-settings (os-specific)'
        ])

        env_overrides = {}
        for var_name in GO_ENV_VARS:
            value, source = golangconfig.setting_value(var_name, window=self.window)
            # Only set overrides that are not coming from the user's shell
            if source in relevant_sources:
                env_overrides[var_name] = value

        # Get the PATH from the shell environment and then prepend any custom
        # value so the user's terminal searches all locations
        value, source = golangconfig.setting_value('PATH', window=self.window)
        if source in relevant_sources:
            shell, env = shellenv.get_env()
            env_overrides['PATH'] = value + os.pathsep + env.get('PATH', '')

        newterm.launch_terminal(working_dir, env=env_overrides)
Beispiel #12
0
    def guru(self, end_offset, begin_offset=None, mode="describe", callback=None):
        """ Builds the guru shell command and calls it, returning it's output as a string.
        """

        pos = "#" + str(end_offset)
        if begin_offset is not None:
            pos = "#%i,#%i" %(begin_offset, end_offset)

        file_path = self.view.file_name()

        # golang config or shellenv ?
        cmd_env = ''
        if use_golangconfig:
            try:
                toolpath, cmd_env = golangconfig.subprocess_info('guru', ['GOPATH', 'PATH'], view=self.view)
                toolpath = os.path.realpath(toolpath)
            except:
                error("golangconfig:", sys.exc_info())
                return
        else:
            toolpath = 'guru'
            cmd_env = shellenv.get_env(for_subprocess=True)[1]
            cmd_env.update(get_setting("env", {}))

        debug("env", cmd_env)

        guru_scope = ",".join(get_setting("guru_scope", ""))

        # add local package to guru scope
        if get_setting("use_current_package", True) :
            current_file_path = os.path.realpath(os.path.dirname(file_path))
            GOPATH = os.path.realpath(cmd_env["GOPATH"])
            GOPATH = os.path.join(GOPATH,"src")
            local_package = os.path.relpath(current_file_path, GOPATH)
            if sublime.platform() == 'windows':
                local_package = local_package.replace('\\', '/')
            debug("GOPATH", GOPATH)
            debug("local_package", local_package)
            guru_scope = guru_scope+','+local_package
        guru_scope = guru_scope.strip()
        debug("guru_scope", guru_scope)
        if len(guru_scope) > 0:
            guru_scope = "-scope "+guru_scope

        guru_json = ""
        if get_setting("guru_json", False):
            guru_json = "-json"

        # Build guru cmd.
        cmd = "%(toolpath)s %(scope)s %(guru_json)s %(mode)s %(file_path)s:%(pos)s" % {
        "toolpath": toolpath,
        "file_path": file_path,
        "pos": pos,
        "guru_json": guru_json,
        "mode": mode,
        "scope": guru_scope} 
        debug("cmd", cmd)

        sublime.set_timeout_async(lambda: self.runInThread(cmd, callback, cmd_env), 0)
    def run_command(self,
                    command,
                    callback=None,
                    show_status=True,
                    filter_empty_args=True,
                    **kwargs):

        shell = False

        if filter_empty_args:
            command = [arg for arg in command if arg]

        if 'working_dir' not in kwargs:
            kwargs['working_dir'] = self.get_working_dir()
        s = sublime.load_settings("Nodejs.sublime-settings")

        if s.get('save_first') and self.active_view() and self.active_view(
        ).is_dirty():
            self.active_view().run_command('save')

        if command[0] == 'node':
            if s.get('node_command'):
                self.insert_command_with_args(s.get('node_command'), command)
            if s.get('node_path'):
                kwargs['env'] = {"NODE_PATH": str(s.get('node_path'))}

        if command[0] == 'npm' and s.get('npm_command'):
            self.insert_command_with_args(s.get('npm_command'), command)

        debug("NodeCommand: run_command: command", command)

        # update paths for searching executables
        kwargs['env'] = {}
        kwargs['env'].update({'PATH': shellenv.get_env()[1]['PATH']})

        if not callback:
            callback = self.generic_done

        if os.name == 'nt':
            shell = True
            # doing exception for debugger commands to be able
            # get PID of node.exe on Windows not cmd.exe
            debug("NodeCommand: run_command: class name",
                  self.__class__.__name__)
            if self.__class__.__name__.lower().find("drun") != -1:
                shell = False

        kwargs['shell'] = shell
        debug("NodeCommand: run_command: kwargs", kwargs)

        thread = CommandThread(command, callback, **kwargs)
        thread.start()

        if show_status:
            message = kwargs.get('status_message', False) or ' '.join(command)
            sublime.status_message(message)
    def get_env_for_subprocess(self, shell):
        shell, env = shellenv.get_env(shell, for_subprocess=True)

        self.assertEqual(str, type(shell))

        self.assertTrue(len(env) > 5)

        for key in env:
            self.assertEqual(str, type(key))
            self.assertEqual(str, type(env[key]))
Beispiel #15
0
    def get_env_for_subprocess(self, shell):
        shell, env = shellenv.get_env(shell, for_subprocess=True)

        self.assertEqual(str, type(shell))

        self.assertTrue(len(env) > 5)

        for key in env:
            self.assertEqual(str, type(key))
            self.assertEqual(str, type(env[key]))
    def run_command(self, command, callback=None, show_status=True,
                    filter_empty_args=True, **kwargs):

        shell = False

        if filter_empty_args:
            command = [arg for arg in command if arg]

        if 'working_dir' not in kwargs:
            kwargs['working_dir'] = self.get_working_dir()
        s = sublime.load_settings("Nodejs.sublime-settings")

        if s.get('save_first') and self.active_view() and self.active_view().is_dirty():
            self.active_view().run_command('save')

        if command[0] == 'node':
            if s.get('node_command'):
                command[0] = s.get('node_command')
            if s.get('node_path'):
                kwargs['env'] = {"NODE_PATH": str(s.get('node_path'))}

        if command[0] == 'npm' and s.get('npm_command'):
            command[0] = s.get('npm_command')

        # update paths for searching executables
        kwargs['env'] = {}
        kwargs['env'].update({'PATH': shellenv.get_env()[1]['PATH']})

        if not callback:
            callback = self.generic_done

        if os.name == 'nt':
            shell = True
            # doing exception for debugger commands to be able 
            # get PID of node.exe on Windows not cmd.exe
            debug("NodeCommand: run_command: class name", self.__class__.__name__)
            if self.__class__.__name__.lower().find("drun") != -1:
                shell = False
        
        kwargs['shell'] = shell
        debug("NodeCommand: run_command: kwargs", kwargs)

        thread = CommandThread(command, callback, **kwargs)
        thread.start()

        if show_status:
            message = kwargs.get('status_message', False) or ' '.join(command)
            sublime.status_message(message)
Beispiel #17
0
    def guru(self,
             end_offset,
             begin_offset=None,
             mode="describe",
             callback=None):
        """ Builds the guru shell command and calls it, returning it's output as a string.
        """

        pos = "#" + str(end_offset)
        if begin_offset is not None:
            pos = "#%i,#%i" % (begin_offset, end_offset)

        #Set GOOS based on os at the end of the file name.
        #TODO Check file header for builds.
        file_path = self.view.file_name()

        merged_env = shellenv.get_env(for_subprocess=True)[1]
        merged_env.update(get_setting("env", {}))
        debug("env", merged_env)

        guru_scope = ",".join(get_setting("guru_scope", ""))

        # assumed local package
        if get_setting("use_current_package", True):
            current_file_path = os.path.realpath(os.path.dirname(file_path))
            GOPATH = os.path.realpath(merged_env["GOPATH"] + "/src") + "/"
            local_package = current_file_path.replace(GOPATH, "")
            debug("current_file_path", current_file_path)
            debug("GOPATH", GOPATH)
            debug("local_package", local_package)
            guru_scope = guru_scope + ',' + local_package
        guru_scope = guru_scope.strip()
        debug("guru_scope", guru_scope)
        if len(guru_scope) > 0:
            guru_scope = "-scope " + guru_scope

        # Build guru cmd.
        cmd = "guru %(scope)s -format=%(output_format)s %(mode)s %(file_path)s:%(pos)s" % {
            "file_path": file_path,
            "pos": pos,
            "output_format": get_setting("guru_format"),
            "mode": mode,
            "scope": guru_scope
        }
        debug("cmd", cmd)

        sublime.set_timeout_async(
            lambda: self.runInThread(cmd, callback, merged_env), 0)
Beispiel #18
0
    def test_build_go_missing(self):
        ensure_not_ui_thread()

        shell, _ = shellenv.get_env()
        search_path = path.expanduser('~')
        with GolangBuildMock(shell=shell, env={'PATH': search_path}):

            file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')

            def _run_build(view, result_queue):
                notify_user('Press the "Open Documentation" button when prompted about go not being found in the PATH')

                view.window().run_command('golang_build')

            open_file(file_path, VIEW_SETTINGS, _run_build)
            time.sleep(0.5)
            self.assertTrue(confirm_user('Were you prompted that go could not be found in the PATH?'))
            self.assertTrue(confirm_user('When you pressed "Open Documentation", was it opened in your browser?'))
Beispiel #19
0
    def guru(self, end_offset, begin_offset=None, mode="describe", callback=None):
        """ Builds the guru shell command and calls it, returning it's output as a string.
        """

        pos = "#" + str(end_offset)
        if begin_offset is not None:
            pos = "#%i,#%i" %(begin_offset, end_offset)

        #Set GOOS based on os at the end of the file name.
        #TODO Check file header for builds.
        file_path = self.view.file_name()


        merged_env = shellenv.get_env(for_subprocess=True)[1]
        merged_env.update(get_setting("env", {}))
        debug("env", merged_env)

        guru_scope = ",".join(get_setting("guru_scope", ""))

        # assumed local package 
        if get_setting("use_current_package", True) :
            current_file_path = os.path.realpath(os.path.dirname(file_path))
            GOPATH = os.path.realpath(merged_env["GOPATH"]+"/src")+"/"
            local_package = current_file_path.replace(GOPATH, "")
            debug("current_file_path", current_file_path)
            debug("GOPATH", GOPATH)
            debug("local_package", local_package)
            guru_scope = guru_scope+','+local_package
        guru_scope = guru_scope.strip()
        debug("guru_scope", guru_scope)
        if len(guru_scope) > 0:
            guru_scope = "-scope "+guru_scope

        # Build guru cmd.
        cmd = "guru %(scope)s -format=%(output_format)s %(mode)s %(file_path)s:%(pos)s" % {
        "file_path": file_path,
        "pos": pos,
        "output_format": get_setting("guru_format"),
        "mode": mode,
        "scope": guru_scope} 
        debug("cmd", cmd)

        sublime.set_timeout_async(lambda: self.runInThread(cmd, callback, merged_env), 0)
Beispiel #20
0
class Nvm(object):
    """
    The class for work with NVM if it is installed in system
    """
    nvm_file = '.nvmrc'

    user_env = shellenv.get_env()[1]

    current_node_version = ''
    current_node_path = ''

    @staticmethod
    def is_installed():
        if os.name == 'nt': return None

        if not Nvm.user_env.get('NVM_BIN', False): return False

        return True

    @staticmethod
    def node_version():
        rx = r'v\d+\.\d+\.\d+'

        if not Nvm.is_installed(): return False
        
        if not Nvm.user_env.get('NVM_SYMLINK_CURRENT', False):
            debug('NVM_SYMLINK_CURRENT', False)
            Nvm.current_node_version = re.findall(rx, 
                    Nvm.user_env.get('NVM_BIN', False))[0]
        else:
            debug('NVM_SYMLINK_CURRENT', True)
            home_dir = os.path.expanduser("~/.nvm/current")
            realpath = os.path.realpath(home_dir)
            Nvm.current_node_version = re.findall(rx, realpath)[0]
        return Nvm.current_node_version
            
    @staticmethod
    def get_current_node_path():
        if os.name == 'nt': return None

        Nvm.current_node_path = Nvm.user_env.get('NVM_BIN', False)
        return Nvm.current_node_path
    def test_build_missing_gopath(self):
        ensure_not_ui_thread()

        shell, env = shellenv.get_env()
        env['GOPATH'] += '12345678'
        with GolangBuildMock(shell=shell, env=env):

            file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go')

            def _run_build(view, result_queue):
                notify_user('Press the "Open Documentation" button when prompted about GOPATH not being found')

                view.window().run_command('golang_build')

            custom_view_settings = VIEW_SETTINGS.copy()
            del custom_view_settings['GOPATH']
            open_file(file_path, custom_view_settings, _run_build)
            time.sleep(0.5)
            self.assertTrue(confirm_user('Were you prompted that GOPATH was not found?'))
            self.assertTrue(confirm_user('When you pressed "Open Documentation", was it opened in your browser?'))
Beispiel #22
0
    def run_command(self,
                    command,
                    callback=None,
                    show_status=True,
                    filter_empty_args=True,
                    **kwargs):
        if filter_empty_args:
            command = [arg for arg in command if arg]

        if 'working_dir' not in kwargs:
            kwargs['working_dir'] = self.get_working_dir()
        s = sublime.load_settings("Nodejs.sublime-settings")

        if s.get('save_first') and self.active_view() and self.active_view(
        ).is_dirty():
            self.active_view().run_command('save')

        if command[0] == 'node':
            if s.get('node_command'):
                command[0] = s.get('node_command')
            if s.get('node_path'):
                kwargs['env'] = {"NODE_PATH": str(s.get('node_path'))}

        if command[0] == 'npm' and s.get('npm_command'):
            command[0] = s.get('npm_command')

        # update paths for searching executables
        kwargs['env'] = {}
        kwargs['env'].update({'PATH': shellenv.get_env()[1]['PATH']})

        if not callback:
            callback = self.generic_done

        thread = CommandThread(command, callback, **kwargs)
        thread.start()

        if show_status:
            message = kwargs.get('status_message', False) or ' '.join(command)
            sublime.status_message(message)
    def test_get_env_ensure_copy(self):
        shell, env = shellenv.get_env()
        env['FOOBAR'] = 'test'
        shell2, env2 = shellenv.get_env()

        self.assertEqual(None, env2.get('FOOBAR'))
Beispiel #24
0
    def run(self,
            window,
            cmd,
            cwd,
            listener,
            env=None,
            decode_json=True,
            json_stop_pattern=None):
        """Run the process.

        :param window: Sublime window.
        :param cmd: The command to run (list of strings).
        :param cwd: The directory where to run the command.
        :param listener: `ProcListener` to receive the output.
        :param env: Dictionary of environment variables to add.
        :param decode_json: If True, will check for lines starting with `{` to
            decode as a JSON message.
        :param json_stop_pattern: Regular expression used to detect when it
            should stop looking for JSON messages.  This is used by `cargo
            run` so that it does not capture output from the user's program
            that might start with an open curly brace.

        :raises ProcessTermiantedError: Process was terminated by another
            thread.
        """
        self.cmd = cmd
        self.cwd = cwd
        self.listener = listener
        self.start_time = time.time()
        self.window = window
        self.decode_json = decode_json
        self.json_stop_pattern = json_stop_pattern

        from . import rust_thread
        try:
            t = rust_thread.THREADS[window.id()]
        except KeyError:
            pass
        else:
            if t.should_exit:
                raise ProcessTerminatedError()

        with PROCS_LOCK:
            PROCS[window.id()] = self
        listener.on_begin(self)

        # Configure the environment.
        self.env = os.environ.copy()
        if util.get_setting('rust_include_shell_env', True):
            global USER_SHELL_ENV
            if USER_SHELL_ENV is None:
                USER_SHELL_ENV = shellenv.get_env()[1]
            self.env.update(USER_SHELL_ENV)

        rust_env = util.get_setting('rust_env')
        if rust_env:
            for k, v in rust_env.items():
                rust_env[k] = os.path.expandvars(v)
            self.env.update(rust_env)

        if env:
            self.env.update(env)

        # XXX: Debug config.
        util.debug('Rust running: %s', self.cmd)

        if sys.platform == 'win32':
            # Prevent a console window from popping up.
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            self.proc = subprocess.Popen(
                self.cmd,
                cwd=self.cwd,
                env=self.env,
                startupinfo=startupinfo,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
            )
        else:
            # Make the process the group leader so we can easily kill all its
            # children.
            self.proc = subprocess.Popen(
                self.cmd,
                cwd=self.cwd,
                preexec_fn=os.setpgrp,
                env=self.env,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
            )

        self._stdout_thread = threading.Thread(
            target=self._read_stdout,
            name='%s: Stdout' % (threading.current_thread().name, ))
        self._stdout_thread.start()
Beispiel #25
0
    def run(self, window, cmd, cwd, listener, env=None,
            decode_json=True, json_stop_pattern=None):
        """Run the process.

        :param window: Sublime window.
        :param cmd: The command to run (list of strings).
        :param cwd: The directory where to run the command.
        :param listener: `ProcListener` to receive the output.
        :param env: Dictionary of environment variables to add.
        :param decode_json: If True, will check for lines starting with `{` to
            decode as a JSON message.
        :param json_stop_pattern: Regular expression used to detect when it
            should stop looking for JSON messages.  This is used by `cargo
            run` so that it does not capture output from the user's program
            that might start with an open curly brace.

        :raises ProcessTermiantedError: Process was terminated by another
            thread.
        :raises OSError: Failed to launch the child process.
            `FileNotFoundError` is a typical example if the executable is not
            found.
        """
        self.cmd = cmd
        self.cwd = cwd
        self.listener = listener
        self.start_time = time.time()
        self.window = window
        self.decode_json = decode_json
        self.json_stop_pattern = json_stop_pattern

        from . import rust_thread
        try:
            t = rust_thread.THREADS[window.id()]
        except KeyError:
            pass
        else:
            if t.should_exit:
                raise ProcessTerminatedError()

        with PROCS_LOCK:
            PROCS[window.id()] = self
        listener.on_begin(self)

        # Configure the environment.
        self.env = os.environ.copy()
        if util.get_setting('rust_include_shell_env', True):
            global USER_SHELL_ENV
            if USER_SHELL_ENV is None:
                USER_SHELL_ENV = shellenv.get_env()[1]
            self.env.update(USER_SHELL_ENV)

        rust_env = util.get_setting('rust_env')
        if rust_env:
            for k, v in rust_env.items():
                rust_env[k] = os.path.expandvars(v)
            self.env.update(rust_env)

        if env:
            self.env.update(env)

        log.log(window, 'Running: %s', ' '.join(self.cmd))

        if sys.platform == 'win32':
            # Prevent a console window from popping up.
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            self.proc = subprocess.Popen(
                self.cmd,
                cwd=self.cwd,
                env=self.env,
                startupinfo=startupinfo,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
            )
        else:
            # Make the process the group leader so we can easily kill all its
            # children.
            self.proc = subprocess.Popen(
                self.cmd,
                cwd=self.cwd,
                preexec_fn=os.setpgrp,
                env=self.env,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
            )

        self._stdout_thread = threading.Thread(target=self._read_stdout,
            name='%s: Stdout' % (threading.current_thread().name,))
        self._stdout_thread.start()
Beispiel #26
0
    def test_get_env_ensure_copy(self):
        shell, env = shellenv.get_env()
        env['FOOBAR'] = 'test'
        shell2, env2 = shellenv.get_env()

        self.assertEqual(None, env2.get('FOOBAR'))
Beispiel #27
0
def subprocess_info(executable_name,
                    required_vars,
                    optional_vars=None,
                    view=None,
                    window=None):
    """
    Gathers and formats information necessary to use subprocess.Popen() to
    run one of the go executables, with details pulled from setting_value() and
    executable_path().

    Ensures that the executable path and env dictionary are properly encoded for
    Sublime Text 2, where byte strings are necessary.

    :param executable_name:
        A unicode string of the executable to locate, e.g. "go" or "gofmt"

    :param required_vars:
        A list of unicode strings of the environment variables that are
        required, e.g. "GOPATH". Obtains values from setting_value().

    :param optional_vars:
        A list of unicode strings of the environment variables that are
        optional, but should be pulled from setting_value() if available - e.g.
        "GOOS", "GOARCH". Obtains values from setting_value().

    :param view:
        A sublime.View object to use in finding project-specific settings. This
        should be passed whenever available.

    :param window:
        A sublime.Window object to use in finding project-specific settings.
        This should be passed whenever available.

    :raises:
        RuntimeError
            When the function is called from any thread but the UI thread
        TypeError
            When any of the parameters are of the wrong type
        golangconfig.ExecutableError
            When the executable requested could not be located. The .name
            attribute contains the name of the executable that could not be
            located. The .dirs attribute contains a list of unicode strings
            of the directories searched.
        golangconfig.EnvVarError
            When one or more required_vars are not available. The .missing
            attribute will be a list of the names of missing environment
            variables.

    :return:
        A two-element tuple.

         - [0] A unicode string (byte string for ST2) of the path to the executable
         - [1] A dict to pass to the env parameter of subprocess.Popen()
    """

    path, _ = executable_path(executable_name, view=view, window=window)
    if path is None:
        name = executable_name
        if sys.platform == 'win32':
            name += '.exe'
        dirs = []
        settings_path, _ = _get_most_specific_setting('PATH',
                                                      view=view,
                                                      window=window)
        if settings_path and settings_path != _NO_VALUE:
            dirs.extend(settings_path.split(os.pathsep))
        _, shell_dirs = shellenv.get_path()
        for shell_dir in shell_dirs:
            if shell_dir not in dirs:
                dirs.append(shell_dir)
        exception = ExecutableError(
            'The executable "%s" could not be located in any of the following locations: "%s"'
            % (name, '", "'.join(dirs)))
        exception.name = name
        exception.dirs = dirs
        raise exception

    path = shellenv.path_encode(path)

    _, env = shellenv.get_env(for_subprocess=True)

    var_groups = [required_vars]
    if optional_vars:
        var_groups.append(optional_vars)

    missing_vars = []

    for var_names in var_groups:
        for var_name in var_names:
            value, _ = setting_value(var_name, view=view, window=window)
            var_key = var_name

            if value is not None:
                value = str_cls(value)
                value = shellenv.env_encode(value)
            var_key = shellenv.env_encode(var_key)

            if value is None:
                if var_key in env:
                    del env[var_key]
                continue

            env[var_key] = value

    for required_var in required_vars:
        var_key = shellenv.env_encode(required_var)
        if var_key not in env:
            missing_vars.append(required_var)

    if missing_vars:
        missing_vars = sorted(missing_vars, key=lambda s: s.lower())
        exception = EnvVarError(
            'The following environment variable%s currently unset: %s' %
            ('s are' if len(missing_vars) > 1 else ' is',
             ', '.join(missing_vars)))
        exception.missing = missing_vars
        raise exception

    encoded_goroot = shellenv.env_encode('GOROOT')
    if encoded_goroot in env:
        unicode_sep = shellenv.path_decode(os.sep)
        name = executable_name
        if sys.platform == 'win32':
            name += '.exe'
        relative_executable_path = shellenv.path_encode('bin%s%s' %
                                                        (unicode_sep, name))
        goroot_executable_path = os.path.join(env[encoded_goroot],
                                              relative_executable_path)
        if goroot_executable_path != path:
            print(
                'golangconfig: warning - binary %s was found at "%s", which is not inside of the GOROOT "%s"'
                % (executable_name, path,
                   shellenv.path_decode(env[encoded_goroot])))

    return (path, env)
Beispiel #28
0
def setting_value(setting_name, view=None, window=None):
    """
    Returns the user's setting for a specific variable, such as GOPATH or
    GOROOT. Supports global and per-platform settings. Finds settings by
    looking in:

    1. If a project is open, the project settings
    2. The global golang.sublime-settings file
    3. The user's environment variables, as defined by their login shell

    If the setting is a known name, e.g. GOPATH or GOROOT, the value will be
    checked to ensure the path exists.

    :param setting_name:
        A unicode string of the setting to retrieve

    :param view:
        A sublime.View object to use in finding project-specific settings. This
        should be passed whenever available.

    :param window:
        A sublime.Window object to use in finding project-specific settings.
        This should be passed whenever available.

    :raises:
        RuntimeError
            When the function is called from any thread but the UI thread
        TypeError
            When any of the parameters are of the wrong type

    :return:
        A two-element tuple.

        If no setting was found, the return value will be:

         - [0] None
         - [1] None

        If a setting was found, the return value will be:

         - [0] The setting value
         - [1] The source of the setting, a unicode string:
           - "project file (os-specific)"
           - "golang.sublime-settings (os-specific)"
           - "project file"
           - "golang.sublime-settings"
           - A unicode string of the path to the user's login shell

        The second element of the tuple is intended to be used in the display
        of debugging information to end users.
    """

    _require_unicode('setting_name', setting_name)
    _check_view_window(view, window)

    setting, source = _get_most_specific_setting(setting_name, view, window)

    if setting == _NO_VALUE:
        setting = None
        source = None

        shell, env = shellenv.get_env()
        if setting_name in env:
            source = shell
            setting = env[setting_name]

    if setting_name not in set(['GOPATH', 'GOROOT']):
        return (setting, source)

    # We add some extra processing here for known settings to improve the
    # user experience, especially around debugging
    is_str = isinstance(setting, str_cls)
    if is_str:
        if os.path.exists(setting):
            return (setting, source)

        if debug_enabled():
            print(
                'golangconfig: the value for %s from %s - "%s" - does not exist on the filesystem'
                % (setting_name, source, setting))

    elif debug_enabled():
        _debug_unicode_string(setting_name, setting, source)

    return (None, None)
def subprocess_info(executable_name, required_vars, optional_vars=None, view=None, window=None):
    """
    Gathers and formats information necessary to use subprocess.Popen() to
    run one of the go executables, with details pulled from setting_value() and
    executable_path().

    Ensures that the executable path and env dictionary are properly encoded for
    Sublime Text 2, where byte strings are necessary.

    :param executable_name:
        A unicode string of the executable to locate, e.g. "go" or "gofmt"

    :param required_vars:
        A list of unicode strings of the environment variables that are
        required, e.g. "GOPATH". Obtains values from setting_value().

    :param optional_vars:
        A list of unicode strings of the environment variables that are
        optional, but should be pulled from setting_value() if available - e.g.
        "GOOS", "GOARCH". Obtains values from setting_value().

    :param view:
        A sublime.View object to use in finding project-specific settings. This
        should be passed whenever available.

    :param window:
        A sublime.Window object to use in finding project-specific settings.
        This should be passed whenever available.

    :raises:
        RuntimeError
            When the function is called from any thread but the UI thread
        TypeError
            When any of the parameters are of the wrong type
        golangconfig.ExecutableError
            When the executable requested could not be located. The .name
            attribute contains the name of the executable that could not be
            located. The .dirs attribute contains a list of unicode strings
            of the directories searched.
        golangconfig.EnvVarError
            When one or more required_vars are not available. The .missing
            attribute will be a list of the names of missing environment
            variables.
        golangconfig.GoPathNotFoundError
            When one or more directories specified by the GOPATH environment
            variable could not be found on disk. The .directories attribute will
            be a list of the directories that could not be found.
        golangconfig.GoRootNotFoundError
            When the directory specified by GOROOT environment variable could
            not be found on disk. The .directory attribute will be the path to
            the directory that could not be found.

        golangconfig.EnvVarError
            When one or more required_vars are not available. The .missing
            attribute will be a list of the names of missing environment
            variables.

    :return:
        A two-element tuple.

         - [0] A unicode string (byte string for ST2) of the path to the executable
         - [1] A dict to pass to the env parameter of subprocess.Popen()
    """

    path, _ = executable_path(executable_name, view=view, window=window)
    if path is None:
        name = executable_name
        if sys.platform == 'win32':
            name += '.exe'
        dirs = []
        settings_path, _ = _get_most_specific_setting('PATH', view=view, window=window)
        if settings_path and settings_path != _NO_VALUE:
            dirs.extend(settings_path.split(os.pathsep))
        _, shell_dirs = shellenv.get_path()
        for shell_dir in shell_dirs:
            if shell_dir not in dirs:
                dirs.append(shell_dir)
        exception = ExecutableError(
            'The executable "%s" could not be located in any of the following locations: "%s"' %
            (
                name,
                '", "'.join(dirs)
            )
        )
        exception.name = name
        exception.dirs = dirs
        raise exception

    path = shellenv.path_encode(path)

    _, env = shellenv.get_env(for_subprocess=True)

    var_groups = [required_vars]
    if optional_vars:
        var_groups.append(optional_vars)

    missing_vars = []

    for var_names in var_groups:
        for var_name in var_names:
            value, _ = setting_value(var_name, view=view, window=window)
            var_key = var_name

            if value is not None:
                value = str_cls(value)
                value = shellenv.env_encode(value)
            var_key = shellenv.env_encode(var_key)

            if value is None:
                if var_key in env:
                    del env[var_key]
                continue

            env[var_key] = value

    for required_var in required_vars:
        var_key = shellenv.env_encode(required_var)
        if var_key not in env:
            missing_vars.append(required_var)

    if missing_vars:
        missing_vars = sorted(missing_vars, key=lambda s: s.lower())
        exception = EnvVarError(
            'The following environment variable%s currently unset: %s' %
            (
                's are' if len(missing_vars) > 1 else ' is',
                ', '.join(missing_vars)
            )
        )
        exception.missing = missing_vars
        raise exception

    encoded_goroot = shellenv.env_encode('GOROOT')
    if encoded_goroot in env:
        unicode_sep = shellenv.path_decode(os.sep)
        name = executable_name
        if sys.platform == 'win32':
            name += '.exe'
        relative_executable_path = shellenv.path_encode('bin%s%s' % (unicode_sep, name))
        goroot_executable_path = os.path.join(env[encoded_goroot], relative_executable_path)
        if goroot_executable_path != path:
            print(
                'golangconfig: warning - binary %s was found at "%s", which is not inside of the GOROOT "%s"' %
                (
                    executable_name,
                    path,
                    shellenv.path_decode(env[encoded_goroot])
                )
            )

    return (path, env)
def setting_value(setting_name, view=None, window=None):
    """
    Returns the user's setting for a specific variable, such as GOPATH or
    GOROOT. Supports global and per-platform settings. Finds settings by
    looking in:

    1. If a project is open, the project settings
    2. The global golang.sublime-settings file
    3. The user's environment variables, as defined by their login shell

    If the setting is a known name, e.g. GOPATH or GOROOT, the value will be
    checked to ensure the path exists.

    :param setting_name:
        A unicode string of the setting to retrieve

    :param view:
        A sublime.View object to use in finding project-specific settings. This
        should be passed whenever available.

    :param window:
        A sublime.Window object to use in finding project-specific settings.
        This should be passed whenever available.

    :raises:
        RuntimeError
            When the function is called from any thread but the UI thread
        TypeError
            When any of the parameters are of the wrong type
        golangconfig.GoPathNotFoundError
            When one or more directories specified by the GOPATH environment
            variable could not be found on disk. The .directories attribute will
            be a list of the directories that could not be found.
        golangconfig.GoRootNotFoundError
            When the directory specified by GOROOT environment variable could
            not be found on disk. The .directory attribute will be the path to
            the directory that could not be found.

    :return:
        A two-element tuple.

        If no setting was found, the return value will be:

         - [0] None
         - [1] None

        If a setting was found, the return value will be:

         - [0] The setting value
         - [1] The source of the setting, a unicode string:
           - "project file (os-specific)"
           - "golang.sublime-settings (os-specific)"
           - "project file"
           - "golang.sublime-settings"
           - A unicode string of the path to the user's login shell

        The second element of the tuple is intended to be used in the display
        of debugging information to end users.
    """

    _require_unicode('setting_name', setting_name)
    _check_view_window(view, window)

    setting, source = _get_most_specific_setting(setting_name, view, window)

    if setting == _NO_VALUE:
        setting = None
        source = None

        shell, env = shellenv.get_env()
        if setting_name in env:
            source = shell
            setting = env[setting_name]

    if setting_name not in set(['GOPATH', 'GOROOT']):
        return (setting, source)

    if setting is None and source is None:
        return (setting, source)

    # We add some extra processing here for known settings to improve the
    # user experience, especially around debugging
    _debug_unicode_string(setting_name, setting, source)

    if not isinstance(setting, str_cls):
        setting = str_cls(setting)

    if setting_name == 'GOROOT':
        if os.path.exists(setting):
            return (setting, source)

    has_multiple = False
    if setting_name == 'GOPATH':
        values = setting.split(os.pathsep)
        has_multiple = len(values) > 1
        missing = []

        for value in values:
            if not os.path.exists(value):
                missing.append(value)

        if not missing:
            return (setting, source)

    if setting_name == 'GOROOT':
        message = 'The GOROOT environment variable value "%s" does not exist on the filesystem'
        e = GoRootNotFoundError(message % setting)
        e.directory = setting
        raise e

    if not has_multiple:
        suffix = 'value "%s" does not exist on the filesystem' % missing[0]
    elif len(missing) == 1:
        suffix = 'contains the directory "%s" that does not exist on the filesystem' % missing[0]
    else:
        paths = ', '.join('"' + path + '"' for path in missing)
        suffix = 'contains %s directories that do not exist on the filesystem: %s' % (len(missing), paths)

    message = 'The GOPATH environment variable ' + suffix
    e = GoPathNotFoundError(message)
    e.directories = missing
    raise e
Beispiel #31
0
def get_env():
    _, env = shellenv.get_env()
    return env
Beispiel #32
0
def setting_value(setting_name, view=None, window=None):
    """
    Returns the user's setting for a specific variable, such as GOPATH or
    GOROOT. Supports global and per-platform settings. Finds settings by
    looking in:

    1. If a project is open, the project settings
    2. The global golang.sublime-settings file
    3. The user's environment variables, as defined by their login shell

    If the setting is a known name, e.g. GOPATH or GOROOT, the value will be
    checked to ensure the path exists.

    :param setting_name:
        A unicode string of the setting to retrieve

    :param view:
        A sublime.View object to use in finding project-specific settings. This
        should be passed whenever available.

    :param window:
        A sublime.Window object to use in finding project-specific settings.
        This should be passed whenever available.

    :raises:
        RuntimeError
            When the function is called from any thread but the UI thread
        TypeError
            When any of the parameters are of the wrong type
        golangconfig.GoPathNotFoundError
            When one or more directories specified by the GOPATH environment
            variable could not be found on disk. The .directories attribute will
            be a list of the directories that could not be found.
        golangconfig.GoRootNotFoundError
            When the directory specified by GOROOT environment variable could
            not be found on disk. The .directory attribute will be the path to
            the directory that could not be found.

    :return:
        A two-element tuple.

        If no setting was found, the return value will be:

         - [0] None
         - [1] None

        If a setting was found, the return value will be:

         - [0] The setting value
         - [1] The source of the setting, a unicode string:
           - "project file (os-specific)"
           - "golang.sublime-settings (os-specific)"
           - "project file"
           - "golang.sublime-settings"
           - A unicode string of the path to the user's login shell

        The second element of the tuple is intended to be used in the display
        of debugging information to end users.
    """

    _require_unicode('setting_name', setting_name)
    _check_view_window(view, window)

    setting, source = _get_most_specific_setting(setting_name, view, window)

    if setting == _NO_VALUE:
        setting = None
        source = None

        shell, env = shellenv.get_env()
        if setting_name in env:
            source = shell
            setting = env[setting_name]

    if setting_name not in set(['GOPATH', 'GOROOT']):
        return (setting, source)

    if setting is None and source is None:
        return (setting, source)

    # We add some extra processing here for known settings to improve the
    # user experience, especially around debugging
    _debug_unicode_string(setting_name, setting, source)

    if not isinstance(setting, str_cls):
        setting = str_cls(setting)

    if setting_name == 'GOROOT':
        if os.path.exists(setting):
            return (setting, source)

    has_multiple = False
    if setting_name == 'GOPATH':
        values = setting.split(os.pathsep)
        has_multiple = len(values) > 1
        missing = []

        for value in values:
            if not os.path.exists(value):
                missing.append(value)

        if not missing:
            return (setting, source)

    if setting_name == 'GOROOT':
        message = 'The GOROOT environment variable value "%s" does not exist on the filesystem'
        e = GoRootNotFoundError(message % setting)
        e.directory = setting
        raise e

    if not has_multiple:
        suffix = 'value "%s" does not exist on the filesystem' % missing[0]
    elif len(missing) == 1:
        suffix = 'contains the directory "%s" that does not exist on the filesystem' % missing[
            0]
    else:
        paths = ', '.join('"' + path + '"' for path in missing)
        suffix = 'contains %s directories that do not exist on the filesystem: %s' % (
            len(missing), paths)

    message = 'The GOPATH environment variable ' + suffix
    e = GoPathNotFoundError(message)
    e.directories = missing
    raise e
Beispiel #33
0

# import lib's modules
from .lib.nodejs_debug import debug, info
from .lib.nodejs_constants import *
from .lib.nodejs_paths import *
from .lib.nodejs_commands import *
from .lib.nodejs_nvm import *


debug('PLUGIN_PATH', PLUGIN_PATH)
debug('PLUGIN_LIB_DIR', PLUGIN_LIB_DIR)
debug('PLUGIN_DEBUG_FILE', PLUGIN_DEBUG_FILE)
debug('UGLIFY_PATH', UGLIFY_PATH)
debug('BUILDER_PATH', BUILDER_PATH)
debug('SHELLENV', shellenv.get_env())


def generate_completions():
    info('Running `node_builddocs` to generate Node.js completions')
    sublime.active_window().run_command('node_builddocs')


def check_and_install_dependencies():
    """
    The function is dosen't check whether npm/node is installed or not.
    """
    # check if already installed
    if os.path.exists(PLUGIN_PACKAGE_LOCK):
        return
Beispiel #34
0
def setting_value(setting_name, view=None, window=None):
    """
    Returns the user's setting for a specific variable, such as GOPATH or
    GOROOT. Supports global and per-platform settings. Finds settings by
    looking in:

    1. If a project is open, the project settings
    2. The global golang.sublime-settings file
    3. The user's environment variables, as defined by their login shell

    If the setting is a known name, e.g. GOPATH or GOROOT, the value will be
    checked to ensure the path exists.

    :param setting_name:
        A unicode string of the setting to retrieve

    :param view:
        A sublime.View object to use in finding project-specific settings. This
        should be passed whenever available.

    :param window:
        A sublime.Window object to use in finding project-specific settings.
        This should be passed whenever available.

    :raises:
        RuntimeError
            When the function is called from any thread but the UI thread
        TypeError
            When any of the parameters are of the wrong type

    :return:
        A two-element tuple.

        If no setting was found, the return value will be:

         - [0] None
         - [1] None

        If a setting was found, the return value will be:

         - [0] The setting value
         - [1] The source of the setting, a unicode string:
           - "project file (os-specific)"
           - "golang.sublime-settings (os-specific)"
           - "project file"
           - "golang.sublime-settings"
           - A unicode string of the path to the user's login shell

        The second element of the tuple is intended to be used in the display
        of debugging information to end users.
    """

    _require_unicode('setting_name', setting_name)
    _check_view_window(view, window)

    setting, source = _get_most_specific_setting(setting_name, view, window)

    if setting == _NO_VALUE:
        setting = None
        source = None

        shell, env = shellenv.get_env()
        if setting_name in env:
            source = shell
            setting = env[setting_name]

    if setting_name not in set(['GOPATH', 'GOROOT']):
        return (setting, source)

    # We add some extra processing here for known settings to improve the
    # user experience, especially around debugging
    is_str = isinstance(setting, str_cls)
    if is_str:
        if os.path.exists(setting):
            return (setting, source)

        if debug_enabled():
            print(
                'golangconfig: the value for %s from %s - "%s" - does not exist on the filesystem' %
                (
                    setting_name,
                    source,
                    setting
                )
            )

    elif debug_enabled():
        _debug_unicode_string(setting_name, setting, source)

    return (None, None)