Skip to content

Commit

Permalink
Add kcidb.io extracted from kcidb
Browse files Browse the repository at this point in the history
  • Loading branch information
spbnick committed Sep 30, 2020
0 parents commit 9cb05e2
Show file tree
Hide file tree
Showing 12 changed files with 2,336 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__pycache__
*.egg-info
*.pyc
17 changes: 17 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[MASTER]

[MESSAGES CONTROL]
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=duplicate-code

[REPORTS]
# Activate the evaluation score.
score=no
15 changes: 15 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
language: python
dist: xenial
python:
- "3.6"
install:
- pip3 install '.[dev]'
before_script:
- git clone --depth=1 https://github.com/kernelci/kcidb.git .kcidb
- git -C .kcidb log -n1
script:
- "flake8 kcidb_io *.py"
- "pylint kcidb_io *.py"
- pytest
- pip3 install .kcidb
- pytest .kcidb
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
kcidb-io
========

`kcidb-io` is a Python 3 library for validating and manipulating Linux Kernel
CI reports in JSON format. This library is used by [`kcidb`][kcidb] - a
package for maintaining a service storing and serving that data.

Installation
------------

`kcidb-io` requires Python v3.6 or later.

To install the package for the current user, run this command:

pip3 install --user <SOURCE>

Where `<SOURCE>` is the location of the package source, e.g. a git repo:

pip3 install --user git+https://github.com/kernelci/kcidb-io.git

or a directory path:

pip3 install --user .

In any case, make sure your PATH includes the `~/.local/bin` directory, e.g.
with:

export PATH="$PATH":~/.local/bin

Using
-----

Here's an example creating an empty report and then validating it:
```python
# Import the kcidb-io package
import kcidb_io
# Create an empty report using the latest schema version
json = kcidb_io.new()
# Validate the report
kcidb_io.schema.validate(json)
```

Hacking
-------

If you want to hack on the source code, install the package in the editable
mode with the `-e/--editable` option, and with "dev" extra included. E.g.:

pip3 install --user --editable '.[dev]'

The latter installs the `kcidb-io` package using the modules from the source
directory, and changes to them will be reflected immediately without the need
to reinstall. It also installs extra development tools, such as `flake8` and
`pylint`.

Releasing
---------

Before releasing make sure the README.md is up to date.

To make a release tag the release commit with `v<NUMBER>`, where `<NUMBER>` is
the next release number, e.g. `v1`. The very next commit after the tag should
update the version number in `setup.py` to be the next one. I.e. continuing
the above example, it should be `2`.

[kcidb]: https://github.com/kernelci/kcidb/
73 changes: 73 additions & 0 deletions kcidb_io/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""Kernel CI reporting I/O data"""

from copy import deepcopy
from kcidb_io import schema

# Silence flake8 "imported but unused" warning
__all__ = ["schema", "new", "merge"]


def new():
"""
Create an empty I/O data set.
Returns:
An empty I/O data set adhering to the latest schema version.
"""
data = dict(version=dict(major=schema.LATEST.major,
minor=schema.LATEST.minor))
assert schema.is_valid_latest(data)
return data


def get_obj_num(data):
"""
Calculate number of objects of any type in an I/O data set adhering to the
latest schema.
Args:
data: The data set to count the objects in.
Must adhere to the latest schema.
Returns:
The number of objects in the data set.
"""
assert schema.is_valid_latest(data)
return sum(len(data[k]) for k in schema.LATEST.tree if k and k in data)


def merge(target, sources, copy_target=True, copy_sources=True):
"""
Merge multiple I/O data into a destination.
Args:
target: The data to merge into.
sources: An iterable containing data sets to merge from.
copy_target: True if "target" contents should be copied before
upgrading and modifying. False if not.
Default is True.
copy_sources: True if "source" contents should be copied before
upgrading and referencing. False if not.
Default is True.
Returns:
The merged data, adhering to the latest schema version.
"""
assert schema.is_valid(target)

if copy_target:
target = deepcopy(target)
target = schema.upgrade(target, copy=False)

for source in sources:
assert schema.is_valid(source)
if copy_sources:
source = deepcopy(source)
source = schema.upgrade(source, copy=False)
for obj_list_name in schema.LATEST.tree:
if obj_list_name in source:
target[obj_list_name] = \
target.get(obj_list_name, []) + source[obj_list_name]

assert schema.is_valid_latest(target)
return target
91 changes: 91 additions & 0 deletions kcidb_io/schema/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"""Kernel CI reporting I/O schema"""

from kcidb_io.schema import v1, v2, v3

# Version 1
V1 = v1.VERSION
# Version 2
V2 = v2.VERSION
# Version 3
V3 = v3.VERSION
# Latest version of the schema
LATEST = V3


def validate(data):
"""
Validate I/O data against one of the schema versions.
Args:
data: The data to validate. Will not be changed.
Returns:
The validated (but unchanged) data.
Raises:
`jsonschema.exceptions.ValidationError` if the data did not adhere
to any of the schema versions.
"""
return LATEST.validate(data)


def is_valid(data):
"""
Check if I/O data is valid according to a schema version.
Args:
data: The data to check.
Returns:
True if the data is valid, false otherwise.
"""
return LATEST.is_valid(data)


def validate_latest(data):
"""
Validate I/O data against the latest schema version only.
Args:
data: The data to validate. Will not be changed.
Returns:
The validated (but unchanged) data.
Raises:
`jsonschema.exceptions.ValidationError` if the data did not adhere
to the latest schema version.
"""
return LATEST.validate_exactly(data)


def is_valid_latest(data):
"""
Check if I/O data is valid according to the latest schema version.
Args:
data: The data to check.
Returns:
True if the data is valid, false otherwise.
"""
return LATEST.is_valid_exactly(data)


def upgrade(data, copy=True):
"""
Upgrade the data to the latest schema version from any of the previous
versions. Validates the data. Has no effect if the data already adheres to
the latest schema version.
Args:
data: The data to upgrade and validate.
Must adhere to a version of the schema.
copy: True, if the data should be copied before upgrading.
False, if the data should be upgraded in-place.
Optional, default is True.
Returns:
The upgraded and validated data.
"""
return LATEST.upgrade(data, copy)
Loading

0 comments on commit 9cb05e2

Please sign in to comment.