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

fix[lang]: disallow absolute relative imports #4268

Open
wants to merge 26 commits into
base: master
Choose a base branch
from

Conversation

sandbubbles
Copy link
Collaborator

What I did

How I did it

  • Removed implicit relative imports in submodules, eliminating ambiguity in import paths.
  • Removed the lines that added the current directory to the top of the search paths. As a result, the poke_search_path function may no longer be necessary.

How to verify it

  • added tests

Commit message

Commit message for the final, squashed PR. (Optional, but reviewers will appreciate it! Please see our commit message style guide for what we would ideally like to see in a commit message.)

Description for the changelog

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@sandbubbles sandbubbles changed the title fix[lang]: disallow absolute relative paths fix[lang]: disallow absolute relative imports Oct 1, 2024
Copy link
Member

@charles-cooper charles-cooper left a comment

Choose a reason for hiding this comment

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

yes, i think poke_search_paths is probably dead now. can you check? if so, let's remove it!

@@ -789,11 +789,7 @@ def _add_import(
# load an InterfaceT or ModuleInfo from an import.
# raises FileNotFoundError
def _load_import(self, node: vy_ast.VyperNode, level: int, module_str: str, alias: str) -> Any:
Copy link
Member

Choose a reason for hiding this comment

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

i guess we can fuse load_import_helper right?

Copy link

codecov bot commented Oct 15, 2024

Codecov Report

Attention: Patch coverage is 25.00000% with 9 lines in your changes missing coverage. Please review.

Project coverage is 51.84%. Comparing base (b3ea663) to head (f2ca3c8).

Files with missing lines Patch % Lines
vyper/semantics/analysis/imports.py 25.00% 9 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (b3ea663) and HEAD (f2ca3c8). Click for more details.

HEAD has 127 uploads less than BASE
Flag BASE (b3ea663) HEAD (f2ca3c8)
138 11
Additional details and impacted files
@@             Coverage Diff             @@
##           master    #4268       +/-   ##
===========================================
- Coverage   91.40%   51.84%   -39.57%     
===========================================
  Files         112      112               
  Lines       15927    15921        -6     
  Branches     2694     2695        +1     
===========================================
- Hits        14558     8254     -6304     
- Misses        935     7055     +6120     
- Partials      434      612      +178     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines +321 to +323
vyper.compiler.compile_code(
code, resolved_path=input_bundle.search_paths[0] / "code.vy", input_bundle=input_bundle
)
Copy link
Member

Choose a reason for hiding this comment

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

why is this change needed?

Copy link
Collaborator Author

@sandbubbles sandbubbles Oct 16, 2024

Choose a reason for hiding this comment

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

Because it imports by a relative path, it needs the current path of the file. By default it is left to unknown (UNKNOWN_CONTRACT_NAME), so then when we ask for the current directory (by .parent) it gets evaluated to "." instead of the temporary directory vreated by the test. But i think you are right that i added it somewhere unnecessarily.

@cyberthirst
Copy link
Collaborator

cyberthirst commented Oct 17, 2024

@charles-cooper, have you considered the concept of packages? because we don't have it, we allow relative imports that can point even outside the project's directory


assert (
compile_code(
code, resolved_path=(input_bundle.search_paths[0]) / subdirs, input_bundle=input_bundle
Copy link
Collaborator

Choose a reason for hiding this comment

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

shouldn't the resolved path end with a file? like code for the 2nd case should be in a/b, right? in which case ..a resolves to a/a and we should get file not found?

@charles-cooper
Copy link
Member

@charles-cooper, have you considered the concept of packages? because we don't have it, we allow relative imports that can point even outside the project's directory

yeah i know, those will raise a compiler panic if you try to create an input bundle.

i think it might be useful to introduce packages, but it needs some design work, and not sure how useful it would really be.

@cyberthirst
Copy link
Collaborator

yeah i know, those will raise a compiler panic if you try to create an input bundle.

i have main.vy in ./tests/custom and run vyper from the same dir as in which tests are

from .... import lib1

exports: lib1.__interface__

so the import targets a file which is in the parent of the project's dir (from which vyper's run) .. and it compiles fine

Comment on lines 155 to 163
def _load_file(self, path: PathLike, level: int):
if level == 0:
self.input_bundle.search_paths = self.absolute_search_paths
else:
ast = self.graph.current_module
current_search_path = Path(ast.resolved_path).parent
self.input_bundle.search_paths = [current_search_path]

with self.input_bundle.poke_search_path(self_search_path):
return self._load_import_helper(node, level, module_str, alias)
return self.input_bundle.load_file(path)
Copy link
Member

Choose a reason for hiding this comment

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

nit: can we move this after _load_import to match the other functions, which are laid out in reverse dependency order

else:
ast = self.graph.current_module
current_search_path = Path(ast.resolved_path).parent
self.input_bundle.search_paths = [current_search_path]
Copy link
Member

Choose a reason for hiding this comment

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

i think this corrupts the input bundle's search path, which might be important if anybody tries to access the search path after compilation (for instance as is done in output_bundle.py). i think we need to restore the original .search_paths after load_file is called.

@cyberthirst
Copy link
Collaborator

cyberthirst commented Oct 29, 2024

yeah i know, those will raise a compiler panic if you try to create an input bundle.

i have main.vy in ./tests/custom and run vyper from the same dir as in which tests are

from .... import lib1

exports: lib1.__interface__

so the import targets a file which is in the parent of the project's dir (from which vyper's run) .. and it compiles fine

i tried to create an output bundle (vyper -f archive) with this setup and it led to compiler panic

Error compiling: tests/custom/test4.vy
vyper.exceptions.CompilerPanic: Invalid path: /Users/blabla/lib1.vy

This is an unhandled internal compiler error. Please create an issue on Github to notify the developers!
https://github.com/vyperlang/vyper/issues/new?template=bug.md

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.

import system allows absolute relative imports
3 participants