aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/Twisted/py2/twisted/protocols/dict.py
diff options
context:
space:
mode:
authorshmel1k <shmel1k@ydb.tech>2023-11-26 18:16:14 +0300
committershmel1k <shmel1k@ydb.tech>2023-11-26 18:43:30 +0300
commitb8cf9e88f4c5c64d9406af533d8948deb050d695 (patch)
tree218eb61fb3c3b96ec08b4d8cdfef383104a87d63 /contrib/python/Twisted/py2/twisted/protocols/dict.py
parent523f645a83a0ec97a0332dbc3863bb354c92a328 (diff)
downloadydb-b8cf9e88f4c5c64d9406af533d8948deb050d695.tar.gz
add kikimr_configure
Diffstat (limited to 'contrib/python/Twisted/py2/twisted/protocols/dict.py')
-rw-r--r--contrib/python/Twisted/py2/twisted/protocols/dict.py415
1 files changed, 415 insertions, 0 deletions
diff --git a/contrib/python/Twisted/py2/twisted/protocols/dict.py b/contrib/python/Twisted/py2/twisted/protocols/dict.py
new file mode 100644
index 0000000000..d7976411bc
--- /dev/null
+++ b/contrib/python/Twisted/py2/twisted/protocols/dict.py
@@ -0,0 +1,415 @@
+# Copyright (c) Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+
+"""
+Dict client protocol implementation.
+
+@author: Pavel Pergamenshchik
+"""
+
+from twisted.protocols import basic
+from twisted.internet import defer, protocol
+from twisted.python import log
+from io import BytesIO
+
+def parseParam(line):
+ """Chew one dqstring or atom from beginning of line and return (param, remaningline)"""
+ if line == b'':
+ return (None, b'')
+ elif line[0:1] != b'"': # atom
+ mode = 1
+ else: # dqstring
+ mode = 2
+ res = b""
+ io = BytesIO(line)
+ if mode == 2: # skip the opening quote
+ io.read(1)
+ while 1:
+ a = io.read(1)
+ if a == b'"':
+ if mode == 2:
+ io.read(1) # skip the separating space
+ return (res, io.read())
+ elif a == b'\\':
+ a = io.read(1)
+ if a == b'':
+ return (None, line) # unexpected end of string
+ elif a == b'':
+ if mode == 1:
+ return (res, io.read())
+ else:
+ return (None, line) # unexpected end of string
+ elif a == b' ':
+ if mode == 1:
+ return (res, io.read())
+ res += a
+
+
+
+def makeAtom(line):
+ """Munch a string into an 'atom'"""
+ # FIXME: proper quoting
+ return filter(lambda x: not (x in map(chr, range(33)+[34, 39, 92])), line)
+
+
+
+def makeWord(s):
+ mustquote = range(33)+[34, 39, 92]
+ result = []
+ for c in s:
+ if ord(c) in mustquote:
+ result.append(b"\\")
+ result.append(c)
+ s = b"".join(result)
+ return s
+
+
+
+def parseText(line):
+ if len(line) == 1 and line == b'.':
+ return None
+ else:
+ if len(line) > 1 and line[0:2] == b'..':
+ line = line[1:]
+ return line
+
+
+
+class Definition:
+ """A word definition"""
+ def __init__(self, name, db, dbdesc, text):
+ self.name = name
+ self.db = db
+ self.dbdesc = dbdesc
+ self.text = text # list of strings not terminated by newline
+
+
+
+class DictClient(basic.LineReceiver):
+ """dict (RFC2229) client"""
+
+ data = None # multiline data
+ MAX_LENGTH = 1024
+ state = None
+ mode = None
+ result = None
+ factory = None
+
+ def __init__(self):
+ self.data = None
+ self.result = None
+
+
+ def connectionMade(self):
+ self.state = "conn"
+ self.mode = "command"
+
+
+ def sendLine(self, line):
+ """Throw up if the line is longer than 1022 characters"""
+ if len(line) > self.MAX_LENGTH - 2:
+ raise ValueError("DictClient tried to send a too long line")
+ basic.LineReceiver.sendLine(self, line)
+
+
+ def lineReceived(self, line):
+ try:
+ line = line.decode("utf-8")
+ except UnicodeError: # garbage received, skip
+ return
+ if self.mode == "text": # we are receiving textual data
+ code = "text"
+ else:
+ if len(line) < 4:
+ log.msg("DictClient got invalid line from server -- %s" % line)
+ self.protocolError("Invalid line from server")
+ self.transport.LoseConnection()
+ return
+ code = int(line[:3])
+ line = line[4:]
+ method = getattr(self, 'dictCode_%s_%s' % (code, self.state), self.dictCode_default)
+ method(line)
+
+
+ def dictCode_default(self, line):
+ """Unknown message"""
+ log.msg("DictClient got unexpected message from server -- %s" % line)
+ self.protocolError("Unexpected server message")
+ self.transport.loseConnection()
+
+
+ def dictCode_221_ready(self, line):
+ """We are about to get kicked off, do nothing"""
+ pass
+
+
+ def dictCode_220_conn(self, line):
+ """Greeting message"""
+ self.state = "ready"
+ self.dictConnected()
+
+
+ def dictCode_530_conn(self):
+ self.protocolError("Access denied")
+ self.transport.loseConnection()
+
+
+ def dictCode_420_conn(self):
+ self.protocolError("Server temporarily unavailable")
+ self.transport.loseConnection()
+
+
+ def dictCode_421_conn(self):
+ self.protocolError("Server shutting down at operator request")
+ self.transport.loseConnection()
+
+
+ def sendDefine(self, database, word):
+ """Send a dict DEFINE command"""
+ assert self.state == "ready", "DictClient.sendDefine called when not in ready state"
+ self.result = None # these two are just in case. In "ready" state, result and data
+ self.data = None # should be None
+ self.state = "define"
+ command = "DEFINE %s %s" % (makeAtom(database.encode("UTF-8")), makeWord(word.encode("UTF-8")))
+ self.sendLine(command)
+
+
+ def sendMatch(self, database, strategy, word):
+ """Send a dict MATCH command"""
+ assert self.state == "ready", "DictClient.sendMatch called when not in ready state"
+ self.result = None
+ self.data = None
+ self.state = "match"
+ command = "MATCH %s %s %s" % (makeAtom(database), makeAtom(strategy), makeAtom(word))
+ self.sendLine(command.encode("UTF-8"))
+
+ def dictCode_550_define(self, line):
+ """Invalid database"""
+ self.mode = "ready"
+ self.defineFailed("Invalid database")
+
+
+ def dictCode_550_match(self, line):
+ """Invalid database"""
+ self.mode = "ready"
+ self.matchFailed("Invalid database")
+
+
+ def dictCode_551_match(self, line):
+ """Invalid strategy"""
+ self.mode = "ready"
+ self.matchFailed("Invalid strategy")
+
+
+ def dictCode_552_define(self, line):
+ """No match"""
+ self.mode = "ready"
+ self.defineFailed("No match")
+
+
+ def dictCode_552_match(self, line):
+ """No match"""
+ self.mode = "ready"
+ self.matchFailed("No match")
+
+
+ def dictCode_150_define(self, line):
+ """n definitions retrieved"""
+ self.result = []
+
+
+ def dictCode_151_define(self, line):
+ """Definition text follows"""
+ self.mode = "text"
+ (word, line) = parseParam(line)
+ (db, line) = parseParam(line)
+ (dbdesc, line) = parseParam(line)
+ if not (word and db and dbdesc):
+ self.protocolError("Invalid server response")
+ self.transport.loseConnection()
+ else:
+ self.result.append(Definition(word, db, dbdesc, []))
+ self.data = []
+
+
+ def dictCode_152_match(self, line):
+ """n matches found, text follows"""
+ self.mode = "text"
+ self.result = []
+ self.data = []
+
+
+ def dictCode_text_define(self, line):
+ """A line of definition text received"""
+ res = parseText(line)
+ if res == None:
+ self.mode = "command"
+ self.result[-1].text = self.data
+ self.data = None
+ else:
+ self.data.append(line)
+
+
+ def dictCode_text_match(self, line):
+ """One line of match text received"""
+ def l(s):
+ p1, t = parseParam(s)
+ p2, t = parseParam(t)
+ return (p1, p2)
+ res = parseText(line)
+ if res == None:
+ self.mode = "command"
+ self.result = map(l, self.data)
+ self.data = None
+ else:
+ self.data.append(line)
+
+
+ def dictCode_250_define(self, line):
+ """ok"""
+ t = self.result
+ self.result = None
+ self.state = "ready"
+ self.defineDone(t)
+
+
+ def dictCode_250_match(self, line):
+ """ok"""
+ t = self.result
+ self.result = None
+ self.state = "ready"
+ self.matchDone(t)
+
+
+ def protocolError(self, reason):
+ """override to catch unexpected dict protocol conditions"""
+ pass
+
+
+ def dictConnected(self):
+ """override to be notified when the server is ready to accept commands"""
+ pass
+
+
+ def defineFailed(self, reason):
+ """override to catch reasonable failure responses to DEFINE"""
+ pass
+
+
+ def defineDone(self, result):
+ """override to catch successful DEFINE"""
+ pass
+
+
+ def matchFailed(self, reason):
+ """override to catch resonable failure responses to MATCH"""
+ pass
+
+
+ def matchDone(self, result):
+ """override to catch successful MATCH"""
+ pass
+
+
+
+class InvalidResponse(Exception):
+ pass
+
+
+
+class DictLookup(DictClient):
+ """Utility class for a single dict transaction. To be used with DictLookupFactory"""
+
+ def protocolError(self, reason):
+ if not self.factory.done:
+ self.factory.d.errback(InvalidResponse(reason))
+ self.factory.clientDone()
+
+
+ def dictConnected(self):
+ if self.factory.queryType == "define":
+ self.sendDefine(*self.factory.param)
+ elif self.factory.queryType == "match":
+ self.sendMatch(*self.factory.param)
+
+
+ def defineFailed(self, reason):
+ self.factory.d.callback([])
+ self.factory.clientDone()
+ self.transport.loseConnection()
+
+
+ def defineDone(self, result):
+ self.factory.d.callback(result)
+ self.factory.clientDone()
+ self.transport.loseConnection()
+
+
+ def matchFailed(self, reason):
+ self.factory.d.callback([])
+ self.factory.clientDone()
+ self.transport.loseConnection()
+
+
+ def matchDone(self, result):
+ self.factory.d.callback(result)
+ self.factory.clientDone()
+ self.transport.loseConnection()
+
+
+
+class DictLookupFactory(protocol.ClientFactory):
+ """Utility factory for a single dict transaction"""
+ protocol = DictLookup
+ done = None
+
+ def __init__(self, queryType, param, d):
+ self.queryType = queryType
+ self.param = param
+ self.d = d
+ self.done = 0
+
+
+ def clientDone(self):
+ """Called by client when done."""
+ self.done = 1
+ del self.d
+
+
+ def clientConnectionFailed(self, connector, error):
+ self.d.errback(error)
+
+
+ def clientConnectionLost(self, connector, error):
+ if not self.done:
+ self.d.errback(error)
+
+
+ def buildProtocol(self, addr):
+ p = self.protocol()
+ p.factory = self
+ return p
+
+
+
+def define(host, port, database, word):
+ """Look up a word using a dict server"""
+ d = defer.Deferred()
+ factory = DictLookupFactory("define", (database, word), d)
+
+ from twisted.internet import reactor
+ reactor.connectTCP(host, port, factory)
+ return d
+
+
+
+def match(host, port, database, strategy, word):
+ """Match a word using a dict server"""
+ d = defer.Deferred()
+ factory = DictLookupFactory("match", (database, strategy, word), d)
+
+ from twisted.internet import reactor
+ reactor.connectTCP(host, port, factory)
+ return d
+