예제 #1
0
    def list_files(
        self,
        *specification: 'Union[FileSpecification, str]',
    ) -> 'List[str]':
        """
        Получение списка файлов с сервера.

        :param specification: Спецификация или маска имени файла
        (если нужны файлы, лежащие в папке текущей базы данных)
        :return: Список файлов
        """
        if not self.check_connection():
            return []

        query = ClientQuery(self, LIST_FILES)

        is_ok = False
        for spec in specification:
            if isinstance(spec, str):
                spec = self.near_master(spec)
            query.ansi(str(spec))
            is_ok = True

        result: 'List[str]' = []
        if not is_ok:
            return result

        with self.execute(query) as response:
            lines = response.ansi_remaining_lines()
            lines = [line for line in lines if line]
            for line in lines:
                result.extend(one for one in irbis_to_lines(line) if one)
        return result
예제 #2
0
    def connect(self,
                host: 'Optional[str]' = None,
                port: int = 0,
                username: '******' = None,
                password: '******' = None,
                database: 'Optional[str]' = None) -> IniFile:
        """
        Подключение к серверу ИРБИС64.

        :return: INI-файл
        """
        if self.connected:
            return self.ini_file

        self.host = host or self.host or throw_value_error()
        self.port = port or self.port or int(throw_value_error())
        self.username = username or self.username or throw_value_error()
        self.password = password or self.password or throw_value_error()
        self.database = self._get_database(database)

        assert isinstance(self.host, str)
        assert isinstance(self.port, int)
        assert isinstance(self.username, str)
        assert isinstance(self.password, str)

        while True:
            self.query_id = 0
            self.client_id = random.randint(100000, 999999)
            query = ClientQuery(self, REGISTER_CLIENT)
            query.ansi(self.username).ansi(self.password)
            with self.execute(query) as response:
                if response.get_return_code() == -3337:
                    continue

                return self._connect(response)
예제 #3
0
    def disconnect(self) -> None:
        """
        Отключение от сервера.

        :return: None.
        """
        if self.connected:
            query = ClientQuery(self, UNREGISTER_CLIENT)
            query.ansi(self.username)
            self.execute_forget(query)
            self.connected = False
예제 #4
0
    def execute_ansi(self, *commands) -> ServerResponse:
        """
        Простой запрос к серверу, когда все строки запроса
        в кодировке ANSI.

        :param commands: Команда и параметры запроса
        :return: Ответ сервера (не забыть закрыть!)
        """
        query = ClientQuery(self, commands[0])
        for line in commands[1:]:
            query.ansi(line)
        return self.execute(query)
예제 #5
0
    async def disconnect_async(self) -> None:
        """
        Асинхронное отключение от сервера.

        :return: None.
        """
        if self.connected:
            query = ClientQuery(self, UNREGISTER_CLIENT)
            query.ansi(self.username)
            response = await self.execute_async(query)
            response.close()
            self.connected = False
예제 #6
0
    def _search_begin(self, parameters: 'Any') -> ClientQuery:
        if not isinstance(parameters, SearchParameters):
            parameters = SearchParameters(str(parameters))

        query = ClientQuery(self, SEARCH)
        parameters.encode(query, self)
        return query
예제 #7
0
    def list_processes(self) -> 'List[Process]':
        """
        Получение списка серверных процессов.

        :return: Список процессов
        """
        if not self.check_connection():
            return []

        query = ClientQuery(self, GET_PROCESS_LIST)
        with self.execute(query) as response:
            response.check_return_code()
            result: 'List[Process]' = []
            process_count = response.number()
            lines_per_process = response.number()

            if not process_count or not lines_per_process:
                return result

            for _ in range(process_count):
                process = Process()
                process.number = response.ansi()
                process.ip_address = response.ansi()
                process.name = response.ansi()
                process.client_id = response.ansi()
                process.workstation = response.ansi()
                process.started = response.ansi()
                process.last_command = response.ansi()
                process.command_number = response.ansi()
                process.process_id = response.ansi()
                process.state = response.ansi()
                result.append(process)

            return result
예제 #8
0
    def update_user_list(self, users: 'List[UserInfo]') -> bool:
        """
        Обновление списка пользователей на сервере.

        :param users:  Список пользователей
        :return: Признак успешности операции.
        """
        if not self.check_connection():
            return False

        assert isinstance(users, list) and users

        query = ClientQuery(self, SET_USER_LIST)
        for user in users:
            query.ansi(user.encode())
        self.execute_forget(query)

        return True
예제 #9
0
 def _fulltext_search_begin(
     self,
     search: SearchParameters,
     fulltext: TextParameters,
 ) -> ClientQuery:
     query = ClientQuery(self, FULL_TEXT_SEARCH)
     search.encode(query, self)
     fulltext.encode(query)
     return query
예제 #10
0
    def update_ini_file(self, lines: 'List[str]') -> bool:
        """
        Обновление строк серверного INI-файла.

        :param lines: Измененные строки.
        :return: Признак успешности операции.
        """
        if not self.check_connection():
            return False

        if not lines:
            return True

        query = ClientQuery(self, UPDATE_INI_FILE)
        for line in lines:
            query.ansi(line)
        self.execute_forget(query)

        return True
예제 #11
0
    def write_text_file(self, *specification: FileSpecification) -> bool:
        """
        Сохранение текстового файла на сервере.

        :param specification: Спецификация (включая текст для сохранения).
        :return: Признак успешности операции.
        """
        if not self.check_connection():
            return False

        query = ClientQuery(self, READ_DOCUMENT)
        is_ok = False
        for spec in specification:
            assert isinstance(spec, FileSpecification)
            query.ansi(str(spec))
            is_ok = True
        if not is_ok:
            return False
        return self._execute_with_bool_result(query)
예제 #12
0
    async def restart_server_async(self) -> bool:
        """
        Асинхронный перезапуск сервера (без утери подключенных клиентов).
        :return: Признак успешности операции.
        """
        if not self.check_connection():
            return False

        query = ClientQuery(self, RESTART_SERVER)
        response = await self.execute_async(query)
        response.close()
        return True
예제 #13
0
    def write_records(self, records: 'List[Record]') -> bool:
        """
        Сохранение нескольких записей на сервере.
        Записи могут принадлежать разным базам.

        :param records: Записи для сохранения.
        :return: Результат.
        """
        if not self.check_connection():
            return False

        if not records:
            return True

        if len(records) == 1:
            return bool(self.write_record(records[0]))

        query = ClientQuery(self, "6")
        query.add(0).add(1)

        for record in records:
            database = record.database or self.database
            line = database + IRBIS_DELIMITER + \
                IRBIS_DELIMITER.join(record.encode())
            query.utf(line)

        with self.execute(query) as response:
            response.check_return_code()

        return True
예제 #14
0
    async def nop_async(self) -> bool:
        """
        Асинхронная пустая операция.

        :return: Признак успешности операции.
        """
        if not self.check_connection():
            return False

        query = ClientQuery(self, NOP)
        response = await self.execute_async(query)
        response.close()
        return True
예제 #15
0
    async def connect_async(self) -> IniFile:
        """
        Асинхронное подключение к серверу ИРБИС64.

        :return: INI-файл
        """
        if self.connected:
            return self.ini_file

        while True:
            self.query_id = 0
            self.client_id = random.randint(100000, 999999)
            query = ClientQuery(self, REGISTER_CLIENT)
            query.ansi(self.username).ansi(self.password)
            response = await self.execute_async(query)
            if response.get_return_code() == -3337:
                response.close()
                continue

            result = self._connect(response)
            response.close()
            return result
예제 #16
0
    def delete_database(self, database: 'Optional[str]' = None) -> bool:
        """
        Удаление базы данных.

        :param database: Имя удаляемой базы.
        :return: Признак успешности операции.
        """
        if not self.check_connection():
            return False

        database = self._get_database(database)
        query = ClientQuery(self, DELETE_DATABASE).ansi(database)
        return self._execute_with_bool_result(query)
예제 #17
0
    def create_dictionary(self, database: 'Optional[str]' = None) -> bool:
        """
        Создание словаря в базе данных.

        :param database: Имя базы данных.
        :return: Признау успешности операции.
        """
        if not self.check_connection():
            return False

        database = self._get_database(database)

        query = ClientQuery(self, CREATE_DICTIONARY).ansi(database)
        return self._execute_with_bool_result(query)
예제 #18
0
    def list_users(self) -> 'List[UserInfo]':
        """
        Получение списка пользователей с сервера.

        :return: Список пользователей
        """
        if not self.check_connection():
            return []

        query = ClientQuery(self, GET_USER_LIST)
        with self.execute(query) as response:
            if not response.check_return_code():
                return []
            result = UserInfo.parse(response)
            return result
예제 #19
0
    def execute(self, query: ClientQuery) -> ServerResponse:
        """
        Выполнение произвольного запроса к серверу.

        :param query: Запрос
        :return: Ответ сервера (не забыть закрыть!)
        """
        self.last_error = 0
        sock = socket.socket()
        sock.connect((self.host, self.port))
        packet = query.encode()
        sock.send(packet)
        result = ServerResponse(self)
        result.read_data(sock)
        result.initial_parse()
        return result
예제 #20
0
    def get_server_stat(self) -> ServerStat:
        """
        Получение статистики с сервера.

        :return: Полученная статистика
        """
        if not self.check_connection():
            return ServerStat()

        query = ClientQuery(self, GET_SERVER_STAT)
        with self.execute(query) as response:
            result = ServerStat()
            if not response.check_return_code():
                return result
            result.parse(response)
            return result
예제 #21
0
    def get_server_version(self) -> ServerVersion:
        """
        Получение версии сервера.

        :return: Версия сервера
        """
        if not self.check_connection():
            return ServerVersion()

        query = ClientQuery(self, SERVER_INFO)
        with self.execute(query) as response:
            result = ServerVersion()
            if not response.check_return_code():
                return result
            lines = response.ansi_remaining_lines()
            result.parse(lines)
            if not self.server_version:
                self.server_version = result.version
            return result
예제 #22
0
    async def execute_async(self, query: ClientQuery) -> ServerResponse:
        """
        Асинхронное исполнение запроса.
        ВНИМАНИЕ: сначала должна быть выполнена инициализация init_async()!

        :param query: Запрос.
        :return: Ответ сервера.
        """
        self.last_error = 0
        reader, writer = await asyncio.open_connection(self.host,
                                                       self.port,
                                                       loop=irbis_event_loop)
        packet = query.encode()
        writer.write(packet)
        result = ServerResponse(self)
        await result.read_data_async(reader)
        result.initial_parse()
        writer.close()
        return result
예제 #23
0
    def read_text_stream(
        self,
        specification: 'Union[FileSpecification, str]',
    ) -> ServerResponse:
        """
        Получение текстового файла с сервера в виде потока.

        :param specification: Спецификация или имя файла
        (если он находится в папке текущей базы данных).
        :return: ServerResponse, из которого можно считывать строки
        """

        if isinstance(specification, str):
            specification = self.near_master(specification)

        assert isinstance(specification, FileSpecification)

        query = ClientQuery(self, READ_DOCUMENT).ansi(str(specification))
        result = self.execute(query)
        return result
예제 #24
0
    def get_database_info(self, database: 'Optional[str]' = None) \
            -> DatabaseInfo:
        """
        Получение информации о базе данных.

        :param database: Имя базы
        :return: Информация о базе
        """
        if not self.check_connection():
            return DatabaseInfo()

        database = self._get_database(database)
        query = ClientQuery(self, RECORD_LIST).ansi(database)
        with self.execute(query) as response:
            result = DatabaseInfo()
            if not response.check_return_code():
                return result

            result.parse(response)
            result.name = database
            return result
예제 #25
0
    async def read_text_file_async(
        self,
        specification: 'Union[FileSpecification, str]',
    ) -> str:
        """
        Асинхронное получение содержимого текстового файла с сервера.

        :param specification: Спецификация или имя файла
            (если он находится в папке текущей базы данных).
        :return: Текст файла или пустая строка, если файл не найден
        """
        if not self.check_connection():
            return ''

        if isinstance(specification, str):
            specification = self.near_master(specification)
        query = ClientQuery(self, READ_DOCUMENT).ansi(str(specification))
        response = await self.execute_async(query)
        result = response.ansi_remaining_text()
        result = irbis_to_dos(result)
        response.close()
        return result
예제 #26
0
    def read_ini_file(self, specification: 'Union[FileSpecification, str]') \
            -> IniFile:
        """
        Чтение INI-файла с сервера.

        :param specification: Спецификация
        :return: INI-файл
        """
        if not self.check_connection():
            return IniFile()

        if isinstance(specification, str):
            specification = self.near_master(specification)

        assert isinstance(specification, FileSpecification)

        query = ClientQuery(self, READ_DOCUMENT).ansi(str(specification))
        with self.execute(query) as response:
            result = IniFile()
            text = irbis_to_lines(response.ansi_remaining_text())
            result.parse(text)
            return result
예제 #27
0
    def read_binary_file(
        self,
        specification: 'Union[FileSpecification, str]',
    ) -> 'Optional[bytearray]':
        """
        Чтение двоичного файла с сервера.

        :param specification: Спецификация файла.
        :return: Массив байт или None.
        """
        if not self.check_connection():
            return None

        if isinstance(specification, str):
            specification = self.near_master(specification)

        assert isinstance(specification, FileSpecification)

        specification.binary = True
        query = ClientQuery(self, READ_DOCUMENT).ansi(str(specification))
        with self.execute(query) as response:
            result = response.get_binary_file()
            return result