parameters: (in_type: t.Type[T], aws_field: t.Any)
docstring: Convert an AWS item back into its py equivalent
  
      This might not even be strictly required, but we check that
      all the types are roughly what we expect, and convert
      Decimals back into ints/floats
docstring_summary: Convert an AWS item back into its py equivalent
docstring_tokens: Convert an AWS item back into its py equivalent
function: def aws_to_py(in_type: t.Type[T], aws_field: t.Any) -> T:
      """
      Convert an AWS item back into its py equivalent
  
      This might not even be strictly required, but we check that
      all the types are roughly what we expect, and convert
      Decimals back into ints/floats
      """
      origin = t.get_origin(in_type)
      args = t.get_args(in_type)
  
      check_type = origin
      if in_type is float:
          check_type = Decimal
      elif in_type is int:
          check_type = (int, Decimal)
      elif is_dataclass(in_type):
          check_type = dict
      elif check_type is set and args:
          if args[0] not in (str, float, int, Decimal):
              check_type = list
  
      if not isinstance(aws_field, check_type or in_type):
          # If you are getting random deserialization errors in tests that you did
          # not touch, have a look at
          # https://github.com/facebook/ThreatExchange/issues/697
          raise AWSSerializationFailure(
              "Deserialization error: "
              f"Expected {in_type} got {type(aws_field)} ({aws_field!r})"
          )
  
      if in_type is int:  # N
          return int(aws_field)  # type: ignore # mypy/issues/10003
      if in_type is float:  # N
          return float(aws_field)  # type: ignore # mypy/issues/10003
      if in_type is Decimal:  # N
          return aws_field  # type: ignore # mypy/issues/10003
      if in_type is str:  # S
          return aws_field  # type: ignore # mypy/issues/10003
      if in_type is bool:  # BOOL
          return aws_field  # type: ignore # mypy/issues/10003
      if in_type is t.Set[str]:  # SS
          return aws_field  # type: ignore # mypy/issues/10003
      if in_type is t.Set[int]:  # SN
          return {int(s) for s in aws_field}  # type: ignore # mypy/issues/10003
      if in_type is t.Set[float]:  # SN
          return {float(s) for s in aws_field}  # type: ignore # mypy/issues/10003
  
      if origin is set:  # L - special case
          return {aws_to_py(args[0], v) for v in aws_field}  # type: ignore # mypy/issues/10003
      if origin is list:  # L
          return [aws_to_py(args[0], v) for v in aws_field]  # type: ignore # mypy/issues/10003
      # It would be possible to add support for nested dataclasses here, which
      # just become maps with the keys as their attributes
      # Another option would be adding a new class that adds methods to convert
      # to an AWS-friendly struct and back
      if origin is dict and args[0] is str:  # M
          # check if value type of map origin is explicitly set
          return {k: aws_to_py(args[1], v) for k, v in aws_field.items()}  # type: ignore # mypy/issues/10003
      if is_dataclass(in_type):
          kwargs = {}
          for field in fields(in_type):
              if not field.init:
                  continue
              val = aws_field.get(field.name)
              if val is None:
                  continue  # Hopefully missing b/c default or version difference
              kwargs[field.name] = aws_to_py(field.type, val)
          return in_type(**kwargs)  # type: ignore  # No idea how to correctly type this
  
      raise AWSSerializationFailure(f"Missing deserialization logic for {in_type!r}")
function_tokens: def aws_to_py ( in_type : t . Type [ T ] , aws_field : t . Any ) -> T : origin = t . get_origin ( in_type ) args = t . get_args ( in_type ) check_type = origin if in_type is float : check_type = Decimal elif in_type is int : check_type = ( int , Decimal ) elif is_dataclass ( in_type ) : check_type = dict elif check_type is set and args : if args [ 0 ] not in ( str , float , int , Decimal ) : check_type = list if not isinstance ( aws_field , check_type or in_type ) : # If you are getting random deserialization errors in tests that you did # not touch, have a look at # https://github.com/facebook/ThreatExchange/issues/697 raise AWSSerializationFailure ( "Deserialization error: " f"Expected {in_type} got {type(aws_field)} ({aws_field!r})" ) if in_type is int : # N return int ( aws_field ) # type: ignore # mypy/issues/10003 if in_type is float : # N return float ( aws_field ) # type: ignore # mypy/issues/10003 if in_type is Decimal : # N return aws_field # type: ignore # mypy/issues/10003 if in_type is str : # S return aws_field # type: ignore # mypy/issues/10003 if in_type is bool : # BOOL return aws_field # type: ignore # mypy/issues/10003 if in_type is t . Set [ str ] : # SS return aws_field # type: ignore # mypy/issues/10003 if in_type is t . Set [ int ] : # SN return { int ( s ) for s in aws_field } # type: ignore # mypy/issues/10003 if in_type is t . Set [ float ] : # SN return { float ( s ) for s in aws_field } # type: ignore # mypy/issues/10003 if origin is set : # L - special case return { aws_to_py ( args [ 0 ] , v ) for v in aws_field } # type: ignore # mypy/issues/10003 if origin is list : # L return [ aws_to_py ( args [ 0 ] , v ) for v in aws_field ] # type: ignore # mypy/issues/10003 # It would be possible to add support for nested dataclasses here, which # just become maps with the keys as their attributes # Another option would be adding a new class that adds methods to convert # to an AWS-friendly struct and back if origin is dict and args [ 0 ] is str : # M # check if value type of map origin is explicitly set return { k : aws_to_py ( args [ 1 ] , v ) for k , v in aws_field . items ( ) } # type: ignore # mypy/issues/10003 if is_dataclass ( in_type ) : kwargs = { } for field in fields ( in_type ) : if not field . init : continue val = aws_field . get ( field . name ) if val is None : continue # Hopefully missing b/c default or version difference kwargs [ field . name ] = aws_to_py ( field . type , val ) return in_type ( * * kwargs ) # type: ignore  # No idea how to correctly type this raise AWSSerializationFailure ( f"Missing deserialization logic for {in_type!r}" )