Skip to content

Commit 26a6553

Browse files
authored
Merge pull request #74 from NorthShoreAutomation/bugfix/bad-response-for-field-mutations
This update fixes validation errors that occurred when creating and u…
2 parents 681e9e1 + 61d851c commit 26a6553

File tree

4 files changed

+316
-43
lines changed

4 files changed

+316
-43
lines changed

docs/CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Changelog
22

3+
## 2025-05-08 "Metadata Field API Improvements & Bugfixes" - version 1.12.0
4+
5+
### Fixed
6+
- Fixed validation errors in field creation and updating by changing the return type from `Field` to `FieldResponse` model
7+
8+
### Changed
9+
- **Improved Metadata Field API (in `pythonik.specs.metadata.MetadataSpec`):**
10+
- Renamed `create_metadata_field()` to `create_field()` for more consistent naming
11+
- Renamed `update_metadata_field()` to `update_field()` for more consistent naming
12+
- Renamed `delete_metadata_field()` to `delete_field()` for more consistent naming
13+
- Return type now uses `FieldResponse` model instead of `Field` for more comprehensive metadata field information
14+
- Added backward compatibility aliases for the old method names (will be removed in a future version)
15+
- **Testing:**
16+
- Updated all tests to use the new method names and return types
17+
- Added tests to verify backward compatibility aliases work correctly
18+
19+
### Technical Details
20+
This update fixes validation errors that occurred when creating and updating metadata fields by correctly using the `FieldResponse` model instead of `Field`, making the API work as expected. It also improves the metadata field management API with more consistent method naming while maintaining backward compatibility through aliases. The `FieldResponse` model provides the proper structure for the API responses, and the backward compatibility aliases ensure existing code continues to work correctly.
21+
322
## 2025-05-08 "Metadata Field Management & Type Safety" - version 1.11.0
423

524
### Added

pythonik/models/metadata/fields.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,30 @@ class Field(_FieldConfigurable):
7171
date_created: Optional[datetime] = None
7272
date_modified: Optional[datetime] = None
7373
mapped_field_name: Optional[str] = None
74+
75+
class FieldResponse(BaseModel):
76+
auto_set: bool
77+
date_created: datetime
78+
date_modified: datetime
79+
description: Optional[str] = None
80+
external_id: Optional[str] = None
81+
field_type: IconikFieldType
82+
hide_if_not_set: bool
83+
is_block_field: bool
84+
is_warning_field: bool
85+
label: str
86+
mapped_field_name: Optional[str] = None
87+
max_value: Optional[float] = None
88+
min_value: Optional[float] = None
89+
multi: bool
90+
name: str
91+
options: Optional[List[FieldOption]] = None
92+
read_only: bool
93+
representative: bool
94+
required: bool
95+
sortable: bool
96+
source_url: Optional[HttpUrl] = None
97+
use_as_facet: bool
98+
99+
class Config:
100+
use_enum_values = True

pythonik/specs/metadata.py

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
CreateViewRequest,
66
UpdateViewRequest,
77
)
8-
from pythonik.models.metadata.view_responses import ViewResponse, ViewListResponse
8+
from pythonik.models.metadata.view_responses import (
9+
ViewResponse,
10+
ViewListResponse,
11+
)
912
from pythonik.models.mutation.metadata.mutate import (
1013
UpdateMetadata,
1114
UpdateMetadataResponse,
1215
)
13-
from pythonik.models.metadata.fields import Field, FieldCreate, FieldUpdate
16+
from pythonik.models.metadata.fields import FieldCreate, FieldUpdate, FieldResponse
1417
from pythonik.specs.base import Spec
1518
from typing import Literal, Union, Dict, Any, List
1619

@@ -401,7 +404,7 @@ def delete_view(self, view_id: str, **kwargs) -> Response:
401404
# Metadata Field Management
402405
# -------------------------
403406

404-
def create_metadata_field(
407+
def create_field(
405408
self,
406409
field_data: FieldCreate,
407410
exclude_defaults: bool = True,
@@ -415,15 +418,16 @@ def create_metadata_field(
415418
**kwargs: Additional kwargs to pass to the request.
416419
417420
Returns:
418-
Response: The created metadata field.
421+
Response: An object containing the HTTP response and a `data` attribute
422+
with a `FieldResponse` model instance on success, or `None` on error.
419423
"""
420424
json_data = self._prepare_model_data(
421425
field_data, exclude_defaults=exclude_defaults
422426
)
423427
resp = self._post(FIELDS_BASE_PATH, json=json_data, **kwargs)
424-
return self.parse_response(resp, Field)
428+
return self.parse_response(resp, FieldResponse)
425429

426-
def update_metadata_field(
430+
def update_field(
427431
self,
428432
field_name: str,
429433
field_data: FieldUpdate,
@@ -439,16 +443,17 @@ def update_metadata_field(
439443
**kwargs: Additional kwargs to pass to the request.
440444
441445
Returns:
442-
Response: The updated metadata field.
446+
Response: An object containing the HTTP response and a `data` attribute
447+
with a `FieldResponse` model instance on success, or `None` on error.
443448
"""
444449
json_data = self._prepare_model_data(
445450
field_data, exclude_defaults=exclude_defaults
446451
)
447452
endpoint = FIELD_BY_NAME_PATH.format(field_name=field_name)
448453
resp = self._put(endpoint, json=json_data, **kwargs)
449-
return self.parse_response(resp, Field)
454+
return self.parse_response(resp, FieldResponse)
450455

451-
def delete_metadata_field(
456+
def delete_field(
452457
self,
453458
field_name: str,
454459
**kwargs,
@@ -465,3 +470,68 @@ def delete_metadata_field(
465470
endpoint = FIELD_BY_NAME_PATH.format(field_name=field_name)
466471
resp = self._delete(endpoint, **kwargs)
467472
return self.parse_response(resp)
473+
474+
# Backward compatibility aliases
475+
# ------------------------------
476+
477+
def create_metadata_field(
478+
self,
479+
field_data: FieldCreate,
480+
exclude_defaults: bool = True,
481+
**kwargs,
482+
) -> Response:
483+
"""Create a new metadata field (deprecated, use create_field instead).
484+
485+
This method is kept for backward compatibility and will be removed in a future version.
486+
487+
Args:
488+
field_data: The data for the new field.
489+
exclude_defaults: Whether to exclude default values when dumping Pydantic models.
490+
**kwargs: Additional kwargs to pass to the request.
491+
492+
Returns:
493+
Response: An object containing the HTTP response and a `data` attribute
494+
with a `FieldResponse` model instance on success, or `None` on error.
495+
"""
496+
return self.create_field(field_data, exclude_defaults, **kwargs)
497+
498+
def update_metadata_field(
499+
self,
500+
field_name: str,
501+
field_data: FieldUpdate,
502+
exclude_defaults: bool = True,
503+
**kwargs,
504+
) -> Response:
505+
"""Update an existing metadata field by its name (deprecated, use update_field instead).
506+
507+
This method is kept for backward compatibility and will be removed in a future version.
508+
509+
Args:
510+
field_name: The name of the field to update.
511+
field_data: The data to update the field with.
512+
exclude_defaults: Whether to exclude default values when dumping Pydantic models.
513+
**kwargs: Additional kwargs to pass to the request.
514+
515+
Returns:
516+
Response: An object containing the HTTP response and a `data` attribute
517+
with a `FieldResponse` model instance on success, or `None` on error.
518+
"""
519+
return self.update_field(field_name, field_data, exclude_defaults, **kwargs)
520+
521+
def delete_metadata_field(
522+
self,
523+
field_name: str,
524+
**kwargs,
525+
) -> Response:
526+
"""Delete a metadata field by its name (deprecated, use delete_field instead).
527+
528+
This method is kept for backward compatibility and will be removed in a future version.
529+
530+
Args:
531+
field_name: The name of the field to delete.
532+
**kwargs: Additional kwargs to pass to the request.
533+
534+
Returns:
535+
Response: An empty response, expecting HTTP 204 No Content on success.
536+
"""
537+
return self.delete_field(field_name, **kwargs)

0 commit comments

Comments
 (0)