JSON schema arrays with uniqueItems=True creates a model using Python sets which are not serializable by default

Ouverte
#259 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
42/100
Type d'issue
Bug
Clarté
Plutôt claire
Activité
À l'abandon
Stack technique
python
Domaine
devtools

Piste de recherche

Commencez par le modèle AccessControl généré et suivez comment un modèle est renvoyé dans un ProgressEvent via la sérialisation JSON de Python. Reproduisez l’échec avec le schéma uniqueItems indiqué, puis vérifiez que le renvoi d’un modèle contenant des valeurs AbstractSet est sérialisé correctement sans conversions manuelles de set en list.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

When an definition in the JSON schema is an array with uniqueItems set to True, CFN generates a model with that attribute typed as an AbstractSet (or Python set in real terms) to guarantee that the items are unique. However the JSON module by default does not serialize sets and when the model is returned from the handler it raises an exception when trying to do so.

In order for the model to be returned I need to convert every set to a list in the model so it can be serialized back into JSON.

For example JSON Schema with the following definition:

"AccessControl": {
    "type": "object",
    "properties": {
        "Producers": {
            "type": "array",
            "uniqueItems": true,
            "insertionOrder": false,
            "items": { "type": "string" }  
        },
        "Consumers": {
            "type": "array",
            "uniqueItems": true,
            "insertionOrder": false,
            "items": { "type": "string" }  
        }
    },
    "required": [ "Producers", "Consumers" ],
    "additionalProperties": false
}

Generates a model with the following class

@dataclass
class AccessControl(BaseModel):
    Producers: Optional[AbstractSet[str]]
    Consumers: Optional[AbstractSet[str]]

    @classmethod
    def _deserialize(
        cls: Type["_AccessControl"],
        json_data: Optional[Mapping[str, Any]],
    ) -> Optional["_AccessControl"]:
        if not json_data:
            return None
        return cls(
            Producers=set_or_none(json_data.get("Producers")),
            Consumers=set_or_none(json_data.get("Consumers")),
        )

If the incoming model to the handler is populated and returned in a ProgressEvent the handler fails with an exception trying to serialize a set which it cant do by default. In order to return the model I have to convert every set to a list ie model.AccessControl.Producers = list(model.AccessControl.Producers). This can be tedious if there are multiple exit points in the handler and so should be handled by the model or by adding a set serializer to JSON.

Langage dominant
Python
Étoiles
107
Forks
46
Métriques de merge des PR
Aucune PR mergée en 30 j

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de aws-cloudformation/cloudformation-cli-python-plugin

Toutes les issues de aws-cloudformation/cloudformation-cli-python-plugin

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.