from threading import Thread
import logging, pathlib, subprocess, json

# import logger
logger = logging.getLogger(__name__)

class IrisSystemThread(Thread):
    def __init__(self, action, callback):
        Thread.__init__(self)
        self.action = action
        self.callback = callback
        self.script_path = pathlib.Path(__file__).parent / "system.sh"

    ##
    # Run the defined action
    ##
    def run(self):
        logger.info("Running system action '"+self.action+"'")

        try:
            self.can_run()
        except Exception as e:
            logger.error(e)

            error = {
                'message': "Permission denied",
                'description': str(e)
            }
            
            return {
                'error': error
            }

        logger.debug("sudo %s %s", self.script_path, self.action)

        proc = subprocess.Popen(["sudo", str(self.script_path), self.action],
            stdout=subprocess.PIPE, 
            stderr=subprocess.STDOUT)
        
        stdout,stderr = proc.communicate()

        if stderr:
            logger.error(stderr.decode())
            self.callback(None, { 'error': stderr.decode() })
        else:
            logger.info(stdout.decode())
            self.callback({ 'output': stdout.decode() }, None)



    ##
    # Check if we have access to the system script (system.sh)
    #
    # @return boolean or exception
    ##
    def can_run(self, *args, **kwargs):

        # Attempt an empty call to our system file
        process = subprocess.Popen("sudo -n %s check" % self.script_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        result, error = process.communicate()
        exitCode = process.wait()

        # Some kind of failure, so we can't run any commands this way
        if exitCode > 0:
            raise Exception("Password-less access to %s was refused. Check your /etc/sudoers file." % self.script_path)
        else:
            return True

@@ -125,16 +125,535 @@
 e__)%0D%0A%0D%0A
+%0D%0Aclass IrisSystemError(Exception):%0D%0A    pass%0D%0A%0D%0A%0D%0Aclass IrisSystemPermissionError(IrisSystemError):%0D%0A    reason = %22Permission denied%22%0D%0A%0D%0A    def __init__(self, path):%0D%0A        message = %22Password-less access to %25s was refused. Check your /etc/sudoers file.%22 %25 path.as_uri()%0D%0A        super().__init__(message)%0D%0A%0D%0A%0D%0Aclass IrisSystemMissingError(IrisSystemError):%0D%0A    reason = %22Not found%22%0D%0A%0D%0A    def __init__(self, path):%0D%0A        message = %22Unable to access %25s.%22 %25 path.as_uri()%0D%0A        super().__init__(message)%0D%0A%0D%0A%0D%0A
 class Ir
@@ -1078,25 +1078,31 @@
  except 
-Exception
+IrisSystemError
  as e:%0D%0A
@@ -1182,35 +1182,24 @@
 ssage': 
-%22Permission denied%22
+e.reason
 ,%0D%0A     
@@ -1228,14 +1228,17 @@
 n': 
-str(e)
+e.message
 %0D%0A  
@@ -1386,16 +1386,25 @@
 ipt_path
+.as_uri()
 , self.a
@@ -1450,16 +1450,17 @@
 en(%5B
+b
 %22sudo%22, 
 str(
@@ -1459,11 +1459,13 @@
 o%22, 
-str
+bytes
 (sel
@@ -1491,16 +1491,25 @@
 f.action
+.encode()
 %5D,%0D%0A    
@@ -1576,14 +1576,12 @@
 ess.
-STDOUT
+PIPE
 )%0D%0A 
@@ -1655,16 +1655,64 @@
 tderr:%0D%0A
+            error_string = os.fsdecode(stderr)%0D%0A
         
@@ -1728,31 +1728,28 @@
 r.error(
-stderr.decode()
+error_string
 )%0D%0A     
@@ -1776,17 +1776,16 @@
 (None, %7B
- 
 'error':
@@ -1789,24 +1789,20 @@
 r': 
-stderr.decode() 
+error_string
 %7D)%0D%0A
@@ -1832,35 +1832,86 @@
     
-logger.info(stdout.decode()
+response_string = os.fsdecode(stdout)%0D%0A            logger.info(response_string
 )%0D%0A 
@@ -1936,17 +1936,16 @@
 llback(%7B
- 
 'output'
@@ -1950,24 +1950,23 @@
 t': 
-stdout.decode() 
+response_string
 %7D, N
@@ -2140,16 +2140,120 @@
 wargs):%0D
+%0A        if not self.script_path.is_file():%0D%0A            raise IrisSystemMissingError(self.script_path)%0D
 %0A%0D%0A     
@@ -2334,16 +2334,17 @@
 s.Popen(
+b
 %22sudo -n
@@ -2352,24 +2352,30 @@
 %25s check%22 %25 
+bytes(
 self.script_
@@ -2378,16 +2378,17 @@
 ipt_path
+)
 , stdout
@@ -2645,92 +2645,34 @@
 ise 
-Exception(%22Password-less access to %25s was refused. Check your /etc/sudoers file.%22 %25 
+IrisSystemPermissionError(
 self

Support arbitrary path encodings and better error handling.