# UTX
![PyPI](https://img.shields.io/pypi/v/utx) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/utx) [![Downloads](https://static.pepy.tech/personalized-badge/utx?period=total&units=international_system&left_color=grey&right_color=brightgreen&left_text=downloads/total)](https://pepy.tech/project/utx) ![GitHub top language](https://img.shields.io/github/languages/top/openutx/utx) ![GitHub stars](https://img.shields.io/github/stars/openutx/utx?style=social) ![https://blog.csdn.net/flower_drop](https://img.shields.io/badge/csdn-%40flower__drop-orange)
## logo
![](https://cdn.jsdelivr.net/gh/openutx/static/image/utx.png)
## 安装
- 命令行执行
```
pip install -U utx
```
## 设计理念
很大程度上借鉴了HttpRunner(优秀的框架)。不同的是,utx更着重写python,而不是写yaml文件。
- 简单是更好的
- 每个人都能用python写自动化
- UI自动化跟的上冲刺迭代和UI变更
这就是utx的设计理念。
## 项目结构
![](https://cdn.jsdelivr.net/gh/openutx/static/image/jg.png)
- utx提供了快速创建项目的能力,也就是脚手架。
- 【app脚手架】
```shell
utx startproject project_name
```
- 【web脚手架】
```shell
utx startproject-web project_name
```
```text
$ utx startproject demo
2021-09-01 12:39:16.491 | INFO | utx.cli.scaffold:create_scaffold:51 - Create new project: demo
Project root dir: /PycharmProjects/demo
Created folder: demo
Created folder: demo/config
Created folder: demo/logs
Created folder: demo/packages
Created folder: demo/report/airtest
Created folder: demo/tests
Created folder: demo/suites
Created file: demo/.gitignore
Created file: demo/conftest.py
Created file: demo/pytest.ini
Created file: demo/run.py
Created file: demo/requirements.txt
Created file: demo/config/conf.py
Created file: demo/config/config.ini
Created file: demo/config/__init__.py
Created file: demo/tests/test_devices.py
Created file: demo/tests/__init__.py
Created file: demo/report/summary_template.html
```
## 调用流程图
![](https://cdn.jsdelivr.net/gh/openutx/static/image/lc.png)
## 专注于写脚本
- 项目结构很清晰。在conftest.py进行一些初始化/参数化/清理工作,在suites/写测试脚本。
>在AirtestIDE中写好.air脚本,然后将文件放到suites文件中。
- 更注重平铺写脚本的方式,这样就离“每个人都能用python写自动化”更近一步。毕竟封装之后看着容易晕,我也晕。
- 去除掉框架的约束,给每个人写python的自由,在测试脚本里你可以尽情发挥你的代码风格,代码能力,千人千面。代价呢,就是代码质量参差不齐。
大胆写,能写,写出来,跑通,就已经是在写自动化,就已经是在创造价值了!
## 轻封装
utx尊重原生用法。
airtest的封装只通过装饰器进行了运行方式的调整,没有做任何其他的冗余修改。
- faker,造数据工具
- pytest,测试框架
- airtest,自动化测试工具
- tidevice,iOS设备管理工具
- pandas、numpy,数据处理工具
安装utx,自动就把这些开源利器安装上了,无需单独安装。未来会集成更多实用工具到utx中。
utx本身是很轻的。
## 核心价值
- 上手 0 门槛,iOS/Android 设备均实现即插即用,随写随调
- 测试用例可读性高,编写成本低,支持python语法,便于公共操作抽象,进一步提高用例可维护性
- 用例执行高鲁棒性,多设备机型切换无需更改用例适配
- 执行集创建简单,支持智能并发、分组单模块执行,更高效更灵活
## 功能介绍
1. 支持android,ios,web 平台的自动化测试框架
2. 脚本批量执行
3. 每个脚本执行日志分开存放
4. 每个脚本单独生成一个html报告并在父文件夹生成一个聚合报告
5. 自定义的聚合报告,详细展示运行结果
6. 重试机制,运行失败自动重跑,可自定义重跑次数
7. 自定义脚本运行,可选择部分模块单独运行
8. 自带脚手架工具可以快速生成框架目录
## app使用说明
- 只需在配置文件中填好相关内容,即可运行!
```ini
[device_info]
;设备远程链接URL 设备ip+端口或者设备唯一标识id,多个设备以,分割;例如 设备1,设备2,设备3
device = 127.0.0.1:5555
;设备平台iOS或者Android
platform = android
;ios设备驱动包名,仅测试iOS时需要
wda = com.facebook.WebDriverAgentRunner.utx.xctrunner
;是否执行安装卸载操作 True/False
init = False
[app_info]
;app包名
package = com.wx.mp.test
;apk或者ipa文件名
filename = app_test.apk
[reruns]
;失败后再次运行次数,默认1次
times = 1
[paths]
;自定义执行case目录层级,文件夹名称(例如:smoke),默认为空
name =
[mode]
;False 表示 运行[suites][cases]选择的用例,True表示运行全部用例
is_all = True
;是否录制视频 True/False
record = False
[suites]
;填写用例的关键字
cases = test.air
```
- app启动命令
1. 普通启动
```shell
python run.py
```
2. 参数化启动
```shell
# Android
python run.py --platform=Android --device=127.0.0.1:5555 --init=True
# iOS
python run.py --platform=iOS --wda=com.facebook.WebDriverAgentRunner.utx.xctrunner --init=True
```
>参数优先级大于配置文件
> >多个设备以,分割; 例如 python run.py --platform=Android --device=设备1,设备2,设备3 --init=True
## web使用说明
- 无需关注 chrome浏览器驱动
> 注意:无需配置 chromedriver ,系统会自动化维护匹配版本。
- 只需在配置文件中填好相关内容,即可运行!
```ini
[web_info]
;被测的主页url
url = https://www.baidu.com/
;是否无界面运行
headless = False
[reruns]
;失败后再次运行次数,默认1次
times = 1
[paths]
;自定义执行case目录层级,文件夹名称(例如:smoke),默认为空
name =
[mode]
;False 表示 运行[suites][cases]选择的用例,True表示运行全部用例
is_all = True
[suites]
;填写用例的关键字
cases = chrome
```
- web启动命令
1. 普通启动
```shell
python run.py
```
2. 参数化启动
```shell
python run.py --headless=True --driver=/Users/admin/driverpath
```
>参数优先级大于配置文件
## 运行结果
- 报告展示
![](https://cdn.jsdelivr.net/gh/openutx/static/image/bg.png)
Raw data
{
"_id": null,
"home_page": "https://github.com/openutx",
"name": "utx",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "utx, airtest, pytest, selenium, ui, tools",
"author": "lijiawei",
"author_email": "jiawei.li2@qq.com",
"download_url": "https://files.pythonhosted.org/packages/6c/7b/909caa66071c74b5678de2c2a1cfe86fe49c8a740a66694a49e82c575cd4/utx-1.4.2.tar.gz",
"platform": "any",
"description": "# UTX\n![PyPI](https://img.shields.io/pypi/v/utx) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/utx) [![Downloads](https://static.pepy.tech/personalized-badge/utx?period=total&units=international_system&left_color=grey&right_color=brightgreen&left_text=downloads/total)](https://pepy.tech/project/utx) ![GitHub top language](https://img.shields.io/github/languages/top/openutx/utx) ![GitHub stars](https://img.shields.io/github/stars/openutx/utx?style=social) ![https://blog.csdn.net/flower_drop](https://img.shields.io/badge/csdn-%40flower__drop-orange)\n## logo\n![](https://cdn.jsdelivr.net/gh/openutx/static/image/utx.png)\n## \u5b89\u88c5\n- \u547d\u4ee4\u884c\u6267\u884c\n```\npip install -U utx\n```\n\n\n## \u8bbe\u8ba1\u7406\u5ff5\n\n\u5f88\u5927\u7a0b\u5ea6\u4e0a\u501f\u9274\u4e86HttpRunner\uff08\u4f18\u79c0\u7684\u6846\u67b6\uff09\u3002\u4e0d\u540c\u7684\u662f\uff0cutx\u66f4\u7740\u91cd\u5199python\uff0c\u800c\u4e0d\u662f\u5199yaml\u6587\u4ef6\u3002\n\n- \u7b80\u5355\u662f\u66f4\u597d\u7684\n- \u6bcf\u4e2a\u4eba\u90fd\u80fd\u7528python\u5199\u81ea\u52a8\u5316\n- UI\u81ea\u52a8\u5316\u8ddf\u7684\u4e0a\u51b2\u523a\u8fed\u4ee3\u548cUI\u53d8\u66f4\n\n\n\u8fd9\u5c31\u662futx\u7684\u8bbe\u8ba1\u7406\u5ff5\u3002\n\n\n## \u9879\u76ee\u7ed3\u6784\n![](https://cdn.jsdelivr.net/gh/openutx/static/image/jg.png)\n\n- utx\u63d0\u4f9b\u4e86\u5feb\u901f\u521b\u5efa\u9879\u76ee\u7684\u80fd\u529b\uff0c\u4e5f\u5c31\u662f\u811a\u624b\u67b6\u3002\n- \u3010app\u811a\u624b\u67b6\u3011\n```shell\nutx startproject project_name\n```\n- \u3010web\u811a\u624b\u67b6\u3011\n```shell\nutx startproject-web project_name\n```\n```text\n$ utx startproject demo\n2021-09-01 12:39:16.491 | INFO | utx.cli.scaffold:create_scaffold:51 - Create new project: demo\nProject root dir: /PycharmProjects/demo\n\nCreated folder: demo\nCreated folder: demo/config\nCreated folder: demo/logs\nCreated folder: demo/packages\nCreated folder: demo/report/airtest\nCreated folder: demo/tests\nCreated folder: demo/suites\nCreated file: demo/.gitignore\nCreated file: demo/conftest.py\nCreated file: demo/pytest.ini\nCreated file: demo/run.py\nCreated file: demo/requirements.txt\nCreated file: demo/config/conf.py\nCreated file: demo/config/config.ini\nCreated file: demo/config/__init__.py\nCreated file: demo/tests/test_devices.py\nCreated file: demo/tests/__init__.py\nCreated file: demo/report/summary_template.html\n\n```\n## \u8c03\u7528\u6d41\u7a0b\u56fe\n\n![](https://cdn.jsdelivr.net/gh/openutx/static/image/lc.png)\n\n## \u4e13\u6ce8\u4e8e\u5199\u811a\u672c\n\n- \u9879\u76ee\u7ed3\u6784\u5f88\u6e05\u6670\u3002\u5728conftest.py\u8fdb\u884c\u4e00\u4e9b\u521d\u59cb\u5316/\u53c2\u6570\u5316/\u6e05\u7406\u5de5\u4f5c\uff0c\u5728suites/\u5199\u6d4b\u8bd5\u811a\u672c\u3002\n>\u5728AirtestIDE\u4e2d\u5199\u597d.air\u811a\u672c\uff0c\u7136\u540e\u5c06\u6587\u4ef6\u653e\u5230suites\u6587\u4ef6\u4e2d\u3002\n- \u66f4\u6ce8\u91cd\u5e73\u94fa\u5199\u811a\u672c\u7684\u65b9\u5f0f\uff0c\u8fd9\u6837\u5c31\u79bb\u201c\u6bcf\u4e2a\u4eba\u90fd\u80fd\u7528python\u5199\u81ea\u52a8\u5316\u201d\u66f4\u8fd1\u4e00\u6b65\u3002\u6bd5\u7adf\u5c01\u88c5\u4e4b\u540e\u770b\u7740\u5bb9\u6613\u6655\uff0c\u6211\u4e5f\u6655\u3002\n- \u53bb\u9664\u6389\u6846\u67b6\u7684\u7ea6\u675f\uff0c\u7ed9\u6bcf\u4e2a\u4eba\u5199python\u7684\u81ea\u7531\uff0c\u5728\u6d4b\u8bd5\u811a\u672c\u91cc\u4f60\u53ef\u4ee5\u5c3d\u60c5\u53d1\u6325\u4f60\u7684\u4ee3\u7801\u98ce\u683c\uff0c\u4ee3\u7801\u80fd\u529b\uff0c\u5343\u4eba\u5343\u9762\u3002\u4ee3\u4ef7\u5462\uff0c\u5c31\u662f\u4ee3\u7801\u8d28\u91cf\u53c2\u5dee\u4e0d\u9f50\u3002\n\n\u5927\u80c6\u5199\uff0c\u80fd\u5199\uff0c\u5199\u51fa\u6765\uff0c\u8dd1\u901a\uff0c\u5c31\u5df2\u7ecf\u662f\u5728\u5199\u81ea\u52a8\u5316\uff0c\u5c31\u5df2\u7ecf\u662f\u5728\u521b\u9020\u4ef7\u503c\u4e86\uff01\n\n\n## \u8f7b\u5c01\u88c5\n\nutx\u5c0a\u91cd\u539f\u751f\u7528\u6cd5\u3002\n\nairtest\u7684\u5c01\u88c5\u53ea\u901a\u8fc7\u88c5\u9970\u5668\u8fdb\u884c\u4e86\u8fd0\u884c\u65b9\u5f0f\u7684\u8c03\u6574\uff0c\u6ca1\u6709\u505a\u4efb\u4f55\u5176\u4ed6\u7684\u5197\u4f59\u4fee\u6539\u3002\n\n- faker\uff0c\u9020\u6570\u636e\u5de5\u5177\n- pytest\uff0c\u6d4b\u8bd5\u6846\u67b6\n- airtest\uff0c\u81ea\u52a8\u5316\u6d4b\u8bd5\u5de5\u5177\n- tidevice\uff0ciOS\u8bbe\u5907\u7ba1\u7406\u5de5\u5177\n- pandas\u3001numpy\uff0c\u6570\u636e\u5904\u7406\u5de5\u5177\n\n\u5b89\u88c5utx\uff0c\u81ea\u52a8\u5c31\u628a\u8fd9\u4e9b\u5f00\u6e90\u5229\u5668\u5b89\u88c5\u4e0a\u4e86\uff0c\u65e0\u9700\u5355\u72ec\u5b89\u88c5\u3002\u672a\u6765\u4f1a\u96c6\u6210\u66f4\u591a\u5b9e\u7528\u5de5\u5177\u5230utx\u4e2d\u3002\n\nutx\u672c\u8eab\u662f\u5f88\u8f7b\u7684\u3002\n\n## \u6838\u5fc3\u4ef7\u503c\n\n- \u4e0a\u624b 0 \u95e8\u69db\uff0ciOS/Android \u8bbe\u5907\u5747\u5b9e\u73b0\u5373\u63d2\u5373\u7528\uff0c\u968f\u5199\u968f\u8c03\n- \u6d4b\u8bd5\u7528\u4f8b\u53ef\u8bfb\u6027\u9ad8\uff0c\u7f16\u5199\u6210\u672c\u4f4e\uff0c\u652f\u6301python\u8bed\u6cd5\uff0c\u4fbf\u4e8e\u516c\u5171\u64cd\u4f5c\u62bd\u8c61\uff0c\u8fdb\u4e00\u6b65\u63d0\u9ad8\u7528\u4f8b\u53ef\u7ef4\u62a4\u6027\n- \u7528\u4f8b\u6267\u884c\u9ad8\u9c81\u68d2\u6027\uff0c\u591a\u8bbe\u5907\u673a\u578b\u5207\u6362\u65e0\u9700\u66f4\u6539\u7528\u4f8b\u9002\u914d\n- \u6267\u884c\u96c6\u521b\u5efa\u7b80\u5355\uff0c\u652f\u6301\u667a\u80fd\u5e76\u53d1\u3001\u5206\u7ec4\u5355\u6a21\u5757\u6267\u884c\uff0c\u66f4\u9ad8\u6548\u66f4\u7075\u6d3b\n\n## \u529f\u80fd\u4ecb\u7ecd\n\n1. \u652f\u6301android,ios,web \u5e73\u53f0\u7684\u81ea\u52a8\u5316\u6d4b\u8bd5\u6846\u67b6\n2. \u811a\u672c\u6279\u91cf\u6267\u884c\n3. \u6bcf\u4e2a\u811a\u672c\u6267\u884c\u65e5\u5fd7\u5206\u5f00\u5b58\u653e\n4. \u6bcf\u4e2a\u811a\u672c\u5355\u72ec\u751f\u6210\u4e00\u4e2ahtml\u62a5\u544a\u5e76\u5728\u7236\u6587\u4ef6\u5939\u751f\u6210\u4e00\u4e2a\u805a\u5408\u62a5\u544a\n5. \u81ea\u5b9a\u4e49\u7684\u805a\u5408\u62a5\u544a\uff0c\u8be6\u7ec6\u5c55\u793a\u8fd0\u884c\u7ed3\u679c\n6. \u91cd\u8bd5\u673a\u5236\uff0c\u8fd0\u884c\u5931\u8d25\u81ea\u52a8\u91cd\u8dd1\uff0c\u53ef\u81ea\u5b9a\u4e49\u91cd\u8dd1\u6b21\u6570\n7. \u81ea\u5b9a\u4e49\u811a\u672c\u8fd0\u884c\uff0c\u53ef\u9009\u62e9\u90e8\u5206\u6a21\u5757\u5355\u72ec\u8fd0\u884c\n8. \u81ea\u5e26\u811a\u624b\u67b6\u5de5\u5177\u53ef\u4ee5\u5feb\u901f\u751f\u6210\u6846\u67b6\u76ee\u5f55\n\n\n## app\u4f7f\u7528\u8bf4\u660e\n\n- \u53ea\u9700\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u586b\u597d\u76f8\u5173\u5185\u5bb9\uff0c\u5373\u53ef\u8fd0\u884c\uff01\n```ini\n[device_info]\n;\u8bbe\u5907\u8fdc\u7a0b\u94fe\u63a5URL \u8bbe\u5907ip+\u7aef\u53e3\u6216\u8005\u8bbe\u5907\u552f\u4e00\u6807\u8bc6id\uff0c\u591a\u4e2a\u8bbe\u5907\u4ee5,\u5206\u5272\uff1b\u4f8b\u5982 \u8bbe\u59071,\u8bbe\u59072,\u8bbe\u59073\ndevice = 127.0.0.1:5555\n;\u8bbe\u5907\u5e73\u53f0iOS\u6216\u8005Android\nplatform = android\n;ios\u8bbe\u5907\u9a71\u52a8\u5305\u540d\uff0c\u4ec5\u6d4b\u8bd5iOS\u65f6\u9700\u8981\nwda = com.facebook.WebDriverAgentRunner.utx.xctrunner\n;\u662f\u5426\u6267\u884c\u5b89\u88c5\u5378\u8f7d\u64cd\u4f5c True/False\ninit = False\n\n[app_info]\n;app\u5305\u540d\npackage = com.wx.mp.test\n;apk\u6216\u8005ipa\u6587\u4ef6\u540d\nfilename = app_test.apk\n\n[reruns]\n;\u5931\u8d25\u540e\u518d\u6b21\u8fd0\u884c\u6b21\u6570\uff0c\u9ed8\u8ba41\u6b21\ntimes = 1\n\n[paths]\n;\u81ea\u5b9a\u4e49\u6267\u884ccase\u76ee\u5f55\u5c42\u7ea7\uff0c\u6587\u4ef6\u5939\u540d\u79f0\uff08\u4f8b\u5982\uff1asmoke\uff09\uff0c\u9ed8\u8ba4\u4e3a\u7a7a\nname = \n\n[mode]\n;False \u8868\u793a \u8fd0\u884c[suites][cases]\u9009\u62e9\u7684\u7528\u4f8b\uff0cTrue\u8868\u793a\u8fd0\u884c\u5168\u90e8\u7528\u4f8b\nis_all = True\n;\u662f\u5426\u5f55\u5236\u89c6\u9891 True/False\nrecord = False\n\n[suites]\n;\u586b\u5199\u7528\u4f8b\u7684\u5173\u952e\u5b57\ncases = test.air\n```\n\n- app\u542f\u52a8\u547d\u4ee4\n1. \u666e\u901a\u542f\u52a8\n```shell\npython run.py\n```\n2. \u53c2\u6570\u5316\u542f\u52a8\n```shell\n# Android\npython run.py --platform=Android --device=127.0.0.1:5555 --init=True\n# iOS\npython run.py --platform=iOS --wda=com.facebook.WebDriverAgentRunner.utx.xctrunner --init=True\n```\n>\u53c2\u6570\u4f18\u5148\u7ea7\u5927\u4e8e\u914d\u7f6e\u6587\u4ef6\n> >\u591a\u4e2a\u8bbe\u5907\u4ee5,\u5206\u5272; \u4f8b\u5982 python run.py --platform=Android --device=\u8bbe\u59071,\u8bbe\u59072,\u8bbe\u59073 --init=True\n\n## web\u4f7f\u7528\u8bf4\u660e\n\n- \u65e0\u9700\u5173\u6ce8 chrome\u6d4f\u89c8\u5668\u9a71\u52a8\n> \u6ce8\u610f\uff1a\u65e0\u9700\u914d\u7f6e chromedriver \uff0c\u7cfb\u7edf\u4f1a\u81ea\u52a8\u5316\u7ef4\u62a4\u5339\u914d\u7248\u672c\u3002\n- \u53ea\u9700\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\u586b\u597d\u76f8\u5173\u5185\u5bb9\uff0c\u5373\u53ef\u8fd0\u884c\uff01\n```ini\n[web_info]\n;\u88ab\u6d4b\u7684\u4e3b\u9875url\nurl = https://www.baidu.com/\n;\u662f\u5426\u65e0\u754c\u9762\u8fd0\u884c\nheadless = False\n\n[reruns]\n;\u5931\u8d25\u540e\u518d\u6b21\u8fd0\u884c\u6b21\u6570\uff0c\u9ed8\u8ba41\u6b21\ntimes = 1\n\n[paths]\n;\u81ea\u5b9a\u4e49\u6267\u884ccase\u76ee\u5f55\u5c42\u7ea7\uff0c\u6587\u4ef6\u5939\u540d\u79f0\uff08\u4f8b\u5982\uff1asmoke\uff09\uff0c\u9ed8\u8ba4\u4e3a\u7a7a\nname = \n\n[mode]\n;False \u8868\u793a \u8fd0\u884c[suites][cases]\u9009\u62e9\u7684\u7528\u4f8b\uff0cTrue\u8868\u793a\u8fd0\u884c\u5168\u90e8\u7528\u4f8b\nis_all = True\n\n[suites]\n;\u586b\u5199\u7528\u4f8b\u7684\u5173\u952e\u5b57\ncases = chrome\n\n```\n\n- web\u542f\u52a8\u547d\u4ee4\n1. \u666e\u901a\u542f\u52a8\n```shell\npython run.py\n```\n2. \u53c2\u6570\u5316\u542f\u52a8\n```shell\npython run.py --headless=True --driver=/Users/admin/driverpath\n```\n>\u53c2\u6570\u4f18\u5148\u7ea7\u5927\u4e8e\u914d\u7f6e\u6587\u4ef6\n\n## \u8fd0\u884c\u7ed3\u679c\n- \u62a5\u544a\u5c55\u793a\n\n![](https://cdn.jsdelivr.net/gh/openutx/static/image/bg.png)\n\n",
"bugtrack_url": null,
"license": "Apache License 2.0",
"summary": "UTX will help you write ui automated tests more easily!",
"version": "1.4.2",
"project_urls": {
"Homepage": "https://github.com/openutx"
},
"split_keywords": [
"utx",
" airtest",
" pytest",
" selenium",
" ui",
" tools"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "159ab5b3f1534f8ac6c48c371edad6d9eed069d1ad1bff141a7b7b4d6ab6f5d5",
"md5": "67f35a4181eac97fbb75aa1bace737f1",
"sha256": "aa3bb0e518521ef9b2ec736e4b45618ae89e9d876494d23ecfa7a488c0e36b0d"
},
"downloads": -1,
"filename": "utx-1.4.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "67f35a4181eac97fbb75aa1bace737f1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 5760129,
"upload_time": "2024-07-04T11:54:05",
"upload_time_iso_8601": "2024-07-04T11:54:05.417215Z",
"url": "https://files.pythonhosted.org/packages/15/9a/b5b3f1534f8ac6c48c371edad6d9eed069d1ad1bff141a7b7b4d6ab6f5d5/utx-1.4.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "6c7b909caa66071c74b5678de2c2a1cfe86fe49c8a740a66694a49e82c575cd4",
"md5": "6d378b77452b1aa61786c63830deb410",
"sha256": "5d77a27bbe64470022f16be168f7aa170e7b05616dbd784cbea18604fc5d287c"
},
"downloads": -1,
"filename": "utx-1.4.2.tar.gz",
"has_sig": false,
"md5_digest": "6d378b77452b1aa61786c63830deb410",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 5722255,
"upload_time": "2024-07-04T11:54:08",
"upload_time_iso_8601": "2024-07-04T11:54:08.209978Z",
"url": "https://files.pythonhosted.org/packages/6c/7b/909caa66071c74b5678de2c2a1cfe86fe49c8a740a66694a49e82c575cd4/utx-1.4.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-04 11:54:08",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "utx"
}