-
Notifications
You must be signed in to change notification settings - Fork 4
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
Integrate VirtualEnv management into Component #296
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I asked a couple of questions about bigger picture architecture and future plans. I'm fine with merging it as-is, unless you think any changes make sense given my comments.
agentos/cli.py
Outdated
frozen_reg = component.to_frozen_registry(force=force) | ||
print(yaml.dump(frozen_reg.to_dict())) | ||
component = Component.from_registry_file(registry_file, component_name) | ||
component.set_environment_handling(use_venv) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we setup environment handling as part of the Component creation (and thus Virtual Env creation) process? I.e., in this case that would happen as part of the Component.from_registry_file()
call on line 235.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, yeah, that seems better.
One (related) awkwardness is that every time we add a new argument to Component.__init__()
, we (usually) need to add that argument to all the Component.from_*()
methods, even if it's just passed through to the Component constructor.
I'm thinking there might be a way to streamline this when we get to the point of making the Component constructor the one source of truth for the spec structure.
But for now, it does seem nicer to add an optional argument to the Component.from_*()
methods instead of a separate setter/getter. Will fix!
agentos/component.py
Outdated
managed_obj = getattr(module, self.class_name) | ||
sys.path.pop() | ||
return managed_obj | ||
|
||
def _build_virtual_env(self) -> VirtualEnv: | ||
if not self._use_venv: | ||
return VirtualEnv(use_venv=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels a little confusing to return a VirtualEnv where everything is a no-op. IIRC, we do this because the no-op venv is equivalent to using the existing the developer's env (which may be a venv or may not), and it is cleaner to just have a no-op VirtualEnv that encapsulates all of the if use_venv: ...
statements than having to use those if statements wherever we use the VirtualEnv instance. Is that right?
If I'm right, then it seems like returning a NoOpVirtualEnv
or DummyVirtualEnv
that implements the same interface as VirtualEnv
might be more intuitive than having a VirtualEnv.use_venv
attribute.
But I'm very likely missing other constraint or nuance here!
Maybe you're planning on cleaning this up as part of #297?
If we do keep the no-op behavior here in VirtualEnv as is, then can we document it in the VirtualEnv class docstring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is cleaner to just have a no-op VirtualEnv that encapsulates all of the if
use_venv: ...
statements than having to use those if statements wherever we use the VirtualEnv instance. Is that right?
Yep, you got it. I have found myself wanting the following pattern several times in the codebase:
if flag:
with context_manager():
do_thing()
else:
do_thing()
but that feels like an awkward pattern to me, so I often try to squish it into straight-line code that always gets a context manager (but that context manager may do nothing, depending on flag
):
with get_maybe_noop_context_manager(flag):
do_thing()
Maybe the latter is less grokkable than the former approach; I'm not sure. Happy to standardize on either one if you have a strong opinion.
But yeah, I like the idea of a NoOpVirtualEnv
. Will fix!
Alrighty @andyk, addressed your comments. Will merge when green. Thanks, as always, for the review! :) |
As the title says, this PR moves venv management into the Component. It also cleans up the VirtualEnv API a little bit (
will create an additional issue for further improvementssee #297):The following demo now works (note, no manual venv management required). First in bash, create a new empty Python environment to run the demo script and install agentos:
Now try to manually build and run the sb3_agent in the Python REPL:
Fixes #280.