Metadata-Version: 2.1
Name: serialize-mcr
Version: 0.0.1
Summary: Creating a serializer for data structures
Home-page: https://github.com/millcityrunner/serialize-mcr
Author: Andrew Ray
Author-email: rayam@iu.edu
License: MIT
Description: ## Latest Version
        serialize-mcr='0.0.1'
        
        ## Maintainers
        Junpu Fan (Original Author, `serial-j` = https://github.com/JunpuFan/serial-j/blob/master)  
        Andrew Ray, rayam@iu.edu (Primary Maintainer) 
        
        ## Features 
           1. serialize-mcr JSON / Python Dictionary data into Python object based on a compact data `schema`.
               1. Data `schema` is a python list `[]` of many `{}`.
               2. Each `{}` in the `schema` defines a property in your `JSON` data. 
               3. The easiest form of a property definition is `{'name':'my_property'}` which means:
                  1. Your `JSON` data **MUST** contain a property called `my_property` .
                  2. Its value **MUST** be a **non-empty** value. 
                  3. Non-empty means that the value of  `my_property` can not be `None`, `""`, `()`, `[]`, or `{}`.
               4. Additional options are available to give you more control over your data definition. Those options are: `nullable`, `optional`, `is_compound`, `compound_serialize-mcrr`, `compound_schema`, `type`, and `default`.
                  1. Option `nullable: True` means the value of `my_property` can be `None`, or a nullable equivalent.
                  2. Option `optional: True` means `my_property` may or may not exist in your `JSON` data.
                     1. In case `my_property` exist, verify all applicable options.
                     2. In case `my_property` doesn't exist, we ignore `my_property`.
                  3. Option `is_compound: True` means `my_property` is a nested `JSON` object or an Array of `JSON` objects.
                     1. When `is_compound: True`, you must provide either `compound_serialize-mcrr` or `compound_schema` so we can property serialize-mcr this nested data structure.
                        1. `compound_serialize-mcrr` is a `serialize-mcr` serialize-mcrr class.
                        2. `compound_schema` has the same structure as the data `schema`.
                  4. Option `type` gives you the power to validate the value of each property in your `JSON` data. Currently supported type definitions are:
                     1. `'type': (bool,)` a boolean value.
                     2. `'type': (float,)` a floating point number.
                     3. `'type': (int,)` an integer.
                     4. `'type': (int, (1, 64, 343))` an enumeration of integers, this means that the value of a `JSON` property should be in `(1, 64, 343)`.
                     5. `'type': (int, range(1, 10, 3)`, a range of integers, this means that the value of a `JSON` property should be in `range(1, 10, 3)`.
                     6. `'type': (int, lambda x: x % 2 == 0)` a user defined `lambda` expression used to filter desired integer values, the above example `lambda`  specifies the value of the `JSON` property should be a `even` number.
                     7. `'type': (str,)` a string value.
                     8. `'type': (str, ('SUCCESS', 'FAILURE'))` an enumeration of strings, this means that the value of a `JSON` property should be in `('SUCCESS', 'FAILURE')`. Note that `('SUCCESS', 'FAILURE')` is just an example here, you can define anything you like.
                     9. `'type': (str, 'email')` an email address.
                     10. `'type': (str, 'url')` a web url.
                     11. `'type': (str, 'ipv4')` an IPv4 address.
                     12. `'type': (str, 'ipv6')` an IPv6 address.
                     13. `'type': (str, 'uuid')` an UUID string.
                     14. `'type': (str, '[^@]+@[^@]+\.[^@]+')` a user defined `regex`.
                  5. Option `default` gives you the power to set a defaulted value for a property in the case where it was not passed in AND the property was optional
                     1. `default` does not work if the property is optional, or in other words `required`
                     2. `default` does a type check against the defined `type` if passed in
                        1. if the type of the `default` value does not conform with the `type` defined, then an error will be thrown
                     3. `default` defaulted value is `None`, therefore both `True` and `False` are also supported in the `default` realm of options.
           2. Automatically validate every JSON properties defined in the `schema` based on varies additional options specified in `schema`.
           3. You are given convenient built-in methods that you can use to convert your data back to JSON encoded string or JSON / Python Dictionary.
           4. You have the flexibility of defining additional methods in your serialize-mcrr class that utilize your data in anyway you want.
        
        
        
        ## Example Codes
        
        | Name                                                  | Code                                                         |
        | ----------------------------------------------------- | ------------------------------------------------------------ |
        | Basic Example                                         | [basic_ex.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/basic_ex.py) |
        | serialize-mcr Nested Json Data with `compound_schema`     | [nested_ex2.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/nested_ex2.py) |
        | serialize-mcr Nested Json Data with `compound_serialize-mcrr` | [nested_ex1.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/nested_ex1.py) |
        | Data Type Validation: all in one example              | [typed_ex.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/typed_ex.py) |
        | Data Type Validation: `bool`                          | [bool_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/bool_data.py) |
        | Data Type Validation: `float`                         | [float_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/float_data.py) |
        | Data Type Validation: `int`                           | [int_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/int_data.py) |
        | Data Type Validation: `int enum`                      | [int_enum_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/int_enum_data.py) |
        | Data Type Validation: `int range`                     | [int_ranged_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/int_ranged_data.py) |
        | Data Type Validation: `int lambda`                    | [int_lambda_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/int_lambda_data.py) |
        | Data Type Validation: `str`                           | [str_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_data.py) |
        | Data Type Validation: `str enum`                      | [str_enum_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_enum_data.py) |
        | Data Type Validation: `str email`                     | [str_email_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_email_data.py) |
        | Data Type Validation: `str url`                       | [str_url_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_url_data.py) |
        | Data Type Validation: `str uuid`                      | [str_uuid_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_uuid_data.py) |
        | Data Type Validation: `str ipv4`                      | [str_ipv4_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_ipv4_data.py) |
        | Data Type Validation: `str ipv6`                      | [str_ipv6_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_ipv6_data.py) |
        | Data Type Validation: `str regex`                     | [str_regex_data.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/str_regex_data.py) |
        | Default Data: `default`                               | [extra_params_ex.py](https://github.com/millcityrunner/serialize-mcr/blob/master/examples/type/extra_params_ex.py) |
        
        
        
        
        ## Basic Example
        Let's first see a basic example. 
        
        ```python
        from serialize_mcr import SerializeMCR
        
        class FruitBucket(SerializeMCR):
            # define how our data should look like using `schema`.
            schema = [
                {'name': 'apple'},
                {'name': 'orange'},
                {'name': 'pineapple'},
            ]
        
        # test data for FruitBucket 
        test1 = dict(
            apple="good apple",
            orange="very good orange",
            pineapple="nice pineapple",
        )
        
        serialize-mcr
        fruits = FruitBucket(test1)
        
        # `fruits` is a proper python object , which means that you can use 
        # `fruits.apple` syntax to retrieve the value of `apple`.
        print(fruits.apple)
        >>> good apple
        
        # ...and other fruits too.
        print(fruits.orange)
        >>> very good orange
        print(fruits.pineapple)
        >>> nice pineapple
        
        # you can get the JSON formatted string back too.
        print(fruits)
        >>> {"apple": "good apple", "orange": "very good orange", "pineapple": "nice pineapple"}
        
        # interested to get the python dictionary back?
        fruits_data = fruits.as_dict()
        print(fruits_data)
        >>> {'apple': 'good apple', 'orange': 'very good orange', 'pineapple': 'nice pineapple'}
        ```
        
        
        
        ## Nested JSON Data 
        
        Let's see how we can serialize-mcr more complex data structure into python object.
        
        
        
        ##### Serializing Nested JSON Data with `compound_schema`.
        
        Define a nested data `schema` called `compound_schema` to serialize-mcr nested `JSON` data.
        
        ```python
        from serialize_mcr import SerializeMCR
        
        class SnackBucket(SerializeMCR):
            schema = [
                {'name': 'apple'},
                {'name': 'orange'},
                {'name': 'pineapple'},
                {'name': 'snack', 'is_compound': True,
                    'compound_schema': [
                         {'name': 'cheese', 'optional': True},
                         {'name': 'chocolate'},
                         {'name': 'chips', 'nullable': True},
                    ],
                },
            ]
        
        test3 = dict(
            apple="good apple",
            orange="very good orange",
            pineapple="nice pineapple",
            snack=[
                dict(
                    cheese="Feta",
                    chocolate="Ferrero Rocher",
                    chips=[] 
                ),
                dict(
                    chocolate="Swiss milk chocolate",
                    chips=["Cheetos", "Lays Classic Potato Chips", "Cool Ranch Doritos"] 
                ),
            ]
        )
        mysnacks = SnackBucket(test3)
        print(mysnacks)
        >>> {"apple": "good apple", "orange": "very good orange", "pineapple": "nice pineapple", 
        >>> "snack": [{"cheese": "Feta", "chocolate": "Ferrero Rocher", "chips": []}, 
        >>>           {"chocolate": "Swiss milk chocolate", "chips": 
        >>>                ["Cheetos", "Lays Classic Potato Chips", "Cool Ranch Doritos"]}]}
        ```
        
        
        
        ##### Serializing Nested JSON Data with `compound_serialize-mcrr`.
        
        Define a separete data `serialize-mcr` serialize-mcrr called `compound_serialize-mcrr` to serialize-mcr nested `JSON` data.
        
        ```python
        from serialize_mcr import SerializeMCR
        class Snack(SerializeMCR):
            schema = [
                # cheese is nice but is optional.
                {'name': 'cheese', 'optional': True},
                # chocolate is a MUST have.
                {'name': 'chocolate'},
                # chips is a must but we have to decide which kind later, 
                # so its value can be None, False, "", {}, [].
                {'name': 'chips', 'nullable': True},
            ]
            
        class NestedBucket(SerializeMCR):
            schema = [
                {'name': 'apple'},
                {'name': 'orange'},
                {'name': 'pineapple'},
                {'name': 'snack', 'is_compound': True, 'compound_serialize-mcrr': Snack}
            ]
            
        # test data for NestedBucket
        test2 = dict(
            apple="good apple",
            orange="very good orange",
            pineapple="nice pineapple",
            snack=dict(
                chocolate="Ferrero Rocher",
                chips=[] # yeah its a list of chips!
            ),
        )
        my_snacks = NestedBucket(test2)
        print(my_snacks)
        >>> {"apple": "good apple", "orange": "very good orange", "pineapple": "nice pineapple", 
        >>>  "snack": {"chocolate": "Ferrero Rocher", "chips": []}}
        ```
        
        
        
        ## Data Type Validation 
        
        a compact example that shows all data types currently supported by this package.
        
        ```python
        from serialize_mcr import SerializeMCR
        
        
        class TypedData(SerializeMCR):
            schema = [
                {'name': 'prop1', 'type': (int,)},
                {'name': 'prop2', 'type': (int, (1, 64, 343))},
                {'name': 'prop3', 'type': (int, range(1, 10, 3))},
                {'name': 'prop4', 'type': (int, lambda x: x % 2 == 0)},
                {'name': 'prop5', 'type': (str,)},
                {'name': 'prop6', 'type': (str, ('SUCCESS', 'FAILURE'))},
                {'name': 'prop7', 'type': (str, 'email')},
                {'name': 'prop8', 'type': (str, 'url')},
                {'name': 'prop9', 'type': (str, 'ipv4')},
                {'name': 'prop10', 'type': (str, 'ipv6')},
                {'name': 'prop11', 'type': (str, 'uuid')},
                {'name': 'prop12', 'type': (str, '[^@]+@[^@]+\.[^@]+')},
                {'name': 'prop13', 'type': (float,)},
                {'name': 'prop14', 'type': (bool,)},
            ]
        
        
        test1 = {
            'prop1': 1,
            'prop2': 64,
            'prop3': 4,
            'prop4': 2,
            'prop5': "str",
            'prop6': 'SUCCESS',
            'prop7': 'anyone@emailservice.com',
            'prop8': 'https://www.something.com/something-something/something/12345',
            'prop9': '172.16.255.1',
            'prop10': '2001:0db8:0a0b:12f0:0000:0000:0000:0001',
            'prop11': 'c026dd66-86f2-498e-8c2c-858179c0c93d',
            'prop12': 'junpufan@me.com',
            'prop13': 0.1,
            'prop14': True
        }
        
        data1 = TypedData(test1)
        print(data1)
        # >>> {"prop1": 1, "prop2": 64, "prop3": 4, "prop4": 2, "prop5": "str",
        # >>> "prop6": "SUCCESS", "prop7": "anyone@emailservice.com",
        # >>> "prop8": "https://www.something.com/something-something/something/12345",
        # >>> "prop9": "172.16.255.1", "prop10": "2001:0db8:0a0b:12f0:0000:0000:0000:0001",
        # >>> "prop11": "c026dd66-86f2-498e-8c2c-858179c0c93d", "prop12": "junpufan@me.com",
        # >>> "prop13": 0.1, "prop14": true}
        
        ```
        
        ## Defaulting Data on Optional Properties Absence
        
        a simple way to ensure a value is set at all times for optional properties in a JSON schema
        
        ```python
        from serialize_mcr import SerializeMCR
        
        class DefaultingValues(SerializeMCR):
            schema = [
                {'name': 'var1', 'type': (int,), 'optional': True, 'default': 0},
                {'name': 'var2', 'type': (str,), 'optional': True, 'default': 'str'},
                {'name': 'var3', 'type': (float,), 'optional': True, 'default': 1.25},
                {'name': 'var4', 'type': (bool,), 'optional': True, 'default': True},
                {'name': 'var5', 'type': (int, (1, 3, 5)), 'optional': True, 'default': 3}
            ]
            
        ### acceptable bodies to pass in
        # since all properties are optional, no values are required to be passed in
        # all values will be set to their defined default value
        test1 = {}
        data1 = DefaultingValues(data=test1)
        
        # choosing some but not all properties will also work, as var2, var3, var5 will be set to their default values
        test2 = {'var1': 24, 'var4': False}
        data2 = DefaultingValues(data=test2)
        
        
        class InvalidDefaultValues(SerializeMCR):
            schema = [
                {'name': 'var1', 'type': (int,), 'default': 0},
                {'name': 'var2', 'type': (str,), 'optional': True, 'default': 1},
                {'name': 'var3', 'type': (float,), 'optional': True, 'default': True},
                {'name': 'var4', 'type': (bool,), 'optional': True, 'default': False},
                {'name': 'var5', 'type': (int, (1, 3, 5)), 'default': 3}
            ]
            
        # var1 is not optional, therefore a default value cannot be set
        # var2 has a defined type of `str`, but a defaulted value of `int`
        # var3 has a defined type of `float`, but a defaulted value of `bool`
        # var4 is acceptable
        # var5 is not optional, therefore a default value cannot be set
        
        ``` 
        **Note: The schema's of a serialize-mcr are not validated until a dataset is passed into the Class, therefore improper schema definitions are acceptable, but will fail to build.**
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown
