主要是配置文件读写和ioc,还有一些工具代码,用pip安装
库结构如下:
buildz.xf
类json格式文件/字符串的读写,和json的区别:大部分情况下不用写引号(讨厌写引号),可以写注释(#,//,/**/),"="和":"等价,"[]"和"()"等价,引号可以写单引号’,双引号",三重引号("""和''',和python一样),引号前面可以加r(和python一样):r"D:\test",最外面可以不用写括号(花括号或中括号),换行"\n"等于逗号","等于分号";",写起来比json方便,但格式错误后,报错内容不详细,要自己找格式错误
示例:
from buildz import xf
s = r"""
a=0,b:1
c=2.3,
d=[a,b,c,d,e,f,g,,,]
e=1e10
f:0.1e-10
g : haha
//加点注释
h = "test\n"
#或者注释
i=r"test\n"
/*
愉快的注释
*/
j={
0=1
2:[(-),(v),(-)]
}
//代码实现原因,括号前没有逗号的数据,会被放到括号里当作列表的第一个元素
//等价于val=[fc,0,1,2,3]
val = fc(0,1,2,3)
来点中文:{
"some english":[
A B C D E F G
]
}
"""
data = xf.loads(s)
print(data)
#打印结果:
#{'a': 0, 'b': 1, 'c': 2.3, 'd': ['a', 'b', 'c', 'd', 'e', 'f', 'g', '', ''], 'e': 10000000000.0, 'f': 1e-11, 'g': 'haha', 'h': 'test\n', 'i': 'test\\n', 'j': {0: 1, 2: [['-'], ['v'], ['-']]}, 'val': ['fc', 0, 1, 2, 3], '来点中文': {'some english': ['A B C D E F G']}}
rs = xf.dumps(data, format=False)
print(rs)
#{a: 0, b: 1, c: 2.3, d: [a, b, c, d, e, f, g, "", ""], e: 10000000000.0, f: 1e-11, g: haha, h: "test\n", i: test\n, j: {0: 1, 2: [[-], [v], [-]]}, val: [fc, 0, 1, 2, 3], 来点中文: {"some english": ["A B C D E F G"]}}
rs = xf.dumps(data, format=True)
print(rs)
#太长可以自己试试
buildz.ioc
参考的spring,可以写配置文件,也可以写@注解
示例:
创建文件test.py和test.js,可以直接拷贝代码后,运行python test.py
test.py:
#test.py
from buildz import ioc
from buildz.ioc import wrap
#两工具模块
from buildz import fz,pyz
@wrap.obj(id="objA")
@wrap.obj_args("val, 123", "ref, objB")
@wrap.obj_set(objC = "ref, objC")
@wrap.obj_set(objD="ref, objD", objE="ref, objE")
class Test:
def __init__(self, val, obj):
self.val = val
self.obj = obj
def show(self):
print(self.__dict__)
pass
def test():
mg = ioc.build()
fps = fz.search(".", ".*\.js")
mg.add_fps(fps)
obj = mg.get("objA")
obj.show()
pass
#和if __name__=="__main__":test()等价:
pyz.lc(locals(), test)
"""
python test.py
运行结果:
{'val': 123, 'obj': <test.Test object at 0x000002B6EF9AF190>, 'objD': <test.Test object at 0x000002B6EF9BD4D0>, 'objE': <test.Test object at 0x000002B6EF9BD8D0>, 'objC': <test.Test object at 0x000002B6EF9BDA10>}
"""
test.js:
// test.js(为了用编辑器展示的默认高亮,建议用js后缀)
{
id: objB
type: obj
src: test.Test
args: [123, null]
}
{
id: objC
type: obj
src: test.Test
args: [123, null]
}
{
id: objD
type: obj
src: test.Test
args: [123, [ref, objC]]
}
{
id: objE
type: obj
src: test.Test
args: [123, [ref, objD]]
}
buildz.pyz
和python系统相关比较大的
from buildz import pyz
# 是否是windows系统,True/False
pyz.is_windows
#对__import__的封装,返回test.Test类
pyz.load("test.Test")
#当前文件目录的上一个目录加入sys.path
pyz.add(__file__,2) #1是当前目录,3是上上个目录
#python的site-packages文件夹位置
pyz.pth()
#在site-packages下创建test.pth(如果不存在),把路径写进去(为了其他地方做import)
pyz.Pth("test.pth").add("/a/b/c")
#等价于
"""
if __name__=="__main__":
fc()
"""
pyz.lc(locals(), fc)
buildz.fz
文件相关的工具代码,后续补充
buildz.db
数据库脚本执行,目前支持mysql,oracle和clickhouse(要自己pip下其他库,见说明),示例待补充
buildz.html
html页面读取和结构化,以及查找功能
用buildz.html.parse(string)把字符串转成结构化数据,然后可以用searchs和finds进行查找,返回的是一个Python对象Result,
可以对Result调用data()获取对象列表,或者text()等获取内容列表
finds和searchs的功能是一样的,只是finds传入的是一个字符串,会转成map来查询,searchs传入的是多个字符串,会转成列表
查询key取值: tag, attrs.属性, text, $
$表示后面是一个python表达式
示例
在本页面获取目录标题:
from buildz import html
import requests as rq
url = "https://blog.youkuaiyun.com/u012332001/article/details/142501903"
rp = rq.get(url,headers={"Host":"blog.youkuaiyun.com","User-Agent":"Mozilla/5.0"})
s=rp.text
data = html.parse(s)
rst = data.finds("tag=article,attrs.class=baidu_pl").finds("tag=h2").text()
print(rst)
rst = data.searchs("tag,article","attrs.class,baidu_pl").searchs("tag,h2").text()
print(rst)
rst = data.finds("tag=article,attrs.class=baidu_pl").searchs("tag,h2").text()
print(rst)
rst = data.finds("tag=article,$='attrs[\"class\"]==\"baidu_pl\"'").searchs("$,'tag==\"h2\"'").text()
print(rst)
#输出都是:
#['buildz.xf', 'buildz.ioc', 'buildz.pyz', 'buildz.fz', 'buildz.db', 'buildz.html', 'buildz.auto', '其他模块描述待补充']
buildz.auto
自动化测试,通过写配置文件,让自动化更简单
简单的例子(运行调用第一个接口就会报错结束,因为url和数据都是乱写的)
代码结构:
codes/
test.py
res/
cache/
cache.js
items/
create.js
login.js
start.js
config.js
datas.js
codes/test.py:
# codes/test.py
from buildz.tools import *
from buildz.auto import Run
def test():
# 路径可以写具体文件,如../res/datas.js,
# 也可以简化写,如../res/datas
# 程序在找不到文件的时候会查找所有匹配得上文件名的文件,如果找到的只有一个文件,也能成功运行
rst = Run()("../res/datas")
print(rst)
pass
pyz.lc(locals(), test)
res/datas.js
// res/datas.js
//配置文件路径,可以是一个文件路径,也可以是一个列表,里面有多个文件路径
configs: config.js
datas: [
// 登录网站
items/login.js
// 创建活动
items/create.js
// 启动活动
items/start.js
]
config.js
// res/config.js
// 要执行的组件,写的是ioc的id,可以自己实现组件,但要实现方法call(maps:dict, fp:string)
// 自动化执行,会依次执行calls里的组件
calls: [
log, //日志配置
cache, //从文件里读取缓存
dbs, //从配置里获取数据库连接
def.deal.type, //从def.deal读取deal配置
list, // 读取datas列表里的数据,并调用deal(自动化步骤主要配置在datas里)
cache.save // 保存缓存到配置文件里
]
//从哪些配置文件读取缓存
cache: [cache/cache.js,cache/save.js]
//往哪个文件里存放缓存
cache.save: cache/save.js
// 日志记录的文件名,可以用python time模块里的日期格式
log: log/%Y%m%d_log.txt
// 要打印的日志类型
log.shows: [info, warn, debug, error]
// 定义deal的处理,写好一个根据type寻找实际deal并执行的预设组件(ioc.id=def.deal.type),可以用,也可以自己实现其他的
def.deal: {
types: {
// 会按列表里顺序执行,前提是列表前一个组件执行成功
get: [defs, request.get, verify, save]
post: [defs, request.json, verify, save]
list: [defs, deal.list]
}
}
res/cache/cache.js
// res/cache/cache.js
user=123
pwd=123
host="127.0.0.1"
res/items/login.js
// res/items/login.js
//这里只是示例,url都是无效的
note: 用户登录
defs: {
$pwd: "#{pwd}"
}
//默认从缓存里读取变量的变量格式:#{变量名}
url: "https://#{host}/login"
type: post
data: {
user: "#{user}"
pwd: $pwd
}
//调用后做哪些验证
verify: [
//调用成功(http状态=200)
"result_status, 200"
//返回的数据解析后,success字段等于1(json解析后会存在result字段中)
"result.success,1"
]
save.mem: {
// 假设登录后通过cookie存放登录状态,将其存入内存缓存
cookie.uid: result_cookies.uid
}
res/items/create.js
// res/items/create.js
//这里只是示例,url都是无效的
note: 创建任务
// 定义局部变量(当前生效),方便写配置,非必须
defs: {
$pwd: "#{pwd}"
}
url: "https://#{host}/task/create"
type: post
//发送http请求时的cookie
cookies: {
uid: "#{cookie.uid}"
}
data: {
taskName: 测试任务
taskType: random
repeat: "1 week"
}
//调用后做哪些验证
verify: [
//调用成功(http状态=200)
"result_status, 200"
//返回的数据解析后,success字段等于1(json解析后会存在result字段中)
"result.success,1"
]
//存缓存文件
save.file: {
// 返回的task字段的id存入缓存
task.id: result.task.id
// 上传字段的taskName存入缓存
task.name: data.taskName
}
res/items/start.js
// res/items/start.js
//这里只是示例,url都是无效的
note: 启动任务
url: "https://#{host}/start"
type: post
cookies: {
uid: "#{cookie.uid}"
}
data: {
taskId: "#{task.id}"
}
//调用后做哪些验证
verify: [
//调用成功(http状态=200)
"result_status, 200"
//返回的数据解析后,success字段等于1(json解析后会存在result字段中)
"result.success,1"
]
运行:
python test.js
运行结果:
codes/log/20241009_log.txt
[INFO] 2024-10-09 00:45:33 load cache from D:\rootz\python\lx\pyz\projs\tests\auto\res\cache/cache.js
[INFO] 2024-10-09 00:47:15 load cache from D:\rootz\python\lx\pyz\projs\tests\auto\res\cache/cache.js
[ERROR] 2024-10-09 00:47:17 error in request 'https://127.0.0.1/login' with method json: HTTPSConnectionPool(host='127.0.0.1', port=443): Max retries exceeded with url: /login (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x00000263B6634990>: Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接。'))