mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Re-do dashboard ANSI colors
This commit is contained in:
		| @@ -78,8 +78,6 @@ class EsphomeyamlCommandWebSocket(tornado.websocket.WebSocketHandler): | |||||||
|                 data = yield self.proc.stdout.read_until_regex('[\n\r]') |                 data = yield self.proc.stdout.read_until_regex('[\n\r]') | ||||||
|             except tornado.iostream.StreamClosedError: |             except tornado.iostream.StreamClosedError: | ||||||
|                 break |                 break | ||||||
|             if data.endswith('\r') and random.randrange(100) < 90: |  | ||||||
|                 continue |  | ||||||
|             try: |             try: | ||||||
|                 data = data.replace('\033', '\\033') |                 data = data.replace('\033', '\\033') | ||||||
|             except UnicodeDecodeError: |             except UnicodeDecodeError: | ||||||
|   | |||||||
| @@ -57,42 +57,27 @@ i.very-large { | |||||||
|   font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace; |   font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace; | ||||||
| } | } | ||||||
|  |  | ||||||
| .log.bold { | .log-bold { font-weight: bold; } | ||||||
|   font-weight: bold; | .log-italic { font-style: italic; } | ||||||
| } | .log-underline { text-decoration: underline; } | ||||||
|  | .log-strikethrough { text-decoration: line-through; } | ||||||
| .log .v { | .log-underline.log-strikethrough { text-decoration: underline line-through; } | ||||||
|   color: #888888; | .log-fg-black { color: rgb(128,128,128); } | ||||||
| } | .log-fg-red { color: rgb(255,0,0); } | ||||||
|  | .log-fg-green { color: rgb(0,255,0); } | ||||||
| .log .d { | .log-fg-yellow { color: rgb(255,255,0); } | ||||||
|   color: #00DDDD; | .log-fg-blue { color: rgb(0,0,255); } | ||||||
| } | .log-fg-magenta { color: rgb(255,0,255); } | ||||||
|  | .log-fg-cyan { color: rgb(0,255,255); } | ||||||
| .log .c { | .log-fg-white { background-color: rgb(255,255,255); } | ||||||
|   color: magenta; | .log-bg-black { background-color: rgb(0,0,0); } | ||||||
| } | .log-bg-red { background-color: rgb(255,0,0); } | ||||||
|  | .log-bg-green { background-color: rgb(0,255,0); } | ||||||
| .log .i { | .log-bg-yellow { background-color: rgb(255,255,0); } | ||||||
|   color: limegreen; | .log-bg-blue { background-color: rgb(0,0,255); } | ||||||
| } | .log-bg-magenta { background-color: rgb(255,0,255); } | ||||||
|  | .log-bg-cyan { background-color: rgb(0,255,255); } | ||||||
| .log .w { | .log-bg-white { background-color: rgb(255,255,255); } | ||||||
|   color: yellow; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .log .e { |  | ||||||
|   color: red; |  | ||||||
|   font-weight: bold; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .log .e { |  | ||||||
|   color: red; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .log .ww { |  | ||||||
|   color: white; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .modal { | .modal { | ||||||
|   width: 95%; |   width: 95%; | ||||||
|   | |||||||
| @@ -1,26 +1,153 @@ | |||||||
| document.addEventListener('DOMContentLoaded', () => { | document.addEventListener('DOMContentLoaded', () => { | ||||||
|     M.AutoInit(document.body); |   M.AutoInit(document.body); | ||||||
|   }); | }); | ||||||
|  |  | ||||||
| const colorReplace = (input) => { | const initializeColorState = () => { | ||||||
|   input = input.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); |   return { | ||||||
|   input = input.replace(/\\033\[(?:0;)?31m/g, '<span class="e">'); |     bold: false, | ||||||
|   input = input.replace(/\\033\[(?:0?1;)?31m/g, '<span class="e bold">'); |     italic: false, | ||||||
|   input = input.replace(/\\033\[(?:0;)?32m/g, '<span class="i">'); |     underline: false, | ||||||
|   input = input.replace(/\\033\[(?:0?1;)?32m/g, '<span class="i bold">'); |     strikethrough: false, | ||||||
|   input = input.replace(/\\033\[(?:0;)?33m/g, '<span class="w">'); |     foregroundColor: false, | ||||||
|   input = input.replace(/\\033\[(?:0?1;)?33m/g, '<span class="w bold">'); |     backgroundColor: false, | ||||||
|   input = input.replace(/\\033\[(?:0;)?35m/g, '<span class="c">'); |     carriageReturn: false, | ||||||
|   input = input.replace(/\\033\[(?:0?1;)?35m/g, '<span class="c bold">'); |   }; | ||||||
|   input = input.replace(/\\033\[(?:0;)?36m/g, '<span class="d">'); | }; | ||||||
|   input = input.replace(/\\033\[(?:0?1;)?36m/g, '<span class="d bold">'); |  | ||||||
|   input = input.replace(/\\033\[(?:0;)?37m/g, '<span class="v">'); |  | ||||||
|   input = input.replace(/\\033\[(?:0?1;)?37m/g, '<span class="v bold">'); |  | ||||||
|   input = input.replace(/\\033\[(?:0;)?38m/g, '<span class="vv">'); |  | ||||||
|   input = input.replace(/\\033\[(?:0?1;)?38m/g, '<span class="vv bold">'); |  | ||||||
|   input = input.replace(/\\033\[0m/g, '</span>'); |  | ||||||
|  |  | ||||||
|   return input; | const colorReplace = (pre, state, text) => { | ||||||
|  |   const re = /(?:\033|\\033)(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g; | ||||||
|  |   let i = 0; | ||||||
|  |  | ||||||
|  |   if (state.carriageReturn) { | ||||||
|  |     pre.removeChild(pre.lastChild); | ||||||
|  |     state.carriageReturn = false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (text.includes("\r")) { | ||||||
|  |     state.carriageReturn = true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const lineSpan = document.createElement("span"); | ||||||
|  |   lineSpan.classList.add("line"); | ||||||
|  |   pre.appendChild(lineSpan); | ||||||
|  |  | ||||||
|  |   const addSpan = (content) => { | ||||||
|  |     if (content === "") | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |     const span = document.createElement("span"); | ||||||
|  |     if (state.bold) span.classList.add("log-bold"); | ||||||
|  |     if (state.italic) span.classList.add("log-italic"); | ||||||
|  |     if (state.underline) span.classList.add("log-underline"); | ||||||
|  |     if (state.strikethrough) span.classList.add("log-strikethrough"); | ||||||
|  |     if (state.foregroundColor !== null) span.classList.add(`log-fg-${state.foregroundColor}`); | ||||||
|  |     if (state.backgroundColor !== null) span.classList.add(`log-bg-${state.backgroundColor}`); | ||||||
|  |     span.appendChild(document.createTextNode(content)); | ||||||
|  |     lineSpan.appendChild(span); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   while (true) { | ||||||
|  |     const match = re.exec(text); | ||||||
|  |     if (match === null) | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |     const j = match.index; | ||||||
|  |     addSpan(text.substring(i, j)); | ||||||
|  |     i = j + match[0].length; | ||||||
|  |  | ||||||
|  |     if (match[1] === undefined) continue; | ||||||
|  |  | ||||||
|  |     for (const colorCode of match[1].split(";")) { | ||||||
|  |       switch (parseInt(colorCode)) { | ||||||
|  |         case 0: | ||||||
|  |           // reset | ||||||
|  |           state.bold = false; | ||||||
|  |           state.italic = false; | ||||||
|  |           state.underline = false; | ||||||
|  |           state.strikethrough = false; | ||||||
|  |           state.foregroundColor = null; | ||||||
|  |           state.backgroundColor = null; | ||||||
|  |           break; | ||||||
|  |         case 1: | ||||||
|  |           state.bold = true; | ||||||
|  |           break; | ||||||
|  |         case 3: | ||||||
|  |           state.italic = true; | ||||||
|  |           break; | ||||||
|  |         case 4: | ||||||
|  |           state.underline = true; | ||||||
|  |           break; | ||||||
|  |         case 9: | ||||||
|  |           state.strikethrough = true; | ||||||
|  |           break; | ||||||
|  |         case 22: | ||||||
|  |           state.bold = false; | ||||||
|  |           break; | ||||||
|  |         case 23: | ||||||
|  |           state.italic = false; | ||||||
|  |           break; | ||||||
|  |         case 24: | ||||||
|  |           state.underline = false; | ||||||
|  |           break; | ||||||
|  |         case 29: | ||||||
|  |           state.strikethrough = false; | ||||||
|  |           break; | ||||||
|  |         case 30: | ||||||
|  |           state.foregroundColor = "black"; | ||||||
|  |           break; | ||||||
|  |         case 31: | ||||||
|  |           state.foregroundColor = "red"; | ||||||
|  |           state.bold = true; | ||||||
|  |           break; | ||||||
|  |         case 32: | ||||||
|  |           state.foregroundColor = "green"; | ||||||
|  |           break; | ||||||
|  |         case 33: | ||||||
|  |           state.foregroundColor = "yellow"; | ||||||
|  |           break; | ||||||
|  |         case 34: | ||||||
|  |           state.foregroundColor = "blue"; | ||||||
|  |           break; | ||||||
|  |         case 35: | ||||||
|  |           state.foregroundColor = "magenta"; | ||||||
|  |           break; | ||||||
|  |         case 36: | ||||||
|  |           state.foregroundColor = "cyan"; | ||||||
|  |           break; | ||||||
|  |         case 37: | ||||||
|  |         case 39: | ||||||
|  |           state.foregroundColor = null; | ||||||
|  |           break; | ||||||
|  |         case 41: | ||||||
|  |           state.backgroundColor = "red"; | ||||||
|  |           break; | ||||||
|  |         case 42: | ||||||
|  |           state.backgroundColor = "green"; | ||||||
|  |           break; | ||||||
|  |         case 43: | ||||||
|  |           state.backgroundColor = "yellow"; | ||||||
|  |           break; | ||||||
|  |         case 44: | ||||||
|  |           state.backgroundColor = "blue"; | ||||||
|  |           break; | ||||||
|  |         case 45: | ||||||
|  |           state.backgroundColor = "magenta"; | ||||||
|  |           break; | ||||||
|  |         case 46: | ||||||
|  |           state.backgroundColor = "cyan"; | ||||||
|  |           break; | ||||||
|  |         case 47: | ||||||
|  |           state.backgroundColor = "white"; | ||||||
|  |           break; | ||||||
|  |         case 40: | ||||||
|  |         case 49: | ||||||
|  |           state.backgroundColor = null; | ||||||
|  |           break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   addSpan(text.substring(i)); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const removeUpdateAvailable = (filename) => { | const removeUpdateAvailable = (filename) => { | ||||||
| @@ -144,6 +271,7 @@ document.querySelectorAll(".action-show-logs").forEach((showLogs) => { | |||||||
|     const modalInstance = M.Modal.getInstance(logsModalElem); |     const modalInstance = M.Modal.getInstance(logsModalElem); | ||||||
|     const log = logsModalElem.querySelector(".log"); |     const log = logsModalElem.querySelector(".log"); | ||||||
|     log.innerHTML = ""; |     log.innerHTML = ""; | ||||||
|  |     const colorState = initializeColorState(); | ||||||
|     const stopLogsButton = logsModalElem.querySelector(".stop-logs"); |     const stopLogsButton = logsModalElem.querySelector(".stop-logs"); | ||||||
|     let stopped = false; |     let stopped = false; | ||||||
|     stopLogsButton.innerHTML = "Stop"; |     stopLogsButton.innerHTML = "Stop"; | ||||||
| @@ -156,8 +284,7 @@ document.querySelectorAll(".action-show-logs").forEach((showLogs) => { | |||||||
|     logSocket.addEventListener('message', (event) => { |     logSocket.addEventListener('message', (event) => { | ||||||
|       const data = JSON.parse(event.data); |       const data = JSON.parse(event.data); | ||||||
|       if (data.event === "line") { |       if (data.event === "line") { | ||||||
|         const msg = data.data; |         colorReplace(log, colorState, data.data); | ||||||
|         log.insertAdjacentHTML('beforeend', colorReplace(msg)); |  | ||||||
|       } else if (data.event === "exit") { |       } else if (data.event === "exit") { | ||||||
|         if (data.code === 0) { |         if (data.code === 0) { | ||||||
|           M.toast({html: "Program exited successfully."}); |           M.toast({html: "Program exited successfully."}); | ||||||
| @@ -192,6 +319,7 @@ document.querySelectorAll(".action-upload").forEach((upload) => { | |||||||
|     const modalInstance = M.Modal.getInstance(uploadModalElem); |     const modalInstance = M.Modal.getInstance(uploadModalElem); | ||||||
|     const log = uploadModalElem.querySelector(".log"); |     const log = uploadModalElem.querySelector(".log"); | ||||||
|     log.innerHTML = ""; |     log.innerHTML = ""; | ||||||
|  |     const colorState = initializeColorState(); | ||||||
|     const stopLogsButton = uploadModalElem.querySelector(".stop-logs"); |     const stopLogsButton = uploadModalElem.querySelector(".stop-logs"); | ||||||
|     let stopped = false; |     let stopped = false; | ||||||
|     stopLogsButton.innerHTML = "Stop"; |     stopLogsButton.innerHTML = "Stop"; | ||||||
| @@ -204,8 +332,7 @@ document.querySelectorAll(".action-upload").forEach((upload) => { | |||||||
|     logSocket.addEventListener('message', (event) => { |     logSocket.addEventListener('message', (event) => { | ||||||
|       const data = JSON.parse(event.data); |       const data = JSON.parse(event.data); | ||||||
|       if (data.event === "line") { |       if (data.event === "line") { | ||||||
|         const msg = data.data; |         colorReplace(log, colorState, data.data); | ||||||
|         log.insertAdjacentHTML('beforeend', colorReplace(msg)); |  | ||||||
|       } else if (data.event === "exit") { |       } else if (data.event === "exit") { | ||||||
|         if (data.code === 0) { |         if (data.code === 0) { | ||||||
|           M.toast({html: "Program exited successfully."}); |           M.toast({html: "Program exited successfully."}); | ||||||
| @@ -241,6 +368,7 @@ document.querySelectorAll(".action-validate").forEach((upload) => { | |||||||
|     const modalInstance = M.Modal.getInstance(validateModalElem); |     const modalInstance = M.Modal.getInstance(validateModalElem); | ||||||
|     const log = validateModalElem.querySelector(".log"); |     const log = validateModalElem.querySelector(".log"); | ||||||
|     log.innerHTML = ""; |     log.innerHTML = ""; | ||||||
|  |     const colorState = initializeColorState(); | ||||||
|     const stopLogsButton = validateModalElem.querySelector(".stop-logs"); |     const stopLogsButton = validateModalElem.querySelector(".stop-logs"); | ||||||
|     let stopped = false; |     let stopped = false; | ||||||
|     stopLogsButton.innerHTML = "Stop"; |     stopLogsButton.innerHTML = "Stop"; | ||||||
| @@ -253,8 +381,7 @@ document.querySelectorAll(".action-validate").forEach((upload) => { | |||||||
|     logSocket.addEventListener('message', (event) => { |     logSocket.addEventListener('message', (event) => { | ||||||
|       const data = JSON.parse(event.data); |       const data = JSON.parse(event.data); | ||||||
|       if (data.event === "line") { |       if (data.event === "line") { | ||||||
|         const msg = data.data; |         colorReplace(log, colorState, data.data); | ||||||
|         log.insertAdjacentHTML('beforeend', colorReplace(msg)); |  | ||||||
|       } else if (data.event === "exit") { |       } else if (data.event === "exit") { | ||||||
|         if (data.code === 0) { |         if (data.code === 0) { | ||||||
|           M.toast({ |           M.toast({ | ||||||
| @@ -296,6 +423,7 @@ document.querySelectorAll(".action-compile").forEach((upload) => { | |||||||
|     const modalInstance = M.Modal.getInstance(compileModalElem); |     const modalInstance = M.Modal.getInstance(compileModalElem); | ||||||
|     const log = compileModalElem.querySelector(".log"); |     const log = compileModalElem.querySelector(".log"); | ||||||
|     log.innerHTML = ""; |     log.innerHTML = ""; | ||||||
|  |     const colorState = initializeColorState(); | ||||||
|     const stopLogsButton = compileModalElem.querySelector(".stop-logs"); |     const stopLogsButton = compileModalElem.querySelector(".stop-logs"); | ||||||
|     let stopped = false; |     let stopped = false; | ||||||
|     stopLogsButton.innerHTML = "Stop"; |     stopLogsButton.innerHTML = "Stop"; | ||||||
| @@ -310,8 +438,7 @@ document.querySelectorAll(".action-compile").forEach((upload) => { | |||||||
|     logSocket.addEventListener('message', (event) => { |     logSocket.addEventListener('message', (event) => { | ||||||
|       const data = JSON.parse(event.data); |       const data = JSON.parse(event.data); | ||||||
|       if (data.event === "line") { |       if (data.event === "line") { | ||||||
|         const msg = data.data; |         colorReplace(log, colorState, data.data); | ||||||
|         log.insertAdjacentHTML('beforeend', colorReplace(msg)); |  | ||||||
|       } else if (data.event === "exit") { |       } else if (data.event === "exit") { | ||||||
|         if (data.code === 0) { |         if (data.code === 0) { | ||||||
|           M.toast({html: "Program exited successfully."}); |           M.toast({html: "Program exited successfully."}); | ||||||
| @@ -354,6 +481,7 @@ document.querySelectorAll(".action-clean-mqtt").forEach((btn) => { | |||||||
|     const modalInstance = M.Modal.getInstance(cleanMqttModalElem); |     const modalInstance = M.Modal.getInstance(cleanMqttModalElem); | ||||||
|     const log = cleanMqttModalElem.querySelector(".log"); |     const log = cleanMqttModalElem.querySelector(".log"); | ||||||
|     log.innerHTML = ""; |     log.innerHTML = ""; | ||||||
|  |     const colorState = initializeColorState(); | ||||||
|     const stopLogsButton = cleanMqttModalElem.querySelector(".stop-logs"); |     const stopLogsButton = cleanMqttModalElem.querySelector(".stop-logs"); | ||||||
|     let stopped = false; |     let stopped = false; | ||||||
|     stopLogsButton.innerHTML = "Stop"; |     stopLogsButton.innerHTML = "Stop"; | ||||||
| @@ -366,8 +494,7 @@ document.querySelectorAll(".action-clean-mqtt").forEach((btn) => { | |||||||
|     logSocket.addEventListener('message', (event) => { |     logSocket.addEventListener('message', (event) => { | ||||||
|       const data = JSON.parse(event.data); |       const data = JSON.parse(event.data); | ||||||
|       if (data.event === "line") { |       if (data.event === "line") { | ||||||
|         const msg = data.data; |         colorReplace(log, colorState, data.data); | ||||||
|         log.insertAdjacentHTML('beforeend', colorReplace(msg)); |  | ||||||
|       } else if (data.event === "exit") { |       } else if (data.event === "exit") { | ||||||
|         stopLogsButton.innerHTML = "Close"; |         stopLogsButton.innerHTML = "Close"; | ||||||
|         stopped = true; |         stopped = true; | ||||||
| @@ -396,6 +523,7 @@ document.querySelectorAll(".action-clean").forEach((btn) => { | |||||||
|     const modalInstance = M.Modal.getInstance(cleanModalElem); |     const modalInstance = M.Modal.getInstance(cleanModalElem); | ||||||
|     const log = cleanModalElem.querySelector(".log"); |     const log = cleanModalElem.querySelector(".log"); | ||||||
|     log.innerHTML = ""; |     log.innerHTML = ""; | ||||||
|  |     const colorState = initializeColorState(); | ||||||
|     const stopLogsButton = cleanModalElem.querySelector(".stop-logs"); |     const stopLogsButton = cleanModalElem.querySelector(".stop-logs"); | ||||||
|     let stopped = false; |     let stopped = false; | ||||||
|     stopLogsButton.innerHTML = "Stop"; |     stopLogsButton.innerHTML = "Stop"; | ||||||
| @@ -408,8 +536,7 @@ document.querySelectorAll(".action-clean").forEach((btn) => { | |||||||
|     logSocket.addEventListener('message', (event) => { |     logSocket.addEventListener('message', (event) => { | ||||||
|       const data = JSON.parse(event.data); |       const data = JSON.parse(event.data); | ||||||
|       if (data.event === "line") { |       if (data.event === "line") { | ||||||
|         const msg = data.data; |         colorReplace(log, colorState, data.data); | ||||||
|         log.insertAdjacentHTML('beforeend', colorReplace(msg)); |  | ||||||
|       } else if (data.event === "exit") { |       } else if (data.event === "exit") { | ||||||
|         if (data.code === 0) { |         if (data.code === 0) { | ||||||
|           M.toast({html: "Program exited successfully."}); |           M.toast({html: "Program exited successfully."}); | ||||||
| @@ -444,6 +571,7 @@ document.querySelectorAll(".action-hass-config").forEach((btn) => { | |||||||
|     const modalInstance = M.Modal.getInstance(hassConfigModalElem); |     const modalInstance = M.Modal.getInstance(hassConfigModalElem); | ||||||
|     const log = hassConfigModalElem.querySelector(".log"); |     const log = hassConfigModalElem.querySelector(".log"); | ||||||
|     log.innerHTML = ""; |     log.innerHTML = ""; | ||||||
|  |     const colorState = initializeColorState(); | ||||||
|     const stopLogsButton = hassConfigModalElem.querySelector(".stop-logs"); |     const stopLogsButton = hassConfigModalElem.querySelector(".stop-logs"); | ||||||
|     let stopped = false; |     let stopped = false; | ||||||
|     stopLogsButton.innerHTML = "Stop"; |     stopLogsButton.innerHTML = "Stop"; | ||||||
| @@ -456,8 +584,7 @@ document.querySelectorAll(".action-hass-config").forEach((btn) => { | |||||||
|     logSocket.addEventListener('message', (event) => { |     logSocket.addEventListener('message', (event) => { | ||||||
|       const data = JSON.parse(event.data); |       const data = JSON.parse(event.data); | ||||||
|       if (data.event === "line") { |       if (data.event === "line") { | ||||||
|         const msg = data.data; |         colorReplace(log, colorState, data.data); | ||||||
|         log.insertAdjacentHTML('beforeend', colorReplace(msg)); |  | ||||||
|       } else if (data.event === "exit") { |       } else if (data.event === "exit") { | ||||||
|         if (data.code === 0) { |         if (data.code === 0) { | ||||||
|           M.toast({html: "Program exited successfully."}); |           M.toast({html: "Program exited successfully."}); | ||||||
|   | |||||||
| @@ -253,7 +253,7 @@ class CheckForUpdateThread(threading.Thread): | |||||||
|  |  | ||||||
|         req = requests.get('{}/_static/version'.format(self.docs_base)) |         req = requests.get('{}/_static/version'.format(self.docs_base)) | ||||||
|         req.raise_for_status() |         req.raise_for_status() | ||||||
|         storage.remote_version = req.text |         storage.remote_version = req.text.strip() | ||||||
|         storage.last_update_check = datetime.utcnow() |         storage.last_update_check = datetime.utcnow() | ||||||
|         storage.save(self._path) |         storage.save(self._path) | ||||||
|         return storage |         return storage | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ import logging | |||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
|  |  | ||||||
|  | from esphomeyaml import core | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -48,6 +50,21 @@ def shlex_quote(s): | |||||||
|     return u"'" + s.replace(u"'", u"'\"'\"'") + u"'" |     return u"'" + s.replace(u"'", u"'\"'\"'") + u"'" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RedirectText(object): | ||||||
|  |     def __init__(self, out): | ||||||
|  |         self._out = out | ||||||
|  |  | ||||||
|  |     def write(self, s): | ||||||
|  |         s = s.replace('\033', '\\033') | ||||||
|  |         self._out.write(s) | ||||||
|  |  | ||||||
|  |     def flush(self): | ||||||
|  |         self._out.flush() | ||||||
|  |  | ||||||
|  |     def isatty(self): | ||||||
|  |         return True | ||||||
|  |  | ||||||
|  |  | ||||||
| def run_external_command(func, *cmd, **kwargs): | def run_external_command(func, *cmd, **kwargs): | ||||||
|     def mock_exit(return_code): |     def mock_exit(return_code): | ||||||
|         raise SystemExit(return_code) |         raise SystemExit(return_code) | ||||||
| @@ -57,6 +74,10 @@ def run_external_command(func, *cmd, **kwargs): | |||||||
|     full_cmd = u' '.join(shlex_quote(x) for x in cmd) |     full_cmd = u' '.join(shlex_quote(x) for x in cmd) | ||||||
|     _LOGGER.info(u"Running:  %s", full_cmd) |     _LOGGER.info(u"Running:  %s", full_cmd) | ||||||
|  |  | ||||||
|  |     if core.FROM_DASHBOARD: | ||||||
|  |         sys.stdout = RedirectText(sys.stdout) | ||||||
|  |         sys.stderr = RedirectText(sys.stderr) | ||||||
|  |  | ||||||
|     capture_stdout = kwargs.get('capture_stdout', False) |     capture_stdout = kwargs.get('capture_stdout', False) | ||||||
|     if capture_stdout: |     if capture_stdout: | ||||||
|         sys.stdout = io.BytesIO() |         sys.stdout = io.BytesIO() | ||||||
| @@ -76,6 +97,11 @@ def run_external_command(func, *cmd, **kwargs): | |||||||
|         sys.argv = orig_argv |         sys.argv = orig_argv | ||||||
|         sys.exit = orig_exit |         sys.exit = orig_exit | ||||||
|  |  | ||||||
|  |         if isinstance(sys.stdout, RedirectText): | ||||||
|  |             sys.stdout = sys.__stdout__ | ||||||
|  |         if isinstance(sys.stderr, RedirectText): | ||||||
|  |             sys.stderr = sys.__stderr__ | ||||||
|  |  | ||||||
|         if capture_stdout: |         if capture_stdout: | ||||||
|             # pylint: disable=lost-exception |             # pylint: disable=lost-exception | ||||||
|             stdout = sys.stdout.getvalue() |             stdout = sys.stdout.getvalue() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user