cain


Namecain JSON
Version 1.1.1 PyPI version JSON
download
home_pagehttps://github.com/Animenosekai/cain
SummaryA small yet powerful data format ✨
upload_time2023-08-25 10:11:44
maintainerAnimenosekai
docs_urlNone
authorAnimenosekai
requires_python>=3.9,<4.0
licenseMIT
keywords animenosekai cain data format
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Cain

<img align="right" src="./assets/cain.png" height="220px">

***A small yet powerful data format ✨***

<br>
<br>

[![PyPI version](https://badge.fury.io/py/cain.svg)](https://pypi.org/project/cain/)
[![Downloads](https://static.pepy.tech/personalized-badge/cain?period=total&units=international_system&left_color=grey&right_color=blue&left_text=Total%20Downloads)](https://pepy.tech/project/cain)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/cain)](https://pypistats.org/packages/cain)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cain)](https://pypi.org/project/cain/)
[![PyPI - Status](https://img.shields.io/pypi/status/cain)](https://pypi.org/project/cain/)
[![GitHub - License](https://img.shields.io/github/license/Animenosekai/cain)](https://github.com/Animenosekai/cain/blob/master/LICENSE)
[![GitHub top language](https://img.shields.io/github/languages/top/Animenosekai/cain)](https://github.com/Animenosekai/cain)
[![CodeQL Checks Badge](https://github.com/Animenosekai/cain/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/Animenosekai/cain/actions/workflows/codeql-analysis.yml)
![Code Size](https://img.shields.io/github/languages/code-size/Animenosekai/cain)
![Repo Size](https://img.shields.io/github/repo-size/Animenosekai/cain)
![Issues](https://img.shields.io/github/issues/Animenosekai/cain)

## Index

- [Index](#index)
- [Purpose](#purpose)
  - [Comparison](#comparison)
    - [JSON](#json)
    - [Cain](#cain-1)
- [Getting Started](#getting-started)
  - [Prerequisites](#prerequisites)
- [Installing](#installing)
  - [Option 1: From PyPI](#option-1-from-pypi)
  - [Option 2: From Git](#option-2-from-git)
- [Usage](#usage)
  - [Python](#python)
    - [Encoding](#encoding)
    - [Decoding](#decoding)
    - [Handling Schemas](#handling-schemas)
      - [Encoding](#encoding-1)
      - [Decoding](#decoding-1)
    - [Custom Encoder](#custom-encoder)
  - [CLI](#cli)
    - [Examples](#examples)
- [Deployment](#deployment)
- [Contributing](#contributing)
- [Authors](#authors)
- [Licensing](#licensing)

## Purpose

Cain is a new data interchange format which aims at providing the smallest possible size to encode data.

It is based on pre-defined schemas which leverages the need to specify it within the final encoded data.

> **Note**  
> Look at the [*SPECIFICATIONS*](https://github.com/Animenosekai/cain/blob/main/SPECIFICATIONS.md) file for more information on the purpose and idea behind this project.

### Comparison

For example, we consider the following object:

```python
{
    "b": 3,
    "c": 5.5,
    "d": True,
    "e": {
        "f": False,
        # "g": b"Hello world"
        "h": "HELLO WORLD",
        "i": "Hi!",
        "j": [1, 2, 3, 1, 1],
        "k": (1, "hello", True),
        "l": None,
        "m": "Yay",
        "n": "Hi",
        "o": 2,
        "p": None
    }
}
```

#### JSON

This is the expected result from a minified JSON encoding:

```json
{"b":3,"c":5.5,"d":true,"e":{"f":false,"h":"HELLO WORLD","i":"Hi!","j":[1,2,3,1,1],"k":[1,"hello",true],"l":null,"m":"Yay","n":"Hi","o":2,"p":null}}
```

#### Cain

This is the expected result from the Cain data format:

```cain
\x00\x00\x03\x00\x00\xb0@\x01\x00\x00HELLO WORLD\x00Hi!\x00\x00\x05\x00\x00\x00\x01\x00\x02\x00\x03\x00\x01\x00\x01\x00\x00\x01hello\x00\x01\x00\x01\x00Yay\x00\x00Hi\x00\x01\x00\x02
```

> **Note**  
> This is 56.76% smaller than the JSON version ✨

***Moreover, objects which can't be encoded using JSON (bytes, set, range, etc.) or wrongly encoded using JSON (ex: tuple) are working out of the box with Cain!***

## Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

### Prerequisites

You will need Python 3 to use this module

```bash
Minimum required versions: 3.9
Incompatible versions:     2
```

Always check if your Python version works with `cain` before using it in production.

## Installing

### Option 1: From PyPI

```bash
pip install --upgrade cain
```

> This will install the latest version from PyPI

### Option 2: From Git

```bash
pip install --upgrade git+https://github.com/Animenosekai/cain.git
```

> This will install the latest development version from the git repository

You can check if you successfully installed it by printing out its version:

```bash
$ cain --version
1.1
```

## Usage

### Python

The main entry point ([cain.py](./cain/cain.py)) provides an API familiar to users of the standard library `json` module. The different datatype also present a very pythonic way of handling data to keep a nice and clean codebase.

#### Encoding

Encoding basic Python object hierarchies:

```python
>>> import cain
>>> from cain.types import Object, Optional
>>> cain.dumps({"a": 2}, Object[{"a": int}])
b'\x00\x00\x02'
>>> class TestObject(Object):
...     bar: tuple[str, Optional[str], float, int]
...
>>> cain.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}], list[str, TestObject])
b'\x00foo\x00\x00\x00baz\x00\x00\x00\x00\x80?\x00\x02'
>>> print(cain.dumps("\"foo\bar", str))
b'"foo\x08ar\x00'
>>> print(cain.dumps('\u1234', str))
b'\xe1\x88\xb4\x00'
>>> print(cain.dumps('\\', str))
b'\\\x00'
>>> schema = list[str, Object[{"bar": tuple[str, Optional[str], float, int]}]]
>>> with open('test.cain', 'w+b') as fp:
...     cain.dump(['foo', {'bar': ('baz', None, 1.0, 2)}], fp, schema)
...
>>> from cain.types import Int
>>> from cain.types.numbers import unsigned
>>> Int[unsigned].encode(4)
b'\x00\x04'
```

You can also add a header using the `include_header` parameter to add a header containing the schema for the encoding data. This gives a more portable output but increases its size.

#### Decoding

Decoding Cain:

```python
>>> import cain
>>> from cain.types import Optional, Object
>>> schema = list[str, Object[{"bar": tuple[str, Optional[str], float, int]}]]
>>> cain.loads(b'\x00foo\x00\x00\x00baz\x00\x00\x00\x00\x80?\x00\x02', schema)
['foo', {'bar': ('baz', None, 1.0, 2)}]
>>> with open('test.cain', 'r+b') as fp:
...     cain.load(fp, schema)
...
['foo', {'bar': ('baz', None, 1.0, 2)}]
>>> from cain.types import Int
>>> from cain.types.numbers import unsigned
>>> Int[unsigned].decode(b'\x00\x04')
4
```

#### Handling Schemas

If you want to dynamically encode/decode data with the Cain format, it is also possible to encode/decode the schema.

This is especially useful when developing a public API for example.

##### Encoding

```python
>>> import cain
>>> from cain.types import Object, Optional
>>> cain.encode_schema(Object[{"a": int}])
b'\x00\x00\x01\x00\x00a\x00\x00\x01\x00\x00\x01\x03\x00\x01\x02\x00\x00\x00\x00\x06\x00\x00\x00\x00\x16'
>>> class TestObject(Object):
...     bar: tuple[str, Optional[str], float, int]
...
>>> cain.encode_schema(list[str, TestObject])
b'\x01\x02\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00...\x00\x16\x01\x00TestObject\x00\x00\x00'
```

##### Decoding

```python
>>> import cain
>>> cain.decode_schema(b'\x00\x00\x01\x00\x00a\x00\x00\x01\x00\x00\x01\x03\x00\x01\x02\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x16\x00')
Object<{'a': Int}>
>>> cain.decode_schema(b'\x01\x02\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00...\x00\x16\x01\x00TestObject\x00\x00\x00')
Array[String, TestObject]
```

#### Custom Encoder

You can also create your own encoders:

```python
>>> import typing
>>> from cain.model import Datatype
>>> class MyObject(Datatype):
...     @classmethod         # *args contains the args passed here : MyObject[args]
...     def _encode(cls, value: typing.Any,*args) -> bytes:
...         ... #  your custom encoding
...         return b'encoded data'
...     #
...     @classmethod
...     def _decode(cls, value: bytes, *args) -> typing.Tuple[typing.Any, bytes]:
...         ... #  `value` contains more than just the value you should decode
...         ... #  try to only decode the first few bytes
...         ... #  your custom decoding
...         return 'decoded data', value # the rest of the value that you didn't decode
... # you can now use `MyObject` in your schemas and encode/decode from it
```

> **Warning**  
> Keep in mind that custom datatypes outside of subclasses of `Object` won't be able to be encoded by the Type encoder (used in schema headers for example)

### CLI

Cain has a pretty complete command-line interface, which lets you manipulate and interact with the Cain data format easily.

For more information, head over to your console and enter:

```bash
cain --help
```

Or

```bash
cain <action> --help
```

#### Examples

> Example usage of the CLI

Preparing the schema:

```python
# test.py
from cain import Object
class Test(Object):
    username: str
    favorite_number: int
```

Trying to encode with a Python schema:

```bash
cain encode '{"username": "Anise", "favorite_number": 2}' --schema="test.py" --schema-name="Test" --include-header --output="test.cain"
```

Trying to decode the previous file:

```bash
$ cain decode test.cain
{
    "favorite_number": 2,
    "username": "Anise"
}
```

Looking up at its schema:

```bash
$ cain schema lookup test.cain --schema-header
{
    "index": 22,
    "name": "Test",
    "annotations_keys": [
        "username",
        "favorite_number"
    ],
    "annotations_values": [
        {
            "index": 26,
            "name": null,
            "annotations_keys": [],
            "annotations_values": [],
            "arguments": [],
            "datatype": "String"
        },
        {
            "index": 6,
            "name": null,
            "annotations_keys": [],
            "annotations_values": [],
            "arguments": [],
            "datatype": "Int"
        }
    ],
    "arguments": [],
    "datatype": "Object"
}
```

Exporting its schema:

```bash
cain schema export test.cain --schema-header --output test.cainschema
```

Trying to encode another object with the exported schema:

```bash
$ cain encode '{"username": "yay", "favorite_number": 3}' --schema=test.cainschema
\x00\x00\x03yay\x00
```

Encoding "Hello world":

```bash
$ cain encode '"Hello world"' --schema="str" --schema-eval
Hello world\x00
$ cain encode '["Hello", "world"]' --schema="list[str]" --schema-eval
\x00\x02\x00\x00Hello\x00world\x00
```

## Deployment

This module is currently in development and might contain bugs.

This comes with a few disadvantages (for example, it takes a longer time to encode objects with Cain than with the standard `json` module) but this is expected to improve over time.

Please verify and test the module thoroughly before releasing anything at a production stage.

Feel free to report any issue you might encounter on Cain's GitHub page.

## Contributing

Pull requests are welcome. For major changes, please open a discussion first to discuss what you would like to change.

Please make sure to update the tests accordingly.

## Authors

- **Animenosekai** - *Initial work* - [Animenosekai](https://github.com/Animenosekai)

## Licensing

This software is licensed under the MIT License. See the [*LICENSE*](./LICENSE) file for more information.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Animenosekai/cain",
    "name": "cain",
    "maintainer": "Animenosekai",
    "docs_url": null,
    "requires_python": ">=3.9,<4.0",
    "maintainer_email": "animenosekai.mail@gmail.com",
    "keywords": "animenosekai,cain,data,format",
    "author": "Animenosekai",
    "author_email": "animenosekai.mail@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/47/c2/a72773ae6f837b9f3c46cce4ffbf31d9dab99a42f9c63b07cddee25a9b12/cain-1.1.1.tar.gz",
    "platform": null,
    "description": "# Cain\n\n<img align=\"right\" src=\"./assets/cain.png\" height=\"220px\">\n\n***A small yet powerful data format \u2728***\n\n<br>\n<br>\n\n[![PyPI version](https://badge.fury.io/py/cain.svg)](https://pypi.org/project/cain/)\n[![Downloads](https://static.pepy.tech/personalized-badge/cain?period=total&units=international_system&left_color=grey&right_color=blue&left_text=Total%20Downloads)](https://pepy.tech/project/cain)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/cain)](https://pypistats.org/packages/cain)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cain)](https://pypi.org/project/cain/)\n[![PyPI - Status](https://img.shields.io/pypi/status/cain)](https://pypi.org/project/cain/)\n[![GitHub - License](https://img.shields.io/github/license/Animenosekai/cain)](https://github.com/Animenosekai/cain/blob/master/LICENSE)\n[![GitHub top language](https://img.shields.io/github/languages/top/Animenosekai/cain)](https://github.com/Animenosekai/cain)\n[![CodeQL Checks Badge](https://github.com/Animenosekai/cain/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/Animenosekai/cain/actions/workflows/codeql-analysis.yml)\n![Code Size](https://img.shields.io/github/languages/code-size/Animenosekai/cain)\n![Repo Size](https://img.shields.io/github/repo-size/Animenosekai/cain)\n![Issues](https://img.shields.io/github/issues/Animenosekai/cain)\n\n## Index\n\n- [Index](#index)\n- [Purpose](#purpose)\n  - [Comparison](#comparison)\n    - [JSON](#json)\n    - [Cain](#cain-1)\n- [Getting Started](#getting-started)\n  - [Prerequisites](#prerequisites)\n- [Installing](#installing)\n  - [Option 1: From PyPI](#option-1-from-pypi)\n  - [Option 2: From Git](#option-2-from-git)\n- [Usage](#usage)\n  - [Python](#python)\n    - [Encoding](#encoding)\n    - [Decoding](#decoding)\n    - [Handling Schemas](#handling-schemas)\n      - [Encoding](#encoding-1)\n      - [Decoding](#decoding-1)\n    - [Custom Encoder](#custom-encoder)\n  - [CLI](#cli)\n    - [Examples](#examples)\n- [Deployment](#deployment)\n- [Contributing](#contributing)\n- [Authors](#authors)\n- [Licensing](#licensing)\n\n## Purpose\n\nCain is a new data interchange format which aims at providing the smallest possible size to encode data.\n\nIt is based on pre-defined schemas which leverages the need to specify it within the final encoded data.\n\n> **Note**  \n> Look at the [*SPECIFICATIONS*](https://github.com/Animenosekai/cain/blob/main/SPECIFICATIONS.md) file for more information on the purpose and idea behind this project.\n\n### Comparison\n\nFor example, we consider the following object:\n\n```python\n{\n    \"b\": 3,\n    \"c\": 5.5,\n    \"d\": True,\n    \"e\": {\n        \"f\": False,\n        # \"g\": b\"Hello world\"\n        \"h\": \"HELLO WORLD\",\n        \"i\": \"Hi!\",\n        \"j\": [1, 2, 3, 1, 1],\n        \"k\": (1, \"hello\", True),\n        \"l\": None,\n        \"m\": \"Yay\",\n        \"n\": \"Hi\",\n        \"o\": 2,\n        \"p\": None\n    }\n}\n```\n\n#### JSON\n\nThis is the expected result from a minified JSON encoding:\n\n```json\n{\"b\":3,\"c\":5.5,\"d\":true,\"e\":{\"f\":false,\"h\":\"HELLO WORLD\",\"i\":\"Hi!\",\"j\":[1,2,3,1,1],\"k\":[1,\"hello\",true],\"l\":null,\"m\":\"Yay\",\"n\":\"Hi\",\"o\":2,\"p\":null}}\n```\n\n#### Cain\n\nThis is the expected result from the Cain data format:\n\n```cain\n\\x00\\x00\\x03\\x00\\x00\\xb0@\\x01\\x00\\x00HELLO WORLD\\x00Hi!\\x00\\x00\\x05\\x00\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x01\\x00\\x01\\x00\\x00\\x01hello\\x00\\x01\\x00\\x01\\x00Yay\\x00\\x00Hi\\x00\\x01\\x00\\x02\n```\n\n> **Note**  \n> This is 56.76% smaller than the JSON version \u2728\n\n***Moreover, objects which can't be encoded using JSON (bytes, set, range, etc.) or wrongly encoded using JSON (ex: tuple) are working out of the box with Cain!***\n\n## Getting Started\n\nThese instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.\n\n### Prerequisites\n\nYou will need Python 3 to use this module\n\n```bash\nMinimum required versions: 3.9\nIncompatible versions:     2\n```\n\nAlways check if your Python version works with `cain` before using it in production.\n\n## Installing\n\n### Option 1: From PyPI\n\n```bash\npip install --upgrade cain\n```\n\n> This will install the latest version from PyPI\n\n### Option 2: From Git\n\n```bash\npip install --upgrade git+https://github.com/Animenosekai/cain.git\n```\n\n> This will install the latest development version from the git repository\n\nYou can check if you successfully installed it by printing out its version:\n\n```bash\n$ cain --version\n1.1\n```\n\n## Usage\n\n### Python\n\nThe main entry point ([cain.py](./cain/cain.py)) provides an API familiar to users of the standard library `json` module. The different datatype also present a very pythonic way of handling data to keep a nice and clean codebase.\n\n#### Encoding\n\nEncoding basic Python object hierarchies:\n\n```python\n>>> import cain\n>>> from cain.types import Object, Optional\n>>> cain.dumps({\"a\": 2}, Object[{\"a\": int}])\nb'\\x00\\x00\\x02'\n>>> class TestObject(Object):\n...     bar: tuple[str, Optional[str], float, int]\n...\n>>> cain.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}], list[str, TestObject])\nb'\\x00foo\\x00\\x00\\x00baz\\x00\\x00\\x00\\x00\\x80?\\x00\\x02'\n>>> print(cain.dumps(\"\\\"foo\\bar\", str))\nb'\"foo\\x08ar\\x00'\n>>> print(cain.dumps('\\u1234', str))\nb'\\xe1\\x88\\xb4\\x00'\n>>> print(cain.dumps('\\\\', str))\nb'\\\\\\x00'\n>>> schema = list[str, Object[{\"bar\": tuple[str, Optional[str], float, int]}]]\n>>> with open('test.cain', 'w+b') as fp:\n...     cain.dump(['foo', {'bar': ('baz', None, 1.0, 2)}], fp, schema)\n...\n>>> from cain.types import Int\n>>> from cain.types.numbers import unsigned\n>>> Int[unsigned].encode(4)\nb'\\x00\\x04'\n```\n\nYou can also add a header using the `include_header` parameter to add a header containing the schema for the encoding data. This gives a more portable output but increases its size.\n\n#### Decoding\n\nDecoding Cain:\n\n```python\n>>> import cain\n>>> from cain.types import Optional, Object\n>>> schema = list[str, Object[{\"bar\": tuple[str, Optional[str], float, int]}]]\n>>> cain.loads(b'\\x00foo\\x00\\x00\\x00baz\\x00\\x00\\x00\\x00\\x80?\\x00\\x02', schema)\n['foo', {'bar': ('baz', None, 1.0, 2)}]\n>>> with open('test.cain', 'r+b') as fp:\n...     cain.load(fp, schema)\n...\n['foo', {'bar': ('baz', None, 1.0, 2)}]\n>>> from cain.types import Int\n>>> from cain.types.numbers import unsigned\n>>> Int[unsigned].decode(b'\\x00\\x04')\n4\n```\n\n#### Handling Schemas\n\nIf you want to dynamically encode/decode data with the Cain format, it is also possible to encode/decode the schema.\n\nThis is especially useful when developing a public API for example.\n\n##### Encoding\n\n```python\n>>> import cain\n>>> from cain.types import Object, Optional\n>>> cain.encode_schema(Object[{\"a\": int}])\nb'\\x00\\x00\\x01\\x00\\x00a\\x00\\x00\\x01\\x00\\x00\\x01\\x03\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x16'\n>>> class TestObject(Object):\n...     bar: tuple[str, Optional[str], float, int]\n...\n>>> cain.encode_schema(list[str, TestObject])\nb'\\x01\\x02\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00...\\x00\\x16\\x01\\x00TestObject\\x00\\x00\\x00'\n```\n\n##### Decoding\n\n```python\n>>> import cain\n>>> cain.decode_schema(b'\\x00\\x00\\x01\\x00\\x00a\\x00\\x00\\x01\\x00\\x00\\x01\\x03\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x16\\x00')\nObject<{'a': Int}>\n>>> cain.decode_schema(b'\\x01\\x02\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00...\\x00\\x16\\x01\\x00TestObject\\x00\\x00\\x00')\nArray[String, TestObject]\n```\n\n#### Custom Encoder\n\nYou can also create your own encoders:\n\n```python\n>>> import typing\n>>> from cain.model import Datatype\n>>> class MyObject(Datatype):\n...     @classmethod         # *args contains the args passed here : MyObject[args]\n...     def _encode(cls, value: typing.Any,*args) -> bytes:\n...         ... #  your custom encoding\n...         return b'encoded data'\n...     #\n...     @classmethod\n...     def _decode(cls, value: bytes, *args) -> typing.Tuple[typing.Any, bytes]:\n...         ... #  `value` contains more than just the value you should decode\n...         ... #  try to only decode the first few bytes\n...         ... #  your custom decoding\n...         return 'decoded data', value # the rest of the value that you didn't decode\n... # you can now use `MyObject` in your schemas and encode/decode from it\n```\n\n> **Warning**  \n> Keep in mind that custom datatypes outside of subclasses of `Object` won't be able to be encoded by the Type encoder (used in schema headers for example)\n\n### CLI\n\nCain has a pretty complete command-line interface, which lets you manipulate and interact with the Cain data format easily.\n\nFor more information, head over to your console and enter:\n\n```bash\ncain --help\n```\n\nOr\n\n```bash\ncain <action> --help\n```\n\n#### Examples\n\n> Example usage of the CLI\n\nPreparing the schema:\n\n```python\n# test.py\nfrom cain import Object\nclass Test(Object):\n    username: str\n    favorite_number: int\n```\n\nTrying to encode with a Python schema:\n\n```bash\ncain encode '{\"username\": \"Anise\", \"favorite_number\": 2}' --schema=\"test.py\" --schema-name=\"Test\" --include-header --output=\"test.cain\"\n```\n\nTrying to decode the previous file:\n\n```bash\n$ cain decode test.cain\n{\n    \"favorite_number\": 2,\n    \"username\": \"Anise\"\n}\n```\n\nLooking up at its schema:\n\n```bash\n$ cain schema lookup test.cain --schema-header\n{\n    \"index\": 22,\n    \"name\": \"Test\",\n    \"annotations_keys\": [\n        \"username\",\n        \"favorite_number\"\n    ],\n    \"annotations_values\": [\n        {\n            \"index\": 26,\n            \"name\": null,\n            \"annotations_keys\": [],\n            \"annotations_values\": [],\n            \"arguments\": [],\n            \"datatype\": \"String\"\n        },\n        {\n            \"index\": 6,\n            \"name\": null,\n            \"annotations_keys\": [],\n            \"annotations_values\": [],\n            \"arguments\": [],\n            \"datatype\": \"Int\"\n        }\n    ],\n    \"arguments\": [],\n    \"datatype\": \"Object\"\n}\n```\n\nExporting its schema:\n\n```bash\ncain schema export test.cain --schema-header --output test.cainschema\n```\n\nTrying to encode another object with the exported schema:\n\n```bash\n$ cain encode '{\"username\": \"yay\", \"favorite_number\": 3}' --schema=test.cainschema\n\\x00\\x00\\x03yay\\x00\n```\n\nEncoding \"Hello world\":\n\n```bash\n$ cain encode '\"Hello world\"' --schema=\"str\" --schema-eval\nHello world\\x00\n$ cain encode '[\"Hello\", \"world\"]' --schema=\"list[str]\" --schema-eval\n\\x00\\x02\\x00\\x00Hello\\x00world\\x00\n```\n\n## Deployment\n\nThis module is currently in development and might contain bugs.\n\nThis comes with a few disadvantages (for example, it takes a longer time to encode objects with Cain than with the standard `json` module) but this is expected to improve over time.\n\nPlease verify and test the module thoroughly before releasing anything at a production stage.\n\nFeel free to report any issue you might encounter on Cain's GitHub page.\n\n## Contributing\n\nPull requests are welcome. For major changes, please open a discussion first to discuss what you would like to change.\n\nPlease make sure to update the tests accordingly.\n\n## Authors\n\n- **Animenosekai** - *Initial work* - [Animenosekai](https://github.com/Animenosekai)\n\n## Licensing\n\nThis software is licensed under the MIT License. See the [*LICENSE*](./LICENSE) file for more information.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A small yet powerful data format \u2728",
    "version": "1.1.1",
    "project_urls": {
        "Documentation": "https://github.com/Animenosekai/cain/blob/main/README.md",
        "Homepage": "https://github.com/Animenosekai/cain",
        "Issue Tracker": "https://github.com/Animenosekai/cain/issues",
        "Repository": "https://github.com/Animenosekai/cain"
    },
    "split_keywords": [
        "animenosekai",
        "cain",
        "data",
        "format"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8f1f51b560d4006603e525a57468086ee33ac9142f70fb3d2254ea4f8ea29d04",
                "md5": "8a8e9aaa7b99ad4cbe12a31ed90c713f",
                "sha256": "67528e6f70ae725befe831824fc35a741c160fe4204afdc764b2dc35348d80d3"
            },
            "downloads": -1,
            "filename": "cain-1.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8a8e9aaa7b99ad4cbe12a31ed90c713f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9,<4.0",
            "size": 35552,
            "upload_time": "2023-08-25T10:11:42",
            "upload_time_iso_8601": "2023-08-25T10:11:42.581699Z",
            "url": "https://files.pythonhosted.org/packages/8f/1f/51b560d4006603e525a57468086ee33ac9142f70fb3d2254ea4f8ea29d04/cain-1.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "47c2a72773ae6f837b9f3c46cce4ffbf31d9dab99a42f9c63b07cddee25a9b12",
                "md5": "342942163900501b028368052383b405",
                "sha256": "e2faeee41ad97de527e2d3bc459b3153da5d55f4da4a55d10136bdb91c77e9cb"
            },
            "downloads": -1,
            "filename": "cain-1.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "342942163900501b028368052383b405",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9,<4.0",
            "size": 28983,
            "upload_time": "2023-08-25T10:11:44",
            "upload_time_iso_8601": "2023-08-25T10:11:44.561482Z",
            "url": "https://files.pythonhosted.org/packages/47/c2/a72773ae6f837b9f3c46cce4ffbf31d9dab99a42f9c63b07cddee25a9b12/cain-1.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-08-25 10:11:44",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Animenosekai",
    "github_project": "cain",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "cain"
}
        
Elapsed time: 0.11935s