0

Given that

the input data x are:

{'comm_name': 'XXX', 'comm_value': '1234:5678', 'dev_name': 'router-1'}

The marshmallow schema is as follows:

class BGPcommunitiesPostgresqlSchema(marshmallow.Schema):
    comm_name = marshmallow.fields.Str(required=True)
    comm_value = marshmallow.fields.Str(required=True)

    @marshmallow.validates('comm_value')
    def check_comm_value(self, value):
        if value.count(":") < 1:
            raise marshmallow.ValidationError("a BGP community value should contain at least once the `:` char")
        if value.count(":") > 2:
            raise marshmallow.ValidationError("a BGP community value should contain no more than two `:` chars")

Let's load it and its data:

schema  = BGPcommunitiesPostgresqlSchema()
zzz = schema.load(x)

If we print that, we get:

zzz.data
Out[17]: {'comm_name': u'XXX', 'comm_value': u'1234:5678'}

Objective: I would like the end result to be:

In [20]: zzz.data
Out[20]: (u'XXX', u'1234:5678')

How can I achieve that result (tuple) when I do zzz.data instead of getting the dict ?

Adam Smith
  • 52,157
  • 12
  • 73
  • 112
nskalis
  • 2,232
  • 8
  • 30
  • 49
  • Try with `zzz.data.items()` – zwer May 24 '17 at 18:50
  • @zwer thanks.. but the question is to get a tuple of the values from the marshmallow schema so that `zzz.data` to return `(u'XXX', u'1234:5678')` – nskalis May 24 '17 at 18:53
  • Why do you want to do this? – Adam Smith May 24 '17 at 18:57
  • well, i am doing dynamic import of libraries and would like to save a dataset to a number of different datastores (elasticsearch, postgresql, etc.) without writing any code. elasticsearch takes as input a json doc, postgresql takes as input a tuple – nskalis May 24 '17 at 19:00
  • 1
    Oh... well, just turn the list of values into a tuple: `tuple(zzz.data.values())` - edit, I get it, you want marshmallow to do it for you... Check Adam Smith's answer... – zwer May 24 '17 at 19:03
  • rolled back to remove irrelevant error handling information. – Adam Smith May 24 '17 at 19:36

1 Answers1

1

According to the docs you can define a @post_load decorated function to return an object after loading the schema.

class BGPcommunitiesPostgresqlSchema(marshmallow.Schema):
    comm_name = marshmallow.fields.Str(required=True)
    comm_value = marshmallow.fields.Str(required=True)

    @marshmallow.validates('comm_value')
    def check_comm_value(self, value):
        if value.count(":") < 1:
            raise marshmallow.ValidationError("a BGP community value should contain at least once the `:` char")
        if value.count(":") > 2:
            raise marshmallow.ValidationError("a BGP community value should contain no more than two `:` chars")

    @marshmallow.post_load
    def value_tuple(self, data):
        return (data["comm_name"], data["comm_value"])
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • Note that I think this is a bad idea overall, and will decrease code quality. You should be providing adapters to output to different serialization strategies (`marsh_to_postgre(in_: dict) -> tuple:`, `marsh_to_elastic(in_: dict) -> str:`, etc). Trying to shoehorn this all into one attribute "data" seems foolish. – Adam Smith May 24 '17 at 19:06
  • thanks! will consider that! by the way, i am facing an issue: the `data` variable inside `value_tuple` function seem to be not-validated. how do i ensure that `data` is after validation ? – nskalis May 24 '17 at 19:17
  • I assume that validation happens during schema load. Are you checking for errors there? The docs recommend doing `schema = BGPcommunitiesPostgresqlSchema(); zzz, errors = schema.load(x)` and checking `errors`. Further it says you can initialize the schema with the `strict=True` kwargs to throw an exception rather than generate an error dict. (`schema = BGPcommunitiesPostgresqlSchema(strict=True)`) – Adam Smith May 24 '17 at 19:20
  • 2
    Please *DO* note that both your questions so far I've been able to answer in a 10 minute reading of the first page of the quickstart guide to marshmallow. I've never used this library before. That implies you haven't done enough independent research before asking the question. – Adam Smith May 24 '17 at 19:23
  • thanks! I just added a comment how i treat the errors. – nskalis May 24 '17 at 19:24
  • ok, i am getting the validation error, but for some reason reason the `del` does not remove the corresponding item – nskalis May 24 '17 at 19:34
  • 1
    @NikosSkalis since you haven't demonstrated basic understanding of the library you're using, nor willingness to do basic research to solve your own problem, I'm unwilling to answer three questions for you within a half hour's time. Stack Overflow is not a codewriting service. Spend a couple days on it, and if you can't figure it out, feel free to ask another question. – Adam Smith May 24 '17 at 19:36