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

🚧 Some improvements for Coordinate type PR #2

Conversation

lig
Copy link

@lig lig commented Jul 5, 2023

No description provided.

@lig lig force-pushed the lig/add-coordinate-latitude-longitude branch from ceb992b to 6440acd Compare July 5, 2023 14:59
@JeanArhancet JeanArhancet force-pushed the feat/add-coordinate-latitude-longitude branch 3 times, most recently from 35a45d8 to b5e7993 Compare July 5, 2023 15:37
@lig lig force-pushed the lig/add-coordinate-latitude-longitude branch from 6440acd to 4bc6007 Compare July 5, 2023 18:39
@lig lig force-pushed the lig/add-coordinate-latitude-longitude branch from 4bc6007 to ed74ea4 Compare July 6, 2023 12:58
@JeanArhancet
Copy link
Owner

Thanks @lig

On my side I've change your implementation to this (parse_args -> parse_str -> parse_tuple) but latitude, longitude validation no longer works. WDYT?

@classmethod
    def __get_pydantic_core_schema__(
            cls, source: Type[Any], handler: GetCoreSchemaHandler
    ) -> core_schema.CoreSchema:
        float_schema = core_schema.float_schema()
        result = core_schema.no_info_before_validator_function(
            cls._parse_args,
            core_schema.union_schema(
                [
                    handler(source),
                    core_schema.no_info_before_validator_function(
                        cls._parse_str,
                        core_schema.no_info_after_validator_function(
                            cls._parse_tuple,
                            core_schema.tuple_positional_schema([float_schema, float_schema]),
                        ),
                    )
                ]
            ),
        )
        return result

    @classmethod
    def _parse_args(cls, value: Any) -> Any:
        if not isinstance(value, ArgsKwargs):
            return value

        args, kwargs = value.args, value.kwargs

        if kwargs:
            return kwargs
        if not args:
            return cls._NULL_ISLAND
        if len(args) == 1:
            return args[0]
        return args

    @classmethod
    def _parse_tuple(cls, value: tuple[float, float]) -> 'Coordinate':
        return cls(latitude=Latitude(value[0]), longitude=Longitude(value[1]))

    @classmethod
    def _parse_str(cls, value: Any) -> Tuple[float, float]:
        if isinstance(value, (str, bytes)):
            try:
                value = tuple([float(x) for x in value.split(',')])
            except ValueError:
                raise PydanticCustomError(
                    'coordinate_error',
                    'value is not a valid coordinate: string is not recognized as a valid coordinate'
                )

        return value

@lig lig force-pushed the lig/add-coordinate-latitude-longitude branch 2 times, most recently from 2ae4694 to af1a98d Compare July 6, 2023 16:15
@JeanArhancet JeanArhancet force-pushed the feat/add-coordinate-latitude-longitude branch 4 times, most recently from 9f627d7 to 074d27c Compare July 7, 2023 12:03
if n_args == 0:
value = cls._NULL_ISLAND
elif n_args == 1:
value = value.args[0]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my branch I've modified this part to add a default latitude, otherwise we'll get an error

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an error about the error case that is needed. We get an error for case like (20.0,) that is a tuple with a single value. This case is in tests as invalid.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You’re right but maybe we can raise an error directly, WDYT?

@JeanArhancet JeanArhancet force-pushed the feat/add-coordinate-latitude-longitude branch from f626e0c to 599a4e6 Compare July 7, 2023 17:26
@lig lig force-pushed the lig/add-coordinate-latitude-longitude branch 2 times, most recently from 7d5fd0d to 4d21b4d Compare July 7, 2023 17:43
@JeanArhancet
Copy link
Owner

JeanArhancet commented Jul 7, 2023

I've updated the function __get_pydantic_core_schema_ from the commit 687f74b and the properties does refer to the Longitude/Latitude limit.
WDYT @lig ?

    def __get_pydantic_core_schema__(cls, source: type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
        return core_schema.no_info_wrap_validator_function(
            cls._parse_args,
            core_schema.no_info_wrap_validator_function(
                cls._parse_str,
                core_schema.chain_schema(
                    [
                        core_schema.no_info_wrap_validator_function(
                            cls._parse_tuple, handler.generate_schema(Tuple[Latitude, Longitude])
                        ),
                        handler(source),
                    ]
                ),
            ),
        )

Schema:

 {
                'properties': {
                    'x': {
                        'format': 'coordinate',
                        'maxItems': 2,
                        'minItems': 2,
                        'prefixItems': [
                            {'maximum': 90.0, 'minimum': -90.0, 'type': 'number'},
                            {'maximum': 180.0, 'minimum': -180.0, 'type': 'number'},
                        ],
                        'title': 'X',
                        'type': 'array',
                    }
                },
                'required': ['x'],
                'title': 'Model',
                'type': 'object',
            },
}

@JeanArhancet JeanArhancet force-pushed the feat/add-coordinate-latitude-longitude branch from 599a4e6 to 13cacb6 Compare July 24, 2023 07:23
@lig lig force-pushed the lig/add-coordinate-latitude-longitude branch from 4d21b4d to b441a0b Compare July 26, 2023 15:35
]
),
core_schema.union_schema(
[core_schema.chain_schema(schema_chain[2 - x :]) for x in range(3)],
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your help, but I don't understand why range(3) and schema_chain[2 - x :] ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The full schema chain includes all three steps of conversion.
We allow entering this chain of transformations from any step. Thus we generate something that could be simplified like this: union([chain([3]), chain([2, 3]), chain([1, 2, 3])]).

@lig
Copy link
Author

lig commented Jul 26, 2023

@JeanArhancet Sorry, I was ill. Now I'm back:)

I've updated my changes. The idea here is that we accept three forms of coordinate for validation and using a canonical form for serialization. This is reflected in the schema being generated for this type (see test_json_schema test)

In my opinion representing Coordinate as object by default for serialization is more useful for further processing data by external consumers, e.g. SPA Web App.

It's possible to implement another type, i.e. CoordinateStr, that uses string representation for serialization. This shouldn't necessarily be a part of this PR.

Please, notice that schema generation requires pydantic>=2.0.3 because of pydantic/pydantic#6515

@JeanArhancet
Copy link
Owner

JeanArhancet commented Jul 26, 2023

@JeanArhancet Sorry, I was ill. Now I'm back:)

I've updated my changes. The idea here is that we accept three forms of coordinate for validation and using a canonical form for serialization. This is reflected in the schema being generated for this type (see test_json_schema test)

In my opinion representing Coordinate as object by default for serialization is more useful for further processing data by external consumers, e.g. SPA Web App.

It's possible to implement another type, i.e. CoordinateStr, that uses string representation for serialization. This shouldn't necessarily be a part of this PR.

Please, notice that schema generation requires pydantic>=2.0.3 because of pydantic/pydantic#6515

I understand better thanks a lot. Maybe we can create a variable to explain this 3 ? numSchemaSupported ?(or comments), WDYT?

@lig
Copy link
Author

lig commented Jul 26, 2023

I understand better thanks a lot. Maybe we can create a variable to explain this 3 ? numSchemaSupported ?(or comments), WDYT?

Indeed, it could be more readable and robust to do something like this: chain_length = len(schema_chain) and use this variable.

Could you please take it from here on your PR?

@JeanArhancet JeanArhancet merged commit 0a79122 into JeanArhancet:feat/add-coordinate-latitude-longitude Jul 26, 2023
@lig lig deleted the lig/add-coordinate-latitude-longitude branch July 26, 2023 16:11
JeanArhancet added a commit that referenced this pull request Aug 6, 2023
* feat: add latitude, longitude and coordinate

* refactor: apply feedbacks

* refactor: apply feedbacks

* refactor: delete __init__ functions

* fix: coordinate parsing

* docs: update coordinate documentation

* refactor: use latitude, longitude in schema

* 🚧 Some improvements for `Coordinate` type PR (#2)

* refactor: delete __init__ functions

* 🚧 Some improvements for `Coordinate` type PR

* Get tests passing

* ✨ Test serialization json schema

* ⬆ Upgrade deps in `pyproject.toml` and `requirements/pyproject.txt

---------

Co-authored-by: JeanArhancet <jean.arhancetebehere@gmail.com>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

* fix: test and requirements

* docs: fix supported format

---------

Co-authored-by: Serge Matveenko <lig@countzero.co>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>
JeanArhancet added a commit that referenced this pull request Aug 23, 2023
* feat: add latitude, longitude and coordinate

* refactor: apply feedbacks

* refactor: apply feedbacks

* refactor: delete __init__ functions

* fix: coordinate parsing

* docs: update coordinate documentation

* refactor: use latitude, longitude in schema

* 🚧 Some improvements for `Coordinate` type PR (#2)

* refactor: delete __init__ functions

* 🚧 Some improvements for `Coordinate` type PR

* Get tests passing

* ✨ Test serialization json schema

* ⬆ Upgrade deps in `pyproject.toml` and `requirements/pyproject.txt

---------

Co-authored-by: JeanArhancet <jean.arhancetebehere@gmail.com>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

* fix: test and requirements

* docs: fix supported format

---------

Co-authored-by: Serge Matveenko <lig@countzero.co>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>
JeanArhancet added a commit that referenced this pull request Aug 23, 2023
* feat: add latitude, longitude and coordinate

* refactor: apply feedbacks

* refactor: apply feedbacks

* refactor: delete __init__ functions

* fix: coordinate parsing

* docs: update coordinate documentation

* refactor: use latitude, longitude in schema

* 🚧 Some improvements for `Coordinate` type PR (#2)

* refactor: delete __init__ functions

* 🚧 Some improvements for `Coordinate` type PR

* Get tests passing

* ✨ Test serialization json schema

* ⬆ Upgrade deps in `pyproject.toml` and `requirements/pyproject.txt

---------

Co-authored-by: JeanArhancet <jean.arhancetebehere@gmail.com>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

* fix: test and requirements

* docs: fix supported format

---------

Co-authored-by: Serge Matveenko <lig@countzero.co>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>
JeanArhancet added a commit that referenced this pull request Oct 30, 2023
* feat: add latitude, longitude and coordinate

* refactor: apply feedbacks

* refactor: apply feedbacks

* refactor: delete __init__ functions

* fix: coordinate parsing

* docs: update coordinate documentation

* refactor: use latitude, longitude in schema

* 🚧 Some improvements for `Coordinate` type PR (#2)

* refactor: delete __init__ functions

* 🚧 Some improvements for `Coordinate` type PR

* Get tests passing

* ✨ Test serialization json schema

* ⬆ Upgrade deps in `pyproject.toml` and `requirements/pyproject.txt

---------

Co-authored-by: JeanArhancet <jean.arhancetebehere@gmail.com>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

* fix: test and requirements

* docs: fix supported format

---------

Co-authored-by: Serge Matveenko <lig@countzero.co>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>
JeanArhancet added a commit that referenced this pull request Oct 30, 2023
Add `Latitude`, `Longitude` and `Coordinate`  (pydantic#76)

* feat: add latitude, longitude and coordinate

* refactor: apply feedbacks

* refactor: apply feedbacks

* refactor: delete __init__ functions

* fix: coordinate parsing

* docs: update coordinate documentation

* refactor: use latitude, longitude in schema

* 🚧 Some improvements for `Coordinate` type PR (#2)

* refactor: delete __init__ functions

* 🚧 Some improvements for `Coordinate` type PR

* Get tests passing

* ✨ Test serialization json schema

* ⬆ Upgrade deps in `pyproject.toml` and `requirements/pyproject.txt

---------

Co-authored-by: JeanArhancet <jean.arhancetebehere@gmail.com>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

* fix: test and requirements

* docs: fix supported format

---------

Co-authored-by: Serge Matveenko <lig@countzero.co>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

✨  add ulib type

refactor: delete init function
JeanArhancet added a commit that referenced this pull request Oct 30, 2023
Add `Latitude`, `Longitude` and `Coordinate`  (pydantic#76)

* feat: add latitude, longitude and coordinate

* refactor: apply feedbacks

* refactor: apply feedbacks

* refactor: delete __init__ functions

* fix: coordinate parsing

* docs: update coordinate documentation

* refactor: use latitude, longitude in schema

* 🚧 Some improvements for `Coordinate` type PR (#2)

* refactor: delete __init__ functions

* 🚧 Some improvements for `Coordinate` type PR

* Get tests passing

* ✨ Test serialization json schema

* ⬆ Upgrade deps in `pyproject.toml` and `requirements/pyproject.txt

---------

Co-authored-by: JeanArhancet <jean.arhancetebehere@gmail.com>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

* fix: test and requirements

* docs: fix supported format

---------

Co-authored-by: Serge Matveenko <lig@countzero.co>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

✨  add ulib type

refactor: delete init function
JeanArhancet added a commit that referenced this pull request Nov 8, 2023
Add `Latitude`, `Longitude` and `Coordinate`  (pydantic#76)

* feat: add latitude, longitude and coordinate

* refactor: apply feedbacks

* refactor: apply feedbacks

* refactor: delete __init__ functions

* fix: coordinate parsing

* docs: update coordinate documentation

* refactor: use latitude, longitude in schema

* 🚧 Some improvements for `Coordinate` type PR (#2)

* refactor: delete __init__ functions

* 🚧 Some improvements for `Coordinate` type PR

* Get tests passing

* ✨ Test serialization json schema

* ⬆ Upgrade deps in `pyproject.toml` and `requirements/pyproject.txt

---------

Co-authored-by: JeanArhancet <jean.arhancetebehere@gmail.com>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

* fix: test and requirements

* docs: fix supported format

---------

Co-authored-by: Serge Matveenko <lig@countzero.co>
Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>

✨  add ulib type

refactor: delete init function
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

Successfully merging this pull request may close these issues.

3 participants