Skip to content

Commit 07f1657

Browse files
author
Alan Christie
committed
fix: Support for gitlab doc URLs
1 parent 98689fa commit 07f1657

File tree

3 files changed

+153
-30
lines changed

3 files changed

+153
-30
lines changed

README.rst

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,28 @@ there::
3434
pip install im-data-manager-job-decoder
3535

3636
Once installed you can validate the definition (expected to be a dictionary
37-
formed from the definition YAML file) with:
37+
formed from the definition YAML file) with::
3838

39-
>>> from decoder import decoder
40-
>>> error = decoder.validate_manifest_schema(manifest)
41-
>>> error = decoder.validate_job_schema(job_definition)
39+
>>> from decoder import decoder
40+
>>> error: Optional[str] = decoder.validate_manifest_schema(manifest)
41+
>>> error: Optional[str] = decoder.validate_job_schema(job_definition)
4242

4343
And run the decoder with:
4444

45-
>>> decoded, success = decoder.decode(text, variables, 'command', decoder.TextEncoding.JINJA2_3_0)
45+
>>> decoded, success = decoder.decode(text, variables, 'command', decoder.TextEncoding.JINJA2_3_0)
46+
47+
A method exists to generate a Data Manger Job documentation URL
48+
for the supported repository types. For example, to get the
49+
auto-generated documentation URL for a GitHub repository-based
50+
job definition you can do this::
51+
52+
>>> doc_url: str = decoder.get_job_doc_url("github",
53+
collection
54+
job_id,
55+
job_definition,
56+
manifest_url)
57+
58+
We support ``github`` and ``gitlab`` as repository types.
4659

4760
.. _PyPI: https://pypi.org/project/im-data-manager-job-decoder
4861

decoder/decoder.py

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""
77
import enum
88
import os
9-
from typing import Any, Dict, Optional, Tuple
9+
from typing import Any, Dict, List, Optional, Tuple
1010

1111
import jsonschema
1212
import yaml
@@ -40,6 +40,10 @@
4040
_MANIFEST_SCHEMA: Dict[str, Any] = yaml.load(schema_file, Loader=yaml.FullLoader)
4141
assert _MANIFEST_SCHEMA
4242

43+
REPO_TYPE_GITHUB: str = "github"
44+
REPO_TYPE_GITLAB: str = "gitlab"
45+
_REPO_TYPES: List[str] = [REPO_TYPE_GITHUB, REPO_TYPE_GITLAB]
46+
4347

4448
class TextEncoding(enum.Enum):
4549
"""A general text encoding format, used initially for Job text fields."""
@@ -81,14 +85,73 @@ def validate_job_schema(job_definition: Dict[str, Any]) -> Optional[str]:
8185
return None
8286

8387

88+
def get_supported_repository_types() -> List[str]:
89+
"""Returns a copy of the supported Git repository types."""
90+
return _REPO_TYPES[:]
91+
92+
93+
def _get_github_job_doc_url(
94+
manifest_url: str, collection: str, job_id: str, doc_url: Optional[str]
95+
) -> str:
96+
"""Returns the path to the doc for a GitHub public reference,
97+
based on the manifest URL, collection and Job ID.
98+
"""
99+
manifest_directory_url, _ = os.path.split(manifest_url)
100+
if doc_url and not doc_url.startswith("https://"):
101+
# doc-url defined but does not start 'https://'
102+
# the doc_url is a path within the docs directory
103+
doc_url = f"{manifest_directory_url}/docs/{doc_url}"
104+
elif doc_url is None:
105+
# No doc-url.
106+
# The doc is expected to be in 'docs',
107+
# as '{job}.md' in the {collection} directory.
108+
doc_url = f"{manifest_directory_url}/docs/{collection}/{job_id}.md"
109+
else:
110+
# How did we get here?
111+
assert False
112+
113+
return doc_url
114+
115+
116+
def _get_gitlab_job_doc_url(
117+
manifest_url: str, collection: str, job_id: str, doc_url: Optional[str]
118+
) -> str:
119+
"""Returns the path to the doc for a GitLab reference,
120+
based on the manifest URL, collection and Job ID.
121+
"""
122+
manifest_directory_url, _ = manifest_url.split("%2f")
123+
if doc_url and not doc_url.startswith("https://"):
124+
# doc-url defined but does not start 'https://'
125+
# the doc_url is a path within the docs directory
126+
doc_url = doc_url.replace("/", "%2f")
127+
doc_url = f"{manifest_directory_url}%2fdocs%2f{doc_url}/raw"
128+
elif doc_url is None:
129+
# No doc-url.
130+
# The doc is expected to be in 'docs',
131+
# as '{job}.md' in the {collection} directory.
132+
doc_url = f"{manifest_directory_url}%2fdocs%2f{collection}%2f{job_id}.md/raw"
133+
else:
134+
# How did we get here?
135+
assert False
136+
137+
return doc_url
138+
139+
84140
def get_job_doc_url(
85-
collection: str, job: str, job_definition: Dict[str, Any], manifest_url: str
141+
repo_type: str,
142+
collection: str,
143+
job: str,
144+
job_definition: Dict[str, Any],
145+
manifest_url: str,
86146
) -> str:
87147
"""Returns the Job's documentation URL for a specific Job using the JOb's
88148
'doc-url' and manifest URL. The job manifest is expected to
89149
have been validated, and we expect to have been given one job structure
90150
from the job's definition, not the whole job definition file.
151+
152+
repo_type must be one of the supported types.
91153
"""
154+
assert repo_type in _REPO_TYPES
92155
assert collection
93156
assert job
94157
assert isinstance(job_definition, dict)
@@ -101,12 +164,12 @@ def get_job_doc_url(
101164
# 3. If the doc-url does not begin https:// then is
102165
# assumed to be relative to the manifest directory URL
103166

104-
# A typical manifest URl will look like this...
167+
# A typical GitHub manifest URL will look like this...
105168
#
106169
# https://raw.githubusercontent.com/InformaticsMatters/
107170
# virtual-screening/main/data-manager/manifest-virtual-screening.yaml
108171
#
109-
# The base for an auto-generated doc-url (if we need it)
172+
# And, in this case the base for an auto-generated doc-url (if we need it)
110173
# will be: -
111174
#
112175
# https://raw.githubusercontent.com/InformaticsMatters/
@@ -117,21 +180,14 @@ def get_job_doc_url(
117180
# If doc-url starts 'https://' just return it
118181
if doc_url and doc_url.startswith("https://"):
119182
return doc_url
120-
121-
# If the doc-url is set (it's not https://)
122-
# so we assume is simply relative to the 'docs' directory
123-
# where the manifest is found.
124-
manifest_directory_url, _ = os.path.split(manifest_url)
125-
if doc_url and not doc_url.startswith("https://"):
126-
# doc-url defined but does not start 'https://'
127-
doc_url = f"{manifest_directory_url}/docs/{doc_url}"
128-
elif doc_url is None:
129-
# No doc-url.
130-
# The
131-
doc_url = f"{manifest_directory_url}/docs/{collection}/{job}.md"
132-
else:
133-
# How did we get here?
134-
assert False
183+
if doc_url is not None:
184+
assert not doc_url.startswith("/")
185+
assert not doc_url.endswith("/")
186+
187+
if repo_type == REPO_TYPE_GITHUB:
188+
doc_url = _get_github_job_doc_url(manifest_url, collection, job, doc_url)
189+
elif repo_type == REPO_TYPE_GITLAB:
190+
doc_url = _get_gitlab_job_doc_url(manifest_url, collection, job, doc_url)
135191

136192
assert doc_url
137193
return doc_url

tests/test_get_job_doc_url.py

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from decoder import decoder
99

1010

11-
def test_get_job_doc_url_with_fq_doc_url():
11+
def test_get_github_job_doc_url_with_fq_doc_url():
1212
# Arrange
1313
collection: str = "collection-x"
1414
job: str = "job-x"
@@ -23,14 +23,16 @@ def test_get_job_doc_url_with_fq_doc_url():
2323
expected_doc_url: str = "https://example.com/docs/doc.md"
2424

2525
# Act
26-
doc_url = decoder.get_job_doc_url(collection, job, job_definition, manifest_url)
26+
doc_url = decoder.get_job_doc_url(
27+
decoder.REPO_TYPE_GITHUB, collection, job, job_definition, manifest_url
28+
)
2729

2830
# Assert
2931
assert doc_url
3032
assert doc_url == expected_doc_url
3133

3234

33-
def test_get_job_doc_url_with_partial_doc_url():
35+
def test_get_github_job_doc_url_with_partial_doc_url():
3436
# Arrange
3537
collection: str = "collection-x"
3638
job: str = "job-x"
@@ -47,14 +49,16 @@ def test_get_job_doc_url_with_partial_doc_url():
4749
)
4850

4951
# Act
50-
doc_url = decoder.get_job_doc_url(collection, job, job_definition, manifest_url)
52+
doc_url = decoder.get_job_doc_url(
53+
decoder.REPO_TYPE_GITHUB, collection, job, job_definition, manifest_url
54+
)
5155

5256
# Assert
5357
assert doc_url
5458
assert doc_url == expected_doc_url
5559

5660

57-
def test_get_job_doc_url_with_no_doc_url():
61+
def test_get_github_job_doc_url_with_no_doc_url():
5862
# Arrange
5963
collection: str = "collection-x"
6064
job: str = "job-x"
@@ -71,7 +75,57 @@ def test_get_job_doc_url_with_no_doc_url():
7175
)
7276

7377
# Act
74-
doc_url = decoder.get_job_doc_url(collection, job, job_definition, manifest_url)
78+
doc_url = decoder.get_job_doc_url(
79+
decoder.REPO_TYPE_GITHUB, collection, job, job_definition, manifest_url
80+
)
81+
82+
# Assert
83+
assert doc_url
84+
assert doc_url == expected_doc_url
85+
86+
87+
def test_get_gitlab_job_doc_url_with_partial_doc_url():
88+
# Arrange
89+
collection: str = "collection-x"
90+
job: str = "job-x"
91+
job_definition: Dict = {"doc-url": "special/doc.md"}
92+
manifest_url: str = (
93+
"https://gitlab.com/api/v4/projects/00000000/repository/files/"
94+
"data-manager%2fmanifest.yaml/raw"
95+
)
96+
expected_doc_url: str = (
97+
"https://gitlab.com/api/v4/projects/00000000/repository/files/"
98+
"data-manager%2fdocs%2fspecial%2fdoc.md/raw"
99+
)
100+
101+
# Act
102+
doc_url = decoder.get_job_doc_url(
103+
decoder.REPO_TYPE_GITLAB, collection, job, job_definition, manifest_url
104+
)
105+
106+
# Assert
107+
assert doc_url
108+
assert doc_url == expected_doc_url
109+
110+
111+
def test_get_gitlab_job_doc_url_with_no_doc_url():
112+
# Arrange
113+
collection: str = "collection-x"
114+
job: str = "job-x"
115+
job_definition: Dict = {}
116+
manifest_url: str = (
117+
"https://gitlab.com/api/v4/projects/00000000/repository/files/"
118+
"data-manager%2fmanifest.yaml/raw"
119+
)
120+
expected_doc_url: str = (
121+
"https://gitlab.com/api/v4/projects/00000000/repository/files/"
122+
"data-manager%2fdocs%2fcollection-x%2fjob-x.md/raw"
123+
)
124+
125+
# Act
126+
doc_url = decoder.get_job_doc_url(
127+
decoder.REPO_TYPE_GITLAB, collection, job, job_definition, manifest_url
128+
)
75129

76130
# Assert
77131
assert doc_url

0 commit comments

Comments
 (0)