4545 _USER_AGENT ,
4646 _DEFAULT_EXPECTED_STATUSES ,
4747 _RequestContext ,
48- _COLUMN_OVERRIDE_KEYS ,
4948 _TYPED_COLUMN_PROPERTIES ,
5049)
5150
@@ -1031,18 +1030,17 @@ def _update_attribute(
10311030 column_name : str ,
10321031 overrides : Dict [str , Any ],
10331032 ) -> str :
1034- """Update constraints on an existing column: GET typed attr -> PUT + @odata.type (#202).
1035-
1036- Hides the PUT-not-PATCH metadata-update contract and the derived
1037- ``@odata.type`` discriminator. GETs the existing attribute to learn its
1038- derived type + ``MetadataId``, applies the override spec (same shape as
1039- create; see ``_apply_column_overrides``), then PUTs a merge payload.
1033+ """Update constraints on an existing column: retrieve the full attr -> PUT it back (#202).
1034+
1035+ Follows the documented column-update contract: the attribute is updated
1036+ with ``PUT`` carrying the *entire* current definition (not a sparse body),
1037+ so properties the caller did not touch are preserved. We learn the derived
1038+ ``@odata.type``, retrieve the complete concrete attribute via the type
1039+ cast, apply the override spec (same shape as create; see
1040+ ``_apply_column_overrides``), and ``PUT`` the merged definition back with
1041+ ``MSCRM.MergeLabels: true`` so localized labels in other languages survive.
10401042 """
1041- if not isinstance (overrides , dict ) or not overrides :
1042- raise TypeError ("overrides must be a non-empty dict of column constraints" )
1043- unknown = set (overrides ) - (_COLUMN_OVERRIDE_KEYS - {"type" })
1044- if unknown :
1045- raise ValueError (f"Unknown column constraint override(s) for '{ column_name } ': { sorted (unknown )} " )
1043+ self ._validate_column_overrides (column_name , overrides )
10461044 ent = self ._get_entity_by_table_schema_name (table_schema_name )
10471045 if not ent or not ent .get ("MetadataId" ):
10481046 raise MetadataError (
@@ -1058,26 +1056,30 @@ def _update_attribute(
10581056 if getattr (err , "status_code" , None ) == 404 :
10591057 raise MetadataError (
10601058 f"Column '{ column_name } ' not found on table '{ table_schema_name } '." ,
1061- subcode = METADATA_TABLE_NOT_FOUND ,
1059+ subcode = METADATA_COLUMN_NOT_FOUND ,
10621060 ) from err
10631061 raise
10641062 attr_metadata_id = existing .get ("MetadataId" )
10651063 odata_type = str (existing .get ("@odata.type" , "" )).lstrip ("#" )
10661064 if not attr_metadata_id or not odata_type :
10671065 raise MetadataError (
10681066 f"Column '{ column_name } ' not found on table '{ table_schema_name } '." ,
1069- subcode = METADATA_TABLE_NOT_FOUND ,
1067+ subcode = METADATA_COLUMN_NOT_FOUND ,
10701068 )
1071- body : Dict [str , Any ] = {
1072- "@odata.type" : odata_type ,
1073- "MetadataId" : attr_metadata_id ,
1074- "SchemaName" : existing .get ("SchemaName" , column_name ),
1075- }
1069+ # Retrieve the COMPLETE concrete definition (via the @odata.type cast) so the
1070+ # PUT round-trips every property the caller did not override, per the
1071+ # documented column-update contract.
1072+ full = self ._request ("get" , f"{ attr_url } /{ odata_type } " ).json ()
1073+ body : Dict [str , Any ] = {k : v for k , v in full .items () if not str (k ).startswith ("@odata." )}
1074+ body ["@odata.type" ] = odata_type
1075+ body ["MetadataId" ] = attr_metadata_id
1076+ body .setdefault ("SchemaName" , existing .get ("SchemaName" , column_name ))
10761077 self ._apply_column_overrides (body , overrides )
10771078 req = _RawRequest (
10781079 method = "PUT" ,
10791080 url = f"{ self .api } /EntityDefinitions({ metadata_id } )/Attributes({ attr_metadata_id } )" ,
10801081 body = json .dumps (body , ensure_ascii = False ),
1082+ headers = {"MSCRM.MergeLabels" : "true" },
10811083 )
10821084 self ._execute_raw (req )
10831085 return column_name
0 commit comments