ancient.rig.register 源代码

register_route = []
end_register_route = []


def _url(match, union):
    """

    当union为true时,替换掉字符中+和*符号

    :param match: 匹配字符串
    :param union:
    :return: 清洗后的字符串

    """
    return match.replace("*", "").replace("+", "") if union else match


[文档]class RESTful: """ RESTful风格路由生成器,用于快速生成restful风格路由, 生成的路由可以被注册,不建议过长的路由匹配,尽量使用querystring 进行参数传递 示例一:: rf = register.rf # 以对象的方式描写RESTful风格路由,相当于 # /zoos/{动物园ID}/animals # 动物园所有动物 # /zoos/{动物园ID}/animals/{动物ID} # 动物园指定ID的动物 @register.route(url=rf.e("zoos").e("animals").url) 示例二:: # 与上述注册方式效果一致 @register.route(url=RESTful(["zoos", "animals"]).u()) @register.route(url=RESTful([("zoos","(正则的类型,斜杠)w"), "animals"]).url) 示例三:: # 压缩实体去掉前缀路径,使用s方法注册的实体不包含前缀,即/{动物园ID} @register.route(url=rf.s("zoos").url) # 控制实例ID标识项是否可以省略,默认是可省略的标识 @register.route(url=rf.e("zoos").u(rf.LOOSE)) # 严格模式下必须包含指定的动物园ID,即无法匹配 /zoos @register.route(url=rf.e("zoos").u(rf.STRICT)) 示例四:: 有时你可能需要匹配的参数是可选的,你可以这样注册 url=rf.e("fruit", **rf.union("apple", "banana", "orange")).url 上面的注册只会对三条路径进行匹配,使用union方法创造可选匹配串,通过**的方式传递给实体方法 /fruit/apple,/fruit/banana,/fruit/orange """ LOOSE = 0 STRICT = 1 IGNORE = 2 def __init__(self, init_entity=None): self.entity = [] self.eof = r"(?:/({}*))?" self.chain = r"/({}+)" if init_entity: for ie in init_entity: if isinstance(ie, str): self.e(ie) elif isinstance(ie, tuple): self.e(*ie)
[文档] @staticmethod def union(*args): """ 返回一个用于shape参数的匹配字符串,代表该内容类型为可选内容,可选范围为传入的内容 :param args: 可选项的列表 :return: 用于shape参数的匹配字符串 """ return {"shape": "|".join(args), "union": True}
[文档] def e(self, name, shape=r"[^\\/]", union=False): """ URL中增加一个实体,实体是有前缀的,前缀名等于name :param name: 实体前缀名称 :param shape: 匹配类型 :param union: 类型是否为可选匹配 :return: RESTful实例对象 """ self.entity.append({ "name": "/" + name, "shape": shape, "union": union, }) return self
[文档] def s(self, name, shape=r"[^\\/]", union=False): """ URL中增加一个简易实体,实体没有前缀 :param name: 实体前缀名称,仅用于标记无实际意义 :param shape: 匹配类型 :param union: 类型是否为可选匹配 :return: RESTful实例对象 """ self.entity.append({ "name": "", "shape": shape, "union": union, }) return self
[文档] def clear(self): """ 清空注册进来的内容 :return: RESTful实例对象 """ self.entity = [] return self
@property def url(self): """ 属性方法,获取url :return: 生成的URL匹配串 """ return self.u(int(len(self.entity) == 1 and not self.entity[0]["name"]))
[文档] def u(self, need_eof=0): """ 获取url :param need_eof: 结尾字符的种类 :return: 生成的URL匹配串 """ result = "" size = len(self.entity) - 1 for idx, e in enumerate(self.entity): result += e["name"] if idx == size: if need_eof == 0: result += _url(self.eof, e["union"]).format(e["shape"]) elif need_eof == 1: result += _url(self.chain, e["union"]).format(e["shape"]) else: break else: result += _url(self.chain, e["union"]).format(e["shape"]) result += r"$" self.clear() return result
[文档]class Router: """ 如果不需要分组可以直接在Handler上面增加装饰器,如:: @register.route(version="v3") class RecpHandler(BaseHandler): ... 访问地址:http://127.0.0.1:8095/v3/recp 分组路由,如:: 实例化router对象 router=register.Router(prefix="/prefix",version="v3") @router.route() class RecpHandler(BaseHandler): ... @router.route(url="/custom") class NewRecpHandler(BaseHandler): ... 访问地址:http://127.0.0.1:8095/v3/prefix/recp 访问地址:http://127.0.0.1:8095/v3/perfix/custom :param version: restful风格版本号 :param prefix: 统一路由前缀 """ def __init__(self, version="", prefix=""): self.version = version.strip("/\\") self.prefix = prefix.strip("/\\")
[文档] @staticmethod def get_pe8(content: str): """ 将大写字母分割转换成下划线分割的形式,如AbcDef-->abc_def :param content: 转换的类名,如果带有Handler结尾将自动去除 :return: 转换后的内容 """ if content.endswith("Handler"): content = content[:-7] for i in filter(lambda x: x.isupper(), content): content = content.replace(i, "_" + i.lower()) return content.strip("_")
[文档] def route(self, url: str = None, prefix: str = "", urls: list = None, end=False): """ ``装饰器`` 添加该装饰器的请求实例,路由路径会被自动注册到路由表中 如果你并不想使用装饰器,你可以直接获取register.register_route的 路由表进行添加内容,通过装饰器注册的类是不区分顺序的,完全类导入顺序 路由具体生成顺序可以在运行程序后查看log下面的webMap.log文件 是否需要路由结尾有/和没有/匹配的地址一样,例如index/和index匹配是一样的 你可以设置url参数如/index/abc/?,这样两个匹配效果是一样的 如果你在配置文件中配置了url_prefix = [] 这是一个列表,会生成一组带前缀的静态文件路由匹配项 而我们的end=True的路由会放到这些带前缀的静态文件管理路由后面 :param url: 路由路径,不填写默认会根据类名生成路径 :param prefix: 如果提供该内容将在路由中添加一个前缀,这个前缀是在统一路由前缀后面的 :param urls: 如果设置该参数,传入一个列表对象,url将不起效果,同时为该类增加多个可匹配的路由 :param end: 声明该路由是否注册到默认路由后面,系统默认路由参考server.py中的default_route :return: None """ global register_route prefix = prefix.strip("/\\") def add_route(func): if urls: routes = map(lambda x: x.lstrip("/\\"), urls) elif url: routes = [url.lstrip("/\\")] else: routes = [self.get_pe8(func.__name__)] path = "/".join(filter(lambda x: x, [self.version, self.prefix, prefix])) path = "/" + path if path else "" for r in routes: if end: end_register_route.append(("{}/{}".format(path, r), func)) else: register_route.append(("{}/{}".format(path, r), func)) return func return add_route
route = Router().route rf = RESTful()