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

Infra: allow for multiple install_hooks() running at the same time #448

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

Conversation

kbolashev
Copy link
Member

@kbolashev kbolashev commented Mar 14, 2024

Infra changes:

  • Added ruff and mypy into dev dependencies (will probably add them to GH Actions in a later PR)
  • Split the DagsHubFilesystem into two classes: DagsHubFilesystem that does the file access stuff, and HookRouter that runs the hook infra + routes the functions to the correct DHFilesystem.
  • Added test scenarios testing multiple hooks running at the same time

Functional changes:

  • Now multiple install_hooks() can be running at the same time and any file access function will be routed to the correct filesystem.
  • uninstall_hooks() now has fs and path arguments that remove specific filesystems. By default all filesystems will be removed
  • Add a get_mounted_filesystems function that returns a list of tuples of (<full mount path>, <fs object>)

Shouldn't be anything backwards-incompatible from a user API perspective

@kbolashev kbolashev added the enhancement New feature or request label Mar 14, 2024
@kbolashev kbolashev self-assigned this Mar 14, 2024
Copy link

dagshub bot commented Mar 14, 2024

@kbolashev
Copy link
Member Author

@guysmoilov guysmoilov self-requested a review March 25, 2024 09:20
Copy link
Member

@guysmoilov guysmoilov left a comment

Choose a reason for hiding this comment

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

Partial review

ruff.toml Outdated Show resolved Hide resolved
dagshub/streaming/errors.py Outdated Show resolved Hide resolved
dagshub/common/api/repo.py Outdated Show resolved Hide resolved
dagshub/common/api/repo.py Outdated Show resolved Hide resolved
@@ -229,16 +253,22 @@ def get_file(self, path: str, revision: Optional[str] = None) -> bytes:
Returns:
bytes: The content of the file.
"""
res = self._http_request("GET", self.raw_api_url(path, revision))
res = self._http_request("GET", self.raw_api_url(path, revision), timeout=None)
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand the meaning of timeout=None and why it applies only here

Copy link
Member Author

@kbolashev kbolashev Mar 26, 2024

Choose a reason for hiding this comment

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

Getting a file has a high possibility of timing out when a user tries to download a huge file.
I set it to infinite wherever there is a chance that there'll be a big file transfer

absolute_path: Optional[Path]
relative_path: Optional[Path]
original_path: Optional[Path]
def __init__(self, fs: "DagsHubFilesystem", file_path: Union[str, bytes, PathLike, "DagshubPath"]):
Copy link
Member

Choose a reason for hiding this comment

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

Why not reuse?

Suggested change
def __init__(self, fs: "DagsHubFilesystem", file_path: Union[str, bytes, PathLike, "DagshubPath"]):
def __init__(self, fs: "DagsHubFilesystem", file_path: PathTypeWithDagshubPath):

Copy link
Member Author

@kbolashev kbolashev Mar 26, 2024

Choose a reason for hiding this comment

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

PathType/PathTypeWithDagshubPath allows an int, which I handle in all of the functions that create DagshubPath before creating it (and that usually means that it's a file descriptor and I can do nothing but just call the original function).
By not having an int here mypy complains that the int wasn't handled

def parse_path(self, file_path: Union[str, bytes, PathLike, "DagshubPath"]) -> Tuple[Path, Optional[Path], Path]:
if isinstance(file_path, DagshubPath):
self.is_binary_path_requested = file_path.is_binary_path_requested
if file_path.fs != self.fs:
Copy link
Member

Choose a reason for hiding this comment

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

If the fs is the same, then we're just creating a copy of the input?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes

return file_path.absolute_path, file_path.relative_path, file_path.original_path
if isinstance(file_path, bytes):
file_path = os.fsdecode(file_path)
orig_path = Path(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.

You don't want to save the original bytes representation of the file_path ?

Copy link
Member Author

@kbolashev kbolashev Mar 26, 2024

Choose a reason for hiding this comment

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

I want to have the og requested path as a Path object because it's more convenient to use.
Having the original path be both a Path object and an additional PathType would be confusing w.r.t. "which one should I be using", so I kept just the single thing I actually care about in it, which is whether the requested path was bytes or not

Copy link
Member Author

Choose a reason for hiding this comment

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

I checked the usages, and it's probably alright to actually just carry over the original path, because I'm not working with it that much

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed it to carry over as-is

if isinstance(file_path, bytes):
file_path = os.fsdecode(file_path)
orig_path = Path(file_path)
abspath = Path(os.path.abspath(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.

This should always be relative to PWD ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can you elaborate on the question? Didn't understand it

abspath = Path(os.path.abspath(file_path))
try:
relpath = abspath.relative_to(os.path.abspath(self.fs.project_root))
if str(relpath).startswith("<"):
Copy link
Member

Choose a reason for hiding this comment

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

What does this condition mean?

Copy link
Member Author

Choose a reason for hiding this comment

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

Honestly don't remember.
Maybe something relating to a different drive, but the docs say that relative_to will throw an error if they are on different drives altogether.

Probably an old leftover, so maybe should delete it

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a commit where it got added: 9174106

Copy link
Member Author

Choose a reason for hiding this comment

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

If it's some IPython magic, then it's probably better to leave it, but could be useful to know how to trigger it at least 🤔

@kbolashev kbolashev changed the base branch from master to feature/models_loading March 27, 2024 08:22
@kbolashev kbolashev changed the base branch from feature/models_loading to master March 27, 2024 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants