Exemplo n.º 1
0
    except Exception as e:
        logging.info(str(e))


# open database
user_home_dir = os.path.expanduser("~")
user_config_dir = os.path.expanduser("~") + "/.config/nginx-odoo"
Path(user_config_dir).mkdir(parents=True, exist_ok=True)
db_path = user_config_dir + "/database.db"
db = DB(db_path)
os.chmod(db_path, 0o600)
db_perm = os.stat(db_path).st_mode & 0o777
if db_perm != 0o600:
    sys.exit('File permissions of {} must be 600 but are: {:o}'.format(
        db_path, db_perm))
db.cleanup()

# check Odoo settings
ODOO_PORT = os.environ.get('NGINX_ODOO_ODOO_PORT', '8069')
ODOO_HOST = os.environ.get('NGINX_ODOO_ODOO_HOST', 'localhost')
ODOO_DATABASE = os.environ.get('NGINX_ODOO_ODOO_DATABASE')
if not ODOO_DATABASE:
    sys.exit('Odoo settings not set in .env')

# try to connect to odoo
try:
    odoo = odoorpc.ODOO(ODOO_HOST, port=ODOO_PORT)
except Exception:
    sys.exit('Odoo not running at {}:{}'.format(ODOO_HOST, ODOO_PORT))

auth_params = {
Exemplo n.º 2
0
class Target:
    '''
    This is the target. It controls/contains the code to be debugged.
    '''
    def __init__(self, dsn: str):
        self.database = DB(dsn, is_async=True)
        self.notice_queue = Queue()
        self.oid = None
        self.executor = None
        self.port = None

    def cleanup(self):
        '''
        Cleanup routine for the target.
        '''
        self.database.cleanup()

    def get_notices(self) -> List[str]:
        '''
        Get all notices the target might have. Reads from an internal queue,
        does not use the DB itself since it is likely blocked.
        '''
        notices = []
        while not self.notice_queue.empty():
            notices.append(self.notice_queue.get())
        logger.debug(f'Target notices: {notices}')
        return notices

    @classmethod
    def _parse_port(cls, port_raw: str) -> int:
        return int(port_raw.split(':')[-1])

    def wait_for_shutdown(self):
        '''
        Wait until the target completed fully.
        '''
        self.executor.join()

    def _run_executor_thread(self, func_call, func_oid):
        self.executor = Thread(target=self._run, args=(func_call, func_oid))
        self.executor.daemon = True
        self.executor.start()

    @classmethod
    def assert_valid_function_call(cls, func_call: str) -> bool:
        return re.match(r'[_a-zA-Z0-9]+\([^\)]*\)(\.[^\)]*\))?',
                        func_call) is not None

    def start(self, func_call: str) -> bool:
        '''
        Start target debugging. Resolve the function to be debugged, find its
        OID and eventually start a thread calling it.
        '''

        print(func_call)
        if not Target.assert_valid_function_call(func_call):
            logger.error(f'Function call seems incomplete: {func_call}')
            return False

        func_name, func_args = Target._parse_func_call(func_call)
        func_oid = get_func_oid_by_name(self.database, func_name)
        if not func_oid:
            logger.error('Function OID not found. Either function is not '
                         'defined or there are multiple with the same name '
                         'which is currently not support')
            return False

        logger.debug(f'Function OID is: {func_oid}')
        self._run_executor_thread(func_call, func_oid)

        # Wait here until the executor started
        logger.debug('Waiting for port')
        self.port = Target._parse_port(self.notice_queue.get())
        logger.debug(f'Port is: {self.port}')

        return True

    def _run(self, func_call: str, func_oid: int):
        '''
        Start a debugging session. Consumes the function call to debug with its
        arguments and returns the session ID once the debugger started.
        '''
        self.oid = func_oid
        self.database.run_sql(f'SELECT * FROM pldbg_oid_debug({func_oid})')

        while True:
            logger.debug('Starting target function')

            try:
                result = self.database.run_sql(f'SELECT * FROM {func_call}',
                                               fetch_result=True,
                                               notice_queue=self.notice_queue)

                # This will now wait here until the function finishes. It will
                # eventually restart immediately. Otherwise, the proxy process
                # hangs until it hits a timeout.

                logger.debug(f'Target result: {result}')

            except QueryCanceled:
                logger.info('Stopped target query')
                break

    @classmethod
    def _parse_func_call(cls, func_call: str) -> Tuple[str, List[str]]:
        '''
        Take a function call and return the function name and its arguments.
        '''
        func_call = func_call.replace(' ', '').replace('(',
                                                       ',').replace(')', '')
        func_call = func_call.split(',')
        return func_call[0], func_call[1:]