Module surrealpy.handler

Expand source code
import os
import threading
import subprocess as sp
import psutil
import shlex
import logging
import socket

# create logger object
logger = logging.getLogger("surrealpy.sync.client")

# if operation system is windows set process name to surreal.exe
if os.name == "nt":
    processName = "surreal.exe"
elif os.name == "posix":
    processName = "surreal"
else:
    print("Unknown OS")
    exit(1)


def checkIfProcessRunning(processName):
    """
    Check if there is any running process that contains the given name processName.
    """
    # Iterate over the all the running process
    for proc in psutil.process_iter():
        try:
            # Check if process name contains the given name string.
            if processName.lower() in proc.name().lower():
                return True
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass
    return False


# this is a thread safe singleton class
# with this class we can start a thread to handle the database process
def getAvaiblePort():
    sock = socket.socket()
    sock.bind(("", 0))

    return sock.getsockname()[1]


class SurrealDBHandler(threading.Thread):
    def __init__(
        self,
        uri: str,
        username: str,
        password: str,
        *,
        host: str = "0.0.0.0",
        port: int = None,
        scheme: str = "http",
    ) -> None:
        # check if surreal is already running
        threading.Thread.__init__(self, daemon=True)
        if checkIfProcessRunning(processName):
            print("Surreal is already running")
            exit(1)

        # check if uri is filepath
        self.__uri = uri
        self.__username = username
        self.__password = password
        self.__host = host
        self.__port = port or getAvaiblePort()
        self.__canrun = True
        self.__scheme = scheme
        if uri == "memory":
            self.__uri = "memory"
        else:
            self.__uri = "file://" + uri

        # start the database process
        self.__commandTemplate = "surreal start --log debug  --user {username} --pass {password} --bind {host}:{port} {uri}"
        self.__command = self.__commandTemplate.format(
            username=self.username,
            password=self.password,
            uri=self.__uri,
            host=host,
            port=port,
        )
        self.__parsedCommand = shlex.split(self.__command)
        # call the super class constructor

    def run(self):
        # start the database process
        self.__process = sp.Popen(self.__parsedCommand)
        # read the output of the process and log it
        while self.__canrun:
            output = self.__process.stdout.readline()
            if output == "" and self.__process.poll() is not None:
                break
            if output:
                logger.debug(output.strip())

    @property
    def uri(self):
        return self.__uri

    @property
    def command(self):
        return self.__command

    @property
    def username(self):
        return self.__username

    @property
    def password(self):
        return self.__password

    @property
    def host(self):
        return self.__host

    @property
    def port(self):
        return self.__port

    @property
    def bind(self):
        return self.__host + ":" + str(self.__port)

    @property
    def scheme(self):
        return self.__scheme

    def stop(self):
        self.__process.terminate()
        self.__process.wait()
        self.__canrun = False
        logger.debug("Surreal process terminated")

    @property
    def sql(self):
        return "{scheme}://{host}:{port}/sql".format(
            scheme=self.scheme,
            host=self.host,
            port=self.port,
        )

Functions

def checkIfProcessRunning(processName)

Check if there is any running process that contains the given name processName.

Expand source code
def checkIfProcessRunning(processName):
    """
    Check if there is any running process that contains the given name processName.
    """
    # Iterate over the all the running process
    for proc in psutil.process_iter():
        try:
            # Check if process name contains the given name string.
            if processName.lower() in proc.name().lower():
                return True
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass
    return False
def getAvaiblePort()
Expand source code
def getAvaiblePort():
    sock = socket.socket()
    sock.bind(("", 0))

    return sock.getsockname()[1]

Classes

class SurrealDBHandler (uri: str, username: str, password: str, *, host: str = '0.0.0.0', port: int = None, scheme: str = 'http')

A class that represents a thread of control.

This class can be safely subclassed in a limited fashion. There are two ways to specify the activity: by passing a callable object to the constructor, or by overriding the run() method in a subclass.

This constructor should always be called with keyword arguments. Arguments are:

group should be None; reserved for future extension when a ThreadGroup class is implemented.

target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.

name is the thread name. By default, a unique name is constructed of the form "Thread-N" where N is a small decimal number.

args is the argument tuple for the target invocation. Defaults to ().

kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.

If a subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.init()) before doing anything else to the thread.

Expand source code
class SurrealDBHandler(threading.Thread):
    def __init__(
        self,
        uri: str,
        username: str,
        password: str,
        *,
        host: str = "0.0.0.0",
        port: int = None,
        scheme: str = "http",
    ) -> None:
        # check if surreal is already running
        threading.Thread.__init__(self, daemon=True)
        if checkIfProcessRunning(processName):
            print("Surreal is already running")
            exit(1)

        # check if uri is filepath
        self.__uri = uri
        self.__username = username
        self.__password = password
        self.__host = host
        self.__port = port or getAvaiblePort()
        self.__canrun = True
        self.__scheme = scheme
        if uri == "memory":
            self.__uri = "memory"
        else:
            self.__uri = "file://" + uri

        # start the database process
        self.__commandTemplate = "surreal start --log debug  --user {username} --pass {password} --bind {host}:{port} {uri}"
        self.__command = self.__commandTemplate.format(
            username=self.username,
            password=self.password,
            uri=self.__uri,
            host=host,
            port=port,
        )
        self.__parsedCommand = shlex.split(self.__command)
        # call the super class constructor

    def run(self):
        # start the database process
        self.__process = sp.Popen(self.__parsedCommand)
        # read the output of the process and log it
        while self.__canrun:
            output = self.__process.stdout.readline()
            if output == "" and self.__process.poll() is not None:
                break
            if output:
                logger.debug(output.strip())

    @property
    def uri(self):
        return self.__uri

    @property
    def command(self):
        return self.__command

    @property
    def username(self):
        return self.__username

    @property
    def password(self):
        return self.__password

    @property
    def host(self):
        return self.__host

    @property
    def port(self):
        return self.__port

    @property
    def bind(self):
        return self.__host + ":" + str(self.__port)

    @property
    def scheme(self):
        return self.__scheme

    def stop(self):
        self.__process.terminate()
        self.__process.wait()
        self.__canrun = False
        logger.debug("Surreal process terminated")

    @property
    def sql(self):
        return "{scheme}://{host}:{port}/sql".format(
            scheme=self.scheme,
            host=self.host,
            port=self.port,
        )

Ancestors

  • threading.Thread

Instance variables

var bind
Expand source code
@property
def bind(self):
    return self.__host + ":" + str(self.__port)
var command
Expand source code
@property
def command(self):
    return self.__command
var host
Expand source code
@property
def host(self):
    return self.__host
var password
Expand source code
@property
def password(self):
    return self.__password
var port
Expand source code
@property
def port(self):
    return self.__port
var scheme
Expand source code
@property
def scheme(self):
    return self.__scheme
var sql
Expand source code
@property
def sql(self):
    return "{scheme}://{host}:{port}/sql".format(
        scheme=self.scheme,
        host=self.host,
        port=self.port,
    )
var uri
Expand source code
@property
def uri(self):
    return self.__uri
var username
Expand source code
@property
def username(self):
    return self.__username

Methods

def run(self)

Method representing the thread's activity.

You may override this method in a subclass. The standard run() method invokes the callable object passed to the object's constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.

Expand source code
def run(self):
    # start the database process
    self.__process = sp.Popen(self.__parsedCommand)
    # read the output of the process and log it
    while self.__canrun:
        output = self.__process.stdout.readline()
        if output == "" and self.__process.poll() is not None:
            break
        if output:
            logger.debug(output.strip())
def stop(self)
Expand source code
def stop(self):
    self.__process.terminate()
    self.__process.wait()
    self.__canrun = False
    logger.debug("Surreal process terminated")