web-dev-qa-db-fra.com

Valider un document yaml en python

L'un des avantages de XML est de pouvoir valider un document par rapport à un fichier XSD. YAML n’ayant pas cette fonctionnalité, comment puis-je valider que le document YAML que j’ouvre est au format attendu par mon application?

43
Jon

Essayez Rx , il a une implémentation Python. Cela fonctionne sur JSON et YAML.

Depuis le site Rx:

"Lors de l'ajout d'une API à votre service Web, vous devez choisir le mode de codage des données que vous envoyez sur la ligne. XML est un choix courant, mais il peut rapidement devenir complexe et fastidieux. Beaucoup d'auteurs de services Web veulent éviter de penser à XML, mais choisissent plutôt des formats qui fournissent quelques types de données simples correspondant aux structures de données communes des langages de programmation modernes, à savoir JSON et YAML.

Malheureusement, bien que ces formats facilitent la transmission de structures de données complexes, ils n’ont pas de système de validation. XML a XML Schemas et RELAX NG, mais ce sont des normes compliquées et parfois déroutantes. Ils ne sont pas très portables pour le type de structure de données fourni par JSON, et si vous voulez éviter XML en tant que codage de données, écrire plus de XML pour valider le premier XML est probablement encore moins attrayant.

Rx est conçu pour fournir un système de validation des données qui correspond aux structures de données de style JSON et est aussi facile à utiliser que JSON lui-même. " </ Blockquote>

9
Lior

Étant donné que JSON et YAML sont des bêtes très similaires, vous pouvez utiliser JSON-Schema pour valider un sous-ensemble important de YAML. Voici un extrait de code (vous aurez besoin de PyYAML et jsonschema installed):

from jsonschema import validate
import yaml

schema = """
type: object
properties:
  testing:
    type: array
    items:
      enum:
        - this
        - is
        - a
        - test
"""

good_instance = """
testing: ['this', 'is', 'a', 'test']
"""

validate(yaml.load(good_instance), yaml.load(schema)) # passes

# Now let's try a bad instance...

bad_instance = """
testing: ['this', 'is', 'a', 'bad', 'test']
"""

validate(yaml.load(bad_instance), yaml.load(schema))

# Fails with:
# ValidationError: 'bad' is not one of ['this', 'is', 'a', 'test']
#
# Failed validating 'enum' in schema['properties']['testing']['items']:
#     {'enum': ['this', 'is', 'a', 'test']}
#
# On instance['testing'][3]:
#     'bad'

Un problème avec ceci est que si votre schéma s'étend sur plusieurs fichiers et que vous utilisez "$ref" pour référencer les autres fichiers, ceux-ci devront être JSON, je pense. Mais il y a probablement des moyens de contourner cela. Dans mon propre projet, je joue avec la spécification du schéma à l'aide de fichiers JSON, tandis que les instances sont YAML.

26
Jack Kelly

Oui, le support de validation est essentiel pour de nombreux cas d'utilisation importants. Voir par exemple YAML et l'importance de la validation de schéma «Stuart Gunter

Comme déjà mentionné, il existe Rx , disponible pour différentes langues, et Kwalify pour Ruby et Java.

Voir aussi la discussion sur PyYAML: YAMLSchemaDiscussion .

Un effort connexe est Schéma JSON , qui a même eu une activité de normalisation IETF ( draft-zyp-json-schema-03 - Un type de support JSON pour décrire la structure et la signification des documents JSON )

8
nealmcb

Celles-ci ont l'air bien. L'analyseur yaml peut gérer la syntaxe erorrs et l'une de ces bibliothèques peut valider les structures de données.

5
Gringo Suave

Je trouve Cerberus très fiable, avec une excellente documentation et une utilisation simple.

Voici un exemple d'implémentation de base:

my_yaml.yaml:

name: 'my_name'
date: 2017-10-01
metrics:
  percentage:
    value: 87
    trend: stable

Définir le schéma de validation dans schema.py:

{
    'name': {
        'required': True,
        'type': 'string'
    },
    'date': {
        'required': True,
        'type': 'date'
    },
    'metrics': {
        'required': True,
        'type': 'dict',
        'schema': {
            'percentage': {
                'required': True,
                'type': 'dict',
                'schema': {
                    'value': {
                        'required': True,
                        'type': 'number',
                        'min': 0,
                        'max': 100
                    }
                    'trend': {
                        'type': 'string',
                        'nullable': True,
                        'regex': '^(?i)(down|equal|up)$'
                    }
                }
            }
        }
    }
}

Utilisation de PyYaml pour charger un document yaml:

def __load_doc():
        with open(__yaml_path, 'r') as stream:
            try:
                return yaml.load(stream)
            except yaml.YAMLError as exception:
                raise exception

L'évaluation du fichier yaml est simple:

schema = eval(open('PATH_TO/schema.py', 'r').read())
        v = Validator(schema)
        doc = __load_doc()
        print v.validate(doc, schema)
        print v.errors

N'oubliez pas que Cerberus est un outil de validation de données agnostique, ce qui signifie qu'il peut prendre en charge d'autres formats que YAML, tels que JSON, XML, etc.

4

Je suis dans la même situation. Je dois valider les éléments de YAML.

Au début, je pensais que les balises PyYAML étaient la meilleure et la plus simple. Mais plus tard, a décidé d’utiliser «PyKwalify», qui définit en réalité un schéma pour YAML.

Étiquettes PyYAML:

Le fichier YAML a un support de balise où nous pouvons appliquer ces vérifications de base en préfixant le type de données. (par exemple) pour un entier - !! int "123"

Plus sur PyYAML: http://pyyaml.org/wiki/PyYAMLDocumentation#Tags .__ C'est bien, mais si vous allez exposer cela à l'utilisateur final, vous risquez de créer une confusion. J'ai fait des recherches pour définir un schéma de YAML. L'idée est que nous pouvons valider le YAML avec son schéma correspondant pour la vérification du type de données de base. Même nos validations personnalisées comme l'adresse IP, des chaînes aléatoires peuvent également être ajoutées. afin que nous puissions avoir notre schéma séparément, laissant YAML simple et lisible.

Je ne peux pas poster plus de liens. S'il vous plaît 'Schéma Google pour YAM'L pour afficher les discussions de schéma.

PyKwalify:

Il existe un paquet appelé PyKwalify qui sert cet objectif: https://pypi.python.org/pypi/pykwalify

Ce forfait correspond le mieux à mes besoins. J'ai essayé cela avec un petit exemple dans ma configuration locale et ça marche. Voici le fichier de schéma d'exemple.

#sample schema

type: map
mapping:
    Emp:
        type:    map
        mapping:
            name:
                type:      str
                required:  yes
            email:
                type:      str
            age:
                type:      int
            birth:
                type:     str

Fichier YAML valide pour ce schéma

---
Emp:
    name:   "abc"
    email:  "[email protected]"
    age:    yy
    birth:  "xx/xx/xxxx"

Merci 

3

J'ai enveloppé certaines bibliothèques python liées à JSON existantes visant à pouvoir les utiliser avec yaml ainsi

La bibliothèque python résultante enveloppe principalement ...

  • jsonschema - un validateur pour les fichiers json par rapport aux fichiers json-schema, étant encapsulé pour permettre la validation des fichiers yaml par rapport aux fichiers json-schema au format yaml-.

  • jsonpath-ng - implémentation de JSONPath pour python, encapsulée pour prendre en charge la sélection JSONPath directement sur les fichiers yaml.

... et est disponible sur github: 

https://github.com/yaccob/ytools

Il peut être installé en utilisant pip:

pip install ytools

Exemple de validation (from https://github.com/yaccob/ytools#validation ):

import ytools
ytools.validate("test/sampleschema.yaml", ["test/sampledata.yaml"])

Ce que vous n’obtenez pas encore, c’est valider contre les schémas externes au format yaml

ytools ne fournit rien de ce qui n’existait pas auparavant - cela rend simplement l’application de certaines solutions existantes plus flexible et plus pratique. 

0
yaccob

Vous pouvez charger un document YAML en tant que dict et utiliser library schema pour le vérifier:

from schema import Schema, And, Use, Optional, SchemaError
import yaml

schema = Schema(
        {
            'created': And(datetime.datetime),
            'author': And(str),
            'email': And(str),
            'description': And(str),
            Optional('tags'): And(str, lambda s: len(s) >= 0),
            'setup': And(list),
            'steps': And(list, lambda steps: all('=>' in s for s in steps), error='Steps should be array of string '
                                                                                  'and contain "=>" to separate'
                                                                                  'actions and expectations'),
            'teardown': And(list)
        }
    )

with open(filepath) as f:
   data = yaml.load(f)
   try:
       schema.validate(data)
   except SchemaError as e:
       print(e)
0
flipback

Vous pouvez utiliser yaml lib de python pour afficher le message/char/ligne/fichier du fichier chargé.

#!/usr/bin/env python

import yaml

with open("example.yaml", 'r') as stream:
    try:
        print(yaml.load(stream))
    except yaml.YAMLError as exc:
        print(exc)

Le message d'erreur est accessible via exc.problem

Accédez à exc.problem_mark pour obtenir un objet <yaml.error.Mark>

Cet objet vous permet d'accéder aux attributs

  • prénom
  • colonne
  • ligne

Vous pouvez donc créer votre propre pointeur sur le problème:

pm = exc.problem_mark
print("Your file {} has an issue on line {} at position {}".format(pm.name, pm.line, pm.column))
0
jaiks

Je ne suis pas au courant d'une solution Python. Mais il existe un validateur de schéma Ruby pour YAML appelé kwalify . Vous devriez pouvoir y accéder en utilisant un sous-processus si vous ne rencontrez pas de bibliothèque python.

0
ars