99from mindee .input .sources import LocalInputSource , UrlInputSource
1010from mindee .parsing .common .async_predict_response import AsyncPredictResponse
1111from mindee .parsing .common .document import Document , serialize_for_json
12+ from mindee .parsing .common .feedback_response import FeedbackResponse
1213from mindee .parsing .common .inference import Inference , TypeInference
1314from mindee .parsing .common .predict_response import PredictResponse
15+ from mindee .parsing .common .string_dict import StringDict
1416
1517
1618@dataclass
@@ -142,43 +144,59 @@ class MindeeParser:
142144 input_doc : Union [LocalInputSource , UrlInputSource ]
143145 """Document to be parsed."""
144146 product_class : Type [Inference ]
145- """Product to parse"""
147+ """Product to parse."""
148+ feedback : Optional [StringDict ]
149+ """Dict representation of a feedback."""
146150
147151 def __init__ (
148152 self ,
149153 parser : Optional [ArgumentParser ] = None ,
150154 parsed_args : Optional [Namespace ] = None ,
151155 client : Optional [Client ] = None ,
152- input_doc : Optional [Union [LocalInputSource , UrlInputSource ]] = None ,
153156 document_info : Optional [CommandConfig ] = None ,
154157 ) -> None :
155158 self .parser = parser if parser else ArgumentParser (description = "Mindee_API" )
156159 self .parsed_args = parsed_args if parsed_args else self ._set_args ()
157- self .client = client if client else Client (api_key = self .parsed_args .api_key )
158- # if self.parsed_args.parse_type == "parse":
159- self .input_doc = input_doc if input_doc else self ._get_input_doc ()
160+ self .client = (
161+ client
162+ if client
163+ else Client (
164+ api_key = self .parsed_args .api_key
165+ if "api_key" in self .parsed_args
166+ else None
167+ )
168+ )
169+ self ._set_input ()
160170 self .document_info = (
161171 document_info if document_info else DOCUMENTS [self .parsed_args .product_name ]
162172 )
163173
164174 def call_endpoint (self ) -> None :
165175 """Calls the proper type of endpoint according to given command."""
166- # if self.parsed_args.parse_type == "parse":
167- self .call_parse ()
168-
169- # else:
170- # self.call_fetch()
171-
172- # def call_fetch(self) -> None:
173- # """Fetches an API's for a previously enqueued document."""
174- # response: AsyncPredictResponse = self._parse_queued()
175- # if self.parsed_args.output_type == "raw":
176- # print(response.raw_http)
177- # else:
178- # if not hasattr(response, "document") or response.document is None:
179- # print(response.job)
180- # else:
181- # print(response.document)
176+ if self .parsed_args .parse_type == "parse" :
177+ self .call_parse ()
178+ else :
179+ self .call_feedback ()
180+
181+ def call_feedback (self ) -> None :
182+ """Sends feedback to an API."""
183+ custom_endpoint : Optional [Endpoint ] = None
184+ if self .parsed_args .product_name == "custom" :
185+ custom_endpoint = self .client .create_endpoint (
186+ self .parsed_args .endpoint_name ,
187+ self .parsed_args .account_name ,
188+ self .parsed_args .api_version ,
189+ )
190+ if self .feedback is None :
191+ raise RuntimeError ("Invalid feedback provided." )
192+
193+ response : FeedbackResponse = self .client .send_feedback (
194+ self .document_info .doc_class ,
195+ self .parsed_args .document_id ,
196+ {"feedback" : self .feedback },
197+ custom_endpoint ,
198+ )
199+ print (json .dumps (response .feedback , indent = 2 ))
182200
183201 def call_parse (self ) -> None :
184202 """Calls an endpoint with the appropriate method, and displays the results."""
@@ -251,51 +269,27 @@ def _parse_async(self) -> AsyncPredictResponse:
251269 endpoint = custom_endpoint ,
252270 )
253271
254- # def _parse_queued(self) -> AsyncPredictResponse:
255- # """Fetches a queue's result from a document's id."""
256- # custom_endpoint: Optional[Endpoint] = None
257- # if self.parsed_args.product_name == "custom":
258- # self.client.create_endpoint(
259- # self.parsed_args.endpoint_name,
260- # self.parsed_args.account_name,
261- # self.parsed_args.api_version,
262- # )
263- # return self.client.parse_queued(
264- # self.document_info.doc_class,
265- # self.parsed_args.queue_id,
266- # custom_endpoint,
267- # )
268-
269272 def _doc_str (self , output_type : str , doc_response : Document ) -> str :
270273 if output_type == "parsed" :
271274 return json .dumps (doc_response , indent = 2 , default = serialize_for_json )
272275 return str (doc_response )
273276
274277 def _set_args (self ) -> Namespace :
275278 """Parse command line arguments."""
276- # call_parser = self.parser.add_subparsers(
277- # dest="parse_type",
278- # required=True,
279- # )
280- # parse_subparser = call_parser.add_parser("parse")
281- # fetch_subparser = call_parser.add_parser("fetch")
282-
283- # parse_product_subparsers = parse_subparser.add_subparsers(
284- # dest="product_name",
285- # required=True,
286- # )
287279 parse_product_subparsers = self .parser .add_subparsers (
288280 dest = "product_name" ,
289281 required = True ,
290282 )
291283
292- # fetch_product_subparsers = fetch_subparser.add_subparsers(
293- # dest="product_name",
294- # required=True,
295- # )
296-
297284 for name , info in DOCUMENTS .items ():
298- parse_subp = parse_product_subparsers .add_parser (name , help = info .help )
285+ parse_subparser = parse_product_subparsers .add_parser (name , help = info .help )
286+
287+ call_parser = parse_subparser .add_subparsers (
288+ dest = "parse_type" , required = True
289+ )
290+ parse_subp = call_parser .add_parser ("parse" )
291+ feedback_subp = call_parser .add_parser ("feedback" )
292+
299293 self ._add_main_options (parse_subp )
300294 self ._add_sending_options (parse_subp )
301295 self ._add_display_options (parse_subp )
@@ -321,16 +315,18 @@ def _set_args(self) -> Namespace:
321315 default = False ,
322316 )
323317
324- # if info.is_async:
325- # fetch_subp = fetch_product_subparsers.add_parser(name, help=info.help)
326- # self._add_main_options(fetch_subp)
327- # self._add_display_options(fetch_subp)
328- # self._add_fetch_options(fetch_subp)
318+ self ._add_main_options (feedback_subp )
319+ self ._add_feedback_options (feedback_subp )
329320
330321 parsed_args = self .parser .parse_args ()
331322 return parsed_args
332323
333324 def _add_main_options (self , parser : ArgumentParser ) -> None :
325+ """
326+ Adds main options for most parsings.
327+
328+ :param parser: current parser.
329+ """
334330 parser .add_argument (
335331 "-k" ,
336332 "--key" ,
@@ -341,7 +337,11 @@ def _add_main_options(self, parser: ArgumentParser) -> None:
341337 )
342338
343339 def _add_display_options (self , parser : ArgumentParser ) -> None :
344- """Adds options related to output/display of a document (parse, parse-queued)."""
340+ """
341+ Adds options related to output/display of a document (parse, parse-queued).
342+
343+ :param parser: current parser.
344+ """
345345 parser .add_argument (
346346 "-o" ,
347347 "--output-type" ,
@@ -355,7 +355,11 @@ def _add_display_options(self, parser: ArgumentParser) -> None:
355355 )
356356
357357 def _add_sending_options (self , parser : ArgumentParser ) -> None :
358- """Adds options for sending requests (parse, enqueue)."""
358+ """
359+ Adds options for sending requests (parse, enqueue).
360+
361+ :param parser: current parser.
362+ """
359363 parser .add_argument (
360364 "-i" ,
361365 "--input-type" ,
@@ -386,15 +390,29 @@ def _add_sending_options(self, parser: ArgumentParser) -> None:
386390 )
387391 parser .add_argument (dest = "path" , help = "Full path to the file" )
388392
389- # def _add_fetch_options(self, parser: ArgumentParser):
390- # """Adds an option to provide the queue ID for an async document."""
391- # parser.add_argument(
392- # dest="queue_id",
393- # help="Async queue ID for a document (required)",
394- # )
393+ def _add_feedback_options (self , parser : ArgumentParser ):
394+ """
395+ Adds the option to give feedback manually.
396+
397+ :param parser: current parser.
398+ """
399+ parser .add_argument (
400+ dest = "document_id" ,
401+ help = "Mindee UUID of the document." ,
402+ type = str ,
403+ )
404+ parser .add_argument (
405+ dest = "feedback" ,
406+ type = json .loads ,
407+ help = 'Feedback JSON string to send, ex \' {"key": "value"}\' .' ,
408+ )
395409
396410 def _add_custom_options (self , parser : ArgumentParser ):
397- """Adds options to custom-type documents."""
411+ """
412+ Adds options to custom-type documents.
413+
414+ :param parser: current parser.
415+ """
398416 parser .add_argument (
399417 "-a" ,
400418 "--account" ,
@@ -418,6 +436,7 @@ def _add_custom_options(self, parser: ArgumentParser):
418436 )
419437
420438 def _get_input_doc (self ) -> Union [LocalInputSource , UrlInputSource ]:
439+ """Loads an input document."""
421440 if self .parsed_args .input_type == "file" :
422441 with open (self .parsed_args .path , "rb" , buffering = 30 ) as file_handle :
423442 return self .client .source_from_file (file_handle )
@@ -435,6 +454,39 @@ def _get_input_doc(self) -> Union[LocalInputSource, UrlInputSource]:
435454 return self .client .source_from_url (self .parsed_args .path )
436455 return self .client .source_from_path (self .parsed_args .path )
437456
457+ def _get_feedback_doc (self ) -> StringDict :
458+ """Loads a feedback."""
459+ json_doc : StringDict = {}
460+ if self .parsed_args .input_type == "file" :
461+ with open (self .parsed_args .path , "rb" , buffering = 30 ) as f_f :
462+ json_doc = json .loads (f_f .read ())
463+ elif self .parsed_args .input_type == "base64" :
464+ with open (self .parsed_args .path , "rt" , encoding = "ascii" ) as f_b64 :
465+ json_doc = json .loads (f_b64 .read ())
466+ elif self .parsed_args .input_type == "bytes" :
467+ with open (self .parsed_args .path , "rb" ) as f_b :
468+ json_doc = json .loads (f_b .read ())
469+ else :
470+ if (
471+ not self .parsed_args .feedback
472+ or not "feedback" in self .parsed_args .feedback
473+ ):
474+ raise RuntimeError ("Invalid feedback." )
475+ if not json_doc or "feedback" not in json_doc :
476+ raise RuntimeError ("Invalid feedback." )
477+ return json_doc
478+
479+ def _set_input (self ) -> None :
480+ """Loads an input document, or a feedback document."""
481+ self .feedback = None
482+ if self .parsed_args .parse_type == "feedback" :
483+ if not self .parsed_args .feedback :
484+ self .feedback = self ._get_feedback_doc ()
485+ else :
486+ self .feedback = self .parsed_args .feedback
487+ else :
488+ self .input_doc = self ._get_input_doc ()
489+
438490
439491def main () -> None :
440492 """Run the Command Line Interface."""
0 commit comments