# Buggy code
def open(self, path, mode="r", encoding="utf-8", remote=None):  # pylint: disable=arguments-differ
    try:
        outs = self._find_outs(path, strict=False)
    except OutputNotFoundError as exc:
        raise FileNotFoundError from exc

    if len(outs) != 1 or (outs[0].is_dir_checksum and path == outs[0].path_info):
        raise IsADirectoryError

    out = outs[0]
    if out.changed_cache(filter_info=path):
        if not self.fetch and not self.stream:
            raise FileNotFoundError

        remote_obj = self.repo.cloud.get_remote(remote)
        if self.stream:
            if out.is_dir_checksum:
                checksum = self._get_granular_checksum(path, out)
            else:
                checksum = out.hash_info.value
            try:
                remote_info = remote_obj.tree.hash_to_path_info(checksum)
                return remote_obj.tree.open(remote_info, mode=mode, encoding=encoding)
            except RemoteActionNotImplemented:
                pass
        cache_info = out.get_used_cache(filter_info=path, remote=remote)
        self.repo.cloud.pull(cache_info, remote=remote)

    if out.is_dir_checksum:
        checksum = self._get_granular_checksum(path, out)
        cache_path = out.cache.tree.hash_to_path_info(checksum).url
    else:
        cache_path = out.cache_path
    return open(cache_path, mode=mode, encoding=encoding)


# Traceback (AssertionError)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-x-xxxxxxxxxxxx> in <module>
----> 1 with open('test/foo') as file:
2     pass
3

.../python3.6/contextlib.py in __enter__(self)
79     def __enter__(self):
80         try:
---> 81             return next(self.gen)
82         except StopIteration:
83             raise RuntimeError("generator didn't yield") from None

.../python3.6/site-packages/dvc/api.py in _open(path, repo, rev, remote, mode, encoding)
82     with _make_repo(repo, rev=rev) as _repo:
83         with _repo.open_by_relpath(
---> 84             path, remote=remote, mode=mode, encoding=encoding
85         ) as fd:
86             yield fd

.../python3.6/contextlib.py in __enter__(self)
79     def __enter__(self):
80         try:
---> 81             return next(self.gen)
82         except StopIteration:
83             raise RuntimeError("generator didn't yield") from None

.../python3.6/site-packages/dvc/repo/__init__.py in open_by_relpath(self, path, remote, mode, encoding)
616             with self.state:
617                 with tree.open(
--> 618                     path, mode=mode, encoding=encoding, remote=remote,
619                 ) as fobj:
620                     yield fobj

.../python3.6/site-packages/dvc/tree/repo.py in open(self, path, mode, encoding, **kwargs)
157                 raise
158
--> 159         return dvc_tree.open(path, mode=mode, encoding=encoding, **kwargs)
160
161     def exists(

.../python3.6/site-packages/dvc/tree/dvc.py in open(self, path, mode, encoding, remote)
80             if self.stream:
81                 if out.is_dir_checksum:
---> 82                     checksum = self._get_granular_checksum(path, out)
83                 else:
84                     checksum = out.hash_info.value

.../python3.6/site-packages/dvc/tree/dvc.py in _get_granular_checksum(self, path, out, remote)
47
48     def _get_granular_checksum(self, path, out, remote=None):
---> 49         assert isinstance(path, PathInfo)
50         if not self.fetch and not self.stream:
51             raise FileNotFoundError

AssertionError:

# Fixed code
def open(self, path: PathInfo, mode="r", encoding="utf-8", remote=None):  # pylint: disable=arguments-differ
    try:
        outs = self._find_outs(path, strict=False)
    except OutputNotFoundError as exc:
        raise FileNotFoundError from exc

    if len(outs) != 1 or (outs[0].is_dir_checksum and path == outs[0].path_info):
        raise IsADirectoryError

    out = outs[0]
    if out.changed_cache(filter_info=path):
        if not self.fetch and not self.stream:
            raise FileNotFoundError

        remote_obj = self.repo.cloud.get_remote(remote)
        if self.stream:
            if out.is_dir_checksum:
                checksum = self._get_granular_checksum(path, out)
            else:
                checksum = out.hash_info.value
            try:
                remote_info = remote_obj.tree.hash_to_path_info(checksum)
                return remote_obj.tree.open(remote_info, mode=mode, encoding=encoding)
            except RemoteActionNotImplemented:
                pass
        cache_info = out.get_used_cache(filter_info=path, remote=remote)
        self.repo.cloud.pull(cache_info, remote=remote)

    if out.is_dir_checksum:
        checksum = self._get_granular_checksum(path, out)
        cache_path = out.cache.tree.hash_to_path_info(checksum).url
    else:
        cache_path = out.cache_path
    return open(cache_path, mode=mode, encoding=encoding)