Этот код работал, но теперь я получаю ошибку рекурсии со счетчика в __getattribute__ - PullRequest
0 голосов
/ 21 октября 2019

Мне нужна помощь, чтобы у моего объекта Query не было ошибки рекурсии. Чтобы проверить правильное количество функций, вызванных цепочкой, я добавляю счетчик для получения атрибута, который вызвал ошибку рекурсии. Этого не было, когда у меня было только несколько функций, но теперь это происходит, и мне нужно исправить

Изменение функции. Использование self, object и т. Д. Я использую python 3.5, и этот код работал меньше, но с тех пор имел ошибки


import mysql.connector as sql

class Database:

    def __init__(self):

        # Attributes
        host = "127.0.0.1"
        database = "database"
        user = "root"
        password = None

        self.connection = sql.connect(
            host = host,
            database = database,
            user = user,
            password = password
        )

        self.cursor = self.connection.cursor()


class Query(object):

    """

        Object initialisers and attributes
        ----------------------------------

    """

    def __init__(self, table):

        super().__init__()

        self.query = None
        self._table = table
        self._count = 0
        self._countRequired = 1
        self._return = False
        self._leadMethods = ["select", "update", "insert", "join"]
        self._selectorMethods = ["where"]
        self._returnTypes = ["fetchAll", "get", "first", "chunk", "last", "row"]
        self._specialCases = ["count", "len", "desc", "asc", "orderBy"]

    def __call__(self):

        if self._count >= self._countRequired:
            self._execute()
        else:
            raise NotImplementedError("Check amount of methods for SQL statement first")

    def __getattr__(self, attr, *args):
        # Updatable
        return "Attributes not found!"

    def __getattribute__(*args):
        args[0]._count += 1
        return object.__getattribute__(*args)


    """

        Private methods and static methods
        ----------------------------------

    """

    @staticmethod
    def count(self, columns):

        chain = ""
        if columns:

            if type(columns) == type([]):

                for i in range(0, len(columns)):
                    if i == len(columns):
                        chain += "COUNT(" + column + ") as count_" + column
                        break
                    chain += "COUNT(" + column + ") as count_" + column + ", "

            elif type(columns) == type(""):

                chain = "COUNT(" + columns + ") as count_" + columns

        return chain

    @staticmethod
    def len(self, columns):

        chain = ""
        if columns:

            if type(columns) == type([]):

                for i in range(0, len(columns)):
                    if i == len(columns):
                        chain += "LEN(" + column + ") as len_" + column
                        break
                    chain += "LEN(" + column + ") as len_" + column + ", "

            elif type(columns) == type(""):

                chain = "LEN(" + columns + ") as len_" + columns

        return chain

    def _execute(self):
        query = self.query
        try:
            self.cursor.execute(query)
            if self._return == True:
                return self.cursor.fetchall()
            return True
        except Exception as e:
            return (False, e)

        self.connection.commit()


    """

        Public methods
        --------------

    """

    def select(self, columns=None, args=None):

        values = None
        if args:
            specialCases = []

            for arg in args:
                for case in self._specialCases[:2]:
                    if arg == case:
                        specialCases += args

            values = []

            for case in specialCases:
                try:
                    case = "" + case
                    x = getattr(self, case)(self, columns)
                    values += [x]
                except Exception as e:
                    print("Special case doesn't exist.")

        selector = ""
        if columns == []:

            for i in range(0, len(columns)):
                if i == len(columns):
                    selector += columns[i]
                    break
                selector += columns[i] + ","
        elif columns:

            selector = columns

        else:
            selector = "*"

        if self.query == None:

            sql = "SELECT " + selector + " FROM " + self._table

            self.query = sql

            self._countRequired += 2
            self._return = True

        return self

    def update(self, columns=None, values=None):

        statement = "UPDATE " + self._table + " SET "

        if len(columns) != len(values):
            raise Exception("Not equal amount of columns and values")

        temp = ""
        if type(columns) == type([]) and type(values) == type([]):
            for i in range(0, len(columns)):
                if i == len(columns):
                    temp += columns[i]  + " = " + values[i]
                    break

        elif type(columns) == type("") and type(values) == type(""):
            temp += str(columns) + " = " + str(values)

        statement += temp

        self._query = statement
        self._countRequired += 1

        return self


    def insert(self, columns=None, values=None):

        statment = "INSERT INTO " + self._table + " "

        temp = "("

        if type(columns) == type([]) and type(values) == type([]):
            for i in range(0, len(columns)):
                if i == len(columns):
                    temp += str(columns[i]) +  ") VALUES ("
                    break
                temp += str(columns[i]) + ", "

            for i in range(0, len(values)):
                if values[i] == None:
                    values[i] = "NULL"
                if i == len(VALUES):
                    temp += str(values[i]) + ")"
                    break
                temp += str(values[i]) + ", "


        return self

    def join (self, table, compareOne, operator, compareTwo, type="INNER"):

        statement = "{} JOIN {} ON {} {} {} ".format(str(type), str(table), str(compareOne), str(operator), str(compareTwo))

        self._query += statement

        return self

    def where(self, column=None, value=None, operator=None):

        statement = " WHERE "

        if not operator:
            operator = "="

        if column and value:
            temp = ""

            if type(column) == type([]) and type(value) == type([]):
                for i in range(0, len(column)):
                    if i == len(column):
                        temp += "{} {} {} ".format(column[i], operator, value[i])
                        break

                    temp += "{} {} {},".format(column[i], operator, value[i])


            elif type(column) == type([]):

                for i in range(0, len(column)):
                    if i == len(column):
                        temp += "{} {} {} ".format(column[i], operator, value)
                        break

                    temp += "{} {} {},".format(column[i], operator, value)


            elif type(value) == type([]):

                for i in range(0, len(value)):
                    if i == len(value):
                        temp += "{} {} {} ".format(column, operator, value[i])
                        break

                    temp += "{} {} {},".format(column, operator, value[i])

            else:

                temp = "{} {} {} ".format(column, operator, value)


            statement += temp

            self.query += statement

        return self

    def fetchAll(self):
        return self

    def get(self):
        return self

    def first(self):
        self.query += "LIMIT 1"
        return self

    def last(self):
        self.query += "DESC LIMIT 1"
        return self

    def row(self, n):
        self.query += "AND id = " + str(n)
        return self

    def chunk(self, n, start=0):
        sql = "AND id BETWEEN " + str(start) + " AND " + str(n)
        self.query += sql
        return self

    """

        Extra Functions

    """

    def orderBy(self, type):

        if type in possible:
            self._query += "ORDER BY " + str(type)
        else:
            raise Exception("Invalid orderBy value. Should be ASC or DESC")
        return self

    def override(self, password, sql):
        if password == "password":
            self._query = SQL
        return self

Должен быть в состоянии напечатать:

q = Query('table').select().where('name', 'test').get()()

и вернулся срезультаты

"SELECT * FROM table WHERE name=test;"

1 Ответ

1 голос
/ 22 октября 2019

Исправлено Я создал массив своих функций, исключая свойство count, что означало, что я считал, только если это был метод, приемлемый для свободного интерфейса

def __getattribute__(self, name):
        methods = ["select", "update", "insert", "join", "where", "get", "row", "last", "first", "fetchAll", "chunk", "override", "orderBy"]
        if name in methods:
            self._count += 1
        return object.__getattribute__(self, name)
...