wrenchbox


Namewrenchbox JSON
Version 1.12.27 PyPI version JSON
download
home_pagehttps://github.com/valency/wrenchbox
SummaryWrenchbox
upload_time2022-12-27 08:46:38
maintainer
docs_urlNone
authorYe Ding
requires_python
license
keywords toolbox tools
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Wrenchbox for Python

A set of utilities for daily development.

本项目是一些常用的 Python 工具集合。

## Install

```shell
pip install -U wrenchbox
```

## Usage

### Alert Hanlder

Send alerts to certain bots or web APIs.

通过钉钉机器人等渠道发送报警信息。

```shell
$ python3 -u -m wrenchbox.alert -h
usage: alert.py [-h] [--debug] --type TYPE [--token TOKEN] msg

positional arguments:
  msg                   the message

optional arguments:
  -h, --help            show this help message and exit
  --debug               show debug information
  --type TYPE, -p TYPE  alert type, must be "dingtalk"
  --token TOKEN, -k TOKEN
                        access token, if any
```

```python
from wrenchbox.alert import DingTalk
DingTalk('token').send('This is a warning message.')
```

```json
200
```

### Configuration Parser

Read a configuration from a YAML or JSON file.

从 YAML 或 JSON 中读取一段配置信息。

```shell
$ python3 -u -m wrenchbox.config -h
usage: config.py [-h] [--debug] config

positional arguments:
  config      config file

optional arguments:
  -h, --help  show this help message and exit
  --debug     show debug information
```

```python
from wrenchbox.config import Configuration
print(json.dumps(Configuration('wrenchbox/config.yml').__dict__, indent=2))
```

```json
{
  "version": 0,
  "name": "00000000-0000-0000-0000-000000000000",
  "config": {
    "key": "value",
    "nested": {
      "key": "value"
    },
    "list": [
      {
        "key": "value"
      },
      {
        "key": "value"
      }
    ]
  }
}
```

The following configurations will be automatically generated if not provided:

- `version` version of the configuration file, could be verified through `Configuration(version=(0,))`
- `worker` ID of the worker, default: 0

- `name` name of the worker, an [UUID](https://www.uuidgenerator.net/) will be generated if not provided

All configuration keys starting with `-` or `.` will be ignored (these keys should be used as audition only).

### Database Hanlder

An advanced database handler based on [SQLAlchemy](https://www.sqlalchemy.org/).

一个基于 [SQLAlchemy](https://www.sqlalchemy.org/) 开发的更简单的数据库处理模块。

```python
from wrenchbox.database import DatabaseHandler
DatabaseHandler({
    'test': 'sqlite:///test.db'
}, [
    ('test', 'test')
]).handle(
    'test', {
        'id': 1
    }, {
        'id': 1,
        'name': str(datetime.now())
    }, replace=True
)
```

The above code will insert or update a record with `id` = `1`.

### Datetime Hanlder

An advanced datetime handler based on [python-dateutil](https://pypi.org/project/python-dateutil/).

一个基于 [python-dateutil](https://pypi.org/project/python-dateutil/) 开发的更简单的日期和时间处理器。

```python
from wrenchbox.datetime import T
print(T().timestamp()) # Get timestamp
print(T().format()) # Format into YYYY-MM-DD HH:MM:SS
print(T().format('d')) # Format into YYYY-MM-DD
print(T().format('t')) # Format into HH:MM:SS
```

```
1598930603.003622
2020-09-01 11:23:23
2020-09-01
11:23:23
```

When initialising `T`, it is possible to pass the following arguments:

- `None` current timestamp will be generated
- `datetime.datetime` will be directly used
- `float` or `int` will be parsed as timestamp
- `str` will be parsed through [python-dateutil](https://pypi.org/project/python-dateutil/)

### Dictionary Hanlder

An advanced dictionary hander providing various tools.

提供了多种多样的字典(dict)处理工具。

```python
from wrenchbox.dict import EnhancedDict
dict_a = {
    'a': 'a',
    'b': {
        'a': 1,
        'b': {
            'a': 1,
            'b': [{
                'a': 1,
                'b': 2
            }, {
                'a': 1,
                'b': {
                    'a': 1,
                    'b': 2
                }
            }]
        }
    }
}
dict_b = {
    'a': 1,
    'b': {
        'b': {
            'b': 2
        }
    }
}
print(dict_a)
print(dict_b)
print(EnhancedDict(dict_a).search('a'))
print(EnhancedDict(dict_a).merge(dict_b))
print(EnhancedDict(dict_b).flatten())
print(EnhancedDict(dict_a).format(lambda x: x + 10, lambda x: isinstance(x, int)))
print(EnhancedDict(dict_a).remove_key('a'))
print(EnhancedDict(dict_a).remove_value(1))
```

```json
{"a": "a", "b": {"a": 1, "b": {"a": 1, "b": [{"a": 1, "b": 2}, {"a": 1, "b": {"a": 1, "b": 2}}]}}}
{"a": 1, "b": {"b": {"b": 2}}}
["a", 1, 1, 1, 1, 1]
{"a": 1, "b": {"a": 1, "b": {"a": 1, "b": 2}}}
{"a": 1, "b_b_b": 2}
{"a": "a", "b": {"a": 11, "b": {"a": 11, "b": [{"a": 11, "b": 12}, {"a": 11, "b": {"a": 11, "b": 12}}]}}}
{"b": {"b": {"b": [{"b": 2}, {"b": {"b": 2}}]}}}
{"a": "a", "b": {"b": {"b": [{"b": 2}, {"b": {"b": 2}}]}}}
```

### IO Handler

An advanced IO handerl providing various tools.

提供了多种多样的 IO 工具。

```python
from wrenchbox.io import BufferedWriter
w = BufferedWriter(buffer=50)
for i in range(100):
    w.write(i)    
w.close()
```

The above code will write two separate files with 50 records each.

### List Hanlder

An advanced list hander providing various tools.

提供了多种多样的列表(list)处理工具。

```python
from wrenchbox.list import EnhancedList
list_a = [1, [1, [2, 3], 2], 2]
print(list_a)
print(EnhancedList(list_a).flatten()) # Flatten the list and put all sub-lists into the root level
print(EnhancedList(list_a).pick(lambda x: x == 1)) # Pick values based on a function
print(EnhancedList(list_a).format(lambda x: x + 1, lambda x: isinstance(x, (int, float)))) # Format values of the list through a filter
```

```json
[1, [1, [2, 3], 2], 2]
[1, 1, 2, 3, 2, 2]
[1, [1]]
[[[2, 3], 2], 2]
[2, [2, [3, 4], 3], 3]
```

### Logging Tools

A series of tools for logging.

提供了美化的日志工具。

```python
from wrenchbox.logging import setup_log, progress
# Create a colorized logger and print logging messages
setup_log(level=logging.DEBUG, path='./log/', tag='wrenchbox')
logging.debug('This is a DEBUG message.')
logging.info('This is an INFO message.')
logging.warning('This is a WARNING message.')
logging.error('This is an ERROR message.')
logging.critical('This is an CRITICAL message.')
# Show a progress bar
for _i in range(100):
    progress(_i, 100)
    time.sleep(0.02)
```

```
[2020-09-28 10:18:40,084] This is a DEBUG message.
[2020-09-28 10:18:40,084] This is an INFO message.
[2020-09-28 10:18:40,084] This is a WARNING message.
[2020-09-28 10:18:40,085] This is an ERROR message.
[2020-09-28 10:18:40,085] This is an CRITICAL message.
[==========================================================--] 97.0%
```

Logs are colorized with the following default config:

```json
{
    DEBUG: "cyan",
    INFO: "green",
    WARNING: "yellow",
    ERROR: "red",
    CRITICAL: "magenta"
}
```

### Number Hanlder

An advanced number hander providing various tools.

提供了多种多样的数字(number)处理工具。

```python
from wrenchbox.number import EnhancedDecimal
print(EnhancedDecimal('3.1415926').round(Decimal('0.1'))) # Round a decimal with any unit like in excel
```

```json
3.1
```

### Object Tools

A series of objects for specific uses.

提供了一些杂项对象。

- `Dict2StrSafe`: a class that correctly converts `self.__dict__` to a JSON string without errors
- `Munch`: an alternative implementation of [Munch](https://github.com/Infinidat/munch)

### Snowflake Code Generator

Generate a series of [Twitter Snowflake Codes](https://developer.twitter.com/en/docs/basics/twitter-ids).

生成若干 [Twitter Snowflake Codes](https://developer.twitter.com/en/docs/basics/twitter-ids)。

```shell
$ python3 -u -m wrenchbox.snowflake -h
usage: snowflake.py [-h] [--debug] [--twepoch TWEPOCH] [-d D] -w W n

positional arguments:
  n                  # of results

optional arguments:
  -h, --help         show this help message and exit
  --debug            show debug information
  --twepoch TWEPOCH  twitter epoch, default: 1483228800000
  -d D               data center id, default: 31
  -w W               worker id, 0-31
```
```python
from wrenchbox.snowflake import Snowflake
print(next(Snowflake(twepoch=1483228800000).generate(31)))
```

```json
495059711868006400
```

### String Handler

An advanced string hander providing various tools.

提供了多种多样的字符串(string)处理工具。

```python
from wrenchbox.string import digits, random_chars, random_letters, random_numbers
print(digits(pi)) # Count the digits of a given float number
print(random_chars(3)) # Generate a random string from [a-zA-Z0-9]
print(random_letters(3)) # Generate a random string from [a-zA-Z]
print(random_numbers(3)) # Generate a random string from [0-9]
```

```
15
63f
FVK
007
```

### Text Handler

A set of advanced text processing modules.

提供了多种多样的文本处理工具。

```shell
$ python3 -u -m wrenchbox.text -h
usage: text.py [-h] [--debug] [--chinese] [-p P] f

positional arguments:
  f           file path

optional arguments:
  -h, --help  show this help message and exit
  --debug     show debug information
  --chinese   specify the input as Chinese
  -p P        part of speech to show, only works for Chinese
```

```python
from wrenchbox.text import S
print([i for i in S(open('test.txt', 'r').read()).v(chinese=True).words if i[1] in ('v',)])
```

```json
[("是", "v", 8), ("获取", "v", 1)]
```




            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/valency/wrenchbox",
    "name": "wrenchbox",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "toolbox,tools",
    "author": "Ye Ding",
    "author_email": "guiewy@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/c5/a3/f35c4e87115551be1cb6a77273dbb20318c14a6b537e150692d9713bbb2f/wrenchbox-1.12.27.tar.gz",
    "platform": null,
    "description": "# Wrenchbox for Python\n\nA set of utilities for daily development.\n\n\u672c\u9879\u76ee\u662f\u4e00\u4e9b\u5e38\u7528\u7684 Python \u5de5\u5177\u96c6\u5408\u3002\n\n## Install\n\n```shell\npip install -U wrenchbox\n```\n\n## Usage\n\n### Alert Hanlder\n\nSend alerts to certain bots or web APIs.\n\n\u901a\u8fc7\u9489\u9489\u673a\u5668\u4eba\u7b49\u6e20\u9053\u53d1\u9001\u62a5\u8b66\u4fe1\u606f\u3002\n\n```shell\n$ python3 -u -m wrenchbox.alert -h\nusage: alert.py [-h] [--debug] --type TYPE [--token TOKEN] msg\n\npositional arguments:\n  msg                   the message\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --debug               show debug information\n  --type TYPE, -p TYPE  alert type, must be \"dingtalk\"\n  --token TOKEN, -k TOKEN\n                        access token, if any\n```\n\n```python\nfrom wrenchbox.alert import DingTalk\nDingTalk('token').send('This is a warning message.')\n```\n\n```json\n200\n```\n\n### Configuration Parser\n\nRead a configuration from a YAML or JSON file.\n\n\u4ece YAML \u6216 JSON \u4e2d\u8bfb\u53d6\u4e00\u6bb5\u914d\u7f6e\u4fe1\u606f\u3002\n\n```shell\n$ python3 -u -m wrenchbox.config -h\nusage: config.py [-h] [--debug] config\n\npositional arguments:\n  config      config file\n\noptional arguments:\n  -h, --help  show this help message and exit\n  --debug     show debug information\n```\n\n```python\nfrom wrenchbox.config import Configuration\nprint(json.dumps(Configuration('wrenchbox/config.yml').__dict__, indent=2))\n```\n\n```json\n{\n  \"version\": 0,\n  \"name\": \"00000000-0000-0000-0000-000000000000\",\n  \"config\": {\n    \"key\": \"value\",\n    \"nested\": {\n      \"key\": \"value\"\n    },\n    \"list\": [\n      {\n        \"key\": \"value\"\n      },\n      {\n        \"key\": \"value\"\n      }\n    ]\n  }\n}\n```\n\nThe following configurations will be automatically generated if not provided:\n\n- `version` version of the configuration file, could be verified through `Configuration(version=(0,))`\n- `worker` ID of the worker, default: 0\n\n- `name` name of the worker, an [UUID](https://www.uuidgenerator.net/) will be generated if not provided\n\nAll configuration keys starting with `-` or `.` will be ignored (these keys should be used as audition only).\n\n### Database Hanlder\n\nAn advanced database handler based on [SQLAlchemy](https://www.sqlalchemy.org/).\n\n\u4e00\u4e2a\u57fa\u4e8e [SQLAlchemy](https://www.sqlalchemy.org/) \u5f00\u53d1\u7684\u66f4\u7b80\u5355\u7684\u6570\u636e\u5e93\u5904\u7406\u6a21\u5757\u3002\n\n```python\nfrom wrenchbox.database import DatabaseHandler\nDatabaseHandler({\n    'test': 'sqlite:///test.db'\n}, [\n    ('test', 'test')\n]).handle(\n    'test', {\n        'id': 1\n    }, {\n        'id': 1,\n        'name': str(datetime.now())\n    }, replace=True\n)\n```\n\nThe above code will insert or update a record with `id` = `1`.\n\n### Datetime Hanlder\n\nAn advanced datetime handler based on [python-dateutil](https://pypi.org/project/python-dateutil/).\n\n\u4e00\u4e2a\u57fa\u4e8e [python-dateutil](https://pypi.org/project/python-dateutil/) \u5f00\u53d1\u7684\u66f4\u7b80\u5355\u7684\u65e5\u671f\u548c\u65f6\u95f4\u5904\u7406\u5668\u3002\n\n```python\nfrom wrenchbox.datetime import T\nprint(T().timestamp()) # Get timestamp\nprint(T().format()) # Format into YYYY-MM-DD HH:MM:SS\nprint(T().format('d')) # Format into YYYY-MM-DD\nprint(T().format('t')) # Format into HH:MM:SS\n```\n\n```\n1598930603.003622\n2020-09-01 11:23:23\n2020-09-01\n11:23:23\n```\n\nWhen initialising `T`, it is possible to pass the following arguments:\n\n- `None` current timestamp will be generated\n- `datetime.datetime` will be directly used\n- `float` or `int` will be parsed as timestamp\n- `str` will be parsed through [python-dateutil](https://pypi.org/project/python-dateutil/)\n\n### Dictionary Hanlder\n\nAn advanced dictionary hander providing various tools.\n\n\u63d0\u4f9b\u4e86\u591a\u79cd\u591a\u6837\u7684\u5b57\u5178\uff08dict\uff09\u5904\u7406\u5de5\u5177\u3002\n\n```python\nfrom wrenchbox.dict import EnhancedDict\ndict_a = {\n    'a': 'a',\n    'b': {\n        'a': 1,\n        'b': {\n            'a': 1,\n            'b': [{\n                'a': 1,\n                'b': 2\n            }, {\n                'a': 1,\n                'b': {\n                    'a': 1,\n                    'b': 2\n                }\n            }]\n        }\n    }\n}\ndict_b = {\n    'a': 1,\n    'b': {\n        'b': {\n            'b': 2\n        }\n    }\n}\nprint(dict_a)\nprint(dict_b)\nprint(EnhancedDict(dict_a).search('a'))\nprint(EnhancedDict(dict_a).merge(dict_b))\nprint(EnhancedDict(dict_b).flatten())\nprint(EnhancedDict(dict_a).format(lambda x: x + 10, lambda x: isinstance(x, int)))\nprint(EnhancedDict(dict_a).remove_key('a'))\nprint(EnhancedDict(dict_a).remove_value(1))\n```\n\n```json\n{\"a\": \"a\", \"b\": {\"a\": 1, \"b\": {\"a\": 1, \"b\": [{\"a\": 1, \"b\": 2}, {\"a\": 1, \"b\": {\"a\": 1, \"b\": 2}}]}}}\n{\"a\": 1, \"b\": {\"b\": {\"b\": 2}}}\n[\"a\", 1, 1, 1, 1, 1]\n{\"a\": 1, \"b\": {\"a\": 1, \"b\": {\"a\": 1, \"b\": 2}}}\n{\"a\": 1, \"b_b_b\": 2}\n{\"a\": \"a\", \"b\": {\"a\": 11, \"b\": {\"a\": 11, \"b\": [{\"a\": 11, \"b\": 12}, {\"a\": 11, \"b\": {\"a\": 11, \"b\": 12}}]}}}\n{\"b\": {\"b\": {\"b\": [{\"b\": 2}, {\"b\": {\"b\": 2}}]}}}\n{\"a\": \"a\", \"b\": {\"b\": {\"b\": [{\"b\": 2}, {\"b\": {\"b\": 2}}]}}}\n```\n\n### IO Handler\n\nAn advanced IO handerl providing various tools.\n\n\u63d0\u4f9b\u4e86\u591a\u79cd\u591a\u6837\u7684 IO \u5de5\u5177\u3002\n\n```python\nfrom wrenchbox.io import BufferedWriter\nw = BufferedWriter(buffer=50)\nfor i in range(100):\n    w.write(i)    \nw.close()\n```\n\nThe above code will write two separate files with 50 records each.\n\n### List Hanlder\n\nAn advanced list hander providing various tools.\n\n\u63d0\u4f9b\u4e86\u591a\u79cd\u591a\u6837\u7684\u5217\u8868\uff08list\uff09\u5904\u7406\u5de5\u5177\u3002\n\n```python\nfrom wrenchbox.list import EnhancedList\nlist_a = [1, [1, [2, 3], 2], 2]\nprint(list_a)\nprint(EnhancedList(list_a).flatten()) # Flatten the list and put all sub-lists into the root level\nprint(EnhancedList(list_a).pick(lambda x: x == 1)) # Pick values based on a function\nprint(EnhancedList(list_a).format(lambda x: x + 1, lambda x: isinstance(x, (int, float)))) # Format values of the list through a filter\n```\n\n```json\n[1, [1, [2, 3], 2], 2]\n[1, 1, 2, 3, 2, 2]\n[1, [1]]\n[[[2, 3], 2], 2]\n[2, [2, [3, 4], 3], 3]\n```\n\n### Logging Tools\n\nA series of tools for logging.\n\n\u63d0\u4f9b\u4e86\u7f8e\u5316\u7684\u65e5\u5fd7\u5de5\u5177\u3002\n\n```python\nfrom wrenchbox.logging import setup_log, progress\n# Create a colorized logger and print logging messages\nsetup_log(level=logging.DEBUG, path='./log/', tag='wrenchbox')\nlogging.debug('This is a DEBUG message.')\nlogging.info('This is an INFO message.')\nlogging.warning('This is a WARNING message.')\nlogging.error('This is an ERROR message.')\nlogging.critical('This is an CRITICAL message.')\n# Show a progress bar\nfor _i in range(100):\n    progress(_i, 100)\n    time.sleep(0.02)\n```\n\n```\n[2020-09-28 10:18:40,084] This is a DEBUG message.\n[2020-09-28 10:18:40,084] This is an INFO message.\n[2020-09-28 10:18:40,084] This is a WARNING message.\n[2020-09-28 10:18:40,085] This is an ERROR message.\n[2020-09-28 10:18:40,085] This is an CRITICAL message.\n[==========================================================--] 97.0%\n```\n\nLogs are colorized with the following default config:\n\n```json\n{\n    DEBUG: \"cyan\",\n    INFO: \"green\",\n    WARNING: \"yellow\",\n    ERROR: \"red\",\n    CRITICAL: \"magenta\"\n}\n```\n\n### Number Hanlder\n\nAn advanced number hander providing various tools.\n\n\u63d0\u4f9b\u4e86\u591a\u79cd\u591a\u6837\u7684\u6570\u5b57\uff08number\uff09\u5904\u7406\u5de5\u5177\u3002\n\n```python\nfrom wrenchbox.number import EnhancedDecimal\nprint(EnhancedDecimal('3.1415926').round(Decimal('0.1'))) # Round a decimal with any unit like in excel\n```\n\n```json\n3.1\n```\n\n### Object Tools\n\nA series of objects for specific uses.\n\n\u63d0\u4f9b\u4e86\u4e00\u4e9b\u6742\u9879\u5bf9\u8c61\u3002\n\n- `Dict2StrSafe`: a class that correctly converts `self.__dict__` to a JSON string without errors\n- `Munch`: an alternative implementation of [Munch](https://github.com/Infinidat/munch)\n\n### Snowflake Code Generator\n\nGenerate a series of [Twitter Snowflake Codes](https://developer.twitter.com/en/docs/basics/twitter-ids).\n\n\u751f\u6210\u82e5\u5e72 [Twitter Snowflake Codes](https://developer.twitter.com/en/docs/basics/twitter-ids)\u3002\n\n```shell\n$ python3 -u -m wrenchbox.snowflake -h\nusage: snowflake.py [-h] [--debug] [--twepoch TWEPOCH] [-d D] -w W n\n\npositional arguments:\n  n                  # of results\n\noptional arguments:\n  -h, --help         show this help message and exit\n  --debug            show debug information\n  --twepoch TWEPOCH  twitter epoch, default: 1483228800000\n  -d D               data center id, default: 31\n  -w W               worker id, 0-31\n```\n```python\nfrom wrenchbox.snowflake import Snowflake\nprint(next(Snowflake(twepoch=1483228800000).generate(31)))\n```\n\n```json\n495059711868006400\n```\n\n### String Handler\n\nAn advanced string hander providing various tools.\n\n\u63d0\u4f9b\u4e86\u591a\u79cd\u591a\u6837\u7684\u5b57\u7b26\u4e32\uff08string\uff09\u5904\u7406\u5de5\u5177\u3002\n\n```python\nfrom wrenchbox.string import digits, random_chars, random_letters, random_numbers\nprint(digits(pi)) # Count the digits of a given float number\nprint(random_chars(3)) # Generate a random string from [a-zA-Z0-9]\nprint(random_letters(3)) # Generate a random string from [a-zA-Z]\nprint(random_numbers(3)) # Generate a random string from [0-9]\n```\n\n```\n15\n63f\nFVK\n007\n```\n\n### Text Handler\n\nA set of advanced text processing modules.\n\n\u63d0\u4f9b\u4e86\u591a\u79cd\u591a\u6837\u7684\u6587\u672c\u5904\u7406\u5de5\u5177\u3002\n\n```shell\n$ python3 -u -m wrenchbox.text -h\nusage: text.py [-h] [--debug] [--chinese] [-p P] f\n\npositional arguments:\n  f           file path\n\noptional arguments:\n  -h, --help  show this help message and exit\n  --debug     show debug information\n  --chinese   specify the input as Chinese\n  -p P        part of speech to show, only works for Chinese\n```\n\n```python\nfrom wrenchbox.text import S\nprint([i for i in S(open('test.txt', 'r').read()).v(chinese=True).words if i[1] in ('v',)])\n```\n\n```json\n[(\"\u662f\", \"v\", 8), (\"\u83b7\u53d6\", \"v\", 1)]\n```\n\n\n\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Wrenchbox",
    "version": "1.12.27",
    "split_keywords": [
        "toolbox",
        "tools"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "b4988505a63b98e023624abaa171fd5b",
                "sha256": "56bbe2938073cca726aef04aa648ba08e888f4f07536818bfd9e867c26c98186"
            },
            "downloads": -1,
            "filename": "wrenchbox-1.12.27.tar.gz",
            "has_sig": false,
            "md5_digest": "b4988505a63b98e023624abaa171fd5b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 29321,
            "upload_time": "2022-12-27T08:46:38",
            "upload_time_iso_8601": "2022-12-27T08:46:38.387252Z",
            "url": "https://files.pythonhosted.org/packages/c5/a3/f35c4e87115551be1cb6a77273dbb20318c14a6b537e150692d9713bbb2f/wrenchbox-1.12.27.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-12-27 08:46:38",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "valency",
    "github_project": "wrenchbox",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "wrenchbox"
}
        
Elapsed time: 0.02186s