Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type coercion of attributes #236

Open
notEthan opened this issue Mar 4, 2022 · 4 comments
Open

type coercion of attributes #236

notEthan opened this issue Mar 4, 2022 · 4 comments

Comments

@notEthan
Copy link
Owner

notEthan commented Mar 4, 2022

Base#[] could coerce children's types, based on format keyword or other indications of a more natural representation. e.g.:

  • format: date-time coerces to a ruby Time
  • format: uuid coerces to UUIDTools::UUID
    • application will have to install/Gemfile external dependencies
  • type: array + uniqueItems: true coerces to Set?
    • weird one. if the Set contains JSIs (ArrayNode#to_ary), they will never be equal, so never uniq'd (being at different pointers - unless I do end up changing Base#==/#hash to disregard pointer). I could skip adding nodes whose content is already in the Set, but that sounds bad.
    • Set is not appropriate if items is an array (or prefixItems/postfixItems used, later)
      • Set is, in practice, ordered, but not in theory.
      • if I do any uniquifying, indices will not match anyway
    • probably not a worthwhile idea, all around.

more thoughts:

  • Base#[]= must coerce opposite to Base#[]. instance data must stay as json types.
  • memoization or recalculation of coerced values? storing a coerced value from a setter? is coercion roundtrip-safe?
  • lots in common here with ActiveRecord/other ORMs' coercions from database types to ruby
@spacether
Copy link

spacether commented Sep 10, 2022

So I think that type coercion is only a good idea for accessors because it sounds like your instances subclass all validated schemas, right?
If so then you need to allow for non format types to also validate the instance payload.
Because you can have

allof:
- type: string
- type: string
  format: date

In python-experimental I make instances subclass all validated schemas and provide acessor methods for format data types.
One can see an example of the accessors here:
https://github.com/OpenAPITools/openapi-generator/blob/master/samples/openapi3/client/petstore/python-experimental/tests_manual/test_decimal_payload.py#L31

And one also needs to allow format to be applied on AnyType schemas like in:
OpenAPITools/openapi-generator#13360

@notEthan
Copy link
Owner Author

Hi Justin, good to hear from you.

only a good idea for accessors

I'm not sure how you mean this. Do you mean object property accessors? I think this would apply equally to any instance.

instances subclass all validated schemas

JSI instances are instances of mixins corresponding to every schema which describes them. This doesn't depend on validation, mostly, e.g. items and properties schemas apply to child instances whether or not they validate (though conditional application like with oneOf or contains is more complicated).

(This isn't really on topic related to type coersion, but worth clarifying I think.)

acessor methods for format data types

This might be the way to go. So far this is just some thoughts thrown together in an issue that I might implement eventually, so haven't figured out what kind of interface would work, allowing access to coerced vs. raw instance data.

And one also needs to allow format to be applied on AnyType schemas like in: OpenAPITools/openapi-generator#13360

I'm not sure what an AnyType schema means, and at a glance I'm not sure what that PR is doing (far too large for me to grok ... or even to tell what's generated code vs the actual origin of all the changes).

@spacether
Copy link

spacether commented Sep 13, 2022

An AnyType schema is an empty schema {}
More than just object property accessors. An accessor method on deserializsd schema instances. Methods like as_date as_datetime, as_decimal etc.

Here is an example of the accessor method as_decimal_oapg that converts a string into a Decimal

        m = DecimalPayload('12')
        assert isinstance(m, DecimalPayload)
        assert isinstance(m, DecimalSchema)
        assert isinstance(m, str)
        assert m == '12'
        assert m.as_decimal_oapg == decimal.Decimal('12')

@spacether
Copy link

spacether commented Sep 16, 2022

I was trying to point out these type unset (AnyType) + format example in my above PR

    AnyTypeAndFormat:
      type: object
      properties:
        uuid:
          format: uuid
        date:
          format: date
        date-time:
          format: date-time
        number:
          format: number
        binary:
          format: binary
        int32:
          format: int32
        int64:
          format: int64
        double:
          format: double
        float:
          format: float

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants