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

2021SC@SDUSC

dav_provider_tools.py是使实现自定义WsgiDAV提供商变得更容易的工具。

文件由VirtualCollection、_VirtualNonCollection、VirtualTextResource三个虚类和FileResource、DAVResolver两个普通的类构成。

虚基类VirtualCollection是一个包含静态成员列表的集合的抽象基类。将成员名传递给构造函数。Get_member()通过调用self.provider.get_resource_inst()实现

主要代码

    def __init__(self, path, environ, display_info, member_name_list):#构造函数
        super(VirtualCollection, self).__init__(path, environ)
        if compat.is_basestring(display_info):
            display_info = {"type": display_info}
        assert type(display_info) is dict
        assert type(member_name_list) is list
        self.display_info = display_info
        self.member_name_list = member_name_list   
    
    
    def get_member(self, name):
        # raise NotImplementedError
        return self.provider.get_resource_inst(
            util.join_uri(self.path, name), self.environ
        )

_VirtualNonCollection是所有非集合资源的抽象基类

VirtualTextResource是一个包含一个字符串的虚拟类。

主要代码

    def __init__(self, path, environ, content, display_name=None, display_type=None):#构造函数
        super(VirtualTextResource, self).__init__(path, environ)
        self.content = content
        self.display_name = display_name
        self.display_type = display_type
​
    def get_content_length(self):
        return len(self.get_content().read())
​
    def get_content_type(self):
        if self.name.endswith(".txt"):
            return "text/plain"
        return "text/html"

FileResource负责表示现有文件

DAVResolver主要是返回一个路径DAVResource对象(如果没有找到则为None)

主要代码

    def __init__(self, parent_resolver, name):#构造函数
        self.parent_resolver = parent_resolver
        self.name = name
​
    def resolve(self, script_name, path_info, environ):
        raise NotImplementedError

hg_dav_provider.py:

发布 Mercurial 存储库的 DAV 提供程序。 存储库呈现为三个顶级集合。 编辑: 包含工作目录,即所有文件。这包括未承诺的 更改和未跟踪的新文件。 该文件夹是可写的。 发布: 包含最新提交的文件,也称为“提示”。 此文件夹是只读的。 档案: 包含最近 10 个修订作为子文件夹。 此文件夹是只读的。

支持的功能:

#.将文件从 /edit/.. 复制或移动到 /edit/.. 文件夹将 导致“hg copy”或“hg rename”。

#.从 /edit/.. 删除资源将导致 hg remove。 #.将文件从 /edit/.. 复制或移动到 /released 文件夹将 导致“hg commit”。 请注意,目标路径被忽略,而是使用源路径。 所以用户可以从 edit/.. 下的某处拖动文件或文件夹 目录并将其直接放在 released 目录中以进行提交 变化。

#.要提交所有更改,只需将“/edit”文件夹拖放到 /released 文件夹。

#.创建新的集合会导致创建一个名为 .directory 的文件,然后是 hg add ed,因为 Mercurial 不跟踪目录。

#.一些属性作为实时属性发布,例如“{hg:}date”。

这个文件也比较复杂。包含HgResource、HgResourceProvider两个类。

HgResource是所有资源的抽象基类 。类的功能比较复杂,主要的代码如下。与类DAVResource关联性强

    def _check_write_access(self):#如果资源不可写,则提高 HTTP_FORBIDDEN
        if self.rev is not None:
            # 只能编辑工作目录
            raise DAVError(HTTP_FORBIDDEN)
    def get_member(self, name):#依赖提供者获取成员实例
        assert self.is_collection
        return self.provider.get_resource_inst(
            util.join_uri(self.path, name), self.environ
        )    
    def get_property_names(self, is_allprop):#Return list of supported property names in Clark Notation.See DAVResource.get_property_names()
    def get_property_value(self, name)#返回属性的值参见 get_property_value() 
    def set_property_value(self, name, value, dry_run=False)#设置或删除属性值。参见 DAVResource.set_property_value() 
    def create_empty_resource(self, name):#创建并返回一个空(长度为 0)的资源作为 self 的成员。参见 DAVResource.create_empty_resource() 
    def create_collection(self, name)#创建一个新集合作为 self 的成员。 创建了一个虚拟成员,因为 Mercurial 不处理文件夹 
     def begin_write(self, content_type=None)#打开内容作为写入流。参见 DAVResource.begin_write() 
        

类HgResourceProvider是为 VirtualResource 派生结构提供服务的 DAV 提供程序。

主要方法def _get_repo_info(self, environ, rev, reload=False)。主要负责返回包含源代码控制下的所有文件的字典。

目录信息:包含每个集合的直接成员的字典。

{文件夹路径:(收藏列表,文件列表),...}

文件:清单中所有文件路径的排序列表。

文件名:包含受源代码控制的所有文件的字典。

def get_resource_inst(self, path, environ)#返回路径的 HgResource 对象。参见 DAVProvider.get_resource_inst() 
def _get_log(self, limit=None)#将日志条目读入字典列表。

mysql_dav_provider.py是WebDAV 提供程序的实现,它提供了一个非常基本的、只读的 MySQL 数据库的资源层模拟。 此模块特定于 WsgiDAV 应用程序。它提供了一个 类“MySQLBrowserProvider”。

用法:(见 doc/sample_wsgidav.conf)

MySQLBrowserProvider(主机、用户、密码、数据库)

host - 数据库服务器的主机

user - 访问数据库的用户名

passwd - 访问数据库的密码

db - 数据库服务器上的数据库名称 MySQLBrowserProvider 提供了一个非常基本的只读 MySQL 数据库的资源层模拟。 它提供以下接口:

  • 共享的根集合由对应于的集合组成表名

  • 在每个表集合中,都有一个名为“_ENTIRE_CONTENTS”的资源.这是一个非集合资源,它返回一个 csv 表示 整桌

  • 如果表只有一个主键,每条表记录也会出现使用主键作为表集合中的非集合资源 值作为其名称。此资源返回记录的 csv 表示并且还将包含记录属性作为实时属性属性名作为属性名,表名以冒号为后缀属性命名空间

包含MySQLBrowserResource、MySQLBrowserProvider两个类。

MySQLBrowserResource:表示单个现有 DAV 资源实例 。

主要函数:

def get_member_list(self)#返回(直接)集合成员名称的列表(UTF-8 字节字符串)
def get_content(self)#打开内容作为阅读流。 
def get_property_names(self, is_allprop)#返回一个属性的值
def get_property_value(self, name):
        基本实现处理:
​
         - ``{DAV:}lockdiscovery`` 和 ``{DAV:}supportedlock`` 使用
           关联的锁管理器。
         - 所有其他 *live* 属性(即名称以“{DAV:}”开头)都是
           委托给 self.getLivePropertyValue()
         - 最后,其他属性被视为*dead*,并使用
           相关的物业经理,如果有的话。
def set_property_value(self, name, value, dry_run=False):#设置或删除属性值。

类MySQLBrowserProvider:负责MySQL浏览器的提供。

主要函数

def _split_path(self, path)#返回(表名,主键)请求路径的元组。 
def get_resource_inst(self, path, environ)#返回路径的信息字典。调用exists() 使目录浏览非常慢。至少与PyFileServer 相比,它只是使用字符串函数来获取display_type 和displayTypeComment  

virtual_dav_provider.py:提供可浏览的 DAV 提供程序的示例实现, 多分类资源树。 它演示了一些自定义 WsgiDAV 的技术。 与已发布的文件系统相比,主要有以下主要区别:

#.像“My doc 1”这样的资源有几个像“key”这样的属性,key, orga, tags, status, description.。 也可能有一个附加文件的列表。

#.这些属性用于动态创建虚拟层次结构。 例如,如果status是draft,则集合 <share>/by_status/draft/ 被创建并且资源被映射到 <share>/by_status/draft/My doc 1

#.资源 My doc 1 呈现为一个集合,其中包含 一些虚拟描述文件和附加文件。

class RootCollection(DAVCollection):#解析顶级请求'/'
class CategoryTypeCollection(DAVCollection):#解析'/catType' URL,例如'/by_tag'。
class CategoryCollection(DAVCollection)#解析'/catType/cat' URL,例如'/by_tag/cool'

所包含的虚类如下

class VirtualResource(DAVCollection)#虚拟“资源”,显示为工件和文件的集合
class _VirtualNonCollection(DAVNonCollection)#所有非集合资源的抽象基类。
class VirtualArtifact(_VirtualNonCollection)#一个虚拟文件,包含资源描述。
class VirtualResFile(_VirtualNonCollection)#代表一个现有的文件,它是一个 VirtualResource 的成员
class VirtualResourceProvider(DAVProvider):#为 VirtualResource 派生结构提供服务的 DAV 提供程序 

VirtualResource是最为主要的类。其主要代码及相应功能如下。

def handle_delete(self):#更改 DELETE 的语义以删除资源标签
   
    # DELETE 仅支持 '/by_tag/' 集合 
    if "/by_tag/" not in self.path:
        raise DAVError(HTTP_FORBIDDEN)
    # 路径必须是 '/by_tag/<tag>/<resname>'
    catType, tag, _rest = util.save_split(self.path.strip("/"), "/", 2)
    assert catType == "by_tag"
    assert tag in self.data["tags"]
    self.data["tags"].remove(tag)
    return True  # OK
​
def handle_copy(self, dest_path, depth_infinity):
#更改 COPY 的语义以添加资源标签
    # destPath 必须是 '/by_tag/<tag>/<resname>'
    if "/by_tag/" not in dest_path:
        raise DAVError(HTTP_FORBIDDEN)
    catType, tag, _rest = util.save_split(dest_path.strip("/"), "/", 2)
    assert catType == "by_tag"
    if tag not in self.data["tags"]:
        self.data["tags"].append(tag)
    return True  # OK
​
def handle_move(self, dest_path):
   #更改 MOVE 的语义以更改资源标签
    # path and destPath必须是 '/by_tag/<tag>/<resname>'
    if "/by_tag/" not in self.path:
        raise DAVError(HTTP_FORBIDDEN)
    if "/by_tag/" not in dest_path:
        raise DAVError(HTTP_FORBIDDEN)
    catType, tag, _rest = util.save_split(self.path.strip("/"), "/", 2)
    assert catType == "by_tag"
    assert tag in self.data["tags"]
    self.data["tags"].remove(tag)
    catType, tag, _rest = util.save_split(dest_path.strip("/"), "/", 2)
    assert catType == "by_tag"
    if tag not in self.data["tags"]:
        self.data["tags"].append(tag)
    return True  # OK
​
def get_ref_url(self):
    refPath = "/by_key/%s" % self.data["key"]
    return compat.quote(self.provider.share_path + refPath)
​
def get_property_names(self, is_allprop):
    # 让基类实现添加支持的 live 和 dead 属性 
    propNameList = super(VirtualResource, self).get_property_names(is_allprop)
    # 添加自定义实时属性(报告“allprop”和“propnames”)
    propNameList.extend(VirtualResource._supportedProps)
    return propNameList
​
def get_property_value(self, name):
    #返回属性的值。参考get_property_value()
    # 支持的自定义实时属性 
    if name == "{virtres:}key":
        return self.data["key"]
    elif name == "{virtres:}title":
        return self.data["title"]
    elif name == "{virtres:}status":
        return self.data["status"]
    elif name == "{virtres:}orga":
        return self.data["orga"]
    elif name == "{virtres:}tags":
        # 'tags' is a string list
        return ",".join(self.data["tags"])
    elif name == "{virtres:}description":
        return self.data["description"]
    
    return super(VirtualResource, self).get_property_value(name)
​
def set_property_value(self, name, value, dry_run=False):
   #设置或删除属性值。 
​
    if value is None:
        # 将永远无法删除属性 
        raise DAVError(HTTP_FORBIDDEN)
    if name == "{virtres:}tags":
        # 值是 etree.Element 类型 
        self.data["tags"] = value.text.split(",")
    elif name == "{virtres:}description":
        # 值是 etree.Element 类型 
        self.data["description"] = value.text
    elif name in VirtualResource._supportedProps:
        # 受支持的属性
        raise DAVError(
            HTTP_FORBIDDEN, err_condition=PRECONDITION_CODE_ProtectedProperty
        )
    else:
        # 不受支持
        raise DAVError(HTTP_FORBIDDEN)
    return
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值