<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

import subprocess
import os
import re
import time
import sublime

from . import Messages
from .Preferences import Preferences
from .I18n import I18n
from .Paths import getEnvBinDir

_ = I18n().translate


class CommandsPy(object):
    """
    Class to handle the different functions allowed by
    the platformio API, to know more information visit
    the web site: www.platformio.org
    """

    def __init__(self, console=False, env_path=False, cwd=None):
        super(CommandsPy, self).__init__()
        env_bin_dir = getEnvBinDir()
        self.python = os.path.join(env_bin_dir, 'python')
        self.Preferences = Preferences()
        self.error_running = False
        self.console = console
        self.cwd = cwd

        # not use env vars in osx
        if(sublime.platform() == 'osx'):
            return

        # env_path from preferences
        if(not env_path):
            env_path = self.Preferences.get('env_path', False)

        # Set the enviroment Path
        if(env_path):
            os.environ['PATH'] = env_path

    def runCommand(self, commands, feedback=False, setReturn=False, extra_message=None, verbose=False):
        """Command

        Runs a CLI command to do/get the differents options from platformIO

        Arguments:
            commands {list} -- command to run

        Keyword Arguments:
            feedback {bool} -- if it's true shows the output in console (default: {False})
            setReturn {bool} -- if it's true return stdout (default: {False})
            extra_message {[str]} -- Push a text in the user console (default: {None})
            verbose {bool} -- When is true show full output in console (default: {False})

        Returns:
            str -- return the stdout of the command execution
        """
        real_time = True
        self.show_warning = False
        self.show_error = False
        self.previous = ''
        self.down_string = False
        self.verbose = verbose

        self.feedback = feedback
        if(feedback):
            self.message_queue = Messages.MessageQueue(self.console)
            self.message_queue.startPrint()

        if(not commands):
            return False

        # get verbose from preferences
        if(not self.verbose):
            self.verbose = self.Preferences.get('verbose_output', False)

        # get command
        self.type_build = False
        command = self.createCommand(commands)

        # time info
        current_time = time.strftime('%H:%M:%S')
        self.start_time = time.time()

        # Console message
        if(feedback):
            self.message_queue.put(feedback, current_time, extra_message)

        # run command
        process = subprocess.Popen(command, stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE, cwd=self.cwd,
                                   universal_newlines=True, shell=True)

        if(setReturn):
            output = process.communicate()
            stdout = output[0]
            stderr = output[1]
            real_time = False

        if(real_time):
            # realtime output
            while True:
                output = process.stdout.readline()
                # exit when there is nothing to show
                if output == '' and process.poll() is not None:
                    break

                self.outputFilter(output, command)

                if(output.strip()):
                    self.previous = output.lower()

        # results
        return_code = process.returncode
        self.resultsOutput(return_code)
        # return output
        if(setReturn):
            if(return_code > 0):
                print(stderr)
            return stdout

    def createCommand(self, commands):
        """
        Create the full CLI command based in the verbose mode

        Arguments:
            command {list} -- actions command to run in platformIO
        """
        options = commands[0]

        try:
            args = " ".join(commands[1:])
        except:
            args = ''

        # full verbose mode
        if(self.verbose and 'run' in options and '-e' in args and 'upload' not in args):
            args += ' -vvv'

        if(sublime.platform() == 'osx'):
            command = '"%s" -m platformio -f -c sublimetext %s %s 2>&1' % (
                self.python, options, args)
        else:
            command = "platformio -f -c sublimetext %s %s 2>&1" % (
                options, args)

        return command

    def outputFilter(self, output, command):
        """Filter

        catch the output of Popen in real time and filter it
        showing minimun information

        Arguments:
            output {[str]} -- text from Popen
            command {[str]} -- current command running
        """
        # show full output
        if(self.verbose):
            self.message_queue.put(output)
            return

        outputif = output.lower()

        # warning and errors
        if('warning:' in outputif and 'cygwin' not in outputif or
                'in function' in outputif or 'in file' in outputif or
                'error:' in outputif or '^' in outputif):

            if('^' in outputif):
                output = self.previous + output
            self.message_queue.put(output)

        if('warning:' in outputif and 'cygwin' not in outputif):
            self.show_warning = True

        if('error:' in outputif):
            self.show_error = True

        if(': programmer' in outputif):
            output = re.sub(r"[^\: ][\w\s+]+$",
                            "El programador no responde", output)
            self.message_queue.put('\n' + output)

        if(' attempt ' in outputif):
            dic = {'attempt': 'intento',
                   'of': 'de',
                   'not in sync': 'no sincronizado'}
            output = multiwordReplace(output, dic)
            self.message_queue.put('\n' + output)

        if('[info]:' in outputif):
            dic = {'Starting on': 'Iniciando en',
                   'Upload size': 'Tamaño de Carga',
                   'Sending invitation to': 'Enviando invitación a',
                   'Waiting for device': 'Esperando dispositivo',
                   'Waiting for result': 'Esperado resultado',
                   'Result': 'Resultado'}
            if("Starting" in output):
                output = '\n' + output
            output = multiwordReplace(output, dic)
            self.message_queue.put(output)

        # realtime output for build command
        if('run' in command and '-e' in command and not 'upload'):
            if('installing' in outputif):<commit_msg>Shows output errors in Deviot console when OTA upload fails<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals

import subprocess
import os
import re
import time
import sublime

from . import Messages
from .Preferences import Preferences
from .I18n import I18n
from .Paths import getEnvBinDir

_ = I18n().translate


class CommandsPy(object):
    """
    Class to handle the different functions allowed by
    the platformio API, to know more information visit
    the web site: www.platformio.org
    """

    def __init__(self, console=False, env_path=False, cwd=None):
        super(CommandsPy, self).__init__()
        env_bin_dir = getEnvBinDir()
        self.python = os.path.join(env_bin_dir, 'python')
        self.Preferences = Preferences()
        self.error_running = False
        self.console = console
        self.cwd = cwd

        # not use env vars in osx
        if(sublime.platform() == 'osx'):
            return

        # env_path from preferences
        if(not env_path):
            env_path = self.Preferences.get('env_path', False)

        # Set the enviroment Path
        if(env_path):
            os.environ['PATH'] = env_path

    def runCommand(self, commands, feedback=False, setReturn=False, extra_message=None, verbose=False):
        """Command

        Runs a CLI command to do/get the differents options from platformIO

        Arguments:
            commands {list} -- command to run

        Keyword Arguments:
            feedback {bool} -- if it's true shows the output in console (default: {False})
            setReturn {bool} -- if it's true return stdout (default: {False})
            extra_message {[str]} -- Push a text in the user console (default: {None})
            verbose {bool} -- When is true show full output in console (default: {False})

        Returns:
            str -- return the stdout of the command execution
        """
        real_time = True
        self.show_warning = False
        self.show_error = False
        self.previous = ''
        self.down_string = False
        self.verbose = verbose

        self.feedback = feedback
        if(feedback):
            self.message_queue = Messages.MessageQueue(self.console)
            self.message_queue.startPrint()

        if(not commands):
            return False

        # get verbose from preferences
        if(not self.verbose):
            self.verbose = self.Preferences.get('verbose_output', False)

        # get command
        self.type_build = False
        command = self.createCommand(commands)

        # time info
        current_time = time.strftime('%H:%M:%S')
        self.start_time = time.time()

        # Console message
        if(feedback):
            self.message_queue.put(feedback, current_time, extra_message)

        # run command
        process = subprocess.Popen(command, stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE, cwd=self.cwd,
                                   universal_newlines=True, shell=True)

        if(setReturn):
            output = process.communicate()
            stdout = output[0]
            stderr = output[1]
            real_time = False

        if(real_time):
            # realtime output
            while True:
                output = process.stdout.readline()
                # exit when there is nothing to show
                if output == '' and process.poll() is not None:
                    break

                self.outputFilter(output, command)

                if(output.strip()):
                    self.previous = output.lower()

        # results
        return_code = process.returncode
        self.resultsOutput(return_code)
        # return output
        if(setReturn):
            if(return_code > 0):
                print(stderr)
            return stdout

    def createCommand(self, commands):
        """
        Create the full CLI command based in the verbose mode

        Arguments:
            command {list} -- actions command to run in platformIO
        """
        options = commands[0]

        try:
            args = " ".join(commands[1:])
        except:
            args = ''

        # full verbose mode
        if(self.verbose and 'run' in options and '-e' in args and 'upload' not in args):
            args += ' -vvv'

        if(sublime.platform() == 'osx'):
            command = '"%s" -m platformio -f -c sublimetext %s %s 2>&1' % (
                self.python, options, args)
        else:
            command = "platformio -f -c sublimetext %s %s 2>&1" % (
                options, args)

        return command

    def outputFilter(self, output, command):
        """Filter

        catch the output of Popen in real time and filter it
        showing minimun information

        Arguments:
            output {[str]} -- text from Popen
            command {[str]} -- current command running
        """
        # show full output
        if(self.verbose):
            self.message_queue.put(output)
            return

        outputif = output.lower()

        # warning and errors
        if('warning:' in outputif and 'cygwin' not in outputif or
                'in function' in outputif or 'in file' in outputif or
                'error:' in outputif or '^' in outputif):

            if('^' in outputif):
                output = self.previous + output
            self.message_queue.put(output)

        if('warning:' in outputif and 'cygwin' not in outputif):
            self.show_warning = True

        if('error:' in outputif):
            self.show_error = True

        if(': programmer' in outputif):
            output = re.sub(r"[^\: ][\w\s+]+$",
                            "El programador no responde", output)
            self.message_queue.put('\n' + output)

        if(' attempt ' in outputif):
            dic = {'attempt': 'intento',
                   'of': 'de',
                   'not in sync': 'no sincronizado'}
            output = multiwordReplace(output, dic)
            self.message_queue.put('\n' + output)

        if('[info]:' in outputif or '[error]:' in outputif):
            dic = {'Starting on': 'Iniciando en',
                   'Upload size': 'Tamaño de Carga',
                   'Sending invitation to': 'Enviando invitación a',
                   'Waiting for device': 'Esperando dispositivo',
                   'Waiting for result': 'Esperado resultado',
                   'Result': 'Resultado',
                   'Authentication': 'Autentificación',
                   'Failed': 'Fallida'}
            if("Starting" in output):
                output = '\n' + output
            output = multiwordReplace(output, dic)
            self.message_queue.put(output)

        # realtime output for build command
        if('run' in command and '-e' in command and not 'upload'):
            if('installing' in outputif):
{'fraction_non_alphanumeric': 0.09774924253354494, 'fraction_numerical': 0.002308469196364161, 'mean_word_length': 1.7714914034386247, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '181881', 'n_tokens_mistral': 3802, 'n_tokens_neox': 3622, 'n_words': 1122}