microsoft / jupyter-Kqlmagic

Extension (Magic) to Jupyter notebook and Jupyter lab, that enable notebook experience working with Kusto, ApplicationInsights, and LogAnalytics data.
Other
85 stars 31 forks source link

Exception: "format() argument 2 must be str, not int" #72

Closed liorbp closed 2 years ago

liorbp commented 3 years ago

Root cause: Kqlmagic fails to parse timespan columns with milliseconds due to typo in string formatting of ticks variable in _timedelta_totimespan() inside _myutils.py

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-b1a86ae756c8> in <module>
----> 1 get_ipython().run_cell_magic('kql', '', "cluster('****').database('****').****\n| take 1\n")

/opt/conda/lib/python3.8/site-packages/IPython/core/interactiveshell.py in run_cell_magic(self, magic_name, line, cell)
   2389             with self.builtin_trap:
   2390                 args = (magic_arg_s, cell)
-> 2391                 result = fn(*args, **kwargs)
   2392             return result
   2393 

<decorator-gen-118> in execute(self, line, cell, local_ns, override_vars, override_options, override_query_properties, override_connection, override_result_set)

/opt/conda/lib/python3.8/site-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
    185     # but it's overkill for just that one bit of state.
    186     def magic_deco(arg):
--> 187         call = lambda f, *a, **k: f(*a, **k)
    188 
    189         if callable(arg):

<decorator-gen-117> in execute(self, line, cell, local_ns, override_vars, override_options, override_query_properties, override_connection, override_result_set)

/opt/conda/lib/python3.8/site-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
    185     # but it's overkill for just that one bit of state.
    186     def magic_deco(arg):
--> 187         call = lambda f, *a, **k: f(*a, **k)
    188 
    189         if callable(arg):

/opt/conda/lib/python3.8/site-packages/Kqlmagic/kql_magic.py in execute(self, line, cell, local_ns, override_vars, override_options, override_query_properties, override_connection, override_result_set)
    663         #
    664 
--> 665         result = kql_core_obj.execute(
    666             line=line,
    667             cell=cell,

/opt/conda/lib/python3.8/site-packages/Kqlmagic/kql_magic_core.py in execute(self, line, cell, local_ns, override_vars, override_options, override_query_properties, override_connection, override_result_set)
    683                         # can't just return result as is, it fails when used with table package pandas_show_schema
    684                         # it will first show the result, and will suppres show by result._repr_html
--> 685                         result.show_result(suppress_next_repr_html_=True)
    686                 else:
    687                     param = parsed["command"].get("param")

/opt/conda/lib/python3.8/site-packages/Kqlmagic/results.py in show_result(self, suppress_next_repr_html_)
    498                 self.show_chart(**self.options, display_handler_name='table_or_chart')
    499             else:
--> 500                 self.show_table(**self.options, display_handler_name='table_or_chart')
    501 
    502             Display.showInfoMessage(feedback_info, display_handler_name='feedback_info', **self.options)

/opt/conda/lib/python3.8/site-packages/Kqlmagic/results.py in show_table(self, display_handler_name, **kwargs)
    585         pandas_display_html_table_schema = None
    586         pandas__repr_data_resource_patched = False
--> 587         if not options.get("popup_window") and len(self) == 1 and len(self[0]) == 1  and (isinstance(self[0][0], dict) or isinstance(self[0][0], list)):
    588             content = Display.to_json_styled_class(self[0][0], options=options)
    589         else:

/opt/conda/lib/python3.8/site-packages/Kqlmagic/results.py in __getitem__(self, key)
    732                 return item
    733 
--> 734         return Display.to_json_styled_class(item, options=self.options)
    735 
    736 

/opt/conda/lib/python3.8/site-packages/Kqlmagic/display.py in to_json_styled_class(item, style, options)
    346         if json_display_style != "raw" and (isinstance(item, list) or isinstance(item, dict) or type(item).__name__ == "KqlRow"):
    347             if json_display_style == "formatted":
--> 348                 return _getitem_FormattedJson(item)
    349             else:
    350                 return _getitem_JSON(item)

/opt/conda/lib/python3.8/site-packages/Kqlmagic/display.py in _getitem_FormattedJson(item, key)
     89         return FormattedJsonList(item, key)
     90     elif isinstance(item, dict) or type(item).__name__ == "KqlRow":
---> 91         return FormattedJsonDict(item)
     92     else:
     93         return item

/opt/conda/lib/python3.8/site-packages/Kqlmagic/display.py in __init__(self, item, *args, **kwargs)
     39         if len(item) == 1 and isinstance(self.get(" "), list):
     40             _dict = self.get(" ")
---> 41         formatted_json = json_dumps(_dict, indent=4, sort_keys=True)
     42         self.colorful_json = highlight(formatted_json.encode("UTF-8"), JsonLexer(), TerminalFormatter())
     43 

/opt/conda/lib/python3.8/site-packages/Kqlmagic/my_utils.py in json_dumps(_dict, **kwargs)
    173 
    174 def json_dumps(_dict:dict, **kwargs)->str:
--> 175     return json.dumps(_dict, default=json_defaults, **kwargs)
    176 
    177 

/opt/conda/lib/python3.8/json/__init__.py in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    232     if cls is None:
    233         cls = JSONEncoder
--> 234     return cls(
    235         skipkeys=skipkeys, ensure_ascii=ensure_ascii,
    236         check_circular=check_circular, allow_nan=allow_nan, indent=indent,

/opt/conda/lib/python3.8/json/encoder.py in encode(self, o)
    199         chunks = self.iterencode(o, _one_shot=True)
    200         if not isinstance(chunks, (list, tuple)):
--> 201             chunks = list(chunks)
    202         return ''.join(chunks)
    203 

/opt/conda/lib/python3.8/json/encoder.py in _iterencode(o, _current_indent_level)
    429             yield from _iterencode_list(o, _current_indent_level)
    430         elif isinstance(o, dict):
--> 431             yield from _iterencode_dict(o, _current_indent_level)
    432         else:
    433             if markers is not None:

/opt/conda/lib/python3.8/json/encoder.py in _iterencode_dict(dct, _current_indent_level)
    403                 else:
    404                     chunks = _iterencode(value, _current_indent_level)
--> 405                 yield from chunks
    406         if newline_indent is not None:
    407             _current_indent_level -= 1

/opt/conda/lib/python3.8/json/encoder.py in _iterencode(o, _current_indent_level)
    436                     raise ValueError("Circular reference detected")
    437                 markers[markerid] = o
--> 438             o = _default(o)
    439             yield from _iterencode(o, _current_indent_level)
    440             if markers is not None:

/opt/conda/lib/python3.8/site-packages/Kqlmagic/my_utils.py in json_defaults(obj)
    162         return obj.isoformat()
    163     elif isinstance(obj, datetime.timedelta):
--> 164         return timedelta_to_timespan(obj, minimal=True)
    165         # return isodate.duration_isoformat(obj)
    166         # return (datetime.datetime.min + obj).time().isoformat()

/opt/conda/lib/python3.8/site-packages/Kqlmagic/my_utils.py in timedelta_to_timespan(_timedelta, minimal)
    196             result = "{0:01}.{1}".format(int(days), result)
    197         if ticks > 0:
--> 198             result = "{0}.{1:07}",format(result, int(ticks))
    199     else:
    200         result = "{0:01}.{1:02}:{2:02}:{3:02}.{4:07}".format(int(days), int(hours), int(minutes), int(seconds), int(ticks))

TypeError: format() argument 2 must be str, not int
mbnshtck commented 3 years ago

Thanks for the catch. Will be fixed it in next version. comming soon.

mbnshtck commented 2 years ago

Done in version 0.1.114