prompt: Error : a bytes-like object is required, not 'MultiValue'
  Hello,
  
  I am getting following error while updating the tag LongTrianglePointIndexList (0066,0040),
  **TypeError: a bytes-like object is required, not 'MultiValue'**
  
  I noticed that the error  gets produced only when the VR is given as "OL" , works fine with "OB", "OF" etc.
  
  sample code (assume 'lineSeq' is the dicom dataset sequence):
  ```python
  import pydicom
  import array
  data=list(range(1,10))
  data=array.array('H', indexData).tostring()  # to convert to unsigned short
  lineSeq.add_new(0x00660040, 'OL', data)   
  ds.save_as("mydicom")
  ```
  outcome: **TypeError: a bytes-like object is required, not 'MultiValue'**
  
  using version - 2.0.0.0
  
  Any help is appreciated.
  
  Thank you
  
instance: {"FAIL_TO_PASS": "[\"pydicom/tests/test_valuerep.py::test_assigning_bytes[OD-bytes-vm017-vmN17-DoubleFloatPixelData]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[OL-bytes-vm019-vmN19-TrackPointIndexList]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[OV-bytes-vm020-vmN20-SelectorOVValue]\"]", "PASS_TO_PASS": "[\"pydicom/tests/test_valuerep.py::TestTM::test_pickling\", \"pydicom/tests/test_valuerep.py::TestTM::test_pickling_tm_from_time\", \"pydicom/tests/test_valuerep.py::TestTM::test_str_and_repr\", \"pydicom/tests/test_valuerep.py::TestTM::test_new_empty_str\", \"pydicom/tests/test_valuerep.py::TestTM::test_new_str_conversion\", \"pydicom/tests/test_valuerep.py::TestTM::test_new_obj_conversion\", \"pydicom/tests/test_valuerep.py::TestTM::test_comparison\", \"pydicom/tests/test_valuerep.py::TestTM::test_time_behavior\", \"pydicom/tests/test_valuerep.py::TestDT::test_pickling\", \"pydicom/tests/test_valuerep.py::TestDT::test_pickling_with_timezone\", \"pydicom/tests/test_valuerep.py::TestDT::test_pickling_dt_from_datetime\", \"pydicom/tests/test_valuerep.py::TestDT::test_pickling_dt_from_datetime_with_timezone\", \"pydicom/tests/test_valuerep.py::TestDT::test_new_empty_str\", \"pydicom/tests/test_valuerep.py::TestDT::test_new_obj_conversion\", \"pydicom/tests/test_valuerep.py::TestDT::test_new_str_conversion\", \"pydicom/tests/test_valuerep.py::TestDT::test_str_and_repr\", \"pydicom/tests/test_valuerep.py::TestDT::test_comparison\", \"pydicom/tests/test_valuerep.py::TestDT::test_datetime_behavior\", \"pydicom/tests/test_valuerep.py::TestDA::test_pickling\", \"pydicom/tests/test_valuerep.py::TestDA::test_new_obj_conversion\", \"pydicom/tests/test_valuerep.py::TestDA::test_str_and_repr\", \"pydicom/tests/test_valuerep.py::TestDA::test_comparison\", \"pydicom/tests/test_valuerep.py::TestDA::test_date_behavior\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[1]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[3.14159265358979]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[-1234.456e78]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[1.234E-5]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[1.234E+5]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[+1]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_valid[42\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[nan]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[-inf]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[3.141592653589793]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[1,000]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[1\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[127.0.0.1]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[1.e]\", \"pydicom/tests/test_valuerep.py::TestIsValidDS::test_invalid[]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[1.0-1.0]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[0.0-0.0]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[-0.0--0.0]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[0.123-0.123]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[-0.321--0.321]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[1e-05-1e-05]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[3.141592653589793-3.14159265358979]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[-3.141592653589793--3.1415926535898]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[5.385940192876374e-07-5.3859401929e-07]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[-5.385940192876374e-07--5.385940193e-07]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[12342534378.125532-12342534378.1255]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[64070869985876.78-64070869985876.8]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_auto_format[1.7976931348623157e+308-1.797693135e+308]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-101]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-100]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[100]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[101]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-16]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-15]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-14]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-13]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-12]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-11]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-10]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-9]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-8]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-7]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-6]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-5]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-4]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-3]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-2]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[-1]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[0]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[1]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[2]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[3]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[4]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[5]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[6]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[7]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[8]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[9]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[10]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[11]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[12]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[13]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[14]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[15]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_pi[16]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-101]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-100]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[100]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[101]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-16]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-15]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-14]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-13]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-12]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-11]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-10]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-9]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-8]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-7]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-6]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-5]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-4]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-3]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-2]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[-1]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[0]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[1]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[2]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[3]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[4]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[5]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[6]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[7]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[8]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[9]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[10]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[11]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[12]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[13]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[14]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[15]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_powers_of_negative_pi[16]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_invalid[nan0]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_invalid[nan1]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_invalid[-inf]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_invalid[inf]\", \"pydicom/tests/test_valuerep.py::TestTruncateFloatForDS::test_wrong_type\", \"pydicom/tests/test_valuerep.py::TestDS::test_empty_value\", \"pydicom/tests/test_valuerep.py::TestDS::test_float_values\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_pickling\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_new_empty\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_str_value\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_str\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_repr\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_DSfloat\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_DSdecimal\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_auto_format[True]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_auto_format[False]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_auto_format_from_invalid_DS\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_auto_format_invalid_string[True]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_auto_format_invalid_string[False]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_auto_format_valid_string[True]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_auto_format_valid_string[False]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_length\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_DSfloat_auto_format\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[nan0]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[-nan]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[inf0]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[-inf0]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[nan1]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[nan2]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[-inf1]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_enforce_valid_values_value[inf1]\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_comparison_operators\", \"pydicom/tests/test_valuerep.py::TestDSfloat::test_hash\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_pickling\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_float_value\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_new_empty\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_str_value\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_DSfloat\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_DSdecimal\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_repr\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_auto_format[True]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_auto_format[False]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_auto_format_from_invalid_DS\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_auto_format_invalid_string[True]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_auto_format_invalid_string[False]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[NaN]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[-NaN]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[Infinity]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[-Infinity]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[val4]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[val5]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[val6]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_enforce_valid_values_value[val7]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_auto_format_valid_string[True]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_auto_format_valid_string[False]\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_DSdecimal_auto_format\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_comparison_operators\", \"pydicom/tests/test_valuerep.py::TestDSdecimal::test_hash\", \"pydicom/tests/test_valuerep.py::TestIS::test_empty_value\", \"pydicom/tests/test_valuerep.py::TestIS::test_str_value\", \"pydicom/tests/test_valuerep.py::TestIS::test_valid_value\", \"pydicom/tests/test_valuerep.py::TestIS::test_invalid_value\", \"pydicom/tests/test_valuerep.py::TestIS::test_pickling\", \"pydicom/tests/test_valuerep.py::TestIS::test_longint\", \"pydicom/tests/test_valuerep.py::TestIS::test_overflow\", \"pydicom/tests/test_valuerep.py::TestIS::test_str\", \"pydicom/tests/test_valuerep.py::TestIS::test_repr\", \"pydicom/tests/test_valuerep.py::TestIS::test_comparison_operators\", \"pydicom/tests/test_valuerep.py::TestIS::test_hash\", \"pydicom/tests/test_valuerep.py::TestBadValueRead::test_read_bad_value_in_VR_default\", \"pydicom/tests/test_valuerep.py::TestBadValueRead::test_read_bad_value_in_VR_enforce_valid_value\", \"pydicom/tests/test_valuerep.py::TestDecimalString::test_DS_decimal_set\", \"pydicom/tests/test_valuerep.py::TestDecimalString::test_valid_decimal_strings\", \"pydicom/tests/test_valuerep.py::TestDecimalString::test_invalid_decimal_strings\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_last_first\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_copy\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_three_component\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_formatting\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_unicode_kr\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_unicode_jp_from_bytes\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_unicode_jp_from_bytes_comp_delimiter\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_unicode_jp_from_bytes_caret_delimiter\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_unicode_jp_from_unicode\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_not_equal\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_encoding_carried\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_hash\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_next\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_iterator\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_contains\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_length\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components_kr_from_bytes\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components_kr_from_unicode\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components_jp_from_bytes\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components_jp_from_unicode\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components_veterinary\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components_with_separator\", \"pydicom/tests/test_valuerep.py::TestPersonName::test_from_named_components_with_separator_from_bytes\", \"pydicom/tests/test_valuerep.py::TestDateTime::test_date\", \"pydicom/tests/test_valuerep.py::TestDateTime::test_date_time\", \"pydicom/tests/test_valuerep.py::TestDateTime::test_time\", \"pydicom/tests/test_valuerep.py::test_person_name_unicode_warns\", \"pydicom/tests/test_valuerep.py::test_set_value[AE-str-vm00-vmN0-Receiver]\", \"pydicom/tests/test_valuerep.py::test_set_value[AS-str-vm01-vmN1-PatientAge]\", \"pydicom/tests/test_valuerep.py::test_set_value[AT-int-vm02-vmN2-OffendingElement]\", \"pydicom/tests/test_valuerep.py::test_set_value[CS-str-vm03-vmN3-QualityControlSubject]\", \"pydicom/tests/test_valuerep.py::test_set_value[DA-str-vm04-vmN4-PatientBirthDate]\", \"pydicom/tests/test_valuerep.py::test_set_value[DS-str-vm05-vmN5-PatientWeight]\", \"pydicom/tests/test_valuerep.py::test_set_value[DS-int-vm06-vmN6-PatientWeight]\", \"pydicom/tests/test_valuerep.py::test_set_value[DS-float-vm07-vmN7-PatientWeight]\", \"pydicom/tests/test_valuerep.py::test_set_value[DT-str-vm08-vmN8-AcquisitionDateTime]\", \"pydicom/tests/test_valuerep.py::test_set_value[FD-float-vm09-vmN9-RealWorldValueLUTData]\", \"pydicom/tests/test_valuerep.py::test_set_value[FL-float-vm010-vmN10-VectorAccuracy]\", \"pydicom/tests/test_valuerep.py::test_set_value[IS-str-vm011-vmN11-BeamNumber]\", \"pydicom/tests/test_valuerep.py::test_set_value[IS-int-vm012-vmN12-BeamNumber]\", \"pydicom/tests/test_valuerep.py::test_set_value[IS-float-vm013-vmN13-BeamNumber]\", \"pydicom/tests/test_valuerep.py::test_set_value[LO-str-vm014-vmN14-DataSetSubtype]\", \"pydicom/tests/test_valuerep.py::test_set_value[LT-str-vm015-vmN15-ExtendedCodeMeaning]\", \"pydicom/tests/test_valuerep.py::test_set_value[OB-bytes-vm016-vmN16-FillPattern]\", \"pydicom/tests/test_valuerep.py::test_set_value[OD-bytes-vm017-vmN17-DoubleFloatPixelData]\", \"pydicom/tests/test_valuerep.py::test_set_value[OF-bytes-vm018-vmN18-UValueData]\", \"pydicom/tests/test_valuerep.py::test_set_value[OL-bytes-vm019-vmN19-TrackPointIndexList]\", \"pydicom/tests/test_valuerep.py::test_set_value[OV-bytes-vm020-vmN20-SelectorOVValue]\", \"pydicom/tests/test_valuerep.py::test_set_value[OW-bytes-vm021-vmN21-TrianglePointIndexList]\", \"pydicom/tests/test_valuerep.py::test_set_value[PN-str-vm022-vmN22-PatientName]\", \"pydicom/tests/test_valuerep.py::test_set_value[SH-str-vm023-vmN23-CodeValue]\", \"pydicom/tests/test_valuerep.py::test_set_value[SL-int-vm024-vmN24-RationalNumeratorValue]\", \"pydicom/tests/test_valuerep.py::test_set_value[SQ-list-vm025-vmN25-BeamSequence]\", \"pydicom/tests/test_valuerep.py::test_set_value[SS-int-vm026-vmN26-SelectorSSValue]\", \"pydicom/tests/test_valuerep.py::test_set_value[ST-str-vm027-vmN27-InstitutionAddress]\", \"pydicom/tests/test_valuerep.py::test_set_value[SV-int-vm028-vmN28-SelectorSVValue]\", \"pydicom/tests/test_valuerep.py::test_set_value[TM-str-vm029-vmN29-StudyTime]\", \"pydicom/tests/test_valuerep.py::test_set_value[UC-str-vm030-vmN30-LongCodeValue]\", \"pydicom/tests/test_valuerep.py::test_set_value[UI-str-vm031-vmN31-SOPClassUID]\", \"pydicom/tests/test_valuerep.py::test_set_value[UL-int-vm032-vmN32-SimpleFrameList]\", \"pydicom/tests/test_valuerep.py::test_set_value[UN-bytes-vm033-vmN33-SelectorUNValue]\", \"pydicom/tests/test_valuerep.py::test_set_value[UR-str-vm034-vmN34-CodingSchemeURL]\", \"pydicom/tests/test_valuerep.py::test_set_value[US-int-vm035-vmN35-SourceAcquisitionBeamNumber]\", \"pydicom/tests/test_valuerep.py::test_set_value[UT-str-vm036-vmN36-StrainAdditionalInformation]\", \"pydicom/tests/test_valuerep.py::test_set_value[UV-int-vm037-vmN37-SelectorUVValue]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[AE-str-vm00-vmN0-Receiver]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[AS-str-vm01-vmN1-PatientAge]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[AT-int-vm02-vmN2-OffendingElement]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[CS-str-vm03-vmN3-QualityControlSubject]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[DA-str-vm04-vmN4-PatientBirthDate]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[DS-str-vm05-vmN5-PatientWeight]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[DS-int-vm06-vmN6-PatientWeight]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[DS-float-vm07-vmN7-PatientWeight]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[DT-str-vm08-vmN8-AcquisitionDateTime]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[FD-float-vm09-vmN9-RealWorldValueLUTData]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[FL-float-vm010-vmN10-VectorAccuracy]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[IS-str-vm011-vmN11-BeamNumber]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[IS-int-vm012-vmN12-BeamNumber]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[IS-float-vm013-vmN13-BeamNumber]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[LO-str-vm014-vmN14-DataSetSubtype]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[LT-str-vm015-vmN15-ExtendedCodeMeaning]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[OB-bytes-vm016-vmN16-FillPattern]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[OF-bytes-vm018-vmN18-UValueData]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[OW-bytes-vm021-vmN21-TrianglePointIndexList]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[PN-str-vm022-vmN22-PatientName]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[SH-str-vm023-vmN23-CodeValue]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[SL-int-vm024-vmN24-RationalNumeratorValue]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[SQ-list-vm025-vmN25-BeamSequence]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[SS-int-vm026-vmN26-SelectorSSValue]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[ST-str-vm027-vmN27-InstitutionAddress]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[SV-int-vm028-vmN28-SelectorSVValue]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[TM-str-vm029-vmN29-StudyTime]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[UC-str-vm030-vmN30-LongCodeValue]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[UI-str-vm031-vmN31-SOPClassUID]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[UL-int-vm032-vmN32-SimpleFrameList]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[UN-bytes-vm033-vmN33-SelectorUNValue]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[UR-str-vm034-vmN34-CodingSchemeURL]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[US-int-vm035-vmN35-SourceAcquisitionBeamNumber]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[UT-str-vm036-vmN36-StrainAdditionalInformation]\", \"pydicom/tests/test_valuerep.py::test_assigning_bytes[UV-int-vm037-vmN37-SelectorUVValue]\"]", "base_commit": "f909c76e31f759246cec3708dadd173c5d6e84b1", "created_at": "2021-06-16T09:47:08Z", "environment_setup_commit": "506ecea8f378dc687d5c504788fc78810a190b7a", "hints_text": "Also tried following code to get the byte string, but same error.\r\n1. data=array.array('L', indexData).tostring()  # to convert to long -> same error\r\n2. data=array.array('Q', indexData).tostring()  # to convert to long long -> same error\r\n\r\n\nO* VRs should be `bytes`. Use `array.tobytes()` instead of `tostring()`?\r\n\r\nAlso, in the future if have an issue it's much more helpful if you post the full traceback rather than the error since we can look at it to figure out where in the code the exception is occurring.\r\n\r\nIt would also help if you posted the version of Python you're using. \r\n\r\nThis works fine for me with Python 3.9 and pydicom 2.1.2:\r\n```python\r\nfrom pydicom import Dataset\r\nimport array\r\n\r\narr = array.array('H', range(10))\r\nds = Dataset()\r\nds.is_little_endian = True\r\nds.is_implicit_VR = False\r\nds.LongTrianglePointIndexList = arr.tobytes()\r\nprint(ds[\"LongTrianglePointIndexList\"].VR)  # 'OL'\r\nds.save_as('temp.dcm')\r\n```\r\nThis also works fine:\r\n```python\r\nds = Dataset()\r\nds.add_new(0x00660040, 'OL', arr.tobytes())\r\n```\nThank you for the answer.\r\nUnfortunately the error still persists with above code.\r\nPlease find the attached detailed error.\r\n[error.txt](https://github.com/pydicom/pydicom/files/6661451/error.txt)\r\n\r\nOne more information is that the 'ds' is actually read from a file in the disk (ds=pydicom.read_file(filename)). \r\nand this byte array is stored under the following sequence\r\nds[0x0066,0x0002][0][0x0066,0x0013][0][0x0066,0x0028][0][0x0066,0x0040] = arr.tobytes()\r\n\r\npydicom - 2.0.0.0\r\npython - 3.6.4\r\n\r\nThank you.\nCould you post a minimal code sample that reproduces the issue please?\r\n\r\nIf you're using something like this:\r\n`ds[0x0066,0x0002][0][0x0066,0x0013][0][0x0066,0x0028][0][0x0066,0x0040] = arr.tobytes()`\r\n\r\nThen you're missing the `.value` assignment:\r\n`ds[0x0066,0x0002][0][0x0066,0x0013][0][0x0066,0x0028][0][0x0066,0x0040].value = arr.tobytes()`\nHello,\r\nabove code line I just mentioned to give an idea where the actual data is stored (tree level).\r\n\r\nPlease find the actual code used below,\r\n```python\r\nimport pydicom\r\nfrom pydicom.sequence import Sequence\r\nfrom pydicom.dataelem import DataElement\r\nfrom pydicom.dataset import Dataset\r\n\r\nds = pydicom.read_file(filename)\r\nsurfaceSeq= ds[0x0066,0x0002]\r\n\r\n#// read existing sequence items in the dataset\r\nseqlist=[]\r\nfor n in surfaceSeq:\r\n    seqlist.append(n)\r\n\r\nnewDs = Dataset()\r\n \r\nsurfaceMeshPrimitiveSq = Dataset()\r\nlineSeq = Dataset()\r\nindexData = list(range(1,100))\r\nindexData = array.array('H', indexData)\r\nindexData = indexData.tobytes()\r\nlineSeq.add_new(0x00660040, 'OL', indexData) \r\nsurfaceMeshPrimitiveSq.add_new(0x00660028, 'SQ', [lineSeq])\r\nnewDs.add_new(0x00660013, 'SQ', [surfaceMeshPrimitiveSq])\r\n\r\n#add the new sequnce item to the list\r\nseqlist.append(newDs)\r\nds[0x0066,0x0002] = DataElement(0x00660002,\"SQ\",seqlist)\r\nds.save_as(filename)\r\n```\nOK, I can reproduce with:\r\n```python\r\n\r\nimport array\r\n\r\nfrom pydicom import Dataset\r\nfrom pydicom.uid import ExplicitVRLittleEndian\r\n\r\nds = Dataset()\r\nds.file_meta = Dataset()\r\nds.file_meta.TransferSyntaxUID = ExplicitVRLittleEndian\r\n\r\nb = array.array('H', range(100)).tobytes()\r\n\r\nds.LongPrimitivePointIndexList = b\r\nds.save_as('1421.dcm')\r\n```\r\nAnd `print(ds)` gives:\r\n```\r\n(0066, 0040) Long Primitive Point Index List     OL: [b'\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\x00\\x05\\x00\\x06\\x00\\x07\\x00\\x08\\x00\\t\\x00\\n\\x00\\x0b\\x00\\x0c\\x00\\r\\x00\\x0e\\x00\\x0f\\x00\\x10\\x00\\x11\\x00\\x12\\x00\\x13\\x00\\x14\\x00\\x15\\x00\\x16\\x00\\x17\\x00\\x18\\x00\\x19\\x00\\x1a\\x00\\x1b\\x00\\x1c\\x00\\x1d\\x00\\x1e\\x00\\x1f\\x00 \\x00!\\x00\"\\x00#\\x00$\\x00%\\x00&\\x00\\'\\x00(\\x00)\\x00*\\x00+\\x00,\\x00-\\x00.\\x00/\\x000\\x001\\x002\\x003\\x004\\x005\\x006\\x007\\x008\\x009\\x00:\\x00;\\x00<\\x00=\\x00>\\x00?\\x00@\\x00A\\x00B\\x00C\\x00D\\x00E\\x00F\\x00G\\x00H\\x00I\\x00J\\x00K\\x00L\\x00M\\x00N\\x00O\\x00P\\x00Q\\x00R\\x00S\\x00T\\x00U\\x00V\\x00W\\x00X\\x00Y\\x00Z\\x00[\\x00', b'\\x00]\\x00^\\x00_\\x00`\\x00a\\x00b\\x00c\\x00']\r\n```\r\nI think this is because the byte value is hitting the hex for the backslash character during assignment. Ouch, that's kinda nasty.", "instance_id": "pydicom__pydicom-1413", "patch": "diff --git a/pydicom/dataelem.py b/pydicom/dataelem.py\n--- a/pydicom/dataelem.py\n+++ b/pydicom/dataelem.py\n@@ -433,13 +433,24 @@ def value(self) -> Any:\n     @value.setter\n     def value(self, val: Any) -> None:\n         \"\"\"Convert (if necessary) and set the value of the element.\"\"\"\n+        # Ignore backslash characters in these VRs, based on:\n+        # * Which str VRs can have backslashes in Part 5, Section 6.2\n+        # * All byte VRs\n+        exclusions = [\n+            'LT', 'OB', 'OD', 'OF', 'OL', 'OV', 'OW', 'ST', 'UN', 'UT',\n+            'OB/OW', 'OW/OB', 'OB or OW', 'OW or OB',\n+            # Probably not needed\n+            'AT', 'FD', 'FL', 'SQ', 'SS', 'SL', 'UL',\n+        ]\n+\n         # Check if is a string with multiple values separated by '\\'\n         # If so, turn them into a list of separate strings\n         #  Last condition covers 'US or SS' etc\n-        if isinstance(val, (str, bytes)) and self.VR not in \\\n-                ['UT', 'ST', 'LT', 'FL', 'FD', 'AT', 'OB', 'OW', 'OF', 'SL',\n-                 'SQ', 'SS', 'UL', 'OB/OW', 'OW/OB', 'OB or OW',\n-                 'OW or OB', 'UN'] and 'US' not in self.VR:\n+        if (\n+            isinstance(val, (str, bytes))\n+            and self.VR not in exclusions\n+            and 'US' not in self.VR\n+        ):\n             try:\n                 if _backslash_str in val:\n                     val = cast(str, val).split(_backslash_str)\n", "problem_statement": "Error : a bytes-like object is required, not 'MultiValue'\nHello,\r\n\r\nI am getting following error while updating the tag LongTrianglePointIndexList (0066,0040),\r\n**TypeError: a bytes-like object is required, not 'MultiValue'**\r\n\r\nI noticed that the error  gets produced only when the VR is given as \"OL\" , works fine with \"OB\", \"OF\" etc.\r\n\r\nsample code (assume 'lineSeq' is the dicom dataset sequence):\r\n```python\r\nimport pydicom\r\nimport array\r\ndata=list(range(1,10))\r\ndata=array.array('H', indexData).tostring()  # to convert to unsigned short\r\nlineSeq.add_new(0x00660040, 'OL', data)   \r\nds.save_as(\"mydicom\")\r\n```\r\noutcome: **TypeError: a bytes-like object is required, not 'MultiValue'**\r\n\r\nusing version - 2.0.0.0\r\n\r\nAny help is appreciated.\r\n\r\nThank you\n", "repo": "pydicom/pydicom", "test_patch": "diff --git a/pydicom/tests/test_valuerep.py b/pydicom/tests/test_valuerep.py\n--- a/pydicom/tests/test_valuerep.py\n+++ b/pydicom/tests/test_valuerep.py\n@@ -1546,3 +1546,16 @@ def test_set_value(vr, pytype, vm0, vmN, keyword):\n     elem = ds[keyword]\n     assert elem.value == list(vmN)\n     assert list(vmN) == elem.value\n+\n+\n+@pytest.mark.parametrize(\"vr, pytype, vm0, vmN, keyword\", VALUE_REFERENCE)\n+def test_assigning_bytes(vr, pytype, vm0, vmN, keyword):\n+    \"\"\"Test that byte VRs are excluded from the backslash check.\"\"\"\n+    if pytype == bytes:\n+        ds = Dataset()\n+        value = b\"\\x00\\x01\" + b\"\\\\\" + b\"\\x02\\x03\"\n+        setattr(ds, keyword, value)\n+        elem = ds[keyword]\n+        assert elem.VR == vr\n+        assert elem.value == value\n+        assert elem.VM == 1\n", "version": "2.1"}
parsed_commit_content: {"file_diffs":[{"old_file_content":"# Copyright 2008-2018 pydicom authors. See LICENSE file for details.\n\"\"\"Define the DataElement class.\n\nA DataElement has a tag,\n              a value representation (VR),\n              a value multiplicity (VM)\n              and a value.\n\"\"\"\n\nimport base64\nimport json\nfrom typing import (\n    Optional, Any, Tuple, Callable, Union, TYPE_CHECKING, Dict, TypeVar, Type,\n    List, NamedTuple, MutableSequence, cast\n)\nimport warnings\n\nfrom pydicom import config  # don't import datetime_conversion directly\nfrom pydicom.config import logger\nfrom pydicom.datadict import (dictionary_has_tag, dictionary_description,\n                              dictionary_keyword, dictionary_is_retired,\n                              private_dictionary_description, dictionary_VR,\n                              repeater_has_tag, private_dictionary_VR)\nfrom pydicom.errors import BytesLengthException\nfrom pydicom.jsonrep import JsonDataElementConverter\nfrom pydicom.multival import MultiValue\nfrom pydicom.tag import Tag, BaseTag\nfrom pydicom.uid import UID\nfrom pydicom import jsonrep\nimport pydicom.valuerep  # don't import DS directly as can be changed by config\nfrom pydicom.valuerep import PersonName\n\nif config.have_numpy:\n    import numpy  # type: ignore[import]\n\nif TYPE_CHECKING:  # pragma: no cover\n    from pydicom.dataset import Dataset\n\n\nBINARY_VR_VALUES = [\n    'US', 'SS', 'UL', 'SL', 'OW', 'OB', 'OL', 'UN',\n    'OB or OW', 'US or OW', 'US or SS or OW', 'FL', 'FD', 'OF', 'OD'\n]\n\n\ndef empty_value_for_VR(\n    VR: Optional[str], raw: bool = False\n) -> Union[bytes, List[str], str, None, PersonName]:\n    \"\"\"Return the value for an empty element for `VR`.\n\n    .. versionadded:: 1.4\n\n    The behavior of this property depends on the setting of\n    :attr:`config.use_none_as_empty_value`. If that is set to ``True``,\n    an empty value is represented by ``None`` (except for VR 'SQ'), otherwise\n    it depends on `VR`. For text VRs (this includes 'AE', 'AS', 'CS', 'DA',\n    'DT', 'LO', 'LT', 'PN', 'SH', 'ST', 'TM', 'UC', 'UI', 'UR' and 'UT') an\n    empty string is used as empty value representation, for all other VRs\n    except 'SQ', ``None``. For empty sequence values (VR 'SQ') an empty list\n    is used in all cases.\n    Note that this is used only if decoding the element - it is always\n    possible to set the value to another empty value representation,\n    which will be preserved during the element object lifetime.\n\n    Parameters\n    ----------\n    VR : str or None\n        The VR of the corresponding element.\n    raw : bool, optional\n        If ``True``, returns the value for a :class:`RawDataElement`,\n        otherwise for a :class:`DataElement`\n\n    Returns\n    -------\n    str or bytes or None or list\n        The value a data element with `VR` is assigned on decoding\n        if it is empty.\n    \"\"\"\n    if VR == 'SQ':\n        return b'' if raw else []\n\n    if config.use_none_as_empty_text_VR_value:\n        return None\n\n    if VR == 'PN':\n        return b'' if raw else PersonName('')\n\n    if VR in (\n        'AE', 'AS', 'CS', 'DA', 'DT', 'LO', 'LT', 'SH', 'ST', 'TM',\n        'UC', 'UI', 'UR', 'UT'\n    ):\n        return b'' if raw else ''\n\n    return None\n\n\ndef _is_bytes(val: object) -> bool:\n    \"\"\"Return True only if `val` is of type `bytes`.\"\"\"\n    return isinstance(val, bytes)\n\n\n# double '\\' because it is used as escape chr in Python\n_backslash_str = \"\\\\\"\n_backslash_byte = b\"\\\\\"\n\n\n_DataElement = TypeVar(\"_DataElement\", bound=\"DataElement\")\n_Dataset = TypeVar(\"_Dataset\", bound=\"Dataset\")\n\n\nclass DataElement:\n    \"\"\"Contain and manipulate a DICOM Element.\n\n    Examples\n    --------\n\n    While its possible to create a new :class:`DataElement` directly and add\n    it to a :class:`~pydicom.dataset.Dataset`:\n\n    >>> from pydicom import Dataset\n    >>> elem = DataElement(0x00100010, 'PN', 'CITIZEN^Joan')\n    >>> ds = Dataset()\n    >>> ds.add(elem)\n\n    Its far more convenient to use a :class:`~pydicom.dataset.Dataset`\n    to add a new :class:`DataElement`, as the VR and tag are determined\n    automatically from the DICOM dictionary:\n\n    >>> ds = Dataset()\n    >>> ds.PatientName = 'CITIZEN^Joan'\n\n    Empty DataElement objects (e.g. with VM = 0) show an empty string as\n    value for text VRs and `None` for non-text (binary) VRs:\n\n    >>> ds = Dataset()\n    >>> ds.PatientName = None\n    >>> ds.PatientName\n    ''\n\n    >>> ds.BitsAllocated = None\n    >>> ds.BitsAllocated\n\n    >>> str(ds.BitsAllocated)\n    'None'\n\n    Attributes\n    ----------\n    descripWidth : int\n        For string display, this is the maximum width of the description\n        field (default ``35``).\n    is_undefined_length : bool\n        Indicates whether the length field for the element was ``0xFFFFFFFFL``\n        (ie undefined).\n    maxBytesToDisplay : int\n        For string display, elements with values containing data which is\n        longer than this value will display ``\"array of # bytes\"``\n        (default ``16``).\n    showVR : bool\n        For string display, include the element's VR just before it's value\n        (default ``True``).\n    tag : pydicom.tag.BaseTag\n        The element's tag.\n    VR : str\n        The element's Value Representation.\n    \"\"\"\n\n    descripWidth = 35\n    maxBytesToDisplay = 16\n    showVR = True\n    is_raw = False\n\n    def __init__(\n        self,\n        tag: Union[int, str, Tuple[int, int]],\n        VR: str,\n        value: Any,\n        file_value_tell: Optional[int] = None,\n        is_undefined_length: bool = False,\n        already_converted: bool = False\n    ) -> None:\n        \"\"\"Create a new :class:`DataElement`.\n\n        Parameters\n        ----------\n        tag : int or str or 2-tuple of int\n            The DICOM (group, element) tag in any form accepted by\n            :func:`~pydicom.tag.Tag` such as ``'PatientName'``,\n            ``(0x10, 0x10)``, ``0x00100010``, etc.\n        VR : str\n            The 2 character DICOM value representation (see DICOM Standard,\n            Part 5, :dcm:`Section 6.2<part05/sect_6.2.html>`).\n        value\n            The value of the data element. One of the following:\n\n            * a single string value\n            * a number\n            * a :class:`list` or :class:`tuple` with all strings or all numbers\n            * a multi-value string with backslash separator\n        file_value_tell : int, optional\n            The byte offset to the start of the encoded element value.\n        is_undefined_length : bool\n            Used internally to store whether the length field for this element\n            was ``0xFFFFFFFF``, i.e. 'undefined length'. Default is ``False``.\n        already_converted : bool\n            Used to determine whether or not the element's value requires\n            conversion to a value with VM > 1. Default is ``False``.\n        \"\"\"\n        if not isinstance(tag, BaseTag):\n            tag = Tag(tag)\n        self.tag = tag\n\n        # a known tag shall only have the VR 'UN' if it has a length that\n        # exceeds the size that can be encoded in 16 bit - all other cases\n        # can be seen as an encoding error and can be corrected\n        if (\n            VR == 'UN'\n            and not tag.is_private\n            and config.replace_un_with_known_vr\n            and (is_undefined_length or value is None or len(value) < 0xffff)\n        ):\n            try:\n                VR = dictionary_VR(tag)\n            except KeyError:\n                pass\n\n        self.VR = VR  # Note: you must set VR before setting value\n        if already_converted:\n            self._value = value\n        else:\n            self.value = value  # calls property setter which will convert\n        self.file_tell = file_value_tell\n        self.is_undefined_length = is_undefined_length\n        self.private_creator: Optional[str] = None\n        self.parent: Optional[\"Dataset\"] = None\n\n    @classmethod\n    def from_json(\n        cls: Type[_DataElement],\n        dataset_class: Type[_Dataset],\n        tag: Union[BaseTag, int, str],\n        vr: str,\n        value: object,\n        value_key: Union[str, None],\n        bulk_data_uri_handler: Optional[\n            Union[\n                Callable[[BaseTag, str, str], Any],\n                Callable[[str], Any]\n            ]\n        ] = None\n    ) -> _DataElement:\n        \"\"\"Return a :class:`DataElement` from JSON.\n\n        .. versionadded:: 1.3\n\n        Parameters\n        ----------\n        dataset_class : dataset.Dataset derived class\n            Class used to create sequence items.\n        tag : pydicom.tag.BaseTag, int or str\n            The data element tag.\n        vr : str\n            The data element value representation.\n        value : list\n            The data element's value(s).\n        value_key : str or None\n            Key of the data element that contains the value\n            (options: ``{\"Value\", \"InlineBinary\", \"BulkDataURI\"}``)\n        bulk_data_uri_handler: callable or None\n            Callable function that accepts either the tag, vr and \"BulkDataURI\"\n            or just the \"BulkDataURI\" of the JSON\n            representation of a data element and returns the actual value of\n            that data element (retrieved via DICOMweb WADO-RS)\n\n        Returns\n        -------\n        DataElement\n        \"\"\"\n        # TODO: test wado-rs retrieve wrapper\n        converter = JsonDataElementConverter(\n            dataset_class, tag, vr, value, value_key, bulk_data_uri_handler\n        )\n        elem_value = converter.get_element_values()\n        try:\n            return cls(tag=tag, value=elem_value, VR=vr)\n        except Exception as exc:\n            raise ValueError(\n                f\"Data element '{tag}' could not be loaded from JSON: \"\n                f\"{elem_value}\"\n            ) from exc\n\n    def to_json_dict(\n        self,\n        bulk_data_element_handler: Optional[Callable[[\"DataElement\"], str]],\n        bulk_data_threshold: int\n    ) -> Dict[str, Any]:\n        \"\"\"Return a dictionary representation of the :class:`DataElement`\n        conforming to the DICOM JSON Model as described in the DICOM\n        Standard, Part 18, :dcm:`Annex F<part18/chaptr_F.html>`.\n\n        .. versionadded:: 1.4\n\n        Parameters\n        ----------\n        bulk_data_element_handler: callable or None\n            Callable that accepts a bulk data element and returns the\n            \"BulkDataURI\" for retrieving the value of the data element\n            via DICOMweb WADO-RS\n        bulk_data_threshold: int\n            Size of base64 encoded data element above which a value will be\n            provided in form of a \"BulkDataURI\" rather than \"InlineBinary\".\n            Ignored if no bulk data handler is given.\n\n        Returns\n        -------\n        dict\n            Mapping representing a JSON encoded data element\n        \"\"\"\n        json_element: Dict[str, Any] = {'vr': self.VR}\n        if self.VR in jsonrep.BINARY_VR_VALUES:\n            if not self.is_empty:\n                binary_value = self.value\n                encoded_value = base64.b64encode(binary_value).decode('utf-8')\n                if (\n                    bulk_data_element_handler is not None\n                    and len(encoded_value) > bulk_data_threshold\n                ):\n                    json_element['BulkDataURI'] = (\n                        bulk_data_element_handler(self)\n                    )\n                else:\n                    logger.info(\n                        f\"encode bulk data element '{self.name}' inline\"\n                    )\n                    json_element['InlineBinary'] = encoded_value\n        elif self.VR == 'SQ':\n            # recursive call to get sequence item JSON dicts\n            value = [\n                ds.to_json(\n                    bulk_data_element_handler=bulk_data_element_handler,\n                    bulk_data_threshold=bulk_data_threshold,\n                    dump_handler=lambda d: d\n                )\n                for ds in self.value\n            ]\n            json_element['Value'] = value\n        elif self.VR == 'PN':\n            if not self.is_empty:\n                elem_value = []\n                if self.VM > 1:\n                    value = self.value\n                else:\n                    value = [self.value]\n                for v in value:\n                    comps = {'Alphabetic': v.components[0]}\n                    if len(v.components) > 1:\n                        comps['Ideographic'] = v.components[1]\n                    if len(v.components) > 2:\n                        comps['Phonetic'] = v.components[2]\n                    elem_value.append(comps)\n                json_element['Value'] = elem_value\n        elif self.VR == 'AT':\n            if not self.is_empty:\n                value = self.value\n                if self.VM == 1:\n                    value = [value]\n                json_element['Value'] = [format(v, '08X') for v in value]\n        else:\n            if not self.is_empty:\n                if self.VM > 1:\n                    value = self.value\n                else:\n                    value = [self.value]\n                json_element['Value'] = [v for v in value]\n        if 'Value' in json_element:\n            json_element['Value'] = jsonrep.convert_to_python_number(\n                json_element['Value'], self.VR\n            )\n        return json_element\n\n    def to_json(\n        self,\n        bulk_data_threshold: int = 1024,\n        bulk_data_element_handler: Optional[\n            Callable[[\"DataElement\"], str]\n        ] = None,\n        dump_handler: Optional[\n            Callable[[Dict[Any, Any]], Dict[str, Any]]\n        ] = None\n    ) -> Dict[str, Any]:\n        \"\"\"Return a JSON representation of the :class:`DataElement`.\n\n        .. versionadded:: 1.3\n\n        Parameters\n        ----------\n        bulk_data_element_handler: callable, optional\n            Callable that accepts a bulk data element and returns the\n            \"BulkDataURI\" for retrieving the value of the data element\n            via DICOMweb WADO-RS\n        bulk_data_threshold: int, optional\n            Size of base64 encoded data element above which a value will be\n            provided in form of a \"BulkDataURI\" rather than \"InlineBinary\".\n            Ignored if no bulk data handler is given.\n        dump_handler : callable, optional\n            Callable function that accepts a :class:`dict` and returns the\n            serialized (dumped) JSON string (by default uses\n            :func:`json.dumps`).\n\n        Returns\n        -------\n        dict\n            Mapping representing a JSON encoded data element\n\n        See also\n        --------\n        Dataset.to_json\n        \"\"\"\n        if dump_handler is None:\n            def json_dump(d):\n                return json.dumps(d, sort_keys=True)\n\n            dump_handler = json_dump\n\n        return dump_handler(\n            self.to_json_dict(bulk_data_element_handler, bulk_data_threshold)\n        )\n\n    @property\n    def value(self) -> Any:\n        \"\"\"Return the element's value.\"\"\"\n        return self._value\n\n    @value.setter\n    def value(self, val: Any) -> None:\n        \"\"\"Convert (if necessary) and set the value of the element.\"\"\"\n        # Check if is a string with multiple values separated by '\\'\n        # If so, turn them into a list of separate strings\n        #  Last condition covers 'US or SS' etc\n        if isinstance(val, (str, bytes)) and self.VR not in \\\n                ['UT', 'ST', 'LT', 'FL', 'FD', 'AT', 'OB', 'OW', 'OF', 'SL',\n                 'SQ', 'SS', 'UL', 'OB/OW', 'OW/OB', 'OB or OW',\n                 'OW or OB', 'UN'] and 'US' not in self.VR:\n            try:\n                if _backslash_str in val:\n                    val = cast(str, val).split(_backslash_str)\n            except TypeError:\n                if _backslash_byte in val:\n                    val = val.split(_backslash_byte)\n        self._value = self._convert_value(val)\n\n    @property\n    def VM(self) -> int:\n        \"\"\"Return the value multiplicity of the element as :class:`int`.\"\"\"\n        if self.value is None:\n            return 0\n        if isinstance(self.value, (str, bytes, PersonName)):\n            return 1 if self.value else 0\n        try:\n            iter(self.value)\n        except TypeError:\n            return 1\n        return len(self.value)\n\n    @property\n    def is_empty(self) -> bool:\n        \"\"\"Return ``True`` if the element has no value.\n\n        .. versionadded:: 1.4\n        \"\"\"\n        return self.VM == 0\n\n    @property\n    def empty_value(self) -> Union[bytes, List[str], None, str, PersonName]:\n        \"\"\"Return the value for an empty element.\n\n        .. versionadded:: 1.4\n\n        See :func:`empty_value_for_VR` for more information.\n\n        Returns\n        -------\n        str or None\n            The value this data element is assigned on decoding if it is empty.\n        \"\"\"\n        return empty_value_for_VR(self.VR)\n\n    def clear(self) -> None:\n        \"\"\"Clears the value, e.g. sets it to the configured empty value.\n\n        .. versionadded:: 1.4\n\n        See :func:`empty_value_for_VR`.\n        \"\"\"\n        self._value = self.empty_value\n\n    def _convert_value(self, val: Any) -> Any:\n        \"\"\"Convert `val` to an appropriate type and return the result.\n\n        Uses the element's VR in order to determine the conversion method and\n        resulting type.\n        \"\"\"\n        if self.VR == 'SQ':  # a sequence - leave it alone\n            from pydicom.sequence import Sequence\n            if isinstance(val, Sequence):\n                return val\n            else:\n                return Sequence(val)\n\n        # if the value is a list, convert each element\n        try:\n            val.append\n        except AttributeError:  # not a list\n            return self._convert(val)\n        else:\n            return MultiValue(self._convert, val)\n\n    def _convert(self, val: Any) -> Any:\n        \"\"\"Convert `val` to an appropriate type for the element's VR.\"\"\"\n        # If the value is a byte string and has a VR that can only be encoded\n        # using the default character repertoire, we convert it to a string\n        # here to allow for byte string input in these cases\n        if _is_bytes(val) and self.VR in (\n                'AE', 'AS', 'CS', 'DA', 'DS', 'DT', 'IS', 'TM', 'UI', 'UR'):\n            val = val.decode()\n\n        if self.VR == 'IS':\n            return pydicom.valuerep.IS(val)\n        elif self.VR == 'DA' and config.datetime_conversion:\n            return pydicom.valuerep.DA(val)\n        elif self.VR == 'DS':\n            return pydicom.valuerep.DS(val)\n        elif self.VR == 'DT' and config.datetime_conversion:\n            return pydicom.valuerep.DT(val)\n        elif self.VR == 'TM' and config.datetime_conversion:\n            return pydicom.valuerep.TM(val)\n        elif self.VR == \"UI\":\n            return UID(val) if val is not None else None\n        elif self.VR == \"PN\":\n            return PersonName(val)\n        elif self.VR == \"AT\" and (val == 0 or val):\n            return val if isinstance(val, BaseTag) else Tag(val)\n        # Later may need this for PersonName as for UI,\n        #    but needs more thought\n        # elif self.VR == \"PN\":\n        #    return PersonName(val)\n        else:  # is either a string or a type 2 optionally blank string\n            return val  # this means a \"numeric\" value could be empty string \"\"\n        # except TypeError:\n            # print \"Could not convert value '%s' to VR '%s' in tag %s\" \\\n            # % (repr(val), self.VR, self.tag)\n        # except ValueError:\n            # print \"Could not convert value '%s' to VR '%s' in tag %s\" \\\n            # % (repr(val), self.VR, self.tag)\n\n    def __eq__(self, other: Any) -> bool:\n        \"\"\"Compare `self` and `other` for equality.\n\n        Returns\n        -------\n        bool\n            The result if `self` and `other` are the same class\n        NotImplemented\n            If `other` is not the same class as `self` then returning\n            :class:`NotImplemented` delegates the result to\n            ``superclass.__eq__(subclass)``.\n        \"\"\"\n        # Faster result if same object\n        if other is self:\n            return True\n\n        if isinstance(other, self.__class__):\n            if self.tag != other.tag or self.VR != other.VR:\n                return False\n\n            # tag and VR match, now check the value\n            if config.have_numpy and isinstance(self.value, numpy.ndarray):\n                return (len(self.value) == len(other.value)\n                        and numpy.allclose(self.value, other.value))\n            else:\n                return self.value == other.value\n\n        return NotImplemented\n\n    def __ne__(self, other: Any) -> bool:\n        \"\"\"Compare `self` and `other` for inequality.\"\"\"\n        return not (self == other)\n\n    def __str__(self) -> str:\n        \"\"\"Return :class:`str` representation of the element.\"\"\"\n        repVal = self.repval or ''\n        if self.showVR:\n            s = \"%s %-*s %s: %s\" % (str(self.tag), self.descripWidth,\n                                    self.description()[:self.descripWidth],\n                                    self.VR, repVal)\n        else:\n            s = \"%s %-*s %s\" % (str(self.tag), self.descripWidth,\n                                self.description()[:self.descripWidth], repVal)\n        return s\n\n    @property\n    def repval(self) -> str:\n        \"\"\"Return a :class:`str` representation of the element's value.\"\"\"\n        long_VRs = {\"OB\", \"OD\", \"OF\", \"OW\", \"UN\", \"UT\"}\n        if set(self.VR.split(\" or \")) & long_VRs:\n            try:\n                length = len(self.value)\n            except TypeError:\n                pass\n            else:\n                if length > self.maxBytesToDisplay:\n                    return \"Array of %d elements\" % length\n        if self.VM > self.maxBytesToDisplay:\n            repVal = \"Array of %d elements\" % self.VM\n        elif isinstance(self.value, UID):\n            repVal = self.value.name\n        else:\n            repVal = repr(self.value)  # will tolerate unicode too\n        return repVal\n\n    def __getitem__(self, key: int) -> Any:\n        \"\"\"Return the item at `key` if the element's value is indexable.\"\"\"\n        try:\n            return self.value[key]\n        except TypeError:\n            raise TypeError(\"DataElement value is unscriptable \"\n                            \"(not a Sequence)\")\n\n    @property\n    def name(self) -> str:\n        \"\"\"Return the DICOM dictionary name for the element as :class:`str`.\n\n        For officially registered DICOM Data Elements this will be the *Name*\n        as given in :dcm:`Table 6-1<part06/chapter_6.html#table_6-1>`.\n        For private elements known to *pydicom*\n        this will be the *Name* in the format ``'[name]'``. For unknown\n        private elements this will be ``'Private Creator'``. For unknown\n        elements this will return an empty string ``''``.\n        \"\"\"\n        return self.description()\n\n    def description(self) -> str:\n        \"\"\"Return the DICOM dictionary name for the element as :class:`str`.\"\"\"\n        if self.tag.is_private:\n            name = \"Private tag data\"  # default\n            if self.private_creator:\n                try:\n                    # If have name from private dictionary, use it, but\n                    #   but put in square brackets so is differentiated,\n                    #   and clear that cannot access it by name\n                    name = private_dictionary_description(\n                        self.tag, self.private_creator)\n                    name = \"[%s]\" % (name)\n                except KeyError:\n                    pass\n            elif self.tag.element >> 8 == 0:\n                name = \"Private Creator\"\n        elif dictionary_has_tag(self.tag) or repeater_has_tag(self.tag):\n            name = dictionary_description(self.tag)\n\n        # implied Group Length dicom versions < 3\n        elif self.tag.element == 0:\n            name = \"Group Length\"\n        else:\n            name = \"\"\n        return name\n\n    @property\n    def is_private(self) -> bool:\n        \"\"\"Return ``True`` if the element's tag is private.\n\n        .. versionadded:: 2.1\n        \"\"\"\n        return self.tag.is_private\n\n    @property\n    def is_retired(self) -> bool:\n        \"\"\"Return the element's retired status as :class:`bool`.\n\n        For officially registered DICOM Data Elements this will be ``True`` if\n        the retired status as given in the DICOM Standard, Part 6,\n        :dcm:`Table 6-1<part06/chapter_6.html#table_6-1>` is 'RET'. For private\n        or unknown elements this will always be ``False``.\n        \"\"\"\n        if dictionary_has_tag(self.tag):\n            return dictionary_is_retired(self.tag)\n\n        return False\n\n    @property\n    def keyword(self) -> str:\n        \"\"\"Return the element's keyword (if known) as :class:`str`.\n\n        For officially registered DICOM Data Elements this will be the\n        *Keyword* as given in\n        :dcm:`Table 6-1<part06/chapter_6.html#table_6-1>`. For private or\n        unknown elements this will return an empty string ``''``.\n        \"\"\"\n        if dictionary_has_tag(self.tag):\n            return dictionary_keyword(self.tag)\n\n        return ''\n\n    def __repr__(self) -> str:\n        \"\"\"Return the representation of the element.\"\"\"\n        if self.VR == \"SQ\":\n            return repr(self.value)\n\n        return str(self)\n\n\nclass RawDataElement(NamedTuple):\n    \"\"\"Container for the data from a raw (mostly) undecoded element.\"\"\"\n    tag: BaseTag\n    VR: Optional[str]\n    length: int\n    value: Optional[bytes]\n    value_tell: int\n    is_implicit_VR: bool\n    is_little_endian: bool\n    is_raw: bool = True\n\n\n# The first and third values of the following elements are always US\n#   even if the VR is SS (PS3.3 C.7.6.3.1.5, C.11.1, C.11.2).\n# (0028,1101-1103) RGB Palette Color LUT Descriptor\n# (0028,3002) LUT Descriptor\n_LUT_DESCRIPTOR_TAGS = (0x00281101, 0x00281102, 0x00281103, 0x00283002)\n\n\ndef _private_vr_for_tag(ds: Optional[\"Dataset\"], tag: BaseTag) -> str:\n    \"\"\"Return the VR for a known private tag, otherwise \"UN\".\n\n    Parameters\n    ----------\n    ds : Dataset, optional\n        The dataset needed for the private creator lookup.\n        If not given, \"UN\" is returned.\n    tag : BaseTag\n        The private tag to lookup. The caller has to ensure that the\n        tag is private.\n\n    Returns\n    -------\n    str\n        \"LO\" if the tag is a private creator, the VR of the private tag if\n        found in the private dictionary, or \"UN\".\n    \"\"\"\n    if tag.is_private_creator:\n        return \"LO\"\n    # invalid private tags are handled as UN\n    if ds is not None and (tag.element & 0xff00):\n        private_creator_tag = tag.group << 16 | (tag.element >> 8)\n        private_creator = ds.get(private_creator_tag, \"\")\n        if private_creator:\n            try:\n                return private_dictionary_VR(tag, private_creator.value)\n            except KeyError:\n                pass\n    return \"UN\"\n\n\ndef DataElement_from_raw(\n    raw_data_element: RawDataElement,\n    encoding: Optional[Union[str, MutableSequence[str]]] = None,\n    dataset: Optional[\"Dataset\"] = None\n) -> DataElement:\n    \"\"\"Return a :class:`DataElement` created from `raw_data_element`.\n\n    Parameters\n    ----------\n    raw_data_element : RawDataElement\n        The raw data to convert to a :class:`DataElement`.\n    encoding : str or list of str, optional\n        The character encoding of the raw data.\n    dataset : Dataset, optional\n        If given, used to resolve the VR for known private tags.\n\n    Returns\n    -------\n    DataElement\n\n    Raises\n    ------\n    KeyError\n        If `raw_data_element` belongs to an unknown non-private tag and\n        `config.enforce_valid_values` is set.\n    \"\"\"\n    # XXX buried here to avoid circular import\n    # filereader->Dataset->convert_value->filereader\n    # (for SQ parsing)\n\n    from pydicom.values import convert_value\n    raw = raw_data_element\n\n    # If user has hooked into conversion of raw values, call his/her routine\n    if config.data_element_callback:\n        raw = config.data_element_callback(\n            raw_data_element,\n            encoding=encoding,\n            **config.data_element_callback_kwargs\n        )\n\n    VR = raw.VR\n    if VR is None:  # Can be if was implicit VR\n        try:\n            VR = dictionary_VR(raw.tag)\n        except KeyError:\n            # just read the bytes, no way to know what they mean\n            if raw.tag.is_private:\n                # for VR for private tags see PS3.5, 6.2.2\n                VR = _private_vr_for_tag(dataset, raw.tag)\n\n            # group length tag implied in versions < 3.0\n            elif raw.tag.element == 0:\n                VR = 'UL'\n            else:\n                msg = \"Unknown DICOM tag {0:s}\".format(str(raw.tag))\n                if config.enforce_valid_values:\n                    msg += \" can't look up VR\"\n                    raise KeyError(msg)\n                else:\n                    VR = 'UN'\n                    msg += \" - setting VR to 'UN'\"\n                    warnings.warn(msg)\n    elif VR == 'UN' and config.replace_un_with_known_vr:\n        # handle rare case of incorrectly set 'UN' in explicit encoding\n        # see also DataElement.__init__()\n        if raw.tag.is_private:\n            VR = _private_vr_for_tag(dataset, raw.tag)\n        elif raw.value is None or len(raw.value) < 0xffff:\n            try:\n                VR = dictionary_VR(raw.tag)\n            except KeyError:\n                pass\n    try:\n        value = convert_value(VR, raw, encoding)\n    except NotImplementedError as e:\n        raise NotImplementedError(\"{0:s} in tag {1!r}\".format(str(e), raw.tag))\n    except BytesLengthException as e:\n        message = (f\"{e} This occurred while trying to parse \"\n                   f\"{raw.tag} according to VR '{VR}'.\")\n        if config.convert_wrong_length_to_UN:\n            warnings.warn(f\"{message} Setting VR to 'UN'.\")\n            VR = \"UN\"\n            value = raw.value\n        else:\n            raise BytesLengthException(\n                f\"{message} To replace this error with a warning set \"\n                \"pydicom.config.convert_wrong_length_to_UN = True.\"\n            )\n\n    if raw.tag in _LUT_DESCRIPTOR_TAGS and value:\n        # We only fix the first value as the third value is 8 or 16\n        try:\n            if value[0] < 0:\n                value[0] += 65536\n        except TypeError:\n            pass\n\n    return DataElement(raw.tag, VR, value, raw.value_tell,\n                       raw.length == 0xFFFFFFFF, already_converted=True)\n","new_file_content":"# Copyright 2008-2018 pydicom authors. See LICENSE file for details.\n\"\"\"Define the DataElement class.\n\nA DataElement has a tag,\n              a value representation (VR),\n              a value multiplicity (VM)\n              and a value.\n\"\"\"\n\n\nimport base64\nimport json\nfrom collections import namedtuple\n\nfrom pydicom import config  # don't import datetime_conversion directly\nfrom pydicom.config import logger\nfrom pydicom import config\nfrom pydicom.datadict import (dictionary_has_tag, dictionary_description,\n                              dictionary_keyword, dictionary_is_retired,\n                              private_dictionary_description, dictionary_VR,\n                              repeater_has_tag)\nfrom pydicom.jsonrep import JsonDataElementConverter\nfrom pydicom.multival import MultiValue\nfrom pydicom.tag import Tag, BaseTag\nfrom pydicom.uid import UID\nfrom pydicom import jsonrep\nimport pydicom.valuerep  # don't import DS directly as can be changed by config\nfrom pydicom.valuerep import PersonName\n\nif config.have_numpy:\n    import numpy\n\nBINARY_VR_VALUES = [\n    'US', 'SS', 'UL', 'SL', 'OW', 'OB', 'OL', 'UN',\n    'OB or OW', 'US or OW', 'US or SS or OW', 'FL', 'FD', 'OF', 'OD'\n]\n\n\ndef empty_value_for_VR(VR, raw=False):\n    \"\"\"Return the value for an empty element for `VR`.\n\n    .. versionadded:: 1.4\n\n    The behavior of this property depends on the setting of\n    :attr:`config.use_none_as_empty_value`. If that is set to ``True``,\n    an empty value is represented by ``None`` (except for VR 'SQ'), otherwise\n    it depends on `VR`. For text VRs (this includes 'AE', 'AS', 'CS', 'DA',\n    'DT', 'LO', 'LT', 'PN', 'SH', 'ST', 'TM', 'UC', 'UI', 'UR' and 'UT') an\n    empty string is used as empty value representation, for all other VRs\n    except 'SQ', ``None``. For empty sequence values (VR 'SQ') an empty list\n    is used in all cases.\n    Note that this is used only if decoding the element - it is always\n    possible to set the value to another empty value representation,\n    which will be preserved during the element object lifetime.\n\n    Parameters\n    ----------\n    VR : str\n        The VR of the corresponding element.\n\n    raw : bool\n        If ``True``, returns the value for a :class:`RawDataElement`,\n        otherwise for a :class:`DataElement`\n\n    Returns\n    -------\n    str or bytes or None or list\n        The value a data element with `VR` is assigned on decoding\n        if it is empty.\n    \"\"\"\n    if VR == 'SQ':\n        return b'' if raw else []\n    if config.use_none_as_empty_text_VR_value:\n        return None\n    if VR in ('AE', 'AS', 'CS', 'DA', 'DT', 'LO', 'LT',\n              'PN', 'SH', 'ST', 'TM', 'UC', 'UI', 'UR', 'UT'):\n        return b'' if raw else ''\n    return None\n\n\ndef _is_bytes(val):\n    \"\"\"Return True only if `val` is of type `bytes`.\"\"\"\n    return isinstance(val, bytes)\n\n\n# double '\\' because it is used as escape chr in Python\n_backslash_str = \"\\\\\"\n_backslash_byte = b\"\\\\\"\n\n\nclass DataElement:\n    \"\"\"Contain and manipulate a DICOM Element.\n\n    Examples\n    --------\n\n    While its possible to create a new :class:`DataElement` directly and add\n    it to a :class:`~pydicom.dataset.Dataset`:\n\n    >>> from pydicom import Dataset\n    >>> elem = DataElement(0x00100010, 'PN', 'CITIZEN^Joan')\n    >>> ds = Dataset()\n    >>> ds.add(elem)\n\n    Its far more convenient to use a :class:`~pydicom.dataset.Dataset`\n    to add a new :class:`DataElement`, as the VR and tag are determined\n    automatically from the DICOM dictionary:\n\n    >>> ds = Dataset()\n    >>> ds.PatientName = 'CITIZEN^Joan'\n\n    Empty DataElement objects (e.g. with VM = 0) show an empty string as\n    value for text VRs and `None` for non-text (binary) VRs:\n\n    >>> ds = Dataset()\n    >>> ds.PatientName = None\n    >>> ds.PatientName\n    ''\n\n    >>> ds.BitsAllocated = None\n    >>> ds.BitsAllocated\n\n    >>> str(ds.BitsAllocated)\n    'None'\n\n    Attributes\n    ----------\n    descripWidth : int\n        For string display, this is the maximum width of the description\n        field (default ``35``).\n    is_undefined_length : bool\n        Indicates whether the length field for the element was ``0xFFFFFFFFL``\n        (ie undefined).\n    maxBytesToDisplay : int\n        For string display, elements with values containing data which is\n        longer than this value will display ``\"array of # bytes\"``\n        (default ``16``).\n    showVR : bool\n        For string display, include the element's VR just before it's value\n        (default ``True``).\n    tag : BaseTag\n        The element's tag.\n    value\n        The element's stored value(s).\n    VR : str\n        The element's Value Representation.\n    \"\"\"\n\n    descripWidth = 35\n    maxBytesToDisplay = 16\n    showVR = True\n    is_raw = False\n\n    def __init__(self,\n                 tag,\n                 VR,\n                 value,\n                 file_value_tell=None,\n                 is_undefined_length=False,\n                 already_converted=False):\n        \"\"\"Create a new :class:`DataElement`.\n\n        Parameters\n        ----------\n        tag : int or or str or list or tuple\n            The DICOM (group, element) tag in any form accepted by\n            :func:`~pydicom.tag.Tag` such as ``[0x0010, 0x0010]``,\n            ``(0x10, 0x10)``, ``0x00100010``, etc.\n        VR : str\n            The 2 character DICOM value representation (see DICOM Standard,\n            Part 5, :dcm:`Section 6.2<part05/sect_6.2.html>`).\n        value\n            The value of the data element. One of the following:\n\n            * a single string value\n            * a number\n            * a :class:`list` or :class:`tuple` with all strings or all numbers\n            * a multi-value string with backslash separator\n\n        file_value_tell : int or None\n            Used internally by :class:`~pydicom.dataset.Dataset` to\n            store the write position for the ``ReplaceDataElementValue()``\n            method. Default is ``None``.\n        is_undefined_length : bool\n            Used internally to store whether the length field for this element\n            was ``0xFFFFFFFFL``, i.e. 'undefined length'. Default is ``False``.\n        already_converted : bool\n            Used to determine whether or not the element's value requires\n            conversion to a value with VM > 1. Default is ``False``.\n        \"\"\"\n        if not isinstance(tag, BaseTag):\n            tag = Tag(tag)\n        self.tag = tag\n\n        # a known tag shall only have the VR 'UN' if it has a length that\n        # exceeds the size that can be encoded in 16 bit - all other cases\n        # can be seen as an encoding error and can be corrected\n        if (VR == 'UN' and not tag.is_private and\n                config.replace_un_with_known_vr and\n                (is_undefined_length or value is None or len(value) < 0xffff)):\n            try:\n                VR = dictionary_VR(tag)\n            except KeyError:\n                pass\n\n        self.VR = VR  # Note: you must set VR before setting value\n        if already_converted:\n            self._value = value\n        else:\n            self.value = value  # calls property setter which will convert\n        self.file_tell = file_value_tell\n        self.is_undefined_length = is_undefined_length\n        self.private_creator = None\n\n    @classmethod\n    def from_json(cls, dataset_class, tag, vr, value, value_key,\n                  bulk_data_uri_handler=None):\n        \"\"\"Return a :class:`DataElement` from JSON.\n\n        .. versionadded:: 1.3\n\n        Parameters\n        ----------\n        dataset_class : dataset.Dataset derived class\n            Class used to create sequence items.\n        tag : BaseTag or int\n            The data element tag.\n        vr : str\n            The data element value representation.\n        value : list\n            The data element's value(s).\n        value_key : str or None\n            Key of the data element that contains the value\n            (options: ``{\"Value\", \"InlineBinary\", \"BulkDataURI\"}``)\n        bulk_data_uri_handler: callable or None\n            Callable function that accepts the \"BulkDataURI\" of the JSON\n            representation of a data element and returns the actual value of\n            that data element (retrieved via DICOMweb WADO-RS)\n\n        Returns\n        -------\n        DataElement\n        \"\"\"\n        # TODO: test wado-rs retrieve wrapper\n        converter = JsonDataElementConverter(dataset_class, tag, vr, value,\n                                             value_key, bulk_data_uri_handler)\n        elem_value = converter.get_element_values()\n        try:\n            return DataElement(tag=tag, value=elem_value, VR=vr)\n        except Exception:\n            raise ValueError(\n                'Data element \"{}\" could not be loaded from JSON: {}'.format(\n                    tag, elem_value\n                )\n            )\n\n    def to_json_dict(self, bulk_data_element_handler, bulk_data_threshold):\n        \"\"\"Return a dictionary representation of the :class:`DataElement`\n        conforming to the DICOM JSON Model as described in the DICOM\n        Standard, Part 18, :dcm:`Annex F<part18/chaptr_F.html>`.\n\n        .. versionadded:: 1.4\n\n        Parameters\n        ----------\n        bulk_data_element_handler: callable or None\n            Callable that accepts a bulk data element and returns the\n            \"BulkDataURI\" for retrieving the value of the data element\n            via DICOMweb WADO-RS\n        bulk_data_threshold: int\n            Size of base64 encoded data element above which a value will be\n            provided in form of a \"BulkDataURI\" rather than \"InlineBinary\".\n            Ignored if no bulk data handler is given.\n\n        Returns\n        -------\n        dict\n            Mapping representing a JSON encoded data element\n        \"\"\"\n        json_element = {'vr': self.VR, }\n        if self.VR in jsonrep.BINARY_VR_VALUES:\n            if not self.is_empty:\n                binary_value = self.value\n                encoded_value = base64.b64encode(binary_value).decode('utf-8')\n                if (bulk_data_element_handler is not None and\n                        len(encoded_value) > bulk_data_threshold):\n                    json_element['BulkDataURI'] = bulk_data_element_handler(\n                        self\n                    )\n                else:\n                    logger.info(\n                        'encode bulk data element \"{}\" inline'.format(\n                            self.name\n                        )\n                    )\n                    json_element['InlineBinary'] = encoded_value\n        elif self.VR == 'SQ':\n            # recursive call to get sequence item JSON dicts\n            value = [\n                ds.to_json(\n                    bulk_data_element_handler=bulk_data_element_handler,\n                    bulk_data_threshold=bulk_data_threshold,\n                    dump_handler=lambda d: d\n                )\n                for ds in self\n            ]\n            json_element['Value'] = value\n        elif self.VR == 'PN':\n            if not self.is_empty:\n                elem_value = []\n                if self.VM > 1:\n                    value = self.value\n                else:\n                    value = [self.value]\n                for v in value:\n                    comps = {'Alphabetic': v.components[0]}\n                    if len(v.components) > 1:\n                        comps['Ideographic'] = v.components[1]\n                    if len(v.components) > 2:\n                        comps['Phonetic'] = v.components[2]\n                    elem_value.append(comps)\n                json_element['Value'] = elem_value\n        elif self.VR == 'AT':\n            if not self.is_empty:\n                value = self.value\n                if self.VM == 1:\n                    value = [value]\n                json_element['Value'] = [format(v, '08X') for v in value]\n        else:\n            if not self.is_empty:\n                if self.VM > 1:\n                    value = self.value\n                else:\n                    value = [self.value]\n                json_element['Value'] = [v for v in value]\n        if hasattr(json_element, 'Value'):\n            json_element['Value'] = jsonrep.convert_to_python_number(\n                json_element['Value'], self.VR\n            )\n        return json_element\n\n    def to_json(self, bulk_data_threshold=1024, bulk_data_element_handler=None,\n                dump_handler=None):\n        \"\"\"Return a JSON representation of the :class:`DataElement`.\n\n        .. versionadded:: 1.3\n\n        Parameters\n        ----------\n        bulk_data_element_handler: callable or None\n            Callable that accepts a bulk data element and returns the\n            \"BulkDataURI\" for retrieving the value of the data element\n            via DICOMweb WADO-RS\n        bulk_data_threshold: int\n            Size of base64 encoded data element above which a value will be\n            provided in form of a \"BulkDataURI\" rather than \"InlineBinary\".\n            Ignored if no bulk data handler is given.\n        dump_handler : callable, optional\n            Callable function that accepts a :class:`dict` and returns the\n            serialized (dumped) JSON string (by default uses\n            :func:`json.dumps`).\n\n        Returns\n        -------\n        dict\n            Mapping representing a JSON encoded data element\n\n        See also\n        --------\n        Dataset.to_json\n        \"\"\"\n        if dump_handler is None:\n            def json_dump(d):\n                return json.dumps(d, sort_keys=True)\n\n            dump_handler = json_dump\n\n        return dump_handler(\n            self.to_json_dict(bulk_data_threshold, bulk_data_element_handler))\n\n    @property\n    def value(self):\n        \"\"\"Return the element's value.\"\"\"\n        return self._value\n\n    @value.setter\n    def value(self, val):\n        \"\"\"Convert (if necessary) and set the value of the element.\"\"\"\n        # Check if is a string with multiple values separated by '\\'\n        # If so, turn them into a list of separate strings\n        #  Last condition covers 'US or SS' etc\n        if isinstance(val, (str, bytes)) and self.VR not in \\\n                ['UT', 'ST', 'LT', 'FL', 'FD', 'AT', 'OB', 'OW', 'OF', 'SL',\n                 'SQ', 'SS', 'UL', 'OB/OW', 'OW/OB', 'OB or OW',\n                 'OW or OB', 'UN'] and 'US' not in self.VR:\n            try:\n                if _backslash_str in val:\n                    val = val.split(_backslash_str)\n            except TypeError:\n                if _backslash_byte in val:\n                    val = val.split(_backslash_byte)\n        self._value = self._convert_value(val)\n\n    @property\n    def VM(self):\n        \"\"\"Return the value multiplicity of the element as :class:`int`.\"\"\"\n        if self.value is None:\n            return 0\n        if isinstance(self.value, (str, bytes, PersonName)):\n            return 1 if self.value else 0\n        try:\n            iter(self.value)\n        except TypeError:\n            return 1\n        return len(self.value)\n\n    @property\n    def is_empty(self):\n        \"\"\"Return ``True`` if the element has no value.\n\n        .. versionadded:: 1.4\n        \"\"\"\n        return self.VM == 0\n\n    @property\n    def empty_value(self):\n        \"\"\"Return the value for an empty element.\n\n        .. versionadded:: 1.4\n\n        See :func:`empty_value_for_VR` for more information.\n\n        Returns\n        -------\n        str or None\n            The value this data element is assigned on decoding if it is empty.\n        \"\"\"\n        return empty_value_for_VR(self.VR)\n\n    def clear(self):\n        \"\"\"Clears the value, e.g. sets it to the configured empty value.\n\n        .. versionadded:: 1.4\n\n        See :func:`empty_value_for_VR`.\n        \"\"\"\n        self._value = self.empty_value\n\n    def _convert_value(self, val):\n        \"\"\"Convert `val` to an appropriate type and return the result.\n\n        Uses the element's VR in order to determine the conversion method and\n        resulting type.\n        \"\"\"\n        if self.VR == 'SQ':  # a sequence - leave it alone\n            from pydicom.sequence import Sequence\n            if isinstance(val, Sequence):\n                return val\n            else:\n                return Sequence(val)\n\n        # if the value is a list, convert each element\n        try:\n            val.append\n        except AttributeError:  # not a list\n            return self._convert(val)\n        else:\n            return MultiValue(self._convert, val)\n\n    def _convert(self, val):\n        \"\"\"Convert `val` to an appropriate type for the element's VR.\"\"\"\n        # If the value is a byte string and has a VR that can only be encoded\n        # using the default character repertoire, we convert it to a string\n        # here to allow for byte string input in these cases\n        if _is_bytes(val) and self.VR in (\n                'AE', 'AS', 'CS', 'DA', 'DS', 'DT', 'IS', 'TM', 'UI', 'UR'):\n            val = val.decode()\n\n        if self.VR == 'IS':\n            return pydicom.valuerep.IS(val)\n        elif self.VR == 'DA' and config.datetime_conversion:\n            return pydicom.valuerep.DA(val)\n        elif self.VR == 'DS':\n            return pydicom.valuerep.DS(val)\n        elif self.VR == 'DT' and config.datetime_conversion:\n            return pydicom.valuerep.DT(val)\n        elif self.VR == 'TM' and config.datetime_conversion:\n            return pydicom.valuerep.TM(val)\n        elif self.VR == \"UI\":\n            return UID(val) if val is not None else None\n        elif self.VR == \"PN\":\n            return PersonName(val)\n        # Later may need this for PersonName as for UI,\n        #    but needs more thought\n        # elif self.VR == \"PN\":\n        #    return PersonName(val)\n        else:  # is either a string or a type 2 optionally blank string\n            return val  # this means a \"numeric\" value could be empty string \"\"\n        # except TypeError:\n            # print \"Could not convert value '%s' to VR '%s' in tag %s\" \\\n            # % (repr(val), self.VR, self.tag)\n        # except ValueError:\n            # print \"Could not convert value '%s' to VR '%s' in tag %s\" \\\n            # % (repr(val), self.VR, self.tag)\n\n    def __eq__(self, other):\n        \"\"\"Compare `self` and `other` for equality.\n\n        Returns\n        -------\n        bool\n            The result if `self` and `other` are the same class\n        NotImplemented\n            If `other` is not the same class as `self` then returning\n            :class:`NotImplemented` delegates the result to\n            ``superclass.__eq__(subclass)``.\n        \"\"\"\n        # Faster result if same object\n        if other is self:\n            return True\n\n        if isinstance(other, self.__class__):\n            if self.tag != other.tag or self.VR != other.VR:\n                return False\n\n            # tag and VR match, now check the value\n            if config.have_numpy and isinstance(self.value, numpy.ndarray):\n                return (len(self.value) == len(other.value)\n                        and numpy.allclose(self.value, other.value))\n            else:\n                return self.value == other.value\n\n        return NotImplemented\n\n    def __ne__(self, other):\n        \"\"\"Compare `self` and `other` for inequality.\"\"\"\n        return not (self == other)\n\n    def __str__(self):\n        \"\"\"Return :class:`str` representation of the element.\"\"\"\n        repVal = self.repval or ''\n        if self.showVR:\n            s = \"%s %-*s %s: %s\" % (str(self.tag), self.descripWidth,\n                                    self.description()[:self.descripWidth],\n                                    self.VR, repVal)\n        else:\n            s = \"%s %-*s %s\" % (str(self.tag), self.descripWidth,\n                                self.description()[:self.descripWidth], repVal)\n        return s\n\n    @property\n    def repval(self):\n        \"\"\"Return a :class:`str` representation of the element's value.\"\"\"\n        long_VRs = {\"OB\", \"OD\", \"OF\", \"OW\", \"UN\", \"UT\"}\n        if set(self.VR.split(\" or \")) & long_VRs:\n            try:\n                length = len(self.value)\n            except TypeError:\n                pass\n            else:\n                if length > self.maxBytesToDisplay:\n                    return \"Array of %d elements\" % length\n        if self.VM > self.maxBytesToDisplay:\n            repVal = \"Array of %d elements\" % self.VM\n        elif isinstance(self.value, UID):\n            repVal = self.value.name\n        else:\n            repVal = repr(self.value)  # will tolerate unicode too\n        return repVal\n\n    def __unicode__(self):\n        \"\"\"Return unicode representation of the element.\"\"\"\n        if isinstance(self.value, str):\n            # start with the string rep then replace the value part\n            #   with the unicode\n            strVal = str(self)\n            strVal = strVal.replace(self.repval, \"\")\n            uniVal = str(strVal) + self.value\n            return uniVal\n        else:\n            return str(self)\n\n    def __getitem__(self, key):\n        \"\"\"Return the item at `key` if the element's value is indexable.\"\"\"\n        try:\n            return self.value[key]\n        except TypeError:\n            raise TypeError(\"DataElement value is unscriptable \"\n                            \"(not a Sequence)\")\n\n    @property\n    def name(self):\n        \"\"\"Return the DICOM dictionary name for the element as :class:`str`.\n\n        For officially registered DICOM Data Elements this will be the *Name*\n        as given in :dcm:`Table 6-1<part06/chapter_6.html#table_6-1>`.\n        For private elements known to *pydicom*\n        this will be the *Name* in the format ``'[name]'``. For unknown\n        private elements this will be ``'Private Creator'``. For unknown\n        elements this will return an empty string ``''``.\n        \"\"\"\n        return self.description()\n\n    def description(self):\n        \"\"\"Return the DICOM dictionary name for the element as :class:`str`.\"\"\"\n        if self.tag.is_private:\n            name = \"Private tag data\"  # default\n            if self.private_creator:\n                try:\n                    # If have name from private dictionary, use it, but\n                    #   but put in square brackets so is differentiated,\n                    #   and clear that cannot access it by name\n                    name = private_dictionary_description(\n                        self.tag, self.private_creator)\n                    name = \"[%s]\" % (name)\n                except KeyError:\n                    pass\n            elif self.tag.element >> 8 == 0:\n                name = \"Private Creator\"\n        elif dictionary_has_tag(self.tag) or repeater_has_tag(self.tag):\n            name = dictionary_description(self.tag)\n\n        # implied Group Length dicom versions < 3\n        elif self.tag.element == 0:\n            name = \"Group Length\"\n        else:\n            name = \"\"\n        return name\n\n    @property\n    def is_retired(self):\n        \"\"\"Return the element's retired status as :class:`bool`.\n\n        For officially registered DICOM Data Elements this will be ``True`` if\n        the retired status as given in the DICOM Standard, Part 6,\n        :dcm:`Table 6-1<part06/chapter_6.html#table_6-1>` is 'RET'. For private\n        or unknown elements this will always be ``False``.\n        \"\"\"\n        if dictionary_has_tag(self.tag):\n            return dictionary_is_retired(self.tag)\n        else:\n            return False\n\n    @property\n    def keyword(self):\n        \"\"\"Return the element's keyword (if known) as :class:`str`.\n\n        For officially registered DICOM Data Elements this will be the\n        *Keyword* as given in\n        :dcm:`Table 6-1<part06/chapter_6.html#table_6-1>`. For private or\n        unknown elements this will return an empty string ``''``.\n        \"\"\"\n        if dictionary_has_tag(self.tag):\n            return dictionary_keyword(self.tag)\n        else:\n            return ''\n\n    def __repr__(self):\n        \"\"\"Return the representation of the element.\"\"\"\n        if self.VR == \"SQ\":\n            return repr(self.value)\n        else:\n            return str(self)\n\n\nmsg = 'tag VR length value value_tell is_implicit_VR is_little_endian'\nRawDataElement = namedtuple('RawDataElement', msg)\nRawDataElement.is_raw = True\n\n\n# The first and third values of the following elements are always US\n#   even if the VR is SS (PS3.3 C.7.6.3.1.5, C.11.1, C.11.2).\n# (0028,1101-1103) RGB Palette Color LUT Descriptor\n# (0028,3002) LUT Descriptor\n_LUT_DESCRIPTOR_TAGS = (0x00281101, 0x00281102, 0x00281103, 0x00283002)\n\n\ndef DataElement_from_raw(raw_data_element, encoding=None):\n    \"\"\"Return a :class:`DataElement` created from `raw_data_element`.\n\n    Parameters\n    ----------\n    raw_data_element : RawDataElement namedtuple\n        The raw data to convert to a :class:`DataElement`.\n    encoding : str, optional\n        The character encoding of the raw data.\n\n    Returns\n    -------\n    DataElement\n    \"\"\"\n    # XXX buried here to avoid circular import\n    # filereader->Dataset->convert_value->filereader\n    # (for SQ parsing)\n\n    from pydicom.values import convert_value\n    raw = raw_data_element\n\n    # If user has hooked into conversion of raw values, call his/her routine\n    if config.data_element_callback:\n        data_elem = config.data_element_callback\n        raw = data_elem(raw_data_element,\n                        **config.data_element_callback_kwargs)\n    VR = raw.VR\n    if VR is None:  # Can be if was implicit VR\n        try:\n            VR = dictionary_VR(raw.tag)\n        except KeyError:\n            # just read the bytes, no way to know what they mean\n            if raw.tag.is_private:\n                # for VR for private tags see PS3.5, 6.2.2\n                if raw.tag.is_private_creator:\n                    VR = 'LO'\n                else:\n                    VR = 'UN'\n\n            # group length tag implied in versions < 3.0\n            elif raw.tag.element == 0:\n                VR = 'UL'\n            else:\n                msg = \"Unknown DICOM tag {0:s}\".format(str(raw.tag))\n                msg += \" can't look up VR\"\n                raise KeyError(msg)\n    elif (VR == 'UN' and not raw.tag.is_private and\n          config.replace_un_with_known_vr):\n        # handle rare case of incorrectly set 'UN' in explicit encoding\n        # see also DataElement.__init__()\n        if (raw.length == 0xffffffff or raw.value is None or\n                len(raw.value) < 0xffff):\n            try:\n                VR = dictionary_VR(raw.tag)\n            except KeyError:\n                pass\n    try:\n        value = convert_value(VR, raw, encoding)\n    except NotImplementedError as e:\n        raise NotImplementedError(\"{0:s} in tag {1!r}\".format(str(e), raw.tag))\n\n    if raw.tag in _LUT_DESCRIPTOR_TAGS and value:\n        # We only fix the first value as the third value is 8 or 16\n        try:\n            if value[0] < 0:\n                value[0] += 65536\n        except TypeError:\n            pass\n\n    return DataElement(raw.tag, VR, value, raw.value_tell,\n                       raw.length == 0xFFFFFFFF, already_converted=True)\n","header":{"file":{"path":"pydicom/dataelem.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/pydicom/dataelem.py"},"plus_file":{"path":"b/pydicom/dataelem.py"},"hunks":[{"descriptor":{"old_range":{"start":433,"length":13},"new_range":{"start":433,"length":24},"section":"def value(self) -> Any:"},"line_group":{"all_lines":[{"content":"    @value.setter","type":"context"},{"content":"    def value(self, val: Any) -> None:","type":"context"},{"content":"        \"\"\"Convert (if necessary) and set the value of the element.\"\"\"","type":"context"},{"content":"        # Ignore backslash characters in these VRs, based on:","type":"added"},{"content":"        # * Which str VRs can have backslashes in Part 5, Section 6.2","type":"added"},{"content":"        # * All byte VRs","type":"added"},{"content":"        exclusions = [","type":"added"},{"content":"            'LT', 'OB', 'OD', 'OF', 'OL', 'OV', 'OW', 'ST', 'UN', 'UT',","type":"added"},{"content":"            'OB/OW', 'OW/OB', 'OB or OW', 'OW or OB',","type":"added"},{"content":"            # Probably not needed","type":"added"},{"content":"            'AT', 'FD', 'FL', 'SQ', 'SS', 'SL', 'UL',","type":"added"},{"content":"        ]","type":"added"},{"content":"","type":"added"},{"content":"        # Check if is a string with multiple values separated by '\\'","type":"context"},{"content":"        # If so, turn them into a list of separate strings","type":"context"},{"content":"        #  Last condition covers 'US or SS' etc","type":"context"},{"content":"        if isinstance(val, (str, bytes)) and self.VR not in \\","type":"deleted"},{"content":"                ['UT', 'ST', 'LT', 'FL', 'FD', 'AT', 'OB', 'OW', 'OF', 'SL',","type":"deleted"},{"content":"                 'SQ', 'SS', 'UL', 'OB/OW', 'OW/OB', 'OB or OW',","type":"deleted"},{"content":"                 'OW or OB', 'UN'] and 'US' not in self.VR:","type":"deleted"},{"content":"        if (","type":"added"},{"content":"            isinstance(val, (str, bytes))","type":"added"},{"content":"            and self.VR not in exclusions","type":"added"},{"content":"            and 'US' not in self.VR","type":"added"},{"content":"        ):","type":"added"},{"content":"            try:","type":"context"},{"content":"                if _backslash_str in val:","type":"context"},{"content":"                    val = cast(str, val).split(_backslash_str)","type":"context"},{"content":"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]}],"old_commit_hash":"f909c76e31f759246cec3708dadd173c5d6e84b1","new_commit_hash":"2e9301e8801e6e30c71ccf6833ec2562420bfbbd","commit_message":"next() no longer starts iterator","commit_date":"2020-06-29T10:45:31+02:00","metadata":{}}