We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Python 3.10 on Windows fails: AttributeError: module 'collections' has no attribute 'Callable'
Thanks to https://github.com/pyreadline/pyreadline/issues/65, Hy on Python 3.10 on Windows no longer starts, and a backtrace similar to the following is the result:

```console
Traceback (most recent call last):
  File "c:\python\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\python\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Python\Scripts\hy.exe\__main__.py", line 4, in <module>
  File "c:\python\lib\site-packages\hy\cmdline.py", line 37, in <module>
    from hy.completer import completion, Completer
  File "c:\python\lib\site-packages\hy\completer.py", line 18, in <module>
    import readline
  File "c:\python\lib\site-packages\readline.py", line 34, in <module>
    rl = Readline()
  File "c:\python\lib\site-packages\pyreadline\rlmain.py", line 422, in __init__
    BaseReadline.__init__(self)
  File "c:\python\lib\site-packages\pyreadline\rlmain.py", line 62, in __init__
    mode.init_editing_mode(None)
  File "c:\python\lib\site-packages\pyreadline\modes\emacs.py", line 633, in init_editing_mode
    self._bind_key('space',       self.self_insert)
  File "c:\python\lib\site-packages\pyreadline\modes\basemode.py", line 162, in _bind_key
    if not callable(func):
  File "c:\python\lib\site-packages\pyreadline\py3k_compat.py", line 8, in callable
    return isinstance(x, collections.Callable)
AttributeError: module 'collections' has no attribute 'Callable'
```

Unfortunately from that bug (and the repository in general), it would appear that `pyreadline` is no longer actively maintained (last update of any kind was in 2015), so for Hy to continue to support Windows on future Python versions will require some amount of workaround (a fork of `pyreadline`, dropping readline support on Windows, etc).

I'm not sure if there's a way to specify that Python 3.10+ and Windows are simply mutually incompatible, but that would be the "simplest" workaround if there's a clean way to specify that. :see_no_evil:

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setup.py`
Content:
```
1 #!/usr/bin/env python
2 # Copyright 2021 the authors.
3 # This file is part of Hy, which is free software licensed under the Expat
4 # license. See the LICENSE.
5 
6 import glob
7 import importlib
8 import inspect
9 import os
10 import sys
11 
12 from setuptools import find_packages, setup
13 from setuptools.command.install import install
14 import fastentrypoints   # Monkey-patches setuptools.
15 
16 from get_version import __version__
17 
18 os.chdir(os.path.split(os.path.abspath(__file__))[0])
19 
20 PKG = "hy"
21 
22 long_description = """Hy is a Python <--> Lisp layer. It helps
23 make things work nicer, and lets Python and the Hy lisp variant play
24 nice together. """
25 
26 class Install(install):
27     def __compile_hy_bytecode(self):
28         for path in sorted(glob.iglob('hy/**.hy', recursive=True)):
29             importlib.util.cache_from_source(path, optimize=self.optimize)
30 
31     def run(self):
32         # Don't bother messing around with deps if they wouldn't be installed anyway.
33         # Code is based on setuptools's install.py.
34         if not (self.old_and_unmanageable or self.single_version_externally_managed
35                 or not self._called_from_setup(inspect.currentframe())):
36             easy_install = self.distribution.get_command_class('easy_install')
37 
38             cmd = easy_install(
39                 self.distribution, args="x", root=self.root, record=self.record,
40             )
41             cmd.ensure_finalized()
42             cmd.always_copy_from = '.'
43             cmd.package_index.scan(glob.glob('*.egg'))
44 
45             cmd.args = self.distribution.install_requires
46 
47             # Avoid deprecation warnings on new setuptools versions.
48             if 'show_deprecation' in inspect.signature(cmd.run).parameters:
49                 cmd.run(show_deprecation=False)
50             else:
51                 cmd.run()
52 
53             # Make sure any new packages get picked up.
54             import site
55             importlib.reload(site)
56             importlib.invalidate_caches()
57 
58         self.__compile_hy_bytecode()
59 
60         # The deps won't be reinstalled because of:
61         # https://github.com/pypa/setuptools/issues/456
62         return install.run(self)
63 
64 setup(
65     name=PKG,
66     version=__version__,
67     install_requires=[
68         'rply>=0.7.7',
69         'funcparserlib>=0.3.6',
70         'colorama',
71         'astor>=0.8 ; python_version < "3.9"',
72         'pyreadline>=2.1 ; os_name == "nt"',
73     ],
74     cmdclass=dict(install=Install),
75     entry_points={
76         'console_scripts': [
77             'hy = hy.cmdline:hy_main',
78             'hy3 = hy.cmdline:hy_main',
79             'hyc = hy.cmdline:hyc_main',
80             'hyc3 = hy.cmdline:hyc_main',
81             'hy2py = hy.cmdline:hy2py_main',
82             'hy2py3 = hy.cmdline:hy2py_main',
83         ]
84     },
85     packages=find_packages(exclude=['tests*']),
86     package_data={
87         'hy.contrib': ['*.hy', '__pycache__/*'],
88         'hy.core': ['*.hy', '__pycache__/*'],
89         'hy.extra': ['*.hy', '__pycache__/*'],
90     },
91     data_files=[
92         ('get_version', ['get_version.py'])
93     ],
94     author="Paul Tagliamonte",
95     author_email="tag@pault.ag",
96     long_description=long_description,
97     description='Lisp and Python love each other.',
98     license="Expat",
99     url="http://hylang.org/",
100     platforms=['any'],
101     classifiers=[
102         "Development Status :: 4 - Beta",
103         "Intended Audience :: Developers",
104         "License :: DFSG approved",
105         "License :: OSI Approved :: MIT License",  # Really "Expat". Ugh.
106         "Operating System :: OS Independent",
107         "Programming Language :: Lisp",
108         "Programming Language :: Python",
109         "Programming Language :: Python :: 3",
110         "Programming Language :: Python :: 3.6",
111         "Programming Language :: Python :: 3.7",
112         "Programming Language :: Python :: 3.8",
113         "Programming Language :: Python :: 3.9",
114         "Programming Language :: Python :: 3.10",
115         "Topic :: Software Development :: Code Generators",
116         "Topic :: Software Development :: Compilers",
117         "Topic :: Software Development :: Libraries",
118     ]
119 )
120
```

Path: `hy/completer.py`
Content:
```
1 # Copyright 2021 the authors.
2 # This file is part of Hy, which is free software licensed under the Expat
3 # license. See the LICENSE.
4 
5 import contextlib
6 import os
7 import re
8 import sys
9 import builtins
10 
11 import hy.macros
12 import hy.compiler
13 
14 
15 docomplete = True
16 
17 try:
18     import readline
19 except ImportError:
20     try:
21         import pyreadline.rlmain
22         import pyreadline.unicode_helper  # NOQA
23         import readline
24     except ImportError:
25         docomplete = False
26 
27 if docomplete:
28     if sys.platform == 'darwin' and 'libedit' in readline.__doc__:
29         readline_bind = "bind ^I rl_complete"
30     else:
31         readline_bind = "tab: complete"
32 
33 
34 class Completer(object):
35 
36     def __init__(self, namespace={}):
37         if not isinstance(namespace, dict):
38             raise TypeError('namespace must be a dictionary')
39         self.namespace = namespace
40         self.path = [builtins.__dict__,
41                      namespace]
42 
43         namespace.setdefault('__macros__', {})
44 
45         self.path.append(namespace['__macros__'])
46 
47     def attr_matches(self, text):
48         # Borrowed from IPython's completer
49         m = re.match(r"(\S+(\.[\w-]+)*)\.([\w-]*)$", text)
50 
51         if m:
52             expr, attr = m.group(1, 3)
53             attr = attr.replace("-", "_")
54             expr = expr.replace("-", "_")
55         else:
56             return []
57 
58         try:
59             obj = eval(expr, self.namespace)
60             words = dir(obj)
61         except Exception:
62             return []
63 
64         n = len(attr)
65         matches = []
66         for w in words:
67             if w[:n] == attr:
68                 matches.append("{}.{}".format(
69                     expr.replace("_", "-"), w.replace("_", "-")))
70         return matches
71 
72     def global_matches(self, text):
73         matches = []
74         for p in self.path:
75             for k in p.keys():
76                 if isinstance(k, str):
77                     k = k.replace("_", "-")
78                     if k.startswith(text):
79                         matches.append(k)
80         return matches
81 
82     def complete(self, text, state):
83         if "." in text:
84             matches = self.attr_matches(text)
85         else:
86             matches = self.global_matches(text)
87         try:
88             return matches[state]
89         except IndexError:
90             return None
91 
92 
93 @contextlib.contextmanager
94 def completion(completer=None):
95     delims = "()[]{} "
96     if not completer:
97         completer = Completer()
98 
99     if docomplete:
100         readline.set_completer(completer.complete)
101         readline.set_completer_delims(delims)
102 
103         history = os.environ.get(
104             "HY_HISTORY", os.path.expanduser("~/.hy-history"))
105         readline.parse_and_bind("set blink-matching-paren on")
106 
107         try:
108             readline.read_history_file(history)
109         except IOError:
110             pass
111 
112         readline.parse_and_bind(readline_bind)
113 
114     try:
115         yield
116     finally:
117         if docomplete:
118             try:
119                 readline.write_history_file(history)
120             except IOError:
121                 pass
122
```
--- 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()

```

diff --git a/hy/completer.py b/hy/completer.py
--- a/hy/completer.py
+++ b/hy/completer.py
@@ -16,13 +16,14 @@
 
 try:
     import readline
-except ImportError:
-    try:
-        import pyreadline.rlmain
-        import pyreadline.unicode_helper  # NOQA
-        import readline
-    except ImportError:
+except AttributeError as e:
+    # https://github.com/pyreadline/pyreadline/issues/65
+    if "module 'collections' has no attribute 'Callable'" in str(e):
         docomplete = False
+    else:
+        raise
+except ImportError:
+    docomplete = False
 
 if docomplete:
     if sys.platform == 'darwin' and 'libedit' in readline.__doc__:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -69,7 +69,6 @@
         'funcparserlib>=0.3.6',
         'colorama',
         'astor>=0.8 ; python_version < "3.9"',
-        'pyreadline>=2.1 ; os_name == "nt"',
     ],
     cmdclass=dict(install=Install),
     entry_points={

{"golden_diff": "diff --git a/hy/completer.py b/hy/completer.py\n--- a/hy/completer.py\n+++ b/hy/completer.py\n@@ -16,13 +16,14 @@\n \n try:\n     import readline\n-except ImportError:\n-    try:\n-        import pyreadline.rlmain\n-        import pyreadline.unicode_helper  # NOQA\n-        import readline\n-    except ImportError:\n+except AttributeError as e:\n+    # https://github.com/pyreadline/pyreadline/issues/65\n+    if \"module 'collections' has no attribute 'Callable'\" in str(e):\n         docomplete = False\n+    else:\n+        raise\n+except ImportError:\n+    docomplete = False\n \n if docomplete:\n     if sys.platform == 'darwin' and 'libedit' in readline.__doc__:\ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -69,7 +69,6 @@\n         'funcparserlib>=0.3.6',\n         'colorama',\n         'astor>=0.8 ; python_version < \"3.9\"',\n-        'pyreadline>=2.1 ; os_name == \"nt\"',\n     ],\n     cmdclass=dict(install=Install),\n     entry_points={\n", "issue": "Python 3.10 on Windows fails: AttributeError: module 'collections' has no attribute 'Callable'\nThanks to https://github.com/pyreadline/pyreadline/issues/65, Hy on Python 3.10 on Windows no longer starts, and a backtrace similar to the following is the result:\r\n\r\n```console\r\nTraceback (most recent call last):\r\n  File \"c:\\python\\lib\\runpy.py\", line 196, in _run_module_as_main\r\n    return _run_code(code, main_globals, None,\r\n  File \"c:\\python\\lib\\runpy.py\", line 86, in _run_code\r\n    exec(code, run_globals)\r\n  File \"C:\\Python\\Scripts\\hy.exe\\__main__.py\", line 4, in <module>\r\n  File \"c:\\python\\lib\\site-packages\\hy\\cmdline.py\", line 37, in <module>\r\n    from hy.completer import completion, Completer\r\n  File \"c:\\python\\lib\\site-packages\\hy\\completer.py\", line 18, in <module>\r\n    import readline\r\n  File \"c:\\python\\lib\\site-packages\\readline.py\", line 34, in <module>\r\n    rl = Readline()\r\n  File \"c:\\python\\lib\\site-packages\\pyreadline\\rlmain.py\", line 422, in __init__\r\n    BaseReadline.__init__(self)\r\n  File \"c:\\python\\lib\\site-packages\\pyreadline\\rlmain.py\", line 62, in __init__\r\n    mode.init_editing_mode(None)\r\n  File \"c:\\python\\lib\\site-packages\\pyreadline\\modes\\emacs.py\", line 633, in init_editing_mode\r\n    self._bind_key('space',       self.self_insert)\r\n  File \"c:\\python\\lib\\site-packages\\pyreadline\\modes\\basemode.py\", line 162, in _bind_key\r\n    if not callable(func):\r\n  File \"c:\\python\\lib\\site-packages\\pyreadline\\py3k_compat.py\", line 8, in callable\r\n    return isinstance(x, collections.Callable)\r\nAttributeError: module 'collections' has no attribute 'Callable'\r\n```\r\n\r\nUnfortunately from that bug (and the repository in general), it would appear that `pyreadline` is no longer actively maintained (last update of any kind was in 2015), so for Hy to continue to support Windows on future Python versions will require some amount of workaround (a fork of `pyreadline`, dropping readline support on Windows, etc).\r\n\r\nI'm not sure if there's a way to specify that Python 3.10+ and Windows are simply mutually incompatible, but that would be the \"simplest\" workaround if there's a clean way to specify that. :see_no_evil:\n", "before_files": [{"content": "#!/usr/bin/env python\n# Copyright 2021 the authors.\n# This file is part of Hy, which is free software licensed under the Expat\n# license. See the LICENSE.\n\nimport glob\nimport importlib\nimport inspect\nimport os\nimport sys\n\nfrom setuptools import find_packages, setup\nfrom setuptools.command.install import install\nimport fastentrypoints   # Monkey-patches setuptools.\n\nfrom get_version import __version__\n\nos.chdir(os.path.split(os.path.abspath(__file__))[0])\n\nPKG = \"hy\"\n\nlong_description = \"\"\"Hy is a Python <--> Lisp layer. It helps\nmake things work nicer, and lets Python and the Hy lisp variant play\nnice together. \"\"\"\n\nclass Install(install):\n    def __compile_hy_bytecode(self):\n        for path in sorted(glob.iglob('hy/**.hy', recursive=True)):\n            importlib.util.cache_from_source(path, optimize=self.optimize)\n\n    def run(self):\n        # Don't bother messing around with deps if they wouldn't be installed anyway.\n        # Code is based on setuptools's install.py.\n        if not (self.old_and_unmanageable or self.single_version_externally_managed\n                or not self._called_from_setup(inspect.currentframe())):\n            easy_install = self.distribution.get_command_class('easy_install')\n\n            cmd = easy_install(\n                self.distribution, args=\"x\", root=self.root, record=self.record,\n            )\n            cmd.ensure_finalized()\n            cmd.always_copy_from = '.'\n            cmd.package_index.scan(glob.glob('*.egg'))\n\n            cmd.args = self.distribution.install_requires\n\n            # Avoid deprecation warnings on new setuptools versions.\n            if 'show_deprecation' in inspect.signature(cmd.run).parameters:\n                cmd.run(show_deprecation=False)\n            else:\n                cmd.run()\n\n            # Make sure any new packages get picked up.\n            import site\n            importlib.reload(site)\n            importlib.invalidate_caches()\n\n        self.__compile_hy_bytecode()\n\n        # The deps won't be reinstalled because of:\n        # https://github.com/pypa/setuptools/issues/456\n        return install.run(self)\n\nsetup(\n    name=PKG,\n    version=__version__,\n    install_requires=[\n        'rply>=0.7.7',\n        'funcparserlib>=0.3.6',\n        'colorama',\n        'astor>=0.8 ; python_version < \"3.9\"',\n        'pyreadline>=2.1 ; os_name == \"nt\"',\n    ],\n    cmdclass=dict(install=Install),\n    entry_points={\n        'console_scripts': [\n            'hy = hy.cmdline:hy_main',\n            'hy3 = hy.cmdline:hy_main',\n            'hyc = hy.cmdline:hyc_main',\n            'hyc3 = hy.cmdline:hyc_main',\n            'hy2py = hy.cmdline:hy2py_main',\n            'hy2py3 = hy.cmdline:hy2py_main',\n        ]\n    },\n    packages=find_packages(exclude=['tests*']),\n    package_data={\n        'hy.contrib': ['*.hy', '__pycache__/*'],\n        'hy.core': ['*.hy', '__pycache__/*'],\n        'hy.extra': ['*.hy', '__pycache__/*'],\n    },\n    data_files=[\n        ('get_version', ['get_version.py'])\n    ],\n    author=\"Paul Tagliamonte\",\n    author_email=\"tag@pault.ag\",\n    long_description=long_description,\n    description='Lisp and Python love each other.',\n    license=\"Expat\",\n    url=\"http://hylang.org/\",\n    platforms=['any'],\n    classifiers=[\n        \"Development Status :: 4 - Beta\",\n        \"Intended Audience :: Developers\",\n        \"License :: DFSG approved\",\n        \"License :: OSI Approved :: MIT License\",  # Really \"Expat\". Ugh.\n        \"Operating System :: OS Independent\",\n        \"Programming Language :: Lisp\",\n        \"Programming Language :: Python\",\n        \"Programming Language :: Python :: 3\",\n        \"Programming Language :: Python :: 3.6\",\n        \"Programming Language :: Python :: 3.7\",\n        \"Programming Language :: Python :: 3.8\",\n        \"Programming Language :: Python :: 3.9\",\n        \"Programming Language :: Python :: 3.10\",\n        \"Topic :: Software Development :: Code Generators\",\n        \"Topic :: Software Development :: Compilers\",\n        \"Topic :: Software Development :: Libraries\",\n    ]\n)\n", "path": "setup.py"}, {"content": "# Copyright 2021 the authors.\n# This file is part of Hy, which is free software licensed under the Expat\n# license. See the LICENSE.\n\nimport contextlib\nimport os\nimport re\nimport sys\nimport builtins\n\nimport hy.macros\nimport hy.compiler\n\n\ndocomplete = True\n\ntry:\n    import readline\nexcept ImportError:\n    try:\n        import pyreadline.rlmain\n        import pyreadline.unicode_helper  # NOQA\n        import readline\n    except ImportError:\n        docomplete = False\n\nif docomplete:\n    if sys.platform == 'darwin' and 'libedit' in readline.__doc__:\n        readline_bind = \"bind ^I rl_complete\"\n    else:\n        readline_bind = \"tab: complete\"\n\n\nclass Completer(object):\n\n    def __init__(self, namespace={}):\n        if not isinstance(namespace, dict):\n            raise TypeError('namespace must be a dictionary')\n        self.namespace = namespace\n        self.path = [builtins.__dict__,\n                     namespace]\n\n        namespace.setdefault('__macros__', {})\n\n        self.path.append(namespace['__macros__'])\n\n    def attr_matches(self, text):\n        # Borrowed from IPython's completer\n        m = re.match(r\"(\\S+(\\.[\\w-]+)*)\\.([\\w-]*)$\", text)\n\n        if m:\n            expr, attr = m.group(1, 3)\n            attr = attr.replace(\"-\", \"_\")\n            expr = expr.replace(\"-\", \"_\")\n        else:\n            return []\n\n        try:\n            obj = eval(expr, self.namespace)\n            words = dir(obj)\n        except Exception:\n            return []\n\n        n = len(attr)\n        matches = []\n        for w in words:\n            if w[:n] == attr:\n                matches.append(\"{}.{}\".format(\n                    expr.replace(\"_\", \"-\"), w.replace(\"_\", \"-\")))\n        return matches\n\n    def global_matches(self, text):\n        matches = []\n        for p in self.path:\n            for k in p.keys():\n                if isinstance(k, str):\n                    k = k.replace(\"_\", \"-\")\n                    if k.startswith(text):\n                        matches.append(k)\n        return matches\n\n    def complete(self, text, state):\n        if \".\" in text:\n            matches = self.attr_matches(text)\n        else:\n            matches = self.global_matches(text)\n        try:\n            return matches[state]\n        except IndexError:\n            return None\n\n\n@contextlib.contextmanager\ndef completion(completer=None):\n    delims = \"()[]{} \"\n    if not completer:\n        completer = Completer()\n\n    if docomplete:\n        readline.set_completer(completer.complete)\n        readline.set_completer_delims(delims)\n\n        history = os.environ.get(\n            \"HY_HISTORY\", os.path.expanduser(\"~/.hy-history\"))\n        readline.parse_and_bind(\"set blink-matching-paren on\")\n\n        try:\n            readline.read_history_file(history)\n        except IOError:\n            pass\n\n        readline.parse_and_bind(readline_bind)\n\n    try:\n        yield\n    finally:\n        if docomplete:\n            try:\n                readline.write_history_file(history)\n            except IOError:\n                pass\n", "path": "hy/completer.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# Copyright 2021 the authors.\n# This file is part of Hy, which is free software licensed under the Expat\n# license. See the LICENSE.\n\nimport glob\nimport importlib\nimport inspect\nimport os\nimport sys\n\nfrom setuptools import find_packages, setup\nfrom setuptools.command.install import install\nimport fastentrypoints   # Monkey-patches setuptools.\n\nfrom get_version import __version__\n\nos.chdir(os.path.split(os.path.abspath(__file__))[0])\n\nPKG = \"hy\"\n\nlong_description = \"\"\"Hy is a Python <--> Lisp layer. It helps\nmake things work nicer, and lets Python and the Hy lisp variant play\nnice together. \"\"\"\n\nclass Install(install):\n    def __compile_hy_bytecode(self):\n        for path in sorted(glob.iglob('hy/**.hy', recursive=True)):\n            importlib.util.cache_from_source(path, optimize=self.optimize)\n\n    def run(self):\n        # Don't bother messing around with deps if they wouldn't be installed anyway.\n        # Code is based on setuptools's install.py.\n        if not (self.old_and_unmanageable or self.single_version_externally_managed\n                or not self._called_from_setup(inspect.currentframe())):\n            easy_install = self.distribution.get_command_class('easy_install')\n\n            cmd = easy_install(\n                self.distribution, args=\"x\", root=self.root, record=self.record,\n            )\n            cmd.ensure_finalized()\n            cmd.always_copy_from = '.'\n            cmd.package_index.scan(glob.glob('*.egg'))\n\n            cmd.args = self.distribution.install_requires\n\n            # Avoid deprecation warnings on new setuptools versions.\n            if 'show_deprecation' in inspect.signature(cmd.run).parameters:\n                cmd.run(show_deprecation=False)\n            else:\n                cmd.run()\n\n            # Make sure any new packages get picked up.\n            import site\n            importlib.reload(site)\n            importlib.invalidate_caches()\n\n        self.__compile_hy_bytecode()\n\n        # The deps won't be reinstalled because of:\n        # https://github.com/pypa/setuptools/issues/456\n        return install.run(self)\n\nsetup(\n    name=PKG,\n    version=__version__,\n    install_requires=[\n        'rply>=0.7.7',\n        'funcparserlib>=0.3.6',\n        'colorama',\n        'astor>=0.8 ; python_version < \"3.9\"',\n    ],\n    cmdclass=dict(install=Install),\n    entry_points={\n        'console_scripts': [\n            'hy = hy.cmdline:hy_main',\n            'hy3 = hy.cmdline:hy_main',\n            'hyc = hy.cmdline:hyc_main',\n            'hyc3 = hy.cmdline:hyc_main',\n            'hy2py = hy.cmdline:hy2py_main',\n            'hy2py3 = hy.cmdline:hy2py_main',\n        ]\n    },\n    packages=find_packages(exclude=['tests*']),\n    package_data={\n        'hy.contrib': ['*.hy', '__pycache__/*'],\n        'hy.core': ['*.hy', '__pycache__/*'],\n        'hy.extra': ['*.hy', '__pycache__/*'],\n    },\n    data_files=[\n        ('get_version', ['get_version.py'])\n    ],\n    author=\"Paul Tagliamonte\",\n    author_email=\"tag@pault.ag\",\n    long_description=long_description,\n    description='Lisp and Python love each other.',\n    license=\"Expat\",\n    url=\"http://hylang.org/\",\n    platforms=['any'],\n    classifiers=[\n        \"Development Status :: 4 - Beta\",\n        \"Intended Audience :: Developers\",\n        \"License :: DFSG approved\",\n        \"License :: OSI Approved :: MIT License\",  # Really \"Expat\". Ugh.\n        \"Operating System :: OS Independent\",\n        \"Programming Language :: Lisp\",\n        \"Programming Language :: Python\",\n        \"Programming Language :: Python :: 3\",\n        \"Programming Language :: Python :: 3.6\",\n        \"Programming Language :: Python :: 3.7\",\n        \"Programming Language :: Python :: 3.8\",\n        \"Programming Language :: Python :: 3.9\",\n        \"Programming Language :: Python :: 3.10\",\n        \"Topic :: Software Development :: Code Generators\",\n        \"Topic :: Software Development :: Compilers\",\n        \"Topic :: Software Development :: Libraries\",\n    ]\n)\n", "path": "setup.py"}, {"content": "# Copyright 2021 the authors.\n# This file is part of Hy, which is free software licensed under the Expat\n# license. See the LICENSE.\n\nimport contextlib\nimport os\nimport re\nimport sys\nimport builtins\n\nimport hy.macros\nimport hy.compiler\n\n\ndocomplete = True\n\ntry:\n    import readline\nexcept AttributeError as e:\n    # https://github.com/pyreadline/pyreadline/issues/65\n    if \"module 'collections' has no attribute 'Callable'\" in str(e):\n        docomplete = False\n    else:\n        raise\nexcept ImportError:\n    docomplete = False\n\nif docomplete:\n    if sys.platform == 'darwin' and 'libedit' in readline.__doc__:\n        readline_bind = \"bind ^I rl_complete\"\n    else:\n        readline_bind = \"tab: complete\"\n\n\nclass Completer(object):\n\n    def __init__(self, namespace={}):\n        if not isinstance(namespace, dict):\n            raise TypeError('namespace must be a dictionary')\n        self.namespace = namespace\n        self.path = [builtins.__dict__,\n                     namespace]\n\n        namespace.setdefault('__macros__', {})\n\n        self.path.append(namespace['__macros__'])\n\n    def attr_matches(self, text):\n        # Borrowed from IPython's completer\n        m = re.match(r\"(\\S+(\\.[\\w-]+)*)\\.([\\w-]*)$\", text)\n\n        if m:\n            expr, attr = m.group(1, 3)\n            attr = attr.replace(\"-\", \"_\")\n            expr = expr.replace(\"-\", \"_\")\n        else:\n            return []\n\n        try:\n            obj = eval(expr, self.namespace)\n            words = dir(obj)\n        except Exception:\n            return []\n\n        n = len(attr)\n        matches = []\n        for w in words:\n            if w[:n] == attr:\n                matches.append(\"{}.{}\".format(\n                    expr.replace(\"_\", \"-\"), w.replace(\"_\", \"-\")))\n        return matches\n\n    def global_matches(self, text):\n        matches = []\n        for p in self.path:\n            for k in p.keys():\n                if isinstance(k, str):\n                    k = k.replace(\"_\", \"-\")\n                    if k.startswith(text):\n                        matches.append(k)\n        return matches\n\n    def complete(self, text, state):\n        if \".\" in text:\n            matches = self.attr_matches(text)\n        else:\n            matches = self.global_matches(text)\n        try:\n            return matches[state]\n        except IndexError:\n            return None\n\n\n@contextlib.contextmanager\ndef completion(completer=None):\n    delims = \"()[]{} \"\n    if not completer:\n        completer = Completer()\n\n    if docomplete:\n        readline.set_completer(completer.complete)\n        readline.set_completer_delims(delims)\n\n        history = os.environ.get(\n            \"HY_HISTORY\", os.path.expanduser(\"~/.hy-history\"))\n        readline.parse_and_bind(\"set blink-matching-paren on\")\n\n        try:\n            readline.read_history_file(history)\n        except IOError:\n            pass\n\n        readline.parse_and_bind(readline_bind)\n\n    try:\n        yield\n    finally:\n        if docomplete:\n            try:\n                readline.write_history_file(history)\n            except IOError:\n                pass\n", "path": "hy/completer.py"}]}