Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

guppy.decorator.guppy.set_module breaks every test #101

Closed
aborgna-q opened this issue Jan 15, 2024 · 5 comments · Fixed by #105
Closed

guppy.decorator.guppy.set_module breaks every test #101

aborgna-q opened this issue Jan 15, 2024 · 5 comments · Fixed by #105
Assignees
Labels
bug Something isn't working

Comments

@aborgna-q
Copy link
Collaborator

aborgna-q commented Jan 15, 2024

I added this innocuous test case that sets the decorator's default module

def test_decorator():
    default_module = GuppyModule("default")
    guppy.set_module(default_module)
    
    @guppy
    def a() -> None:
        pass
        
    assert default_module.contains_function("a")

Since the decorator compiles the program when called without an explicit module, this causes every other test after it to crash.

FAILED tests/integration/test_unused.py::test_not_always_defined3 - guppy.error.GuppyError: The module `default` has already been compiled
...
=========================================== 58 failed, 142 passed, 9 skipped in 1.56s ============================================
@aborgna-q aborgna-q added the bug Something isn't working label Jan 15, 2024
@aborgna-q aborgna-q changed the title guppy.decorator.guppy.set_module causes errors guppy.decorator.guppy.set_module breaks every test Jan 15, 2024
@aborgna-q
Copy link
Collaborator Author

I think it'd be better to not have the global state in guppy._module, and instead to return an instance when we want to set the default;

guppy = decorator.guppy.with_default(my_module)

@guppy
def a() -> None:
    pass

And in that overridden case, we should avoid automatically compiling the result (since we do have access to the module).

@mark-koch
Copy link
Collaborator

Yeah, the current solution is not great.

I like your suggestion. Additionally, we could also offer a context manager:

with guppy.module(my_module):
    @guppy
    def foo() -> None:
        pass

Though the extra indentation could be annoying...

Something I've been thinking about is that the implicitly generated module could be used accross the whole Python file/module:

# File example.py

@guppy  # Automatically generates a Guppy module named "example"
def foo() -> None:
    pass

@guppy  # Places the function into the same module
def bar() -> None:
    pass

hugr = guppy.compile()  # Compiles the implicit module for this file

This could be very convenient since I believe in most cases, users want to have all function in the file placed into the same module anyways. Though I'm not sure how this would play with Jupyter notebooks.

@aborgna-q
Copy link
Collaborator Author

I like the per-context module idea. Ideally this should work in local contexts that are potentially executed multiple times, e.g.

def test() -> Hugr:
    # Initialize a module local to this function
    @guppy
    def foo() -> None:
        pass
    # Compile the module, and clear it out from the decorator state.
    return guppy.compile()
    
test()
# Creates a _new_ module, and compiles it.
test()

@aborgna-q
Copy link
Collaborator Author

We may be able to combine the idea with the resource manager. We'll need some sort of stack of local modules 🤔

@mark-koch
Copy link
Collaborator

I think we probably want a dictionary mapping Python module names to Guppy modules (since there could be multiple files). If calling guppy.compile() clears the entry in the dict, I think your example would work?

@aborgna-q aborgna-q self-assigned this Jan 15, 2024
aborgna-q added a commit that referenced this issue Jan 18, 2024
Makes `@guppy` define local modules by default. Fixes #101.

- Removes `_Guppy.set_module`
- Adds a `_Guppy.compile` that compiles and returns the local module.
- Similarly, a `_Guppy.take_module` that returns the module without
compiling it (and removes it from the local context).
- Adds a `@guppy(compile=True)` option as a fall-back to the previous
behaviour, where it directly compiles a Hugr.

Look at the first commit. The second is just noise updating the tests to
use the `compile` flag.

I wonder if it'd be better to have a different decorator that compiles
directly to hugrs instead of the `compile` flag.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants