prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  etymology: Empty argument not handled
  Doing `.ety` with no or an empty argument doesn't behave properly.
  
  On Python 2 (my old personal instance), it causes `TypeError: None object cannot be quoted (file "/usr/lib/python2.7/urllib.py", line 1255, in quote)`
  
  On Python 3 ("official" Sopel instance on freenode), the command looks up the etymology of "None" (and gets no results, because of the capital letter).
  
  This is a good, easy issue for first-time contributors to fix.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `sopel/modules/etymology.py`
  Content:
  ```
  1 # coding=utf-8
  2 """
  3 etymology.py - Sopel Etymology Module
  4 Copyright 2007-9, Sean B. Palmer, inamidst.com
  5 Copyright 2018-9, Sopel contributors
  6 Licensed under the Eiffel Forum License 2.
  7 
  8 https://sopel.chat
  9 """
  10 from __future__ import unicode_literals, absolute_import, print_function, division
  11 
  12 from re import sub
  13 
  14 from requests import get
  15 
  16 from sopel.module import commands, example, NOLIMIT
  17 from sopel.tools import web
  18 
  19 try:
  20     # Python 2.7
  21     from HTMLParser import HTMLParser
  22     h = HTMLParser()
  23     unescape = h.unescape
  24 except ImportError:
  25     try:
  26         # Python 3.4+
  27         from html import unescape  # https://stackoverflow.com/a/2087433
  28     except ImportError:
  29         # Python 3.3... sigh
  30         from html.parser import HTMLParser
  31         h = HTMLParser()
  32         unescape = h.unescape
  33 
  34 
  35 ETYURI = 'https://www.etymonline.com/word/%s'
  36 ETYSEARCH = 'https://www.etymonline.com/search?q=%s'
  37 
  38 
  39 def etymology(word):
  40     # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc
  41     # entries? - http://swhack.com/logs/2006-07-19#T15-05-29
  42 
  43     if len(word) > 25:
  44         raise ValueError("Word too long: %s[…]" % word[:10])
  45 
  46     ety = get(ETYURI % web.quote(word))
  47     if ety.status_code != 200:
  48         return None
  49 
  50     # Let's find it
  51     start = ety.text.find("word__defination")
  52     start = ety.text.find("<p>", start)
  53     stop = ety.text.find("</p>", start)
  54     sentence = ety.text[start + 3:stop]
  55     # Clean up
  56     sentence = unescape(sentence)
  57     sentence = sub('<[^<]+?>', '', sentence)
  58 
  59     maxlength = 275
  60     if len(sentence) > maxlength:
  61         sentence = sentence[:maxlength]
  62         words = sentence[:-5].split(' ')
  63         words.pop()
  64         sentence = ' '.join(words) + ' […]'
  65 
  66     sentence = '"' + sentence.replace('"', "'") + '"'
  67     return sentence + ' - ' + (ETYURI % web.quote(word))
  68 
  69 
  70 @commands('ety')
  71 @example('.ety word')
  72 def f_etymology(bot, trigger):
  73     """Look up the etymology of a word"""
  74     word = trigger.group(2)
  75 
  76     try:
  77         result = etymology(word)
  78     except IOError:
  79         msg = "Can't connect to etymonline.com (%s)" % (ETYURI % web.quote(word))
  80         bot.say(msg, trigger.sender)
  81         return NOLIMIT
  82     except (AttributeError, TypeError):
  83         result = None
  84     except ValueError as ve:
  85         result = str(ve)
  86 
  87     if result is not None:
  88         bot.say(result, trigger.sender)
  89     else:
  90         uri = ETYSEARCH % web.quote(word)
  91         msg = 'Can\'t find the etymology for "%s". Try %s' % (word, uri)
  92         bot.say(msg, trigger.sender)
  93         return NOLIMIT
  94
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/sopel/modules/etymology.py b/sopel/modules/etymology.py
  --- a/sopel/modules/etymology.py
  +++ b/sopel/modules/etymology.py
  @@ -40,6 +40,9 @@
       # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc
       # entries? - http://swhack.com/logs/2006-07-19#T15-05-29
   
  +    if not word:
  +        raise ValueError("No word to look for.")
  +
       if len(word) > 25:
           raise ValueError("Word too long: %s[…]" % word[:10])
  
verification_info: {"golden_diff": "diff --git a/sopel/modules/etymology.py b/sopel/modules/etymology.py\n--- a/sopel/modules/etymology.py\n+++ b/sopel/modules/etymology.py\n@@ -40,6 +40,9 @@\n     # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc\n     # entries? - http://swhack.com/logs/2006-07-19#T15-05-29\n \n+    if not word:\n+        raise ValueError(\"No word to look for.\")\n+\n     if len(word) > 25:\n         raise ValueError(\"Word too long: %s[\u2026]\" % word[:10])\n", "issue": "etymology: Empty argument not handled\nDoing `.ety` with no or an empty argument doesn't behave properly.\r\n\r\nOn Python 2 (my old personal instance), it causes `TypeError: None object cannot be quoted (file \"/usr/lib/python2.7/urllib.py\", line 1255, in quote)`\r\n\r\nOn Python 3 (\"official\" Sopel instance on freenode), the command looks up the etymology of \"None\" (and gets no results, because of the capital letter).\r\n\r\nThis is a good, easy issue for first-time contributors to fix.\n", "before_files": [{"content": "# coding=utf-8\n\"\"\"\netymology.py - Sopel Etymology Module\nCopyright 2007-9, Sean B. Palmer, inamidst.com\nCopyright 2018-9, Sopel contributors\nLicensed under the Eiffel Forum License 2.\n\nhttps://sopel.chat\n\"\"\"\nfrom __future__ import unicode_literals, absolute_import, print_function, division\n\nfrom re import sub\n\nfrom requests import get\n\nfrom sopel.module import commands, example, NOLIMIT\nfrom sopel.tools import web\n\ntry:\n    # Python 2.7\n    from HTMLParser import HTMLParser\n    h = HTMLParser()\n    unescape = h.unescape\nexcept ImportError:\n    try:\n        # Python 3.4+\n        from html import unescape  # https://stackoverflow.com/a/2087433\n    except ImportError:\n        # Python 3.3... sigh\n        from html.parser import HTMLParser\n        h = HTMLParser()\n        unescape = h.unescape\n\n\nETYURI = 'https://www.etymonline.com/word/%s'\nETYSEARCH = 'https://www.etymonline.com/search?q=%s'\n\n\ndef etymology(word):\n    # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc\n    # entries? - http://swhack.com/logs/2006-07-19#T15-05-29\n\n    if len(word) > 25:\n        raise ValueError(\"Word too long: %s[\u2026]\" % word[:10])\n\n    ety = get(ETYURI % web.quote(word))\n    if ety.status_code != 200:\n        return None\n\n    # Let's find it\n    start = ety.text.find(\"word__defination\")\n    start = ety.text.find(\"<p>\", start)\n    stop = ety.text.find(\"</p>\", start)\n    sentence = ety.text[start + 3:stop]\n    # Clean up\n    sentence = unescape(sentence)\n    sentence = sub('<[^<]+?>', '', sentence)\n\n    maxlength = 275\n    if len(sentence) > maxlength:\n        sentence = sentence[:maxlength]\n        words = sentence[:-5].split(' ')\n        words.pop()\n        sentence = ' '.join(words) + ' [\u2026]'\n\n    sentence = '\"' + sentence.replace('\"', \"'\") + '\"'\n    return sentence + ' - ' + (ETYURI % web.quote(word))\n\n\n@commands('ety')\n@example('.ety word')\ndef f_etymology(bot, trigger):\n    \"\"\"Look up the etymology of a word\"\"\"\n    word = trigger.group(2)\n\n    try:\n        result = etymology(word)\n    except IOError:\n        msg = \"Can't connect to etymonline.com (%s)\" % (ETYURI % web.quote(word))\n        bot.say(msg, trigger.sender)\n        return NOLIMIT\n    except (AttributeError, TypeError):\n        result = None\n    except ValueError as ve:\n        result = str(ve)\n\n    if result is not None:\n        bot.say(result, trigger.sender)\n    else:\n        uri = ETYSEARCH % web.quote(word)\n        msg = 'Can\\'t find the etymology for \"%s\". Try %s' % (word, uri)\n        bot.say(msg, trigger.sender)\n        return NOLIMIT\n", "path": "sopel/modules/etymology.py"}], "after_files": [{"content": "# coding=utf-8\n\"\"\"\netymology.py - Sopel Etymology Module\nCopyright 2007-9, Sean B. Palmer, inamidst.com\nCopyright 2018-9, Sopel contributors\nLicensed under the Eiffel Forum License 2.\n\nhttps://sopel.chat\n\"\"\"\nfrom __future__ import unicode_literals, absolute_import, print_function, division\n\nfrom re import sub\n\nfrom requests import get\n\nfrom sopel.module import commands, example, NOLIMIT\nfrom sopel.tools import web\n\ntry:\n    # Python 2.7\n    from HTMLParser import HTMLParser\n    h = HTMLParser()\n    unescape = h.unescape\nexcept ImportError:\n    try:\n        # Python 3.4+\n        from html import unescape  # https://stackoverflow.com/a/2087433\n    except ImportError:\n        # Python 3.3... sigh\n        from html.parser import HTMLParser\n        h = HTMLParser()\n        unescape = h.unescape\n\n\nETYURI = 'https://www.etymonline.com/word/%s'\nETYSEARCH = 'https://www.etymonline.com/search?q=%s'\n\n\ndef etymology(word):\n    # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc\n    # entries? - http://swhack.com/logs/2006-07-19#T15-05-29\n\n    if not word:\n        raise ValueError(\"No word to look for.\")\n\n    if len(word) > 25:\n        raise ValueError(\"Word too long: %s[\u2026]\" % word[:10])\n\n    ety = get(ETYURI % web.quote(word))\n    if ety.status_code != 200:\n        return None\n\n    # Let's find it\n    start = ety.text.find(\"word__defination\")\n    start = ety.text.find(\"<p>\", start)\n    stop = ety.text.find(\"</p>\", start)\n    sentence = ety.text[start + 3:stop]\n    # Clean up\n    sentence = unescape(sentence)\n    sentence = sub('<[^<]+?>', '', sentence)\n\n    maxlength = 275\n    if len(sentence) > maxlength:\n        sentence = sentence[:maxlength]\n        words = sentence[:-5].split(' ')\n        words.pop()\n        sentence = ' '.join(words) + ' [\u2026]'\n\n    sentence = '\"' + sentence.replace('\"', \"'\") + '\"'\n    return sentence + ' - ' + (ETYURI % web.quote(word))\n\n\n@commands('ety')\n@example('.ety word')\ndef f_etymology(bot, trigger):\n    \"\"\"Look up the etymology of a word\"\"\"\n    word = trigger.group(2)\n\n    try:\n        result = etymology(word)\n    except IOError:\n        msg = \"Can't connect to etymonline.com (%s)\" % (ETYURI % web.quote(word))\n        bot.say(msg, trigger.sender)\n        return NOLIMIT\n    except (AttributeError, TypeError):\n        result = None\n    except ValueError as ve:\n        result = str(ve)\n\n    if result is not None:\n        bot.say(result, trigger.sender)\n    else:\n        uri = ETYSEARCH % web.quote(word)\n        msg = 'Can\\'t find the etymology for \"%s\". Try %s' % (word, uri)\n        bot.say(msg, trigger.sender)\n        return NOLIMIT\n", "path": "sopel/modules/etymology.py"}]}