Skip to content

Commit 3e804cd

Browse files
fix: preserve fragments when rewriting variant refs (#64)
* fix: preserve fragments when rewriting variant refs * fix: propagate variant needs for refs with fragments * fix: regenerate models to reflect fixed propagation * style: format __init__.py files with pre-commit --------- Co-authored-by: damaz91 <federico.damato91@gmail.com>
1 parent ec6b32a commit 3e804cd

12 files changed

Lines changed: 541 additions & 24 deletions

preprocess_schemas.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -449,16 +449,21 @@ def rewrite_refs_to_variants(root, op, file_path, variant_needs):
449449
for node in iter_nodes(root):
450450
if isinstance(node, dict) and "$ref" in node:
451451
ref = node["$ref"]
452-
if "#" not in ref: # External file reference
453-
abs_target = (file_path.parent / ref).resolve()
454-
if (
455-
str(abs_target) in variant_needs
456-
and op in variant_needs[str(abs_target)]
457-
):
458-
ref_path = Path(ref)
459-
node["$ref"] = str(
460-
ref_path.parent / f"{ref_path.stem}_{op}_request.json"
461-
)
452+
ref_file, separator, fragment = ref.partition("#")
453+
if not ref_file:
454+
continue
455+
abs_target = (file_path.parent / ref_file).resolve()
456+
if (
457+
str(abs_target) in variant_needs
458+
and op in variant_needs[str(abs_target)]
459+
):
460+
ref_path = Path(ref_file)
461+
variant_ref = str(
462+
ref_path.parent / f"{ref_path.stem}_{op}_request.json"
463+
)
464+
node["$ref"] = variant_ref + (
465+
separator + fragment if separator else ""
466+
)
462467

463468

464469
def _apply_request_rules_to_object(
@@ -592,8 +597,9 @@ def extract_external_refs(schema, path):
592597
for node in iter_nodes(data):
593598
if isinstance(node, dict) and "$ref" in node:
594599
ref = node["$ref"]
595-
if "#" not in ref:
596-
abs_path = str((path.parent / ref).resolve())
600+
ref_file, _, _ = ref.partition("#")
601+
if ref_file:
602+
abs_path = str((path.parent / ref_file).resolve())
597603
refs.append((name, abs_path))
598604
return refs
599605

src/ucp_sdk/models/schemas/shopping/payment_complete_request.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from pydantic import BaseModel, ConfigDict
2222

23-
from .types import payment_instrument
23+
from .types import payment_instrument_complete_request
2424

2525

2626
class PaymentCompleteRequest(BaseModel):
@@ -31,9 +31,10 @@ class PaymentCompleteRequest(BaseModel):
3131
model_config = ConfigDict(
3232
extra="allow",
3333
)
34-
instruments: list[payment_instrument.SelectedPaymentInstrument] | None = (
35-
None
36-
)
34+
instruments: (
35+
list[payment_instrument_complete_request.SelectedPaymentInstrument]
36+
| None
37+
) = None
3738
"""
3839
The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields.
3940
"""

src/ucp_sdk/models/schemas/shopping/payment_create_request.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from pydantic import BaseModel, ConfigDict
2222

23-
from .types import payment_instrument
23+
from .types import payment_instrument_create_request
2424

2525

2626
class PaymentCreateRequest(BaseModel):
@@ -31,9 +31,9 @@ class PaymentCreateRequest(BaseModel):
3131
model_config = ConfigDict(
3232
extra="allow",
3333
)
34-
instruments: list[payment_instrument.SelectedPaymentInstrument] | None = (
35-
None
36-
)
34+
instruments: (
35+
list[payment_instrument_create_request.SelectedPaymentInstrument] | None
36+
) = None
3737
"""
3838
The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields.
3939
"""

src/ucp_sdk/models/schemas/shopping/payment_update_request.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from pydantic import BaseModel, ConfigDict
2222

23-
from .types import payment_instrument
23+
from .types import payment_instrument_update_request
2424

2525

2626
class PaymentUpdateRequest(BaseModel):
@@ -31,9 +31,9 @@ class PaymentUpdateRequest(BaseModel):
3131
model_config = ConfigDict(
3232
extra="allow",
3333
)
34-
instruments: list[payment_instrument.SelectedPaymentInstrument] | None = (
35-
None
36-
)
34+
instruments: (
35+
list[payment_instrument_update_request.SelectedPaymentInstrument] | None
36+
) = None
3737
"""
3838
The payment instruments available for this payment. Each instrument is associated with a specific handler via the handler_id field. Handlers can extend the base payment_instrument schema to add handler-specific fields.
3939
"""
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2026 UCP Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# generated by datamodel-codegen
16+
# pylint: disable=all
17+
# pyformat: disable
18+
19+
from __future__ import annotations
20+
21+
from pydantic import BaseModel, ConfigDict
22+
23+
24+
class PaymentCredentialCompleteRequest(BaseModel):
25+
"""
26+
The base definition for any payment credential. Handlers define specific credential types.
27+
"""
28+
29+
model_config = ConfigDict(
30+
extra="allow",
31+
)
32+
type: str
33+
"""
34+
The credential type discriminator. Specific schemas will constrain this to a constant value.
35+
"""
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2026 UCP Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# generated by datamodel-codegen
16+
# pylint: disable=all
17+
# pyformat: disable
18+
19+
from __future__ import annotations
20+
21+
from pydantic import BaseModel, ConfigDict
22+
23+
24+
class PaymentCredentialCreateRequest(BaseModel):
25+
"""
26+
The base definition for any payment credential. Handlers define specific credential types.
27+
"""
28+
29+
model_config = ConfigDict(
30+
extra="allow",
31+
)
32+
type: str
33+
"""
34+
The credential type discriminator. Specific schemas will constrain this to a constant value.
35+
"""
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2026 UCP Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# generated by datamodel-codegen
16+
# pylint: disable=all
17+
# pyformat: disable
18+
19+
from __future__ import annotations
20+
21+
from pydantic import BaseModel, ConfigDict
22+
23+
24+
class PaymentCredentialUpdateRequest(BaseModel):
25+
"""
26+
The base definition for any payment credential. Handlers define specific credential types.
27+
"""
28+
29+
model_config = ConfigDict(
30+
extra="allow",
31+
)
32+
type: str
33+
"""
34+
The credential type discriminator. Specific schemas will constrain this to a constant value.
35+
"""
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Copyright 2026 UCP Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# generated by datamodel-codegen
16+
# pylint: disable=all
17+
# pyformat: disable
18+
19+
from __future__ import annotations
20+
21+
from typing import Any
22+
23+
from pydantic import BaseModel, ConfigDict
24+
25+
from . import (
26+
payment_credential_complete_request,
27+
postal_address_complete_request,
28+
)
29+
30+
31+
class PaymentInstrumentCompleteRequest(BaseModel):
32+
"""
33+
The base definition for any payment instrument. It links the instrument to a specific payment handler.
34+
"""
35+
36+
model_config = ConfigDict(
37+
extra="allow",
38+
)
39+
id: str
40+
"""
41+
A unique identifier for this instrument instance, assigned by the platform.
42+
"""
43+
handler_id: str
44+
"""
45+
The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition.
46+
"""
47+
type: str
48+
"""
49+
The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value.
50+
"""
51+
billing_address: (
52+
postal_address_complete_request.PostalAddressCompleteRequest | None
53+
) = None
54+
"""
55+
The billing address associated with this payment method.
56+
"""
57+
credential: (
58+
payment_credential_complete_request.PaymentCredentialCompleteRequest
59+
| None
60+
) = None
61+
display: dict[str, Any] | None = None
62+
"""
63+
Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler.
64+
"""
65+
66+
67+
class SelectedPaymentInstrument(PaymentInstrumentCompleteRequest):
68+
"""
69+
A payment instrument with selection state.
70+
"""
71+
72+
model_config = ConfigDict(
73+
extra="allow",
74+
)
75+
selected: bool | None = None
76+
"""
77+
Whether this instrument is selected by the user.
78+
"""
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright 2026 UCP Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# generated by datamodel-codegen
16+
# pylint: disable=all
17+
# pyformat: disable
18+
19+
from __future__ import annotations
20+
21+
from typing import Any
22+
23+
from pydantic import BaseModel, ConfigDict
24+
25+
from . import payment_credential_create_request, postal_address_create_request
26+
27+
28+
class PaymentInstrumentCreateRequest(BaseModel):
29+
"""
30+
The base definition for any payment instrument. It links the instrument to a specific payment handler.
31+
"""
32+
33+
model_config = ConfigDict(
34+
extra="allow",
35+
)
36+
id: str
37+
"""
38+
A unique identifier for this instrument instance, assigned by the platform.
39+
"""
40+
handler_id: str
41+
"""
42+
The unique identifier for the handler instance that produced this instrument. This corresponds to the 'id' field in the Payment Handler definition.
43+
"""
44+
type: str
45+
"""
46+
The broad category of the instrument (e.g., 'card', 'tokenized_card'). Specific schemas will constrain this to a constant value.
47+
"""
48+
billing_address: (
49+
postal_address_create_request.PostalAddressCreateRequest | None
50+
) = None
51+
"""
52+
The billing address associated with this payment method.
53+
"""
54+
credential: (
55+
payment_credential_create_request.PaymentCredentialCreateRequest | None
56+
) = None
57+
display: dict[str, Any] | None = None
58+
"""
59+
Display information for this payment instrument. Each payment instrument schema defines its specific display properties, as outlined by the payment handler.
60+
"""
61+
62+
63+
class SelectedPaymentInstrument(PaymentInstrumentCreateRequest):
64+
"""
65+
A payment instrument with selection state.
66+
"""
67+
68+
model_config = ConfigDict(
69+
extra="allow",
70+
)
71+
selected: bool | None = None
72+
"""
73+
Whether this instrument is selected by the user.
74+
"""

0 commit comments

Comments
 (0)