cabinet


Namecabinet JSON
Version 1!2.0.0 PyPI version JSON
download
home_pagehttps://github.com/tylerjwoodfin/cabinet
SummaryEasily manage data storage and logging across repos
upload_time2025-02-09 05:39:52
maintainerNone
docs_urlNone
authorTyler Woodfin
requires_python>=3.10
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Cabinet
Cabinet is a lightweight, flexible data organization tool that lets you manage your data with the simplicity of a JSON file or the power of MongoDB - your choice. It also lets you log messages to a file of your choice and send mail from the terminal.

## ✨ Features

- More easily access your data across multiple projects
- More easily log messages to the file of your choice
- Edit MongoDB as though it were a JSON file
- Log to a file/directory of your choice without having to configure `logger` each time
- Easily send mail from the terminal

## Breaking change in 2.0.0
- `mongodb_connection_string` replaces `mongodb_username` and `mongodb_password`.

## Installation and Setup

### CLI and Python Library (Recommended)

- Install [pipx](https://pypa.github.io/pipx/) if you don't have it already

- Install `cabinet`:
```bash
pipx install cabinet
cabinet --config
```

### CLI Only
```bash
curl -s https://api.github.com/repos/tylerjwoodfin/cabinet/releases/latest \
| grep "browser_download_url" \
| cut -d '"' -f 4 \
| xargs curl -L -o cabinet.pex

sudo mv cabinet.pex /usr/local/bin/cabinet
```

## Dependencies

Outside of the standard Python library, the following packages are included as part of `pipx install cabinet`:

- `pymongo`: Provides the MongoDB client and related errors.
- `prompt_toolkit`: Provides functionality for command-line interfaces.

## Structure

- Data is stored in `~/.cabinet/data.json` or MongoDB
  - data from MongoDB is interacted with as if it were a JSON file
  - cache is written when retrieving data.
  - if cache is older than 1 hour, it is refreshed; otherwise, data is pulled from cache by default
- Logs are written to `~/.cabinet/log/LOG_DAILY_YYYY-MM-DD` by default
  - You can change the path to something other than `~/.cabinet/log` as needed by setting/modifying `~/.config/cabinet/config.json` -> `path_dir_log`

## CLI usage
```markdown
Usage: cabinet [OPTIONS]

Options:
  -h, --help            show this help message and exit
  --configure, -config  Configure
  --edit, -e            Edit Cabinet as MongoDB as a JSON file
  --edit-file EDIT_FILE, -ef EDIT_FILE
                        Edit a specific file
  --force-cache-update  Disable using the cache for MongoDB queries
  --no-create           (for -ef) Do not create file if it does not exist
  --get GET [GET ...], -g GET [GET ...]
                        Get a property from MongoDB
  --put PUT [PUT ...], -p PUT [PUT ...]
                        Put a property into MongoDB
  --remove REMOVE [REMOVE ...], -rm REMOVE [REMOVE ...]
                        Remove a property from MongoDB
  --get-file GET_FILE   Get file
  --export              Exports MongoDB to ~/.cabinet/export
  --strip               (for --get-file) Whether to strip file content whitespace
  --log LOG, -l LOG     Log a message to the default location
  --level LOG_LEVEL     (for -l) Log level [debug, info, warn, error, critical]
  --editor EDITOR       (for --edit and --edit-file) Specify an editor to use
  -v, --version         Show version number and exit

Mail:
  --mail                Sends an email
  --subject SUBJECT, -s SUBJECT
                        Email subject
  --body BODY, -b BODY  Email body
  --to TO_ADDR, -t TO_ADDR
                        The "to" email address
```

## Configuration

- Configuration data is stored in `~/.config/cabinet/config.json`.

- Upon first launch, the tool will walk you through each option.
  - `path_dir_log` is the directory where logs will be stored by default.
  - `mongodb_enabled` is a boolean that determines whether MongoDB is used.
  - `mongodb_db_name` is the name of the database you want to use by default.
  - `mongodb_connection_string` is the connection string for MongoDB.
  - `editor` is the default editor that will be used when editing files.
  - You will be prompted to enter your MongoDB credentials (optional).
  - If you choose not to use MongoDB, data will be stored in `~/.cabinet/data.json`.

- Follow these instructions to find your MongoDB connection string: [MongoDB Atlas](https://docs.atlas.mongodb.com/tutorial/connect-to-your-cluster/) or [MongoDB](https://docs.mongodb.com/manual/reference/connection-string/) (for local MongoDB, untested).

- You will be asked to configure your default editor from the list of available editors on
  your system. If this step is skipped, or an error occurs, `nano` will be used.

  You can change this with `cabinet --config` and modifying the `editor` attribute.

Your `config.json` should look something like this:
```json
{
    "path_dir_log": "/path/to/your/log/directory",
    "mongodb_db_name": "cabinet (or other name of your choice)",
    "editor": "nvim",
    "mongodb_enabled": true,
    "mongodb_connection_string": "<your connection string>",
}
```

### edit_file() shortcuts
- see example below to enable something like
  - `cabinet -ef shopping` from the terminal
    - rather than `cabinet -ef "~/path/to/shopping_list.md"`
  - or `cabinet.Cabinet().edit("shopping")`
    - rather than `cabinet.Cabinet().edit("~/path/to/whatever.md")`

file:
```json
# example only; these commands will be unique to your setup

{
  "path": {
    "edit": {
      "shopping": {
        "value": "~/path/to/whatever.md",
      },
      "todo": {
        "value": "~/path/to/whatever.md",
      }
    }
  }
}
```

set from terminal:
```bash
cabinet -p edit shopping value "~/path/to/whatever.md"
cabinet -p edit todo value "~/path/to/whatever.md"
```

### mail

- It is NEVER a good idea to store your password openly either locally or in MongoDB; for this reason, I recommend a "throwaway" account that is only used for sending emails, such as a custom domain email.
- Gmail and most other mainstream email providers won't work with this; for support, search for sending mail from your email provider with `smtplib`.
- In Cabinet (`cabinet -e`), add the `email` object to make your settings file look like this example:

file:
```json
{
    "email": {
        "from": "throwaway@example.com",
        "from_pw": "example",
        "from_name": "Cabinet (or other name of your choice)",
        "to": "destination@protonmail.com",
        "smtp_server": "example.com",
        "imap_server": "example.com",
        "port": 123
    }
}
```

set from terminal:
```bash
cabinet -p email from throwaway@example.com
cabinet -p email from_pw example
...
```

## Examples

### `put`

python:
```python
from cabinet import Cabinet

cab = Cabinet()

cab.put("employee", "Tyler", "salary", 7.25)
```

or terminal:
```bash
cabinet -p employee Tyler salary 7.25
```

results in this structure in MongoDB:
```json
{
    "employee": {
        "Tyler": {
            "salary": 7.25 # or "7.25" if done from terminal
        }
    }
}
```

### `get`

python:
```python
from cabinet import Cabinet

cab = Cabinet()

print(cab.get("employee", "Tyler", "salary"))

# or cab.get("employee", "Tyler", "salary", is_print = True)
```

or terminal:
```bash
cabinet -g employee Tyler salary
```
- optional: `--force-cache-update` to force a cache update

results in:
```bash
7.25
```

### `remove`

python:
```python
from cabinet import Cabinet

cab = Cabinet()

cab.remove("employee", "Tyler", "salary")
```

or terminal:
```bash
cabinet -rm employee Tyler salary
```

results in this structure in MongoDB:
```json
{
    "employee": {
        "tyler": {}
    }
}
```

### `edit`

terminal:
```bash

# opens file in the default editor (`cabinet --config` -> 'editor'), saves upon exit
cabinet -e

# or

cabinet --edit

# you can add an 'editor':

cabinet -e --editor=code
```

### `edit_file`

python:
```python
from cabinet import Cabinet

cab = Cabinet()

# if put("path", "edit", "shopping", "/path/to/shopping.md") has been called, this will edit the file assigned to that shortcut.

# opens file in the default editor (`cabinet --config` -> 'editor'), saves upon exit
cab.edit("shopping")

# or you can edit a file directly...
cab.edit("/path/to/shopping.md")

# you can pass an 'editor' to override the default:
cab.edit("/path/to/shopping.md", editor="nvim")
```

terminal:
```bash
# assumes path -> edit -> shopping -> path/to/shopping.md has been set
cabinet -ef shoppping

# or

cabinet -ef "/path/to/shopping.md"

# or
```

### `mail`

python:
```python

from cabinet import Mail

mail = Mail()

mail.send('Test Subject', 'Test Body')
```

terminal:
```bash
cabinet --mail --subject "Test Subject" --body "Test Body"

# or

cabinet --mail -s "Test Subject" -b "Test Body"
```

### `log`

python:
```python
from cabinet import Cabinet

cab = Cabinet()

# writes to a file named LOG_DAILY_YYYY-MM-DD in `~/.cabinet/log` inside a YYYY-MM-DD folder
# writes somewhere other than `~/.cabinet/log`, if `~/.config/cabinet/config.json` has `path_dir_log` set

cab.log("Connection timed out") # defaults to 'info' if no level is set
cab.log("This function hit a breakpoint", level="debug")
cab.log("Looks like the server is on fire", level="critical")
cab.log("This is fine", level="info")

# writes to a file named LOG_TEMPERATURE in the default log directory
cab.log("30", log_name="LOG_TEMPERATURE")

# writes to a file named LOG_TEMPERATURE in ~/weather
cab.log("30", log_name="LOG_TEMPERATURE", log_folder_path="~/weather")

    # format
    # 2021-12-29 19:29:27,896 — INFO — 30

```

terminal:
```bash
# defaults to 'info' if no level is set
cabinet -l "Connection timed out"

# -l and --log are interchangeable
cabinet --log "Connection timed out"

# change levels with --level
cabinet --log "Server is on fire" --level "critical"
```

### `logdb`

python:
```python
from cabinet import Cabinet
cab = Cabinet()
cab.logdb("Connection timed out") # logs default to a `logs` collection in MongoDB
cab.logdb("This function hit a breakpoint", level="debug", collection_name="debugging logs") # customize the collection name
cab.logdb("Temperature changed significantly", level="critical", db_name="weather") # customize the database name
cab.logdb("This is fine", level="info", cluster_name="myCluster") # customize the cluster name
```
terminal:
```bash
# defaults to 'info' if no level is set
cabinet -ldb "Connection timed out"
# -l and --log are interchangeable
cabinet --logdb "Connection timed out"
# change levels with --level
cabinet --logdb "Server is on fire" --level "critical"
```

## Disclaimers

- Although I've done quite a bit of testing, I can't guarantee everything that works on my machine will work on yours. Always back up your data to multiple places to avoid data loss.
- If you find any issues, please contact me... or get your hands dirty and raise a PR!

## Author

- Tyler Woodfin
  - [GitHub](https://www.github.com/tylerjwoodfin)
  - [LinkedIn](https://www.linkedin.com/in/tylerjwoodfin)
  - [Website](http://tyler.cloud)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/tylerjwoodfin/cabinet",
    "name": "cabinet",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": null,
    "author": "Tyler Woodfin",
    "author_email": "feedback-cabinet@tyler.cloud",
    "download_url": "https://files.pythonhosted.org/packages/85/b3/fcc6497f0719c71875a8804bd8494e16c19d44b4b45e84c30bc66edce73a/cabinet-1!2.0.0.tar.gz",
    "platform": null,
    "description": "# Cabinet\nCabinet is a lightweight, flexible data organization tool that lets you manage your data with the simplicity of a JSON file or the power of MongoDB - your choice. It also lets you log messages to a file of your choice and send mail from the terminal.\n\n## \u2728 Features\n\n- More easily access your data across multiple projects\n- More easily log messages to the file of your choice\n- Edit MongoDB as though it were a JSON file\n- Log to a file/directory of your choice without having to configure `logger` each time\n- Easily send mail from the terminal\n\n## Breaking change in 2.0.0\n- `mongodb_connection_string` replaces `mongodb_username` and `mongodb_password`.\n\n## Installation and Setup\n\n### CLI and Python Library (Recommended)\n\n- Install [pipx](https://pypa.github.io/pipx/) if you don't have it already\n\n- Install `cabinet`:\n```bash\npipx install cabinet\ncabinet --config\n```\n\n### CLI Only\n```bash\ncurl -s https://api.github.com/repos/tylerjwoodfin/cabinet/releases/latest \\\n| grep \"browser_download_url\" \\\n| cut -d '\"' -f 4 \\\n| xargs curl -L -o cabinet.pex\n\nsudo mv cabinet.pex /usr/local/bin/cabinet\n```\n\n## Dependencies\n\nOutside of the standard Python library, the following packages are included as part of `pipx install cabinet`:\n\n- `pymongo`: Provides the MongoDB client and related errors.\n- `prompt_toolkit`: Provides functionality for command-line interfaces.\n\n## Structure\n\n- Data is stored in `~/.cabinet/data.json` or MongoDB\n  - data from MongoDB is interacted with as if it were a JSON file\n  - cache is written when retrieving data.\n  - if cache is older than 1 hour, it is refreshed; otherwise, data is pulled from cache by default\n- Logs are written to `~/.cabinet/log/LOG_DAILY_YYYY-MM-DD` by default\n  - You can change the path to something other than `~/.cabinet/log` as needed by setting/modifying `~/.config/cabinet/config.json` -> `path_dir_log`\n\n## CLI usage\n```markdown\nUsage: cabinet [OPTIONS]\n\nOptions:\n  -h, --help            show this help message and exit\n  --configure, -config  Configure\n  --edit, -e            Edit Cabinet as MongoDB as a JSON file\n  --edit-file EDIT_FILE, -ef EDIT_FILE\n                        Edit a specific file\n  --force-cache-update  Disable using the cache for MongoDB queries\n  --no-create           (for -ef) Do not create file if it does not exist\n  --get GET [GET ...], -g GET [GET ...]\n                        Get a property from MongoDB\n  --put PUT [PUT ...], -p PUT [PUT ...]\n                        Put a property into MongoDB\n  --remove REMOVE [REMOVE ...], -rm REMOVE [REMOVE ...]\n                        Remove a property from MongoDB\n  --get-file GET_FILE   Get file\n  --export              Exports MongoDB to ~/.cabinet/export\n  --strip               (for --get-file) Whether to strip file content whitespace\n  --log LOG, -l LOG     Log a message to the default location\n  --level LOG_LEVEL     (for -l) Log level [debug, info, warn, error, critical]\n  --editor EDITOR       (for --edit and --edit-file) Specify an editor to use\n  -v, --version         Show version number and exit\n\nMail:\n  --mail                Sends an email\n  --subject SUBJECT, -s SUBJECT\n                        Email subject\n  --body BODY, -b BODY  Email body\n  --to TO_ADDR, -t TO_ADDR\n                        The \"to\" email address\n```\n\n## Configuration\n\n- Configuration data is stored in `~/.config/cabinet/config.json`.\n\n- Upon first launch, the tool will walk you through each option.\n  - `path_dir_log` is the directory where logs will be stored by default.\n  - `mongodb_enabled` is a boolean that determines whether MongoDB is used.\n  - `mongodb_db_name` is the name of the database you want to use by default.\n  - `mongodb_connection_string` is the connection string for MongoDB.\n  - `editor` is the default editor that will be used when editing files.\n  - You will be prompted to enter your MongoDB credentials (optional).\n  - If you choose not to use MongoDB, data will be stored in `~/.cabinet/data.json`.\n\n- Follow these instructions to find your MongoDB connection string: [MongoDB Atlas](https://docs.atlas.mongodb.com/tutorial/connect-to-your-cluster/) or [MongoDB](https://docs.mongodb.com/manual/reference/connection-string/) (for local MongoDB, untested).\n\n- You will be asked to configure your default editor from the list of available editors on\n  your system. If this step is skipped, or an error occurs, `nano` will be used.\n\n  You can change this with `cabinet --config` and modifying the `editor` attribute.\n\nYour `config.json` should look something like this:\n```json\n{\n    \"path_dir_log\": \"/path/to/your/log/directory\",\n    \"mongodb_db_name\": \"cabinet (or other name of your choice)\",\n    \"editor\": \"nvim\",\n    \"mongodb_enabled\": true,\n    \"mongodb_connection_string\": \"<your connection string>\",\n}\n```\n\n### edit_file() shortcuts\n- see example below to enable something like\n  - `cabinet -ef shopping` from the terminal\n    - rather than `cabinet -ef \"~/path/to/shopping_list.md\"`\n  - or `cabinet.Cabinet().edit(\"shopping\")`\n    - rather than `cabinet.Cabinet().edit(\"~/path/to/whatever.md\")`\n\nfile:\n```json\n# example only; these commands will be unique to your setup\n\n{\n  \"path\": {\n    \"edit\": {\n      \"shopping\": {\n        \"value\": \"~/path/to/whatever.md\",\n      },\n      \"todo\": {\n        \"value\": \"~/path/to/whatever.md\",\n      }\n    }\n  }\n}\n```\n\nset from terminal:\n```bash\ncabinet -p edit shopping value \"~/path/to/whatever.md\"\ncabinet -p edit todo value \"~/path/to/whatever.md\"\n```\n\n### mail\n\n- It is NEVER a good idea to store your password openly either locally or in MongoDB; for this reason, I recommend a \"throwaway\" account that is only used for sending emails, such as a custom domain email.\n- Gmail and most other mainstream email providers won't work with this; for support, search for sending mail from your email provider with `smtplib`.\n- In Cabinet (`cabinet -e`), add the `email` object to make your settings file look like this example:\n\nfile:\n```json\n{\n    \"email\": {\n        \"from\": \"throwaway@example.com\",\n        \"from_pw\": \"example\",\n        \"from_name\": \"Cabinet (or other name of your choice)\",\n        \"to\": \"destination@protonmail.com\",\n        \"smtp_server\": \"example.com\",\n        \"imap_server\": \"example.com\",\n        \"port\": 123\n    }\n}\n```\n\nset from terminal:\n```bash\ncabinet -p email from throwaway@example.com\ncabinet -p email from_pw example\n...\n```\n\n## Examples\n\n### `put`\n\npython:\n```python\nfrom cabinet import Cabinet\n\ncab = Cabinet()\n\ncab.put(\"employee\", \"Tyler\", \"salary\", 7.25)\n```\n\nor terminal:\n```bash\ncabinet -p employee Tyler salary 7.25\n```\n\nresults in this structure in MongoDB:\n```json\n{\n    \"employee\": {\n        \"Tyler\": {\n            \"salary\": 7.25 # or \"7.25\" if done from terminal\n        }\n    }\n}\n```\n\n### `get`\n\npython:\n```python\nfrom cabinet import Cabinet\n\ncab = Cabinet()\n\nprint(cab.get(\"employee\", \"Tyler\", \"salary\"))\n\n# or cab.get(\"employee\", \"Tyler\", \"salary\", is_print = True)\n```\n\nor terminal:\n```bash\ncabinet -g employee Tyler salary\n```\n- optional: `--force-cache-update` to force a cache update\n\nresults in:\n```bash\n7.25\n```\n\n### `remove`\n\npython:\n```python\nfrom cabinet import Cabinet\n\ncab = Cabinet()\n\ncab.remove(\"employee\", \"Tyler\", \"salary\")\n```\n\nor terminal:\n```bash\ncabinet -rm employee Tyler salary\n```\n\nresults in this structure in MongoDB:\n```json\n{\n    \"employee\": {\n        \"tyler\": {}\n    }\n}\n```\n\n### `edit`\n\nterminal:\n```bash\n\n# opens file in the default editor (`cabinet --config` -> 'editor'), saves upon exit\ncabinet -e\n\n# or\n\ncabinet --edit\n\n# you can add an 'editor':\n\ncabinet -e --editor=code\n```\n\n### `edit_file`\n\npython:\n```python\nfrom cabinet import Cabinet\n\ncab = Cabinet()\n\n# if put(\"path\", \"edit\", \"shopping\", \"/path/to/shopping.md\") has been called, this will edit the file assigned to that shortcut.\n\n# opens file in the default editor (`cabinet --config` -> 'editor'), saves upon exit\ncab.edit(\"shopping\")\n\n# or you can edit a file directly...\ncab.edit(\"/path/to/shopping.md\")\n\n# you can pass an 'editor' to override the default:\ncab.edit(\"/path/to/shopping.md\", editor=\"nvim\")\n```\n\nterminal:\n```bash\n# assumes path -> edit -> shopping -> path/to/shopping.md has been set\ncabinet -ef shoppping\n\n# or\n\ncabinet -ef \"/path/to/shopping.md\"\n\n# or\n```\n\n### `mail`\n\npython:\n```python\n\nfrom cabinet import Mail\n\nmail = Mail()\n\nmail.send('Test Subject', 'Test Body')\n```\n\nterminal:\n```bash\ncabinet --mail --subject \"Test Subject\" --body \"Test Body\"\n\n# or\n\ncabinet --mail -s \"Test Subject\" -b \"Test Body\"\n```\n\n### `log`\n\npython:\n```python\nfrom cabinet import Cabinet\n\ncab = Cabinet()\n\n# writes to a file named LOG_DAILY_YYYY-MM-DD in `~/.cabinet/log` inside a YYYY-MM-DD folder\n# writes somewhere other than `~/.cabinet/log`, if `~/.config/cabinet/config.json` has `path_dir_log` set\n\ncab.log(\"Connection timed out\") # defaults to 'info' if no level is set\ncab.log(\"This function hit a breakpoint\", level=\"debug\")\ncab.log(\"Looks like the server is on fire\", level=\"critical\")\ncab.log(\"This is fine\", level=\"info\")\n\n# writes to a file named LOG_TEMPERATURE in the default log directory\ncab.log(\"30\", log_name=\"LOG_TEMPERATURE\")\n\n# writes to a file named LOG_TEMPERATURE in ~/weather\ncab.log(\"30\", log_name=\"LOG_TEMPERATURE\", log_folder_path=\"~/weather\")\n\n    # format\n    # 2021-12-29 19:29:27,896 \u2014 INFO \u2014 30\n\n```\n\nterminal:\n```bash\n# defaults to 'info' if no level is set\ncabinet -l \"Connection timed out\"\n\n# -l and --log are interchangeable\ncabinet --log \"Connection timed out\"\n\n# change levels with --level\ncabinet --log \"Server is on fire\" --level \"critical\"\n```\n\n### `logdb`\n\npython:\n```python\nfrom cabinet import Cabinet\ncab = Cabinet()\ncab.logdb(\"Connection timed out\") # logs default to a `logs` collection in MongoDB\ncab.logdb(\"This function hit a breakpoint\", level=\"debug\", collection_name=\"debugging logs\") # customize the collection name\ncab.logdb(\"Temperature changed significantly\", level=\"critical\", db_name=\"weather\") # customize the database name\ncab.logdb(\"This is fine\", level=\"info\", cluster_name=\"myCluster\") # customize the cluster name\n```\nterminal:\n```bash\n# defaults to 'info' if no level is set\ncabinet -ldb \"Connection timed out\"\n# -l and --log are interchangeable\ncabinet --logdb \"Connection timed out\"\n# change levels with --level\ncabinet --logdb \"Server is on fire\" --level \"critical\"\n```\n\n## Disclaimers\n\n- Although I've done quite a bit of testing, I can't guarantee everything that works on my machine will work on yours. Always back up your data to multiple places to avoid data loss.\n- If you find any issues, please contact me... or get your hands dirty and raise a PR!\n\n## Author\n\n- Tyler Woodfin\n  - [GitHub](https://www.github.com/tylerjwoodfin)\n  - [LinkedIn](https://www.linkedin.com/in/tylerjwoodfin)\n  - [Website](http://tyler.cloud)\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Easily manage data storage and logging across repos",
    "version": "1!2.0.0",
    "project_urls": {
        "Homepage": "https://github.com/tylerjwoodfin/cabinet",
        "bug tracker": "https://github.com/tylerjwoodfin/cabinet/issues"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "834c8bbda8b76111cf026958fc4592c9d0a30ed9c8126c073279daefbf6ab90d",
                "md5": "859bf32b70b289929bf5198f174d59fa",
                "sha256": "447f86fcc9c8d4d51dcf2c1bf08931fdf05855847562b8f5ef70add519a4d6c4"
            },
            "downloads": -1,
            "filename": "cabinet-1!2.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "859bf32b70b289929bf5198f174d59fa",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 23213,
            "upload_time": "2025-02-09T05:39:51",
            "upload_time_iso_8601": "2025-02-09T05:39:51.212933Z",
            "url": "https://files.pythonhosted.org/packages/83/4c/8bbda8b76111cf026958fc4592c9d0a30ed9c8126c073279daefbf6ab90d/cabinet-1!2.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "85b3fcc6497f0719c71875a8804bd8494e16c19d44b4b45e84c30bc66edce73a",
                "md5": "3cbb86a0f8d828ac746203beea7c4048",
                "sha256": "2c91e040971050977a283cb5be0a902015de8c7a526fcfb7776fc2e6bae75d4d"
            },
            "downloads": -1,
            "filename": "cabinet-1!2.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "3cbb86a0f8d828ac746203beea7c4048",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 25231,
            "upload_time": "2025-02-09T05:39:52",
            "upload_time_iso_8601": "2025-02-09T05:39:52.467284Z",
            "url": "https://files.pythonhosted.org/packages/85/b3/fcc6497f0719c71875a8804bd8494e16c19d44b4b45e84c30bc66edce73a/cabinet-1!2.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-09 05:39:52",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "tylerjwoodfin",
    "github_project": "cabinet",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "cabinet"
}
        
Elapsed time: 0.46373s