[entropy.transceivers] more API work on EntropyTransceiver and EntropyUriHandler classes and subclasses

This commit is contained in:
Fabio Erculiani
2009-11-15 16:36:50 +01:00
parent d0fe45ab84
commit 38d0f0fc4d
2 changed files with 169 additions and 32 deletions
+148 -32
View File
@@ -28,7 +28,7 @@ from entropy.output import TextInterface, darkblue, darkred, purple, blue, \
brown, darkgreen, red, bold
from entropy.i18n import _
from entropy.misc import ParallelTask
from entropy.misc import ParallelTask, Lifo
from entropy.core.settings.base import SystemSettings
from entropy.exceptions import *
@@ -741,6 +741,24 @@ class EntropyTransceiver(TextInterface):
self._timeout = None
self._silent = None
self._output_interface = None
self.__with_stack = Lifo()
def __enter__(self):
"""
Support for "with" statement, this method will execute swallow() and
return a valid EntropyUriHandler instance.
"""
handler = self.swallow()
self.__with_stack.push(handler)
return handler
def __exit__(self, exc_type, exc_value, traceback):
"""
Support for "with" statement, this method will automagically close the
previously created EntropyUriHandler instance connection.
"""
handler = self.__with_stack.pop() # if this fails, it's not a good sign
handler.close()
def set_output_interface(self, output_interface):
"""
@@ -853,6 +871,20 @@ class EntropyUriHandler(TextInterface):
self._silent = False
self._timeout = None
def __enter__(self):
"""
Support for "with" statement, this will trigger UriHandler connection
setup.
"""
raise NotImplementedError()
def __exit__(self, exc_type, exc_value, traceback):
"""
Support for "with" statement, this will trigger UriHandler connection
hang up.
"""
raise NotImplementedError()
@staticmethod
def approve_uri(uri):
"""
@@ -1033,6 +1065,7 @@ class EntropyUriHandler(TextInterface):
@type remote_path: string
@return: content
@rtype: list
@raise ValueError: if remote_path does not exist
"""
raise NotImplementedError()
@@ -1046,6 +1079,7 @@ class EntropyUriHandler(TextInterface):
@type remote_path: string
@return: content
@rtype: list
@raise ValueError: if remote_path does not exist
"""
raise NotImplementedError()
@@ -1061,6 +1095,30 @@ class EntropyUriHandler(TextInterface):
"""
raise NotImplementedError()
def is_dir(self, remote_path):
"""
Given a remote path (which can point to dir or file), determine whether
it's a directory.
@param remote_path: URI to handle
@type remote_path: string
@return: True, if remote_path is a directory
@rtype: bool
"""
raise NotImplementedError()
def is_file(self, remote_path):
"""
Given a remote path (which can point to dir or file), determine whether
it's a file.
@param remote_path: URI to handle
@type remote_path: string
@return: True, if remote_path is a file
@rtype: bool
"""
raise NotImplementedError()
def makedirs(self, remote_path):
"""
Given a remote path, recursively create all the missing directories.
@@ -1137,6 +1195,49 @@ class EntropyFtpUriHandler(EntropyUriHandler):
self._connect()
self._disconnect()
def __enter__(self):
pass # self.__connect_if_not()
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def __extract_ftp_data(self, ftpuri):
ftpuser = ftpuri.split("ftp://")[-1].split(":")[0]
if (not ftpuser):
ftpuser = "anonymous@"
ftppassword = "anonymous"
else:
ftppassword = ftpuri.split("@")[:-1]
if len(ftppassword) > 1:
ftppassword = '@'.join(ftppassword)
ftppassword = ftppassword.split(":")[-1]
if (not ftppassword):
ftppassword = "anonymous"
else:
ftppassword = ftppassword[0]
ftppassword = ftppassword.split(":")[-1]
if not ftppassword:
ftppassword = "anonymous"
ftpport = ftpuri.split(":")[-1]
try:
ftpport = int(ftpport)
except ValueError:
ftpport = 21
ftpdir = '/'
if ftpuri.count("/") > 2:
if ftpuri.startswith("ftp://"):
ftpdir = ftpuri[6:]
ftpdir = "/" + ftpdir.split("/", 1)[-1]
ftpdir = ftpdir.split(":")[0]
if not ftpdir:
ftpdir = '/'
elif ftpdir.endswith("/") and (ftpdir != "/"):
ftpdir = ftpdir[:-1]
return ftpuser, ftppassword, ftpport, ftpdir
def __connect_if_not(self):
"""
Handy internal method.
@@ -1385,7 +1486,7 @@ class EntropyFtpUriHandler(EntropyUriHandler):
self.__filesize = 0
with open(tmp_save_path, "wb") as f:
rc = self.__ftpconn.retrbinary('RETR ' + path, writer, 1024)
rc = self.__ftpconn.retrbinary('RETR ' + path, writer, 8192)
f.flush()
done = rc.find("226") != -1
@@ -1412,32 +1513,6 @@ class EntropyFtpUriHandler(EntropyUriHandler):
)
self._reconnect() # reconnect
def __ftp_advanced_stor(self, cmd, fp):
"""
this function also supports callback, because storbinary doesn't
"""
self.__ftpconn.voidcmd('TYPE I')
conn = self.__ftpconn.transfercmd(cmd)
while True:
buf = fp.readline()
if not buf:
break
conn.sendall(buf)
self._commit_buffer_update(len(buf))
self._update_speed()
self._update_progress()
self._speed_limit_loop()
# that's another workaround
#return "226"
try:
rc = self.__ftpconn.voidresp()
except:
self._reconnect()
return "226"
return rc
def upload(self, load_path, remote_path):
self.__connect_if_not()
@@ -1446,6 +1521,12 @@ class EntropyFtpUriHandler(EntropyUriHandler):
tmp_path = path + ".dtmp"
tries = 0
def updater(buf):
self._commit_buffer_update(len(buf))
self._update_speed()
self._update_progress()
self._speed_limit_loop()
while tries < 10:
tries += 1
@@ -1459,7 +1540,8 @@ class EntropyFtpUriHandler(EntropyUriHandler):
self.__filesize = round(float(file_size)/ 1024, 1)
self.__filekbcount = 0
rc = self.__ftp_advanced_stor("STOR " + tmp_path, f)
rc = self.__ftpconn.storbinary("STOR " + tmp_path, f,
8192, updater)
# now we can rename the file with its original name
self.rename(tmp_path, path)
@@ -1531,7 +1613,10 @@ class EntropyFtpUriHandler(EntropyUriHandler):
def list_content(self, remote_path):
self.__connect_if_not()
path = os.path.join(self.__ftpdir, remote_path)
return [os.path.basename(x) for x in self.__ftpconn.nlst(path)]
try:
return [os.path.basename(x) for x in self.__ftpconn.nlst(path)]
except self.ftplib.error_temp:
raise ValueError("No such file or directory")
def list_content_metadata(self, remote_path):
self.__connect_if_not()
@@ -1540,7 +1625,11 @@ class EntropyFtpUriHandler(EntropyUriHandler):
mybuffer = []
def bufferizer(buf):
mybuffer.append(buf)
self.__ftpconn.dir(path, bufferizer)
try:
self.__ftpconn.dir(path, bufferizer)
except self.ftplib.error_temp:
raise ValueError("No such file or directory")
data = []
for item in mybuffer:
@@ -1551,6 +1640,28 @@ class EntropyFtpUriHandler(EntropyUriHandler):
return data
def is_dir(self, remote_path):
self.__connect_if_not()
path = os.path.join(self.__ftpdir, remote_path)
cwd = self._get_cwd()
data = True
try:
self.__set_cwd(path)
except self.ftplib.error_perm:
data = False
finally:
self.__set_cwd(cwd)
return data
def is_file(self, remote_path):
if self.is_dir(remote_path):
return False
return self.is_path_available(remote_path)
def _is_path_available(self, full_path):
path, fn = os.path.split(full_path)
@@ -1560,7 +1671,12 @@ class EntropyFtpUriHandler(EntropyUriHandler):
if y == fn:
content.append(y)
self.__ftpconn.retrlines('NLST %s' % (path,), cb)
try:
self.__ftpconn.retrlines('NLST %s' % (path,), cb)
except self.ftplib.error_temp as err:
if not str(err).startswith("450"):
raise # wtf?
# path does not exist if FTP error 450 is raised
if content:
return True
@@ -0,0 +1,21 @@
import sys, os
sys.path.insert(0, "../../libraries")
from entropy.transceivers import EntropyTransceiver
txc = EntropyTransceiver("uri://")
# txc.set_speed_limit(35)
txc.set_silent(False)
txc.set_verbosity(True)
handler = txc.swallow()
print handler
print "listing", handler.list_content(".")
print "listing meta", handler.list_content_metadata(".")
print "pushing keep alive", handler.keep_alive()
print "trying to delete test.rnd", handler.is_path_available("test.rnd"), handler.delete("test.rnd")
print "trying to upload test.rnd", handler.upload("test.rnd", "test.rnd")
print "getting md5 of test.rnd", handler.get_md5("test.rnd")
print "downloading test.rnd", handler.download("test.rnd", "test.rnd_down"), os.path.isfile("test.rnd_down")
print "renaming test.rnd", handler.rename("test.rnd", "test.rnd2")
print "checking if test.rnd2 is available", handler.is_path_available("test.rnd2"), "old one =>", handler.is_path_available("test.rnd")
print "deleting test.rnd2", handler.delete("test.rnd2"), handler.is_path_available("test.rnd2")
print "bye bye", handler.close()