Skip to content

Commit

Permalink
Merge branch 'r/0.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Grokzen committed Jan 20, 2013
2 parents 538e599 + 1b5795a commit c804544
Show file tree
Hide file tree
Showing 52 changed files with 2,550 additions and 0 deletions.
9 changes: 9 additions & 0 deletions License.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Copyright (c) 2013 grokzen.se

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
exclude *.py
include setup.py
include lib/pykwalify/META-*
graft lib/config
graft tests
32 changes: 32 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
help:
@echo "Please use 'make <target>' where <target> is one of"
@echo " clean remove temporary files created by build tools"
@echo " cleanall all the above + tmp files from development tools"
@echo " cleanmeta Cleans out all META.* files from the lib folder"
@echo " test run test suite"
@echo " sdist make a source distribution"
@echo " install install package"

clean:
-rm -f MANIFEST
-rm -rf dist/*
-rm -rf build/*

cleanmeta:
-rm -rf lib/pykwalify/META-*

cleanall: clean cleanmeta
-find . -type f -name "*~" -exec rm -f "{}" \;
-find . -type f -name "*.orig" -exec rm -f "{}" \;
-find . -type f -name "*.rej" -exec rm -f "{}" \;
-find . -type f -name "*.pyc" -exec rm -f "{}" \;
-find . -type f -name "*.parse-index" -exec rm -f "{}" \;

test:
python runtests.py

sdist: cleanmeta
python setup.py sdist

install: cleanmeta
python setup.py install
100 changes: 100 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# pyKwalify

YAML/JSON validation library

This framework is a port of the java version of the framework kwalify that can be found at: http://www.kuwata-lab.com/kwalify/

The source code can be found at: http://sourceforge.net/projects/kwalify/files/kwalify-java/0.5.1/

The schema used in this library: http://www.kuwata-lab.com/kwalify/ruby/users-guide.01.html#schema

## How to install

Note: It is recomended allways to use a virtual-enviroment when using pyKwalify

1. Download the release you want to install from a tag, latest stable build or the dev branch.
2. Run "pip install pykwalify-x.x.x.tar.gz"
3. To use pykwalify run "pykwalify" in your terminal

## Build from source

1. Download the release you want to install from a tag, latest stable build or the dev branch.
2. Run "make sdist"
3. To install run "make pip install dist/pykwalify-x.x.x.tar.gz"

## Install from source

1. Download the release you want to install from a tag, latest stable build or the dev branch.
2. Run "make install"

## pyKwalify python dependencies

- argparse 1.2.1
- PyYaml 3.10

## Supported python version

- Python 2.7.x - (Not yet tested)
- Python 3.1.x - Yes
- Python 3.2.x - Yes
- Python 3.3.x - (Not yet tested)

# Implemented validation rules
```
type:
Type of value. The followings are available:
- str
- int
- float [NYI]
- bool
- number (== int or float) [NYI]
- text (== str or number) [NYI]
- date [NYI]
- time [NYI]
- timestamp [NYI]
- seq
- map
- scalar (all but seq and map)
- any (means any data) [NYI]
required:
Value is required when true (default is false). This is similar to not-null constraint in RDBMS.
enum:
List of available values.
pattern:
Specifies regular expression pattern of value. (Uses re.match() )
range:
Range of value between max/max-ex and min/min-ex.
'max' means 'max-inclusive'. (a > b)
'min' means 'min-inclusive'. (a < b)
'max-ex' means 'max-exclusive'. (a >= b)
'min-ex' means 'min-exclusive'. (a <= b)
Type seq, map, bool and any are not available with range:.
length:
Range of length of value between max/max-ex and min/min-ex. Only type str and text are available with length:.
unique:
Value is unique for mapping or sequence. This is similar to unique constraint of RDBMS.
name:
Name of schema.
desc:
Description. This is not used for validation.
```

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some features'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

## License

MIT.
16 changes: 16 additions & 0 deletions ReleaseNotes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
=============
Release Notes
=============


v0.1.0
======

- Initial stable release of pyKwalify.
- All functions is not currently implemented but the cli/lib can be used but probably with some bugs.
- This should be considered a Alpha release used for bug and stable testing and to be based on further new feature requests for the next version.
- Implemented most validation rules from the original Java version of kwalify. Some is currently not implemented and can be found via [NYI] tag in output, doc & code.
- Installable via pip (Not the official online pip repo but from the releases folder found in this repo)
- Supports YAML & JSON files from cli and any dict/list data structure if used in lib mode.
- Uses pythons internal logging functionality and default logging output can be changed by changing logging.ini (python 3.1.x) or logging.yaml (python 3.2.x) to change the default logging output, or use -v cli input argument to change the logging level. If in lib mode it uses your implemented python std logging.

25 changes: 25 additions & 0 deletions lib/config/logging.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This logging configuration will be used in python versions <= 3.1.x

[loggers]
keys=root

[handlers]
keys=console

[formatters]
keys=simple

[logger_root]
level=INFO
handlers=console

[handler_console]
class=StreamHandler
level=INFO
formatter=simple
args=(sys.stdout,)

[formatter_simple]
format= %(levelname)s - %(name)s:%(lineno)s - %(message)s
datefmt=
class=logging.Formatter
15 changes: 15 additions & 0 deletions lib/config/logging.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This logging configuration will be used in python versions >= 3.2.x

version: 1
formatters:
simple:
format: ' %(levelname)s - %(name)s:%(lineno)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: simple
stream: ext://sys.stdout
root:
level: INFO
handlers: [console]
167 changes: 167 additions & 0 deletions lib/pykwalify/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# -*- coding: utf-8 -*-

""" pykwalify """

__author__ = 'Grokzen <[email protected]>'
#__version__ = '.'.join(map(str, __version_info__))
__foobar__ = "0.1.0"

# Set to True to have revision from Version Control System in version string
__devel__ = True

import sys
import os
from io import StringIO

# init python std logging
import logging
import logging.config

# 3rd party imports
import yaml

PACKAGE_NAME = "pykwalify"
IN_VIRTUALENV = True if hasattr(sys, 'real_prefix') else False


def init_logging():
if sys.version_info >= (3,2,0):
logging_file = "logging.yaml"
else:
# If 3.1.x or lower use old ini file
logging_file = "logging.ini"

p = get_config_path(logging_file)

with open(p) as stream:
if not __devel__:
io = StringIO(stream.read().replace("%(name)s:%(lineno)s - ", "") )
else:
io = StringIO(stream.read() )

if sys.version_info >= (3,2,0):
logging.config.dictConfig(yaml.load(io) )
else:
logging.config.fileConfig(io)


def split_path(string):
"""Takes a string containing a filesystem path and returns a list of
normalized pieces of that path.
Note that this function makes an absolute path into a relative, so use with caution.
Example: split_path('/foo/bar')
Returns: ['foo', 'bar']
Example: split_path('foo/bar/baz/')
Returns: ['foo', 'bar', 'baz']
Example: split_path('foo.txt')
Returns: ['foo.txt']
Arguments:
- `string`: string that might contain os.sep (likely "/")
"""
res = []
if os.sep in string:
splitted = string.split(os.sep)
for piece in reversed(splitted):
if piece: # remove empty pieces from split, e.g. /foo/bar is ['', 'foo', 'bar']
res.append(piece)
else:
res.append(string)
return res


def list_path(*args):
"""Takes strings containing filesystem paths and returns a list of
normalized and split pieces of those paths.
Note: this is analogous to concat_path() except that this function returns
a list, which in turn be used as an *args input to os.path.join() and be
cross-platform since all parts of the code uses os.sep instead of a
hardcoded "/".
Example: list_path('foo+bar', 'foo/bar/', '/one/two', 'bar')
Returns: ['foo+bar', 'foo', 'bar', 'one', 'two', 'bar']
Arguments:
- `*args`: strings
"""
res = []
for arg in args:
if os.sep in arg:
splitted = split_path(arg)
for piece in reversed(splitted):
res.append(piece)
else:
res.append(arg)
return res


def concat_path(b, *args):
""" Concats b with all arguments in '*args', handles if any argument contains more then 1 directory, example: foo/bar/asd/
Note: this is analogous to list_path() except that this function returns a
string, though this function is not cross-platform since it uses a
hardcoded "/" instead of os.sep.
Arguments:
- `b`: string - base from where to concat all '*args'
- `*args`: strings - all extra paths to concat, concats in order of list
"""
base = b # tmp var
for a in args:
if "/" in a:
for s in a.split("/"):
base = os.path.join(base, s)
else:
base = os.path.join(base, a)

return base


def get_install_path(*args):
""" Returns the root directory, either the root of the filesystem or the
virtualenv root.
Arguments:
- `*args`: string that will be concatenated with the root directory
"""
if IN_VIRTUALENV:
path = sys.prefix
else:
# TODO can this be done in a more portable fashion? Untested on
# Windows.
path = os.sep
return concat_path(path, *args)



def get_etc_path(*args):
base = [get_install_path(), 'etc', PACKAGE_NAME]
path = base + list_path(*args)
return os.path.join(*path)


def get_share_path(*args):
base = [get_install_path(), 'usr', 'share', PACKAGE_NAME]
path = base + list_path(*args)
return os.path.join(*path)


def get_config_path(extra = ""):
""" Locates the config directory depending if installed or not, or if inside virtualenv or not.
Appends variable extra to the end of the located path.
"""
IN_VIRTUALENV = True if hasattr(sys, 'real_prefix') else False
if IN_VIRTUALENV:
path = os.path.join(sys.prefix, "etc", PACKAGE_NAME, extra)
if not os.path.exists(path): # we are not installed, running from source tree
(prefix, bindir) = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))
p = os.path.join(prefix, PACKAGE_NAME, "lib", "config", extra)
else:
p = path
else:
p = os.path.join(os.sep, 'etc', PACKAGE_NAME, extra)

return p
Loading

0 comments on commit c804544

Please sign in to comment.