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

Hack in fragile GitLab support #879

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Extract Gitlab API calls into client class
cbowdon committed Jan 27, 2020
commit 7d3d62a0e5d37020ed09c75d573b62987056792f
71 changes: 71 additions & 0 deletions nbviewer/providers/gitlab/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import json
import os
from tornado.httpclient import AsyncHTTPClient, HTTPError
from tornado.log import app_log
from ...utils import response_text


class GitlabClient(object):
"""Asynchronous client for a private GitLab instance using V4 REST API."""

def __init__(self, host, token=None, client=None):
"""Init a GitlabClient.

host: str
token: optional str
This needs a private access token - if not provided, uses
environment variable GITLAB_TOKEN
client: AsyncHTTPClient
"""
self.client = client or AsyncHTTPClient()
self.host = host
self.token = token or os.environ.get("GITLAB_TOKEN")

@property
def api_url(self):
"""The base URL of the REST API."""
return "https://{host}/api/v4".format(host=self.host)

async def _fetch_json(self, url):
"""Fetch JSON content at URL."""
app_log.info("Fetching " + url)
response = await self.client.fetch(url)
text = response_text(response)
content = json.loads(text)
return content

async def projects(self):
"""List all projects accessible on this GitLab instance."""
projects_url = ("{base}/projects?private_token={token}"
.format(base=self.api_url, token=self.token))
return await self._fetch_json(projects_url)

async def tree(self, project_id, branch):
"""List all files in the given branch and project.

project_id: int
branch: str
"""
tree_url = ("{base}/projects/{project_id}/repository/tree"
"?recursive=true"
"&ref={branch}"
"&per_page=1000"
"&private_token={token}"
.format(base=self.api_url,
project_id=project_id,
branch=branch,
token=self.token))
return await self._fetch_json(tree_url)

def raw_file_url(self, project_id, blob_sha):
"""URL of the raw file matching given blob SHA in project.

project_id: int
blob_sha: str
"""
raw_url = ("{base}/projects/{project_id}"
"/repository/blobs/{blob_sha}/raw?private_token={token}")
return raw_url.format(base=self.api_url,
project_id=project_id,
blob_sha=blob_sha,
token=self.token)
35 changes: 5 additions & 30 deletions nbviewer/providers/gitlab/handlers.py
Original file line number Diff line number Diff line change
@@ -5,25 +5,17 @@
from ..base import RenderingHandler, cached
from ...utils import response_text
from .. import _load_handler_from_location
from .client import GitlabClient


class GitlabHandler(RenderingHandler):

async def get_notebook_data(self, host, group, repo, blob, branch, path):

token = os.environ.get("GITLAB_TOKEN")

base_url = "https://{host}/api/v4".format(host=host)

projects_url = ("{base_url}/projects?private_token={token}"
.format(base_url=base_url, token=token))

app_log.info("Fetching " + projects_url)
client = GitlabClient(host)

try:
projects_response = await self.fetch(projects_url)
projects_text = response_text(projects_response)
projects = json.loads(projects_text)
projects = await client.projects()

path_with_namespace = "{group}/{repo}".format(group=group, repo=repo)

@@ -35,18 +27,7 @@ async def get_notebook_data(self, host, group, repo, blob, branch, path):
else:
raise Exception("Project path not found: " + path_with_namespace)

prj = project["id"]
tree_url = ("{base_url}/projects/{prj}/repository/tree?recursive=true&ref={branch}&per_page=1000&private_token={token}"
.format(base_url=base_url,
prj=prj,
branch=branch,
token=token))

app_log.info("Fetching " + tree_url)

tree_response = await self.fetch(tree_url)
tree_text = response_text(tree_response)
tree = json.loads(tree_text)
tree = await client.tree(project["id"], branch)

blob = None
for item in tree:
@@ -56,13 +37,7 @@ async def get_notebook_data(self, host, group, repo, blob, branch, path):
else:
raise Exception("Blob not found: " + path)

sha = blob["id"]

raw_url = "{base_url}/projects/{prj}/repository/blobs/{sha}/raw?private_token={token}"
return raw_url.format(base_url=base_url,
prj=prj,
sha=sha,
token=token)
return client.raw_file_url(project["id"], blob["id"])

except Exception as e:
app_log.error(e)