Skip to content

Commit 961116e

Browse files
SK-2838: fix redaction type in detokenize interface (#249)
1 parent 4ea39dd commit 961116e

7 files changed

Lines changed: 50 additions & 11 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ from skyflow.utils.enums import RedactionType
239239

240240
detokenize_request = DetokenizeRequest(
241241
data=[
242-
{'token': 'token1', 'redaction': RedactionType.PLAIN_TEXT},
243-
{'token': 'token2', 'redaction': RedactionType.PLAIN_TEXT}
242+
{'token': 'token1', 'redaction_type': RedactionType.PLAIN_TEXT},
243+
{'token': 'token2', 'redaction_type': RedactionType.PLAIN_TEXT}
244244
],
245245
continue_on_error=True
246246
)

samples/vault_api/detokenize_records.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ def perform_detokenization():
5555
detokenize_data = [
5656
{
5757
'token': '<TOKEN1>', # Token to be detokenized
58-
'redaction': RedactionType.REDACTED
58+
'redaction_type': RedactionType.REDACTED
5959
},
6060
{
6161
'token': '<TOKEN2>', # Token to be detokenized
62-
'redaction': RedactionType.MASKED
62+
'redaction_type': RedactionType.MASKED
6363
}
6464
]
6565

skyflow/utils/_skyflow_messages.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class Error(Enum):
122122
INVOKE_CONNECTION_FAILED = f"{error_prefix} Invoke Connection operation failed."
123123

124124
INVALID_IDS_TYPE = f"{error_prefix} Validation error. 'ids' has a value of type {{}}. Specify 'ids' as list."
125-
INVALID_REDACTION_TYPE = f"{error_prefix} Validation error. 'redaction' has a value of type {{}}. Specify 'redaction' as type Skyflow.RedactionType."
125+
INVALID_REDACTION_TYPE = f"{error_prefix} Validation error. 'redaction_type' has a value of type {{}}. Specify 'redaction_type' as type Skyflow.RedactionType."
126126
INVALID_COLUMN_NAME = f"{error_prefix} Validation error. column_name has a value of type {{}}. Specify 'column' as a string."
127127
INVALID_COLUMN_VALUE = f"{error_prefix} Validation error. column_values key has a value of type {{}}. Specify column_values key as list."
128128
INVALID_COLUMN_VALUES = f"{error_prefix} Validation error. column_values key is an empty list. Specify at least one column value when column_name is passed."
@@ -131,15 +131,15 @@ class Error(Enum):
131131
INVALID_OFF_SET_VALUE = f"{error_prefix} Validation error. offset key has a value of type {{}}. Specify offset key as integer."
132132
INVALID_LIMIT_VALUE = f"{error_prefix} Validation error. limit key has a value of type {{}}. Specify limit key as integer."
133133
INVALID_DOWNLOAD_URL_VALUE = f"{error_prefix} Validation error. download_url key has a value of type {{}}. Specify download_url key as boolean."
134-
REDACTION_WITH_TOKENS_NOT_SUPPORTED = f"{error_prefix} Validation error. 'redaction' can't be used when tokens are specified. Remove 'redaction' from payload if tokens are specified."
134+
REDACTION_WITH_TOKENS_NOT_SUPPORTED = f"{error_prefix} Validation error. 'redaction_type' can't be used when tokens are specified. Remove 'redaction_type' from payload if tokens are specified."
135135
TOKENS_GET_COLUMN_NOT_SUPPORTED = f"{error_prefix} Validation error. Column name and/or column values can't be used when tokens are specified. Remove unique column values or tokens from the payload."
136136
BOTH_IDS_AND_COLUMN_DETAILS_SPECIFIED = f"{error_prefix} Validation error. Both Skyflow IDs and column details can't be specified. Either specify Skyflow IDs or unique column details."
137137
INVALID_ORDER_BY_VALUE = f"{error_prefix} Validation error. order_by key has a value of type {{}}. Specify order_by key as Skyflow.OrderBy"
138138

139139
UPDATE_FIELD_KEY_ERROR = f"{error_prefix} Validation error. Fields are empty in an update payload. Specify at least one field."
140140
INVALID_FIELDS_TYPE = f"{error_prefix} Validation error. The 'data' key has a value of type {{}}. Specify 'data' as a dictionary."
141141
IDS_KEY_ERROR = f"{error_prefix} Validation error. 'ids' key is missing from the payload. Specify an 'ids' key."
142-
INVALID_TOKENS_LIST_VALUE = f"{error_prefix} Validation error. The 'data' field is invalid. Specify 'data' as a list of dictionaries containing 'token' and 'redaction'."
142+
INVALID_TOKENS_LIST_VALUE = f"{error_prefix} Validation error. The 'data' field is invalid. Specify 'data' as a list of dictionaries containing 'token' and 'redaction_type'."
143143
INVALID_DATA_FOR_DETOKENIZE = f"{error_prefix}"
144144
EMPTY_TOKENS_LIST_VALUE = f"{error_prefix} Validation error. Tokens are empty in detokenize payload. Specify at lease one token"
145145
INVALID_TOKEN_TYPE = f"{ERROR}: [{error_prefix}] Invalid {{}} request. Tokens should be of type string."
@@ -417,6 +417,9 @@ class HttpStatus(Enum):
417417
BAD_REQUEST = "Bad Request"
418418

419419
class Warning(Enum):
420+
DETOKENIZE_REDACTION_KEY_DEPRECATED = (
421+
f"{WARN}: [{error_prefix}] 'redaction' key in detokenize data is deprecated and will be removed in a future version. Use 'redaction_type' instead."
422+
)
420423
UPDATE_LOG_LEVEL_DEPRECATED = (
421424
f"{WARN}: [{error_prefix}] Skyflow.update_log_level() is deprecated. "
422425
"Use Skyflow.set_log_level() instead."

skyflow/utils/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class RequestParameter:
174174
VALUE = 'value'
175175
COLUMN_GROUP = 'column_group'
176176
REDACTION = 'redaction'
177+
REDACTION_TYPE = 'redaction_type'
177178

178179

179180
class FileUploadField:

skyflow/utils/validations/_validations.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
FileUploadField,
1212
DeidentifyFileRequestField, RequestOperation, ConfigType, SqlCommand, ConfigField, OptionField, CredentialField, Detect
1313
)
14-
from skyflow.utils.logger import log_info, log_error_log
14+
from skyflow.utils.logger import log_info, log_warn, log_error_log
1515
from skyflow.vault.detect import DeidentifyTextRequest, ReidentifyTextRequest, TokenFormat, Transformations, \
1616
GetDetectRunRequest, Bleep, DeidentifyFileRequest
1717
from skyflow.vault.detect._file_input import FileInput
@@ -713,7 +713,17 @@ def validate_detokenize_request(logger, request):
713713
invalid_input_error_code)
714714

715715
token = item.get(ResponseField.TOKEN)
716-
redaction = item.get(RequestParameter.REDACTION, None)
716+
717+
has_redaction = RequestParameter.REDACTION in item
718+
has_redaction_type = RequestParameter.REDACTION_TYPE in item
719+
720+
if has_redaction:
721+
log_warn(SkyflowMessages.Warning.DETOKENIZE_REDACTION_KEY_DEPRECATED.value, logger)
722+
723+
if has_redaction_type:
724+
redaction = item.get(RequestParameter.REDACTION_TYPE)
725+
else:
726+
redaction = item.get(RequestParameter.REDACTION, None)
717727

718728
if not isinstance(token, str) or not token:
719729
raise SkyflowError(SkyflowMessages.Error.INVALID_TOKEN_TYPE.value.format(RequestOperation.DETOKENIZE),

skyflow/vault/controller/_vault.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def detokenize(self, request: DetokenizeRequest):
223223
tokens_list = [
224224
V1DetokenizeRecordRequest(
225225
token=item.get(ResponseField.TOKEN),
226-
redaction=item.get(RequestParameter.REDACTION, RedactionType.DEFAULT)
226+
redaction=item.get(RequestParameter.REDACTION_TYPE) or item.get(RequestParameter.REDACTION, RedactionType.DEFAULT)
227227
)
228228
for item in request.data
229229
]

tests/utils/validations/test__validations.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,11 +1057,36 @@ def test_validate_detokenize_request_invalid_continue_on_error_type(self):
10571057
self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_CONTINUE_ON_ERROR_TYPE.value)
10581058

10591059
def test_validate_detokenize_request_invalid_redaction_type(self):
1060-
request = DetokenizeRequest(data=[{"token": "token123", "redaction": "invalid"}], continue_on_error=False)
1060+
request = DetokenizeRequest(data=[{"token": "token123", "redaction_type": "invalid"}], continue_on_error=False)
10611061
with self.assertRaises(SkyflowError) as context:
10621062
validate_detokenize_request(self.logger, request)
10631063
self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_REDACTION_TYPE.value.format(str(type("invalid"))))
10641064

1065+
def test_validate_detokenize_request_deprecated_redaction_key_emits_warn(self):
1066+
from unittest.mock import patch
1067+
request = DetokenizeRequest(data=[{"token": "token123", "redaction": RedactionType.PLAIN_TEXT}], continue_on_error=False)
1068+
with patch('skyflow.utils.validations._validations.log_warn') as mock_warn:
1069+
validate_detokenize_request(self.logger, request)
1070+
mock_warn.assert_called_once()
1071+
self.assertIn("redaction_type", mock_warn.call_args[0][0])
1072+
1073+
def test_validate_detokenize_request_both_keys_prioritizes_redaction_type_and_warns(self):
1074+
from unittest.mock import patch
1075+
request = DetokenizeRequest(
1076+
data=[{"token": "token123", "redaction": RedactionType.PLAIN_TEXT, "redaction_type": RedactionType.MASKED}],
1077+
continue_on_error=False
1078+
)
1079+
with patch('skyflow.utils.validations._validations.log_warn') as mock_warn:
1080+
validate_detokenize_request(self.logger, request)
1081+
mock_warn.assert_called_once()
1082+
1083+
def test_validate_detokenize_request_redaction_type_only_no_warn(self):
1084+
from unittest.mock import patch
1085+
request = DetokenizeRequest(data=[{"token": "token123", "redaction_type": RedactionType.PLAIN_TEXT}], continue_on_error=False)
1086+
with patch('skyflow.utils.validations._validations.log_warn') as mock_warn:
1087+
validate_detokenize_request(self.logger, request)
1088+
mock_warn.assert_not_called()
1089+
10651090

10661091
def test_validate_deidentify_file_request_wait_time_negative(self):
10671092
file_input = FileInput(file_path=self.temp_file_path)

0 commit comments

Comments
 (0)