Skip to main content

A Library to enable preconversion of any Python type into one that is easily serializable

Project description

preconvert - Supercharge Your Serializers

PyPI version Build Status codecov Gitter License Downloads


Read Latest Documentation - Browse GitHub Code Repository


Preconvert is a library that extends existing serializiers (json, simplejson, bson, msgpack, ..) to be capable of converting all the types you use. It accomplishes this by efficiently preconverting just the types the serializers aren't aware of (things like dataclasses and namedtuples) into basic built-in types that all serializers can understand. It then provides a mechanism for you to build custom preconverters, and preconvert_plugins that automatically take effect when installed via pip.

Quickstart

  1. Install preconvert using pip:

     pip3 install preconvert
    
  2. Replace existing json (or other serialization library) with preconvert equivalent:

     from preconvert.output import simplejson as json
    
     ...
    
     json.dumps(MY_COMPLEX_OBJECT_WITH_DATA_CLASSSES)
    
  3. Define preconverters for any custom types, even if they aren't under your control:

     import numpy
     from preconvert import json
    
    
     class Employee:
    
         def __init__(self, first_name, last_name):
             self.first_name = first_name
             self.last_name = last_name
    
         def __preconvert__(self):
             return {'name': {'first': self.first_name, 'last': self.last_name}}
    
    
     @preconvert.converter(numpy.integer)
     def numpy_integer_to_python_int(numpy_int):
         return int(numpy_int)
    
    
     json.dumps({
         'employee': Employee('Timothy', 'Crosley'),
         'height_inches': numpy.int_(73)
     })
    
  4. Enjoy a more comprehensive and configurable serializer!

Why?

Have you ever tried to json.dumps a data structure, only to be surprised when your DataClass throws an exception, or your namedtuple outputs as a list? Preconvert was created to solve this problem across common serialization formats.

Before preconvert:

import sys
import json
from dataclasses import dataclass


@dataclass
class InventoryItem:
    """Class for keeping track of an item in inventory."""
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand


my_store_inventory = [InventoryItem("beer", unit_price=0.0, quantity_on_hand=sys.maxsize),  InventoryItem("bacon", unit_price=2.5, quantity_on_hand=3)]
json.dumps(my_store_inventory)

output >>>

    177
    178
--> 179         raise TypeError(f'Object of type {o.__class__.__name__} '
    180                         f'is not JSON serializable')
    181

TypeError: Object of type InventoryItem is not JSON serializable

D:

After preconvert:

import sys
import json
from preconvert.output import json


@dataclass
class InventoryItem:
    """Class for keeping track of an item in inventory."""
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand


my_store_inventory = [
    InventoryItem("beer", unit_price=0.0, quantity_on_hand=sys.maxsize),
    InventoryItem("bacon", unit_price=2.5, quantity_on_hand=3)
]
json.dumps(my_store_inventory)

>>> [
        {
            "name": "beer",
            "unit_price": 0.0,
            "quantity_on_hand": 9223372036854775807
        },
        {
            "name": "bacon",
            "unit_price": 2.5,
            "quantity_on_hand": 3
        }
    ]

:D

Design goals:

  • Easy utilization from existing projects
  • Enable conversion from complex to simple types independant of desired output format
  • Provide built in conversion for common types that are not universally supported (dataclasses, namedtuple, etc...)
  • Provide a way to build custom preconverts or override built-in preconverts
  • Ability to build preconverts that are dependent on the destination format
  • Minimal overhead when utilized with common serialization formats

How do I use this?

If your project uses one of our built-in supported serializers (json, msgpak, bson) you can simply replace your existing serializer import with a preconvert one:

from preconvert.outputs import json

OR

from preconvert.outputs import simplejson as json

OR

from preconvert.outputs import msgpack

OR

from preconvert.outputs import bson

If not you can inject preconvert before usage of any other serializers, often by setting a default or on_onknown parameter:

import preconvert
import my_serializer

my_serializer.dumps(default=preconvert.default_serializable)

How do I extend this?

Want to add preconversion to your own custom types? For OOP projects, one easy way to do this is to add a __preconvert__ method to your object:

class MyCustomClass(object):
    def __init__(self, first_name, children=()):
        self.first_name = first_name
        self.children = children

    def __jsonifiable__(self)
        return {'first': self.first_name, 'children': children}

For other entities, such as objects you do not control, you can register a new preconvert using the preconvert.converter decorator:

import preconvert


@preconvert.converter(SomeFrameworkObject)
def convert_framework_object(instance):
    return {'name': instance.name}

You can also, optionally, specify preconversions per an intended serialization format:

import preconvert


@preconvert.json(SomeFrameworkObject)
def convert_framework_object(instance):
    return {'json': {'name': instance.name}}


@preconvert.msgpack(SomeFrameworkObject)
def convert_framework_object(instance):
    return ['name', instance.name]

Finally, you can resister any modules that contain converters to package 'preconvert.converters' entrypoints, and they will take effect automatically as long as the package that contains them is installed. See the preconvert_numpy for an example of how this works.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

preconvert-0.0.6.tar.gz (128.5 kB view details)

Uploaded Source

Built Distribution

preconvert-0.0.6-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file preconvert-0.0.6.tar.gz.

File metadata

  • Download URL: preconvert-0.0.6.tar.gz
  • Upload date:
  • Size: 128.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.1.0 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.7.1

File hashes

Hashes for preconvert-0.0.6.tar.gz
Algorithm Hash digest
SHA256 ddc2c0b6cd8e02e9ed8ea9b983854a06c06ab4030f6e09836504157cde3b29c3
MD5 e6deb79e7236f5480462a6ec5bf5f851
BLAKE2b-256 542c29ec9f0103289160e991f4fc0f4fbd34e0d5b1f5739a7785337ef5d2faab

See more details on using hashes here.

File details

Details for the file preconvert-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: preconvert-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 17.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/41.1.0 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.7.1

File hashes

Hashes for preconvert-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 4824251345c20e4af085b463623ed7825da070e900df683c0ef4e34431ff832e
MD5 a0606d778334256d9cd7a3abe4d3a09e
BLAKE2b-256 55fd2835e0150bfd387aa1869f349b95d5103a1e79f76f67b1292f965a27a37e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page