Name | atomic-bomb-engine JSON |
Version |
0.39.0
JSON |
| download |
home_page | None |
Summary | 使用rust开发的高性能python压测工具 |
upload_time | 2024-05-15 09:26:16 |
maintainer | None |
docs_url | None |
author | None |
requires_python | None |
license | MIT |
keywords |
rust
python
binding
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# atomic-bomb-engine-py
#### [atomic-bomb-engine](https://github.com/we-lsp/atomic-bomb-engine)的python包装实现
<img src="img/atomic-bomb-engine-logo.png" width="350px" height="350px" alt="logo">
## 前端仓库
#### [atomic-bomb-engine-front](https://github.com/GiantAxeWhy/atomic-bomb-engine-front)
## 使用条件:
- python版本 >= 3.8
- windows(x86), linux(x86), mac
## 使用方法:
- ### 准备开始
通过pip安装 (0.5.0版本之前)
```shell
pip install atomic-bomb-engine-py
```
在python中引用时注意,需要引用atomic_bomb_engine, 而不是atomic_bomb_engine_py
<br/> 为了避免混淆,0.5.0版本之后,pip更换了包名,更改为atomic-bomb-engine,
```shell
pip install atomic-bomb-engine
```
在python中导入
```python
import atomic_bomb_engine
```
异步使用的时候,还需要引用asyncio
```python
import asyncio
```
- ### 开始压测
- ~~单接口压测~~ (功能与多接口压测重叠,已废除)
- 多接口压测
多接口压测可以先使用
```python
runner = atomic_bomb_engine.BatchRunner()
```
实例化一个runner类
通过runner类中的run方法开启压测
run方法函数签名如下
```python
def run(
self,
test_duration_secs: int,
concurrent_requests: int,
api_endpoints:List[Dict],
step_option:Dict[str, int]|None=None,
setup_options:List[Dict[str, Any]]|None=None,
verbose:bool=False,
should_prevent:bool=False,
assert_channel_buffer_size:int=1024,
timeout_secs=0,
cookie_store_enable=True
) -> None:
"""
批量压测
:param test_duration_secs: 测试持续时间
:param concurrent_requests: 并发数
:param api_endpoints: 接口信息
:param step_option: 阶梯加压选项
:param setup_options: 初始化选项
:param verbose: 打印详细信息
:param should_prevent: 是否禁用睡眠
:param assert_channel_buffer_size: 断言队列buffer大小
:param timeout_secs: http超时时间
:param cookie_store_enable: 是否为客户端启用持久性cookie存储。
"""
```
使用assert_option方法可以返回断言选项字典
```python
assert_options=[
atomic_bomb_engine.assert_option("$.code", 429),
atomic_bomb_engine.assert_option("$.code", 200)
])
```
jsonpath如果不会用的话,建议去[jsonpath](https://jsonpath.com/)学习
使用step_option方法可以返回阶梯加压选项字典
```python
def step_option(increase_step: int, increase_interval: int) -> Dict[str, int]:
"""
生成step option
:param increase_step: 阶梯步长
:param increase_interval: 阶梯间隔
"""
```
同样的本包中也包含了一个对api_endpoint的包装:endpoint方法,方便调用,endpoint中的assert_options中也可以套用assert_option方法
```python
async def run_batch():
result = await atomic_bomb_engine.batch_async(
# 测试持续时间
test_duration_secs=60,
# 并发量
concurrent_requests=200,
# 阶梯设置(每5秒增加30个并发)
step_option=atomic_bomb_engine.step_option(increase_step=30, increase_interval=5),
# 接口超时时间
timeout_secs=10,
# 是否开启客户端启用持久性cookie存储
cookie_store_enable=True,
# 全局初始化
setup_options=[
atomic_bomb_engine.setup_option(
name="初始化-1",
url="http://localhost:8080/setup",
method="get",
jsonpath_extract=[
atomic_bomb_engine.jsonpath_extract_option(key="test-msg", jsonpath="$.msg"),
atomic_bomb_engine.jsonpath_extract_option(key="test-code", jsonpath="$.code"),
]
)],
# 是否开启详细日志
verbose=False,
# 被压接口设置
api_endpoints=[
atomic_bomb_engine.endpoint(
# 接口任务命名
name="test-1",
# 针对每个接口初始化
setup_options=[
atomic_bomb_engine.setup_option(
name="api-初始化-1",
url="http://localhost:8080/api_setup",
method="get",
jsonpath_extract=[
atomic_bomb_engine.jsonpath_extract_option(key="api-test-msg-1", jsonpath="$.msg"),
atomic_bomb_engine.jsonpath_extract_option(key="api-test-code-1", jsonpath="$.code"),
]
)
],
# 被压接口url
url="http://localhost:8080/direct",
# 请求方式
method="POST",
# 权重
weight=1,
# 发送json请求
json={"name": "{{api-test-msg-1}}", "number": 1},
# 断言选项
assert_options=[
atomic_bomb_engine.assert_option(jsonpath="$.number", reference_object=1),
],
# 思考时间选项(在最大和最小之间随机,单位毫秒)
think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),
),
])
print(result)
return result
```
监听时可以在使用完run方法后,继续迭代runner即可
压测+同时监听
```python
import asyncio
async def batch_async():
runner = atomic_bomb_engine.BatchRunner()
runner.run(
test_duration_secs=30,
concurrent_requests=30,
step_option=atomic_bomb_engine.step_option(increase_step=3, increase_interval=3),
timeout_secs=15,
cookie_store_enable=True,
verbose=False,
api_endpoints=[
atomic_bomb_engine.endpoint(
name="test-1",
url="http://127.0.0.1:8080/direct",
method="POST",
json={"name": "test-1", "number": 1},
weight=100,
assert_options=[
atomic_bomb_engine.assert_option(jsonpath="$.msg", reference_object="操作成功"),
],
),
])
return runner
async def main():
results = await batch_async()
for res in results:
if res.get("should_wait"):
await asyncio.sleep(0.1)
print(res)
if __name__ == '__main__':
asyncio.run(main())
```
# 压测时使用ui界面监控
0.5.0版本后,添加了ui页面,支持批量压测方法
<br/>导入
```python
from atomic_bomb_engine import server
```
使用
```python
import asyncio
import atomic_bomb_engine
from atomic_bomb_engine import server
@server.ui(port=8000)
async def batch_async():
runner = atomic_bomb_engine.BatchRunner()
runner.run(
# 测试持续时间
test_duration_secs=60,
# 并发量
concurrent_requests=200,
# 阶梯设置(每5秒增加30个并发)
step_option=atomic_bomb_engine.step_option(increase_step=30, increase_interval=5),
# 接口超时时间
timeout_secs=10,
# 是否开启客户端启用持久性cookie存储
cookie_store_enable=True,
# 全局初始化
setup_options=[
atomic_bomb_engine.setup_option(
name="初始化-1",
url="http://localhost:8080/setup",
method="get",
jsonpath_extract=[
atomic_bomb_engine.jsonpath_extract_option(key="test-msg", jsonpath="$.msg"),
atomic_bomb_engine.jsonpath_extract_option(key="test-code", jsonpath="$.code"),
]
)],
# 是否开启详细日志
verbose=False,
# 被压接口设置
api_endpoints=[
atomic_bomb_engine.endpoint(
# 接口任务命名
name="test-1",
# 针对每个接口初始化
setup_options=[
atomic_bomb_engine.setup_option(
name="api-初始化-1",
url="http://localhost:8080/api_setup",
method="get",
jsonpath_extract=[
atomic_bomb_engine.jsonpath_extract_option(key="api-test-msg-1", jsonpath="$.msg"),
atomic_bomb_engine.jsonpath_extract_option(key="api-test-code-1", jsonpath="$.code"),
]
)
],
# 被压接口url
url="http://localhost:8080/direct",
# 请求方式
method="POST",
# 权重
weight=1,
# 发送json请求
json={"name": "{{api-test-msg-1}}", "number": 1},
# 断言选项
assert_options=[
atomic_bomb_engine.assert_option(jsonpath="$.number", reference_object=1),
],
# 思考时间选项(在最大和最小之间随机,单位毫秒)
think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),
),
])
return runner
if __name__ == '__main__':
asyncio.run(batch_async())
```
使用server.ui装饰器,可以给批量压测方法启动一个简单的web服务器,不需要再手动监听BatchListenIter生成器
## 内部架构图
![architecture.png](img/architecture.png)
## [0.19.0] - 2024-04-16
### Added
- 增加了初始化和参数模版功能
```python
setup_options=[
atomic_bomb_engine.setup_option(
name="初始化-1",
url="http://localhost:8080/setup",
method="get",
jsonpath_extract=[
atomic_bomb_engine.jsonpath_extract_option(key="test-msg", jsonpath="$.msg"),
atomic_bomb_engine.jsonpath_extract_option(key="test-code", jsonpath="$.code"),
]
)]
```
上述实例展示了如何在初始化的时候调用某个接口,并且通过jsonpath将数据提取出来,保存在全局变量test-msg和test-code中
提取完全局变量后,就可以在后续的api_endpoints中使用
```python
api_endpoints=[
atomic_bomb_engine.endpoint(
# 接口任务命名
name="test-1",
# 针对每个接口初始化
setup_options=[
atomic_bomb_engine.setup_option(
name="api-初始化-1",
url="http://localhost:8080/api_setup",
method="get",
jsonpath_extract=[
atomic_bomb_engine.jsonpath_extract_option(key="api-test-msg-1", jsonpath="$.msg"),
atomic_bomb_engine.jsonpath_extract_option(key="api-test-code-1", jsonpath="$.code"),
]
)
],
# 被压接口url
url="http://localhost:8080/direct",
# 请求方式
method="POST",
# 权重
weight=1,
# 发送json请求
json={"name": "{{api-test-msg-1}}", "number": 1},
# 断言选项
assert_options=[
atomic_bomb_engine.assert_option(jsonpath="$.number", reference_object=1),
],
# 思考时间选项(在最大和最小之间随机,单位毫秒)
think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),
),
]
```
上述实例展示了如何在请求中使用全局变量,使用双大括号即可使用
### Fixed
- 修复了如果http状态码错误时,不会记录
- 修复了json反序列化的问题
## [0.20.0] - 2024-04-17
### Added
断言更改为异步生产消费,提升性能
## bug和需求
- 如果发现了bug,把复现步骤一起写到Issus中哈
- 如果有需求也可以在Issues中讨论
- 本程序是本人业余时间开发,不太准备保证时效性,但是如果有时间,一定第一时间回复和修改bug
## [0.22.0] - 2024-04-18
### Added
前端进行了性能优化
## [0.24.0] - 2024-04-22
### Added
异步断言使用了补偿消息,保证消息的一致性
## [0.25.0] - 2024-04-23
### Added
在endpoints中增加思考时间,模拟用户行为
```python
think_time_option(min_millis=200, max_millis=300)
```
- min_millis:最小思考时间(毫秒)
- max_millis:最大思考时间(毫秒)
使用时在endpoint中增加think_time_option参数
```python
api_endpoints=[
atomic_bomb_engine.endpoint(
name="test-1",
url="http://localhost:8080/a",
method="POST",
weight=1,
timeout_secs=10,
json={"name": "{{test-msg}}", "number": "{{test-code}}"},
think_time_option=atomic_bomb_engine.think_time_option(min_millis=200, max_millis=300),
),
]
```
## [0.26.0] - 2024-04-24
### Added
- 增加endpoint中的setup,在并发中可以做接口断言
- 增加有关联条件下的cookie自动管理功能
```python
atomic_bomb_engine.endpoint(
# 接口任务命名
name="test-1",
# 针对每个接口初始化
setup_options=[
atomic_bomb_engine.setup_option(
name="api-初始化-1",
url="http://localhost:8080/api_setup",
method="get",
jsonpath_extract=[
atomic_bomb_engine.jsonpath_extract_option(key="api-test-msg-1", jsonpath="$.msg"),
atomic_bomb_engine.jsonpath_extract_option(key="api-test-code-1", jsonpath="$.code"),
]
)
],
# 被压接口url
url="http://localhost:8080/direct",
# 请求方式
method="POST",
# 权重
weight=1,
# 发送json请求
json={"name": "{{api-test-msg-1}}", "number": 1},
# 断言选项
assert_options=[
atomic_bomb_engine.assert_option(jsonpath="$.number", reference_object=1),
],
# 思考时间选项(在最大和最小之间随机,单位毫秒)
think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),
)
```
- 参数cookie_store_enable控制是否自动管理cookie,前置条件的cookie会带入到最终的压测接口中
- 在endpoint中使用setup_options可以传入多个接口,并且提取参数
- 提取到的参数如果和全局的setup的key冲突,会覆盖全局提取到的参数
- 接口中提取的参数只能在本线程(v-user)中使用
- ⚠️ 使用时注意:setup_options是顺序执行的,没有并发,但是相当于添加了think time
## [0.28.0] - 2024-04-25
### Added
- 将持久化cookie添加到全局选项中
- 复用http client
- 选择性开启断言任务
- 接口初始化时出现错误等待后重试##
## [0.29.0] - 2024-04-25
### Added
- 优化并发逻辑
- 前端更改为web worker发送心跳
## [0.38.0] - 2024-05-7
### Added
- 增加附件上传功能
- 在初始化和每个接口中增加了multipart_options参数用于附件上传
- 增加multipart_option方法封装附件参数
- form_key: form表单的key
- path: 附件路径
- file_name: 附件名
- mime: 附件类型 (类型可以参考[这里](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types))
```python
api_endpoints=[
atomic_bomb_engine.endpoint(
name="test-file",
url="http://127.0.0.1:8888/upload",
method="post",
weight=100,
multipart_options=[atomic_bomb_engine.multipart_option(form_key="file", path="./ui.py", file_name="ui.py", mime="text/plain")],
assert_options=[
atomic_bomb_engine.assert_option(jsonpath="$.message", reference_object="File uploaded successfully!"),
],
think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),
),]
```
## [0.39.0] - 2024-05-15
### Added
- 启用BatchRunner类,每次执行可以返回一个迭代器
- 废除run_batch方法
- 废除ResultsIter迭代器
## bug和需求
- 如果发现了bug,把复现步骤一起写到Issus中哈
- 如果有需求也可以在Issues中讨论
- 本程序是本人业余时间开发,不太准备保证时效性,但是如果有时间,一定第一时间回复和修改bug
## TODO
- [x] 前端展示页面 ✅
- [x] 接口关联 ✅
- [x] 每个接口可以配置思考时间 ✅
- [x] 增加form支持 ✅
- [ ] 增加代理支持
- [x] 增加附件支持 ✅
- [ ] 断言支持不等于等更多表达方式
## 联系方式
- 邮箱:[qyzhg@qyzhg.com](mailto:qyzhg@qyzhg.com)
- 微信:qy-zhg
## 👏🏻👏🏻👏🏻欢迎加群交流
![img.png](img/img.png)
Raw data
{
"_id": null,
"home_page": null,
"name": "atomic-bomb-engine",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "rust, python, binding",
"author": null,
"author_email": "qyzhg <qyzhg@qyzhg.com>",
"download_url": null,
"platform": null,
"description": "# atomic-bomb-engine-py\n#### [atomic-bomb-engine](https://github.com/we-lsp/atomic-bomb-engine)\u7684python\u5305\u88c5\u5b9e\u73b0\n\n<img src=\"img/atomic-bomb-engine-logo.png\" width=\"350px\" height=\"350px\" alt=\"logo\">\n\n\n## \u524d\u7aef\u4ed3\u5e93\n#### [atomic-bomb-engine-front](https://github.com/GiantAxeWhy/atomic-bomb-engine-front)\n\n## \u4f7f\u7528\u6761\u4ef6\uff1a\n- python\u7248\u672c >= 3.8\n- windows(x86), linux(x86), mac\n\n## \u4f7f\u7528\u65b9\u6cd5\uff1a\n- ### \u51c6\u5907\u5f00\u59cb\n\u901a\u8fc7pip\u5b89\u88c5 \uff080.5.0\u7248\u672c\u4e4b\u524d\uff09\n```shell\npip install atomic-bomb-engine-py\n```\n\u5728python\u4e2d\u5f15\u7528\u65f6\u6ce8\u610f\uff0c\u9700\u8981\u5f15\u7528atomic_bomb_engine, \u800c\u4e0d\u662fatomic_bomb_engine_py\n<br/> \u4e3a\u4e86\u907f\u514d\u6df7\u6dc6\uff0c0.5.0\u7248\u672c\u4e4b\u540e\uff0cpip\u66f4\u6362\u4e86\u5305\u540d\uff0c\u66f4\u6539\u4e3aatomic-bomb-engine\uff0c\n```shell\npip install atomic-bomb-engine\n```\n\u5728python\u4e2d\u5bfc\u5165\n```python\nimport atomic_bomb_engine\n```\n\u5f02\u6b65\u4f7f\u7528\u7684\u65f6\u5019\uff0c\u8fd8\u9700\u8981\u5f15\u7528asyncio\n```python\nimport asyncio\n```\n- ### \u5f00\u59cb\u538b\u6d4b\n - ~~\u5355\u63a5\u53e3\u538b\u6d4b~~ \uff08\u529f\u80fd\u4e0e\u591a\u63a5\u53e3\u538b\u6d4b\u91cd\u53e0\uff0c\u5df2\u5e9f\u9664\uff09\n\n - \u591a\u63a5\u53e3\u538b\u6d4b\n\n\u591a\u63a5\u53e3\u538b\u6d4b\u53ef\u4ee5\u5148\u4f7f\u7528\n```python \nrunner = atomic_bomb_engine.BatchRunner()\n```\n\u5b9e\u4f8b\u5316\u4e00\u4e2arunner\u7c7b\n\u901a\u8fc7runner\u7c7b\u4e2d\u7684run\u65b9\u6cd5\u5f00\u542f\u538b\u6d4b\nrun\u65b9\u6cd5\u51fd\u6570\u7b7e\u540d\u5982\u4e0b\n```python\ndef run(\n self,\n test_duration_secs: int,\n concurrent_requests: int,\n api_endpoints:List[Dict],\n step_option:Dict[str, int]|None=None,\n setup_options:List[Dict[str, Any]]|None=None,\n verbose:bool=False,\n should_prevent:bool=False,\n assert_channel_buffer_size:int=1024,\n timeout_secs=0,\n cookie_store_enable=True\n ) -> None:\n \"\"\"\n \u6279\u91cf\u538b\u6d4b\n :param test_duration_secs: \u6d4b\u8bd5\u6301\u7eed\u65f6\u95f4\n :param concurrent_requests: \u5e76\u53d1\u6570\n :param api_endpoints: \u63a5\u53e3\u4fe1\u606f\n :param step_option: \u9636\u68af\u52a0\u538b\u9009\u9879\n :param setup_options: \u521d\u59cb\u5316\u9009\u9879\n :param verbose: \u6253\u5370\u8be6\u7ec6\u4fe1\u606f\n :param should_prevent: \u662f\u5426\u7981\u7528\u7761\u7720\n :param assert_channel_buffer_size: \u65ad\u8a00\u961f\u5217buffer\u5927\u5c0f\n :param timeout_secs: http\u8d85\u65f6\u65f6\u95f4\n :param cookie_store_enable: \u662f\u5426\u4e3a\u5ba2\u6237\u7aef\u542f\u7528\u6301\u4e45\u6027cookie\u5b58\u50a8\u3002\n \"\"\"\n```\n\n\u4f7f\u7528assert_option\u65b9\u6cd5\u53ef\u4ee5\u8fd4\u56de\u65ad\u8a00\u9009\u9879\u5b57\u5178\n```python\nassert_options=[\natomic_bomb_engine.assert_option(\"$.code\", 429),\natomic_bomb_engine.assert_option(\"$.code\", 200)\n])\n```\njsonpath\u5982\u679c\u4e0d\u4f1a\u7528\u7684\u8bdd\uff0c\u5efa\u8bae\u53bb[jsonpath](https://jsonpath.com/)\u5b66\u4e60\n\n\u4f7f\u7528step_option\u65b9\u6cd5\u53ef\u4ee5\u8fd4\u56de\u9636\u68af\u52a0\u538b\u9009\u9879\u5b57\u5178\n```python\ndef step_option(increase_step: int, increase_interval: int) -> Dict[str, int]:\n \"\"\"\n \u751f\u6210step option\n :param increase_step: \u9636\u68af\u6b65\u957f\n :param increase_interval: \u9636\u68af\u95f4\u9694\n \"\"\"\n```\n\n\u540c\u6837\u7684\u672c\u5305\u4e2d\u4e5f\u5305\u542b\u4e86\u4e00\u4e2a\u5bf9api_endpoint\u7684\u5305\u88c5\uff1aendpoint\u65b9\u6cd5\uff0c\u65b9\u4fbf\u8c03\u7528\uff0cendpoint\u4e2d\u7684assert_options\u4e2d\u4e5f\u53ef\u4ee5\u5957\u7528assert_option\u65b9\u6cd5\n ```python\nasync def run_batch():\n result = await atomic_bomb_engine.batch_async(\n # \u6d4b\u8bd5\u6301\u7eed\u65f6\u95f4\n test_duration_secs=60,\n # \u5e76\u53d1\u91cf\n concurrent_requests=200,\n # \u9636\u68af\u8bbe\u7f6e\uff08\u6bcf5\u79d2\u589e\u52a030\u4e2a\u5e76\u53d1\uff09\n step_option=atomic_bomb_engine.step_option(increase_step=30, increase_interval=5),\n # \u63a5\u53e3\u8d85\u65f6\u65f6\u95f4\n timeout_secs=10,\n # \u662f\u5426\u5f00\u542f\u5ba2\u6237\u7aef\u542f\u7528\u6301\u4e45\u6027cookie\u5b58\u50a8\n cookie_store_enable=True,\n # \u5168\u5c40\u521d\u59cb\u5316\n setup_options=[\n atomic_bomb_engine.setup_option(\n name=\"\u521d\u59cb\u5316-1\",\n url=\"http://localhost:8080/setup\",\n method=\"get\",\n jsonpath_extract=[\n atomic_bomb_engine.jsonpath_extract_option(key=\"test-msg\", jsonpath=\"$.msg\"),\n atomic_bomb_engine.jsonpath_extract_option(key=\"test-code\", jsonpath=\"$.code\"),\n ]\n )],\n # \u662f\u5426\u5f00\u542f\u8be6\u7ec6\u65e5\u5fd7\n verbose=False,\n # \u88ab\u538b\u63a5\u53e3\u8bbe\u7f6e\n api_endpoints=[\n atomic_bomb_engine.endpoint(\n # \u63a5\u53e3\u4efb\u52a1\u547d\u540d\n name=\"test-1\",\n # \u9488\u5bf9\u6bcf\u4e2a\u63a5\u53e3\u521d\u59cb\u5316\n setup_options=[\n atomic_bomb_engine.setup_option(\n name=\"api-\u521d\u59cb\u5316-1\",\n url=\"http://localhost:8080/api_setup\",\n method=\"get\",\n jsonpath_extract=[\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-msg-1\", jsonpath=\"$.msg\"),\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-code-1\", jsonpath=\"$.code\"),\n ]\n )\n ],\n # \u88ab\u538b\u63a5\u53e3url\n url=\"http://localhost:8080/direct\",\n # \u8bf7\u6c42\u65b9\u5f0f\n method=\"POST\",\n # \u6743\u91cd\n weight=1,\n # \u53d1\u9001json\u8bf7\u6c42\n json={\"name\": \"{{api-test-msg-1}}\", \"number\": 1},\n # \u65ad\u8a00\u9009\u9879\n assert_options=[\n atomic_bomb_engine.assert_option(jsonpath=\"$.number\", reference_object=1),\n ],\n # \u601d\u8003\u65f6\u95f4\u9009\u9879\uff08\u5728\u6700\u5927\u548c\u6700\u5c0f\u4e4b\u95f4\u968f\u673a\uff0c\u5355\u4f4d\u6beb\u79d2\uff09\n think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),\n ),\n ])\n print(result)\n return result\n ```\n \n\u76d1\u542c\u65f6\u53ef\u4ee5\u5728\u4f7f\u7528\u5b8crun\u65b9\u6cd5\u540e\uff0c\u7ee7\u7eed\u8fed\u4ee3runner\u5373\u53ef\n\n\u538b\u6d4b+\u540c\u65f6\u76d1\u542c\n\n```python \nimport asyncio\n\n\nasync def batch_async():\n runner = atomic_bomb_engine.BatchRunner()\n runner.run(\n test_duration_secs=30,\n concurrent_requests=30,\n step_option=atomic_bomb_engine.step_option(increase_step=3, increase_interval=3),\n timeout_secs=15,\n cookie_store_enable=True,\n verbose=False,\n api_endpoints=[\n atomic_bomb_engine.endpoint(\n name=\"test-1\",\n url=\"http://127.0.0.1:8080/direct\",\n method=\"POST\",\n json={\"name\": \"test-1\", \"number\": 1},\n weight=100,\n assert_options=[\n atomic_bomb_engine.assert_option(jsonpath=\"$.msg\", reference_object=\"\u64cd\u4f5c\u6210\u529f\"),\n ],\n ),\n ])\n return runner\n\n\nasync def main():\n results = await batch_async()\n for res in results:\n if res.get(\"should_wait\"):\n await asyncio.sleep(0.1)\n print(res)\n\n\nif __name__ == '__main__':\n asyncio.run(main())\n```\n\n# \u538b\u6d4b\u65f6\u4f7f\u7528ui\u754c\u9762\u76d1\u63a7\n\n0.5.0\u7248\u672c\u540e\uff0c\u6dfb\u52a0\u4e86ui\u9875\u9762\uff0c\u652f\u6301\u6279\u91cf\u538b\u6d4b\u65b9\u6cd5\n<br/>\u5bfc\u5165\n```python\nfrom atomic_bomb_engine import server\n```\n\u4f7f\u7528\n```python\nimport asyncio\n\nimport atomic_bomb_engine\nfrom atomic_bomb_engine import server\n\n\n@server.ui(port=8000)\nasync def batch_async():\n runner = atomic_bomb_engine.BatchRunner()\n runner.run(\n # \u6d4b\u8bd5\u6301\u7eed\u65f6\u95f4\n test_duration_secs=60,\n # \u5e76\u53d1\u91cf\n concurrent_requests=200,\n # \u9636\u68af\u8bbe\u7f6e\uff08\u6bcf5\u79d2\u589e\u52a030\u4e2a\u5e76\u53d1\uff09\n step_option=atomic_bomb_engine.step_option(increase_step=30, increase_interval=5),\n # \u63a5\u53e3\u8d85\u65f6\u65f6\u95f4\n timeout_secs=10,\n # \u662f\u5426\u5f00\u542f\u5ba2\u6237\u7aef\u542f\u7528\u6301\u4e45\u6027cookie\u5b58\u50a8\n cookie_store_enable=True,\n # \u5168\u5c40\u521d\u59cb\u5316\n setup_options=[\n atomic_bomb_engine.setup_option(\n name=\"\u521d\u59cb\u5316-1\",\n url=\"http://localhost:8080/setup\",\n method=\"get\",\n jsonpath_extract=[\n atomic_bomb_engine.jsonpath_extract_option(key=\"test-msg\", jsonpath=\"$.msg\"),\n atomic_bomb_engine.jsonpath_extract_option(key=\"test-code\", jsonpath=\"$.code\"),\n ]\n )],\n # \u662f\u5426\u5f00\u542f\u8be6\u7ec6\u65e5\u5fd7\n verbose=False,\n # \u88ab\u538b\u63a5\u53e3\u8bbe\u7f6e\n api_endpoints=[\n atomic_bomb_engine.endpoint(\n # \u63a5\u53e3\u4efb\u52a1\u547d\u540d\n name=\"test-1\",\n # \u9488\u5bf9\u6bcf\u4e2a\u63a5\u53e3\u521d\u59cb\u5316\n setup_options=[\n atomic_bomb_engine.setup_option(\n name=\"api-\u521d\u59cb\u5316-1\",\n url=\"http://localhost:8080/api_setup\",\n method=\"get\",\n jsonpath_extract=[\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-msg-1\", jsonpath=\"$.msg\"),\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-code-1\", jsonpath=\"$.code\"),\n ]\n )\n ],\n # \u88ab\u538b\u63a5\u53e3url\n url=\"http://localhost:8080/direct\",\n # \u8bf7\u6c42\u65b9\u5f0f\n method=\"POST\",\n # \u6743\u91cd\n weight=1,\n # \u53d1\u9001json\u8bf7\u6c42\n json={\"name\": \"{{api-test-msg-1}}\", \"number\": 1},\n # \u65ad\u8a00\u9009\u9879\n assert_options=[\n atomic_bomb_engine.assert_option(jsonpath=\"$.number\", reference_object=1),\n ],\n # \u601d\u8003\u65f6\u95f4\u9009\u9879\uff08\u5728\u6700\u5927\u548c\u6700\u5c0f\u4e4b\u95f4\u968f\u673a\uff0c\u5355\u4f4d\u6beb\u79d2\uff09\n think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),\n ),\n ])\n return runner\n\n\nif __name__ == '__main__':\n asyncio.run(batch_async())\n```\n\n\u4f7f\u7528server.ui\u88c5\u9970\u5668\uff0c\u53ef\u4ee5\u7ed9\u6279\u91cf\u538b\u6d4b\u65b9\u6cd5\u542f\u52a8\u4e00\u4e2a\u7b80\u5355\u7684web\u670d\u52a1\u5668\uff0c\u4e0d\u9700\u8981\u518d\u624b\u52a8\u76d1\u542cBatchListenIter\u751f\u6210\u5668\n\n## \u5185\u90e8\u67b6\u6784\u56fe\n![architecture.png](img/architecture.png)\n\n## [0.19.0] - 2024-04-16\n### Added\n- \u589e\u52a0\u4e86\u521d\u59cb\u5316\u548c\u53c2\u6570\u6a21\u7248\u529f\u80fd\n```python\nsetup_options=[\n atomic_bomb_engine.setup_option(\n name=\"\u521d\u59cb\u5316-1\",\n url=\"http://localhost:8080/setup\",\n method=\"get\",\n jsonpath_extract=[\n atomic_bomb_engine.jsonpath_extract_option(key=\"test-msg\", jsonpath=\"$.msg\"),\n atomic_bomb_engine.jsonpath_extract_option(key=\"test-code\", jsonpath=\"$.code\"),\n ]\n )]\n```\n\u4e0a\u8ff0\u5b9e\u4f8b\u5c55\u793a\u4e86\u5982\u4f55\u5728\u521d\u59cb\u5316\u7684\u65f6\u5019\u8c03\u7528\u67d0\u4e2a\u63a5\u53e3\uff0c\u5e76\u4e14\u901a\u8fc7jsonpath\u5c06\u6570\u636e\u63d0\u53d6\u51fa\u6765\uff0c\u4fdd\u5b58\u5728\u5168\u5c40\u53d8\u91cftest-msg\u548ctest-code\u4e2d\n\u63d0\u53d6\u5b8c\u5168\u5c40\u53d8\u91cf\u540e\uff0c\u5c31\u53ef\u4ee5\u5728\u540e\u7eed\u7684api_endpoints\u4e2d\u4f7f\u7528\n```python\napi_endpoints=[\n atomic_bomb_engine.endpoint(\n # \u63a5\u53e3\u4efb\u52a1\u547d\u540d\n name=\"test-1\",\n # \u9488\u5bf9\u6bcf\u4e2a\u63a5\u53e3\u521d\u59cb\u5316\n setup_options=[\n atomic_bomb_engine.setup_option(\n name=\"api-\u521d\u59cb\u5316-1\",\n url=\"http://localhost:8080/api_setup\",\n method=\"get\",\n jsonpath_extract=[\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-msg-1\", jsonpath=\"$.msg\"),\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-code-1\", jsonpath=\"$.code\"),\n ]\n )\n ],\n # \u88ab\u538b\u63a5\u53e3url\n url=\"http://localhost:8080/direct\",\n # \u8bf7\u6c42\u65b9\u5f0f\n method=\"POST\",\n # \u6743\u91cd\n weight=1,\n # \u53d1\u9001json\u8bf7\u6c42\n json={\"name\": \"{{api-test-msg-1}}\", \"number\": 1},\n # \u65ad\u8a00\u9009\u9879\n assert_options=[\n atomic_bomb_engine.assert_option(jsonpath=\"$.number\", reference_object=1),\n ],\n # \u601d\u8003\u65f6\u95f4\u9009\u9879\uff08\u5728\u6700\u5927\u548c\u6700\u5c0f\u4e4b\u95f4\u968f\u673a\uff0c\u5355\u4f4d\u6beb\u79d2\uff09\n think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),\n ),\n]\n```\n\u4e0a\u8ff0\u5b9e\u4f8b\u5c55\u793a\u4e86\u5982\u4f55\u5728\u8bf7\u6c42\u4e2d\u4f7f\u7528\u5168\u5c40\u53d8\u91cf\uff0c\u4f7f\u7528\u53cc\u5927\u62ec\u53f7\u5373\u53ef\u4f7f\u7528\n\n### Fixed\n- \u4fee\u590d\u4e86\u5982\u679chttp\u72b6\u6001\u7801\u9519\u8bef\u65f6\uff0c\u4e0d\u4f1a\u8bb0\u5f55\n- \u4fee\u590d\u4e86json\u53cd\u5e8f\u5217\u5316\u7684\u95ee\u9898\n\n## [0.20.0] - 2024-04-17\n### Added\n\u65ad\u8a00\u66f4\u6539\u4e3a\u5f02\u6b65\u751f\u4ea7\u6d88\u8d39\uff0c\u63d0\u5347\u6027\u80fd\n\n## bug\u548c\u9700\u6c42\n- \u5982\u679c\u53d1\u73b0\u4e86bug\uff0c\u628a\u590d\u73b0\u6b65\u9aa4\u4e00\u8d77\u5199\u5230Issus\u4e2d\u54c8\n- \u5982\u679c\u6709\u9700\u6c42\u4e5f\u53ef\u4ee5\u5728Issues\u4e2d\u8ba8\u8bba\n- \u672c\u7a0b\u5e8f\u662f\u672c\u4eba\u4e1a\u4f59\u65f6\u95f4\u5f00\u53d1\uff0c\u4e0d\u592a\u51c6\u5907\u4fdd\u8bc1\u65f6\u6548\u6027\uff0c\u4f46\u662f\u5982\u679c\u6709\u65f6\u95f4\uff0c\u4e00\u5b9a\u7b2c\u4e00\u65f6\u95f4\u56de\u590d\u548c\u4fee\u6539bug\n\n## [0.22.0] - 2024-04-18\n### Added\n\u524d\u7aef\u8fdb\u884c\u4e86\u6027\u80fd\u4f18\u5316\n\n## [0.24.0] - 2024-04-22\n### Added\n\u5f02\u6b65\u65ad\u8a00\u4f7f\u7528\u4e86\u8865\u507f\u6d88\u606f\uff0c\u4fdd\u8bc1\u6d88\u606f\u7684\u4e00\u81f4\u6027\n\n## [0.25.0] - 2024-04-23\n### Added\n\u5728endpoints\u4e2d\u589e\u52a0\u601d\u8003\u65f6\u95f4,\u6a21\u62df\u7528\u6237\u884c\u4e3a\n```python\nthink_time_option(min_millis=200, max_millis=300)\n```\n - min_millis:\u6700\u5c0f\u601d\u8003\u65f6\u95f4(\u6beb\u79d2)\n - max_millis:\u6700\u5927\u601d\u8003\u65f6\u95f4(\u6beb\u79d2)\n\n\u4f7f\u7528\u65f6\u5728endpoint\u4e2d\u589e\u52a0think_time_option\u53c2\u6570\n\n```python\napi_endpoints=[\n atomic_bomb_engine.endpoint(\n name=\"test-1\",\n url=\"http://localhost:8080/a\",\n method=\"POST\",\n weight=1,\n timeout_secs=10,\n json={\"name\": \"{{test-msg}}\", \"number\": \"{{test-code}}\"},\n think_time_option=atomic_bomb_engine.think_time_option(min_millis=200, max_millis=300),\n ),\n]\n```\n\n## [0.26.0] - 2024-04-24\n### Added\n- \u589e\u52a0endpoint\u4e2d\u7684setup\uff0c\u5728\u5e76\u53d1\u4e2d\u53ef\u4ee5\u505a\u63a5\u53e3\u65ad\u8a00\n- \u589e\u52a0\u6709\u5173\u8054\u6761\u4ef6\u4e0b\u7684cookie\u81ea\u52a8\u7ba1\u7406\u529f\u80fd\n```python\natomic_bomb_engine.endpoint(\n # \u63a5\u53e3\u4efb\u52a1\u547d\u540d\n name=\"test-1\",\n # \u9488\u5bf9\u6bcf\u4e2a\u63a5\u53e3\u521d\u59cb\u5316\n setup_options=[\n atomic_bomb_engine.setup_option(\n name=\"api-\u521d\u59cb\u5316-1\",\n url=\"http://localhost:8080/api_setup\",\n method=\"get\",\n jsonpath_extract=[\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-msg-1\", jsonpath=\"$.msg\"),\n atomic_bomb_engine.jsonpath_extract_option(key=\"api-test-code-1\", jsonpath=\"$.code\"),\n ]\n )\n ],\n # \u88ab\u538b\u63a5\u53e3url\n url=\"http://localhost:8080/direct\",\n # \u8bf7\u6c42\u65b9\u5f0f\n method=\"POST\",\n # \u6743\u91cd\n weight=1,\n # \u53d1\u9001json\u8bf7\u6c42\n json={\"name\": \"{{api-test-msg-1}}\", \"number\": 1},\n # \u65ad\u8a00\u9009\u9879\n assert_options=[\n atomic_bomb_engine.assert_option(jsonpath=\"$.number\", reference_object=1),\n ],\n # \u601d\u8003\u65f6\u95f4\u9009\u9879\uff08\u5728\u6700\u5927\u548c\u6700\u5c0f\u4e4b\u95f4\u968f\u673a\uff0c\u5355\u4f4d\u6beb\u79d2\uff09\n think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),\n)\n```\n- \u53c2\u6570cookie_store_enable\u63a7\u5236\u662f\u5426\u81ea\u52a8\u7ba1\u7406cookie\uff0c\u524d\u7f6e\u6761\u4ef6\u7684cookie\u4f1a\u5e26\u5165\u5230\u6700\u7ec8\u7684\u538b\u6d4b\u63a5\u53e3\u4e2d\n- \u5728endpoint\u4e2d\u4f7f\u7528setup_options\u53ef\u4ee5\u4f20\u5165\u591a\u4e2a\u63a5\u53e3\uff0c\u5e76\u4e14\u63d0\u53d6\u53c2\u6570\n- \u63d0\u53d6\u5230\u7684\u53c2\u6570\u5982\u679c\u548c\u5168\u5c40\u7684setup\u7684key\u51b2\u7a81\uff0c\u4f1a\u8986\u76d6\u5168\u5c40\u63d0\u53d6\u5230\u7684\u53c2\u6570\n- \u63a5\u53e3\u4e2d\u63d0\u53d6\u7684\u53c2\u6570\u53ea\u80fd\u5728\u672c\u7ebf\u7a0b\uff08v-user\uff09\u4e2d\u4f7f\u7528\n- \u26a0\ufe0f \u4f7f\u7528\u65f6\u6ce8\u610f:setup_options\u662f\u987a\u5e8f\u6267\u884c\u7684\uff0c\u6ca1\u6709\u5e76\u53d1\uff0c\u4f46\u662f\u76f8\u5f53\u4e8e\u6dfb\u52a0\u4e86think time\n\n## [0.28.0] - 2024-04-25\n### Added\n- \u5c06\u6301\u4e45\u5316cookie\u6dfb\u52a0\u5230\u5168\u5c40\u9009\u9879\u4e2d\n- \u590d\u7528http client\n- \u9009\u62e9\u6027\u5f00\u542f\u65ad\u8a00\u4efb\u52a1\n- \u63a5\u53e3\u521d\u59cb\u5316\u65f6\u51fa\u73b0\u9519\u8bef\u7b49\u5f85\u540e\u91cd\u8bd5##\n\n## [0.29.0] - 2024-04-25\n### Added\n- \u4f18\u5316\u5e76\u53d1\u903b\u8f91\n- \u524d\u7aef\u66f4\u6539\u4e3aweb worker\u53d1\u9001\u5fc3\u8df3\n\n## [0.38.0] - 2024-05-7\n### Added\n- \u589e\u52a0\u9644\u4ef6\u4e0a\u4f20\u529f\u80fd\n - \u5728\u521d\u59cb\u5316\u548c\u6bcf\u4e2a\u63a5\u53e3\u4e2d\u589e\u52a0\u4e86multipart_options\u53c2\u6570\u7528\u4e8e\u9644\u4ef6\u4e0a\u4f20\n - \u589e\u52a0multipart_option\u65b9\u6cd5\u5c01\u88c5\u9644\u4ef6\u53c2\u6570\n - form_key: form\u8868\u5355\u7684key\n - path: \u9644\u4ef6\u8def\u5f84\n - file_name: \u9644\u4ef6\u540d\n - mime: \u9644\u4ef6\u7c7b\u578b (\u7c7b\u578b\u53ef\u4ee5\u53c2\u8003[\u8fd9\u91cc](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types))\n```python\napi_endpoints=[\n atomic_bomb_engine.endpoint(\n name=\"test-file\",\n url=\"http://127.0.0.1:8888/upload\",\n method=\"post\",\n weight=100,\n multipart_options=[atomic_bomb_engine.multipart_option(form_key=\"file\", path=\"./ui.py\", file_name=\"ui.py\", mime=\"text/plain\")],\n assert_options=[\n atomic_bomb_engine.assert_option(jsonpath=\"$.message\", reference_object=\"File uploaded successfully!\"),\n ],\n think_time_option=atomic_bomb_engine.think_time_option(min_millis=500, max_millis=1200),\n ),]\n```\n\n## [0.39.0] - 2024-05-15\n### Added\n- \u542f\u7528BatchRunner\u7c7b\uff0c\u6bcf\u6b21\u6267\u884c\u53ef\u4ee5\u8fd4\u56de\u4e00\u4e2a\u8fed\u4ee3\u5668\n- \u5e9f\u9664run_batch\u65b9\u6cd5\n- \u5e9f\u9664ResultsIter\u8fed\u4ee3\u5668\n\n## bug\u548c\u9700\u6c42\n- \u5982\u679c\u53d1\u73b0\u4e86bug\uff0c\u628a\u590d\u73b0\u6b65\u9aa4\u4e00\u8d77\u5199\u5230Issus\u4e2d\u54c8\n- \u5982\u679c\u6709\u9700\u6c42\u4e5f\u53ef\u4ee5\u5728Issues\u4e2d\u8ba8\u8bba\n- \u672c\u7a0b\u5e8f\u662f\u672c\u4eba\u4e1a\u4f59\u65f6\u95f4\u5f00\u53d1\uff0c\u4e0d\u592a\u51c6\u5907\u4fdd\u8bc1\u65f6\u6548\u6027\uff0c\u4f46\u662f\u5982\u679c\u6709\u65f6\u95f4\uff0c\u4e00\u5b9a\u7b2c\u4e00\u65f6\u95f4\u56de\u590d\u548c\u4fee\u6539bug\n\n## TODO\n- [x] \u524d\u7aef\u5c55\u793a\u9875\u9762 \u2705\n- [x] \u63a5\u53e3\u5173\u8054 \u2705\n- [x] \u6bcf\u4e2a\u63a5\u53e3\u53ef\u4ee5\u914d\u7f6e\u601d\u8003\u65f6\u95f4 \u2705\n- [x] \u589e\u52a0form\u652f\u6301 \u2705\n- [ ] \u589e\u52a0\u4ee3\u7406\u652f\u6301\n- [x] \u589e\u52a0\u9644\u4ef6\u652f\u6301 \u2705\n- [ ] \u65ad\u8a00\u652f\u6301\u4e0d\u7b49\u4e8e\u7b49\u66f4\u591a\u8868\u8fbe\u65b9\u5f0f\n\n## \u8054\u7cfb\u65b9\u5f0f\n- \u90ae\u7bb1:[qyzhg@qyzhg.com](mailto:qyzhg@qyzhg.com)\n- \u5fae\u4fe1:qy-zhg\n\n## \ud83d\udc4f\ud83c\udffb\ud83d\udc4f\ud83c\udffb\ud83d\udc4f\ud83c\udffb\u6b22\u8fce\u52a0\u7fa4\u4ea4\u6d41\n![img.png](img/img.png)\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "\u4f7f\u7528rust\u5f00\u53d1\u7684\u9ad8\u6027\u80fdpython\u538b\u6d4b\u5de5\u5177",
"version": "0.39.0",
"project_urls": null,
"split_keywords": [
"rust",
" python",
" binding"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "6f85c905e93a0af37b494aa8c1c8bad76b70f40ff10ef24e67cc6a0cb4b5a861",
"md5": "4551caa8295e2c68d2756d2a192d793d",
"sha256": "6e1ee6a0800e789b049b519bc6351e152ad49748621fac96aff91b81a97cb56e"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp310-cp310-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "4551caa8295e2c68d2756d2a192d793d",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": null,
"size": 3776089,
"upload_time": "2024-05-15T09:26:16",
"upload_time_iso_8601": "2024-05-15T09:26:16.895474Z",
"url": "https://files.pythonhosted.org/packages/6f/85/c905e93a0af37b494aa8c1c8bad76b70f40ff10ef24e67cc6a0cb4b5a861/atomic_bomb_engine-0.39.0-cp310-cp310-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9f375cf3c0207744170bf2af67f0ff36c240c796849b02e4f73a86b8fa34c392",
"md5": "368d74bc18a24e5c136ac146a30a8269",
"sha256": "97aa509d8a6693a26bfceb694a35e547cef59f57e10107c34388befdb4b6a732"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp310-cp310-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "368d74bc18a24e5c136ac146a30a8269",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": null,
"size": 3707258,
"upload_time": "2024-05-15T09:22:44",
"upload_time_iso_8601": "2024-05-15T09:22:44.937846Z",
"url": "https://files.pythonhosted.org/packages/9f/37/5cf3c0207744170bf2af67f0ff36c240c796849b02e4f73a86b8fa34c392/atomic_bomb_engine-0.39.0-cp310-cp310-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f90d04a82427a0df97cd5a9324046149f02bf6a9920e9fdb4b2edc193bf2a2c9",
"md5": "2523837aea1cb680ad5b26d987a4e0b4",
"sha256": "4fb12d29b6b9ee4e5042f7b9532d117baf8d044c7354e40aebbbf991c19a3249"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp310-cp310-manylinux_2_34_x86_64.whl",
"has_sig": false,
"md5_digest": "2523837aea1cb680ad5b26d987a4e0b4",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": null,
"size": 6115500,
"upload_time": "2024-05-15T09:20:03",
"upload_time_iso_8601": "2024-05-15T09:20:03.117212Z",
"url": "https://files.pythonhosted.org/packages/f9/0d/04a82427a0df97cd5a9324046149f02bf6a9920e9fdb4b2edc193bf2a2c9/atomic_bomb_engine-0.39.0-cp310-cp310-manylinux_2_34_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "889792fbd059690e2cc47ae1c61d5384d2f23996e1b3bbf175b6cebf7dfb0dcb",
"md5": "29aab98a52a0f476f041f4847d138595",
"sha256": "e03b9bdfdd180692e0be6dd1db25587307953bb880201036ea23a461075ba04e"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp310-cp310-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "29aab98a52a0f476f041f4847d138595",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": null,
"size": 4507650,
"upload_time": "2024-05-15T09:23:53",
"upload_time_iso_8601": "2024-05-15T09:23:53.783309Z",
"url": "https://files.pythonhosted.org/packages/88/97/92fbd059690e2cc47ae1c61d5384d2f23996e1b3bbf175b6cebf7dfb0dcb/atomic_bomb_engine-0.39.0-cp310-cp310-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d8a2b656e5ed0c3a1a64f1afa968ba5f615507462abb13ae24d5b3aab23c7045",
"md5": "f54f7d69fb96d31fc8b90f751584b628",
"sha256": "47cf958f4efba5c7f8d395d47a1c4d34f3b1045c19c66db0a09b1b734c902c3f"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp310-none-win_amd64.whl",
"has_sig": false,
"md5_digest": "f54f7d69fb96d31fc8b90f751584b628",
"packagetype": "bdist_wheel",
"python_version": "cp310",
"requires_python": null,
"size": 3482174,
"upload_time": "2024-05-15T09:23:19",
"upload_time_iso_8601": "2024-05-15T09:23:19.470017Z",
"url": "https://files.pythonhosted.org/packages/d8/a2/b656e5ed0c3a1a64f1afa968ba5f615507462abb13ae24d5b3aab23c7045/atomic_bomb_engine-0.39.0-cp310-none-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b6e43f9c819a0b5e58c19f68654d5f6ace45046e28eb3e3df49809ed7cbe25d3",
"md5": "e1336117ba12ace2fc424b01555ce557",
"sha256": "b932a45821281b828ce1eb5195e7ff05ef013e8f9bba406441b26355a4c15848"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp311-cp311-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "e1336117ba12ace2fc424b01555ce557",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": null,
"size": 3776406,
"upload_time": "2024-05-15T09:26:03",
"upload_time_iso_8601": "2024-05-15T09:26:03.371464Z",
"url": "https://files.pythonhosted.org/packages/b6/e4/3f9c819a0b5e58c19f68654d5f6ace45046e28eb3e3df49809ed7cbe25d3/atomic_bomb_engine-0.39.0-cp311-cp311-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "240b9745a4906d9638bc5f599368a2008d502b17d18042fc034a6ebb360e2e41",
"md5": "231a07ff30d7616451257ba7967a190e",
"sha256": "b140a53d8a37f248d970755fc32eb7b8e7e8f59220a87e2ad7b1f5012c05f280"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp311-cp311-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "231a07ff30d7616451257ba7967a190e",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": null,
"size": 3707057,
"upload_time": "2024-05-15T09:21:31",
"upload_time_iso_8601": "2024-05-15T09:21:31.344565Z",
"url": "https://files.pythonhosted.org/packages/24/0b/9745a4906d9638bc5f599368a2008d502b17d18042fc034a6ebb360e2e41/atomic_bomb_engine-0.39.0-cp311-cp311-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0a4eb59168de89714ae05a2efbc09884a40ce44ec3957944dcb12177ca61b214",
"md5": "9aa795ea810fbfce6bd4e64bf6b381f5",
"sha256": "e976259a3f250cf0094b83fcfdafcfa39bf5850bc153a8ad6511f6c80a777a47"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp311-cp311-manylinux_2_34_x86_64.whl",
"has_sig": false,
"md5_digest": "9aa795ea810fbfce6bd4e64bf6b381f5",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": null,
"size": 6118343,
"upload_time": "2024-05-15T09:20:07",
"upload_time_iso_8601": "2024-05-15T09:20:07.360777Z",
"url": "https://files.pythonhosted.org/packages/0a/4e/b59168de89714ae05a2efbc09884a40ce44ec3957944dcb12177ca61b214/atomic_bomb_engine-0.39.0-cp311-cp311-manylinux_2_34_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "26bcfbc1f0058554cbba8320f1cf81555300cf4faae4423452c3278e394faeba",
"md5": "bc755d925cd693c82bd181205e59356d",
"sha256": "23903f53f18114fad2c1e2bd883039140b3f6ce6b818d985850f73b866c8c1e9"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp311-cp311-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "bc755d925cd693c82bd181205e59356d",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": null,
"size": 4506773,
"upload_time": "2024-05-15T09:23:32",
"upload_time_iso_8601": "2024-05-15T09:23:32.286246Z",
"url": "https://files.pythonhosted.org/packages/26/bc/fbc1f0058554cbba8320f1cf81555300cf4faae4423452c3278e394faeba/atomic_bomb_engine-0.39.0-cp311-cp311-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "96308e534675b86685566295aae7d774765c3a2543bcc8cd81212b51a79741b0",
"md5": "2d0f2aa4bf5df94eb7483114e59cc3c0",
"sha256": "bcf57b629cba41d807befc54b1072790b16cdecbff595e6f91bcc95f0fe6c2c3"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp311-none-win_amd64.whl",
"has_sig": false,
"md5_digest": "2d0f2aa4bf5df94eb7483114e59cc3c0",
"packagetype": "bdist_wheel",
"python_version": "cp311",
"requires_python": null,
"size": 3481778,
"upload_time": "2024-05-15T09:23:20",
"upload_time_iso_8601": "2024-05-15T09:23:20.541712Z",
"url": "https://files.pythonhosted.org/packages/96/30/8e534675b86685566295aae7d774765c3a2543bcc8cd81212b51a79741b0/atomic_bomb_engine-0.39.0-cp311-none-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "99a80af846b3e57467210dd7e0b9fab1b772dc3ba8dedc5eb5d11ba232e65531",
"md5": "3661af24d4246c1005ea8f494c3f779e",
"sha256": "85d4bfa500baebe1a8ca4c18dff1e5b8127ccc5b81bbf9f1c233bdb0ef72ec8b"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp312-cp312-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "3661af24d4246c1005ea8f494c3f779e",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": null,
"size": 3775800,
"upload_time": "2024-05-15T09:26:14",
"upload_time_iso_8601": "2024-05-15T09:26:14.711478Z",
"url": "https://files.pythonhosted.org/packages/99/a8/0af846b3e57467210dd7e0b9fab1b772dc3ba8dedc5eb5d11ba232e65531/atomic_bomb_engine-0.39.0-cp312-cp312-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8cbe80e60813e89534ca47ba545981b4c1aa3ee00d124bd23e96074a1866c53a",
"md5": "262cf4ed12a097ff75b4ed805d1db5d6",
"sha256": "762880a11b70fe896b2d9fa38ea4e42ae8e09f2e8c952487c2353e2b6e1a164e"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp312-cp312-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "262cf4ed12a097ff75b4ed805d1db5d6",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": null,
"size": 3709517,
"upload_time": "2024-05-15T09:24:09",
"upload_time_iso_8601": "2024-05-15T09:24:09.868436Z",
"url": "https://files.pythonhosted.org/packages/8c/be/80e60813e89534ca47ba545981b4c1aa3ee00d124bd23e96074a1866c53a/atomic_bomb_engine-0.39.0-cp312-cp312-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9dcce91b5c2de34d8a7b0066aedd87ec92ffc0a7ec66f3922427ecde41583ea8",
"md5": "53e033ccea809e20b417e120ea31ada6",
"sha256": "0be77503670187b3bbab92f3044b11ec79e8444adcdfdca4a435b773a1250f8f"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp312-cp312-manylinux_2_34_x86_64.whl",
"has_sig": false,
"md5_digest": "53e033ccea809e20b417e120ea31ada6",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": null,
"size": 6118319,
"upload_time": "2024-05-15T09:20:06",
"upload_time_iso_8601": "2024-05-15T09:20:06.795576Z",
"url": "https://files.pythonhosted.org/packages/9d/cc/e91b5c2de34d8a7b0066aedd87ec92ffc0a7ec66f3922427ecde41583ea8/atomic_bomb_engine-0.39.0-cp312-cp312-manylinux_2_34_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3837f10c333472640756bccde1e2aa890cbc8f2527ad3fbfd5656b729fe9dfdc",
"md5": "c0a0e565c852430f1dca053c258d582b",
"sha256": "305be8f7108d3781d518eb29a4737dcea89bcd151dbbf49e4f0149f9c8057cb8"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp312-cp312-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "c0a0e565c852430f1dca053c258d582b",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": null,
"size": 4509618,
"upload_time": "2024-05-15T09:23:46",
"upload_time_iso_8601": "2024-05-15T09:23:46.877181Z",
"url": "https://files.pythonhosted.org/packages/38/37/f10c333472640756bccde1e2aa890cbc8f2527ad3fbfd5656b729fe9dfdc/atomic_bomb_engine-0.39.0-cp312-cp312-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e65963e32473e45f001359cefb325a523d18e42c159a753f6d77fbb8eb08f105",
"md5": "6ec71314417a07a144aef926fd12ac3f",
"sha256": "b0251ca41961b5fa649a48b6ad4da37279d4342c8345672ab4fcb50779aaf0c8"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp312-none-win_amd64.whl",
"has_sig": false,
"md5_digest": "6ec71314417a07a144aef926fd12ac3f",
"packagetype": "bdist_wheel",
"python_version": "cp312",
"requires_python": null,
"size": 3485619,
"upload_time": "2024-05-15T09:23:23",
"upload_time_iso_8601": "2024-05-15T09:23:23.332181Z",
"url": "https://files.pythonhosted.org/packages/e6/59/63e32473e45f001359cefb325a523d18e42c159a753f6d77fbb8eb08f105/atomic_bomb_engine-0.39.0-cp312-none-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "a999c33d0bcb364ac9ac17856bbc288b8ecb97ba79d59f627d877a96cda7787b",
"md5": "df5cbc8e6c2251347ea31644c8f5d837",
"sha256": "e6c5712b88f859b40fca8bfb5bb26d64a8f130ac87d60e36193b7e020a00278a"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp38-cp38-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "df5cbc8e6c2251347ea31644c8f5d837",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": null,
"size": 3776776,
"upload_time": "2024-05-15T09:27:16",
"upload_time_iso_8601": "2024-05-15T09:27:16.132547Z",
"url": "https://files.pythonhosted.org/packages/a9/99/c33d0bcb364ac9ac17856bbc288b8ecb97ba79d59f627d877a96cda7787b/atomic_bomb_engine-0.39.0-cp38-cp38-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5c619853a143396e73b2a4c033c9d5f29ecf9d5d53ee12fb319252dd6873418a",
"md5": "aa0e3dfdaaf983a70c70ddf5fe492f89",
"sha256": "25b8bc9b23591035eaf3bafdf0f281673d5dce0b8beb824fe1f9e0627ed2c7be"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp38-cp38-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "aa0e3dfdaaf983a70c70ddf5fe492f89",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": null,
"size": 3707696,
"upload_time": "2024-05-15T09:21:32",
"upload_time_iso_8601": "2024-05-15T09:21:32.828573Z",
"url": "https://files.pythonhosted.org/packages/5c/61/9853a143396e73b2a4c033c9d5f29ecf9d5d53ee12fb319252dd6873418a/atomic_bomb_engine-0.39.0-cp38-cp38-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b05df67646c8250fa35ba797edd975ae5a2a854c301f9e289194426ef35660bc",
"md5": "1a6b3b4640a969825c4a4080f60a9760",
"sha256": "936e11fd7f51cdafb0176167dadefee80b3d722cfdc4ed96fb8429329895e032"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp38-cp38-manylinux_2_34_x86_64.whl",
"has_sig": false,
"md5_digest": "1a6b3b4640a969825c4a4080f60a9760",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": null,
"size": 6116579,
"upload_time": "2024-05-15T09:20:09",
"upload_time_iso_8601": "2024-05-15T09:20:09.150761Z",
"url": "https://files.pythonhosted.org/packages/b0/5d/f67646c8250fa35ba797edd975ae5a2a854c301f9e289194426ef35660bc/atomic_bomb_engine-0.39.0-cp38-cp38-manylinux_2_34_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f5afa9e26ceb4099a6dad005df909b0de64921618e1a878b3c816a94cb3c3138",
"md5": "10519068e7f66b7e8fb6b182798094bb",
"sha256": "28696f128affc372cf1c2ed36f56ef0730a5c0207ac531ec6ecc5a94cc93aae1"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp38-cp38-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "10519068e7f66b7e8fb6b182798094bb",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": null,
"size": 4507252,
"upload_time": "2024-05-15T09:23:17",
"upload_time_iso_8601": "2024-05-15T09:23:17.748889Z",
"url": "https://files.pythonhosted.org/packages/f5/af/a9e26ceb4099a6dad005df909b0de64921618e1a878b3c816a94cb3c3138/atomic_bomb_engine-0.39.0-cp38-cp38-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e8e746c3da886227063eff9565e5c0bbfc2573a99ec48e074f24485ee2a40ba7",
"md5": "ce4171d0e67bedd80918afa6017936d3",
"sha256": "065dff4b71140f0a3afc88d22374649def0948c2ac5ac72f5a13b9bebfaff121"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp38-none-win_amd64.whl",
"has_sig": false,
"md5_digest": "ce4171d0e67bedd80918afa6017936d3",
"packagetype": "bdist_wheel",
"python_version": "cp38",
"requires_python": null,
"size": 3482597,
"upload_time": "2024-05-15T09:22:43",
"upload_time_iso_8601": "2024-05-15T09:22:43.637303Z",
"url": "https://files.pythonhosted.org/packages/e8/e7/46c3da886227063eff9565e5c0bbfc2573a99ec48e074f24485ee2a40ba7/atomic_bomb_engine-0.39.0-cp38-none-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "98b50482d82ef7897fe209d55060ab8428ddcb81823cb36634da3f8b10d56fda",
"md5": "1e608d3025e896a0bce02ef8dbbdca26",
"sha256": "42a66e4bceeaaaef71cfffbd3a5b3512a34587799d5410d8287a27a3f202c214"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp39-cp39-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "1e608d3025e896a0bce02ef8dbbdca26",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": null,
"size": 3776395,
"upload_time": "2024-05-15T09:30:51",
"upload_time_iso_8601": "2024-05-15T09:30:51.720362Z",
"url": "https://files.pythonhosted.org/packages/98/b5/0482d82ef7897fe209d55060ab8428ddcb81823cb36634da3f8b10d56fda/atomic_bomb_engine-0.39.0-cp39-cp39-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5ff0e197c6bfb0282ca48456ff30d64e459703a29a2e2117b845090fa15e4c65",
"md5": "de6c26e68d65e405c7704d5f9bd39dc8",
"sha256": "4179dd51adea519c84597913f62d3afe0e1c7142f6b571b232b8ac6a0da8116f"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp39-cp39-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "de6c26e68d65e405c7704d5f9bd39dc8",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": null,
"size": 3707553,
"upload_time": "2024-05-15T09:22:15",
"upload_time_iso_8601": "2024-05-15T09:22:15.147849Z",
"url": "https://files.pythonhosted.org/packages/5f/f0/e197c6bfb0282ca48456ff30d64e459703a29a2e2117b845090fa15e4c65/atomic_bomb_engine-0.39.0-cp39-cp39-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b7b6b46d3a25b0b871ac18d8cca7479f7f51325e1f6d46d254f6c5a3e5ac5f4d",
"md5": "e8a175ed6044c4d7df96447679d7b6ce",
"sha256": "37696d09ef71d6060dbbdab5edd0ce160b66ef4aa2c8175b3c73f34bd099d518"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp39-cp39-manylinux_2_34_x86_64.whl",
"has_sig": false,
"md5_digest": "e8a175ed6044c4d7df96447679d7b6ce",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": null,
"size": 6116025,
"upload_time": "2024-05-15T09:20:14",
"upload_time_iso_8601": "2024-05-15T09:20:14.594356Z",
"url": "https://files.pythonhosted.org/packages/b7/b6/b46d3a25b0b871ac18d8cca7479f7f51325e1f6d46d254f6c5a3e5ac5f4d/atomic_bomb_engine-0.39.0-cp39-cp39-manylinux_2_34_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "67da119477304fda4b5490b1ce259376f872b251d5e01d600b487276063bfb50",
"md5": "939eb164c01dc0d0fa174b11600252e4",
"sha256": "fc076bffd0493ca357534dc9ec6a562d508b1f7b64ede03e146fae6224c74eeb"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp39-cp39-musllinux_1_2_x86_64.whl",
"has_sig": false,
"md5_digest": "939eb164c01dc0d0fa174b11600252e4",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": null,
"size": 4508236,
"upload_time": "2024-05-15T09:23:28",
"upload_time_iso_8601": "2024-05-15T09:23:28.083804Z",
"url": "https://files.pythonhosted.org/packages/67/da/119477304fda4b5490b1ce259376f872b251d5e01d600b487276063bfb50/atomic_bomb_engine-0.39.0-cp39-cp39-musllinux_1_2_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "1f3066d4f5307f4a1a696e53303c5a127d60a000549ffc35c4dbe8e614f9447a",
"md5": "f07d63b21352cf4c7868c8b8286ca147",
"sha256": "96dd841483eaff2fd76ddc1f54bf9f1dad26d23c4c821a9b4d71f4f687842131"
},
"downloads": -1,
"filename": "atomic_bomb_engine-0.39.0-cp39-none-win_amd64.whl",
"has_sig": false,
"md5_digest": "f07d63b21352cf4c7868c8b8286ca147",
"packagetype": "bdist_wheel",
"python_version": "cp39",
"requires_python": null,
"size": 3482973,
"upload_time": "2024-05-15T09:22:33",
"upload_time_iso_8601": "2024-05-15T09:22:33.796502Z",
"url": "https://files.pythonhosted.org/packages/1f/30/66d4f5307f4a1a696e53303c5a127d60a000549ffc35c4dbe8e614f9447a/atomic_bomb_engine-0.39.0-cp39-none-win_amd64.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-15 09:26:16",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "atomic-bomb-engine"
}