Esempio n. 1
0
    async def _resolve_path_to_ids(self, path, start_at=None):
        ret = start_at or [{
            'title': '',
            'mimeType': 'folder',
            'id': self.folder['id'],
        }]
        item_id = ret[0]['id']
        # parts is list of [path_part_name, is_folder]
        parts = [[parse.unquote(x), True] for x in path.strip('/').split('/')]

        if not path.endswith('/'):
            parts[-1][1] = False
        while parts:
            current_part = parts.pop(0)
            query = "title = '{}' " \
                    "and trashed = false " \
                    "and mimeType != 'application/vnd.google-apps.form' " \
                    "and mimeType != 'application/vnd.google-apps.map' " \
                    "and mimeType {} '{}'".format(
                        clean_query(current_part[0]),
                        '=' if current_part[1] else '!=',
                        self.FOLDER_MIME_TYPE
                    )
            async with self.request(
                'GET',
                self.build_url('files', item_id, 'children', q=query, fields='items(id)'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                data = await resp.json()

            try:
                item_id = data['items'][0]['id']
            except (KeyError, IndexError):
                if parts:
                    raise exceptions.MetadataError('{} not found'.format(str(path)), code=http.client.NOT_FOUND)
                name, ext = os.path.splitext(current_part[0])
                if ext not in ('.gdoc', '.gdraw', '.gslides', '.gsheet'):
                    return ret + [{
                        'id': None,
                        'title': current_part[0],
                        'mimeType': 'folder' if path.endswith('/') else '',
                    }]
                parts.append([name, current_part[1]])

            async with self.request(
                'GET',
                self.build_url('files', item_id, fields='id,title,mimeType'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                ret.append(await resp.json())

        return ret
Esempio n. 2
0
    async def _resolve_path_to_ids(self, path, start_at=None):
        ret = start_at or [{
            'title': '',
            'mimeType': 'folder',
            'id': self.folder['id'],
        }]
        item_id = ret[0]['id']
        # parts is list of [path_part_name, is_folder]
        parts = [[parse.unquote(x), True] for x in path.strip('/').split('/')]

        if not path.endswith('/'):
            parts[-1][1] = False
        while parts:
            current_part = parts.pop(0)
            query = "title = '{}' " \
                    "and trashed = false " \
                    "and mimeType != 'application/vnd.google-apps.form' " \
                    "and mimeType {} '{}'".format(
                        clean_query(current_part[0]),
                        '=' if current_part[1] else '!=',
                        self.FOLDER_MIME_TYPE
                    )
            async with self.request(
                'GET',
                self.build_url('files', item_id, 'children', q=query, fields='items(id)'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                data = await resp.json()

            try:
                item_id = data['items'][0]['id']
            except (KeyError, IndexError):
                if parts:
                    raise exceptions.MetadataError('{} not found'.format(str(path)), code=http.client.NOT_FOUND)
                name, ext = os.path.splitext(current_part[0])
                if ext not in ('.gdoc', '.gdraw', '.gslides', '.gsheet'):
                    return ret + [{
                        'id': None,
                        'title': current_part[0],
                        'mimeType': 'folder' if path.endswith('/') else '',
                    }]
                parts.append([name, current_part[1]])

            async with self.request(
                'GET',
                self.build_url('files', item_id, fields='id,title,mimeType'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                ret.append(await resp.json())

        return ret
Esempio n. 3
0
    def validate_v1_path(self, path, **kwargs):
        if not getattr(self, '_repo', None):
            self._repo = yield from self._fetch_repo()
            self.default_branch = self._repo['default_branch']

        branch_ref = kwargs.get('ref') or kwargs.get(
            'branch') or self.default_branch

        implicit_folder = path.endswith('/')

        url = furl.furl(self.build_repo_url('contents', path))
        url.args.update({'ref': branch_ref})
        resp = yield from self.make_request('GET',
                                            url.url,
                                            expects=(200, ),
                                            throws=exceptions.MetadataError)

        content = yield from resp.json()
        explicit_folder = isinstance(content, list)

        if implicit_folder != explicit_folder:
            raise exceptions.NotFoundError(path)

        path = GitHubPath(path)
        for part in path.parts:
            part._id = (branch_ref, None)

        # TODO Validate that filesha is a valid sha
        path.parts[-1]._id = (branch_ref, kwargs.get('fileSha'))

        return path
Esempio n. 4
0
    def validate_v1_path(self, path, **kwargs):
        if not getattr(self, '_repo', None):
            self._repo = yield from self._fetch_repo()
            self.default_branch = self._repo['default_branch']

        branch_ref = kwargs.get('ref') or kwargs.get('branch') or self.default_branch

        implicit_folder = path.endswith('/')

        url = furl.furl(self.build_repo_url('contents', path))
        url.args.update({'ref': branch_ref})
        resp = yield from self.make_request(
            'GET',
            url.url,
            expects=(200, 403),
            throws=exceptions.MetadataError
        )

        content = yield from resp.json()

        explicit_folder = isinstance(content, list)

        if implicit_folder != explicit_folder:
            raise exceptions.NotFoundError(path)

        path = GitHubPath(path)
        for part in path.parts:
            part._id = (branch_ref, None)

        # TODO Validate that filesha is a valid sha
        path.parts[-1]._id = (branch_ref, kwargs.get('fileSha'))

        return path
Esempio n. 5
0
    async def validate_v1_path(self, path, **kwargs):
        if path == '/':
            return GoogleDrivePath('/', _ids=[self.folder['id']], folder=True)

        implicit_folder = path.endswith('/')
        parts = await self._resolve_path_to_ids(path)
        explicit_folder = parts[-1]['mimeType'] == self.FOLDER_MIME_TYPE
        if parts[-1]['id'] is None or implicit_folder != explicit_folder:
            raise exceptions.NotFoundError(str(path))

        names, ids = zip(*[(parse.quote(x['title'], safe=''), x['id']) for x in parts])
        return GoogleDrivePath('/'.join(names), _ids=ids, folder='folder' in parts[-1]['mimeType'])
Esempio n. 6
0
    async def validate_v1_path(self, path, **kwargs):
        if path == '/':
            return GoogleDrivePath('/', _ids=[self.folder['id']], folder=True)

        implicit_folder = path.endswith('/')
        parts = await self._resolve_path_to_ids(path)
        explicit_folder = parts[-1]['mimeType'] == self.FOLDER_MIME_TYPE
        if parts[-1]['id'] is None or implicit_folder != explicit_folder:
            raise exceptions.NotFoundError(str(path))

        names, ids = zip(*[(parse.quote(x['title'], safe=''), x['id']) for x in parts])
        return GoogleDrivePath('/'.join(names), _ids=ids, folder='folder' in parts[-1]['mimeType'])
Esempio n. 7
0
    def _resolve_path_to_ids(self, path, start_at=None):
        ret = start_at or [{
            'title': '',
            'mimeType': 'folder',
            'id': self.folder['id'],
        }]
        item_id = ret[0]['id']
        parts = [parse.unquote(x) for x in path.strip('/').split('/')]

        while parts:
            current_part = parts.pop(0)

            resp = yield from self.make_request(
                'GET',
                self.build_url('files',
                               item_id,
                               'children',
                               q="title = '{}'".format(
                                   clean_query(current_part)),
                               fields='items(id)'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            )

            try:
                item_id = (yield from resp.json())['items'][0]['id']
            except (KeyError, IndexError):
                if parts:
                    raise exceptions.MetadataError('{} not found'.format(
                        str(path)),
                                                   code=http.client.NOT_FOUND)
                name, ext = os.path.splitext(current_part)
                if ext not in ('.gdoc', '.gdraw', '.gslides', '.gsheet'):
                    return ret + [
                        {
                            'id': None,
                            'title': current_part,
                            'mimeType': 'folder' if path.endswith('/') else '',
                        }
                    ]
                parts.append(name)

            resp = yield from self.make_request(
                'GET',
                self.build_url('files', item_id, fields='id,title,mimeType'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            )

            ret.append((yield from resp.json()))

        return ret
    async def _search_tree_for_path(self, path, tree_sha, recursive=True):
        """Search through the given tree for an entity matching the name and type of `path`.
        """
        tree = await self._fetch_tree(tree_sha, recursive=True)

        if tree['truncated']:
            raise GitHubUnsupportedRepoError

        implicit_type = 'tree' if path.endswith('/') else 'blob'

        for entity in tree['tree']:
            if entity['path'] == path.strip('/') and entity['type'] == implicit_type:
                return entity

        raise exceptions.NotFoundError(str(path))
Esempio n. 9
0
    async def _search_tree_for_path(self, path, tree_sha, recursive=True):
        """Search through the given tree for an entity matching the name and type of `path`.
        """
        tree = await self._fetch_tree(tree_sha, recursive=True)

        if tree['truncated']:
            raise GitHubUnsupportedRepoError

        implicit_type = 'tree' if path.endswith('/') else 'blob'

        for entity in tree['tree']:
            if entity['path'] == path.strip(
                    '/') and entity['type'] == implicit_type:
                return entity

        raise exceptions.NotFoundError(str(path))
Esempio n. 10
0
    def _resolve_path_to_ids(self, path, start_at=None):
        ret = start_at or [{
            'title': '',
            'mimeType': 'folder',
            'id': self.folder['id'],
        }]
        item_id = ret[0]['id']
        parts = [parse.unquote(x) for x in path.strip('/').split('/')]

        while parts:
            current_part = parts.pop(0)

            resp = yield from self.make_request(
                'GET',
                self.build_url('files', item_id, 'children', q='title = "{}"'.format(current_part.replace('"', '\\"')), fields='items(id)'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            )

            try:
                item_id = (yield from resp.json())['items'][0]['id']
            except (KeyError, IndexError):
                if parts:
                    raise exceptions.MetadataError('{} not found'.format(str(path)), code=http.client.NOT_FOUND)
                name, ext = os.path.splitext(current_part)
                if ext not in ('.gdoc', '.gsheet'):
                    return ret + [{
                        'id': None,
                        'title': current_part,
                        'mimeType': 'folder' if path.endswith('/') else '',
                    }]
                parts.append(name)

            resp = yield from self.make_request(
                'GET',
                self.build_url('files', item_id, fields='id,title,mimeType'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            )

            ret.append((yield from resp.json()))

        return ret
Esempio n. 11
0
    def _resolve_path_to_ids(self, path, start_at=None):
        ret = start_at or [{"title": "", "mimeType": "folder", "id": self.folder["id"]}]
        item_id = ret[0]["id"]
        parts = [parse.unquote(x) for x in path.strip("/").split("/")]

        while parts:
            current_part = parts.pop(0)

            resp = yield from self.make_request(
                "GET",
                self.build_url(
                    "files", item_id, "children", q="title = '{}'".format(clean_query(current_part)), fields="items(id)"
                ),
                expects=(200,),
                throws=exceptions.MetadataError,
            )

            try:
                item_id = (yield from resp.json())["items"][0]["id"]
            except (KeyError, IndexError):
                if parts:
                    raise exceptions.MetadataError("{} not found".format(str(path)), code=http.client.NOT_FOUND)
                name, ext = os.path.splitext(current_part)
                if ext not in (".gdoc", ".gdraw", ".gslides", ".gsheet"):
                    return ret + [
                        {"id": None, "title": current_part, "mimeType": "folder" if path.endswith("/") else ""}
                    ]
                parts.append(name)

            resp = yield from self.make_request(
                "GET",
                self.build_url("files", item_id, fields="id,title,mimeType"),
                expects=(200,),
                throws=exceptions.MetadataError,
            )

            ret.append((yield from resp.json()))

        return ret
Esempio n. 12
0
    async def _resolve_path_to_ids(self, path, start_at=None):
        """Takes a path and traverses the file tree (ha!) beginning at ``start_at``, looking for
        something that matches ``path``.  Returns a list of dicts for each part of the path, with
        ``title``, ``mimeType``, and ``id`` keys.
        """
        ret = start_at or [{
            'title': '',
            'mimeType': 'folder',
            'id': self.folder['id'],
        }]
        item_id = ret[0]['id']
        # parts is list of [path_part_name, is_folder]
        parts = [[parse.unquote(x), True] for x in path.strip('/').split('/')]

        if not path.endswith('/'):
            parts[-1][1] = False
        while parts:
            current_part = parts.pop(0)
            query = "title = '{}' " \
                    "and trashed = false " \
                    "and mimeType != 'application/vnd.google-apps.form' " \
                    "and mimeType != 'application/vnd.google-apps.map' " \
                    "and mimeType {} '{}'".format(
                        clean_query(current_part[0]),
                        '=' if current_part[1] else '!=',
                        self.FOLDER_MIME_TYPE
                    )
            async with self.request(
                    'GET',
                    self.build_url('files',
                                   item_id,
                                   'children',
                                   q=query,
                                   fields='items(id)'),
                    expects=(200, ),
                    throws=exceptions.MetadataError,
            ) as resp:
                data = await resp.json()

            try:
                item_id = data['items'][0]['id']
            except (KeyError, IndexError):
                if parts:
                    # if we can't find an intermediate path part, that's an error
                    raise exceptions.MetadataError('{} not found'.format(
                        str(path)),
                                                   code=http.client.NOT_FOUND)

                # Couldn't find id for last part of path. If path includes Google Doc extension,
                # search again without extension (gdrive won't find it if included). Otherwise,
                # assume file or folder doesn't yet exist (i.e. id = None)
                name, ext = os.path.splitext(current_part[0])
                if ext not in ('.gdoc', '.gdraw', '.gslides', '.gsheet'):
                    return ret + [
                        {
                            'id': None,
                            'title': current_part[0],
                            'mimeType': 'folder' if path.endswith('/') else '',
                        }
                    ]
                # strip google docs extension and try again
                parts.append([name, current_part[1]])
                continue

            async with self.request(
                    'GET',
                    self.build_url('files',
                                   item_id,
                                   fields='id,title,mimeType'),
                    expects=(200, ),
                    throws=exceptions.MetadataError,
            ) as resp:
                ret.append(await resp.json())

        return ret
Esempio n. 13
0
    async def _resolve_path_to_ids(self, path, start_at=None):
        """Takes a path and traverses the file tree (ha!) beginning at ``start_at``, looking for
        something that matches ``path``.  Returns a list of dicts for each part of the path, with
        ``title``, ``mimeType``, and ``id`` keys.
        """
        ret = start_at or [{
            'title': '',
            'mimeType': 'folder',
            'id': self.folder['id'],
        }]
        item_id = ret[0]['id']
        # parts is list of [path_part_name, is_folder]
        parts = [[parse.unquote(x), True] for x in path.strip('/').split('/')]

        if not path.endswith('/'):
            parts[-1][1] = False
        while parts:
            current_part = parts.pop(0)
            part_name, part_is_folder = current_part[0], current_part[1]
            name, ext = os.path.splitext(part_name)
            if not part_is_folder and ext in ('.gdoc', '.gdraw', '.gslides', '.gsheet'):
                gd_ext = drive_utils.get_mimetype_from_ext(ext)
                query = "title = '{}' " \
                        "and trashed = false " \
                        "and mimeType = '{}'".format(clean_query(name), gd_ext)
            else:
                query = "title = '{}' " \
                        "and trashed = false " \
                        "and mimeType != 'application/vnd.google-apps.form' " \
                        "and mimeType != 'application/vnd.google-apps.map' " \
                        "and mimeType {} '{}'".format(
                            clean_query(part_name),
                            '=' if part_is_folder else '!=',
                            self.FOLDER_MIME_TYPE
                        )
            async with self.request(
                'GET',
                self.build_url('files', item_id, 'children', q=query, fields='items(id)'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                data = await resp.json()

            try:
                item_id = data['items'][0]['id']
            except (KeyError, IndexError):
                if parts:
                    # if we can't find an intermediate path part, that's an error
                    raise exceptions.MetadataError('{} not found'.format(str(path)), code=http.client.NOT_FOUND)
                return ret + [{
                    'id': None,
                    'title': part_name,
                    'mimeType': 'folder' if part_is_folder else '',
                }]

            async with self.request(
                'GET',
                self.build_url('files', item_id, fields='id,title,mimeType'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                ret.append(await resp.json())

        return ret
Esempio n. 14
0
    async def _resolve_path_to_ids(self, path, start_at=None):
        """Takes a path and traverses the file tree (ha!) beginning at ``start_at``, looking for
        something that matches ``path``.  Returns a list of dicts for each part of the path, with
        ``title``, ``mimeType``, and ``id`` keys.
        """
        ret = start_at or [{
            'title': '',
            'mimeType': 'folder',
            'id': self.folder['id'],
        }]
        item_id = ret[0]['id']
        # parts is list of [path_part_name, is_folder]
        parts = [[parse.unquote(x), True] for x in path.strip('/').split('/')]

        if not path.endswith('/'):
            parts[-1][1] = False
        while parts:
            current_part = parts.pop(0)
            query = "title = '{}' " \
                    "and trashed = false " \
                    "and mimeType != 'application/vnd.google-apps.form' " \
                    "and mimeType != 'application/vnd.google-apps.map' " \
                    "and mimeType {} '{}'".format(
                        clean_query(current_part[0]),
                        '=' if current_part[1] else '!=',
                        self.FOLDER_MIME_TYPE
                    )
            async with self.request(
                'GET',
                self.build_url('files', item_id, 'children', q=query, fields='items(id)'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                data = await resp.json()

            try:
                item_id = data['items'][0]['id']
            except (KeyError, IndexError):
                if parts:
                    # if we can't find an intermediate path part, that's an error
                    raise exceptions.MetadataError('{} not found'.format(str(path)), code=http.client.NOT_FOUND)

                # Couldn't find id for last part of path. If path includes Google Doc extension,
                # search again without extension (gdrive won't find it if included). Otherwise,
                # assume file or folder doesn't yet exist (i.e. id = None)
                name, ext = os.path.splitext(current_part[0])
                if ext not in ('.gdoc', '.gdraw', '.gslides', '.gsheet'):
                    return ret + [{
                        'id': None,
                        'title': current_part[0],
                        'mimeType': 'folder' if path.endswith('/') else '',
                    }]
                # strip google docs extension and try again
                parts.append([name, current_part[1]])
                continue

            async with self.request(
                'GET',
                self.build_url('files', item_id, fields='id,title,mimeType'),
                expects=(200, ),
                throws=exceptions.MetadataError,
            ) as resp:
                ret.append(await resp.json())

        return ret