0

With the following pytest file:

(import pytest [mark])
(import pathlib [Path])
(require oreo [with-cwd])
(defn [mark.with-cwd] test-with-cwd [cookies]
      (let [ cwd (.cwd Path) ]
           (with-cwd cookies (assert (= (.cwd Path) cookies)))
           (assert (= (.cwd Path) cwd))))

I'm getting the following error:

Traceback (most recent call last):
  File "/home/shadowrylander/shadowrylander/sylveon/syvlorg/oreo/tests/test-with-cwd.hy", line 7, in test_with_cwd
    (with-cwd cookies (assert (= (.cwd Path) cookies)))
NameError: name 'os' is not defined

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/shadowrylander/shadowrylander/sylveon/syvlorg/oreo/tests/test-with-cwd.hy", line 7, in test_with_cwd
    (with-cwd cookies (assert (= (.cwd Path) cookies)))
NameError: name 'os' is not defined

The cookies fixture is as follows:

@pytest.fixture()
def cookies(request):
    from pathlib import Path
    return Path(request.config.rootdir).expanduser().resolve(strict = True) / "cookies"

And finally, with-cwd in the oreo module is basically:

(eval-and-compile (import os hy))
(defmacro with-cwd [dir #* body]
          (setv cwd (hy.gensym))
          `(let [ ~cwd (.cwd Path) ]
                (try (.chdir os ~dir)
                     ~@body
                     (finally (.chdir os ~cwd)))))

I am using hy version 0.25.0. The test works if I import os in the test file itself.


Update

This new one does not seem to work either, giving me the same error:

(defmacro with-cwd [dir #* body]
          (setv cwd (hy.gensym)
                os (hy.gensym))
          `(let [ ~cwd (.cwd Path) ]
                (import os :as ~os)
                (try ((. ~os chdir) ~dir)
                     ~@body
                     (finally ((. ~os chdir) ~cwd)))))

ShadowRylander
  • 361
  • 2
  • 8

1 Answers1

1

It sounds like you've all but entirely answered your own question, but haven't quite the connected the dots. As usual, it's easier to see what's going on in a minimal example:

(defmacro m []
  (import os)
  `(os.getcwd))

(print (m))

This raises NameError: name 'os' is not defined because os indeed is not defined at runtime in the scope in which m expands. The code is equivalent to simply

(print (os.getcwd))

So either os has to already be in the scope where the macro expands, or you have to include the import in the expansion, like so:

(defmacro m []
  (setv os (hy.gensym))
  `(do
    (import os :as ~os)
    ((. ~os getcwd))))

(print (m))
Kodiologist
  • 2,984
  • 18
  • 33
  • But I thought that's what `(eval-and-compile (import os))` does? Do I need that line, then? – ShadowRylander Jan 07 '23 at 04:03
  • Also, it still does not seem to be working; I've updated my question with the new macro. – ShadowRylander Jan 07 '23 at 05:45
  • @ShadowRylander "But I thought that's what `(eval-and-compile (import os))` does?" — It's expanding in the wrong file to solve your problem. "Also, it still does not seem to be working" — I've told you several times that you need to simplify your code to the minimum example that reproduces your problem, and when your problem involves multiple files, you should provide the exact shell commands to generate each. If you still can't be bothered to do this, I'm not going to keep helping you. Simplification would in many cases help you solve the problem yourself. – Kodiologist Jan 07 '23 at 15:17
  • Is there any official documentation for testing `hy` scripts? Once again, my problem was that my test files were being cached, which means the old code was being used. Next time, I will try to add my shell commands as well; I am using an extremely complicated setup, which means I can't state every last command I use. – ShadowRylander Jan 07 '23 at 19:17
  • "Is there any official documentation for testing `hy` scripts?" — No. "I am using an extremely complicated setup" — Then when you want to ask a question, simplify. – Kodiologist Jan 07 '23 at 23:31
  • Fair enough; thanks for the help! – ShadowRylander Jan 08 '23 at 08:32
  • Although could you give me some tips on how to simplify these? For example, do I need to simplify the code itself more, or the testing procedure, or all of the above...? – ShadowRylander Jan 08 '23 at 09:01
  • 1
    @ShadowRylander You can try going bottom-up, by writing the simplest possible code that replicates your error, or top-down, by systematically removing parts of your code until you have the simplest possible code that replicates your error. The top-down approach is usually more effective when you don't have any leads about what's going on. For example, the first step in your case here would've been to replicate the error without `pytest`. Then you could try using a stub library with just the macro in question rather than `oreo`. And so on. – Kodiologist Jan 08 '23 at 17:44