Repository: hylang/hy

Issue:
Can't `hy.eval` a `require` form in Python
I'm getting an error when doing a `require` using the `hy.eval` functionality.

The version of python works when hy is loaded:

```
hy 0.18.0 using CPython(default) 3.7.5 on Darwin                                                                                                                                
=> (require  [hy.contrib.walk [let]])                                                                                                                                           
True
```  

but fails when doing the same thing in python.

```
$ python
Python 3.7.5 (default, Jun  8 2020, 17:36:22) 
[Clang 11.0.3 (clang-1103.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import hy
>>> hy.eval(hy.read_str("(require  [hy.contrib.walk [let]])"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/chris/.pyenv/versions/3.7.5/lib/python3.7/site-packages/hy/compiler.py", line 2099, in hy_eval
    module.__dict__, locals)
  File "<string>", line 1, in <module>
  File "/Users/chris/.pyenv/versions/3.7.5/lib/python3.7/site-packages/hy/macros.py", line 170, in require
    if _same_modules(source_module, target_module):
  File "/Users/chris/.pyenv/versions/3.7.5/lib/python3.7/site-packages/hy/macros.py", line 118, in _same_modules
    target_filename = _get_filename(target_module)
  File "/Users/chris/.pyenv/versions/3.7.5/lib/python3.7/site-packages/hy/macros.py", line 109, in _get_filename
    filename = loader.get_filename()
AttributeError: type object 'BuiltinImporter' has no attribute 'get_filename'
```

Discussion:
homonoidian: I wrote a simple test; didn't know where exactly to place it, though; so it is where it is. My first contribution, I don't know things... but hope to help.
Kodiologist: There's no need to call Python as an external command for the test. Just use the Python code you want to test as the body of your test.

Use `tests/resources/macros.hy` instead of `let` for an example macro.

The commit message and the title of this issue should be more descriptive; "Fix #1911" is uninformative without first looking up the bug.
Kodiologist: Thanks, good work. Would you please:
- Move the test to `tests/importer/test_importer.py`
- Rename it to remove the "bin"
- Update NEWS
- Squash your changes into one commit
- As a separate commit, add yourself to AUTHORS
homonoidian: Thank y'all for patience with me. Hope the thing is right now.

Patch:
diff --git a/AUTHORS b/AUTHORS
index aa9ce4b7..eda7ad9c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -99,4 +99,5 @@
 * Raymund MARTINEZ <zhaqenl@protonmail.com>
 * Zepeng Zhang <redraiment@gmail.com>
 * Joseph Egan <joseph.s.egan@gmail.com>
-* Xi Jin <xij@usc.edu>
\ No newline at end of file
+* Xi Jin <xij@usc.edu>
+* Alexey Yurchenko <homonoidian@yandex.ru>
diff --git a/NEWS.rst b/NEWS.rst
index 7895d516..260668ec 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -1,5 +1,12 @@
 .. default-role:: code
 
+Unreleased
+==============================
+
+Bug Fixes
+------------------------------
+* Fixed a bug that made `hy.eval` from Python fail on `require`.
+
 0.19.0
 ==============================
 
diff --git a/hy/macros.py b/hy/macros.py
index cb8178ed..43c5913b 100644
--- a/hy/macros.py
+++ b/hy/macros.py
@@ -105,7 +105,7 @@ def _same_modules(source_module, target_module):
         try:
             if not inspect.ismodule(module):
                 loader = pkgutil.get_loader(module)
-                if loader:
+                if isinstance(loader, importlib.machinery.SourceFileLoader):
                     filename = loader.get_filename()
             else:
                 filename = inspect.getfile(module)


Test patch:
diff --git a/tests/importer/test_importer.py b/tests/importer/test_importer.py
index 90806d75..ef044315 100644
--- a/tests/importer/test_importer.py
+++ b/tests/importer/test_importer.py
@@ -289,3 +289,9 @@ def test_docstring():
         assert mod.a == 1
     finally:
         sys.path.pop(0)
+
+
+def test_hy_python_require():
+    # https://github.com/hylang/hy/issues/1911
+    test = "(do (require [tests.resources.macros [test-macro]]) (test-macro) blah)"
+    assert hy.eval(hy.read_str(test)) == 1