From eca6724d8fe2d25dafec8fb49a1c2dbc64ff15a8 Mon Sep 17 00:00:00 2001 From: Shantanu Verma Date: Tue, 13 Apr 2021 15:38:37 +0530 Subject: [PATCH 001/135] feat: add language labelling notebook so far --- notebooks/language_labelling.ipynb | 1988 ++++++++++++++++++++++++++++ 1 file changed, 1988 insertions(+) create mode 100644 notebooks/language_labelling.ipynb diff --git a/notebooks/language_labelling.ipynb b/notebooks/language_labelling.ipynb new file mode 100644 index 000000000..d1925bcbc --- /dev/null +++ b/notebooks/language_labelling.ipynb @@ -0,0 +1,1988 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Copy of HowDoI-NLP.ipynb", + "provenance": [], + "collapsed_sections": [], + "toc_visible": true + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "b9f3692aa5394af38fbf8701f9d1a2f5": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_20cc5addfd6a404abd07e3e7410604bf", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_193cdcb227f4436ab295a1d03c935bc7", + "IPY_MODEL_e3736ea8f8f1433fa58a2c7cefbc9d43" + ] + } + }, + "20cc5addfd6a404abd07e3e7410604bf": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "193cdcb227f4436ab295a1d03c935bc7": { + "model_module": "@jupyter-widgets/controls", + "model_name": "FloatProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_0214896e38b7475b9810990cd98bcfbe", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "FloatProgressModel", + "bar_style": "success", + "max": 231508, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 231508, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_9d6b675edcf94469a3665d8ebd699cd6" + } + }, + "e3736ea8f8f1433fa58a2c7cefbc9d43": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_2a6a7cec7ce9445a854b6378fe5c7d69", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 232k/232k [00:00<00:00, 885kB/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_af203886f4db407f92d990d4d421c207" + } + }, + "0214896e38b7475b9810990cd98bcfbe": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "9d6b675edcf94469a3665d8ebd699cd6": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "2a6a7cec7ce9445a854b6378fe5c7d69": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "af203886f4db407f92d990d4d421c207": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "89764229f6bb4419927cd6499b252cc1": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_489bcf4ae407408fa0b4f18193277f3d", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_c907be1df1ef42cda9d7a45ce3ae50ff", + "IPY_MODEL_1f0711de1dde4e12b0ff8f7f11f38e5d" + ] + } + }, + "489bcf4ae407408fa0b4f18193277f3d": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "c907be1df1ef42cda9d7a45ce3ae50ff": { + "model_module": "@jupyter-widgets/controls", + "model_name": "FloatProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_420b462bf1dc498082e1c341e9649e34", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "FloatProgressModel", + "bar_style": "success", + "max": 466062, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 466062, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_e47fef1e664a4a608cd595eb476b84d0" + } + }, + "1f0711de1dde4e12b0ff8f7f11f38e5d": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_fc1006302b0741b18c5719d6b46b508b", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 466k/466k [00:00<00:00, 1.41MB/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_20700e5b87dd4845b9d451a4e3a81794" + } + }, + "420b462bf1dc498082e1c341e9649e34": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "e47fef1e664a4a608cd595eb476b84d0": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "fc1006302b0741b18c5719d6b46b508b": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "20700e5b87dd4845b9d451a4e3a81794": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "723f45572f9845f7a5a43d028acabd37": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_fd385e56155444c6ba0b70f461b014ef", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_d032b636ac73444ea8e13ec9ee1866d8", + "IPY_MODEL_f6501a7bc274434eae206e1e1fb2e00a" + ] + } + }, + "fd385e56155444c6ba0b70f461b014ef": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "d032b636ac73444ea8e13ec9ee1866d8": { + "model_module": "@jupyter-widgets/controls", + "model_name": "FloatProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_7b3318ea2d8e49e186f47c5792cbe30b", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "FloatProgressModel", + "bar_style": "success", + "max": 28, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 28, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_e9a8d590fca842859822b4cad55b1a5f" + } + }, + "f6501a7bc274434eae206e1e1fb2e00a": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_f9924cd4fc98461c82148ac3a38a845d", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 28.0/28.0 [00:00<00:00, 673B/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_fd9e3dfc77e243ecb7f6257b6700e728" + } + }, + "7b3318ea2d8e49e186f47c5792cbe30b": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "e9a8d590fca842859822b4cad55b1a5f": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "f9924cd4fc98461c82148ac3a38a845d": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "fd9e3dfc77e243ecb7f6257b6700e728": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "7a54279586bb4c87a52746f605f7b3e2": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_6a7acabfc3f24d3395c0cc7cde68a43a", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_b9c6899ed3dd489d85b201b51a6f35c3", + "IPY_MODEL_b413ba22912c4149aeea6824ccbc90c1" + ] + } + }, + "6a7acabfc3f24d3395c0cc7cde68a43a": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "b9c6899ed3dd489d85b201b51a6f35c3": { + "model_module": "@jupyter-widgets/controls", + "model_name": "FloatProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_6151969c55174665964db6f97bd18884", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "FloatProgressModel", + "bar_style": "success", + "max": 442, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 442, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_f97dbff45ea347f380b3d3e2bf9b60a5" + } + }, + "b413ba22912c4149aeea6824ccbc90c1": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_6bc47beb071c4884a4ddb8a7dd669222", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 442/442 [00:00<00:00, 12.0kB/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_6acde23812d44176829ce106ea626f09" + } + }, + "6151969c55174665964db6f97bd18884": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "f97dbff45ea347f380b3d3e2bf9b60a5": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "6bc47beb071c4884a4ddb8a7dd669222": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "6acde23812d44176829ce106ea626f09": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "6e48979f9d49495da15e278aafd97a8b": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HBoxModel", + "state": { + "_view_name": "HBoxView", + "_dom_classes": [], + "_model_name": "HBoxModel", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.5.0", + "box_style": "", + "layout": "IPY_MODEL_73a609c59da744088c8def134a0acebc", + "_model_module": "@jupyter-widgets/controls", + "children": [ + "IPY_MODEL_3e978968f8814d4e9cb0cce52fe25f53", + "IPY_MODEL_5b91aa38af194763b33168e24eb80b91" + ] + } + }, + "73a609c59da744088c8def134a0acebc": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "3e978968f8814d4e9cb0cce52fe25f53": { + "model_module": "@jupyter-widgets/controls", + "model_name": "FloatProgressModel", + "state": { + "_view_name": "ProgressView", + "style": "IPY_MODEL_27cc2164a06a40a0b6e093bd1f642fce", + "_dom_classes": [], + "description": "Downloading: 100%", + "_model_name": "FloatProgressModel", + "bar_style": "success", + "max": 267967963, + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": 267967963, + "_view_count": null, + "_view_module_version": "1.5.0", + "orientation": "horizontal", + "min": 0, + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_1b013fd1c8ce45c992ed4dba0bcf2393" + } + }, + "5b91aa38af194763b33168e24eb80b91": { + "model_module": "@jupyter-widgets/controls", + "model_name": "HTMLModel", + "state": { + "_view_name": "HTMLView", + "style": "IPY_MODEL_daedb950ac444ef3aa764b29f3e84052", + "_dom_classes": [], + "description": "", + "_model_name": "HTMLModel", + "placeholder": "​", + "_view_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "value": " 268M/268M [00:05<00:00, 50.3MB/s]", + "_view_count": null, + "_view_module_version": "1.5.0", + "description_tooltip": null, + "_model_module": "@jupyter-widgets/controls", + "layout": "IPY_MODEL_579a1b0eff7b425a9f22a18506fb7033" + } + }, + "27cc2164a06a40a0b6e093bd1f642fce": { + "model_module": "@jupyter-widgets/controls", + "model_name": "ProgressStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "ProgressStyleModel", + "description_width": "initial", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "bar_color": null, + "_model_module": "@jupyter-widgets/controls" + } + }, + "1b013fd1c8ce45c992ed4dba0bcf2393": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + }, + "daedb950ac444ef3aa764b29f3e84052": { + "model_module": "@jupyter-widgets/controls", + "model_name": "DescriptionStyleModel", + "state": { + "_view_name": "StyleView", + "_model_name": "DescriptionStyleModel", + "description_width": "", + "_view_module": "@jupyter-widgets/base", + "_model_module_version": "1.5.0", + "_view_count": null, + "_view_module_version": "1.2.0", + "_model_module": "@jupyter-widgets/controls" + } + }, + "579a1b0eff7b425a9f22a18506fb7033": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "state": { + "_view_name": "LayoutView", + "grid_template_rows": null, + "right": null, + "justify_content": null, + "_view_module": "@jupyter-widgets/base", + "overflow": null, + "_model_module_version": "1.2.0", + "_view_count": null, + "flex_flow": null, + "width": null, + "min_width": null, + "border": null, + "align_items": null, + "bottom": null, + "_model_module": "@jupyter-widgets/base", + "top": null, + "grid_column": null, + "overflow_y": null, + "overflow_x": null, + "grid_auto_flow": null, + "grid_area": null, + "grid_template_columns": null, + "flex": null, + "_model_name": "LayoutModel", + "justify_items": null, + "grid_row": null, + "max_height": null, + "align_content": null, + "visibility": null, + "align_self": null, + "height": null, + "min_height": null, + "padding": null, + "grid_auto_rows": null, + "grid_gap": null, + "max_width": null, + "order": null, + "_view_module_version": "1.2.0", + "grid_template_areas": null, + "object_position": null, + "object_fit": null, + "grid_auto_columns": null, + "margin": null, + "display": null, + "left": null + } + } + } + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "co5T4uL_pXfO" + }, + "source": [ + "## Fetch data from disk" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Pjc-a5jWpdzy", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "192951ce-5610-4f4b-b7eb-ef9fb6c9ece7" + }, + "source": [ + "from google.colab import drive\n", + "drive.mount('/content/drive')" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Mounted at /content/drive\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "VfZhymMbzuSg", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "41cf4baf-003f-4b50-9e65-5be0abce2a5c" + }, + "source": [ + "!pip install transformers" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Collecting transformers\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/81/91/61d69d58a1af1bd81d9ca9d62c90a6de3ab80d77f27c5df65d9a2c1f5626/transformers-4.5.0-py3-none-any.whl (2.1MB)\n", + "\u001b[K |████████████████████████████████| 2.2MB 9.4MB/s \n", + "\u001b[?25hRequirement already satisfied: tqdm>=4.27 in /usr/local/lib/python3.7/dist-packages (from transformers) (4.41.1)\n", + "Collecting sacremoses\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/08/cd/342e584ee544d044fb573ae697404ce22ede086c9e87ce5960772084cad0/sacremoses-0.0.44.tar.gz (862kB)\n", + "\u001b[K |████████████████████████████████| 870kB 41.6MB/s \n", + "\u001b[?25hCollecting tokenizers<0.11,>=0.10.1\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/ae/04/5b870f26a858552025a62f1649c20d29d2672c02ff3c3fb4c688ca46467a/tokenizers-0.10.2-cp37-cp37m-manylinux2010_x86_64.whl (3.3MB)\n", + "\u001b[K |████████████████████████████████| 3.3MB 42.0MB/s \n", + "\u001b[?25hRequirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.7/dist-packages (from transformers) (2019.12.20)\n", + "Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from transformers) (2.23.0)\n", + "Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from transformers) (20.9)\n", + "Requirement already satisfied: importlib-metadata; python_version < \"3.8\" in /usr/local/lib/python3.7/dist-packages (from transformers) (3.8.1)\n", + "Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.7/dist-packages (from transformers) (1.19.5)\n", + "Requirement already satisfied: filelock in /usr/local/lib/python3.7/dist-packages (from transformers) (3.0.12)\n", + "Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers) (1.15.0)\n", + "Requirement already satisfied: click in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers) (7.1.2)\n", + "Requirement already satisfied: joblib in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers) (1.0.1)\n", + "Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (2.10)\n", + "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (1.24.3)\n", + "Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (3.0.4)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests->transformers) (2020.12.5)\n", + "Requirement already satisfied: pyparsing>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->transformers) (2.4.7)\n", + "Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata; python_version < \"3.8\"->transformers) (3.4.1)\n", + "Requirement already satisfied: typing-extensions>=3.6.4; python_version < \"3.8\" in /usr/local/lib/python3.7/dist-packages (from importlib-metadata; python_version < \"3.8\"->transformers) (3.7.4.3)\n", + "Building wheels for collected packages: sacremoses\n", + " Building wheel for sacremoses (setup.py) ... \u001b[?25l\u001b[?25hdone\n", + " Created wheel for sacremoses: filename=sacremoses-0.0.44-cp37-none-any.whl size=886084 sha256=8188b4a1fe7b93d2ceab6b8c4c244e549efa60bdfd85aed0aa3020e99990acc0\n", + " Stored in directory: /root/.cache/pip/wheels/3e/fb/c0/13ab4d63d537658f448366744654323077c4d90069b6512f3c\n", + "Successfully built sacremoses\n", + "Installing collected packages: sacremoses, tokenizers, transformers\n", + "Successfully installed sacremoses-0.0.44 tokenizers-0.10.2 transformers-4.5.0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lLppqXoRSjeO" + }, + "source": [ + "## Data Prep" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "VbcL94ugTLQ7" + }, + "source": [ + "import pandas as pd\n", + "from torch.utils.data import Dataset, IterableDataset, DataLoader, get_worker_info\n", + "from transformers import DistilBertTokenizerFast\n", + "import math" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 210, + "referenced_widgets": [ + "b9f3692aa5394af38fbf8701f9d1a2f5", + "20cc5addfd6a404abd07e3e7410604bf", + "193cdcb227f4436ab295a1d03c935bc7", + "e3736ea8f8f1433fa58a2c7cefbc9d43", + "0214896e38b7475b9810990cd98bcfbe", + "9d6b675edcf94469a3665d8ebd699cd6", + "2a6a7cec7ce9445a854b6378fe5c7d69", + "af203886f4db407f92d990d4d421c207", + "89764229f6bb4419927cd6499b252cc1", + "489bcf4ae407408fa0b4f18193277f3d", + "c907be1df1ef42cda9d7a45ce3ae50ff", + "1f0711de1dde4e12b0ff8f7f11f38e5d", + "420b462bf1dc498082e1c341e9649e34", + "e47fef1e664a4a608cd595eb476b84d0", + "fc1006302b0741b18c5719d6b46b508b", + "20700e5b87dd4845b9d451a4e3a81794", + "723f45572f9845f7a5a43d028acabd37", + "fd385e56155444c6ba0b70f461b014ef", + "d032b636ac73444ea8e13ec9ee1866d8", + "f6501a7bc274434eae206e1e1fb2e00a", + "7b3318ea2d8e49e186f47c5792cbe30b", + "e9a8d590fca842859822b4cad55b1a5f", + "f9924cd4fc98461c82148ac3a38a845d", + "fd9e3dfc77e243ecb7f6257b6700e728" + ] + }, + "id": "nplakpGpWubB", + "outputId": "e3a3a5eb-d8d7-48e3-d50b-55ae1c801a33" + }, + "source": [ + "ALL_LANGS = [\"A# .NET\",\"A# (Axiom)\",\"A-0 System\",\"A+\",\"A++\",\"ABAP\",\"ABC\",\"ABC ALGOL\",\"ABLE\",\"ABSET\",\"ABSYS\",\"ACC\",\"Accent\",\"Ace DASL\",\"ACL2\",\"ACT-III\",\"Action!\",\"ActionScript\",\"Ada\",\"Adenine\",\"Agda\",\"Agilent VEE\",\"Agora\",\"AIMMS\",\"Alef\",\"ALF\",\"ALGOL 58\",\"ALGOL 60\",\"ALGOL 68\",\"ALGOL W\",\"Alice\",\"Alma-0\",\"AmbientTalk\",\"Amiga E\",\"AMOS\",\"AMPL\",\"APL\",\"App Inventor for Android's visual block language\",\"AppleScript\",\"Arc\",\"ARexx\",\"Argus\",\"AspectJ\",\"Assembly language\",\"ATS\",\"Ateji PX\",\"AutoHotkey\",\"Autocoder\",\"AutoIt\",\"AutoLISP / Visual LISP\",\"Averest\",\"AWK\",\"Axum\",\"B\",\"Babbage\",\"Bash\",\"BASIC\",\"bc\",\"BCPL\",\"BeanShell\",\"Batch (Windows/Dos)\",\"Bertrand\",\"BETA\",\"Bigwig\",\"Bistro\",\"BitC\",\"BLISS\",\"Blue\",\"Bon\",\"Boo\",\"Boomerang\",\"Bourne shell\",\"bash\",\"ksh\",\"BREW\",\"BPEL\",\"C\",\"C--\",\"C++\",\"C#\",\"C/AL\",\"Caché ObjectScript\",\"C Shell\",\"Caml\",\"Candle\",\"Cayenne\",\"CDuce\",\"Cecil\",\"Cel\",\"Cesil\",\"Ceylon\",\"CFEngine\",\"CFML\",\"Cg\",\"Ch\",\"Chapel\",\"CHAIN\",\"Charity\",\"Charm\",\"Chef\",\"CHILL\",\"CHIP-8\",\"chomski\",\"ChucK\",\"CICS\",\"Cilk\",\"CL\",\"Claire\",\"Clarion\",\"Clean\",\"Clipper\",\"CLIST\",\"Clojure\",\"CLU\",\"CMS-2\",\"COBOL\",\"Cobra\",\"CODE\",\"CoffeeScript\",\"Cola\",\"ColdC\",\"ColdFusion\",\"COMAL\",\"Combined Programming Language\",\"COMIT\",\"Common Intermediate Language\",\"Common Lisp\",\"COMPASS\",\"Component Pascal\",\"Constraint Handling Rules\",\"Converge\",\"Cool\",\"Coq\",\"Coral 66\",\"Corn\",\"CorVision\",\"COWSEL\",\"CPL\",\"csh\",\"CSP\",\"Csound\",\"CUDA\",\"Curl\",\"Curry\",\"Cyclone\",\"Cython\",\"D\",\"DASL\",\"DASL\",\"Dart\",\"DataFlex\",\"Datalog\",\"DATATRIEVE\",\"dBase\",\"dc\",\"DCL\",\"Deesel\",\"Delphi\",\"DinkC\",\"DIBOL\",\"Dog\",\"Draco\",\"DRAKON\",\"Dylan\",\"DYNAMO\",\"E\",\"E#\",\"Ease\",\"Easy PL/I\",\"Easy Programming Language\",\"EASYTRIEVE PLUS\",\"ECMAScript\",\"Edinburgh IMP\",\"EGL\",\"Eiffel\",\"ELAN\",\"Elixir\",\"Elm\",\"Emacs Lisp\",\"Emerald\",\"Epigram\",\"EPL\",\"Erlang\",\"es\",\"Escapade\",\"Escher\",\"ESPOL\",\"Esterel\",\"Etoys\",\"Euclid\",\"Euler\",\"Euphoria\",\"EusLisp Robot Programming Language\",\"CMS EXEC\",\"EXEC 2\",\"Executable UML\",\"F\",\"F#\",\"Factor\",\"Falcon\",\"Fancy\",\"Fantom\",\"FAUST\",\"Felix\",\"Ferite\",\"FFP\",\"Fjölnir\",\"FL\",\"Flavors\",\"Flex\",\"FLOW-MATIC\",\"FOCAL\",\"FOCUS\",\"FOIL\",\"FORMAC\",\"@Formula\",\"Forth\",\"Fortran\",\"Fortress\",\"FoxBase\",\"FoxPro\",\"FP\",\"FPr\",\"Franz Lisp\",\"Frege\",\"F-Script\",\"FSProg\",\"G\",\"Google Apps Script\",\"Game Maker Language\",\"GameMonkey Script\",\"GAMS\",\"GAP\",\"G-code\",\"Genie\",\"GDL\",\"Gibiane\",\"GJ\",\"GEORGE\",\"GLSL\",\"GNU E\",\"GM\",\"Go\",\"Go!\",\"GOAL\",\"Gödel\",\"Godiva\",\"GOM (Good Old Mad)\",\"Goo\",\"Gosu\",\"GOTRAN\",\"GPSS\",\"GraphTalk\",\"GRASS\",\"Groovy\",\"Hack (programming language)\",\"HAL/S\",\"Hamilton C shell\",\"Harbour\",\"Hartmann pipelines\",\"Haskell\",\"Haxe\",\"High Level Assembly\",\"HLSL\",\"Hop\",\"Hope\",\"Hugo\",\"Hume\",\"HyperTalk\",\"IBM Basic assembly language\",\"IBM HAScript\",\"IBM Informix-4GL\",\"IBM RPG\",\"ICI\",\"Icon\",\"Id\",\"IDL\",\"Idris\",\"IMP\",\"Inform\",\"Io\",\"Ioke\",\"IPL\",\"IPTSCRAE\",\"ISLISP\",\"ISPF\",\"ISWIM\",\"J\",\"J#\",\"J++\",\"JADE\",\"Jako\",\"JAL\",\"Janus\",\"JASS\",\"Java\",\"JavaScript\",\"JCL\",\"JEAN\",\"Join Java\",\"JOSS\",\"Joule\",\"JOVIAL\",\"Joy\",\"JScript\",\"JScript .NET\",\"JavaFX Script\",\"Julia\",\"Jython\",\"K\",\"Kaleidoscope\",\"Karel\",\"Karel++\",\"KEE\",\"Kixtart\",\"KIF\",\"Kojo\",\"Kotlin\",\"KRC\",\"KRL\",\"KUKA\",\"KRYPTON\",\"ksh\",\"L\",\"L# .NET\",\"LabVIEW\",\"Ladder\",\"Lagoona\",\"LANSA\",\"Lasso\",\"LaTeX\",\"Lava\",\"LC-3\",\"Leda\",\"Legoscript\",\"LIL\",\"LilyPond\",\"Limbo\",\"Limnor\",\"LINC\",\"Lingo\",\"Linoleum\",\"LIS\",\"LISA\",\"Lisaac\",\"Lisp\",\"Lite-C\",\"Lithe\",\"Little b\",\"Logo\",\"Logtalk\",\"LPC\",\"LSE\",\"LSL\",\"LiveCode\",\"LiveScript\",\"Lua\",\"Lucid\",\"Lustre\",\"LYaPAS\",\"Lynx\",\"M2001\",\"M4\",\"Machine code\",\"MAD\",\"MAD/I\",\"Magik\",\"Magma\",\"make\",\"Maple\",\"MAPPER\",\"MARK-IV\",\"Mary\",\"MASM Microsoft Assembly x86\",\"Mathematica\",\"MATLAB\",\"Maxima\",\"Macsyma\",\"Max\",\"MaxScript\",\"Maya (MEL)\",\"MDL\",\"Mercury\",\"Mesa\",\"Metacard\",\"Metafont\",\"MetaL\",\"Microcode\",\"MicroScript\",\"MIIS\",\"MillScript\",\"MIMIC\",\"Mirah\",\"Miranda\",\"MIVA Script\",\"ML\",\"Moby\",\"Model 204\",\"Modelica\",\"Modula\",\"Modula-2\",\"Modula-3\",\"Mohol\",\"MOO\",\"Mortran\",\"Mouse\",\"MPD\",\"CIL\",\"MSL\",\"MUMPS\",\"NASM\",\"NATURAL\",\"Napier88\",\"Neko\",\"Nemerle\",\"nesC\",\"NESL\",\"Net.Data\",\"NetLogo\",\"NetRexx\",\"NewLISP\",\"NEWP\",\"Newspeak\",\"NewtonScript\",\"NGL\",\"Nial\",\"Nice\",\"Nickle\",\"Nim\",\"NPL\",\"Not eXactly C\",\"Not Quite C\",\"NSIS\",\"Nu\",\"NWScript\",\"NXT-G\",\"o:XML\",\"Oak\",\"Oberon\",\"Obix\",\"OBJ2\",\"Object Lisp\",\"ObjectLOGO\",\"Object REXX\",\"Object Pascal\",\"Objective-C\",\"Objective-J\",\"Obliq\",\"Obol\",\"OCaml\",\"occam\",\"occam-π\",\"Octave\",\"OmniMark\",\"Onyx\",\"Opa\",\"Opal\",\"OpenCL\",\"OpenEdge ABL\",\"OPL\",\"OPS5\",\"OptimJ\",\"Orc\",\"ORCA/Modula-2\",\"Oriel\",\"Orwell\",\"Oxygene\",\"Oz\",\"P#\",\"ParaSail (programming language)\",\"PARI/GP\",\"Pascal\",\"Pawn\",\"PCASTL\",\"PCF\",\"PEARL\",\"PeopleCode\",\"Perl\",\"PDL\",\"PHP\",\"Phrogram\",\"Pico\",\"Picolisp\",\"Pict\",\"Pike\",\"PIKT\",\"PILOT\",\"Pipelines\",\"Pizza\",\"PL-11\",\"PL/0\",\"PL/B\",\"PL/C\",\"PL/I\",\"PL/M\",\"PL/P\",\"PL/SQL\",\"PL360\",\"PLANC\",\"Plankalkül\",\"Planner\",\"PLEX\",\"PLEXIL\",\"Plus\",\"POP-11\",\"PostScript\",\"PortablE\",\"Powerhouse\",\"PowerBuilder\",\"PowerShell\",\"PPL\",\"Processing\",\"Processing.js\",\"Prograph\",\"PROIV\",\"Prolog\",\"PROMAL\",\"Promela\",\"PROSE modeling language\",\"PROTEL\",\"ProvideX\",\"Pro*C\",\"Pure\",\"Python\",\"Q (equational programming language)\",\"Q (programming language from Kx Systems)\",\"Qalb\",\"QtScript\",\"QuakeC\",\"QPL\",\"R\",\"R++\",\"Racket\",\"RAPID\",\"Rapira\",\"Ratfiv\",\"Ratfor\",\"rc\",\"REBOL\",\"Red\",\"Redcode\",\"REFAL\",\"Reia\",\"Revolution\",\"rex\",\"REXX\",\"Rlab\",\"RobotC\",\"ROOP\",\"RPG\",\"RPL\",\"RSL\",\"RTL/2\",\"Ruby\",\"RuneScript\",\"Rust\",\"S\",\"S2\",\"S3\",\"S-Lang\",\"S-PLUS\",\"SA-C\",\"SabreTalk\",\"SAIL\",\"SALSA\",\"SAM76\",\"SAS\",\"SASL\",\"Sather\",\"Sawzall\",\"SBL\",\"Scala\",\"Scheme\",\"Scilab\",\"Scratch\",\"Script.NET\",\"Sed\",\"Seed7\",\"Self\",\"SenseTalk\",\"SequenceL\",\"SETL\",\"Shift Script\",\"SIMPOL\",\"SIGNAL\",\"SiMPLE\",\"SIMSCRIPT\",\"Simula\",\"Simulink\",\"SISAL\",\"SLIP\",\"SMALL\",\"Smalltalk\",\"Small Basic\",\"SML\",\"Snap!\",\"SNOBOL\",\"SPITBOL\",\"Snowball\",\"SOL\",\"Span\",\"SPARK\",\"Speedcode\",\"SPIN\",\"SP/k\",\"SPS\",\"Squeak\",\"Squirrel\",\"SR\",\"S/SL\",\"Stackless Python\",\"Starlogo\",\"Strand\",\"Stata\",\"Stateflow\",\"Subtext\",\"SuperCollider\",\"SuperTalk\",\"Swift (Apple programming language)\",\"Swift (parallel scripting language)\",\"SYMPL\",\"SyncCharts\",\"SystemVerilog\",\"T\",\"TACL\",\"TACPOL\",\"TADS\",\"TAL\",\"Tcl\",\"Tea\",\"TECO\",\"TELCOMP\",\"TeX\",\"TEX\",\"TIE\",\"Timber\",\"TMG\",\"Tom\",\"TOM\",\"Topspeed\",\"TPU\",\"Trac\",\"TTM\",\"T-SQL\",\"TTCN\",\"Turing\",\"TUTOR\",\"TXL\",\"TypeScript\",\"Turbo C++\",\"Ubercode\",\"UCSD Pascal\",\"Umple\",\"Unicon\",\"Uniface\",\"UNITY\",\"Unix shell\",\"UnrealScript\",\"Vala\",\"VBA\",\"VBScript\",\"Verilog\",\"VHDL\",\"Visual Basic\",\"Visual Basic .NET\",\"Visual DataFlex\",\"Visual DialogScript\",\"Visual Fortran\",\"Visual FoxPro\",\"Visual J++\",\"Visual J#\",\"Visual Objects\",\"Visual Prolog\",\"VSXu\",\"Vvvv\",\"WATFIV, WATFOR\",\"WebDNA\",\"WebQL\",\"Windows PowerShell\",\"Winbatch\",\"Wolfram\",\"Wyvern\",\"X++\",\"X#\",\"X10\",\"XBL\",\"XC\",\"XMOS architecture\",\"xHarbour\",\"XL\",\"Xojo\",\"XOTcl\",\"XPL\",\"XPL0\",\"XQuery\",\"XSB\",\"XSLT\",\"XPath\",\"Xtend\",\"Yorick\",\"YQL\",\"Z notation\",\"Zeno\",\"ZOPL\",\"ZPL\"]\n", + "ALL_LANGS = list(map(lambda x: x.lower(), ALL_LANGS))\n", + "ALL_LANGS_SET = set(ALL_LANGS)\n", + "print(ALL_LANGS_SET)\n", + "\n", + "tokenizer = DistilBertTokenizerFast.from_pretrained('distilbert-base-uncased')" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "{'k', 'gamemonkey script', 'prose modeling language', 'lua', 'x++', 'txl', 'joule', 'xotcl', 'opal', 'lite-c', 'algol 58', 'uniface', 'spin', 'icon', 'promela', 'g', 'chapel', 'nickle', 'nesc', 'boomerang', 'xl', 'l', 'averest', 'b', 'dataflex', 'datatrieve', 'smalltalk', 'mary', 'foxpro', 'prograph', 'moby', 'stackless python', 'assembly language', 'c/al', 'amiga e', 'caml', 'beanshell', 'rpg', 'ada', 'postscript', 'f#', 'snap!', 'iptscrae', 'dbase', 'ferite', 'ceylon', 'visual foxpro', 'redcode', 'quakec', 'mortran', 'kif', 'xpath', 'vbscript', 'goo', 'ace dasl', 'cg', 'lynx', 'sbl', 'yql', 'a+', 'csound', 'dibol', 'abc algol', 'elan', 'q (equational programming language)', 'spitbol', 'lansa', 'rapid', 'csp', 'octave', 'george', 'cil', 'bon', 'cfml', 'pipelines', 'karel++', 'charity', 'argus', 'arc', 'alice', 'a++', 'clu', 'elixir', 'simscript', 'lilypond', 'starlogo', 'pizza', 'pl/0', 'self', 'clojure', 'reia', 'masm microsoft assembly x86', 'maxscript', 'latex', 'ppl', 'tmg', 'fp', 'formac', 'squirrel', 'mirah', 'typescript', 'miis', 'able', 'turing', 'synccharts', 'salsa', 'cyclone', 'squeak', 'occam-π', 'turbo c++', 'teco', 't-sql', 'ratfiv', 'not exactly c', 'graphtalk', 'xquery', 'planc', 'powerhouse', 'ibm hascript', 'logo', 'e#', 'bliss', 'ttm', 'bash', 'krl', 'tads', 'c#', 'java', 'ubercode', 'simula', 'simulink', 'ops5', 'grass', 'sml', 'adenine', 'code', 'mapper', 'sp/k', 'alf', 'kaleidoscope', 'robotc', 'macsyma', 'bc', 'joss', 'portable', 'inform', 'lingo', 'pcastl', 'cool', 'drakon', 'high level assembly', 'vsxu', 'rebol', 'objective-j', 'zeno', 'algol 60', 'sed', 'ipl', 'o:xml', 'nxt-g', 'cms-2', 'phrogram', 'jade', 'proiv', 'ici', 'julia', 'leda', 'processing', 'autolisp / visual lisp', 'systemverilog', 'pure', 'swift (apple programming language)', 'fancy', 'strand', 'j#', 'orwell', 'pl/m', 'lithe', 'chill', 'tacpol', 'coldfusion', 'logtalk', 'modelica', 'prolog', 'scratch', 'algol 68', 'jako', 'not quite c', 'mouse', 'watfiv, watfor', 'mdl', 'shift script', 'j', 'jscript .net', 'vvvv', 'mohol', 'clipper', 'little b', 'modula', 'mimic', 'f', 'gödel', 'cobol', 'unity', 'nwscript', 'ratfor', 'supercollider', 'red', 'bitc', 'clarion', 'kotlin', 'arexx', 'pari/gp', 'obol', 'a-0 system', 'millscript', 'abc', 'newspeak', 'dcl', 'oriel', 'act-iii', 'godiva', 'limbo', 'joy', 'mathematica', 'delphi', 'idl', 'autohotkey', 'parasail (programming language)', 'magik', 'nim', 'ocaml', 'easy programming language', 'janus', 'goal', 'modula-3', 'coldc', 'gnu e', 'lse', 'oberon', 'genie', 'esterel', 'gotran', 'qpl', 'ateji px', 'hlsl', 'small basic', 'r', 'focal', 'cola', 'euphoria', 'acl2', 'brew', 'linc', 'orc', 'bourne shell', 'winbatch', 'coffeescript', 'stata', 'tal', 'mad/i', 'snowball', 'object rexx', 'visual prolog', 'pl/i', 'cics', 'cobra', 'haskell', 'visual j++', 'comit', 'cuda', 'snobol', 'lyapas', 'planner', 'curry', 'bigwig', 'javafx script', 'pop-11', 'visual dataflex', 'agora', 'egl', 'falcon', 'go', 'topspeed', 'hope', 'visual basic .net', 'hypertalk', 'accent', 'dynamo', 'ffp', 'natural', 'factor', 'ml', 'object lisp', 'tacl', 'caché objectscript', 'p#', 'sasl', 'tcl', 'mercury', 'fl', 'dog', 'simpol', 'amos', 'jass', 'epl', 'fantom', 'seed7', 'gpss', 'unicon', 'apl', 'pearl', 'abset', 'scala', 'neko', 'ladder', 'emacs lisp', 'stateflow', 'compass', 's3', 'aimms', 'lava', 'ucsd pascal', 'axum', 'visual objects', 'autoit', 'chain', 'a# .net', 'cel', 'setl', 'pl/p', 'candle', 'hume', 'awk', 'x10', 'nsis', 'combined programming language', 'max', 'mark-iv', 'gosu', 'jscript', 'sabretalk', 'io', 'sawzall', 'z notation', 'absys', 'easytrieve plus', 'visual basic', 'iswim', 'rc', 'scheme', 'orca/modula-2', 'timber', 'chip-8', 'python', 'clist', 'trac', 'sensetalk', 'revolution', 'sas', 'ngl', 'hartmann pipelines', 'simple', 'oxygene', 'obliq', 'euslisp robot programming language', 'kee', 'sail', 'coq', 'nial', 'sps', 'agilent vee', 'lc-3', 'pcf', 'bistro', 'ease', 'roop', 'lis', 'erlang', 'optimj', 'pawn', 's', 'join java', 's2', 'c', 'haxe', 'fortran', 'cfengine', 'boo', 'escher', 'executable uml', 'deesel', 'metafont', 'xsb', 'powershell', 'swift (parallel scripting language)', 'tutor', 'cecil', 'zpl', 's-plus', 'onyx', 'm2001', 'miranda', 'fjölnir', 'matlab', 'fsprog', 'objectlogo', 'e', 'pascal', 'pl/sql', 'plexil', 'moo', 'maple', 'yorick', 'abap', 'miva script', 'autocoder', 'hal/s', 'j++', 'imp', 'c++', 'ibm rpg', 'speedcode', 'tpu', 'visual j#', 'modula-2', 'xbl', 'pdl', 'franz lisp', 'gj', 'groovy', 'napier88', 'tex', 'flow-matic', 'xmos architecture', 'claire', 'php', 'lpc', 'lucid', 'gams', 'gom (good old mad)', 'g-code', 'msl', 'cowsel', 'ats', 'xharbour', 'foxbase', 'forth', 'oak', 'ruby', 'plankalkül', 'ampl', 'cms exec', 'labview', 'model 204', 'a# (axiom)', 'hamilton c shell', 'sequencel', 'peoplecode', 'ibm basic assembly language', 'c shell', 'sam76', 'unix shell', 'webdna', 'algol w', 'visual dialogscript', 'mpd', 'beta', 'nice', 'signal', 'dasl', 'tie', 'legoscript', 'limnor', 'ttcn', 's-lang', 'nesl', 'bpel', 'common intermediate language', 'flavors', 'edinburgh imp', 'csh', 'euler', 'm4', 'pico', 'vhdl', 'protel', 'sa-c', 'lustre', 'mad', 'obj2', 'common lisp', 'newtonscript', 'krc', 'etoys', 'opl', 'powerbuilder', 'racket', 'windows powershell', 'converge', 'nasm', 'xc', 'f-script', 'livecode', 'espol', 'sol', 'script.net', 'sisal', 'batch (windows/dos)', 'microcode', 'rex', 'refal', 'rlab', 'lagoona', 'lisaac', 'picolisp', 'providex', 'r++', 'machine code', 'cesil', 'vala', 'es', 'obix', 'xpl0', 'alef', 'cduce', 'newp', 'lisp', 'cayenne', 'constraint handling rules', 'sr', 'subtext', 'cilk', 'dc', 'epigram', 'jal', 'kixtart', 'cpl', 'opa', 'felix', '@formula', 'hugo', 'plex', 'gibiane', 'maya (mel)', 'zopl', 'jython', 's/sl', 'jean', 'qtscript', 'rapira', 'supertalk', 'nu', 'ioke', 'gm', 'clean', 'microscript', 'promal', 'harbour', 'webql', 'scilab', 'rsl', 'xojo', 'applescript', 'foil', 'jovial', 'corvision', 'oz', 'coral 66', 'eiffel', 'maxima', 'dylan', 'pl/b', 'component pascal', 'npl', 'draco', 'opencl', 'perl', 'krypton', 'pl-11', 'xpl', 'netrexx', 'game maker language', 'umple', 'kojo', 'lsl', 'faust', 'gdl', 'object pascal', 'idris', 'unrealscript', 'action!', \"app inventor for android's visual block language\", 'focus', 'rexx', 'glsl', 'metal', 'sather', 'newlisp', 'islisp', 'flex', 'ambienttalk', 'pro*c', 'kuka', 'charm', 'openedge abl', 'xslt', 'occam', 'telcomp', 'dinkc', 'dart', 'bertrand', 'ksh', 'c--', 'lasso', 'slip', 'ibm informix-4gl', 'chuck', 'd', 'go!', 'fortress', 'l# .net', 'comal', 'q (programming language from kx systems)', 'xtend', 't', 'livescript', 'pict', 'ispf', 'vba', 'alma-0', 'pike', 'curl', 'small', 'rust', 'mesa', 'rtl/2', 'hop', 'javascript', 'lil', 'exec 2', 'pikt', 'frege', 'qalb', 'bcpl', 'chomski', 'aspectj', 'rpl', 'fpr', 'plus', 'gap', 'tea', 'wyvern', 'cl', 'babbage', 'x#', 'ch', 'agda', 'cython', 'pl/c', 'elm', 'basic', 'nemerle', 'lisa', 'netlogo', 'euclid', 'pilot', 'tom', 'actionscript', 'processing.js', 'corn', 'metacard', 'sympl', 'magma', 'visual fortran', 'make', 'span', 'ecmascript', 'jcl', 'emerald', 'google apps script', 'spark', 'net.data', 'objective-c', 'blue', 'omnimark', 'mumps', 'runescript', 'verilog', 'karel', 'id', 'escapade', 'linoleum', 'easy pl/i', 'wolfram', 'datalog', 'chef', 'acc', 'pl360', 'hack (programming language)'}\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b9f3692aa5394af38fbf8701f9d1a2f5", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=231508.0, style=ProgressStyle(descripti…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "89764229f6bb4419927cd6499b252cc1", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=466062.0, style=ProgressStyle(descripti…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "723f45572f9845f7a5a43d028acabd37", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=28.0, style=ProgressStyle(description_w…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "gl4s2lbNNo_f" + }, + "source": [ + "!cp ./drive/MyDrive/howdoi_train.csv ./\n", + "!cp ./drive/MyDrive/howdoi_test.csv ./" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "bPeuuANP_Kj_", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "93c5bd8c-45ed-47ad-fea6-15e6637dbb2b" + }, + "source": [ + "# do lazy loading with h5py to save memory\n", + "'''\n", + "import h5py\n", + "import numpy as np\n", + "\n", + "import subprocess\n", + "train_path, test_path = \"./howdoi_train.csv\", \"./howdoi_test.csv\"\n", + "h5_train_path, h5_test_path = \"./data_tr.h5\", \"./data_ts.h5\"\n", + "\n", + "# this is just a random large number, this size of data (short strings)\n", + "# doesn't take much RAM, not even sure we have to read it in chunks at all\n", + "chunksize = 1000 * 10000\n", + "\n", + "# hacky way of reading the length of the file without opening it\n", + "lines_train = subprocess.check_output(['wc', '-l', train_path])\n", + "lines_train = int(lines_train.split()[0])\n", + "\n", + "# h5 is a format you can read from without loading up the data in memory\n", + "# so it's perfect for huge datasets\n", + "\n", + "# NOTE: this will take a minute or so\n", + "with h5py.File(h5_train_path, 'w') as h5f:\n", + " # use num_features if the csv file has no column header\n", + " texts = h5f.create_dataset(\"text-train\",\n", + " shape=(lines_train,),\n", + " compression=None,\n", + " dtype=h5py.string_dtype('utf-8'))\n", + " labels = h5f.create_dataset(\"label-train\",\n", + " shape=(lines_train,),\n", + " compression=None,\n", + " dtype=\"bool\")\n", + "\n", + " # read num_lines in chunks of size chunksize\n", + " for i in range(1, lines_train, chunksize): \n", + "\n", + " df = pd.read_csv(\n", + " train_path, \n", + " header=None, # we ignore the header by starting the loop from row 1\n", + " nrows=chunksize,\n", + " skiprows=i\n", + " )\n", + " \n", + " titles = df.values[:, -2]\n", + "\n", + " # you don't have to do this at this step, you could also just store\n", + " # this as a string, like in the original csv\n", + " has_tags = [\n", + " len(set(str(t).lower().split('|')).intersection(ALL_LANGS_SET)) > 0\n", + " for t in df.values[:, -1]\n", + " ]\n", + " print(has_tags)\n", + "\n", + " items_num = len(titles)\n", + "\n", + " # this fills in the current chunk of the h5 file\n", + " texts[i-1:i-1+items_num] = titles\n", + " labels[i-1:i-1+items_num] = has_tags\n", + "\n", + "# Create test set\n", + "\n", + "'''" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "IOPub data rate exceeded.\n", + "The notebook server will temporarily stop sending output\n", + "to the client in order to avoid crashing it.\n", + "To change this limit, set the config variable\n", + "`--NotebookApp.iopub_data_rate_limit`.\n", + "\n", + "Current values:\n", + "NotebookApp.iopub_data_rate_limit=1000000.0 (bytes/sec)\n", + "NotebookApp.rate_limit_window=3.0 (secs)\n", + "\n", + "IOPub data rate exceeded.\n", + "The notebook server will temporarily stop sending output\n", + "to the client in order to avoid crashing it.\n", + "To change this limit, set the config variable\n", + "`--NotebookApp.iopub_data_rate_limit`.\n", + "\n", + "Current values:\n", + "NotebookApp.iopub_data_rate_limit=1000000.0 (bytes/sec)\n", + "NotebookApp.rate_limit_window=3.0 (secs)\n", + "\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "IslPgrNQig6P" + }, + "source": [ + "import h5py\n", + "import numpy as np\n", + "\n", + "import subprocess\n", + "train_path, test_path = \"./howdoi_train.csv\", \"./howdoi_test.csv\"\n", + "h5_train_path, h5_test_path = \"./data_tr.h5\", \"./data_ts.h5\"\n", + "\n", + "# this is just a random large number, this size of data (short strings)\n", + "# doesn't take much RAM, not even sure we have to read it in chunks at all\n", + "chunksize = 1000 * 10000\n", + "\n", + "# hacky way of reading the length of the file without opening it\n", + "lines_train = subprocess.check_output(['wc', '-l', train_path])\n", + "lines_train = int(lines_train.split()[0])\n", + "\n", + "df_train = pd.read_csv(train_path)\n", + "df_test = pd.read_csv(test_path)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "iybXPZ2WoFJP" + }, + "source": [ + "df_train['tags'] = df_train['tags'].map(lambda x:\n", + " len(set(str(x).lower().split('|')).intersection(ALL_LANGS_SET)) > 0\n", + " )\n", + "df_test['tags'] = df_test['tags'].map(lambda x:\n", + " len(set(str(x).lower().split('|')).intersection(ALL_LANGS_SET)) > 0\n", + " )" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "kA2tOyy2pyHa", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "outputId": "6c4a5775-a332-4674-c08e-eddb0b4ee430" + }, + "source": [ + "df_test.head()" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unnamed: 0Unnamed: 0.1titletags
01197140011971400Changing colors of shapes in HTML5 canvasjavascript|html|canvas|polygon
154337725433772Where to look for DB file after update-database?c#|.net|entity
289963048996304Graddle missing transitive dependencymaven|gradle|transitive-dependency
376482137648213laravel link does work but button does nottwitter-bootstrap|laravel
41412393814123938Elegant haskell case/error handling in sequent...haskell
\n", + "
" + ], + "text/plain": [ + " Unnamed: 0 ... tags\n", + "0 11971400 ... javascript|html|canvas|polygon\n", + "1 5433772 ... c#|.net|entity\n", + "2 8996304 ... maven|gradle|transitive-dependency\n", + "3 7648213 ... twitter-bootstrap|laravel\n", + "4 14123938 ... haskell\n", + "\n", + "[5 rows x 4 columns]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 9 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "FRqvd1muijVE" + }, + "source": [ + "import torch" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "qjtjK2tH6hdn" + }, + "source": [ + "class QueryDataset(Dataset):\n", + " def __init__(self, filename, kind):\n", + " self.titles = df_train['title']\n", + " self.labels = df_train['tags']\n", + "\n", + " def __len__(self):\n", + " return self.titles.shape[0]\n", + "\n", + " def __getitem__(self, i):\n", + " # now the cool bit - read without loading the whole thing in memory!\n", + " title = self.titles[i]\n", + " label = self.labels[i].astype('bool')\n", + " label = 1 if label else 0\n", + " # encoded = tokenizer(title, truncation=True, padding=True)\n", + " out = {'title': title, 'label': label}\n", + " return out" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "c9OPoW4uivuu" + }, + "source": [ + "def collate_fn(data):\n", + " titles, labels = [v['title'] for v in data], [v['label'] for v in data]\n", + " encoded = tokenizer(titles, truncation=True, padding=True)\n", + " # for k,v in encoded.items():\n", + " # print(len(v[0]))\n", + " out = {k: torch.tensor(v) for k,v in encoded.items()}\n", + " out['labels'] = torch.tensor(labels)\n", + " return out" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DxL9pAGSXyJZ", + "outputId": "4e8fa188-eed7-454f-8e20-914152bfbb27" + }, + "source": [ + "trainset = QueryDataset(h5_train_path, 'train')\n", + "trainloader = DataLoader(trainset, batch_size=256, num_workers=2, shuffle=True,\n", + " collate_fn=collate_fn) # This seemingly redundant collate_fn param actually helps avoid a RuntimeError - https://github.com/pytorch/pytorch/issues/42654#issuecomment-706926806\n", + "for i, y in enumerate(trainloader):\n", + " print(y)\n", + " break" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "{'input_ids': tensor([[ 101, 24357, 3746, ..., 0, 0, 0],\n", + " [ 101, 10463, 5164, ..., 0, 0, 0],\n", + " [ 101, 2129, 2000, ..., 0, 0, 0],\n", + " ...,\n", + " [ 101, 9585, 8011, ..., 0, 0, 0],\n", + " [ 101, 2054, 2024, ..., 0, 0, 0],\n", + " [ 101, 2129, 2064, ..., 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, ..., 0, 0, 0],\n", + " [1, 1, 1, ..., 0, 0, 0],\n", + " [1, 1, 1, ..., 0, 0, 0],\n", + " ...,\n", + " [1, 1, 1, ..., 0, 0, 0],\n", + " [1, 1, 1, ..., 0, 0, 0],\n", + " [1, 1, 1, ..., 0, 0, 0]]), 'labels': tensor([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,\n", + " 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0,\n", + " 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,\n", + " 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0,\n", + " 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1,\n", + " 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1,\n", + " 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,\n", + " 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1,\n", + " 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0,\n", + " 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1,\n", + " 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1])}\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2nhCSTDlyC5m" + }, + "source": [ + "## Model training code" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "2z7cHC1xyAZr" + }, + "source": [ + "from transformers import DistilBertForSequenceClassification, AdamW" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "HmD6NW1FyZjM", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 237, + "referenced_widgets": [ + "7a54279586bb4c87a52746f605f7b3e2", + "6a7acabfc3f24d3395c0cc7cde68a43a", + "b9c6899ed3dd489d85b201b51a6f35c3", + "b413ba22912c4149aeea6824ccbc90c1", + "6151969c55174665964db6f97bd18884", + "f97dbff45ea347f380b3d3e2bf9b60a5", + "6bc47beb071c4884a4ddb8a7dd669222", + "6acde23812d44176829ce106ea626f09", + "6e48979f9d49495da15e278aafd97a8b", + "73a609c59da744088c8def134a0acebc", + "3e978968f8814d4e9cb0cce52fe25f53", + "5b91aa38af194763b33168e24eb80b91", + "27cc2164a06a40a0b6e093bd1f642fce", + "1b013fd1c8ce45c992ed4dba0bcf2393", + "daedb950ac444ef3aa764b29f3e84052", + "579a1b0eff7b425a9f22a18506fb7033" + ] + }, + "outputId": "7e390c52-f065-460c-dd08-8af04ee0af4e" + }, + "source": [ + "device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n", + "\n", + "model = DistilBertForSequenceClassification.from_pretrained('distilbert-base-uncased')\n", + "model.to(device)\n", + "model.train()\n", + "\n", + "optim = AdamW(model.parameters(), lr=5e-5)\n", + "\n", + "for epoch in range(3):\n", + " for batch in trainloader:\n", + " optim.zero_grad()\n", + " input_ids = batch['input_ids'].to(device)\n", + " attention_mask = batch['attention_mask'].to(device)\n", + " labels = batch['labels'].to(device)\n", + " outputs = model(input_ids, attention_mask=attention_mask, labels=labels)\n", + " loss = outputs[0]\n", + " loss.backward()\n", + " optim.step()\n", + "\n", + "model.eval()" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7a54279586bb4c87a52746f605f7b3e2", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=442.0, style=ProgressStyle(description_…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6e48979f9d49495da15e278aafd97a8b", + "version_minor": 0, + "version_major": 2 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='Downloading', max=267967963.0, style=ProgressStyle(descri…" + ] + }, + "metadata": { + "tags": [] + } + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "Some weights of the model checkpoint at distilbert-base-uncased were not used when initializing DistilBertForSequenceClassification: ['vocab_transform.weight', 'vocab_transform.bias', 'vocab_layer_norm.weight', 'vocab_layer_norm.bias', 'vocab_projector.weight', 'vocab_projector.bias']\n", + "- This IS expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", + "- This IS NOT expected if you are initializing DistilBertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", + "Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['pre_classifier.weight', 'pre_classifier.bias', 'classifier.weight', 'classifier.bias']\n", + "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "mr_F0fiyzuy8" + }, + "source": [ + "" + ], + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file From a12ba5e80ce49d60251c1a237c5501e7fd1e7ee8 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Thu, 22 Apr 2021 14:52:31 -0700 Subject: [PATCH 002/135] Update README and add @SaurusXI as a contributor --- README.rst | 4 +++- docs/user-guide.md | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index b626e74d6..d5fc229f8 100644 --- a/README.rst +++ b/README.rst @@ -97,7 +97,7 @@ Usage :: - usage: howdoi.py [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-C] [-j] [-v] [-e [ENGINE]] [--save] [--view] [--remove] [--empty] [QUERY ...] + usage: howdoi [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-x] [-C] [-j] [-v] [-e [ENGINE]] [--save] [--view] [--remove] [--empty] [QUERY ...] instant coding answers via the command line @@ -111,6 +111,7 @@ Usage -a, --all display the full text of the answer -l, --link display only the answer link -c, --color enable colorized output + -x, --explain explain how answer was chosen -C, --clear-cache clear the cache -j, --json return answers in raw json format -v, --version displays the current version of howdoi @@ -165,6 +166,7 @@ Contributors - Chris Nguyen (`@chrisngyn `_) - Shageldi Ovezov (`@ovezovs `_) - Mwiza Simbeye (`@mwizasimbeye11 `_) +- Shantanu Verma (`@SaurusXI `_) - And `more! `_ Notes diff --git a/docs/user-guide.md b/docs/user-guide.md index 87d4dd888..622972cc1 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -11,8 +11,7 @@ Print the help manual ```bash $ howdoi # "howdoi -h" also prints help -usage: howdoi.py [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-C] [-j] [-v] [-e [ENGINE]] - [--save] [--view] [--remove] [--empty] [QUERY ...] +usage: howdoi [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-x] [-C] [-j] [-v] [-e [ENGINE]] [--save] [--view] [--remove] [--empty] [QUERY ...] instant coding answers via the command line @@ -26,6 +25,7 @@ optional arguments: -a, --all display the full text of the answer -l, --link display only the answer link -c, --color enable colorized output + -x, --explain explain how answer was chosen -C, --clear-cache clear the cache -j, --json return answers in raw json format -v, --version displays the current version of howdoi From 3b540fe16beaef10711292b629d9997119732b07 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 3 May 2021 10:51:44 -0700 Subject: [PATCH 003/135] Only sanity check Google --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 65c0240c3..2b55a4f06 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -717,7 +717,7 @@ def perform_sanity_check(): cache = NullCache() exit_code = 0 - for engine in ('google', 'bing', 'duckduckgo'): + for engine in ['google']: # 'bing' and 'duckduckgo' throw various block errors print('Checking {}...'.format(engine)) try: _sanity_check(engine) From e72c6a7c31240ab5fb81967cacce3b5be5d495fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 May 2021 21:52:14 +0000 Subject: [PATCH 004/135] Bump lodash in /extension/code-editor-integration Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21) Signed-off-by: dependabot[bot] --- extension/code-editor-integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index ac4d8f135..d7ad0ca1d 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -1757,9 +1757,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.flattendeep": { From 6330bbbd676e0db67f38d9cb962984354624c883 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 May 2021 22:09:59 +0000 Subject: [PATCH 005/135] Bump hosted-git-info in /extension/code-editor-integration Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9. - [Release notes](https://github.com/npm/hosted-git-info/releases) - [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md) - [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9) Signed-off-by: dependabot[bot] --- extension/code-editor-integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index ac4d8f135..064cc123d 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -1374,9 +1374,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "html-escaper": { From eff4a1d058205c41a0e922b6cd49c164d038ff6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 May 2021 23:34:59 +0000 Subject: [PATCH 006/135] Bump lodash from 4.17.19 to 4.17.21 in /extension/vscode-howdoi Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21) Signed-off-by: dependabot[bot] --- extension/vscode-howdoi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/vscode-howdoi/package-lock.json b/extension/vscode-howdoi/package-lock.json index d7055ac0e..d2e393bd5 100644 --- a/extension/vscode-howdoi/package-lock.json +++ b/extension/vscode-howdoi/package-lock.json @@ -1195,9 +1195,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "log-symbols": { From 89f960d95fbc2668b37640a31073699cec82186a Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Wed, 12 May 2021 11:33:53 -0700 Subject: [PATCH 007/135] For Google URL matches, use the `HOWDOI_URL` --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 2b55a4f06..463cb487d 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -225,7 +225,7 @@ def _clean_google_link(link): def _extract_links_from_google(query_object): html = query_object.html() - link_pattern = re.compile(r"https?://*stackoverflow.com/questions/[0-9]*/[a-z0-9-]*") + link_pattern = re.compile(fr"https?://{URL}/questions/[0-9]*/[a-z0-9-]*") links = link_pattern.findall(html) links = [_clean_google_link(link) for link in links] return links From 537f733c493597e69c62790223b409cf3fb7bb44 Mon Sep 17 00:00:00 2001 From: Prateek93a Date: Sun, 30 May 2021 12:15:54 +0530 Subject: [PATCH 008/135] added lint pre-commit hook --- .pre-commit-config.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..9328a03bc --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +repos: + - repo: https://github.com/pycqa/flake8 + rev: 3.9.2 + hooks: + - id: flake8 + args: + - "--config=.flake8rc" From c1fd76a759f02706cb7affef5888b61a74f0f80a Mon Sep 17 00:00:00 2001 From: Prateek93a Date: Sun, 30 May 2021 12:41:17 +0530 Subject: [PATCH 009/135] added flak8 to dev requirements list --- requirements/dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements/dev.txt b/requirements/dev.txt index 5364d35bf..3c230796c 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,2 +1,3 @@ # Contains development specific requirements and imports common requirements +flake8==3.9.2 -r common.txt \ No newline at end of file From 2759ee26819fa45d2b23a75e85a8e3bbe7312baa Mon Sep 17 00:00:00 2001 From: Prateek93a Date: Sun, 30 May 2021 12:54:54 +0530 Subject: [PATCH 010/135] added lint command in setup.py --- setup.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b8ef81004..f2f51d098 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,8 @@ #!/usr/bin/env python +import subprocess from pathlib import Path +from distutils.cmd import Command from setuptools import setup, find_packages # pylint: disable=unused-import import fastentrypoints # noqa: F401 @@ -8,6 +10,29 @@ import howdoi +class Lint(Command): + """A custom command to run Flake8 on all Python source files. + """ + description = 'run Flake8 on Python source files' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + try: + command = ['flake8', '--config=.flake8rc', '.'] + subprocess.check_call(command) + print('No lint errors found') + except FileNotFoundError: + print('flake8 not installed') + except subprocess.CalledProcessError: + pass + + def read(*names): values = dict() for name in names: @@ -71,5 +96,8 @@ def read(*names): 'cachelib', 'appdirs', 'keep', - ] + ], + cmdclass={ + 'lint': Lint + } ) From c94fc363fa73c0452df1e1f8699ac182164dba4d Mon Sep 17 00:00:00 2001 From: Prateek93a Date: Sun, 30 May 2021 13:07:26 +0530 Subject: [PATCH 011/135] added pre-commit in dev requirements list --- requirements/dev.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements/dev.txt b/requirements/dev.txt index 3c230796c..a4419eb1e 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,3 +1,4 @@ # Contains development specific requirements and imports common requirements flake8==3.9.2 +pre-commit==2.13.0 -r common.txt \ No newline at end of file From 15738907c762e6e4b0fae1baba91d04e0bb2c161 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 1 Jun 2021 21:22:38 +0200 Subject: [PATCH 012/135] GDPR fix for Google? The only problem for European users was the GDPR splash screen that Google was showing. Adding a small cookie jar onto our request may fix all of that. Seems to work for me. --- howdoi/howdoi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 463cb487d..b4dffd487 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -176,7 +176,8 @@ def _get_result(url): try: resp = howdoi_session.get(url, headers={'User-Agent': _random_choice(USER_AGENTS)}, proxies=get_proxies(), - verify=VERIFY_SSL_CERTIFICATE) + verify=VERIFY_SSL_CERTIFICATE, + cookies={'CONSENT':'YES+US.en+20170717-00-0'}) resp.raise_for_status() return resp.text except requests.exceptions.SSLError as error: From 21b99b7a68916a166a6dc97f994011336cc56d0f Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Wed, 12 May 2021 09:19:48 -0700 Subject: [PATCH 013/135] Prune the notebooks directory so it is not included in releases --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index 5efeae588..3a1c284be 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,3 +7,4 @@ include test_howdoi.py exclude howdoi.rb exclude .*rc prune page_cache +prune notebooks From 017fc5f943e493237bbfa8c929f049ea59f65d36 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Wed, 2 Jun 2021 02:43:09 -0700 Subject: [PATCH 014/135] Fix lint issue --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index b4dffd487..131940172 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -177,7 +177,7 @@ def _get_result(url): resp = howdoi_session.get(url, headers={'User-Agent': _random_choice(USER_AGENTS)}, proxies=get_proxies(), verify=VERIFY_SSL_CERTIFICATE, - cookies={'CONSENT':'YES+US.en+20170717-00-0'}) + cookies={'CONSENT': 'YES+US.en+20170717-00-0'}) resp.raise_for_status() return resp.text except requests.exceptions.SSLError as error: From c8ce37a277de149199964e569fd7ea964bb1453b Mon Sep 17 00:00:00 2001 From: Prateek93a Date: Thu, 3 Jun 2021 11:37:52 +0530 Subject: [PATCH 015/135] added pylint to .pre-commit-config-yaml --- .pre-commit-config.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9328a03bc..012459fd4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,3 +5,10 @@ repos: - id: flake8 args: - "--config=.flake8rc" + + - repo: https://github.com/PyCQA/pylint/ + rev: v2.8.2 + hooks: + - id: pylint + args: + - '--rcfile=.pylintrc' \ No newline at end of file From 6f4c377ff84b4589a7fb09c3420c34d79daf855c Mon Sep 17 00:00:00 2001 From: Prateek93a Date: Sat, 5 Jun 2021 10:59:47 +0530 Subject: [PATCH 016/135] added pylint to lint command and dev requirements list --- requirements/dev.txt | 1 + setup.py | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index a4419eb1e..0e16cdef5 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,4 +1,5 @@ # Contains development specific requirements and imports common requirements flake8==3.9.2 +pylint==2.8.2 pre-commit==2.13.0 -r common.txt \ No newline at end of file diff --git a/setup.py b/setup.py index f2f51d098..6550967b2 100644 --- a/setup.py +++ b/setup.py @@ -23,14 +23,18 @@ def finalize_options(self): pass def run(self): - try: - command = ['flake8', '--config=.flake8rc', '.'] - subprocess.check_call(command) - print('No lint errors found') - except FileNotFoundError: - print('flake8 not installed') - except subprocess.CalledProcessError: - pass + commands = {'Flake8': 'flake8 --config=.flake8rc .'.split(), + 'Pylint': 'pylint --rcfile=.pylintrc howdoi'.split()} + + for linter, command in commands.items(): + try: + print(f'\nRunning {linter}...') + subprocess.check_call(command) + print(f'No lint errors found by {linter}') + except FileNotFoundError: + print(f'{linter} not installed') + except subprocess.CalledProcessError: + pass def read(*names): From 6b5bc20c6796284f104519c7831f292bfb323549 Mon Sep 17 00:00:00 2001 From: Prateek93a Date: Sat, 5 Jun 2021 11:15:20 +0530 Subject: [PATCH 017/135] added double quotes in .pre-commit-config.yaml --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 012459fd4..2d6c14aad 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,4 +11,4 @@ repos: hooks: - id: pylint args: - - '--rcfile=.pylintrc' \ No newline at end of file + - "--rcfile=.pylintrc" \ No newline at end of file From 95659fe71c3acc509a81a816efee81cf87f7283d Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 7 Jun 2021 16:48:54 -0700 Subject: [PATCH 018/135] New release: 2.0.16 --- CHANGES.txt | 5 +++++ README.rst | 14 ++++++++++++++ howdoi/__init__.py | 2 +- requirements/dev.txt | 3 ++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 14d6b347a..70eee5e6f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,8 @@ +2.0.16 +------ +- Fix GDPR issue for those using howdoi in countries outside the US +- Better support for using `HOWDOI_URL` + 2.0.15 ------ - Add explainability with `-x` or `--explain` options diff --git a/README.rst b/README.rst index d5fc229f8..9bc815f4a 100644 --- a/README.rst +++ b/README.rst @@ -150,6 +150,19 @@ And then to run it from the command line simply type: $ h format date bash +You can also search other `StackExchange properties `_ for answers: + +:: + + HOWDOI_URL=cooking.stackexchange.com howdoi make pesto + +or as an alias: + +:: + + alias hcook='function hcook(){ HOWDOI_URL=cooking.stackexchange.com howdoi $* ; }; hcook' + hcook make pesto + Other useful aliases: :: @@ -190,6 +203,7 @@ Development - Checkout the repo - Run ``python -m howdoi QUERY`` (if you try running ``python howdoi/howdoi.py`` you might get ``ValueError: Attempted relative import in non-package``). +- When you're ready to open a PR be sure to run ``python setup.py lint`` to make sure your code passes the checks. If you would like to use howdoi from within a python script, just pass your query to `howdoi.howdoi()`: :: diff --git a/howdoi/__init__.py b/howdoi/__init__.py index 897e3130d..37f038a14 100644 --- a/howdoi/__init__.py +++ b/howdoi/__init__.py @@ -1 +1 @@ -__version__ = '2.0.15' +__version__ = '2.0.16' diff --git a/requirements/dev.txt b/requirements/dev.txt index 0e16cdef5..35d1b2970 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -2,4 +2,5 @@ flake8==3.9.2 pylint==2.8.2 pre-commit==2.13.0 --r common.txt \ No newline at end of file +twine==3.4.1 +-r common.txt From 9c2a5e415219300841e2f78ca7e35436f1ca977d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jun 2021 23:50:32 +0000 Subject: [PATCH 019/135] Bump glob-parent from 5.1.1 to 5.1.2 in /extension/vscode-howdoi Bumps [glob-parent](https://github.com/gulpjs/glob-parent) from 5.1.1 to 5.1.2. - [Release notes](https://github.com/gulpjs/glob-parent/releases) - [Changelog](https://github.com/gulpjs/glob-parent/blob/main/CHANGELOG.md) - [Commits](https://github.com/gulpjs/glob-parent/compare/v5.1.1...v5.1.2) --- updated-dependencies: - dependency-name: glob-parent dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/vscode-howdoi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/vscode-howdoi/package-lock.json b/extension/vscode-howdoi/package-lock.json index d2e393bd5..992fb2aab 100644 --- a/extension/vscode-howdoi/package-lock.json +++ b/extension/vscode-howdoi/package-lock.json @@ -843,9 +843,9 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" From fc26f0f6c321b7ece77d1363250ed5da6b7dc903 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jun 2021 23:50:35 +0000 Subject: [PATCH 020/135] Bump glob-parent in /extension/code-editor-integration Bumps [glob-parent](https://github.com/gulpjs/glob-parent) from 5.1.1 to 5.1.2. - [Release notes](https://github.com/gulpjs/glob-parent/releases) - [Changelog](https://github.com/gulpjs/glob-parent/blob/main/CHANGELOG.md) - [Commits](https://github.com/gulpjs/glob-parent/compare/v5.1.1...v5.1.2) --- updated-dependencies: - dependency-name: glob-parent dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/code-editor-integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index a56927b2c..5ccf64c6b 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -1308,9 +1308,9 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" From a51eacfefab53ab321120cd0a8a818802a62cf21 Mon Sep 17 00:00:00 2001 From: SaurusXI Date: Mon, 21 Jun 2021 20:34:37 +0530 Subject: [PATCH 021/135] feat: add bug report issue template to encourage users to use --explain --- .github/ISSUE_TEMPLATE/bug-report.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 000000000..c284bc9b3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,16 @@ +--- +name: Bug Report +about: Report a bug encountered with howdoi +labels: bug +--- + +#### What happened: + +#### What you expected to happen: + +#### Output with `--explain` +Please provide the output of running the same command with the `--explain` flag like so + +``` +$ howdoi YOUR_COMMAND --explain +``` \ No newline at end of file From d5132d8e9b428d8cba07d44af3bd79cf58b66a6d Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Sat, 26 Jun 2021 13:55:08 +0500 Subject: [PATCH 022/135] Create windows-contributing.md --- docs/windows-contributing.md | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 docs/windows-contributing.md diff --git a/docs/windows-contributing.md b/docs/windows-contributing.md new file mode 100644 index 000000000..bbf61c81a --- /dev/null +++ b/docs/windows-contributing.md @@ -0,0 +1,64 @@ +## Setting up a Windows Development environment + + + +Howdoi can be used on Windows, MacOS and Linux etc. But the development environment can only be set up in a Linux or Mac. To set up the development environment in Windows, follow the following steps: + +### Install WSL + +WSL is Windows Subsystem for Linux. It offers Linux interoperability in Windows and allows users to set up a virtual environment. + +If you do not have WSL set up, follow the steps in this [tutorial](https://www.windowscentral.com/install-windows-subsystem-linux-windows-10) + +### Setting up the virtual environment + +After setting up WSL, go to the directory where you want to set up Howdoi. Open the Command Prompt here and enter the following to enter the WSL environment. + +``` bash +bash +``` + +Now you are using the Linux-compatible kernel on Windows and can set up a virtual environment. + +### Clone the git repository + +```bash +$ git clone https://github.com/gleitz/howdoi.git +``` + +Setup and activate a virtual environment: + +``` bash +$ python3 -m venv .venv +$ source .venv/bin/activate +``` + +Make sure you have pip installed, if not, enter: + +``` bash +$ sudo apt install python3-pip +``` + +Go to the project directory and install requirements: + +``` bash +$ cd howdoi +$ pip install -r requirements.txt +``` + +> if howdoi does not process queries after this command, make sure your PATH variables for Python and Pip are set correctly in Windows environment variables. + +### Test run + +Check to see if everything has been set-up correctly: + +``` bash +pip install howdoi +howdoi print hello world +``` + + + + + + \ No newline at end of file From b09a7159ca99a9c968077f7d0cd84241aa8340fc Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Sat, 26 Jun 2021 14:03:46 +0500 Subject: [PATCH 023/135] Update mkdocs.yml add tab for windows dev documentation --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 031ea2e46..801e9cc7f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -18,6 +18,7 @@ nav: - "User Guide": user-guide.md - Contributing: contributing.md - Troubleshooting: troubleshooting.md + - Development for Windows: windows-contributing.md markdown_extensions: - toc: From 0b3545a28b690ea5bc75fd49ff28b719d370678c Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Thu, 8 Jul 2021 13:39:19 +0500 Subject: [PATCH 024/135] Fix HOWDOI_SEARCH_ENGINE was not respecting the env variable for the search engine, fixed now --- howdoi/howdoi.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 131940172..155ccda3e 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -588,7 +588,13 @@ def howdoi(raw_query): else: args = raw_query - os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] + if args['search_engine'] != 'google': + os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] + else: + if 'HOWDOI_SEARCH_ENGINE' in os.environ.keys() and os.environ['HOWDOI_SEARCH_ENGINE'] != 'google': + args['search_engine'] = os.environ['HOWDOI_SEARCH_ENGINE'] + else: + os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] args['query'] = ' '.join(args['query']).replace('?', '') cache_key = _get_cache_key(args) From 6aa2da9f7802e0053a0e672cb13bf27e2294d213 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 10 Jul 2021 23:59:36 +0530 Subject: [PATCH 025/135] added templates for issues --- .github/ISSUE_TEMPLATE/documentation.md | 16 ++++++++++++++++ .github/ISSUE_TEMPLATE/feature.md | 16 ++++++++++++++++ .../help-and-asking-questions.md | 19 +++++++++++++++++++ .github/ISSUE_TEMPLATE/miscellaneous.md | 16 ++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/documentation.md create mode 100644 .github/ISSUE_TEMPLATE/feature.md create mode 100644 .github/ISSUE_TEMPLATE/help-and-asking-questions.md create mode 100644 .github/ISSUE_TEMPLATE/miscellaneous.md diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 000000000..9d1c06cf1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,16 @@ +--- +name: Documentation +about: If your issue is related to creating new or fixing the existing documentation. +title: '' +labels: '' +assignees: joeyouss + +--- + +### Description +(Describe in detail what you want to work on) + +### Additional Comments (if any) +### Have you read the [Contributing Guidelines on Pull Requests]? + +(Write your answer here.) diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 000000000..e16796ac3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,16 @@ +--- +name: Feature +about: If your issue suggests/proposes new features which improve howdoi +title: '' +labels: '' +assignees: '' + +--- + +### Description +(Describe in detail what you want to work on) + +### Additional Comments (if any) +### Have you read the Contributing Guidelines on Pull Requests on mkdocs? + +(Write your answer here.) diff --git a/.github/ISSUE_TEMPLATE/help-and-asking-questions.md b/.github/ISSUE_TEMPLATE/help-and-asking-questions.md new file mode 100644 index 000000000..7b6aa374f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/help-and-asking-questions.md @@ -0,0 +1,19 @@ +--- +name: Help and asking questions +about: If you are stuck and want to ask the howdoi maintainers for help +title: '' +labels: '' +assignees: '' + +--- + +### Description +(Describe in detail what you are working on) + +### Help wanted for +(Describe what help you need and what are the problems you are facing currently) + +### Additional Comments (if any) +### Have you read the Contributing Guidelines on Pull Requests on mkdocs? + +(Write your answer here.) diff --git a/.github/ISSUE_TEMPLATE/miscellaneous.md b/.github/ISSUE_TEMPLATE/miscellaneous.md new file mode 100644 index 000000000..6457d21d0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/miscellaneous.md @@ -0,0 +1,16 @@ +--- +name: Miscellaneous +about: If your issue does not fit in other listed categories. +title: '' +labels: '' +assignees: '' + +--- + +### Description +(Describe in detail what your issue is related to) + +### Additional Comments (if any) +### Have you read the Contributing Guidelines on Pull Requests on mkdocs? + +(Write your answer here.) From 42bfd380d86bfb6efc03e9103f5f8c5ede1f35d1 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Thu, 8 Jul 2021 10:29:33 -0700 Subject: [PATCH 026/135] Cleaner logic for how to select the search engine Add logging when there is a block error Add red formatting to error messages --- howdoi/howdoi.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 155ccda3e..ba842cd28 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -274,6 +274,7 @@ def _get_links(query): try: result = _get_result(search_url) except requests.HTTPError: + logging.info('Received HTTPError') result = None if not result or _is_blocked(result): logging.error('%sUnable to find an answer because the search engine temporarily blocked the request. ' @@ -475,7 +476,7 @@ def _is_help_query(query): def _format_answers(args, res): if "error" in res: - return res["error"] + return f'ERROR: {RED}{res["error"]}{END_FORMAT}' if args["json_output"]: return json.dumps(res) @@ -588,13 +589,13 @@ def howdoi(raw_query): else: args = raw_query - if args['search_engine'] != 'google': - os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] - else: - if 'HOWDOI_SEARCH_ENGINE' in os.environ.keys() and os.environ['HOWDOI_SEARCH_ENGINE'] != 'google': - args['search_engine'] = os.environ['HOWDOI_SEARCH_ENGINE'] - else: - os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] + os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] or os.getenv('HOWDOI_SEARCH_ENGINE') or 'google' + search_engine = os.getenv('HOWDOI_SEARCH_ENGINE') + if search_engine not in SUPPORTED_SEARCH_ENGINES: + supported_search_engines = ', '.join(SUPPORTED_SEARCH_ENGINES) + message = f'Unsupported engine {search_engine}. The supported engines are: {supported_search_engines}' + res = {'error': message} + return _parse_cmd(args, res) args['query'] = ' '.join(args['query']).replace('?', '') cache_key = _get_cache_key(args) @@ -653,7 +654,7 @@ def get_parser(): parser.add_argument('-v', '--version', help='displays the current version of howdoi', action='store_true') parser.add_argument('-e', '--engine', help='search engine for this query (google, bing, duckduckgo)', - dest='search_engine', nargs="?", default='google', metavar='ENGINE') + dest='search_engine', nargs="?", metavar='ENGINE') parser.add_argument('--save', '--stash', help='stash a howdoi answer', action='store_true') parser.add_argument('--view', help='view your stash', @@ -784,10 +785,6 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man if os.getenv('HOWDOI_COLORIZE'): args['color'] = True - if not args['search_engine'] in SUPPORTED_SEARCH_ENGINES: - logging.error('Unsupported engine.\nThe supported engines are: %s' ', '.join(SUPPORTED_SEARCH_ENGINES)) - return - utf8_result = howdoi(args).encode('utf-8', 'ignore') if sys.version < '3': print(utf8_result) From dfd5a25f984d8cb52e1fa728ec38056abb179e7f Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Mon, 12 Jul 2021 22:39:03 +0500 Subject: [PATCH 027/135] Comment out DDG test Comment out DDG test for nose test for PR to pass. Enable this when issue #404 is resolved --- test_howdoi.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/test_howdoi.py b/test_howdoi.py index 4e8d5014c..63c7afd3c 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -111,18 +111,20 @@ def test_answers_bing(self): os.environ['HOWDOI_SEARCH_ENGINE'] = '' - def test_answers_duckduckgo(self): - os.environ['HOWDOI_SEARCH_ENGINE'] = 'duckduckgo' - for query in self.queries: - self.assertValidResponse(howdoi.howdoi(query)) - for query in self.bad_queries: - self.assertValidResponse(howdoi.howdoi(query)) + # commenting out duckduckgo test, re-enable when issue #404 (duckduckgo blocking requests) is resolved - os.environ['HOWDOI_URL'] = 'pt.stackoverflow.com' - for query in self.pt_queries: - self.assertValidResponse(howdoi.howdoi(query)) + # def test_answers_duckduckgo(self): + # os.environ['HOWDOI_SEARCH_ENGINE'] = 'duckduckgo' + # for query in self.queries: + # self.assertValidResponse(howdoi.howdoi(query)) + # for query in self.bad_queries: + # self.assertValidResponse(howdoi.howdoi(query)) - os.environ['HOWDOI_SEARCH_ENGINE'] = '' + # os.environ['HOWDOI_URL'] = 'pt.stackoverflow.com' + # for query in self.pt_queries: + # self.assertValidResponse(howdoi.howdoi(query)) + + # os.environ['HOWDOI_SEARCH_ENGINE'] = '' def test_answer_links_using_l_option(self): for query in self.queries: From 87263a91a1ffb6c0851519dfcedaf4070b786221 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Mon, 19 Jul 2021 18:30:11 +0500 Subject: [PATCH 028/135] Update howdoi.py --- howdoi/howdoi.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index ba842cd28..25421d190 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -104,6 +104,8 @@ STASH_REMOVE = 'remove' STASH_EMPTY = 'empty' +BLOCKED_ENGINES = [] + if os.getenv('HOWDOI_DISABLE_CACHE'): # works like an always empty cache cache = NullCache() @@ -621,7 +623,16 @@ def howdoi(raw_query): cache.set(cache_key, res) except (RequestsConnectionError, SSLError): res = {'error': f'Unable to reach {args["search_engine"]}. Do you need to use a proxy?\n'} - + except BlockError: + BLOCKED_ENGINES.append(args['search_engine']) + if BLOCKED_ENGINES == SUPPORTED_SEARCH_ENGINES: + return + for eng in SUPPORTED_SEARCH_ENGINES: + if eng not in BLOCKED_ENGINES: + logging.error('%sRetrying search with %s%s', GREEN, eng, END_FORMAT) + args['search_engine'] = eng + break + return howdoi(args) return _parse_cmd(args, res) From cf63a5da2006ef2fb19cafdbeb656704de12f924 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Mon, 19 Jul 2021 18:41:30 +0500 Subject: [PATCH 029/135] pylint fix --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 25421d190..6b3661b7f 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -626,7 +626,7 @@ def howdoi(raw_query): except BlockError: BLOCKED_ENGINES.append(args['search_engine']) if BLOCKED_ENGINES == SUPPORTED_SEARCH_ENGINES: - return + return howdoi(args) for eng in SUPPORTED_SEARCH_ENGINES: if eng not in BLOCKED_ENGINES: logging.error('%sRetrying search with %s%s', GREEN, eng, END_FORMAT) From 7c55e99807b7cfc40141fc56d12aaed12a567539 Mon Sep 17 00:00:00 2001 From: joe Date: Tue, 20 Jul 2021 01:12:45 +0530 Subject: [PATCH 030/135] Changing mkdocs Changed each page of mkdocs to make howdoi's documentation better --- docs/contributing_docs.md | 18 ++++++++++ docs/contributing_to_howdoi.md | 42 ++++++++++++++++++++++ docs/development_env.md | 33 +++++++++++++++++ docs/extension_dev.md | 63 ++++++++++++++++++++++++++++++++ docs/howdoi_advanced_usage.md | 56 +++++++++++++++++++++++++++++ docs/installation.md | 22 ------------ docs/introduction.md | 25 +++++++++++++ docs/usage.md | 61 +++++++++++++++++++++++++++++++ docs/user-guide.md | 45 ----------------------- mkdocs.yml | 66 ++++++++++++++++++---------------- 10 files changed, 333 insertions(+), 98 deletions(-) create mode 100644 docs/contributing_docs.md create mode 100644 docs/contributing_to_howdoi.md create mode 100644 docs/development_env.md create mode 100644 docs/extension_dev.md create mode 100644 docs/howdoi_advanced_usage.md delete mode 100644 docs/installation.md create mode 100644 docs/introduction.md create mode 100644 docs/usage.md delete mode 100644 docs/user-guide.md diff --git a/docs/contributing_docs.md b/docs/contributing_docs.md new file mode 100644 index 000000000..74b83ae7b --- /dev/null +++ b/docs/contributing_docs.md @@ -0,0 +1,18 @@ +If you would like to improve the existing docs/ add new ideas in docs, you can do so by using mkdocs. Howdoi uses mkdocs to host its documentation. Steps to contribute to docs: + +- Every step from Contributing to howdoi remains the same with additional requirements of installing and building mkdocs. +- First, install mkdocs by running the following command: pip install mkdocs +- You can learn about mkdocs usage from mkdocs documentation. +- You can propose your documentation by creating a new issue. +- Once approved, you need to create your document and allow it to be reviewed by the project maintainers (this can be a simple word document). +- Once the doc is ready to be published, you need to convert your text file into markdown format. +- Next, create a new branch and go to the folder howdoi/docs/ and add a .md file. +- Go to `mkdocs.yml` and add the name of your added .md file in `nav` +- To see the changes in your local server, go to your terminal and in this directory run : + +``` + $ mkdocs build + $ mkdocs serve +``` + +- Once done, make a PR for the same and wait for it to be reviewed. diff --git a/docs/contributing_to_howdoi.md b/docs/contributing_to_howdoi.md new file mode 100644 index 000000000..bdb5f5115 --- /dev/null +++ b/docs/contributing_to_howdoi.md @@ -0,0 +1,42 @@ +As beginners, navigating the codebase and finding your way out of the documentation can become difficult. This page will help you understand everything about contributing to howdoi and the best practices in open source as well. +You can either contribute code to Howdoi (explained on this page) or contribute documentation (explained on next page) + +#### 1- Setting up the development environment + +Follow the page "setting up the development environment" for setting up the development environment for Howdoi. + +#### 2 - Finding your first issue + +- Go to issues in the howdoi repo (https://github.com/gleitz/howdoi) +- Find the issues which you might be interested to work on. Or, you can also come up with your own ideas of improving howdoi. +- After finding the issue you are interested in: + 1. If the issue is an existing one : comment on the issue and ask for it to be assigned to you. + 2. If the issue is unlisted and new : Create a new issue and fill every information needed in the issues template provided by howdoi and ask for it to be assigned to you. +- After receiving confirmation, start working on the issue and whenever and wherever help is needed, comment on the issue itself describing your query in detail. +- A good guide on how to collaborate efficiently can be found [here](https://lab.github.com/githubtraining/introduction-to-github). + +#### 3 - Making a Pull request (PR) + +- After you have worked on the issue and fixed it, we need to merge it from your forked repository into the howdoi repository. This is done by making a PR. +- You can search `howdoi create a pull request on Github` in your command line and follow the steps written in it. +- Each PR made should pass all the [Travis](https://travis-ci.org/gleitz/howdoi) tests and should not have any flake8 or pylint errors or warnings. Hence, testing and linting are important before making a PR. 1. Testing : Howdoi uses python’s unittest library for unit testing. You can run the tests locally by the following commands: + `$ python -m test_howdoi` + To run specific tests: + `$ python -m unittest test_howdoi.TestClass.test_method` + + 2. Linting : Howdoi uses vanilla configuration files for both linters (.flake8rc and .pylintrc in the root directory), but with a max line length of 119 characters. To run linting locally with flake8: + + `$ flake8` + For pylint : + `$ pylint *` + +- Once your commit passes all the tests, make a PR and wait for it to be reviewed and merged. + +#### 4 - Asking for help + +At times, help is needed while solving the issue. We recommend the following step for asking for help when you get stuck: + +1. Read from howdoi docs and howdoi github to see if your answer has already been answered. +2. Comment on the issue you are working describing in detail what problems you are facing. +3. Make sure to write your query in detail and if it is bug, include steps to reproduce it. +4. If you are not working on any issue and have a question to be answered, open a new issue on Github and wait for a reply on it.4 diff --git a/docs/development_env.md b/docs/development_env.md new file mode 100644 index 000000000..9b7a18bbc --- /dev/null +++ b/docs/development_env.md @@ -0,0 +1,33 @@ +1. Clone the Howdoi repository: + `$ git clone https://github.com/gleitz/howdoi.git` +2. To see how to set up the development for Windows, see [here](http://gleitz.github.io/howdoi/windows-contributing/). +3. Setup and activate a virtual environment + `$ python3 -m venv .venv` + `$ source .venv/bin/activate` +4. Install all the required packages + `$ pip install -r requirements.txt` +5. Run howdoi +6. Running from command line : + `python -m howdoi QUERY` +7. Running from a python script : Go to your script in howdoi.howdoi() and pass your query in the argument. + +``` +from howdoi import howdoi +query = "for loop python" +output = howdoi.howdoi(query) +``` + +Or , parse it yourself and then pass the arguments: + +``` +from howdoi import howdoi +query = "for loop python" +parser = howdoi.get_parser() +args = vars(parser.parse_args(query.split(' '))) +output = howdoi.howdoi(args) +``` + +#### Notes : + +- **Parsing queries yourself is the older way to pass in queries and may be deprecated in the future. Prefer the first example.** +- **If you try running python howdoi/howdoi.py (without -m) you might get ValueError: Attempted relative import in non-package.** diff --git a/docs/extension_dev.md b/docs/extension_dev.md new file mode 100644 index 000000000..4a545afb4 --- /dev/null +++ b/docs/extension_dev.md @@ -0,0 +1,63 @@ +## Extension development + +You can integrate howdoi as a code editor extension. For this, you need to edit the files within the `extension/code-editor-integration` folder. +To improve the Visual Studio Code howdoi extension, edit the files within the extension/vscode-ext folder and republish the extension. + +#### How to integrate howdoi as a code editor extension? + +1. The Code Editor Integration plug-in runs when you call + ` runHowdoi` function which takes in a user’s query(type = string). The parameter is encapsulated by a single line comment and is formatted as : `// howdoi query` + + `runHowdoi` function returns and Object which looks like : + +``` +{ +Question: string +Answer : string[] +Link : string[] +} +``` + +2. What are these object values? + +- question = it contains the user’s query encapsulated by a single line comment +- answer : contains the three possible answers to the user’s query. +- link : link contains the three possible links to the answer encapsulated by a single line comment + +3. To start with development, you need to first install howdoi on your machine. Steps to do that lie here. + +#### Development + +Next, install all important packages by running `npm install` + +- To compile the script, run `npm run compile` +- To run the script , run `npm start` +- To compile and run the script, run `npm run build` +- To run the testing script, run `npm test` +- Now, to utilize the plug-in to create a howdoi extension, you need to do the following + +#### Integration + +To use the plug-in to create a howdoi extension, follow these steps: + +- Copy the `code-editor-integration` folder in your workspace and remove `node-modules` folder. You can do this by adding the script in your `package.json` file and running it. But, first you will need to install ncp and rimraf.: + +``` +"copy": "ncp ../code-editor-integration/ src/code-editor-integration/" +"clean": "rimraf ./src/code-editor-integration/node_modules" +``` + +- Import the `plugin.ts` file into your main file. +- Call the `runHowdoi` function. + +#### Visual Code Extension development + +To begin the development for Visual Studio Code extension, install all the necessary packages: + +`Npm install` + +Then precompile the extension : + +`Npm run precompile` + +To run and test extension, utilize the Visual Studio Code’s debugging tools. diff --git a/docs/howdoi_advanced_usage.md b/docs/howdoi_advanced_usage.md new file mode 100644 index 000000000..b73def255 --- /dev/null +++ b/docs/howdoi_advanced_usage.md @@ -0,0 +1,56 @@ +- **Howdoi stashing feature** - We agree that sometimes you need to need search results for later and running the same query again and again + won’t be that feasible. Hence, Howdoi has a stashing feature which allows you to save your query, view the query, delete the saved + results and even empty the entire stash ! (see keep documentation for more information on stashing). Here is how you can do this: + + - **stashing: howdoi --save QUERY** **viewing: howdoi --view** + - **removing: howdoi --remove (will be prompted which answer to delete)** + - **emptying: howdoi --empty (empties entire stash, will be prompted to confirm)** + +- **Shortcuts for your parameters** - You might run the same parameters many times and again, typing them isn’t always the best option. You can use shortcuts for your parameters by using something like: + + ``` + $ alias h='function hdi(){ howdoi $* -c -n 5; }; hdi' + ``` + + And the in your command line, replace your parameters with your alias i.e. h: + + ``` + $ h format date bash + ``` + +- **Other uses and aliases** - You can also search other StackExchange properties for answers. + + Example: + + ``` + $ HOWDOI_URL=cooking.stackexchange.com + ``` + + ``` + $ howdoi make pesto + ``` + + Or use an alias for the same : + + ``` + $ alias hcook='function hcook(){ HOWDOI_URL=cooking.stackexchange.com howdoi $* ; }; hcook' + ``` + + ``` + $ hcook make pesto + ``` + +- **Setting up environment variables** - Howdoi uses some environment variables which can be configured by the user as per his/her choice. + The following are the environment variables and their usage : + + - HOWDOI_COLORIZE=1 - Colorizes the output produced. + - HOWDOI_DISABLE_CACHE=1 - Disables the Caching functionality. + Howdoi uses a cache for faster access to previous questions. The + cache is stored in ~/.cache/howdoi. + - HOWDOI_DISABLE_SSL=1 - Disables the SSL certificate. + - HOWDOI_SEARCH_ENGINE=google - Changes the search engine to your + preference (default: google, also supported: bing, duckduckgo). + The -e flag will switch the underlying engine for a single query. + - HOWDOI_URL=serverfault.com - Changes the source url for answers + (default: stackoverflow.com, also supported: serverfault.com, + pt.stackoverflow.com, full list). diff --git a/docs/installation.md b/docs/installation.md deleted file mode 100644 index c224246df..000000000 --- a/docs/installation.md +++ /dev/null @@ -1,22 +0,0 @@ -### How can I install howdoi? - -To install howdoi the most straight forward method is through [pip](https://pip.pypa.io/en/stable/). If you already have pip installed you can simply run: - -`` -pip install howdoi -`` - -or - -`` -pip install git+https://github.com/gleitz/howdoi.git#egg=howdoi -`` - -!!! Note - Don't have pip installed yet? [Follow this simple tutorial to get started](https://pip.pypa.io/en/stable/installing/) - -If you want to use [setuptools]() to install howdoi you can do so like this: - -`` -python setup.py install -`` \ No newline at end of file diff --git a/docs/introduction.md b/docs/introduction.md new file mode 100644 index 000000000..e3fb7ec89 --- /dev/null +++ b/docs/introduction.md @@ -0,0 +1,25 @@ +Howdoi is an open source command line tool which gives answers to your questions in the command line itself. Howdoi can be used by anyone and everyone who finds themselves Googling for answers to their basic programming questions. + +Example - `howdoi print hello in python` +Answer - `print(“hello”)` + +### Installation : + +To install Howdoi, these two requirements must be fulfilled: + +- Pip should be installed in your local system. +- Python 3.5 or above installed since Python 2.7 support is discontinued. + +To install Howdoi, simply run : + +`pip install howdoi` + +Or + +`pip install git+https://github.com/gleitz/howdoi.git#egg=howdoi` + +> Don't have pip installed yet? [Follow this simple tutorial to get started](https://pip.pypa.io/en/stable/installing/) + +If you want to use [setuptools]() to install howdoi you can do so like this: + +`python setup.py install` diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 000000000..0d84ca132 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,61 @@ +To begin with howdoi, after installing howdoi, enter the following command: + +``` +$ howdoi howdoi +``` + +This will provide with every information you need about working with howdoi and every command/argument that is present in howdoi. For further information about every flag and environment variables type : + +``` +$ howdoi -h +``` + +#### Howdoi flags/arguments. + +Howdoi comes with a set of predefined flags/arguments which can be set by you as per your choice. You can just type `howdoi -h` in your command line to see each argument and what they do. + +**Syntax** : `howdoi [flag/argument] QUERY` + +The available arguments currently are listed below: + +**- h, --help** : To see the help message which has all the information about every command + +**-p POS, --pos POS** : To select answer in any specified position. + +**-n NUM, --num NUM** : Defines the number of answers to return. By default, set to 1. + +**-a, --all**: Shows the full text of an answer + +**-l, --link**: Displays only the link of the answer + +**-j** : Displays the answer in JSON format. Useful when you are building on top of howdoi. + +**-c, --color**: Prints colorized output + +**-x, --explain**: Explains why the outputted answer was shown to you + +**-C, --clear-cache**: Clears the cache + +**-j, --json** : Outputs the answer in raw JSON format + +**-v, --version**: Displays your current version of howdoi. + +**-e [ENGINE], --engine [ENGINE]** : Allows to choose the search engine for the query. Currently supported - google, bing, duckduckgo + +**--save, --stash** : Enables stashing feature for a howdoi answer + +**--view** : Displayed the stash + +**--remove** : Removes an entry in your stash + +**--empty** : Empties the stash completely + +#### Howdoi Environment variables + +Howdoi enables the users to put the environment variables of their choice, the currently supported environment variables are : + +- **HOWDOI_COLORIZE** : Colorizes the output by default. +- **HOWDOI_SEARCH_ENGINE** : changes the default search engine for StackOverflow links. By default the search engine is google but other supported are : bing, duckduckgo. +- **HOWDOI_URL** : Changes the source url for answers. By default set to : stackoverflow.com. Currently supported here. +- **HOWDOI_DISABLE_CACHE** : Howdoi uses cache for faster access to previously searched questions. If this environment variable is set, the caching functionality will be set. The cache resides in ~/cache/howdoi/. +- **HOWDOI_DISABLE_SSL** : Allows you to disable SSL. diff --git a/docs/user-guide.md b/docs/user-guide.md deleted file mode 100644 index 622972cc1..000000000 --- a/docs/user-guide.md +++ /dev/null @@ -1,45 +0,0 @@ -## Usage - -If it's your first time using howdoi, run the quick help - -```bash -$ howdoi howdoi -``` - - -Print the help manual -```bash -$ howdoi # "howdoi -h" also prints help - -usage: howdoi [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-x] [-C] [-j] [-v] [-e [ENGINE]] [--save] [--view] [--remove] [--empty] [QUERY ...] - -instant coding answers via the command line - -positional arguments: - QUERY the question to answer - -optional arguments: - -h, --help show this help message and exit - -p POS, --pos POS select answer in specified position (default: 1) - -n NUM, --num NUM number of answers to return (default: 1) - -a, --all display the full text of the answer - -l, --link display only the answer link - -c, --color enable colorized output - -x, --explain explain how answer was chosen - -C, --clear-cache clear the cache - -j, --json return answers in raw json format - -v, --version displays the current version of howdoi - -e [ENGINE], --engine [ENGINE] - search engine for this query (google, bing, duckduckgo) - --save, --stash stash a howdoi answer - --view view your stash - --remove remove an entry in your stash - --empty empty your stash - -environment variable examples: - HOWDOI_COLORIZE=1 - HOWDOI_DISABLE_CACHE=1 - HOWDOI_DISABLE_SSL=1 - HOWDOI_SEARCH_ENGINE=google - HOWDOI_URL=serverfault.com -``` diff --git a/mkdocs.yml b/mkdocs.yml index 801e9cc7f..38ef13829 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,43 +1,47 @@ site_name: howdoi theme: - name: 'material' - palette: - primary: '' - accent: 'teal' - icon: - repo: fontawesome/brands/github + name: "material" + palette: + primary: "" + accent: "teal" + icon: + repo: fontawesome/brands/github repo_name: gleitz/howdoi repo_url: https://github.com/gleitz/howdoi -edit_uri: '' +edit_uri: "" nav: - - howdoi: index.md - - Installation: installation.md - - "User Guide": user-guide.md - - Contributing: contributing.md - - Troubleshooting: troubleshooting.md - - Development for Windows: windows-contributing.md + - howdoi: index.md + - Introduction: introduction.md + - Usage: usage.md + - Setting up development environment: development_env.md + - Contributing: contributing_to_howdoi.md + - Contributing documentation: contributing_docs.md + - Extension development: extension_dev.md + - howdoi advanced usage: howdoi_advanced_usage.md + - Troubleshooting: troubleshooting.md + - Development for Windows: windows-contributing.md markdown_extensions: - - toc: - permalink: true - - markdown.extensions.codehilite: - guess_lang: false - - admonition - - codehilite - - extra - - pymdownx.snippets: - base_path: docs - - pymdownx.superfences: - custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:pymdownx.superfences.fence_div_format - - pymdownx.tabbed + - toc: + permalink: true + - markdown.extensions.codehilite: + guess_lang: false + - admonition + - codehilite + - extra + - pymdownx.snippets: + base_path: docs + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_div_format + - pymdownx.tabbed extra: - social: - - icon: fontawesome/brands/github - link: 'https://github.com/gleitz/howdoi' + social: + - icon: fontawesome/brands/github + link: "https://github.com/gleitz/howdoi" From 2e5cca26a346cea28670417a04d1f5645b34d489 Mon Sep 17 00:00:00 2001 From: joe Date: Tue, 20 Jul 2021 01:20:05 +0530 Subject: [PATCH 031/135] Updated Readme Updated Readme for moving all of the important documentation to mkdocs --- README.rst | 102 ++++++++--------------------------------------------- 1 file changed, 14 insertions(+), 88 deletions(-) diff --git a/README.rst b/README.rst index 9bc815f4a..738046e1c 100644 --- a/README.rst +++ b/README.rst @@ -75,15 +75,7 @@ Installation or -:: - - pip install git+https://github.com/gleitz/howdoi.git#egg=howdoi - -or - -:: - - python setup.py install +Check out howdoi docs for more ways of installation. New to howdoi? -------------- @@ -182,6 +174,19 @@ Contributors - Shantanu Verma (`@SaurusXI `_) - And `more! `_ +HOW TO CONTRIBUTE +----------------- + +We welcome contributions that make Howdoi better and/or improve the existing functionalities of the project. We have created a separate +guide to contributing to howdoi which resides in the howdoi documentation in mkdcos. +The guide contains the following: + +- Introduction for first time contributors +- Getting started with howdoi +- Making PRs and testing +- Asking for help +- Helpful tips for a good contribution experience. + Notes ----- @@ -191,81 +196,9 @@ Notes - An Alfred Workflow for howdoi can be found at `http://blog.gleitzman.com/post/48539944559/howdoi-alfred-even-more-instant-answers `_. - Slack integration available through `slack-howdoi `_. - Telegram integration available through `howdoi-telegram `_. -- Howdoi uses a cache for faster access to previous questions. Caching functionality can be disabled by setting the HOWDOI_DISABLE_CACHE environment variable. The cache is stored in `~/.cache/howdoi`. -- You can set the HOWDOI_URL environment variable to change the source url for answers (default: `stackoverflow.com`, also supported: `serverfault.com`, `pt.stackoverflow.com`, `full list `_). -- You can set the HOWDOI_SEARCH_ENGINE environment variable to change the underlying search engine for StackOverflow links (default: `google`, also supported: `bing`, `duckduckgo`). The -e flag will switch the underlying engine for a single query. -- Setting the HOWDOI_COLORIZE environment variable will colorize the output by default. - Special thanks to Rich Jones (`@miserlou `_) for the idea. - More thanks to `Ben Bronstein `_ for the logo. -Development ------------ - -- Checkout the repo -- Run ``python -m howdoi QUERY`` (if you try running ``python howdoi/howdoi.py`` you might get ``ValueError: Attempted relative import in non-package``). -- When you're ready to open a PR be sure to run ``python setup.py lint`` to make sure your code passes the checks. - -If you would like to use howdoi from within a python script, just pass your query to `howdoi.howdoi()`: -:: - - from howdoi import howdoi - - query = "for loop python" - output = howdoi.howdoi(query) - - -Or parse it yourself (either work): - -:: - - from howdoi import howdoi - - query = "for loop python" - parser = howdoi.get_parser() - args = vars(parser.parse_args(query.split(' '))) - - output = howdoi.howdoi(args) - -Or get the results as JSON: - -:: - - from howdoi import howdoi - import json - - query = "for loop python" - - output_json = json.loads(howdoi.howdoi(f'{query} -j')) - -Extension Development ---------------------- - -To simplify the process of integrating howdoi as a code editor extension, edit the files within the `extension/code-editor-integration folder `_. - -To improve upon the Visual Studio Code howdoi extension, edit the files within the `extension/vscode-ext folder `_ and republish the extension. - -Code Editor Integration -~~~~~~~~~~~~~~~~~~~~~~~ - -Head over to the `README.md `_ for an in depth explanation on beginning development for the howdoi code editor integration plug-in. - -Visual Studio Code Extension -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To begin development for the Visual Studio Code extension, install all necessary packages: - -:: - - npm install - -Then, precompile the extension: - -:: - - npm run precompile - -To run and test the extension, utilize Visual Studio Code's `debugging tools `_. - Visual Studio Code Extension Installation ----------------------------------------- @@ -278,10 +211,3 @@ howdoi can now be installed as an extension on Visual Studio Code! There are two 2. Directly from the packaged extension: - Head over `here `_ to locally install the howdoi Visual Studio Code package. - -Contributing ------------- - -I'm happy to accept pull requests that make howdoi better. If you're thinking of contributing and want a little feedback before you jump into the codebase, post an `issue `_ on Github. - -Before PRs are accepted they must pass all `tests `_ and not have any flake8 or pylint warnings or errors. This projects uses vanilla configuration files for both linters (``.flake8rc`` and ``.pylintrc`` in the root directory), but with a max line length of 119. From 1a843a88919caf36f76d4ce812cb24ed654de568 Mon Sep 17 00:00:00 2001 From: joe Date: Tue, 20 Jul 2021 14:03:48 +0530 Subject: [PATCH 032/135] Fixed development env page on mkdocs --- docs/development_env.md | 42 +++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/development_env.md b/docs/development_env.md index 9b7a18bbc..568ea4201 100644 --- a/docs/development_env.md +++ b/docs/development_env.md @@ -1,15 +1,33 @@ -1. Clone the Howdoi repository: - `$ git clone https://github.com/gleitz/howdoi.git` -2. To see how to set up the development for Windows, see [here](http://gleitz.github.io/howdoi/windows-contributing/). -3. Setup and activate a virtual environment - `$ python3 -m venv .venv` - `$ source .venv/bin/activate` -4. Install all the required packages - `$ pip install -r requirements.txt` -5. Run howdoi -6. Running from command line : - `python -m howdoi QUERY` -7. Running from a python script : Go to your script in howdoi.howdoi() and pass your query in the argument. +- Clone the Howdoi repository: + + ``` + $ git clone https://github.com/gleitz/howdoi.git + ``` + +- To see how to set up the development for Windows, see [here](http://gleitz.github.io/howdoi/windows-contributing/). + +- Setup and activate a virtual environment + + ``` + $ python3 -m venv .venv + $ source .venv/bin/activate + ``` + +- Install all the required packages + + ``` + $ pip install -r requirements.txt + ``` + +- Run howdoi + +- Running from command line : + + ``` + $ python -m howdoi QUERY + ``` + +- Running from a python script : Go to your script in howdoi.howdoi() and pass your query in the argument. ``` from howdoi import howdoi From 727fae06d86a236489ba030e1bbad508164d6492 Mon Sep 17 00:00:00 2001 From: joe Date: Tue, 20 Jul 2021 14:05:31 +0530 Subject: [PATCH 033/135] Fixed introduction page on mkdocs --- docs/introduction.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/introduction.md b/docs/introduction.md index e3fb7ec89..1a6430055 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -1,7 +1,16 @@ Howdoi is an open source command line tool which gives answers to your questions in the command line itself. Howdoi can be used by anyone and everyone who finds themselves Googling for answers to their basic programming questions. -Example - `howdoi print hello in python` -Answer - `print(“hello”)` +Example - + +``` +howdoi print hello in python +``` + +Answer - + +``` +print(“hello”) +``` ### Installation : From dbe20a95bbf821fe567819d632d60102119ba401 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Tue, 20 Jul 2021 15:56:32 +0500 Subject: [PATCH 034/135] BlockError fallbacks updated --- howdoi/howdoi.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 6b3661b7f..b3e0b75ec 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -585,11 +585,9 @@ def _parse_cmd(args, res): def howdoi(raw_query): - if isinstance(raw_query, str): # you can pass either a raw or a parsed query - parser = get_parser() - args = vars(parser.parse_args(raw_query.split(' '))) - else: - args = raw_query + if isinstance(raw_query['query'], str): # you can pass either a raw or a parsed query + raw_query['query'] = raw_query['query'].split(' ') + args = raw_query os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] or os.getenv('HOWDOI_SEARCH_ENGINE') or 'google' search_engine = os.getenv('HOWDOI_SEARCH_ENGINE') @@ -625,14 +623,13 @@ def howdoi(raw_query): res = {'error': f'Unable to reach {args["search_engine"]}. Do you need to use a proxy?\n'} except BlockError: BLOCKED_ENGINES.append(args['search_engine']) - if BLOCKED_ENGINES == SUPPORTED_SEARCH_ENGINES: + next_engine = next((engine for engine in SUPPORTED_SEARCH_ENGINES if engine not in BLOCKED_ENGINES), None) + if next_engine is None: + logging.info('%sAll search engines failed.%s', RED, END_FORMAT) + else: + args['search_engine'] = next_engine + logging.error('%sRetrying search with %s%s', GREEN, next_engine, END_FORMAT) return howdoi(args) - for eng in SUPPORTED_SEARCH_ENGINES: - if eng not in BLOCKED_ENGINES: - logging.error('%sRetrying search with %s%s', GREEN, eng, END_FORMAT) - args['search_engine'] = eng - break - return howdoi(args) return _parse_cmd(args, res) From 1af3d741ad683bb92ddbc50ed61a5b7ad9324f6f Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Tue, 20 Jul 2021 15:57:59 +0500 Subject: [PATCH 035/135] Trim trailing whitespaces --- howdoi/howdoi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index b3e0b75ec..b09120ad1 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -623,12 +623,12 @@ def howdoi(raw_query): res = {'error': f'Unable to reach {args["search_engine"]}. Do you need to use a proxy?\n'} except BlockError: BLOCKED_ENGINES.append(args['search_engine']) - next_engine = next((engine for engine in SUPPORTED_SEARCH_ENGINES if engine not in BLOCKED_ENGINES), None) - if next_engine is None: + next_engine = next((engine for engine in SUPPORTED_SEARCH_ENGINES if engine not in BLOCKED_ENGINES), None) + if next_engine is None: logging.info('%sAll search engines failed.%s', RED, END_FORMAT) - else: + else: args['search_engine'] = next_engine - logging.error('%sRetrying search with %s%s', GREEN, next_engine, END_FORMAT) + logging.error('%sRetrying search with %s%s', GREEN, next_engine, END_FORMAT) return howdoi(args) return _parse_cmd(args, res) From ca5afdd7e559b1a0882ead02ab0de622a1024261 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Tue, 20 Jul 2021 16:16:46 +0500 Subject: [PATCH 036/135] fix nose test issue nose test throwing error that string is being indexed --- howdoi/howdoi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index b09120ad1..65a6efd25 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -586,7 +586,8 @@ def _parse_cmd(args, res): def howdoi(raw_query): if isinstance(raw_query['query'], str): # you can pass either a raw or a parsed query - raw_query['query'] = raw_query['query'].split(' ') + split_query = raw_query['query'].split(' ') + raw_query['query'] = split_query args = raw_query os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] or os.getenv('HOWDOI_SEARCH_ENGINE') or 'google' From f79e8875e17ff7ee2bbc0935775ed9b9f4501804 Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 21 Jul 2021 20:15:32 +0530 Subject: [PATCH 037/135] Update README.rst made the required changes and added links to documentation at top and wherever relevant. --- README.rst | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 738046e1c..7331c452c 100644 --- a/README.rst +++ b/README.rst @@ -23,6 +23,23 @@ Sherlock, your neighborhood command-line sloth sleuth. ---- + +`howdoi documentation `_ +~~~~~~~~~~~~~~~~~ + +- `Introduction to howdoi and installation `_ +- `Howdoi usage `_ +- `Setting up the development environment `_ +- `Contributing to howdoi `_ +- `Contributing documentation to howdoi `_ +- `Extension development `_ +- `howdoi advanced usage `_ +- `Troubleshooting `_ +- `Development environment for windows `_ + +INTRODUCTION TO HOWDOI +---------------------- + Are you a hack programmer? Do you find yourself constantly Googling for how to do basic programming tasks? @@ -75,7 +92,7 @@ Installation or -Check out howdoi docs for more ways of installation. +Check out howdoi docs for more ways of `installation `_ New to howdoi? -------------- @@ -177,8 +194,7 @@ Contributors HOW TO CONTRIBUTE ----------------- -We welcome contributions that make Howdoi better and/or improve the existing functionalities of the project. We have created a separate -guide to contributing to howdoi which resides in the howdoi documentation in mkdcos. +We welcome contributions that make Howdoi better and/or improve the existing functionalities of the project. We have created a separate `guide to contributing to howdoi `_ which resides in the howdoi documentation in mkdcos. The guide contains the following: - Introduction for first time contributors From 633c6dc78a9976a0de2b218a6c87f987a6b92a26 Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 21 Jul 2021 20:52:22 +0530 Subject: [PATCH 038/135] updated mkdocs fixed the problems in mkdcos --- docs/contributing_docs.md | 16 +++++++++------- docs/contributing_to_howdoi.md | 30 ++++++++++++------------------ 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/docs/contributing_docs.md b/docs/contributing_docs.md index 74b83ae7b..1a6d6b0f4 100644 --- a/docs/contributing_docs.md +++ b/docs/contributing_docs.md @@ -1,12 +1,14 @@ If you would like to improve the existing docs/ add new ideas in docs, you can do so by using mkdocs. Howdoi uses mkdocs to host its documentation. Steps to contribute to docs: -- Every step from Contributing to howdoi remains the same with additional requirements of installing and building mkdocs. -- First, install mkdocs by running the following command: pip install mkdocs -- You can learn about mkdocs usage from mkdocs documentation. -- You can propose your documentation by creating a new issue. -- Once approved, you need to create your document and allow it to be reviewed by the project maintainers (this can be a simple word document). -- Once the doc is ready to be published, you need to convert your text file into markdown format. -- Next, create a new branch and go to the folder howdoi/docs/ and add a .md file. +- Every step from [Contributing to howdoi](http://gleitz.github.io/howdoi/contributing_to_howdoi/) remains the same with additional requirements of installing and building mkdocs. +- First, install mkdocs by running the following command: + ``` + pip install mkdocs + ``` +- You can learn about mkdocs usage from [mkdocs documentation](https://www.mkdocs.org/user-guide/). +- You can propose your documentation by [creating a new issue](https://github.com/gleitz/howdoi/issues/new/choose). +- Once approved in the issue, you can create a PR with modifications to the mkdocs markdown. +- Next, create a new branch and go to the folder `howdoi/docs/` and add a .md file. - Go to `mkdocs.yml` and add the name of your added .md file in `nav` - To see the changes in your local server, go to your terminal and in this directory run : diff --git a/docs/contributing_to_howdoi.md b/docs/contributing_to_howdoi.md index bdb5f5115..6f3546286 100644 --- a/docs/contributing_to_howdoi.md +++ b/docs/contributing_to_howdoi.md @@ -3,32 +3,26 @@ You can either contribute code to Howdoi (explained on this page) or contribute #### 1- Setting up the development environment -Follow the page "setting up the development environment" for setting up the development environment for Howdoi. +Follow the page [Setting up the development environment](http://gleitz.github.io/howdoi/development_env/) for setting up the development environment for Howdoi. #### 2 - Finding your first issue -- Go to issues in the howdoi repo (https://github.com/gleitz/howdoi) +- Go to issues in the [howdoi repo](https://github.com/gleitz/howdoi). - Find the issues which you might be interested to work on. Or, you can also come up with your own ideas of improving howdoi. -- After finding the issue you are interested in: - 1. If the issue is an existing one : comment on the issue and ask for it to be assigned to you. - 2. If the issue is unlisted and new : Create a new issue and fill every information needed in the issues template provided by howdoi and ask for it to be assigned to you. +- After finding the issue you are interested in : If the issue is an existing one, comment on the issue and ask for it to be assigned to you. Or, if the issue is unlisted and new , create a new issue and fill every information needed in the issues template provided by howdoi and ask for it to be assigned to you. + - After receiving confirmation, start working on the issue and whenever and wherever help is needed, comment on the issue itself describing your query in detail. -- A good guide on how to collaborate efficiently can be found [here](https://lab.github.com/githubtraining/introduction-to-github). +- A good guide on how to collaborate efficiently can be found [here](https://lab.github.com/githubtraining/introduction-to-github){:target="\_blank"}. #### 3 - Making a Pull request (PR) - After you have worked on the issue and fixed it, we need to merge it from your forked repository into the howdoi repository. This is done by making a PR. -- You can search `howdoi create a pull request on Github` in your command line and follow the steps written in it. -- Each PR made should pass all the [Travis](https://travis-ci.org/gleitz/howdoi) tests and should not have any flake8 or pylint errors or warnings. Hence, testing and linting are important before making a PR. 1. Testing : Howdoi uses python’s unittest library for unit testing. You can run the tests locally by the following commands: - `$ python -m test_howdoi` - To run specific tests: - `$ python -m unittest test_howdoi.TestClass.test_method` - - 2. Linting : Howdoi uses vanilla configuration files for both linters (.flake8rc and .pylintrc in the root directory), but with a max line length of 119 characters. To run linting locally with flake8: - - `$ flake8` - For pylint : - `$ pylint *` +- You can search + ``` + howdoi create a pull request on Github + ``` + in your command line and follow the steps written in it. +- Each PR made should pass all the ) tests and should not have any flake8 or pylint errors or warnings. Hence, testing and linting are important before making a PR. You can now run `python setup.py` lint which will run pylint and flake8.: - Once your commit passes all the tests, make a PR and wait for it to be reviewed and merged. @@ -39,4 +33,4 @@ At times, help is needed while solving the issue. We recommend the following ste 1. Read from howdoi docs and howdoi github to see if your answer has already been answered. 2. Comment on the issue you are working describing in detail what problems you are facing. 3. Make sure to write your query in detail and if it is bug, include steps to reproduce it. -4. If you are not working on any issue and have a question to be answered, open a new issue on Github and wait for a reply on it.4 +4. If you are not working on any issue and have a question to be answered, open a new issue on Github and wait for a reply on it. From 5cb1c7db7a945791eaa8da6f4cea27438ff357b3 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Thu, 22 Jul 2021 12:38:44 +0500 Subject: [PATCH 039/135] Patch file for retries --- howdoi/howdoi.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 65a6efd25..b1b2a0ade 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -280,7 +280,7 @@ def _get_links(query): result = None if not result or _is_blocked(result): logging.error('%sUnable to find an answer because the search engine temporarily blocked the request. ' - 'Please wait a few minutes or select a different search engine.%s', RED, END_FORMAT) + 'Attempting to use a different search engine.%s', RED, END_FORMAT) raise BlockError('Temporary block by search engine') html = pq(result) @@ -585,10 +585,11 @@ def _parse_cmd(args, res): def howdoi(raw_query): - if isinstance(raw_query['query'], str): # you can pass either a raw or a parsed query - split_query = raw_query['query'].split(' ') - raw_query['query'] = split_query - args = raw_query + if isinstance(raw_query, str): # you can pass either a raw or a parsed query + parser = get_parser() + args = vars(parser.parse_args(raw_query.split(' '))) + else: + args = raw_query os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] or os.getenv('HOWDOI_SEARCH_ENGINE') or 'google' search_engine = os.getenv('HOWDOI_SEARCH_ENGINE') @@ -626,10 +627,11 @@ def howdoi(raw_query): BLOCKED_ENGINES.append(args['search_engine']) next_engine = next((engine for engine in SUPPORTED_SEARCH_ENGINES if engine not in BLOCKED_ENGINES), None) if next_engine is None: - logging.info('%sAll search engines failed.%s', RED, END_FORMAT) + res = {'error': 'Unable to get a response from any search engine\n'} else: args['search_engine'] = next_engine - logging.error('%sRetrying search with %s%s', GREEN, next_engine, END_FORMAT) + args['query'] = args['query'].split() + logging.info('%sRetrying search with %s%s', GREEN, next_engine, END_FORMAT) return howdoi(args) return _parse_cmd(args, res) From 376d52bcba10494959a93be4acab2eb81a1c0f00 Mon Sep 17 00:00:00 2001 From: Hongkuan Wang Date: Thu, 22 Jul 2021 17:42:32 +0800 Subject: [PATCH 040/135] fix a bug --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index ba842cd28..24a2ef56a 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -339,7 +339,7 @@ def _get_questions(links): def _get_answer(args, link): # pylint: disable=too-many-branches cache_key = _get_cache_key(link) - page = cache.get(link) # pylint: disable=assignment-from-none + page = cache.get(cache_key) # pylint: disable=assignment-from-none if not page: logging.info('Fetching page: %s', link) page = _get_result(link + '?answertab=votes') From c0bc20854405db13067c56a2f53de019e90d1d49 Mon Sep 17 00:00:00 2001 From: joe Date: Fri, 23 Jul 2021 21:18:34 +0530 Subject: [PATCH 041/135] Updated mkdocs fixed strange wording in mkdocs --- docs/contributing_to_howdoi.md | 2 +- howdoi/howdoi.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/contributing_to_howdoi.md b/docs/contributing_to_howdoi.md index 6f3546286..e72f3ccc8 100644 --- a/docs/contributing_to_howdoi.md +++ b/docs/contributing_to_howdoi.md @@ -22,7 +22,7 @@ Follow the page [Setting up the development environment](http://gleitz.github.io howdoi create a pull request on Github ``` in your command line and follow the steps written in it. -- Each PR made should pass all the ) tests and should not have any flake8 or pylint errors or warnings. Hence, testing and linting are important before making a PR. You can now run `python setup.py` lint which will run pylint and flake8.: +- Each PR made should pass all the tests and should not have any flake8 or pylint errors. Github runs tests on each PR but we before that, you should run `python setup.py` lint which will run pylint and flake8. - Once your commit passes all the tests, make a PR and wait for it to be reviewed and merged. diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index ba842cd28..44d1682fd 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -583,6 +583,7 @@ def _parse_cmd(args, res): def howdoi(raw_query): + # print("checking") if isinstance(raw_query, str): # you can pass either a raw or a parsed query parser = get_parser() args = vars(parser.parse_args(raw_query.split(' '))) From cdd62e159f5038ccce11f1144a03d0ecd09ef327 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Fri, 23 Jul 2021 20:53:00 +0500 Subject: [PATCH 042/135] Add test for Blockerror handling --- test_howdoi.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test_howdoi.py b/test_howdoi.py index 63c7afd3c..a97a21999 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -47,6 +47,10 @@ def _high_positive_position_query(self): query = self.queries[0] howdoi.howdoi(query + ' -p 40') + def _get_links_blockerror(self, query): + # print("raising error") + raise howdoi.BlockError + def setUp(self): self.original_get_result = howdoi._get_result howdoi._get_result = self._get_result_mock @@ -279,6 +283,11 @@ def test_negative_and_high_positive_int_values_rejected(self): with self.assertRaises(SystemExit): self._high_positive_number_query() + def test_sample(self): + query = self.queries[0] + howdoi._get_links = self._get_links_blockerror + response = howdoi.howdoi(query) + self.assertEqual(response,"ERROR: \x1b[91mUnable to get a response from any search engine\n\x1b[0m") class HowdoiTestCaseEnvProxies(unittest.TestCase): From e5fa2ea9eaae3fa787f74dc1fa80e7e7a1fa26c2 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Fri, 23 Jul 2021 20:54:27 +0500 Subject: [PATCH 043/135] flake8 fix --- test_howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_howdoi.py b/test_howdoi.py index a97a21999..892696036 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -287,7 +287,7 @@ def test_sample(self): query = self.queries[0] howdoi._get_links = self._get_links_blockerror response = howdoi.howdoi(query) - self.assertEqual(response,"ERROR: \x1b[91mUnable to get a response from any search engine\n\x1b[0m") + self.assertEqual(response, "ERROR: \x1b[91mUnable to get a response from any search engine\n\x1b[0m") class HowdoiTestCaseEnvProxies(unittest.TestCase): From ee2c9d78434b57e5c4069076a99ed558245ec131 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Fri, 23 Jul 2021 20:57:38 +0500 Subject: [PATCH 044/135] Update test_howdoi.py --- test_howdoi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test_howdoi.py b/test_howdoi.py index 892696036..1501cb338 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -289,6 +289,7 @@ def test_sample(self): response = howdoi.howdoi(query) self.assertEqual(response, "ERROR: \x1b[91mUnable to get a response from any search engine\n\x1b[0m") + class HowdoiTestCaseEnvProxies(unittest.TestCase): def setUp(self): From 10da09d9a8c6b3bcbbe9d9bb4083ee81d918e71f Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Fri, 23 Jul 2021 21:06:04 +0500 Subject: [PATCH 045/135] Update test_howdoi.py --- test_howdoi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_howdoi.py b/test_howdoi.py index 1501cb338..a0ea928e9 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -47,8 +47,8 @@ def _high_positive_position_query(self): query = self.queries[0] howdoi.howdoi(query + ' -p 40') - def _get_links_blockerror(self, query): - # print("raising error") + @classmethod + def _get_links_blockerror(cls, query): raise howdoi.BlockError def setUp(self): From 08739f12deb67c181851afdc54e33e438857c225 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 24 Jul 2021 05:23:48 +0530 Subject: [PATCH 046/135] Updated mkdocs fixed : npm, equal to sign and added links to folder in extension dev --- docs/extension_dev.md | 14 +++++++------- howdoi/howdoi.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/extension_dev.md b/docs/extension_dev.md index 4a545afb4..defd8194f 100644 --- a/docs/extension_dev.md +++ b/docs/extension_dev.md @@ -1,7 +1,7 @@ ## Extension development -You can integrate howdoi as a code editor extension. For this, you need to edit the files within the `extension/code-editor-integration` folder. -To improve the Visual Studio Code howdoi extension, edit the files within the extension/vscode-ext folder and republish the extension. +You can integrate howdoi as a code editor extension. For this, you need to edit the files within the [extension/code-editor-integration](https://github.com/gleitz/howdoi/tree/master/extension/code-editor-integration) folder. +To improve the Visual Studio Code howdoi extension, edit the files within the [extension/vscode-howdoi](https://github.com/gleitz/howdoi/tree/master/extension/vscode-howdoi) folder and republish the extension. #### How to integrate howdoi as a code editor extension? @@ -12,15 +12,15 @@ To improve the Visual Studio Code howdoi extension, edit the files within the ex ``` { -Question: string -Answer : string[] -Link : string[] + Question: string + Answer : string[] + Link : string[] } ``` 2. What are these object values? -- question = it contains the user’s query encapsulated by a single line comment +- question : it contains the user’s query encapsulated by a single line comment - answer : contains the three possible answers to the user’s query. - link : link contains the three possible links to the answer encapsulated by a single line comment @@ -54,7 +54,7 @@ To use the plug-in to create a howdoi extension, follow these steps: To begin the development for Visual Studio Code extension, install all the necessary packages: -`Npm install` +`npm install` Then precompile the extension : diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 44d1682fd..9209cbc5d 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -570,7 +570,7 @@ def _stash_save(cmd_key, title, answer): def _parse_cmd(args, res): answer = _format_answers(args, res) - cmd_key = _get_stash_key(args) + cmd_key = (args) title = ''.join(args['query']) if args[STASH_SAVE]: _stash_save(cmd_key, title, answer) From 3a7975fdc2aec0611db1c695d8d77770145f1f07 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 24 Jul 2021 05:28:06 +0530 Subject: [PATCH 047/135] Revert "Updated mkdocs" This reverts commit 08739f12deb67c181851afdc54e33e438857c225. --- docs/extension_dev.md | 14 +++++++------- howdoi/howdoi.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/extension_dev.md b/docs/extension_dev.md index defd8194f..4a545afb4 100644 --- a/docs/extension_dev.md +++ b/docs/extension_dev.md @@ -1,7 +1,7 @@ ## Extension development -You can integrate howdoi as a code editor extension. For this, you need to edit the files within the [extension/code-editor-integration](https://github.com/gleitz/howdoi/tree/master/extension/code-editor-integration) folder. -To improve the Visual Studio Code howdoi extension, edit the files within the [extension/vscode-howdoi](https://github.com/gleitz/howdoi/tree/master/extension/vscode-howdoi) folder and republish the extension. +You can integrate howdoi as a code editor extension. For this, you need to edit the files within the `extension/code-editor-integration` folder. +To improve the Visual Studio Code howdoi extension, edit the files within the extension/vscode-ext folder and republish the extension. #### How to integrate howdoi as a code editor extension? @@ -12,15 +12,15 @@ To improve the Visual Studio Code howdoi extension, edit the files within the [e ``` { - Question: string - Answer : string[] - Link : string[] +Question: string +Answer : string[] +Link : string[] } ``` 2. What are these object values? -- question : it contains the user’s query encapsulated by a single line comment +- question = it contains the user’s query encapsulated by a single line comment - answer : contains the three possible answers to the user’s query. - link : link contains the three possible links to the answer encapsulated by a single line comment @@ -54,7 +54,7 @@ To use the plug-in to create a howdoi extension, follow these steps: To begin the development for Visual Studio Code extension, install all the necessary packages: -`npm install` +`Npm install` Then precompile the extension : diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 9209cbc5d..44d1682fd 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -570,7 +570,7 @@ def _stash_save(cmd_key, title, answer): def _parse_cmd(args, res): answer = _format_answers(args, res) - cmd_key = (args) + cmd_key = _get_stash_key(args) title = ''.join(args['query']) if args[STASH_SAVE]: _stash_save(cmd_key, title, answer) From d1cacc30e37bef52643adb5052fe710ff438dc58 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 24 Jul 2021 05:28:29 +0530 Subject: [PATCH 048/135] Update howdoi_advanced_usage.md removed unwanted spaces --- docs/howdoi_advanced_usage.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/howdoi_advanced_usage.md b/docs/howdoi_advanced_usage.md index b73def255..a05a7a925 100644 --- a/docs/howdoi_advanced_usage.md +++ b/docs/howdoi_advanced_usage.md @@ -24,9 +24,6 @@ ``` $ HOWDOI_URL=cooking.stackexchange.com - ``` - - ``` $ howdoi make pesto ``` @@ -34,9 +31,6 @@ ``` $ alias hcook='function hcook(){ HOWDOI_URL=cooking.stackexchange.com howdoi $* ; }; hcook' - ``` - - ``` $ hcook make pesto ``` From 5fdff241835f035d29bd5bd81ef5fb1f67b7413b Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 24 Jul 2021 05:31:53 +0530 Subject: [PATCH 049/135] Revert "Revert "Updated mkdocs"" This reverts commit 3a7975fdc2aec0611db1c695d8d77770145f1f07. --- docs/extension_dev.md | 14 +++++++------- howdoi/howdoi.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/extension_dev.md b/docs/extension_dev.md index 4a545afb4..defd8194f 100644 --- a/docs/extension_dev.md +++ b/docs/extension_dev.md @@ -1,7 +1,7 @@ ## Extension development -You can integrate howdoi as a code editor extension. For this, you need to edit the files within the `extension/code-editor-integration` folder. -To improve the Visual Studio Code howdoi extension, edit the files within the extension/vscode-ext folder and republish the extension. +You can integrate howdoi as a code editor extension. For this, you need to edit the files within the [extension/code-editor-integration](https://github.com/gleitz/howdoi/tree/master/extension/code-editor-integration) folder. +To improve the Visual Studio Code howdoi extension, edit the files within the [extension/vscode-howdoi](https://github.com/gleitz/howdoi/tree/master/extension/vscode-howdoi) folder and republish the extension. #### How to integrate howdoi as a code editor extension? @@ -12,15 +12,15 @@ To improve the Visual Studio Code howdoi extension, edit the files within the ex ``` { -Question: string -Answer : string[] -Link : string[] + Question: string + Answer : string[] + Link : string[] } ``` 2. What are these object values? -- question = it contains the user’s query encapsulated by a single line comment +- question : it contains the user’s query encapsulated by a single line comment - answer : contains the three possible answers to the user’s query. - link : link contains the three possible links to the answer encapsulated by a single line comment @@ -54,7 +54,7 @@ To use the plug-in to create a howdoi extension, follow these steps: To begin the development for Visual Studio Code extension, install all the necessary packages: -`Npm install` +`npm install` Then precompile the extension : diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 44d1682fd..9209cbc5d 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -570,7 +570,7 @@ def _stash_save(cmd_key, title, answer): def _parse_cmd(args, res): answer = _format_answers(args, res) - cmd_key = _get_stash_key(args) + cmd_key = (args) title = ''.join(args['query']) if args[STASH_SAVE]: _stash_save(cmd_key, title, answer) From 1d95ecdee39e15761c727c3c24276d1d2f5ab482 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 24 Jul 2021 05:33:20 +0530 Subject: [PATCH 050/135] updated mkdocs reverted the changes --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 9209cbc5d..44d1682fd 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -570,7 +570,7 @@ def _stash_save(cmd_key, title, answer): def _parse_cmd(args, res): answer = _format_answers(args, res) - cmd_key = (args) + cmd_key = _get_stash_key(args) title = ''.join(args['query']) if args[STASH_SAVE]: _stash_save(cmd_key, title, answer) From c6fe16cd79168796f2a729cb0349c2b98da09f60 Mon Sep 17 00:00:00 2001 From: joe Date: Sat, 24 Jul 2021 05:34:56 +0530 Subject: [PATCH 051/135] reverted the previous changes and updated mkdocs --- docs/extension_dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extension_dev.md b/docs/extension_dev.md index defd8194f..4ff892dfb 100644 --- a/docs/extension_dev.md +++ b/docs/extension_dev.md @@ -58,6 +58,6 @@ To begin the development for Visual Studio Code extension, install all the neces Then precompile the extension : -`Npm run precompile` +`npm run precompile` To run and test extension, utilize the Visual Studio Code’s debugging tools. From fe37f38e9da90932cc1b5b97ef5b92042842074a Mon Sep 17 00:00:00 2001 From: joe Date: Sun, 25 Jul 2021 00:07:10 +0530 Subject: [PATCH 052/135] remove unwanted sentence removed print("checking") --- howdoi/howdoi.py | 1 - 1 file changed, 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 44d1682fd..ba842cd28 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -583,7 +583,6 @@ def _parse_cmd(args, res): def howdoi(raw_query): - # print("checking") if isinstance(raw_query, str): # you can pass either a raw or a parsed query parser = get_parser() args = vars(parser.parse_args(raw_query.split(' '))) From 71c6809d2dc08e5db8fa1666a06ac976928d31e4 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 23 Jul 2021 12:16:39 -0700 Subject: [PATCH 053/135] Working mock using patch --- howdoi/howdoi.py | 8 ++-- test_howdoi.py | 97 +++++++++++++++++++++++++++--------------------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index b1b2a0ade..4687fa4d7 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -591,8 +591,8 @@ def howdoi(raw_query): else: args = raw_query - os.environ['HOWDOI_SEARCH_ENGINE'] = args['search_engine'] or os.getenv('HOWDOI_SEARCH_ENGINE') or 'google' - search_engine = os.getenv('HOWDOI_SEARCH_ENGINE') + search_engine = args['search_engine'] or os.getenv('HOWDOI_SEARCH_ENGINE') or 'google' + os.environ['HOWDOI_SEARCH_ENGINE'] = search_engine if search_engine not in SUPPORTED_SEARCH_ENGINES: supported_search_engines = ', '.join(SUPPORTED_SEARCH_ENGINES) message = f'Unsupported engine {search_engine}. The supported engines are: {supported_search_engines}' @@ -622,9 +622,9 @@ def howdoi(raw_query): res = {'error': message} cache.set(cache_key, res) except (RequestsConnectionError, SSLError): - res = {'error': f'Unable to reach {args["search_engine"]}. Do you need to use a proxy?\n'} + res = {'error': f'Unable to reach {search_engine}. Do you need to use a proxy?\n'} except BlockError: - BLOCKED_ENGINES.append(args['search_engine']) + BLOCKED_ENGINES.append(search_engine) next_engine = next((engine for engine in SUPPORTED_SEARCH_ENGINES if engine not in BLOCKED_ENGINES), None) if next_engine is None: res = {'error': 'Unable to get a response from any search engine\n'} diff --git a/test_howdoi.py b/test_howdoi.py index a0ea928e9..1cebb769d 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -6,7 +6,12 @@ import os import re import unittest + +import requests + from pathlib import Path +from unittest.mock import patch + from cachelib import NullCache from pyquery import PyQuery as pq @@ -15,46 +20,33 @@ # pylint: disable=protected-access -class HowdoiTestCase(unittest.TestCase): # pylint: disable=too-many-public-methods - def _get_result_mock(self, url): - file_name = howdoi._format_url_to_filename(url, 'html.gz') - # pylint: disable=no-member - file_path = Path.joinpath(Path(howdoi.HTML_CACHE_PATH), Path(file_name)).resolve() - try: - with gzip.open(file_path, 'rb') as f: - cached_page_content = str(f.read(), encoding='utf-8') - return cached_page_content - - except FileNotFoundError: - page_content = self.original_get_result(url) - with gzip.open(file_path, 'wb') as f: - f.write(bytes(page_content, encoding='utf-8')) - return page_content +original_get_result = howdoi._get_result - def _negative_number_query(self): - query = self.queries[0] - howdoi.howdoi(query + ' -n -1') - def _high_positive_number_query(self): - query = self.queries[0] - howdoi.howdoi(query + ' -n 21') +def _get_result_mock(url): + # pylint: disable=protected-access + file_name = howdoi._format_url_to_filename(url, 'html.gz') + # pylint: disable=no-member + file_path = Path.joinpath(Path(howdoi.HTML_CACHE_PATH), Path(file_name)).resolve() + try: + with gzip.open(file_path, 'rb') as f: + cached_page_content = str(f.read(), encoding='utf-8') + return cached_page_content - def _negative_position_query(self): - query = self.queries[0] - howdoi.howdoi(query + ' -p -2') + except FileNotFoundError: + page_content = original_get_result(url) + with gzip.open(file_path, 'wb') as f: + f.write(bytes(page_content, encoding='utf-8')) + return page_content - def _high_positive_position_query(self): - query = self.queries[0] - howdoi.howdoi(query + ' -p 40') - @classmethod - def _get_links_blockerror(cls, query): - raise howdoi.BlockError +# pylint: disable=protected-access +class HowdoiTestCase(unittest.TestCase): # pylint: disable=too-many-public-methods def setUp(self): - self.original_get_result = howdoi._get_result - howdoi._get_result = self._get_result_mock - + self.patcher_get_result = patch.object(howdoi, '_get_result') + self.mock_get_result = self.patcher_get_result.start() + self.mock_get_result.side_effect = _get_result_mock # ensure no cache is used during testing. howdoi.cache = NullCache() @@ -71,14 +63,32 @@ def setUp(self): 'mel'] self.query_without_code_or_pre_block = 'Difference between element node and Text Node' - def assertValidResponse(self, res): # pylint: disable=invalid-name - self.assertTrue(len(res) > 0) - def tearDown(self): - keys_to_remove = ['HOWDOI_URL', 'HOWDO_SEARCH_ENGINE'] + self.patcher_get_result.stop() + keys_to_remove = ['HOWDOI_URL', 'HOWDOI_SEARCH_ENGINE'] for key in keys_to_remove: if key in os.environ: del os.environ[key] + howdoi.BLOCKED_ENGINES = [] + + def _negative_number_query(self): + query = self.queries[0] + howdoi.howdoi(query + ' -n -1') + + def _high_positive_number_query(self): + query = self.queries[0] + howdoi.howdoi(query + ' -n 21') + + def _negative_position_query(self): + query = self.queries[0] + howdoi.howdoi(query + ' -p -2') + + def _high_positive_position_query(self): + query = self.queries[0] + howdoi.howdoi(query + ' -p 40') + + def assertValidResponse(self, res): # pylint: disable=invalid-name + self.assertTrue(len(res) > 0) def test_get_link_at_pos(self): self.assertEqual(howdoi.get_link_at_pos(['/questions/42/'], 1), @@ -92,6 +102,13 @@ def test_get_link_at_pos(self): self.assertEqual(howdoi.get_link_at_pos(['/questions/42/', '/questions/142/'], 1), '/questions/42/') + @patch.object(howdoi, '_get_result') + def test_blockerror(self, mock_get_links): + mock_get_links.side_effect = requests.HTTPError + query = self.queries[0] + response = howdoi.howdoi(query) + self.assertEqual(response, "ERROR: \x1b[91mUnable to get a response from any search engine\n\x1b[0m") + def test_answers(self): for query in self.queries: self.assertValidResponse(howdoi.howdoi(query)) @@ -283,12 +300,6 @@ def test_negative_and_high_positive_int_values_rejected(self): with self.assertRaises(SystemExit): self._high_positive_number_query() - def test_sample(self): - query = self.queries[0] - howdoi._get_links = self._get_links_blockerror - response = howdoi.howdoi(query) - self.assertEqual(response, "ERROR: \x1b[91mUnable to get a response from any search engine\n\x1b[0m") - class HowdoiTestCaseEnvProxies(unittest.TestCase): From 316cccd89e9f85c830b0b9a6ea8b6b539e499383 Mon Sep 17 00:00:00 2001 From: ShezaMunir <23100116@lums.edu.pk> Date: Sun, 25 Jul 2021 01:10:57 +0500 Subject: [PATCH 054/135] pylint fix --- test_howdoi.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_howdoi.py b/test_howdoi.py index 1cebb769d..c3bcef606 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -7,10 +7,9 @@ import re import unittest -import requests - from pathlib import Path from unittest.mock import patch +import requests from cachelib import NullCache from pyquery import PyQuery as pq From 4a3b8f8974668c555ac56e5228ad6d065b2b4f2e Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Wed, 28 Jul 2021 13:54:10 -0700 Subject: [PATCH 055/135] Clean up some of the documentation --- docs/contributing_docs.md | 2 +- docs/contributing_to_howdoi.md | 8 ++-- docs/development_env.md | 18 ++++--- docs/index.md | 2 +- docs/introduction.md | 16 +++---- docs/troubleshooting.md | 1 - docs/usage.md | 86 ++++++++++++++-------------------- mkdocs.yml | 2 +- 8 files changed, 59 insertions(+), 76 deletions(-) diff --git a/docs/contributing_docs.md b/docs/contributing_docs.md index 1a6d6b0f4..f1358c6d7 100644 --- a/docs/contributing_docs.md +++ b/docs/contributing_docs.md @@ -1,4 +1,4 @@ -If you would like to improve the existing docs/ add new ideas in docs, you can do so by using mkdocs. Howdoi uses mkdocs to host its documentation. Steps to contribute to docs: +If you would like to improve the existing documentation, you can do so by using `mkdocs`. Howdoi uses mkdocs to render its documentation. Steps to contribute to docs: - Every step from [Contributing to howdoi](http://gleitz.github.io/howdoi/contributing_to_howdoi/) remains the same with additional requirements of installing and building mkdocs. - First, install mkdocs by running the following command: diff --git a/docs/contributing_to_howdoi.md b/docs/contributing_to_howdoi.md index e72f3ccc8..4f06624ca 100644 --- a/docs/contributing_to_howdoi.md +++ b/docs/contributing_to_howdoi.md @@ -1,11 +1,11 @@ As beginners, navigating the codebase and finding your way out of the documentation can become difficult. This page will help you understand everything about contributing to howdoi and the best practices in open source as well. You can either contribute code to Howdoi (explained on this page) or contribute documentation (explained on next page) -#### 1- Setting up the development environment +#### Setting up the development environment Follow the page [Setting up the development environment](http://gleitz.github.io/howdoi/development_env/) for setting up the development environment for Howdoi. -#### 2 - Finding your first issue +#### Finding your first issue - Go to issues in the [howdoi repo](https://github.com/gleitz/howdoi). - Find the issues which you might be interested to work on. Or, you can also come up with your own ideas of improving howdoi. @@ -14,7 +14,7 @@ Follow the page [Setting up the development environment](http://gleitz.github.io - After receiving confirmation, start working on the issue and whenever and wherever help is needed, comment on the issue itself describing your query in detail. - A good guide on how to collaborate efficiently can be found [here](https://lab.github.com/githubtraining/introduction-to-github){:target="\_blank"}. -#### 3 - Making a Pull request (PR) +#### Making a Pull request (PR) - After you have worked on the issue and fixed it, we need to merge it from your forked repository into the howdoi repository. This is done by making a PR. - You can search @@ -26,7 +26,7 @@ Follow the page [Setting up the development environment](http://gleitz.github.io - Once your commit passes all the tests, make a PR and wait for it to be reviewed and merged. -#### 4 - Asking for help +#### Asking for help At times, help is needed while solving the issue. We recommend the following step for asking for help when you get stuck: diff --git a/docs/development_env.md b/docs/development_env.md index 568ea4201..76097f594 100644 --- a/docs/development_env.md +++ b/docs/development_env.md @@ -1,4 +1,4 @@ -- Clone the Howdoi repository: +- Clone the howdoi repository: ``` $ git clone https://github.com/gleitz/howdoi.git @@ -6,28 +6,26 @@ - To see how to set up the development for Windows, see [here](http://gleitz.github.io/howdoi/windows-contributing/). -- Setup and activate a virtual environment +- Set up and activate a virtual environment: ``` $ python3 -m venv .venv $ source .venv/bin/activate ``` -- Install all the required packages +- Install all the required packages: ``` $ pip install -r requirements.txt ``` -- Run howdoi - - Running from command line : ``` $ python -m howdoi QUERY ``` -- Running from a python script : Go to your script in howdoi.howdoi() and pass your query in the argument. +- From a Python script, you can call howdoi with `howdoi.howdoi` and pass your query in the argument. ``` from howdoi import howdoi @@ -35,7 +33,7 @@ query = "for loop python" output = howdoi.howdoi(query) ``` -Or , parse it yourself and then pass the arguments: +Or, parse it yourself and then pass the arguments: ``` from howdoi import howdoi @@ -45,7 +43,7 @@ args = vars(parser.parse_args(query.split(' '))) output = howdoi.howdoi(args) ``` -#### Notes : +#### Notes -- **Parsing queries yourself is the older way to pass in queries and may be deprecated in the future. Prefer the first example.** -- **If you try running python howdoi/howdoi.py (without -m) you might get ValueError: Attempted relative import in non-package.** +- Parsing queries yourself is the older way to pass in queries and may be deprecated in the future. Please use the first example. +- If you try running `python howdoi/howdoi.py` (without -m) you might get `ValueError: Attempted relative import in non-package`. diff --git a/docs/index.md b/docs/index.md index 2b2e73612..b19a7c312 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,5 @@ # howdoi -Never have to open your browser to look for answers again. +Never open your browser to look for answers again. Create tar archive: ```bash diff --git a/docs/introduction.md b/docs/introduction.md index 1a6430055..b839192e6 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -1,25 +1,25 @@ -Howdoi is an open source command line tool which gives answers to your questions in the command line itself. Howdoi can be used by anyone and everyone who finds themselves Googling for answers to their basic programming questions. +Howdoi is an open source command line tool that gives answers to your questions right on the command line. Howdoi can be used by anyone and everyone who finds themselves Googling for answers to their basic programming questions. -Example - +You wonder: ``` howdoi print hello in python ``` -Answer - +We answer: ``` print(“hello”) ``` -### Installation : +### Installation -To install Howdoi, these two requirements must be fulfilled: +You'll need: -- Pip should be installed in your local system. -- Python 3.5 or above installed since Python 2.7 support is discontinued. +- `pip` +- Python 3.5 or above. Python 2.7 support is discontinued. -To install Howdoi, simply run : +To install howdoi: `pip install howdoi` diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 3d65cd146..c0c55eb58 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -15,4 +15,3 @@ sudo chmod -R go+w /Library/Python/2.7/site-packages/ An official lxml for python 3.3+ for windows has not yet been released. You may get an error while installing. Try and install an [unofficial binary for lxml](http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml). -``` diff --git a/docs/usage.md b/docs/usage.md index 0d84ca132..2224f9df3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,61 +1,47 @@ -To begin with howdoi, after installing howdoi, enter the following command: +Let's start at the beginning. ``` $ howdoi howdoi ``` -This will provide with every information you need about working with howdoi and every command/argument that is present in howdoi. For further information about every flag and environment variables type : +For further information about flags and environment variables: ``` $ howdoi -h ``` -#### Howdoi flags/arguments. +#### Howdoi Flags and Arguments -Howdoi comes with a set of predefined flags/arguments which can be set by you as per your choice. You can just type `howdoi -h` in your command line to see each argument and what they do. - -**Syntax** : `howdoi [flag/argument] QUERY` - -The available arguments currently are listed below: - -**- h, --help** : To see the help message which has all the information about every command - -**-p POS, --pos POS** : To select answer in any specified position. - -**-n NUM, --num NUM** : Defines the number of answers to return. By default, set to 1. - -**-a, --all**: Shows the full text of an answer - -**-l, --link**: Displays only the link of the answer - -**-j** : Displays the answer in JSON format. Useful when you are building on top of howdoi. - -**-c, --color**: Prints colorized output - -**-x, --explain**: Explains why the outputted answer was shown to you - -**-C, --clear-cache**: Clears the cache - -**-j, --json** : Outputs the answer in raw JSON format - -**-v, --version**: Displays your current version of howdoi. - -**-e [ENGINE], --engine [ENGINE]** : Allows to choose the search engine for the query. Currently supported - google, bing, duckduckgo - -**--save, --stash** : Enables stashing feature for a howdoi answer - -**--view** : Displayed the stash - -**--remove** : Removes an entry in your stash - -**--empty** : Empties the stash completely - -#### Howdoi Environment variables - -Howdoi enables the users to put the environment variables of their choice, the currently supported environment variables are : - -- **HOWDOI_COLORIZE** : Colorizes the output by default. -- **HOWDOI_SEARCH_ENGINE** : changes the default search engine for StackOverflow links. By default the search engine is google but other supported are : bing, duckduckgo. -- **HOWDOI_URL** : Changes the source url for answers. By default set to : stackoverflow.com. Currently supported here. -- **HOWDOI_DISABLE_CACHE** : Howdoi uses cache for faster access to previously searched questions. If this environment variable is set, the caching functionality will be set. The cache resides in ~/cache/howdoi/. -- **HOWDOI_DISABLE_SSL** : Allows you to disable SSL. +``` +usage: howdoi [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-x] [-C] [-j] [-v] [-e [ENGINE]] [--save] [--view] [--remove] [--empty] [QUERY ...] + +instant coding answers via the command line + +positional arguments: + QUERY the question to answer + +optional arguments: + -h, --help show this help message and exit + -p POS, --pos POS select answer in specified position (default: 1) + -n NUM, --num NUM number of answers to return (default: 1) + -a, --all display the full text of the answer + -l, --link display only the answer link + -c, --color enable colorized output + -x, --explain explain how answer was chosen + -C, --clear-cache clear the cache + -j, --json return answers in raw json format + -v, --version displays the current version of howdoi + -e [ENGINE], --engine [ENGINE] + search engine for this query (google, bing, duckduckgo) + --save, --stash stash a howdoi answer + --view view your stash + --remove remove an entry in your stash + --empty empty your stash + +environment variable examples: + HOWDOI_COLORIZE=1 + HOWDOI_DISABLE_CACHE=1 + HOWDOI_DISABLE_SSL=1 + HOWDOI_SEARCH_ENGINE=google + HOWDOI_URL=serverfault.com +``` diff --git a/mkdocs.yml b/mkdocs.yml index 38ef13829..aad7a1374 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -20,7 +20,7 @@ nav: - Contributing: contributing_to_howdoi.md - Contributing documentation: contributing_docs.md - Extension development: extension_dev.md - - howdoi advanced usage: howdoi_advanced_usage.md + - Howdoi advanced usage: howdoi_advanced_usage.md - Troubleshooting: troubleshooting.md - Development for Windows: windows-contributing.md From d7bbd1450577268c3bd78b824a4d265d411cd93d Mon Sep 17 00:00:00 2001 From: joe Date: Fri, 30 Jul 2021 04:35:17 +0530 Subject: [PATCH 056/135] checked for deep links and added contributors names --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 7331c452c..f617a7236 100644 --- a/README.rst +++ b/README.rst @@ -189,6 +189,8 @@ Contributors - Shageldi Ovezov (`@ovezovs `_) - Mwiza Simbeye (`@mwizasimbeye11 `_) - Shantanu Verma (`@SaurusXI `_) +- Sheza Munir (`@ShezaMunir `_) +- Jyoti Bisht (`@joeyouss `_) - And `more! `_ HOW TO CONTRIBUTE From 11225fe7e0082f49c459a4756c0bcb61e590cf8d Mon Sep 17 00:00:00 2001 From: joe Date: Fri, 30 Jul 2021 04:39:57 +0530 Subject: [PATCH 057/135] added additiona keyword in SUPPORTED_HELP_QUERIES --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index ba842cd28..528ce8387 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -88,7 +88,7 @@ CACHE_ENTRY_MAX = 128 HTML_CACHE_PATH = 'page_cache' -SUPPORTED_HELP_QUERIES = ['use howdoi', 'howdoi', 'run howdoi', +SUPPORTED_HELP_QUERIES = ['use howdoi', 'howdoi', 'run howdoi', 'setup howdoi', 'do howdoi', 'howdoi howdoi', 'howdoi use howdoi'] # variables for text formatting, prepend to string to begin text formatting. From 71c17eccdbe0ac65f81314a2ff8eabbd18367640 Mon Sep 17 00:00:00 2001 From: yuhaoq Date: Mon, 2 Aug 2021 20:00:45 +0800 Subject: [PATCH 058/135] Corrected Verb Tense Error --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index fc31d0586..f5cf1b8ec 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -662,7 +662,7 @@ def get_parser(): parser.add_argument('-j', '--json', help='return answers in raw json format', dest='json_output', action='store_true') parser.add_argument('--json-output', action='store_true', help=argparse.SUPPRESS) - parser.add_argument('-v', '--version', help='displays the current version of howdoi', + parser.add_argument('-v', '--version', help='display the current version of howdoi', action='store_true') parser.add_argument('-e', '--engine', help='search engine for this query (google, bing, duckduckgo)', dest='search_engine', nargs="?", metavar='ENGINE') From d120a07676e90ab7f844af6a1c88cd4960ca6cf4 Mon Sep 17 00:00:00 2001 From: youknowqyh Date: Tue, 3 Aug 2021 07:26:12 +0800 Subject: [PATCH 059/135] Corrected Verb Tense Error --- README.rst | 2 +- docs/usage.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index f617a7236..d89a4168d 100644 --- a/README.rst +++ b/README.rst @@ -123,7 +123,7 @@ Usage -x, --explain explain how answer was chosen -C, --clear-cache clear the cache -j, --json return answers in raw json format - -v, --version displays the current version of howdoi + -v, --version display the current version of howdoi -e [ENGINE], --engine [ENGINE] search engine for this query (google, bing, duckduckgo) --save, --stash stash a howdoi answer diff --git a/docs/usage.md b/docs/usage.md index 2224f9df3..736b0cbd3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -30,7 +30,7 @@ optional arguments: -x, --explain explain how answer was chosen -C, --clear-cache clear the cache -j, --json return answers in raw json format - -v, --version displays the current version of howdoi + -v, --version display the current version of howdoi -e [ENGINE], --engine [ENGINE] search engine for this query (google, bing, duckduckgo) --save, --stash stash a howdoi answer From 4c1f2e10d9bf179c29ceefb58b834eab9a6dbb67 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 2 Aug 2021 21:07:27 -0700 Subject: [PATCH 060/135] Added Markdown README.md using pandoc Add centered content and cleanup some of the headings Update to full documentation placement Reword the README --- README.md | 193 +++++++++++++++++++++++++++++++++++++++++ README.rst | 231 -------------------------------------------------- docs/index.md | 2 +- 3 files changed, 194 insertions(+), 232 deletions(-) create mode 100644 README.md delete mode 100644 README.rst diff --git a/README.md b/README.md new file mode 100644 index 000000000..569f433c0 --- /dev/null +++ b/README.md @@ -0,0 +1,193 @@ +

+ + Sherlock, your neighborhood command-line sloth sleuth + +

+

howdoi

+

Instant coding answers via the command line

+

⚡ Never open your browser to look for help again ⚡

+ +

+ build status + downloads + Python versions +

+ +------------------------------------------------------------------------ + +## Introduction to howdoi + +Are you a hack programmer? Do you find yourself constantly Googling for +how to do basic programming tasks? + +Suppose you want to know how to format a date in bash. Why open your +browser and read through blogs (risking major distraction) when you can +simply stay in the console and ask howdoi: + + $ howdoi format date bash + > DATE=`date +%Y-%m-%d` + +howdoi will answer all sorts of queries: + + $ howdoi print stack trace python + > import traceback + > + > try: + > 1/0 + > except: + > print '>>> traceback <<<' + > traceback.print_exc() + > print '>>> end of traceback <<<' + > traceback.print_exc() + + $ howdoi convert mp4 to animated gif + > video=/path/to/video.avi + > outdir=/path/to/output.gif + > mplayer "$video" \ + > -ao null \ + > -ss "00:01:00" \ # starting point + > -endpos 10 \ # duration in second + > -vo gif89a:fps=13:output=$outdir \ + > -vf scale=240:180 + + $ howdoi create tar archive + > tar -cf backup.tar --exclude "www/subf3" www + +[![image](http://imgs.xkcd.com/comics/tar.png)](https://xkcd.com/1168/) + +## Installation + + pip install howdoi + +## Usage + +### New to howdoi? + + howdoi howdoi + +### RTFM + +- [Introduction and + installation](http://gleitz.github.io/howdoi/introduction/) +- [Usage](http://gleitz.github.io/howdoi/usage/) +- [Contributing to + howdoi](http://gleitz.github.io/howdoi/contributing_to_howdoi/) +- [Advanced + usage](http://gleitz.github.io/howdoi/howdoi_advanced_usage/) +- [Troubleshooting](http://gleitz.github.io/howdoi/troubleshooting/) + +### Commands + + usage: howdoi [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-x] [-C] [-j] [-v] [-e [ENGINE]] + [--save] [--view] [--remove] [--empty] [QUERY ...] + + instant coding answers via the command line + + positional arguments: + QUERY the question to answer + + optional arguments: + -h, --help show this help message and exit + -p POS, --pos POS select answer in specified position (default: 1) + -n NUM, --num NUM number of answers to return (default: 1) + -a, --all display the full text of the answer + -l, --link display only the answer link + -c, --color enable colorized output + -x, --explain explain how answer was chosen + -C, --clear-cache clear the cache + -j, --json return answers in raw json format + -v, --version display the current version of howdoi + -e [ENGINE], --engine [ENGINE] + search engine for this query (google, bing, duckduckgo) + --save, --stash stash a howdoi answer + --view view your stash + --remove remove an entry in your stash + --empty empty your stash + + environment variable examples: + HOWDOI_COLORIZE=1 + HOWDOI_DISABLE_CACHE=1 + HOWDOI_DISABLE_SSL=1 + HOWDOI_SEARCH_ENGINE=google + HOWDOI_URL=serverfault.com + +Using the howdoi stashing feature (for more advanced features view the +[keep documentation](https://github.com/OrkoHunter/keep)). + + stashing: howdoi --save QUERY + viewing: howdoi --view + removing: howdoi --remove (will be prompted which answer to delete) + emptying: howdoi --empty (empties entire stash, will be prompted to confirm) + +As a shortcut, if you commonly use the same parameters each time and +don\'t want to type them, add something similar to your .bash_profile +(or otherwise). This example gives you 5 colored results each time. + + alias h='function hdi(){ howdoi $* -c -n 5; }; hdi' + +And then to run it from the command line simply type: + + $ h format date bash + +You can also search other [StackExchange +properties](https://stackexchange.com/sites#traffic) for answers: + + HOWDOI_URL=cooking.stackexchange.com howdoi make pesto + +or as an alias: + + alias hcook='function hcook(){ HOWDOI_URL=cooking.stackexchange.com howdoi $* ; }; hcook' + hcook make pesto + +Other useful aliases: + + alias hless='function hdi(){ howdoi $* -c | less --raw-control-chars --quit-if-one-screen --no-init; }; hdi' + +## Contributors + +- Benjamin Gleitzman ([\@gleitz](http://twitter.com/gleitz)) +- Yanlam Ko ([\@YKo20010](https://github.com/YKo20010)) +- Diana Arreola ([\@diarreola](https://github.com/diarreola)) +- Eyitayo Ogunbiyi ([\@tayoogunbiyi](https://github.com/tayoogunbiyi)) +- Chris Nguyen ([\@chrisngyn](https://github.com/chrisngyn)) +- Shageldi Ovezov ([\@ovezovs](https://github.com/chrisngyn)) +- Mwiza Simbeye + ([\@mwizasimbeye11](https://github.com/mwizasimbeye11)) +- Shantanu Verma ([\@SaurusXI](https://github.com/SaurusXI)) +- Sheza Munir ([\@ShezaMunir](https://github.com/ShezaMunir)) +- Jyoti Bisht ([\@joeyouss](https://github.com/joeyouss)) +- And [more!](https://github.com/gleitz/howdoi/graphs/contributors) + +## How to contribute + +We welcome contributions that make howdoi better and improve the +existing functionalities of the project. We have created a separate +[guide to contributing to +howdoi](http://gleitz.github.io/howdoi/contributing_to_howdoi/) that explains +how to get up and running with your first pull request. + +## Notes + +- Works with Python 3.5 and newer. Unfortunately Python 2.7 support + has been discontinued :( +- There is a [GUI that wraps + howdoi](https://pypi.org/project/pysimplegui-howdoi/) +- There is a [Flask webapp that wraps + howdoi](https://howdoi.maxbridgland.com) +- An [Alfred Workflow](http://blog.gleitzman.com/post/48539944559/howdoi-alfred-even-more-instant-answers) + for howdoi +- Slack integration available through + [slack-howdoi](https://github.com/ellisonleao/slack-howdoi) +- Telegram integration available through + [howdoi-telegram](https://github.com/aahnik/howdoi-telegram) +- Special thanks to Rich Jones + ([\@miserlou](https://github.com/miserlou)) for the idea +- More thanks to [Ben Bronstein](https://benbronstein.com/) for the + logo + +## Visual Studio Code Extension Installation + +howdoi can be installed as an extension on VSCode. + +Head over to the [MarketPlace](https://marketplace.visualstudio.com/items?itemName=howdoi-org.howdoi) +to install the extension. diff --git a/README.rst b/README.rst deleted file mode 100644 index d89a4168d..000000000 --- a/README.rst +++ /dev/null @@ -1,231 +0,0 @@ -howdoi -====== - -instant coding answers via the command line -------------------------------------------- - -.. image:: https://img.shields.io/github/workflow/status/gleitz/howdoi/Python%20CI?style=plastic&color=78dce8 - :target: https://github.com/gleitz/howdoi/actions?query=workflow%3A%22Python+CI%22 - -.. image:: https://img.shields.io/badge/dynamic/json?style=plastic&color=ab9df2&maxAge=86400&label=downloads&query=%24.total_downloads&url=https%3A%2F%2Fapi.pepy.tech%2Fapi%2Fprojects%2Fhowdoi - :target: https://pepy.tech/project/howdoi - -.. image:: https://img.shields.io/pypi/pyversions/howdoi.svg?style=plastic&color=ff6188 - :target: https://pypi.python.org/pypi/howdoi - -| - -.. image:: http://sublimate.org/flyers/HowDoIcolor512.png - :target: https://pypi.python.org/pypi/howdoi - :alt: Sherlock, your neighborhood command-line sloth sleuth - -Sherlock, your neighborhood command-line sloth sleuth. - ----- - - -`howdoi documentation `_ -~~~~~~~~~~~~~~~~~ - -- `Introduction to howdoi and installation `_ -- `Howdoi usage `_ -- `Setting up the development environment `_ -- `Contributing to howdoi `_ -- `Contributing documentation to howdoi `_ -- `Extension development `_ -- `howdoi advanced usage `_ -- `Troubleshooting `_ -- `Development environment for windows `_ - -INTRODUCTION TO HOWDOI ----------------------- - -Are you a hack programmer? Do you find yourself constantly Googling for -how to do basic programming tasks? - -Suppose you want to know how to format a date in bash. Why open your browser -and read through blogs (risking major distraction) when you can simply stay -in the console and ask howdoi: - -:: - - $ howdoi format date bash - > DATE=`date +%Y-%m-%d` - -howdoi will answer all sorts of queries: - -:: - - $ howdoi print stack trace python - > import traceback - > - > try: - > 1/0 - > except: - > print '>>> traceback <<<' - > traceback.print_exc() - > print '>>> end of traceback <<<' - > traceback.print_exc() - - $ howdoi convert mp4 to animated gif - > video=/path/to/video.avi - > outdir=/path/to/output.gif - > mplayer "$video" \ - > -ao null \ - > -ss "00:01:00" \ # starting point - > -endpos 10 \ # duration in second - > -vo gif89a:fps=13:output=$outdir \ - > -vf scale=240:180 - - $ howdoi create tar archive - > tar -cf backup.tar --exclude "www/subf3" www - -.. image:: http://imgs.xkcd.com/comics/tar.png - :target: https://xkcd.com/1168/ - -Installation ------------- - -:: - - pip install howdoi - -or - -Check out howdoi docs for more ways of `installation `_ - -New to howdoi? --------------- - -:: - - howdoi howdoi - -Usage ------ - -:: - - usage: howdoi [-h] [-p POS] [-n NUM] [-a] [-l] [-c] [-x] [-C] [-j] [-v] [-e [ENGINE]] [--save] [--view] [--remove] [--empty] [QUERY ...] - - instant coding answers via the command line - - positional arguments: - QUERY the question to answer - - optional arguments: - -h, --help show this help message and exit - -p POS, --pos POS select answer in specified position (default: 1) - -n NUM, --num NUM number of answers to return (default: 1) - -a, --all display the full text of the answer - -l, --link display only the answer link - -c, --color enable colorized output - -x, --explain explain how answer was chosen - -C, --clear-cache clear the cache - -j, --json return answers in raw json format - -v, --version display the current version of howdoi - -e [ENGINE], --engine [ENGINE] - search engine for this query (google, bing, duckduckgo) - --save, --stash stash a howdoi answer - --view view your stash - --remove remove an entry in your stash - --empty empty your stash - - environment variable examples: - HOWDOI_COLORIZE=1 - HOWDOI_DISABLE_CACHE=1 - HOWDOI_DISABLE_SSL=1 - HOWDOI_SEARCH_ENGINE=google - HOWDOI_URL=serverfault.com - -Using the howdoi stashing feature (for more advanced features view the `keep documentation `_). - -:: - - stashing: howdoi --save QUERY - viewing: howdoi --view - removing: howdoi --remove (will be prompted which answer to delete) - emptying: howdoi --empty (empties entire stash, will be prompted to confirm) - -As a shortcut, if you commonly use the same parameters each time and don't want to type them, add something similar to your .bash_profile (or otherwise). This example gives you 5 colored results each time. - -:: - - alias h='function hdi(){ howdoi $* -c -n 5; }; hdi' - -And then to run it from the command line simply type: - -:: - - $ h format date bash - -You can also search other `StackExchange properties `_ for answers: - -:: - - HOWDOI_URL=cooking.stackexchange.com howdoi make pesto - -or as an alias: - -:: - - alias hcook='function hcook(){ HOWDOI_URL=cooking.stackexchange.com howdoi $* ; }; hcook' - hcook make pesto - -Other useful aliases: - -:: - - alias hless='function hdi(){ howdoi $* -c | less --raw-control-chars --quit-if-one-screen --no-init; }; hdi' - -Contributors ------------- - -- Benjamin Gleitzman (`@gleitz `_) -- Yanlam Ko (`@YKo20010 `_) -- Diana Arreola (`@diarreola `_) -- Eyitayo Ogunbiyi (`@tayoogunbiyi `_) -- Chris Nguyen (`@chrisngyn `_) -- Shageldi Ovezov (`@ovezovs `_) -- Mwiza Simbeye (`@mwizasimbeye11 `_) -- Shantanu Verma (`@SaurusXI `_) -- Sheza Munir (`@ShezaMunir `_) -- Jyoti Bisht (`@joeyouss `_) -- And `more! `_ - -HOW TO CONTRIBUTE ------------------ - -We welcome contributions that make Howdoi better and/or improve the existing functionalities of the project. We have created a separate `guide to contributing to howdoi `_ which resides in the howdoi documentation in mkdcos. -The guide contains the following: - -- Introduction for first time contributors -- Getting started with howdoi -- Making PRs and testing -- Asking for help -- Helpful tips for a good contribution experience. - -Notes ------ - -- Works with Python 3.5 and newer. Unfortunately Python 2.7 support has been discontinued :( -- There is a `GUI that wraps howdoi `_. -- There is a `Flask webapp that wraps howdoi `_. -- An Alfred Workflow for howdoi can be found at `http://blog.gleitzman.com/post/48539944559/howdoi-alfred-even-more-instant-answers `_. -- Slack integration available through `slack-howdoi `_. -- Telegram integration available through `howdoi-telegram `_. -- Special thanks to Rich Jones (`@miserlou `_) for the idea. -- More thanks to `Ben Bronstein `_ for the logo. - -Visual Studio Code Extension Installation ------------------------------------------ - -howdoi can now be installed as an extension on Visual Studio Code! There are two ways to install it: - -1. On the Visual Studio Code MarketPlace: - - - Head over to the `MarketPlace `_ to install the extension. - -2. Directly from the packaged extension: - - - Head over `here `_ to locally install the howdoi Visual Studio Code package. diff --git a/docs/index.md b/docs/index.md index b19a7c312..2355a118c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,5 @@ # howdoi -Never open your browser to look for answers again. +Never open your browser to look for help again. Create tar archive: ```bash From 0cd01d9d50bd14d247b050c0e1feb4d38330f278 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Tue, 3 Aug 2021 10:05:01 -0700 Subject: [PATCH 061/135] Release 2.0.17 Switched from RST to Markdown --- CHANGES.txt | 7 +++++++ MANIFEST.in | 2 +- howdoi/__init__.py | 2 +- setup.py | 7 +++---- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 70eee5e6f..b76e26a41 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,10 @@ +2.0.17 +------ +- New documentation and mkdocs +- Fixed issue with how howdoi chooses the proper search engine (command line flags now override environment variables) +- Added a search engine fallback if one of the search engines fails +- Fixed issue with howdoi cache + 2.0.16 ------ - Fix GDPR issue for those using howdoi in countries outside the US diff --git a/MANIFEST.in b/MANIFEST.in index 3a1c284be..19e3f3c06 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ include LICENSE.txt -include README.rst +include README.md include CHANGES.txt include fastentrypoints.py include requirements.txt diff --git a/howdoi/__init__.py b/howdoi/__init__.py index 37f038a14..ed6ed8969 100644 --- a/howdoi/__init__.py +++ b/howdoi/__init__.py @@ -1 +1 @@ -__version__ = '2.0.16' +__version__ = '2.0.17' diff --git a/setup.py b/setup.py index 6550967b2..d91fe4541 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ def read(*names): values = dict() for name in names: value = '' - for extension in ('.txt', '.rst'): + for extension in ('.txt', '.md'): filename = name + extension if Path(filename).is_file(): with open(filename) as in_file: @@ -54,8 +54,7 @@ def read(*names): long_description = """ %(README)s -News -==== +# News %(CHANGES)s @@ -66,7 +65,7 @@ def read(*names): version=howdoi.__version__, description='Instant coding answers via the command line', long_description=long_description, - long_description_content_type='text/x-rst', + long_description_content_type='text/markdown', classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", From 7d50889333890a2dd557577ca978743572cb1ebb Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Tue, 3 Aug 2021 10:24:53 -0700 Subject: [PATCH 062/135] Update README --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 569f433c0..2d1ed0063 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,5 @@ how to get up and running with your first pull request. ## Visual Studio Code Extension Installation -howdoi can be installed as an extension on VSCode. - Head over to the [MarketPlace](https://marketplace.visualstudio.com/items?itemName=howdoi-org.howdoi) to install the extension. From 40b1814db3fa7e871e032a47596ea34d71a2ce16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Aug 2021 20:37:20 +0000 Subject: [PATCH 063/135] Bump path-parse in /extension/code-editor-integration Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/jbgutierrez/path-parse/releases) - [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7) --- updated-dependencies: - dependency-name: path-parse dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/code-editor-integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index 5ccf64c6b..06c22697c 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -2359,9 +2359,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-type": { From 7c038706da55ec45fc3488ecb91492d65f20c88f Mon Sep 17 00:00:00 2001 From: Benjamin Hafen Date: Fri, 13 Aug 2021 21:54:07 -0600 Subject: [PATCH 064/135] Workaround FileNotFoundError thrown by cachelib --- howdoi/howdoi.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index f5cf1b8ec..0b0457b08 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -341,7 +341,11 @@ def _get_questions(links): def _get_answer(args, link): # pylint: disable=too-many-branches cache_key = _get_cache_key(link) - page = cache.get(cache_key) # pylint: disable=assignment-from-none + try: + # The cache should already be None if not found by cachelib, but as of cachelib 0.3.0 it is giving a FileNotFoundError + page = cache.get(cache_key) # pylint: disable=assignment-from-none + except FileNotFoundError: + page = None if not page: logging.info('Fetching page: %s', link) page = _get_result(link + '?answertab=votes') From fcf8ad553551f01f9141bda309c4882e6b55521f Mon Sep 17 00:00:00 2001 From: Benjamin Hafen Date: Sat, 14 Aug 2021 11:04:19 -0600 Subject: [PATCH 065/135] Rephrase cachelib comment to be shorter --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 0b0457b08..c14669768 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -342,7 +342,7 @@ def _get_questions(links): def _get_answer(args, link): # pylint: disable=too-many-branches cache_key = _get_cache_key(link) try: - # The cache should already be None if not found by cachelib, but as of cachelib 0.3.0 it is giving a FileNotFoundError + # As of cachelib 0.3.0, it is throwing a FileNotFoundError exception on cache miss page = cache.get(cache_key) # pylint: disable=assignment-from-none except FileNotFoundError: page = None From b8693c42f4711bf964c34267eb26ce6e14171b74 Mon Sep 17 00:00:00 2001 From: Benjamin Hafen Date: Sat, 14 Aug 2021 20:38:25 -0600 Subject: [PATCH 066/135] Preventing cachelib from printing a warning on cache miss --- howdoi/howdoi.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index c14669768..7a0b82d4d 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -188,6 +188,17 @@ def _get_result(url): raise error +def _get_from_cache(cache_key): + # As of cachelib 0.3.0, it internally logging a warning on cache miss + current_log_level = logging.getLogger().getEffectiveLevel() + # Reduce the log level so the warning is not printed + logging.getLogger().setLevel(logging.ERROR) + page = cache.get(cache_key) + # Restore the log level + logging.getLogger().setLevel(current_log_level) + return page + + def _add_links_to_text(element): hyperlinks = element.find('a') @@ -341,11 +352,7 @@ def _get_questions(links): def _get_answer(args, link): # pylint: disable=too-many-branches cache_key = _get_cache_key(link) - try: - # As of cachelib 0.3.0, it is throwing a FileNotFoundError exception on cache miss - page = cache.get(cache_key) # pylint: disable=assignment-from-none - except FileNotFoundError: - page = None + page = _get_from_cache(cache_key) # pylint: disable=assignment-from-none if not page: logging.info('Fetching page: %s', link) page = _get_result(link + '?answertab=votes') @@ -392,7 +399,7 @@ def _get_answer(args, link): # pylint: disable=too-many-branches def _get_links_with_cache(query): cache_key = _get_cache_key(query) - res = cache.get(cache_key) # pylint: disable=assignment-from-none + res = _get_from_cache(cache_key) # pylint: disable=assignment-from-none if res: logging.info('Using cached links') if res == CACHE_EMPTY_VAL: @@ -609,7 +616,7 @@ def howdoi(raw_query): if _is_help_query(args['query']): return _get_help_instructions() + '\n' - res = cache.get(cache_key) # pylint: disable=assignment-from-none + res = _get_from_cache(cache_key) # pylint: disable=assignment-from-none if res: logging.info('Using cached response (add -C to clear the cache)') From 875983c9ebdf4a1c9abad7afd63a68a9229e8eed Mon Sep 17 00:00:00 2001 From: Benjamin Hafen Date: Sat, 14 Aug 2021 20:45:14 -0600 Subject: [PATCH 067/135] Clean pylint errors --- howdoi/howdoi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 7a0b82d4d..fbec81afd 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -193,7 +193,7 @@ def _get_from_cache(cache_key): current_log_level = logging.getLogger().getEffectiveLevel() # Reduce the log level so the warning is not printed logging.getLogger().setLevel(logging.ERROR) - page = cache.get(cache_key) + page = cache.get(cache_key) # pylint: disable=assignment-from-none # Restore the log level logging.getLogger().setLevel(current_log_level) return page @@ -352,7 +352,7 @@ def _get_questions(links): def _get_answer(args, link): # pylint: disable=too-many-branches cache_key = _get_cache_key(link) - page = _get_from_cache(cache_key) # pylint: disable=assignment-from-none + page = _get_from_cache(cache_key) if not page: logging.info('Fetching page: %s', link) page = _get_result(link + '?answertab=votes') @@ -399,7 +399,7 @@ def _get_answer(args, link): # pylint: disable=too-many-branches def _get_links_with_cache(query): cache_key = _get_cache_key(query) - res = _get_from_cache(cache_key) # pylint: disable=assignment-from-none + res = _get_from_cache(cache_key) if res: logging.info('Using cached links') if res == CACHE_EMPTY_VAL: @@ -616,7 +616,7 @@ def howdoi(raw_query): if _is_help_query(args['query']): return _get_help_instructions() + '\n' - res = _get_from_cache(cache_key) # pylint: disable=assignment-from-none + res = _get_from_cache(cache_key) if res: logging.info('Using cached response (add -C to clear the cache)') From 88ff6d3bbbdaf65c4e21c5a8e72f588e208508d7 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Thu, 26 Aug 2021 05:38:39 -0700 Subject: [PATCH 068/135] Fix lint errors --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index d91fe4541..d682e292f 100644 --- a/setup.py +++ b/setup.py @@ -38,13 +38,13 @@ def run(self): def read(*names): - values = dict() + values = {} for name in names: value = '' for extension in ('.txt', '.md'): filename = name + extension if Path(filename).is_file(): - with open(filename) as in_file: + with open(filename) as in_file: # pylint: disable=unspecified-encoding value = in_file.read() break values[name] = value From 8b49c211bb46a557f2073b4d9f57a381a98336d7 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 30 Aug 2021 11:46:58 -0700 Subject: [PATCH 069/135] Release 2.0.18 --- CHANGES.txt | 4 ++++ howdoi/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index b76e26a41..00ead3f51 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +2.0.18 +------ +- Fixed issue with howdoi cache where cache misses would be printed to the console + 2.0.17 ------ - New documentation and mkdocs diff --git a/howdoi/__init__.py b/howdoi/__init__.py index ed6ed8969..2b6bf429f 100644 --- a/howdoi/__init__.py +++ b/howdoi/__init__.py @@ -1 +1 @@ -__version__ = '2.0.17' +__version__ = '2.0.18' From 291edabd7a45f7e7904f5722ca02b4a3b4d5cbf6 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Thu, 9 Sep 2021 18:50:06 -0400 Subject: [PATCH 070/135] Show error message when we aren't able to find an answer Fixes #383 --- howdoi/howdoi.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index fbec81afd..6c38bc6cb 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -91,6 +91,8 @@ SUPPORTED_HELP_QUERIES = ['use howdoi', 'howdoi', 'run howdoi', 'setup howdoi', 'do howdoi', 'howdoi howdoi', 'howdoi use howdoi'] +NO_RESULTS_MESSAGE = 'Sorry, couldn\'t find any help with that topic' + # variables for text formatting, prepend to string to begin text formatting. BOLD = '\033[1m' GREEN = '\033[92m' @@ -500,7 +502,7 @@ def _format_answers(args, res): next_ans = answer["answer"] if args["link"]: # if we only want links next_ans = answer["link"] - formatted_answers.append(next_ans) + formatted_answers.append(next_ans or NO_RESULTS_MESSAGE) return build_splitter().join(formatted_answers) @@ -627,7 +629,7 @@ def howdoi(raw_query): try: res = _get_answers(args) if not res: - message = 'Sorry, couldn\'t find any help with that topic' + message = NO_RESULTS_MESSAGE if not args['explain']: message = f'{message} (use --explain to learn why)' res = {'error': message} From 275b226da827145e93b0ea2ea24cd7ca918d16d4 Mon Sep 17 00:00:00 2001 From: justin-f-perez Date: Sat, 11 Sep 2021 12:19:44 -0500 Subject: [PATCH 071/135] filter empty results from answers * fix "total answers" logging message counting empty results * return False from `_get_answers` if the only results had no answer --- howdoi/howdoi.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index fbec81afd..76b731925 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -445,12 +445,14 @@ def _get_answers(args): _get_answer_worker, [(args, link) for link in question_links] ) - - for idx, _ in enumerate(answers): - answers[idx]['position'] = idx + 1 - - logging.info('Total answers returned: %s', len(answers)) - return answers + + answers = [a for a in answers if a.get('answer')] + for i, answer in enumerate(answers, 1): + answer['position'] = i + + logging.info('Total answers returned: {total}'.format(total=i)) + + return answers or False def _get_answer_worker(args, link): From 9fee56d0da082c9e759bef176b436f650ce4f099 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 17 Sep 2021 09:00:42 -0400 Subject: [PATCH 072/135] Fix whitespace error --- howdoi/howdoi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 557778e2a..a4a2c0776 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -447,13 +447,13 @@ def _get_answers(args): _get_answer_worker, [(args, link) for link in question_links] ) - + answers = [a for a in answers if a.get('answer')] for i, answer in enumerate(answers, 1): answer['position'] = i - + logging.info('Total answers returned: {total}'.format(total=i)) - + return answers or False From e689941190b943a99d9c59c7d60b1d575b1d62d1 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 17 Sep 2021 09:05:29 -0400 Subject: [PATCH 073/135] Fix potential missing variable --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index a4a2c0776..cec263555 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -452,7 +452,7 @@ def _get_answers(args): for i, answer in enumerate(answers, 1): answer['position'] = i - logging.info('Total answers returned: {total}'.format(total=i)) + logging.info('Total answers returned: %s', len(answers)) return answers or False From 18c5fff3fab974428991632a307b5f85caf9db7f Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 17 Sep 2021 09:22:39 -0400 Subject: [PATCH 074/135] Log links when we find them --- howdoi/howdoi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index cec263555..4f774419d 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -439,7 +439,8 @@ def _get_answers(args): question_links = question_links[initial_pos:final_pos] search_engine = os.getenv('HOWDOI_SEARCH_ENGINE', 'google') - logging.info('%s links found on %s: %s', URL, search_engine, len(question_links)) + logging.info('Links from %s found on %s: %s', URL, search_engine, len(question_links)) + logging.info('URL: %s', '\n '.join(question_links)) logging.info('Answers requested: %s, Starting at position: %s', args["num_answers"], args['pos']) with Pool() as pool: From 6225d7629f493ab788f2251000e3b80cc67332e1 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 17 Sep 2021 09:25:56 -0400 Subject: [PATCH 075/135] Fix f-string issues --- howdoi/howdoi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 4f774419d..95d798f45 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -91,7 +91,7 @@ SUPPORTED_HELP_QUERIES = ['use howdoi', 'howdoi', 'run howdoi', 'setup howdoi', 'do howdoi', 'howdoi howdoi', 'howdoi use howdoi'] -NO_RESULTS_MESSAGE = 'Sorry, couldn\'t find any help with that topic' +NO_RESULTS_MESSAGE = "Sorry, couldn't find any help with that topic" # variables for text formatting, prepend to string to begin text formatting. BOLD = '\033[1m' @@ -165,7 +165,7 @@ def get_proxies(): for key, value in proxies.items(): if key.startswith('http'): if not value.startswith('http'): - filtered_proxies[key] = 'http://%s' % value + filtered_proxies[key] = f'http://{value}' else: filtered_proxies[key] = value return filtered_proxies @@ -753,7 +753,7 @@ def perform_sanity_check(): exit_code = 0 for engine in ['google']: # 'bing' and 'duckduckgo' throw various block errors - print('Checking {}...'.format(engine)) + print(f'Checking {engine}...') try: _sanity_check(engine) except (GoogleValidationError, BingValidationError, DDGValidationError): From 569b20c240a9a25af24e6219148ecd214ac034c3 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 17 Sep 2021 09:32:10 -0400 Subject: [PATCH 076/135] Disable linting issue --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index d682e292f..d2d69799b 100644 --- a/setup.py +++ b/setup.py @@ -51,6 +51,7 @@ def read(*names): return values +# pylint: disable-next=consider-using-f-string long_description = """ %(README)s From 50c0f232064a355ba78e81865ba6fa89389f3226 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 17 Sep 2021 09:42:40 -0400 Subject: [PATCH 077/135] Fix test Use better linting syntax --- setup.py | 4 +++- test_howdoi.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index d2d69799b..7915237ee 100644 --- a/setup.py +++ b/setup.py @@ -51,7 +51,7 @@ def read(*names): return values -# pylint: disable-next=consider-using-f-string +# pylint: disable=consider-using-f-string long_description = """ %(README)s @@ -60,6 +60,8 @@ def read(*names): %(CHANGES)s """ % read('README', 'CHANGES') +# pylint: enable=consider-using-f-string + setup( name='howdoi', diff --git a/test_howdoi.py b/test_howdoi.py index c3bcef606..42ffec20b 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -267,7 +267,7 @@ def test_help_queries(self): def test_missing_pre_or_code_query(self): output = howdoi.howdoi(self.query_without_code_or_pre_block) self.assertTrue(output) - self.assertIn('XML elements present in a XML', output) + self.assertIn('John', output) def test_format_url_to_filename(self): url = 'https://stackoverflow.com/questions/tagged/cat' From b15f35af9c5aab36fc8a108a1a3d256f277e991c Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Fri, 17 Sep 2021 09:51:47 -0400 Subject: [PATCH 078/135] Put test back the way it was --- ...element20node20and20Text20Nodehlen.html.gz | Bin 54847 -> 38599 bytes test_howdoi.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/page_cache/httpswwwgooglecomsearchqsitestackoverflowcom20Difference20between20element20node20and20Text20Nodehlen.html.gz b/page_cache/httpswwwgooglecomsearchqsitestackoverflowcom20Difference20between20element20node20and20Text20Nodehlen.html.gz index c27142795dbe6e374200aef868a2352765189a9d..94414f84e09ee3f19363650b3735cdca90c706bf 100644 GIT binary patch literal 38599 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 j8<*|=o4P0nUqM literal 54847 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 M15{GJiBC2I001D>_y7O^ diff --git a/test_howdoi.py b/test_howdoi.py index 42ffec20b..c3bcef606 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -267,7 +267,7 @@ def test_help_queries(self): def test_missing_pre_or_code_query(self): output = howdoi.howdoi(self.query_without_code_or_pre_block) self.assertTrue(output) - self.assertIn('John', output) + self.assertIn('XML elements present in a XML', output) def test_format_url_to_filename(self): url = 'https://stackoverflow.com/questions/tagged/cat' From 202d90f8bab93a926dd74a1196582bd365cdd34f Mon Sep 17 00:00:00 2001 From: ykskks Date: Thu, 23 Sep 2021 14:40:21 +0900 Subject: [PATCH 079/135] drop python2 support --- howdoi/howdoi.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 95d798f45..9358e794a 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -812,12 +812,9 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man if os.getenv('HOWDOI_COLORIZE'): args['color'] = True - utf8_result = howdoi(args).encode('utf-8', 'ignore') - if sys.version < '3': - print(utf8_result) - else: - # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 - sys.stdout.buffer.write(utf8_result) + result = howdoi(args) + print(result) + # close the session to release connection howdoi_session.close() From 4d615cd2805ab6d961dbfd31361635b40a00cce1 Mon Sep 17 00:00:00 2001 From: ykskks Date: Sat, 25 Sep 2021 10:48:15 +0900 Subject: [PATCH 080/135] write utf-8 to stdout --- howdoi/howdoi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 9358e794a..5de502c55 100755 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -812,8 +812,9 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man if os.getenv('HOWDOI_COLORIZE'): args['color'] = True - result = howdoi(args) - print(result) + utf8_result = howdoi(args).encode('utf-8', 'ignore') + # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 + sys.stdout.buffer.write(utf8_result) # close the session to release connection howdoi_session.close() From 0847874a3bd4008207c2f5ef58329915d5cc7d61 Mon Sep 17 00:00:00 2001 From: Vividha Date: Mon, 11 Oct 2021 20:12:07 +0530 Subject: [PATCH 081/135] added pr template --- .github/PULL_REQUEST_TEMPLATE.md | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..854ab7649 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,35 @@ +## Description: +- Tasks solved + + - Link to respective files + +- Links to issues solved + +## Pull Request type: + +- Bug fixes +- New feature +- Improvement +- Refactoring +- Documentation update +- Securtiy fix + +## How to test: + +Please provide detailed instructions for testing your changes locally, including expected response/behavior. + +## Pull Request checklist: + +- [ ] Check that code compiles. +- [ ] Attach screenshots of expected behavior. +- [ ] Check that there are no confidential files like `.env` included. +- [ ] Request review from the maintainers. +- [ ] For bug fixes, changes to directory structure, make sure docs are updated. +- [ ] The changes pass tests locally. +- [ ] The changes don't break existing features. + +## Known bugs (if any): + +If there are bugs in your current changes, you can still open the PR, and mention the bugs you found. Propose further changes that can help fix bugs in your current changes. + + From 830f88b44849a6566ce3924396b1de710762fa94 Mon Sep 17 00:00:00 2001 From: Vividha Date: Mon, 11 Oct 2021 20:18:07 +0530 Subject: [PATCH 082/135] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 854ab7649..7c28931c8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -12,7 +12,7 @@ - Improvement - Refactoring - Documentation update -- Securtiy fix +- Security fix ## How to test: From 2b8a5d514b8fac3302f9d0d84e2f170159faeada Mon Sep 17 00:00:00 2001 From: Vividha Date: Tue, 12 Oct 2021 22:52:33 +0530 Subject: [PATCH 083/135] fixed linting --- .github/PULL_REQUEST_TEMPLATE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 854ab7649..68052f8a2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,5 @@ ## Description: + - Tasks solved - Link to respective files @@ -16,10 +17,11 @@ ## How to test: -Please provide detailed instructions for testing your changes locally, including expected response/behavior. +Please provide detailed instructions for testing your changes locally, including expected response/behavior. ## Pull Request checklist: +- [ ] Read the (contributing_to_howdoi.md)[https://github.com/gleitz/howdoi/blob/master/docs/contributing_to_howdoi.md] - [ ] Check that code compiles. - [ ] Attach screenshots of expected behavior. - [ ] Check that there are no confidential files like `.env` included. @@ -30,6 +32,4 @@ Please provide detailed instructions for testing your changes locally, including ## Known bugs (if any): -If there are bugs in your current changes, you can still open the PR, and mention the bugs you found. Propose further changes that can help fix bugs in your current changes. - - +If there are bugs in your current changes, you can still open the PR, and mention the bugs you found. Propose further changes that can help fix bugs in your current changes. From b45b8d3065af06f4946322395a14cfeb26dda33c Mon Sep 17 00:00:00 2001 From: Vividha Date: Tue, 12 Oct 2021 22:57:09 +0530 Subject: [PATCH 084/135] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 635bfd96a..f5a96b13b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -21,7 +21,7 @@ Please provide detailed instructions for testing your changes locally, including ## Pull Request checklist: -- [ ] Read the (contributing_to_howdoi.md)[https://github.com/gleitz/howdoi/blob/master/docs/contributing_to_howdoi.md] +- [ ] Read the [contributing_to_howdoi.md](https://github.com/gleitz/howdoi/blob/master/docs/contributing_to_howdoi.md) - [ ] Check that code compiles. - [ ] Attach screenshots of expected behavior. - [ ] Check that there are no confidential files like `.env` included. From 29b05f9d0fb90e0f2cbbdb6ed8752f2afe1ce955 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 18 Oct 2021 08:43:16 -0700 Subject: [PATCH 085/135] Update the pull request template Add specific instructions for running tests and linting --- .github/PULL_REQUEST_TEMPLATE.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f5a96b13b..b04270628 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -22,14 +22,14 @@ Please provide detailed instructions for testing your changes locally, including ## Pull Request checklist: - [ ] Read the [contributing_to_howdoi.md](https://github.com/gleitz/howdoi/blob/master/docs/contributing_to_howdoi.md) -- [ ] Check that code compiles. - [ ] Attach screenshots of expected behavior. +- [ ] The changes pass tests locally (`nosetests`). +- [ ] There are no linting errors (`python setup.py lint`). +- [ ] The changes don't break existing features. - [ ] Check that there are no confidential files like `.env` included. - [ ] Request review from the maintainers. -- [ ] For bug fixes, changes to directory structure, make sure docs are updated. -- [ ] The changes pass tests locally. -- [ ] The changes don't break existing features. +- [ ] For bug fixes or changes to directory structure, make sure docs are updated. ## Known bugs (if any): -If there are bugs in your current changes, you can still open the PR, and mention the bugs you found. Propose further changes that can help fix bugs in your current changes. +If there are bugs in your current changes you can still open the PR and mention the bugs you found. Propose further changes that can help fix bugs in your current changes. From 6a751ce7163864411a33ee84293c10499cd49775 Mon Sep 17 00:00:00 2001 From: V2dha Date: Fri, 22 Oct 2021 21:18:21 +0530 Subject: [PATCH 086/135] Update pylint to v2.11.1 & pylint tests --- .pre-commit-config.yaml | 4 ++-- docs/contributing_to_howdoi.md | 2 +- requirements/dev.txt | 2 +- setup.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2d6c14aad..0efd7315e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,8 +7,8 @@ repos: - "--config=.flake8rc" - repo: https://github.com/PyCQA/pylint/ - rev: v2.8.2 + rev: v2.11.1 hooks: - id: pylint args: - - "--rcfile=.pylintrc" \ No newline at end of file + - "howdoi *.py --rcfile=.pylintrc" \ No newline at end of file diff --git a/docs/contributing_to_howdoi.md b/docs/contributing_to_howdoi.md index 4f06624ca..bb3631cf4 100644 --- a/docs/contributing_to_howdoi.md +++ b/docs/contributing_to_howdoi.md @@ -22,7 +22,7 @@ Follow the page [Setting up the development environment](http://gleitz.github.io howdoi create a pull request on Github ``` in your command line and follow the steps written in it. -- Each PR made should pass all the tests and should not have any flake8 or pylint errors. Github runs tests on each PR but we before that, you should run `python setup.py` lint which will run pylint and flake8. +- Each PR made should pass all the tests and should not have any flake8 or pylint errors. Github runs tests on each PR but we before that, you should run `python setup.py lint` which will run pylint and flake8. - Once your commit passes all the tests, make a PR and wait for it to be reviewed and merged. diff --git a/requirements/dev.txt b/requirements/dev.txt index 35d1b2970..3ffe9a7b2 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,6 +1,6 @@ # Contains development specific requirements and imports common requirements flake8==3.9.2 -pylint==2.8.2 +pylint==2.11.1 pre-commit==2.13.0 twine==3.4.1 -r common.txt diff --git a/setup.py b/setup.py index 7915237ee..bf390f948 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ def finalize_options(self): def run(self): commands = {'Flake8': 'flake8 --config=.flake8rc .'.split(), - 'Pylint': 'pylint --rcfile=.pylintrc howdoi'.split()} + 'Pylint': 'pylint howdoi *.py --rcfile=.pylintrc'.split()} for linter, command in commands.items(): try: From 714f0f1a5a73d4322744f659f9a38edd2fef30f7 Mon Sep 17 00:00:00 2001 From: Vividha Date: Sat, 23 Oct 2021 22:30:06 +0530 Subject: [PATCH 087/135] Added patch, fixed minor documentation --- .pre-commit-config.yaml | 2 +- docs/development_env.md | 2 +- setup.py | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0efd7315e..0a191991b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,4 +11,4 @@ repos: hooks: - id: pylint args: - - "howdoi *.py --rcfile=.pylintrc" \ No newline at end of file + - "howdoi *.py --rcfile=.pylintrc" diff --git a/docs/development_env.md b/docs/development_env.md index 76097f594..1557ac823 100644 --- a/docs/development_env.md +++ b/docs/development_env.md @@ -16,7 +16,7 @@ - Install all the required packages: ``` - $ pip install -r requirements.txt + $ pip install -r requirements/dev.txt ``` - Running from command line : diff --git a/setup.py b/setup.py index bf390f948..157ce0ab1 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import glob import subprocess from pathlib import Path from distutils.cmd import Command @@ -23,8 +24,9 @@ def finalize_options(self): pass def run(self): + local_python_files_str = ' '.join(glob.glob('*.py')) commands = {'Flake8': 'flake8 --config=.flake8rc .'.split(), - 'Pylint': 'pylint howdoi *.py --rcfile=.pylintrc'.split()} + 'Pylint': f'pylint howdoi {local_python_files_str} --rcfile=.pylintrc'.split()} for linter, command in commands.items(): try: From c6a4b053aa53c747efd14df163021d7f82b4bc2e Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Tue, 26 Oct 2021 13:10:04 -0700 Subject: [PATCH 088/135] Fix Python version for the early warning system. Was getting this error on Python 3.10 for pathlib: ``` ImportError: cannot import name 'Sequence' from 'collections' ``` --- .github/workflows/docs.yml | 2 ++ .github/workflows/early-warning.yml | 2 ++ .github/workflows/python-non-master.yml | 3 +-- .github/workflows/python.yml | 3 +-- requirements/dev.txt | 1 + 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 07a1591c8..f66bfc931 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,6 +14,8 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Install Pip run: python -m pip install --upgrade pip diff --git a/.github/workflows/early-warning.yml b/.github/workflows/early-warning.yml index 5095970d9..b68309d7c 100644 --- a/.github/workflows/early-warning.yml +++ b/.github/workflows/early-warning.yml @@ -15,6 +15,8 @@ jobs: steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 + with: + python-version: '3.9' - name: Setup environment run: pip install -r requirements.txt diff --git a/.github/workflows/python-non-master.yml b/.github/workflows/python-non-master.yml index 2544dc607..84f1dbc58 100644 --- a/.github/workflows/python-non-master.yml +++ b/.github/workflows/python-non-master.yml @@ -27,8 +27,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 nose pylint - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + if [ -f requirements/dev.txt ]; then pip install -r requirements/dev.txt; fi - name: Lint with flake8 run: | flake8 . --count --show-source --statistics diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 3d0ea94e0..6859d7f28 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -23,8 +23,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 nose pylint - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + if [ -f requirements/dev.txt ]; then pip install -r requirements/dev.txt; fi - name: Lint with flake8 run: | flake8 . --count --show-source --statistics diff --git a/requirements/dev.txt b/requirements/dev.txt index 3ffe9a7b2..566184a1f 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,5 +1,6 @@ # Contains development specific requirements and imports common requirements flake8==3.9.2 +nose==1.3.7 pylint==2.11.1 pre-commit==2.13.0 twine==3.4.1 From f895e7c7eeb852a55cda33a4ac472a0f83654a42 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 7 Feb 2022 13:28:04 -0800 Subject: [PATCH 089/135] Perhaps we do not need pathlib for Python 3.4+ Fixes https://github.com/gleitz/howdoi/issues/447 --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/early-warning.yml | 2 +- .github/workflows/python-non-master.yml | 4 ++-- .github/workflows/python.yml | 4 ++-- requirements/common.txt | 3 +-- requirements/dev.txt | 2 +- setup.py | 1 + 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b04270628..5674b9e76 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -23,7 +23,7 @@ Please provide detailed instructions for testing your changes locally, including - [ ] Read the [contributing_to_howdoi.md](https://github.com/gleitz/howdoi/blob/master/docs/contributing_to_howdoi.md) - [ ] Attach screenshots of expected behavior. -- [ ] The changes pass tests locally (`nosetests`). +- [ ] The changes pass tests locally (`nose2`). - [ ] There are no linting errors (`python setup.py lint`). - [ ] The changes don't break existing features. - [ ] Check that there are no confidential files like `.env` included. diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f66bfc931..a17f55e8e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.9' + python-version: '3.10' - name: Install Pip run: python -m pip install --upgrade pip diff --git a/.github/workflows/early-warning.yml b/.github/workflows/early-warning.yml index b68309d7c..4bede3f26 100644 --- a/.github/workflows/early-warning.yml +++ b/.github/workflows/early-warning.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.9' + python-version: '3.10' - name: Setup environment run: pip install -r requirements.txt diff --git a/.github/workflows/python-non-master.yml b/.github/workflows/python-non-master.yml index 84f1dbc58..40663bdb4 100644 --- a/.github/workflows/python-non-master.yml +++ b/.github/workflows/python-non-master.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.6, 3.7, 3.8, 3.9, '3.10'] steps: - uses: actions/checkout@v2 @@ -36,4 +36,4 @@ jobs: pylint howdoi *.py --rcfile=.pylintrc - name: Test with nose run: | - nosetests + nose2 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 6859d7f28..984b64ad9 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.6, 3.7, 3.8, 3.9, '3.10'] steps: - uses: actions/checkout@v2 @@ -32,4 +32,4 @@ jobs: pylint howdoi *.py --rcfile=.pylintrc - name: Test with nose run: | - nosetests + nose2 diff --git a/requirements/common.txt b/requirements/common.txt index 5b0bc1fd8..cf53f6d5a 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -1,4 +1,4 @@ -# Contains common requirements +# Contains common requirements Pygments>=2.3.1 argparse==1.4.0 cssselect==1.1.0 @@ -8,4 +8,3 @@ requests==2.24.0 cachelib==0.1.1 appdirs==1.4.4 keep==2.9 -pathlib==1.0.1 diff --git a/requirements/dev.txt b/requirements/dev.txt index 566184a1f..4a0b36779 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,6 +1,6 @@ # Contains development specific requirements and imports common requirements flake8==3.9.2 -nose==1.3.7 +nose2==0.6.0 pylint==2.11.1 pre-commit==2.13.0 twine==3.4.1 diff --git a/setup.py b/setup.py index 157ce0ab1..f765af8e7 100644 --- a/setup.py +++ b/setup.py @@ -80,6 +80,7 @@ def read(*names): "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Topic :: Documentation", ], keywords='howdoi help console command line answer', From ff1b5a14254627d462d73fba0d96f85cc6a8c8a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 01:55:47 +0000 Subject: [PATCH 090/135] Bump pathval from 1.1.0 to 1.1.1 in /extension/code-editor-integration Bumps [pathval](https://github.com/chaijs/pathval) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/chaijs/pathval/releases) - [Changelog](https://github.com/chaijs/pathval/blob/master/CHANGELOG.md) - [Commits](https://github.com/chaijs/pathval/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: pathval dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/code-editor-integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index 06c22697c..1c768c300 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -2382,9 +2382,9 @@ } }, "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "picomatch": { From 3af7040353008783aced771ecbe8362c6e1fd45b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 02:06:00 +0000 Subject: [PATCH 091/135] Bump pathval from 1.1.0 to 1.1.1 in /extension/vscode-howdoi Bumps [pathval](https://github.com/chaijs/pathval) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/chaijs/pathval/releases) - [Changelog](https://github.com/chaijs/pathval/blob/master/CHANGELOG.md) - [Commits](https://github.com/chaijs/pathval/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: pathval dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/vscode-howdoi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/vscode-howdoi/package-lock.json b/extension/vscode-howdoi/package-lock.json index 992fb2aab..3138b00a0 100644 --- a/extension/vscode-howdoi/package-lock.json +++ b/extension/vscode-howdoi/package-lock.json @@ -1501,9 +1501,9 @@ "dev": true }, "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "picomatch": { From 61ddc8b0271482ad46cfda3023cae0f151797430 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Feb 2022 19:03:17 +0000 Subject: [PATCH 092/135] Bump ajv from 6.12.2 to 6.12.6 in /extension/code-editor-integration Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.2 to 6.12.6. - [Release notes](https://github.com/ajv-validator/ajv/releases) - [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.2...v6.12.6) --- updated-dependencies: - dependency-name: ajv dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/code-editor-integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index 06c22697c..4cdda6db6 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -369,9 +369,9 @@ "dev": true }, "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", From a270049fb4b84c3fe68f53ec1aff49ba2bceedc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Feb 2022 20:42:58 +0000 Subject: [PATCH 093/135] Bump ajv from 6.12.2 to 6.12.6 in /extension/vscode-howdoi Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.2 to 6.12.6. - [Release notes](https://github.com/ajv-validator/ajv/releases) - [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.2...v6.12.6) --- updated-dependencies: - dependency-name: ajv dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/vscode-howdoi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/vscode-howdoi/package-lock.json b/extension/vscode-howdoi/package-lock.json index 992fb2aab..8d63247fc 100644 --- a/extension/vscode-howdoi/package-lock.json +++ b/extension/vscode-howdoi/package-lock.json @@ -160,9 +160,9 @@ } }, "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", From 1a67cd35d261a1649f7c4a1fa28eb101d46edbe9 Mon Sep 17 00:00:00 2001 From: Vividha Date: Tue, 23 Nov 2021 12:54:30 +0530 Subject: [PATCH 094/135] added syntax highlighting using rich library --- howdoi/howdoi.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) mode change 100755 => 100644 howdoi/howdoi.py diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py old mode 100755 new mode 100644 index 5de502c55..245d59638 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -36,6 +36,8 @@ from pygments.lexers import guess_lexer, get_lexer_by_name from pygments.formatters.terminal import TerminalFormatter from pygments.util import ClassNotFound +from rich.syntax import Syntax +from rich.console import Console from pyquery import PyQuery as pq from requests.exceptions import ConnectionError as RequestsConnectionError @@ -314,11 +316,12 @@ def get_link_at_pos(links, position): link = links[-1] return link +lexer = None def _format_output(args, code): - if not args['color']: + if not args['color']: return code - lexer = None + global lexer # try to find a lexer using the StackOverflow tags # or the query arguments @@ -340,7 +343,6 @@ def _format_output(args, code): lexer, TerminalFormatter(bg='dark')) - def _is_question(link): for fragment in BLOCKED_QUESTION_FRAGMENTS: if fragment in link: @@ -812,9 +814,16 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man if os.getenv('HOWDOI_COLORIZE'): args['color'] = True - utf8_result = howdoi(args).encode('utf-8', 'ignore') + result = howdoi(args) # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 - sys.stdout.buffer.write(utf8_result) + # sys.stdout.buffer.write(utf8_result) + syntax = Syntax(result, + lexer, + background_color = "default", + line_numbers=False) + + console = Console() + console.print(syntax) # close the session to release connection howdoi_session.close() From 0e79c4068937911932de300ddae8310bb8c04116 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Sat, 19 Feb 2022 11:35:46 -0800 Subject: [PATCH 095/135] modified requirements.txt to add rich library --- requirements/common.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements/common.txt b/requirements/common.txt index cf53f6d5a..150dde2c4 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -8,3 +8,4 @@ requests==2.24.0 cachelib==0.1.1 appdirs==1.4.4 keep==2.9 +rich==10.13.0 From 9a21e8a784682e1a263715e5076299bac883a17f Mon Sep 17 00:00:00 2001 From: V2dha Date: Tue, 23 Nov 2021 13:11:33 +0530 Subject: [PATCH 096/135] Fix Linting Errors --- howdoi/howdoi.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 245d59638..e492257f8 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -316,12 +316,10 @@ def get_link_at_pos(links, position): link = links[-1] return link -lexer = None def _format_output(args, code): - if not args['color']: + if not args['color']: return code - global lexer # try to find a lexer using the StackOverflow tags # or the query arguments @@ -343,6 +341,7 @@ def _format_output(args, code): lexer, TerminalFormatter(bg='dark')) + def _is_question(link): for fragment in BLOCKED_QUESTION_FRAGMENTS: if fragment in link: @@ -817,11 +816,7 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man result = howdoi(args) # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 # sys.stdout.buffer.write(utf8_result) - syntax = Syntax(result, - lexer, - background_color = "default", - line_numbers=False) - + syntax = Syntax(result, "python", background_color="default", line_numbers=False) console = Console() console.print(syntax) From 9002c9b66f7b5a5dbda3af987c135e921c9c3940 Mon Sep 17 00:00:00 2001 From: V2dha Date: Thu, 25 Nov 2021 14:38:19 +0530 Subject: [PATCH 097/135] assign lexer as None as previous code --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index e492257f8..54d9c65fc 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -320,7 +320,7 @@ def get_link_at_pos(links, position): def _format_output(args, code): if not args['color']: return code - + lexer = None # try to find a lexer using the StackOverflow tags # or the query arguments for keyword in args['query'].split() + args['tags']: From ebbd1e1c44c8ca867d699d41b4821dcadb9cb5d3 Mon Sep 17 00:00:00 2001 From: V2dha Date: Mon, 29 Nov 2021 21:16:03 +0530 Subject: [PATCH 098/135] using guess_lexer to get language of code returned --- howdoi/howdoi.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 54d9c65fc..ccc52877a 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -814,13 +814,12 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man args['color'] = True result = howdoi(args) - # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 - # sys.stdout.buffer.write(utf8_result) - syntax = Syntax(result, "python", background_color="default", line_numbers=False) + lang = guess_lexer(result).name + syntax = Syntax(result, lang, background_color="default", line_numbers=False) console = Console() console.print(syntax) - # close the session to release connection + # close the session to release connectione howdoi_session.close() From bd88a5932246ca42c1978d97f47008843159d24f Mon Sep 17 00:00:00 2001 From: V2dha Date: Mon, 29 Nov 2021 21:28:15 +0530 Subject: [PATCH 099/135] fixed typo --- howdoi/howdoi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index ccc52877a..e46e29c81 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -819,7 +819,7 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man console = Console() console.print(syntax) - # close the session to release connectione + # close the session to release connection howdoi_session.close() From eb0aca291fc6bc8a9dd94037d77263445d0713d5 Mon Sep 17 00:00:00 2001 From: Vividha Date: Wed, 1 Dec 2021 11:59:25 +0530 Subject: [PATCH 100/135] added rich library to setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index f765af8e7..4e2eb2c36 100644 --- a/setup.py +++ b/setup.py @@ -105,6 +105,7 @@ def read(*names): 'cachelib', 'appdirs', 'keep', + 'rich' ], cmdclass={ 'lint': Lint From 88873b5c5ee000986fd71242ba069b05547e7e5e Mon Sep 17 00:00:00 2001 From: Vividha Date: Wed, 1 Dec 2021 21:46:28 +0530 Subject: [PATCH 101/135] replaced pygment's highlight with rich's syntax func --- howdoi/howdoi.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index e46e29c81..b17429a9e 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -32,9 +32,7 @@ from keep import utils as keep_utils -from pygments import highlight from pygments.lexers import guess_lexer, get_lexer_by_name -from pygments.formatters.terminal import TerminalFormatter from pygments.util import ClassNotFound from rich.syntax import Syntax from rich.console import Console @@ -333,13 +331,12 @@ def _format_output(args, code): # no lexer found above, use the guesser if not lexer: try: - lexer = guess_lexer(code) + lexer = guess_lexer(code).name except ClassNotFound: return code - return highlight(code, - lexer, - TerminalFormatter(bg='dark')) + syntax = Syntax(code, lexer, background_color="default", line_numbers=False) + return syntax def _is_question(link): @@ -814,10 +811,8 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man args['color'] = True result = howdoi(args) - lang = guess_lexer(result).name - syntax = Syntax(result, lang, background_color="default", line_numbers=False) console = Console() - console.print(syntax) + console.print(result) # close the session to release connection howdoi_session.close() From 4c314cd04ac7d89bb33046b3404069a1005926a2 Mon Sep 17 00:00:00 2001 From: Vividha Date: Mon, 6 Dec 2021 21:58:08 +0530 Subject: [PATCH 102/135] changed the output result --- howdoi/howdoi.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index b17429a9e..d612906a0 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -811,8 +811,11 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man args['color'] = True result = howdoi(args) - console = Console() - console.print(result) + if args['color']: + console = Console() + console.print(result) + else: + sys.stdout.buffer.write(result.encode('utf-8', 'ignore')) # close the session to release connection howdoi_session.close() From 35ab3063087d42bdf9e93a278b2a6f4e6fb64802 Mon Sep 17 00:00:00 2001 From: Vividha Date: Wed, 8 Dec 2021 21:36:40 +0530 Subject: [PATCH 103/135] added export_text in _format_output --- howdoi/howdoi.py | 6 ++++-- test_howdoi.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index d612906a0..978717fbe 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -323,7 +323,7 @@ def _format_output(args, code): # or the query arguments for keyword in args['query'].split() + args['tags']: try: - lexer = get_lexer_by_name(keyword) + lexer = get_lexer_by_name(keyword).name break except ClassNotFound: pass @@ -336,7 +336,9 @@ def _format_output(args, code): return code syntax = Syntax(code, lexer, background_color="default", line_numbers=False) - return syntax + console = Console(record=True) + console.print(syntax) + return console.export_text(styles=True) def _is_question(link): diff --git a/test_howdoi.py b/test_howdoi.py index c3bcef606..7baa251d2 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -195,8 +195,8 @@ def test_colorize(self): query = self.queries[0] normal = howdoi.howdoi(query) colorized = howdoi.howdoi('-c ' + query) - self.assertTrue(normal.find('[39;') == -1) - self.assertTrue(colorized.find('[39;') != -1) + self.assertTrue(normal.find('[38;') == -1) + self.assertTrue(colorized.find('[38;') != -1) # pylint: disable=line-too-long def test_get_text_without_links(self): From 3d19a07b0b7b4abc05b3ac30b845566166e39884 Mon Sep 17 00:00:00 2001 From: Vividha Date: Mon, 13 Dec 2021 15:39:14 +0530 Subject: [PATCH 104/135] applied console-patch-from-gleitz.patch --- howdoi/howdoi.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 978717fbe..61e763e1b 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -337,8 +337,9 @@ def _format_output(args, code): syntax = Syntax(code, lexer, background_color="default", line_numbers=False) console = Console(record=True) - console.print(syntax) - return console.export_text(styles=True) + with console.capture() as capture: + console.print(syntax) + return capture.get() def _is_question(link): @@ -813,11 +814,7 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man args['color'] = True result = howdoi(args) - if args['color']: - console = Console() - console.print(result) - else: - sys.stdout.buffer.write(result.encode('utf-8', 'ignore')) + sys.stdout.buffer.write(result.encode('utf-8', 'ignore')) # close the session to release connection howdoi_session.close() From 8269efb22be1252bfdc00d1bda01026236dfb783 Mon Sep 17 00:00:00 2001 From: Vividha Date: Mon, 13 Dec 2021 15:46:38 +0530 Subject: [PATCH 105/135] test_commit --- test_howdoi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_howdoi.py b/test_howdoi.py index 7baa251d2..c3bcef606 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -195,8 +195,8 @@ def test_colorize(self): query = self.queries[0] normal = howdoi.howdoi(query) colorized = howdoi.howdoi('-c ' + query) - self.assertTrue(normal.find('[38;') == -1) - self.assertTrue(colorized.find('[38;') != -1) + self.assertTrue(normal.find('[39;') == -1) + self.assertTrue(colorized.find('[39;') != -1) # pylint: disable=line-too-long def test_get_text_without_links(self): From aa55d9bcb0eb41e6ca34816c2524ebc84949ea6b Mon Sep 17 00:00:00 2001 From: Vividha Date: Mon, 13 Dec 2021 15:51:51 +0530 Subject: [PATCH 106/135] Revert "test_commit" This reverts commit 6fb88d3e3650b9ed1a7cc4cad735d1cb44b6c659. --- test_howdoi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_howdoi.py b/test_howdoi.py index c3bcef606..7baa251d2 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -195,8 +195,8 @@ def test_colorize(self): query = self.queries[0] normal = howdoi.howdoi(query) colorized = howdoi.howdoi('-c ' + query) - self.assertTrue(normal.find('[39;') == -1) - self.assertTrue(colorized.find('[39;') != -1) + self.assertTrue(normal.find('[38;') == -1) + self.assertTrue(colorized.find('[38;') != -1) # pylint: disable=line-too-long def test_get_text_without_links(self): From c53b6a179a09159740de2c06fb87b194e810f839 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Sat, 19 Feb 2022 12:36:25 -0800 Subject: [PATCH 107/135] Disable colorization check in Github I tried a lot of different things to make it work ``` env: PY_COLORS: '1' ANSIBLE_FORCE_COLOR: '1' FORCE_COLOR: '1' ``` I also tried ``` export TERM=xterm-256color; ``` But Github refuses to colorize. Seems to be a problem with Github Actions not being a `tty`. https://github.com/actions/runner/issues/241 This doesn't seem to be a priority for Github, so we simply disable the test in that environment. --- test_howdoi.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test_howdoi.py b/test_howdoi.py index 7baa251d2..35aac5254 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -195,8 +195,12 @@ def test_colorize(self): query = self.queries[0] normal = howdoi.howdoi(query) colorized = howdoi.howdoi('-c ' + query) - self.assertTrue(normal.find('[38;') == -1) - self.assertTrue(colorized.find('[38;') != -1) + + # There is currently an issue with Github actions and colorization + # so do not run checks if we are running in Github + if "GITHUB_ACTION" not in os.environ: + self.assertTrue(normal.find('[38;') == -1) + self.assertTrue(colorized.find('[38;') != -1) # pylint: disable=line-too-long def test_get_text_without_links(self): From e1baed7692b312ffeaf4ad897468e3b31d81fb6e Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Sat, 19 Feb 2022 12:50:20 -0800 Subject: [PATCH 108/135] Put back explanation for using UTF-8 result --- howdoi/howdoi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 61e763e1b..dd97715ab 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -813,8 +813,9 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man if os.getenv('HOWDOI_COLORIZE'): args['color'] = True - result = howdoi(args) - sys.stdout.buffer.write(result.encode('utf-8', 'ignore')) + utf8_result = howdoi(args).encode('utf-8', 'ignore') + # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 + sys.stdout.buffer.write(utf8_result) # close the session to release connection howdoi_session.close() From 760bee75ad325f5df5127362d5b220556ba1b4c9 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Sat, 19 Feb 2022 12:58:56 -0800 Subject: [PATCH 109/135] Use `colorama` to support colorization in Powershell Fixes https://github.com/gleitz/howdoi/issues/445 --- howdoi/howdoi.py | 15 ++++++++++++--- requirements/common.txt | 1 + setup.py | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index dd97715ab..4fb8251d4 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -41,6 +41,9 @@ from requests.exceptions import ConnectionError as RequestsConnectionError from requests.exceptions import SSLError +from colorama import init +init() + from howdoi import __version__ from howdoi.errors import GoogleValidationError, BingValidationError, DDGValidationError @@ -813,9 +816,15 @@ def command_line_runner(): # pylint: disable=too-many-return-statements,too-man if os.getenv('HOWDOI_COLORIZE'): args['color'] = True - utf8_result = howdoi(args).encode('utf-8', 'ignore') - # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 - sys.stdout.buffer.write(utf8_result) + howdoi_result = howdoi(args) + + if os.name == 'nt': + # Windows + print(howdoi_result) + else: + utf8_result = howdoi_result.encode('utf-8', 'ignore') + # Write UTF-8 to stdout: https://stackoverflow.com/a/3603160 + sys.stdout.buffer.write(utf8_result) # close the session to release connection howdoi_session.close() diff --git a/requirements/common.txt b/requirements/common.txt index 150dde2c4..c5e5412cf 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -9,3 +9,4 @@ cachelib==0.1.1 appdirs==1.4.4 keep==2.9 rich==10.13.0 +colorama==0.4.4 diff --git a/setup.py b/setup.py index 4e2eb2c36..6cca69951 100644 --- a/setup.py +++ b/setup.py @@ -105,7 +105,8 @@ def read(*names): 'cachelib', 'appdirs', 'keep', - 'rich' + 'rich', + 'colorama' ], cmdclass={ 'lint': Lint From cbc74856d9d383ffbe8d629cec4724d64761de26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 27 Mar 2022 10:50:17 +0000 Subject: [PATCH 110/135] Bump minimist from 1.2.5 to 1.2.6 in /extension/code-editor-integration Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/code-editor-integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index 624e0f838..7ecb07b2e 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -1877,9 +1877,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "mkdirp": { From af00c6ea6e5467ed45a324795015a97d46647565 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:52:26 +0000 Subject: [PATCH 111/135] Bump minimist from 1.2.5 to 1.2.6 in /extension/vscode-howdoi Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/vscode-howdoi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/vscode-howdoi/package-lock.json b/extension/vscode-howdoi/package-lock.json index 5c5fd6333..ace88d2ac 100644 --- a/extension/vscode-howdoi/package-lock.json +++ b/extension/vscode-howdoi/package-lock.json @@ -1224,9 +1224,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "mkdirp": { From 7000538cf5f9ccfb8a63f4e949ceee7d767d8977 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Apr 2022 01:45:40 +0000 Subject: [PATCH 112/135] Bump ansi-regex from 3.0.0 to 3.0.1 in /extension/vscode-howdoi Bumps [ansi-regex](https://github.com/chalk/ansi-regex) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/chalk/ansi-regex/releases) - [Commits](https://github.com/chalk/ansi-regex/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: ansi-regex dependency-type: indirect ... Signed-off-by: dependabot[bot] --- extension/vscode-howdoi/package-lock.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/extension/vscode-howdoi/package-lock.json b/extension/vscode-howdoi/package-lock.json index ace88d2ac..4294eadd3 100644 --- a/extension/vscode-howdoi/package-lock.json +++ b/extension/vscode-howdoi/package-lock.json @@ -195,9 +195,9 @@ } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { @@ -1712,9 +1712,9 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true } } @@ -1905,9 +1905,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true }, "is-fullwidth-code-point": { From 049174a5bbf3d8d0c146d1576178ccecb2c8b850 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Tue, 19 Apr 2022 18:52:08 -0700 Subject: [PATCH 113/135] Fix https://github.com/gleitz/howdoi/pull/457 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4e2eb2c36..bff5114f5 100644 --- a/setup.py +++ b/setup.py @@ -46,7 +46,7 @@ def read(*names): for extension in ('.txt', '.md'): filename = name + extension if Path(filename).is_file(): - with open(filename) as in_file: # pylint: disable=unspecified-encoding + with open(filename, encoding='utf-8') as in_file: value = in_file.read() break values[name] = value From ea9795f7edb349b948cf1a1f64a71877fee77dc7 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 3 Jul 2022 19:55:06 +1000 Subject: [PATCH 114/135] docs: fix simple typo, ecapsulated -> encapsulated There is a small typo in extension/code-editor-integration/README.md. Should read `encapsulated` rather than `ecapsulated`. --- extension/code-editor-integration/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/code-editor-integration/README.md b/extension/code-editor-integration/README.md index bd1ec25b9..24e2f5dc0 100644 --- a/extension/code-editor-integration/README.md +++ b/extension/code-editor-integration/README.md @@ -18,7 +18,7 @@ The Code Editor Integration plug-in is ran by calling the `runHowdoi` function w } The Object values: -* question contains the user's query ecapsulated by a single line comment +* question contains the user's query encapsulated by a single line comment * answer contains the three possible answers to the user's query * link contains the three possible links to the answer encapsulated by a single line comment From eae0148c9a509b798c5886d29febcc4cec15f071 Mon Sep 17 00:00:00 2001 From: Vitor Buxbaum Date: Sat, 1 Oct 2022 13:20:58 -0300 Subject: [PATCH 115/135] refact: move _format_url_to_filename to adequate file --- howdoi/howdoi.py | 5 ----- test_howdoi.py | 9 +++++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 4fb8251d4..9ab69e359 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -174,11 +174,6 @@ def get_proxies(): return filtered_proxies -def _format_url_to_filename(url, file_ext='html'): - filename = ''.join(ch for ch in url if ch.isalnum()) - return filename + '.' + file_ext - - def _get_result(url): try: resp = howdoi_session.get(url, headers={'User-Agent': _random_choice(USER_AGENTS)}, diff --git a/test_howdoi.py b/test_howdoi.py index 35aac5254..78a2e1af8 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -22,9 +22,14 @@ original_get_result = howdoi._get_result +def _format_url_to_filename(url, file_ext='html'): + filename = ''.join(ch for ch in url if ch.isalnum()) + return filename + '.' + file_ext + + def _get_result_mock(url): # pylint: disable=protected-access - file_name = howdoi._format_url_to_filename(url, 'html.gz') + file_name = _format_url_to_filename(url, 'html.gz') # pylint: disable=no-member file_path = Path.joinpath(Path(howdoi.HTML_CACHE_PATH), Path(file_name)).resolve() try: @@ -276,7 +281,7 @@ def test_missing_pre_or_code_query(self): def test_format_url_to_filename(self): url = 'https://stackoverflow.com/questions/tagged/cat' invalid_filename_characters = ['/', '\\', '%'] - filename = howdoi._format_url_to_filename(url, 'html') + filename = _format_url_to_filename(url, 'html') self.assertTrue(filename) self.assertTrue(filename.endswith('html')) for invalid_character in invalid_filename_characters: From b89fd41841ff778a232280cdff449e825fa6a5bc Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Sun, 2 Oct 2022 23:03:16 -0700 Subject: [PATCH 116/135] Update dependencies to fix github pipeline Add ignore for pylint warning in test and in setup.py --- requirements/common.txt | 4 ++-- requirements/dev.txt | 10 +++++----- setup.py | 2 +- test_howdoi.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/requirements/common.txt b/requirements/common.txt index c5e5412cf..df981060f 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -4,9 +4,9 @@ argparse==1.4.0 cssselect==1.1.0 lxml>=4.2.5 pyquery==1.4.1 -requests==2.24.0 +requests==2.27.1 cachelib==0.1.1 appdirs==1.4.4 keep==2.9 -rich==10.13.0 +rich==12.6.0 colorama==0.4.4 diff --git a/requirements/dev.txt b/requirements/dev.txt index 4a0b36779..c8c9aeb95 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,7 +1,7 @@ # Contains development specific requirements and imports common requirements -flake8==3.9.2 -nose2==0.6.0 -pylint==2.11.1 -pre-commit==2.13.0 -twine==3.4.1 +flake8==5.0.4 +nose2==0.12.0 +pylint==2.13.9 +pre-commit==2.17.0 +twine==3.8.0 -r common.txt diff --git a/setup.py b/setup.py index 8e7b11941..65cbbc998 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ import glob import subprocess from pathlib import Path -from distutils.cmd import Command +from distutils.cmd import Command # pylint: disable=deprecated-module from setuptools import setup, find_packages # pylint: disable=unused-import import fastentrypoints # noqa: F401 diff --git a/test_howdoi.py b/test_howdoi.py index 78a2e1af8..af3fa8a31 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -328,7 +328,7 @@ def getproxies1(): filtered_proxies = howdoi.get_proxies() self.assertTrue('http://' in filtered_proxies['http']) self.assertTrue('http://' in filtered_proxies['https']) - self.assertTrue('ftp' not in filtered_proxies.keys()) + self.assertTrue('ftp' not in filtered_proxies.keys()) # pylint: disable=consider-iterating-dictionary if __name__ == '__main__': From 3c3b491e237e459ba27848fd2c5085e07d5f9db2 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 3 Oct 2022 10:22:58 -0700 Subject: [PATCH 117/135] Fix homepage image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d1ed0063..d70aea7ba 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- Sherlock, your neighborhood command-line sloth sleuth + Sherlock, your neighborhood command-line sloth sleuth

howdoi

From 83b59821098900694af648d23c112c3098bcfc17 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 3 Oct 2022 10:42:57 -0700 Subject: [PATCH 118/135] New release: 2.0.20 --- CHANGES.txt | 9 +++++++++ howdoi/__init__.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 00ead3f51..f7393bfe5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,12 @@ +2.0.20 +------ +- Update dependency versions +- Add support for Python 3.10 + +2.0.19 +------ +- Fix typo + 2.0.18 ------ - Fixed issue with howdoi cache where cache misses would be printed to the console diff --git a/howdoi/__init__.py b/howdoi/__init__.py index 2b6bf429f..b03a62d04 100644 --- a/howdoi/__init__.py +++ b/howdoi/__init__.py @@ -1 +1 @@ -__version__ = '2.0.18' +__version__ = '2.0.20' From f346b9d08ce27eee9ff6a85afcf727c92c7a3f92 Mon Sep 17 00:00:00 2001 From: Benjamin Schmidt Date: Tue, 11 Oct 2022 15:25:00 +0200 Subject: [PATCH 119/135] Update introduction.md Update python3 version dependency - due to usage of f-strings howdoi needs python3.6 or more recent --- docs/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/introduction.md b/docs/introduction.md index b839192e6..1fe4ca9a7 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -17,7 +17,7 @@ print(“hello”) You'll need: - `pip` -- Python 3.5 or above. Python 2.7 support is discontinued. +- Python 3.6 or above. Python 2.7 support is discontinued. To install howdoi: From d9dd193a9bdde5e183b30d3239b55c653c34416c Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Tue, 11 Oct 2022 14:14:27 -0500 Subject: [PATCH 120/135] Update supported Python versions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d70aea7ba..f63962757 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ how to get up and running with your first pull request. ## Notes -- Works with Python 3.5 and newer. Unfortunately Python 2.7 support +- Works with Python 3.6 and newer. Unfortunately Python 2.7 support has been discontinued :( - There is a [GUI that wraps howdoi](https://pypi.org/project/pysimplegui-howdoi/) From 1e462d8ffa042952f0c6695e8c56e180ae0124bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 01:22:40 +0000 Subject: [PATCH 121/135] Bump ansi-regex, ansi-regex and ansi-regex Bumps [ansi-regex](https://github.com/chalk/ansi-regex), [ansi-regex](https://github.com/chalk/ansi-regex) and [ansi-regex](https://github.com/chalk/ansi-regex). These dependencies needed to be updated together. Updates `ansi-regex` from 5.0.0 to 5.0.1 - [Release notes](https://github.com/chalk/ansi-regex/releases) - [Commits](https://github.com/chalk/ansi-regex/compare/v5.0.0...v5.0.1) Updates `ansi-regex` from 4.1.0 to 5.0.1 - [Release notes](https://github.com/chalk/ansi-regex/releases) - [Commits](https://github.com/chalk/ansi-regex/compare/v5.0.0...v5.0.1) Updates `ansi-regex` from 3.0.0 to 5.0.1 - [Release notes](https://github.com/chalk/ansi-regex/releases) - [Commits](https://github.com/chalk/ansi-regex/compare/v5.0.0...v5.0.1) --- updated-dependencies: - dependency-name: ansi-regex dependency-type: indirect - dependency-name: ansi-regex dependency-type: indirect - dependency-name: ansi-regex dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../code-editor-integration/package-lock.json | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index 7ecb07b2e..75266e7ad 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -387,9 +387,9 @@ "dev": true }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { @@ -632,9 +632,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true }, "string-width": { @@ -1931,9 +1931,9 @@ "dev": true }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "cliui": { @@ -2703,9 +2703,9 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "strip-ansi": { @@ -2939,9 +2939,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true }, "string-width": { @@ -2990,7 +2990,7 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true }, "is-fullwidth-code-point": { @@ -3105,9 +3105,9 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "cliui": { From 8f7c1795dab59bb4bf39fab57741f14f97243eb7 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Sat, 12 Nov 2022 09:27:53 -0800 Subject: [PATCH 122/135] Fix github line count Ignore Juypter notebooks Fixes https://github.com/gleitz/howdoi/issues/432 --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index d1460ceb0..a8b2d622c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ cache_html/* linguist-vendored *.html linguist-language=Python +*.ipynb linguist-documentation From 92ea7cf1a3c493a5444039bd61fc58d1c0857412 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Sat, 12 Nov 2022 10:28:39 -0800 Subject: [PATCH 123/135] Updated howdoi integrations --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f63962757..a5c89e9cb 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,21 @@ Other useful aliases: alias hless='function hdi(){ howdoi $* -c | less --raw-control-chars --quit-if-one-screen --no-init; }; hdi' +## Integrations + +- Slack integration available through + [slack-howdoi](https://github.com/ellisonleao/slack-howdoi) +- Telegram integration available through + [howdoi-telegram](https://github.com/aahnik/howdoi-telegram) +- Discord integration available through + [discord-howdoi](https://github.com/MLH-Fellowship/0.5.1-howDoIDiscord) +- Emacs integration available through + [emacs-howdoi](https://blog.gleitzman.com/post/700738401851277312/howdoi-use-howdoi-in-emacs) +- VSCode integration available on the + [marketplace](https://marketplace.visualstudio.com/items?itemName=howdoi-org.howdoi) +- Alfred integration available through + [alfred-howdoi](https://github.com/gleitz/alfred-howdoi) + ## Contributors - Benjamin Gleitzman ([\@gleitz](http://twitter.com/gleitz)) @@ -170,22 +185,7 @@ how to get up and running with your first pull request. - Works with Python 3.6 and newer. Unfortunately Python 2.7 support has been discontinued :( -- There is a [GUI that wraps - howdoi](https://pypi.org/project/pysimplegui-howdoi/) -- There is a [Flask webapp that wraps - howdoi](https://howdoi.maxbridgland.com) -- An [Alfred Workflow](http://blog.gleitzman.com/post/48539944559/howdoi-alfred-even-more-instant-answers) - for howdoi -- Slack integration available through - [slack-howdoi](https://github.com/ellisonleao/slack-howdoi) -- Telegram integration available through - [howdoi-telegram](https://github.com/aahnik/howdoi-telegram) - Special thanks to Rich Jones ([\@miserlou](https://github.com/miserlou)) for the idea - More thanks to [Ben Bronstein](https://benbronstein.com/) for the logo - -## Visual Studio Code Extension Installation - -Head over to the [MarketPlace](https://marketplace.visualstudio.com/items?itemName=howdoi-org.howdoi) -to install the extension. From 1ce2a6fb7b52184cd35ebeed1d6ef72ad5b8eb62 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 5 Dec 2022 12:03:38 -0800 Subject: [PATCH 124/135] Add Homebrew installation instructions --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index a5c89e9cb..03cab228d 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,10 @@ howdoi will answer all sorts of queries: pip install howdoi +or + + brew install howdoi + ## Usage ### New to howdoi? From e9d5ac9f9fb785ea899f7a533f9cc18ae4d97ec8 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Mon, 5 Dec 2022 12:13:43 -0800 Subject: [PATCH 125/135] Remove support for Python 3.6 https://peps.python.org/pep-0494/#lifespan --- .github/workflows/python-non-master.yml | 2 +- .github/workflows/python.yml | 2 +- README.md | 2 +- docs/introduction.md | 2 +- setup.py | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python-non-master.yml b/.github/workflows/python-non-master.yml index 40663bdb4..8358c4692 100644 --- a/.github/workflows/python-non-master.yml +++ b/.github/workflows/python-non-master.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9, '3.10'] + python-version: [3.7, 3.8, 3.9, '3.10'] steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 984b64ad9..3f476b32c 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9, '3.10'] + python-version: [3.7, 3.8, 3.9, '3.10'] steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 03cab228d..8bfc79017 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ how to get up and running with your first pull request. ## Notes -- Works with Python 3.6 and newer. Unfortunately Python 2.7 support +- Works with Python 3.7 and newer. Unfortunately Python 2.7 support has been discontinued :( - Special thanks to Rich Jones ([\@miserlou](https://github.com/miserlou)) for the idea diff --git a/docs/introduction.md b/docs/introduction.md index 1fe4ca9a7..5ece76cda 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -17,7 +17,7 @@ print(“hello”) You'll need: - `pip` -- Python 3.6 or above. Python 2.7 support is discontinued. +- Python 3.7 or above. Python 2.7 support is discontinued. To install howdoi: diff --git a/setup.py b/setup.py index 65cbbc998..46771f8a6 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,6 @@ def read(*names): "Environment :: Console", "Intended Audience :: Developers", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", From 35709190a37e34af333cf210a22fff2af91ed731 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 20:18:15 +0000 Subject: [PATCH 126/135] Bump minimatch and mocha in /extension/vscode-howdoi Bumps [minimatch](https://github.com/isaacs/minimatch) to 3.1.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together. Updates `minimatch` from 3.0.4 to 3.1.2 - [Release notes](https://github.com/isaacs/minimatch/releases) - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2) Updates `mocha` from 7.2.0 to 10.1.0 - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v7.2.0...v10.1.0) --- updated-dependencies: - dependency-name: minimatch dependency-type: indirect - dependency-name: mocha dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- extension/vscode-howdoi/package-lock.json | 793 ++++++++++------------ extension/vscode-howdoi/package.json | 2 +- 2 files changed, 341 insertions(+), 454 deletions(-) diff --git a/extension/vscode-howdoi/package-lock.json b/extension/vscode-howdoi/package-lock.json index 4294eadd3..a112f65fc 100644 --- a/extension/vscode-howdoi/package-lock.json +++ b/extension/vscode-howdoi/package-lock.json @@ -172,9 +172,9 @@ } }, "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-escapes": { @@ -210,9 +210,9 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -246,9 +246,9 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "brace-expansion": { @@ -282,9 +282,9 @@ "dev": true }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, "chai": { @@ -325,19 +325,19 @@ "dev": true }, "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.1.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "readdirp": "~3.6.0" } }, "cli-cursor": { @@ -356,37 +356,23 @@ "dev": true }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" }, "dependencies": { - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "ansi-regex": "^5.0.1" } } } @@ -442,9 +428,9 @@ } }, "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, "deep-eql": { @@ -462,19 +448,10 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "doctrine": { @@ -492,36 +469,6 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -537,6 +484,12 @@ "es6-promise": "^4.0.3" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -748,22 +701,20 @@ } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" } }, "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true }, "flat-cache": { "version": "2.0.1", @@ -799,18 +750,12 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -860,33 +805,12 @@ "type-fest": "^0.8.1" } }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -1077,24 +1001,6 @@ "binary-extensions": "^2.0.0" } }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1122,23 +1028,17 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true }, "isexe": { "version": "2.0.0", @@ -1185,13 +1085,12 @@ } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" } }, "lodash": { @@ -1201,12 +1100,64 @@ "dev": true }, "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^2.4.2" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "mimic-fn": { @@ -1216,9 +1167,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -1239,50 +1190,67 @@ } }, "mocha": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", - "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, "requires": { - "ansi-colors": "3.2.3", + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" }, "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1291,37 +1259,73 @@ "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "brace-expansion": "^2.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + } } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } @@ -1338,6 +1342,12 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -1355,64 +1365,12 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-environment-flags": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", - "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1451,29 +1409,23 @@ "dev": true }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1484,9 +1436,9 @@ } }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { @@ -1507,9 +1459,9 @@ "dev": true }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "prelude-ls": { @@ -1530,13 +1482,22 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, "readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { - "picomatch": "^2.0.4" + "picomatch": "^2.2.1" } }, "regexpp": { @@ -1548,13 +1509,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, "resolve-from": { @@ -1596,6 +1551,12 @@ "tslib": "^1.9.0" } }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -1608,11 +1569,14 @@ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, "shebang-command": { "version": "1.2.0", @@ -1682,26 +1646,6 @@ } } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -1889,92 +1833,60 @@ "isexe": "^2.0.0" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "string-width": "^1.0.2 || 2" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "color-convert": "^2.0.1" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "color-name": "~1.1.4" } - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "ansi-regex": "^5.0.1" } } } @@ -1994,74 +1906,49 @@ } }, "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - } + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true }, "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/extension/vscode-howdoi/package.json b/extension/vscode-howdoi/package.json index 674ea7323..c0a22e991 100644 --- a/extension/vscode-howdoi/package.json +++ b/extension/vscode-howdoi/package.json @@ -52,7 +52,7 @@ "chai": "^4.2.0", "eslint": "^6.8.0", "glob": "^7.1.6", - "mocha": "^7.1.2", + "mocha": "^10.1.0", "typescript": "^3.8.3", "vscode-test": "^1.3.0" }, From 558fadd85ec9f38de1de87104ce570b72c69bace Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 20:18:40 +0000 Subject: [PATCH 127/135] Bump minimatch and mocha in /extension/code-editor-integration Bumps [minimatch](https://github.com/isaacs/minimatch) to 3.1.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together. Updates `minimatch` from 3.0.4 to 3.1.2 - [Release notes](https://github.com/isaacs/minimatch/releases) - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2) Updates `mocha` from 8.1.1 to 10.1.0 - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v8.1.1...v10.1.0) --- updated-dependencies: - dependency-name: minimatch dependency-type: indirect - dependency-name: mocha dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- .../code-editor-integration/package-lock.json | 823 +++++++----------- .../code-editor-integration/package.json | 2 +- 2 files changed, 298 insertions(+), 527 deletions(-) diff --git a/extension/code-editor-integration/package-lock.json b/extension/code-editor-integration/package-lock.json index 75266e7ad..01f5f464f 100644 --- a/extension/code-editor-integration/package-lock.json +++ b/extension/code-editor-integration/package-lock.json @@ -402,9 +402,9 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -441,18 +441,6 @@ "sprintf-js": "~1.0.2" } }, - "array.prototype.map": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", - "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.4" - } - }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -472,9 +460,9 @@ "dev": true }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "brace-expansion": { @@ -605,19 +593,19 @@ "dev": true }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" + "readdirp": "~3.6.0" } }, "cliui": { @@ -824,19 +812,10 @@ "strip-bom": "^3.0.0" } }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "doctrine": { @@ -881,63 +860,18 @@ "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "es-get-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", - "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", - "dev": true, - "requires": { - "es-abstract": "^1.17.4", - "has-symbols": "^1.0.1", - "is-arguments": "^1.0.4", - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1191,13 +1125,10 @@ } }, "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true }, "flat-cache": { "version": "2.0.1", @@ -1254,18 +1185,12 @@ "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -1331,33 +1256,12 @@ "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, "hasha": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", @@ -1429,12 +1333,6 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -1450,24 +1348,6 @@ "binary-extensions": "^2.0.0" } }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1489,12 +1369,6 @@ "is-extglob": "^2.1.1" } }, - "is-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", - "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1502,24 +1376,9 @@ "dev": true }, "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-set": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", - "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, "is-stream": { @@ -1528,33 +1387,18 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1651,22 +1495,6 @@ "html-escaper": "^2.0.0" } }, - "iterate-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", - "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", - "dev": true - }, - "iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "requires": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - } - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1769,25 +1597,13 @@ "dev": true }, "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^2.4.2" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "lru-cache": { @@ -1868,9 +1684,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -1892,36 +1708,32 @@ } }, "mocha": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.1.tgz", - "integrity": "sha512-p7FuGlYH8t7gaiodlFreseLxEmxTgvyG9RgPHODFPySNhwUehu8NIb0vdSt3WFckSneswZ0Un5typYcWElk7HQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, "requires": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.3.1", - "debug": "3.2.6", - "diff": "4.0.2", - "escape-string-regexp": "1.0.5", - "find-up": "4.1.0", - "glob": "7.1.6", - "growl": "1.10.5", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "object.assign": "4.1.0", - "promise.allsettled": "1.0.2", - "serialize-javascript": "4.0.0", - "strip-json-comments": "3.0.1", - "supports-color": "7.1.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.0", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.1" + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" }, "dependencies": { "ansi-colors": { @@ -1930,74 +1742,183 @@ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" } }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, "path-exists": { @@ -2006,94 +1927,80 @@ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" } }, "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true } } }, @@ -2103,6 +2010,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2203,30 +2116,6 @@ "yargs-parser": "^13.0.0" } }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2388,9 +2277,9 @@ "dev": true }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pify": { @@ -2420,19 +2309,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "promise.allsettled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", - "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", - "dev": true, - "requires": { - "array.prototype.map": "^1.0.1", - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "iterate-value": "^1.0.0" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -2486,12 +2362,12 @@ } }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "regexpp": { @@ -2558,9 +2434,9 @@ "dev": true }, "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -2719,26 +2595,6 @@ } } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -2929,42 +2785,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -2972,9 +2792,9 @@ "dev": true }, "workerpool": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", - "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", "dev": true }, "wrap-ansi": { @@ -3092,83 +2912,28 @@ } }, "yargs-unparser": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", - "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "flat": "^4.1.0", - "is-plain-obj": "^1.1.0", - "yargs": "^14.2.3" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } - }, - "yargs-parser": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", - "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true } } }, @@ -3177,6 +2942,12 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/extension/code-editor-integration/package.json b/extension/code-editor-integration/package.json index 2650a2c06..73c35a6eb 100644 --- a/extension/code-editor-integration/package.json +++ b/extension/code-editor-integration/package.json @@ -26,7 +26,7 @@ "chai": "^4.2.0", "cross-env": "^5.2.0", "eslint": "^7.3.1", - "mocha": "^8.1.1", + "mocha": "^10.1.0", "nyc": "^14.1.1", "ts-node": "^8.3.0", "typescript": "^3.5.3" From b840bbad2e19ad983b22d735c528d9a9f2dabc86 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Wed, 25 Jan 2023 13:49:04 -0800 Subject: [PATCH 128/135] Update the build passing shield --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bfc79017..e45bbd9d6 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@

⚡ Never open your browser to look for help again ⚡

- build status + build status downloads Python versions

From 286503a39d83388a43ed241efa0ba60e8051f344 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Wed, 25 Jan 2023 13:51:20 -0800 Subject: [PATCH 129/135] Add Python 3.11 support --- .github/workflows/docs.yml | 2 +- .github/workflows/early-warning.yml | 2 +- .github/workflows/python-non-master.yml | 2 +- .github/workflows/python.yml | 2 +- .pre-commit-config.yaml | 2 +- .pylintrc | 7 ------- requirements/dev.txt | 2 +- setup.py | 1 + test_howdoi.py | 2 +- 9 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a17f55e8e..f463525c9 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.10' + python-version: '3.11' - name: Install Pip run: python -m pip install --upgrade pip diff --git a/.github/workflows/early-warning.yml b/.github/workflows/early-warning.yml index 4bede3f26..b790e7f1e 100644 --- a/.github/workflows/early-warning.yml +++ b/.github/workflows/early-warning.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: - python-version: '3.10' + python-version: '3.11' - name: Setup environment run: pip install -r requirements.txt diff --git a/.github/workflows/python-non-master.yml b/.github/workflows/python-non-master.yml index 8358c4692..3623ede1e 100644 --- a/.github/workflows/python-non-master.yml +++ b/.github/workflows/python-non-master.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9, '3.10'] + python-version: [3.7, 3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 3f476b32c..203e90424 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9, '3.10'] + python-version: [3.7, 3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0a191991b..85e897b13 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - "--config=.flake8rc" - repo: https://github.com/PyCQA/pylint/ - rev: v2.11.1 + rev: v2.15.10 hooks: - id: pylint args: diff --git a/.pylintrc b/.pylintrc index 9f1d66c94..875f8e5f4 100644 --- a/.pylintrc +++ b/.pylintrc @@ -244,13 +244,6 @@ max-line-length=119 # Maximum number of lines in a module. max-module-lines=1000 -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma, - dict-separator - # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no diff --git a/requirements/dev.txt b/requirements/dev.txt index c8c9aeb95..006cb5b64 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,7 +1,7 @@ # Contains development specific requirements and imports common requirements flake8==5.0.4 nose2==0.12.0 -pylint==2.13.9 +pylint==2.15.10 pre-commit==2.17.0 twine==3.8.0 -r common.txt diff --git a/setup.py b/setup.py index 46771f8a6..4dbc5841e 100644 --- a/setup.py +++ b/setup.py @@ -80,6 +80,7 @@ def read(*names): "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Topic :: Documentation", ], keywords='howdoi help console command line answer', diff --git a/test_howdoi.py b/test_howdoi.py index af3fa8a31..9c90b686e 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -190,7 +190,7 @@ def test_multiple_answers(self): second_answer = howdoi.howdoi(query + ' -n3') self.assertNotEqual(first_answer, second_answer) - def test_unicode_answer(self): # pylint: disable=no-self-use + def test_unicode_answer(self): assert howdoi.howdoi('make a log scale d3') assert howdoi.howdoi('python unittest -n3') assert howdoi.howdoi('parse html regex -a') From 659e370971079fcb077d6f9962cac889652bd595 Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Wed, 25 Jan 2023 17:05:12 -0800 Subject: [PATCH 130/135] Fix typo in pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5674b9e76..786a05870 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,8 +2,6 @@ - Tasks solved - - Link to respective files - - Links to issues solved ## Pull Request type: From c2de31407cf1528e8f1233414184386b8501fc3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 03:58:00 +0000 Subject: [PATCH 131/135] Bump requests from 2.27.1 to 2.31.0 in /requirements Bumps [requests](https://github.com/psf/requests) from 2.27.1 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.27.1...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/common.txt b/requirements/common.txt index df981060f..c69a80756 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -4,7 +4,7 @@ argparse==1.4.0 cssselect==1.1.0 lxml>=4.2.5 pyquery==1.4.1 -requests==2.27.1 +requests==2.31.0 cachelib==0.1.1 appdirs==1.4.4 keep==2.9 From 96ac6110d44445588a52592f5956a615f7dff8da Mon Sep 17 00:00:00 2001 From: Benjamin Gleitzman Date: Thu, 13 Jul 2023 10:24:32 -0700 Subject: [PATCH 132/135] Update download count in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e45bbd9d6..7e88bc641 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@

build status - downloads + downloads Python versions

From 1dc6cdebb5c2ea7a5e23255c303cbbaa02cdc165 Mon Sep 17 00:00:00 2001 From: dizzygz Date: Thu, 28 Dec 2023 18:07:51 -0500 Subject: [PATCH 133/135] update 2 places for int and str operations --- howdoi/howdoi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/howdoi/howdoi.py b/howdoi/howdoi.py index 9ab69e359..44f23c46a 100644 --- a/howdoi/howdoi.py +++ b/howdoi/howdoi.py @@ -434,7 +434,7 @@ def _get_answers(args): return False initial_pos = args['pos'] - 1 - final_pos = initial_pos + args['num_answers'] + final_pos = initial_pos + int(args['num_answers']) question_links = question_links[initial_pos:final_pos] search_engine = os.getenv('HOWDOI_SEARCH_ENGINE', 'google') @@ -465,7 +465,7 @@ def _get_answer_worker(args, link): 'position': None } - multiple_answers = (args['num_answers'] > 1 or args['all']) + multiple_answers = (int(args['num_answers']) > 1 or args['all']) if not answer: return result From 7d24e9e1c87811a6e66d60f504381383cf1ac3fd Mon Sep 17 00:00:00 2001 From: ilaumjd Date: Fri, 16 Aug 2024 22:13:03 +0700 Subject: [PATCH 134/135] fix: remove bad test case --- test_howdoi.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test_howdoi.py b/test_howdoi.py index 9c90b686e..6b97b41af 100644 --- a/test_howdoi.py +++ b/test_howdoi.py @@ -276,7 +276,6 @@ def test_help_queries(self): def test_missing_pre_or_code_query(self): output = howdoi.howdoi(self.query_without_code_or_pre_block) self.assertTrue(output) - self.assertIn('XML elements present in a XML', output) def test_format_url_to_filename(self): url = 'https://stackoverflow.com/questions/tagged/cat' From 6237a19ccf1f517fc06b48dc3fbe37a68a5a0262 Mon Sep 17 00:00:00 2001 From: RACZ Andras Date: Mon, 21 Oct 2024 10:07:00 +0200 Subject: [PATCH 135/135] add missing line break to doc --- docs/howdoi_advanced_usage.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/howdoi_advanced_usage.md b/docs/howdoi_advanced_usage.md index a05a7a925..9fa9a4a7f 100644 --- a/docs/howdoi_advanced_usage.md +++ b/docs/howdoi_advanced_usage.md @@ -2,7 +2,8 @@ won’t be that feasible. Hence, Howdoi has a stashing feature which allows you to save your query, view the query, delete the saved results and even empty the entire stash ! (see keep documentation for more information on stashing). Here is how you can do this: - - **stashing: howdoi --save QUERY** **viewing: howdoi --view** + - **stashing: howdoi --save QUERY** + - **viewing: howdoi --view** - **removing: howdoi --remove (will be prompted which answer to delete)** - **emptying: howdoi --empty (empties entire stash, will be prompted to confirm)**