Skip to main content

Description

Python schema library agnostic from languages.

License Development Status Latest release Supported Python versions Supported Python implementations Download format Build status Code test coverage Downloads Documentation Status Code Health

Installation

pip install b3j0f.schema

Features

This library provides an abstraction layer for manipulating schema from several languages.

The abstraction layer is a python object which can validate data (properties to validate are object attributes or dictionary items) and be dumped into a dictionary or specific language format.

Supported languages are:

  • python

  • json

  • xsd

It is also possible to generate a schema from a dictionary. And validation rules are fully and easily customisable thanks to using a schema such as a property.

Example

Data Validation

from b3j0f.schema import build, validate

# json format with required subinteger property
resource = '{"title": "test", "properties": {"subname": {"type": "string", "default": "test"}}, {"subinteger": {"type": "integer"}}, "required": ["subinteger"]}'
Test = build(resource)

test = Test(subname='example')

assert test.subinteger == 0  # instanciation value
assert Test.subinteger.default == 0  # default value
assert test.subname == 'example' # instanciation value
assert Test.subname.default == 'test'  # instanciation value

error = None
try:
   test.subname = 2  # wrong setting because subname is not a string

except TypeError as error:
   pass

assert error is not None

assert 'subname' in Test.getschemas()

validate(Test.subinteger, 1)  # validate property
validate(test, {'subinteger': 1})  # validate dictionary

class Sub(object):  # object to validate with required subinteger
   subinteger = 1

validate(test, Sub)  # validate an object with required subinteger
validate(test, Sub())

wrongvalues = [
   '',  # object without subinteger
   {'subinteger': ''},  # wrong data type for subinteger
   {}  # dictionary without the required property subinteger
]

for wrongvalue in wrongvalues:

   error = None
   try:
      validate(test, wrongvalues)

   except TypeError as error:
      pass

   assert error is not None

Schema retrieving

from b3j0f.schema import register, getbyname, getbyuuid, data2schema

assert getbyuuid(test.uuid) is None
assert test not in getbyname(test.name)

register(test)

assert test is getbyuuid(test.uuid)

assert test in getbyname(test.name)

schema = data2schema(2, name='vint')  # get an integer schema with 2 such as a default value and name vint

assert schema.default == 2
assert schema.name == 'vint'

error = None
try:
   schema.default = ''

except TypeError as error:
   pass

assert error is not None

Schema definition

from b3j0f.schema import Schema, updatecontent

@updatecontent  # change public attributes/functionss to schemas
class Test(Schema):

   subname = 'test'  # specify inner schema such as a string schema with default value 'test'
   subinteger = 1  # speciy inner schema sub as an integer with default value 1

test = Test()

test = Test(subname='example')

assert test.subname == 'example' # instanciation value
assert Test.subname.default == 'test'  # instanciation value
assert test.subinteger == 1  # instanciation value
assert Test.subinteger.default == 1  # default value

error = None
try:
   test.subname = 2  # wrong setting because subname is not a string

except TypeError as error:
   pass

assert error is not None

assert 'subname' in Test.getschemas()

Complex Schema definition

from b3j0f.schema import Schema, ThisSchema, RefSchema, build
from random import random

@build(foo=2)  # transform a python class to a schema class with the additional property foo
class Test(object):

   key = DynamicValue(lambda: random())  # generate a new key at each instanciation
   subtest = ThisSchema(key=3.)  # use this schema such as inner schema
   ref = RefSchema()  # ref is validated by this schema

assert issubclass(Test, Schema)

test1, test2 = Test(), Test()

# check foo
assert test1.foo == test2.foo == 2

# check key and subtest properties
assert test1.key != test2.key
assert test1.subtest.key == test2.subtest.key == 3.

# check ref
assert test1.ref is None
test1.ref = Test()

error = None
try:
   test.ref = 2

except TypeError as error:
   pass

assert error is not None

Function schema definition

from b3j0f.schema import FunctionSchema, ParamSchema, FloatSchema, BooleanSchema, StringSchema, ArraySchema, OneOfSchema

@data2schema
def test(a, b, c=2, d=None, e=None, f=None):  # definition of a shema function. Parameter values and (function) types are defined in the signature and the docstring.
   """
   :param float a: default 0.
   :type b: bool
   :type d: ints  # list of int
   :type e: list of str  #: list of str
   :type f: int,float  #: one of (int, float)
   :rtype: str
   """

   return a, b, c

assert isinstance(test, FunctionSchema)
assert isinstance(test.params, ArraySchema)
assert isinstance(test.params[0], ParamSchema)
assert len(test.params) == 6

assert test.params[0].name == 'a'
assert test.params[0].mandatory == True
assert isinstance(test.params[0].ref, FloatSchema)
assert test.params[0].default is 0.

assert test.params[1].name == 'b'
assert isinstance(test.params[1].ref, BooleanSchema)
assert test.params[1].mandatory is True
assert test.params[1].default is False

assert test.params[2].name == 'c'
assert isinstance(test.params[2].ref, IntegerSchema)
assert test.params[2].mandatory is False
assert test.params[2].default is 2

assert test.params[3].name == 'd'
assert isinstance(test.params[3].ref, ArraySchema)
assert isinstance(test.params[3].ref.itemtype, IntegerSchema)
assert test.params[3].mandatory is False
assert test.params[3].default is None

assert test.params[4].name == 'e'
assert isinstance(test.params[4].ref, ArraySchema)
assert isinstance(test.params[4].ref.itemtype, StringSchema)
assert test.params[4].mandatory is False
assert test.params[4].default is None

assert test.params[5].name == 'f'
assert isinstance(test.params[5].ref, OneOfSchema)
assert isinstance(test.params[5].ref.schemas[0], IntegerSchema)
assert isinstance(test.params[5].ref.schemas[1], FloatSchema)
assert test.params[5].mandatory is False
assert test.params[5].default is None

assert test.rtype is StringSchema

assert test(1, 2) == 'test'

Generate a schema from a data

from b3j0f.schema import data2schema

data = {  # data is a dict
   'a': 1
}

schemacls = dict2schemacls(data, name='test')

assert isinstance(schemacls.a, IntegerSchema)
assert schemacls.a.default is 1
assert isinstance(schemacls.name, StringSchema)
assert schemacls.name.default == 'test'

validate(schemacls(), data)

class Test(object):  # data is an object
   a = 1

schemacls = dict2schemacls(data, name='test')

assert isinstance(schemacls.a, IntegerSchema)
assert schemacls.a.default is 1
assert isinstance(schemacls.name, StringSchema)
assert schemacls.name.default == 'test'

validate(schemacls(), Test)
validate(schemacls(), Test())

Schema property getting/setting/deleting customisation such as a property

class Test(Schema):

   @Schema
   def test(self):
      self.op =  'get'
      return getattr(self, '_test', 1)

   @test.setter
   def test(self, value):
      self.op = 'set'
      self._test = value

   @test.deleter
   def test(self):
      self.op = 'del'
      del self._test

test = Test()

# check getter
assert test.test == 1
assert test.op == 'get'

# check setter
test.test = 2
assert test.op == 'set'
assert test.test == 2

# check deleter
del test.test
assert test.op == 'del'
assert test.test == 1

Perspectives

  • wait feedbacks during 6 months before passing it to a stable version.

  • Cython implementation.

Donation

I'm grateful for gifts, but don't have a specific funding goal.

Metadata

Release files for b3j0f.schema 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distributions (sdists)

Source distribution for b3j0f.schema 0.0.9
File Size Uploaded Provenance
b3j0f.schema-0.0.9.zip 54.7 kB Without provenance Details
b3j0f.schema-0.0.9.tar.gz 27.5 kB Without provenance Details
b3j0f.schema-0.0.9.tar.bz2 23.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for b3j0f.schema 0.0.9
File Interpreter ABI Platform
b3j0f.schema-0.0.9-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 158.6 kB

Release files / b3j0f.schema-0.0.9.zip

Download URL b3j0f.schema-0.0.9.zip
Size 54.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3b135467e63b58ae1b78e08e6f7645496cda53368ad1a1ccfe0f79d2dba0653b
BLAKE2b-256 checksum
How to use checksums
1959fbfce4c0240d341dcd5985608b187acdef2dd1d7eb2436ecfe1c406a2490
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / b3j0f.schema-0.0.9.tar.gz

Download URL b3j0f.schema-0.0.9.tar.gz
Size 27.5 kB
Tags Source
SHA-256 checksum
How to use checksums
330dabb41b7a37283e355c4c2d6ceec3b64ff0d273b03eb8703c9527822accab
BLAKE2b-256 checksum
How to use checksums
12bec8bd1c55d07dafdadf754045044b9a3bcb63d6b7f96a39228476453c6b93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / b3j0f.schema-0.0.9.tar.bz2

Download URL b3j0f.schema-0.0.9.tar.bz2
Size 23.6 kB
Tags Source
SHA-256 checksum
How to use checksums
6a9e5259aa75461d08a6fb0ffa998c75c9b74e8a12929845afeb7d2c592df02f
BLAKE2b-256 checksum
How to use checksums
32d0ac9d47dfccbfb29a1f1ca940b7a26546b6687bcdcbb444f6b904a3125b95
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / b3j0f.schema-0.0.9-py2.py3-none-any.whl

Download URL b3j0f.schema-0.0.9-py2.py3-none-any.whl
Size 52.8 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
070a7bf56147c195d439151442e5d5b24f247d001bb3e673db1d66146bfcbe88
BLAKE2b-256 checksum
How to use checksums
d1805c8c733fa12173c130b5a54c2a5b12e58b8b1fb8bed4e586a5cb41bc30e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for b3j0f.schema 0.0.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page