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

include_source as in-source option replacing MODAL_AUTOMOUNT #2804

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

freider
Copy link
Contributor

@freider freider commented Jan 24, 2025

Introduces an include_source argument in App.__init__, app.function and app.cls that lets users configure which class of python packages are automatically included as source mounts in created modal functions/classes (what we used to call "automount" behavior).

This will supersede the MODAL_AUTOMOUNT configuration value which will eventually be deprecated.

In follow up PR, anyone that is still on "MODAL_AUTOMOUNT=1" behavior (the default), hasn't explicitly set include_source=True | False and seemingly rely on automounting in their code will be warned that implicit automounting is going away soon and they need to use the include_source in-code configuration option instead to keep the old behavior (or preferably add explicit .add_local_python_source() to their images).

Backward/forward compatibility checks

Check these boxes or delete any item (or this section) if not relevant for this PR.

  • Client+Server: this change is compatible with old servers
  • Client forward compatibility: this change ensures client can accept data intended for later versions of itself

Note on protobuf: protobuf message changes in one place may have impact to
multiple entities (client, server, worker, database). See points above.


Changelog

  • Introduces an include_source argument in the App.function and App.cls decorators that let users configure which class of python packages are automatically included as source mounts in created modal functions/classes (what we used to call "automount" behavior). This will supersede the MODAL_AUTOMOUNT configuration value which will eventually be deprecated. As a convenience, the modal.App constructor will also accept an include_source argument which serves as the default for all the app's functions and classes.

    The include_source argument accepts the following values:

    • True (default in a future version of Modal) Automatically includes the Python files of the source package of the function's own home module, but not any other local packages. Roughly equivalent ot MODAL_AUTOMOUNT=0 in previous versions of Modal.
    • False - don't include any local source. Assumes the function's home module is importable in the container environment through some other means (typically added to the provided modal.Image's Python environment).
    • None (the default) - use current soon-to-be-deprecated automounting behavior, including source of all first party packages that are not installed into site-packages locally.
  • Minor change to MODAL_AUTOMOUNT=0: When running/deploying using a module path (e.g. modal run mypak.mymod), all non .pyc files of the source package (mypak in this case) are now included in the function's container. Previously, only the function's home .py module file + any __init__.py files in its package structure were included. Note that this is only for MODAL_AUTOMOUNT=0. To get full control over which source files are included with your functions, you can set include_source=False on your function (see above) and manually specify the files to include using the ignore argument to Image.add_local_python_source.

@freider freider changed the title "Automount" as in-source option include_source as in-source option replacing MODAL_AUTOMOUNT Jan 24, 2025
@freider freider requested a review from mwaskom January 24, 2025 13:43
@@ -60,3 +60,6 @@ known-first-party = [
"modal_version",
]
extra-standard-library = ["pytest"]

[tool.pyright]
reportUnnecessaryComparison = true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found this gem for pyright that is deactivated by default - warns if a comparison would always evaluate to False because you mistyped a literal etc.

env={**os.environ, "MODAL_AUTOMOUNT": "0"},
)
assert p.returncode == 0
files = set(servicer.files_name2sha.keys()) - set(env_mount_files)
assert files == {
"/root/pkg_a/__init__.py",
"/root/pkg_a/a.py",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to the automount=0 behavior results in this, as documented by the second changelog bullet

@mwaskom
Copy link
Contributor

mwaskom commented Jan 28, 2025

I edited the changelog for formatting but have two questions about it:

  • Is "this_package" a magical incantation to get add "self"?
  • Would it be simpler to ignore *.pyc?

@freider
Copy link
Contributor Author

freider commented Jan 28, 2025

I edited the changelog for formatting but have two questions about it:

  • Is "this_package" a magical incantation to get add "self"?
  • Would it be simpler to ignore *.pyc?

I just removed the change of the entrypoint mount file inclusion filter from this PR, since it feels like a big enough change that it warrants a deprecation warning first. Made a comment and will make a separate PR that adds that warning instead

This_package is not a magical incantation, it just served as an example of the package containing the function, I think. Removing .pyc might be simpler yeah - all files in pycache should be .pyc right?

@@ -346,7 +341,7 @@ def get_entrypoint_mount(self) -> list[_Mount]:
remote_path=remote_path,
)
]
return []
return [] # this should never be reached...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is known in the business as "dramatic foreshadowing"

field = rand.choice(list(oneof.fields) + [None])
if field is not None:
oneof_fields.add(field.name)
oneof_field: Union[FieldDescriptor, None] = rand.choice(list(oneof.fields) + [None])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was some typing BS that randomly popped up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants