Java教程

【山大智云开发日志】seafdav分析(12)

本文主要是介绍【山大智云开发日志】seafdav分析(12),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

2021SC@SDUSC

stream_tools.py:实现 FileLikeQueue 帮助器类。 此帮助程序类旨在处理传入 PUT 的用例 请求应直接流式传输到远程目标。 用法:将此类的一个实例返回给`begin_write`,并将其传递给 同时消费者:

 def begin_write(self, contentType=None):

        队列 = FileLikeQueue(max_size=1)

        requests.post(..., 数据=队列)

        返回队列

文件中包含FileLikeQueue、StreamingFile两个类。

FileLikeQueue类:行为类似于文件的块队列。 read() 和 write() 通常从不同的线程调用。 此帮助程序类旨在处理传入 PUT 的用例 请求应直接流式传输到远程目标:

def begin_write(self, contentType=None):

         # 创建代理缓冲区

        队列 = FileLikeQueue(max_size=1)

        # ...并将其用作消费者的来源:

        requests.post(..., 数据=队列)

        # 将它作为目标传递给 PUT 处理程序

        返回队列

函数read(self, size=0):从队列中读取一大块字节。 size = 0:读取下一个块(任意长度) > 0:读取一大块 `size` 字节(如果流已关闭,则读取更少) < 0:将所有字节作为单个块读取(即阻塞直到流关闭) 此方法会阻塞,直到请求的大小可用。 但是,如果调用了 close(),则立即返回 ''。

 def read(self, size=0):
        """Read a chunk of bytes from queue.

        size = 0: Read next chunk (arbitrary length)
             > 0: Read one chunk of `size` bytes (or less if stream was closed)
             < 0: Read all bytes as single chunk (i.e. blocks until stream is closed)

        This method blocks until the requested size become available.
        However, if close() was called, '' is returned immediately.
        """
        res = self.unread
        self.unread = ""
        # Get next chunk, cumulating requested size as needed
        while res == "" or size < 0 or (size > 0 and len(res) < size):
            try:
                # Read pending data, blocking if neccessary
                # (but handle the case that close() is called while waiting)
                res += compat.to_native(self.queue.get(True, 0.1))
            except compat.queue.Empty:
                # There was no pending data: wait for more, unless close() was called
                if self.is_closed:
                    break
        # Deliver `size` bytes from buffer
        if size > 0 and len(res) > size:
            self.unread = res[size:]
            res = res[:size]
        # print("FileLikeQueue.read({}) => {} bytes".format(size, len(res)))
        return res

函数write(self, chunk)将一大块字节(或一个可迭代的)放入队列。如果达到 max_size 块数,则可能会阻塞。

    def write(self, chunk):
        """Put a chunk of bytes (or an iterable) to the queue.

        May block if max_size number of chunks is reached.
        """
        if self.is_closed:
            raise ValueError("Cannot write to closed object")
        # print("FileLikeQueue.write(), n={}".format(len(chunk)))
        # Add chunk to queue (blocks if queue is full)
        if compat.is_basestring(chunk):
            self.queue.put(chunk)
        else:  # if not a string, assume an iterable
            for o in chunk:
                self.queue.put(o)

StreamingFile类 :环绕迭代器/数据流的文件对象

函数__init__(self, data_stream):用数据流初始化对象。

    def __init__(self, data_stream):
        """Intialise the object with the data stream."""
        self.data_stream = data_stream
        self.buffer = ""

函数read(self, size=None):从迭代器读取字节

代码

    def read(self, size=None):
        """Read bytes from an iterator."""
        while size is None or len(self.buffer) < size:
            try:
                self.buffer += next(self.data_stream)
            except StopIteration:
                break

        sized_chunk = self.buffer[:size]
        if size is None:
            self.buffer = ""
        else:
            self.buffer = self.buffer[size:]
        return sized_chunk

wsgidav_app.py:处理 HTTP 请求的 WSGI 容器。这个对象被传递给 WSGI 服务器并对外代表我们的 WsgiDAV 应用程序。 在初始化: 使用配置字典初始化锁管理器、属性管理器、 域控制器。 创建一个共享到提供者映射的字典。 初始化中间件对象并设置 WSGI 应用程序堆栈。 对于每个请求: 查找当前请求的注册 DAV 提供程序。 在 WSGI ``environ`` 中添加或修改信息: 环境[“SCRIPT_NAME”] 当前共享的挂载点。 环境[“PATH_INFO”] 资源路径,相对于挂载路径。 环境[“wsgidav.provider”] 注册用于处理当前的 DAVProvider 对象 要求。 环境[“wsgidav.config”] 配置字典。 环境[“wsgidav.verbose”] 调试级别 [0-3]。 记录 HTTP 请求,然后将请求传递给第一个中间件。

函数resolve_provider(self, path):获取给定路径的注册 DAVProvider。 返回: 元组:(共享,提供者)

 def resolve_provider(self, path):
        """Get the registered DAVProvider for a given path.

        Returns:
            tuple: (share, provider)
        """
        # Find DAV provider that matches the share
        share = None
        lower_path = path.lower()
        for r in self.sorted_share_list:
            # @@: Case sensitivity should be an option of some sort here;
            # os.path.normpath might give the preferred case for a filename.
            if r == "/":
                share = r
                break
            elif lower_path == r or lower_path.startswith(r + "/"):
                share = r
                break

        if share is None:
            return None, None
        return share, self.provider_map.get(share)

xml_tools.py:用于不同 etree 包的小包装。

函数string_to_xml(text):将 XML 字符串转换为 etree.Element

def string_to_xml(text):
    """Convert XML string into etree.Element."""
    try:
        return etree.XML(text)
    except Exception:
        # TODO:
        # ExpatError: reference to invalid character number: line 1, column 62
        # litmus fails, when xml is used instead of lxml
        # 18. propget............... FAIL (PROPFIND on `/temp/litmus/prop2':
        #   Could not read status line: connection was closed by server)
        # text = <ns0:high-unicode xmlns:ns0="http://example.com/neon/litmus/">&#55296;&#56320;
        #   </ns0:high-unicode>
        #        t2 = text.encode("utf8")
        #        return etree.XML(t2)
        _logger.error(
            "Error parsing XML string. "
            "If lxml is not available, and unicode is involved, then "
            "installing lxml _may_ solve this issue."
        )
        _logger.error("XML source: {}".format(text))
        raise

函数xml_to_bytes(element, pretty_print=False):etree.tostring 的包装器,它负责处理不受支持的 pretty_print 选项并预先添加一个编码标头。

def xml_to_bytes(element, pretty_print=False):
    """Wrapper for etree.tostring, that takes care of unsupported pretty_print
    option and prepends an encoding header."""
    if use_lxml:
        xml = etree.tostring(
            element, encoding="UTF-8", xml_declaration=True, pretty_print=pretty_print
        )
    else:
        xml = etree.tostring(element, encoding="UTF-8")
        if not xml.startswith(b"<?xml "):
            xml = b'<?xml version="1.0" encoding="utf-8" ?>\n' + xml

    assert xml.startswith(b"<?xml ")  # ET should prepend an encoding header
    return xml

函数make_multistatus_el():etree.Element 的包装器,负责处理不受支持的 nsmap 选项。

def make_multistatus_el():
    """Wrapper for etree.Element, that takes care of unsupported nsmap option."""
    if use_lxml:
        return etree.Element("{DAV:}multistatus", nsmap={"D": "DAV:"})
    return etree.Element("{DAV:}multistatus")

函数make_prop_el():etree.Element 的包装器,负责处理不受支持的 nsmap 选项

def make_prop_el():
    """Wrapper for etree.Element, that takes care of unsupported nsmap option."""
    if use_lxml:
        return etree.Element("{DAV:}prop", nsmap={"D": "DAV:"})
    return etree.Element("{DAV:}prop")

函数make_sub_element(parent, tag, nsmap=None):etree.SubElement 的包装器,负责处理不受支持的 nsmap 选项。

def make_sub_element(parent, tag, nsmap=None):
    """Wrapper for etree.SubElement, that takes care of unsupported nsmap option."""
    if use_lxml:
        return etree.SubElement(parent, tag, nsmap=nsmap)
    return etree.SubElement(parent, tag)

函数element_content_as_string(element):

序列化 etree.Element。

     注意:元素可能包含多个子元素或仅包含文本(即根本没有子元素)。 因此,当传递回 etree.XML() 时,生成的字符串可能会引发异常

def element_content_as_string(element):
    """Serialize etree.Element.

    Note: element may contain more than one child or only text (i.e. no child
          at all). Therefore the resulting string may raise an exception, when
          passed back to etree.XML().
    """
    if len(element) == 0:
        return element.text or ""  # Make sure, None is returned as ''
    stream = compat.StringIO()
    for childnode in element:
        stream.write(xml_to_bytes(childnode, pretty_print=False) + "\n")
        # print(xml_to_bytes(childnode, pretty_print=False), file=stream)
    s = stream.getvalue()
    stream.close()
    return s

这篇关于【山大智云开发日志】seafdav分析(12)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!