У меня проблема. Я уже упоминал о ней, но вот, решил посоветоваться.
Абстрактно: есть клиент и сервер. После того, как клиент коннектится система становится равноправной или одноранговой. Пользователю не нужно лишних проблем и он не знает про то, каким протоколом идёт общение. Для этого я реализовал традиционное трио: клиент - шлюз/фасад - sender/reciver.
Так вот, к чему я веду. Мне нужен нормальный интерфейс между клиентом и шлюзом. Система попучилась довольно проста, что мне и нравится, но мне совершенно не нравится, как это выглядет. Как то нелогично. А работать с этим придётся довольно долго! И неохота мне перелопачивать весь код, когда до меня допрёт как это нарисовать нормально. Буду премного благодарен, если поможете мне с его оформлением.
Итак, это сам шлюз:
# -*- coding: utf-8 -*-
class RemoteObject(object):
def __init__(self, Proxy, Name):
self.__Proxy = Proxy
self.__Name = Name
def __call__(self, *args, **kw):
return self.__Proxy.SocketParser.callObject(self.__Name, args, kw)
def __getattr__(self, MethodName):
return lambda *args, **kw: self.__Proxy.SocketParser.callObjectMethod(
self.__Name, MethodName, args, kw)
class Proxy(object):
class ProxyException(Exception): pass
def __init__(self, SocketFile, SocketParser):
self.SocketFile = SocketFile
self.SharedObjects = {} ## {'ИмяОбъекта': Объект, ...}
self.SocketParser = SocketParser(self)
def setRecivePaused(self, Bool): self.SocketParser.RecivePaused = Bool
RecivePaused = property(lambda self: self.SocketParser.RecivePaused, setRecivePaused)
def register(self, Object, Name = None, SharedMethods = [], IsCallable = None):
if Name is None: Name = Object.Name
if IsCallable is None: IsCallable = callable(Object)
if hasattr(Object, "SharedMethods"):
self.SharedObjects[Name] = (Object, Object.SharedMethods + SharedMethods, IsCallable)
else: self.SharedObjects[Name] = (Object, SharedMethods, IsCallable)
def unregister(self, Name):
del self.SharedObjects[Name]
def localCall(self, ObjectName, MetodName = None, Args = (), Kw = {}):
'''Вызов локального зарегистрированного объекта. Используется Parser\'ом, а не клиентом.'''
...
def getObject(self, Name): return RemoteObject(self, Name)
def __getitem__(self, Name): return self.getObject(Name)А работает это так (первая сторона):Proxy = Proxy(Parser) ## В парсер лезть не будем, не о нём речь
Proxy.register(int, 'int') ## Регистрируем функцию int с именем 'int'
class O(object):
Name = 'Test'
SharedMethods = ['sum', 'mul']
def sum(self, x, y): return x + y
mul = lambda self, x, y: x*y
def __call__(self, x = 2, y = 1): return x**y
o = O()
Proxy.register(o) ## Регистрируем объект o с именем 'Test' и разрешёнными методами sum и mul
Proxy.RecivePaused = False ## Готовы к приёмуТеперь другая сторона:Proxy = Proxy(Parser)
Proxy.RecivePaused = False
print Proxy['int']('12345') #=> 12345
o = Proxy['Test']
print o.sum(123, 321) #=> 444
print o.mul(x = 123, y = 321) #=> 39483
print o(y = 100000) #=> ...не будем забивать форум 30103-мя цифрами...Стоит упомянуть, что параметры и результаты запросов ограничены следующими типами:NoneType, bool, str, unicode, int, long, float, decimal.Decimal,
datetime.time, datetime.date, datetime.datetime и datetime.interval.
А так же "контейнеры" list, tulpe и dict, содержащие только вышеперечисленные типы.
Ещё хочу ввести тип итератор, который будет запрашивать новые данные по мере обработки, но это не так просто, как может показаться.
Приму в дар любые предложения по повышению удобства использования этого кода.
P.S. Идея ReciveObject нагло спёрта мною из Pyro (Python Remote Objects).
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.