99from nypl_py_utils .functions .log_helper import create_log
1010from requests .exceptions import JSONDecodeError , RequestException
1111
12+
1213class AvroClient :
1314 """
1415 Base class for Avro schema interaction. Takes as input the
1516 Platform API endpoint from which to fetch the schema in JSON format.
1617 """
17-
18+
1819 def __init__ (self , platform_schema_url ):
19- self .logger = create_log ('avro_encoder' )
20- self .schema = avro .schema .parse (
21- self .get_json_schema (platform_schema_url ))
22-
20+ self .logger = create_log ("avro_encoder" )
21+ self .schema = avro .schema .parse (self .get_json_schema (platform_schema_url ))
22+
2323 def get_json_schema (self , platform_schema_url ):
2424 """
2525 Fetches a JSON response from the input Platform API endpoint and
2626 interprets it as an Avro schema.
2727 """
28- self .logger .info ('Fetching Avro schema from {}' .format (
29- platform_schema_url ))
28+ self .logger .info ("Fetching Avro schema from {}" .format (platform_schema_url ))
3029 try :
3130 response = requests .get (platform_schema_url )
3231 response .raise_for_status ()
3332 except RequestException as e :
3433 self .logger .error (
35- 'Failed to retrieve schema from {url}: {error}' .format (
36- url = platform_schema_url , error = e ))
34+ "Failed to retrieve schema from {url}: {error}" .format (
35+ url = platform_schema_url , error = e
36+ )
37+ )
3738 raise AvroClientError (
38- 'Failed to retrieve schema from {url}: {error}' .format (
39- url = platform_schema_url , error = e )) from None
39+ "Failed to retrieve schema from {url}: {error}" .format (
40+ url = platform_schema_url , error = e
41+ )
42+ ) from None
4043
4144 try :
4245 json_response = response .json ()
43- return json_response [' data' ][ ' schema' ]
46+ return json_response [" data" ][ " schema" ]
4447 except (JSONDecodeError , KeyError ) as e :
4548 self .logger .error (
46- 'Retrieved schema is malformed: {errorType} {errorMessage}'
47- .format (errorType = type (e ), errorMessage = e ))
49+ "Retrieved schema is malformed: {errorType} {errorMessage}" .format (
50+ errorType = type (e ), errorMessage = e
51+ )
52+ )
4853 raise AvroClientError (
49- 'Retrieved schema is malformed: {errorType} {errorMessage}'
50- .format (errorType = type (e ), errorMessage = e )) from None
51-
54+ "Retrieved schema is malformed: {errorType} {errorMessage}" .format (
55+ errorType = type (e ), errorMessage = e
56+ )
57+ ) from None
58+
5259
5360class AvroEncoder (AvroClient ):
5461 """
@@ -63,18 +70,17 @@ def encode_record(self, record):
6370 Returns the encoded record as a byte string.
6471 """
6572 self .logger .debug (
66- ' Encoding record using {schema} schema' .format (
67- schema = self . schema . name ) )
73+ " Encoding record using {schema} schema" .format (schema = self . schema . name )
74+ )
6875 datum_writer = DatumWriter (self .schema )
6976 with BytesIO () as output_stream :
7077 encoder = BinaryEncoder (output_stream )
7178 try :
7279 datum_writer .write (record , encoder )
7380 return output_stream .getvalue ()
7481 except AvroException as e :
75- self .logger .error ('Failed to encode record: {}' .format (e ))
76- raise AvroClientError (
77- 'Failed to encode record: {}' .format (e )) from None
82+ self .logger .error ("Failed to encode record: {}" .format (e ))
83+ raise AvroClientError ("Failed to encode record: {}" .format (e )) from None
7884
7985 def encode_batch (self , record_list ):
8086 """
@@ -83,8 +89,10 @@ def encode_batch(self, record_list):
8389 Returns a list of byte strings where each string is an encoded record.
8490 """
8591 self .logger .info (
86- 'Encoding ({num_rec}) records using {schema} schema' .format (
87- num_rec = len (record_list ), schema = self .schema .name ))
92+ "Encoding ({num_rec}) records using {schema} schema" .format (
93+ num_rec = len (record_list ), schema = self .schema .name
94+ )
95+ )
8896 encoded_records = []
8997 datum_writer = DatumWriter (self .schema )
9098 with BytesIO () as output_stream :
@@ -96,9 +104,10 @@ def encode_batch(self, record_list):
96104 output_stream .seek (0 )
97105 output_stream .truncate (0 )
98106 except AvroException as e :
99- self .logger .error (' Failed to encode record: {}' .format (e ))
107+ self .logger .error (" Failed to encode record: {}" .format (e ))
100108 raise AvroClientError (
101- 'Failed to encode record: {}' .format (e )) from None
109+ "Failed to encode record: {}" .format (e )
110+ ) from None
102111 return encoded_records
103112
104113
@@ -110,34 +119,37 @@ class AvroDecoder(AvroClient):
110119
111120 def decode_record (self , record , encoding = "binary" ):
112121 """
113- Decodes a single record represented either as a byte or
122+ Decodes a single record represented either as a byte or
114123 base64 string, using the given Avro schema.
115124
116125 Returns a dictionary where each key is a field in the schema.
117126 """
118- self .logger .info ('Decoding {rec} of type {type} using {schema} schema' .format (
119- rec = record , type = encoding , schema = self .schema .name ))
120-
127+ self .logger .info (
128+ "Decoding {rec} of type {type} using {schema} schema" .format (
129+ rec = record , type = encoding , schema = self .schema .name
130+ )
131+ )
132+
121133 if encoding == "base64" :
122134 return self ._decode_base64 (record )
123135 elif encoding == "binary" :
124136 return self ._decode_binary (record )
125137 else :
126- self .logger .error ('Failed to decode record due to encoding type: {}' .format (encoding ))
127- raise AvroClientError (
128- 'Invalid encoding type: {}' .format (encoding ))
129-
138+ self .logger .error (
139+ "Failed to decode record due to encoding type: {}" .format (encoding )
140+ )
141+ raise AvroClientError ("Invalid encoding type: {}" .format (encoding ))
142+
130143 def _decode_base64 (self , record ):
131- decoded_data = base64 .b64decode (record ). decode ( "utf-8" )
144+ decoded_data = base64 .b64decode (record )
132145 try :
133146 return json .loads (decoded_data )
134147 except Exception as e :
135148 if isinstance (decoded_data , bytes ):
136- self ._decode_binary (decoded_data )
149+ return self ._decode_binary (decoded_data )
137150 else :
138- self .logger .error ('Failed to decode record: {}' .format (e ))
139- raise AvroClientError (
140- 'Failed to decode record: {}' .format (e )) from None
151+ self .logger .error ("Failed to decode record: {}" .format (e ))
152+ raise AvroClientError ("Failed to decode record: {}" .format (e )) from None
141153
142154 def _decode_binary (self , record ):
143155 datum_reader = DatumReader (self .schema )
@@ -146,11 +158,10 @@ def _decode_binary(self, record):
146158 try :
147159 return datum_reader .read (decoder )
148160 except Exception as e :
149- self .logger .error ('Failed to decode record: {}' .format (e ))
150- raise AvroClientError (
151- 'Failed to decode record: {}' .format (e )) from None
161+ self .logger .error ("Failed to decode record: {}" .format (e ))
162+ raise AvroClientError ("Failed to decode record: {}" .format (e )) from None
152163
153164
154165class AvroClientError (Exception ):
155166 def __init__ (self , message = None ):
156- self .message = message
167+ self .message = message
0 commit comments