PyLinks 0.0.0.dev23__tar.gz → 0.0.0.dev24__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/PKG-INFO +2 -2
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/pyproject.toml +2 -2
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/PyLinks.egg-info/PKG-INFO +2 -2
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/PyLinks.egg-info/SOURCES.txt +1 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/__init__.py +2 -4
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/api/doi.py +6 -6
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/api/github.py +8 -14
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/api/orcid.py +2 -2
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/http.py +9 -9
- pylinks-0.0.0.dev24/src/pylinks/site/__init__.py +1 -0
- pylinks-0.0.0.dev24/src/pylinks/site/binder.py +185 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/site/conda.py +4 -5
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/site/github.py +32 -20
- pylinks-0.0.0.dev24/src/pylinks/site/lib_io.py +67 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/site/pypi.py +4 -5
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/site/readthedocs.py +7 -8
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/url.py +2 -2
- PyLinks-0.0.0.dev23/src/pylinks/site/__init__.py +0 -1
- PyLinks-0.0.0.dev23/src/pylinks/site/binder.py +0 -2
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/setup.cfg +0 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/PyLinks.egg-info/dependency_links.txt +0 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/PyLinks.egg-info/not-zip-safe +0 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/PyLinks.egg-info/requires.txt +0 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/PyLinks.egg-info/top_level.txt +0 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/_settings.py +0 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/api/__init__.py +0 -0
- {PyLinks-0.0.0.dev23 → pylinks-0.0.0.dev24}/src/pylinks/exceptions.py +0 -0
|
@@ -17,10 +17,10 @@ namespaces = true
|
|
|
17
17
|
# ----------------------------------------- Project Metadata -------------------------------------
|
|
18
18
|
#
|
|
19
19
|
[project]
|
|
20
|
-
version = "0.0.0.
|
|
20
|
+
version = "0.0.0.dev24"
|
|
21
21
|
name = "PyLinks"
|
|
22
22
|
dependencies = [
|
|
23
23
|
"requests >= 2.31.0, < 3",
|
|
24
24
|
]
|
|
25
|
-
requires-python = ">=3.
|
|
25
|
+
requires-python = ">=3.10"
|
|
26
26
|
|
|
@@ -11,7 +11,5 @@ but can be used directly from the root. It returns a URL object, also defined in
|
|
|
11
11
|
Other available modules offer shortcuts for creating useful URLs for popular online services.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
from ._settings import settings
|
|
15
|
-
from
|
|
16
|
-
from .http import request, download, graphql_query
|
|
17
|
-
from . import api, site
|
|
14
|
+
from pylinks._settings import settings
|
|
15
|
+
from pylinks import url, http, api, site, exceptions
|
|
@@ -5,7 +5,7 @@ import datetime
|
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
7
|
# Non-standard libraries
|
|
8
|
-
|
|
8
|
+
import pylinks as _pylinks
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class DOI:
|
|
@@ -58,13 +58,13 @@ class DOI:
|
|
|
58
58
|
accept += f"; style={style}"
|
|
59
59
|
if locale:
|
|
60
60
|
accept += f"; locale={locale}"
|
|
61
|
-
return
|
|
61
|
+
return _pylinks.http.request(
|
|
62
62
|
self.url, headers={"accept": accept}, encoding="utf-8", response_type="str"
|
|
63
63
|
)
|
|
64
64
|
|
|
65
65
|
@property
|
|
66
66
|
def bibtex(self) -> str:
|
|
67
|
-
return
|
|
67
|
+
return _pylinks.http.request(
|
|
68
68
|
self.url,
|
|
69
69
|
headers={"accept": "application/x-bibtex"},
|
|
70
70
|
encoding="utf-8",
|
|
@@ -73,7 +73,7 @@ class DOI:
|
|
|
73
73
|
|
|
74
74
|
@property
|
|
75
75
|
def ris(self) -> str:
|
|
76
|
-
return
|
|
76
|
+
return _pylinks.http.request(
|
|
77
77
|
self.url,
|
|
78
78
|
headers={"accept": "application/x-research-info-systems"},
|
|
79
79
|
encoding="utf-8",
|
|
@@ -85,7 +85,7 @@ class DOI:
|
|
|
85
85
|
"""
|
|
86
86
|
Citation data as a dictionary with Citeproc JSON schema.
|
|
87
87
|
"""
|
|
88
|
-
return
|
|
88
|
+
return _pylinks.http.request(
|
|
89
89
|
self.url,
|
|
90
90
|
headers={"accept": "application/citeproc+json"},
|
|
91
91
|
encoding="utf-8",
|
|
@@ -98,7 +98,7 @@ class DOI:
|
|
|
98
98
|
journal = data["container-title"] or None
|
|
99
99
|
journal_abbr = (
|
|
100
100
|
(
|
|
101
|
-
data.get("container-title-short") or
|
|
101
|
+
data.get("container-title-short") or _pylinks.http.request(
|
|
102
102
|
f"https://abbreviso.toolforge.org/abbreviso/a/{journal}",
|
|
103
103
|
response_type="str",
|
|
104
104
|
).title()
|
|
@@ -5,16 +5,15 @@ import re
|
|
|
5
5
|
import mimetypes
|
|
6
6
|
|
|
7
7
|
# Non-standard libraries
|
|
8
|
-
import pylinks
|
|
9
|
-
from pylinks import request, url, graphql_query
|
|
8
|
+
import pylinks as _pylinks
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
class GitHub:
|
|
13
12
|
|
|
14
13
|
def __init__(self, token: Optional[str] = None):
|
|
15
14
|
self._endpoint = {
|
|
16
|
-
"api": url("https://api.github.com"),
|
|
17
|
-
"upload": url("https://uploads.github.com"),
|
|
15
|
+
"api": _pylinks.url.create("https://api.github.com"),
|
|
16
|
+
"upload": _pylinks.url.create("https://uploads.github.com"),
|
|
18
17
|
}
|
|
19
18
|
self._token = token
|
|
20
19
|
self._headers = {"X-GitHub-Api-Version": "2022-11-28"}
|
|
@@ -31,7 +30,7 @@ class GitHub:
|
|
|
31
30
|
extra_headers: dict | None = None,
|
|
32
31
|
) -> dict:
|
|
33
32
|
headers = self._headers | extra_headers if extra_headers else self._headers
|
|
34
|
-
response = graphql_query(
|
|
33
|
+
response = _pylinks.http.graphql_query(
|
|
35
34
|
url=self._endpoint["api"] / "graphql",
|
|
36
35
|
query=f"{{{query}}}",
|
|
37
36
|
headers=headers,
|
|
@@ -50,7 +49,7 @@ class GitHub:
|
|
|
50
49
|
f'mutation($mutationInput:{mutation_input_name}!) '
|
|
51
50
|
f'{{{mutation_name}(input:$mutationInput) {{{mutation_payload}}}}}'
|
|
52
51
|
)
|
|
53
|
-
response = graphql_query(
|
|
52
|
+
response = _pylinks.http.graphql_query(
|
|
54
53
|
url=self._endpoint["api"] / "graphql",
|
|
55
54
|
query=query,
|
|
56
55
|
variables={"mutationInput": mutation_input},
|
|
@@ -69,7 +68,7 @@ class GitHub:
|
|
|
69
68
|
endpoint: Literal['api', 'upload'] = "api"
|
|
70
69
|
):
|
|
71
70
|
headers = self._headers | extra_headers if extra_headers else self._headers
|
|
72
|
-
return request(
|
|
71
|
+
return _pylinks.http.request(
|
|
73
72
|
verb=verb,
|
|
74
73
|
url=self._endpoint[endpoint] / query,
|
|
75
74
|
headers=headers,
|
|
@@ -328,7 +327,7 @@ class Repo:
|
|
|
328
327
|
if entry["type"] == "file":
|
|
329
328
|
filename = Path(entry["path"]).name
|
|
330
329
|
full_download_path = download_path / filename
|
|
331
|
-
|
|
330
|
+
_pylinks.http.download(
|
|
332
331
|
url=entry["download_url"], filepath=full_download_path, create_dirs=create_dirs
|
|
333
332
|
)
|
|
334
333
|
final_download_paths.append(full_download_path)
|
|
@@ -362,7 +361,7 @@ class Repo:
|
|
|
362
361
|
full_download_path = download_path / download_filename
|
|
363
362
|
else:
|
|
364
363
|
full_download_path = download_path / Path(content["path"]).name
|
|
365
|
-
|
|
364
|
+
_pylinks.http.download(
|
|
366
365
|
url=content["download_url"],
|
|
367
366
|
filepath=full_download_path,
|
|
368
367
|
create_dirs=create_dirs,
|
|
@@ -391,11 +390,6 @@ class Repo:
|
|
|
391
390
|
def discussion_categories(self) -> list[dict[str, str]]:
|
|
392
391
|
"""Get discussion categories for a repository.
|
|
393
392
|
|
|
394
|
-
Parameters
|
|
395
|
-
----------
|
|
396
|
-
access_token : str
|
|
397
|
-
GitHub access token.
|
|
398
|
-
|
|
399
393
|
Returns
|
|
400
394
|
-------
|
|
401
395
|
A list of discussion categories as dictionaries with keys "name", "slug", and "id".
|
|
@@ -3,7 +3,7 @@ import re
|
|
|
3
3
|
import warnings
|
|
4
4
|
|
|
5
5
|
# Non-standard libraries
|
|
6
|
-
import pylinks
|
|
6
|
+
import pylinks as _pylinks
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Orcid:
|
|
@@ -20,7 +20,7 @@ class Orcid:
|
|
|
20
20
|
@property
|
|
21
21
|
def records(self) -> dict:
|
|
22
22
|
if not self._data:
|
|
23
|
-
self._data =
|
|
23
|
+
self._data = _pylinks.http.request(
|
|
24
24
|
url=f"https://pub.orcid.org/v3.0/{self.id}",
|
|
25
25
|
headers={"Accept": "application/json"},
|
|
26
26
|
response_type="json",
|
|
@@ -20,7 +20,7 @@ import time
|
|
|
20
20
|
from functools import wraps
|
|
21
21
|
from pathlib import Path
|
|
22
22
|
import requests
|
|
23
|
-
|
|
23
|
+
import pylinks as _pylinks
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class RetryConfig(NamedTuple):
|
|
@@ -73,7 +73,7 @@ class HTTPRequestRetryConfig(NamedTuple):
|
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
def request(
|
|
76
|
-
url: str,
|
|
76
|
+
url: str | _pylinks.url.URL,
|
|
77
77
|
verb: Union[str, Literal["GET", "POST", "PUT", "PATCH", "OPTIONS", "DELETE"]] = "GET",
|
|
78
78
|
params: Optional[Union[dict, List[tuple], bytes]] = None,
|
|
79
79
|
data: Optional[Union[dict, List[tuple], bytes]] = None,
|
|
@@ -189,7 +189,7 @@ def request(
|
|
|
189
189
|
else _retry_on_exception(
|
|
190
190
|
get_response,
|
|
191
191
|
config=retry_config.config_status,
|
|
192
|
-
catch=exceptions.WebAPITemporaryStatusCodeError,
|
|
192
|
+
catch=_pylinks.exceptions.WebAPITemporaryStatusCodeError,
|
|
193
193
|
)
|
|
194
194
|
)
|
|
195
195
|
# Call the (decorated or non-decorated) response function.
|
|
@@ -212,7 +212,7 @@ def request(
|
|
|
212
212
|
if response_verifier is None or response_verifier(response_value):
|
|
213
213
|
return response_value
|
|
214
214
|
# otherwise raise
|
|
215
|
-
raise exceptions.WebAPIValueError(response_value=response_value, response_verifier=response_verifier)
|
|
215
|
+
raise _pylinks.exceptions.WebAPIValueError(response_value=response_value, response_verifier=response_verifier)
|
|
216
216
|
|
|
217
217
|
# Depending on specifications in argument `retry_config`, either decorate `get_response_value`
|
|
218
218
|
# with `retry_on_exception`, or leave it as is.
|
|
@@ -226,7 +226,7 @@ def request(
|
|
|
226
226
|
else _retry_on_exception(
|
|
227
227
|
get_response_value,
|
|
228
228
|
config=retry_config.config_response,
|
|
229
|
-
catch=exceptions.WebAPIValueError,
|
|
229
|
+
catch=_pylinks.exceptions.WebAPIValueError,
|
|
230
230
|
)
|
|
231
231
|
)
|
|
232
232
|
# Call the (decorated or non-decorated) response-value function and return.
|
|
@@ -266,9 +266,9 @@ def graphql_query(
|
|
|
266
266
|
response = request(**args)
|
|
267
267
|
if isinstance(response, dict):
|
|
268
268
|
if "errors" in response:
|
|
269
|
-
raise exceptions.WebAPIError(response)
|
|
269
|
+
raise _pylinks.exceptions.WebAPIError(response)
|
|
270
270
|
elif "data" not in response:
|
|
271
|
-
raise exceptions.WebAPIError(response)
|
|
271
|
+
raise _pylinks.exceptions.WebAPIError(response)
|
|
272
272
|
else:
|
|
273
273
|
response = response["data"]
|
|
274
274
|
return response
|
|
@@ -352,9 +352,9 @@ def _raise_for_status_code(
|
|
|
352
352
|
temporary_error_status_codes is not None
|
|
353
353
|
and response.status_code in temporary_error_status_codes
|
|
354
354
|
):
|
|
355
|
-
raise exceptions.WebAPITemporaryStatusCodeError(response)
|
|
355
|
+
raise _pylinks.exceptions.WebAPITemporaryStatusCodeError(response)
|
|
356
356
|
if error_status_code_range[0] <= response.status_code <= error_status_code_range[1]:
|
|
357
|
-
raise exceptions.WebAPIPersistentStatusCodeError(response)
|
|
357
|
+
raise _pylinks.exceptions.WebAPIPersistentStatusCodeError(response)
|
|
358
358
|
return
|
|
359
359
|
|
|
360
360
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from pylinks.site import binder, conda, github, pypi, readthedocs, lib_io
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""URLs for Binder images.
|
|
2
|
+
|
|
3
|
+
References
|
|
4
|
+
----------
|
|
5
|
+
- [Binder](https://mybinder.org/)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import pylinks as _pylinks
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_BASE_URL = _pylinks.url.create(url="https://mybinder.org/v2")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def github(
|
|
16
|
+
user: str,
|
|
17
|
+
repo: str,
|
|
18
|
+
ref: str = "HEAD",
|
|
19
|
+
notebook_path: str | None = None,
|
|
20
|
+
) -> _pylinks.url.URL:
|
|
21
|
+
"""Create a Binder URL for a GitHub repository.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
user : str
|
|
26
|
+
GitHub username.
|
|
27
|
+
repo : str
|
|
28
|
+
GitHub repository name.
|
|
29
|
+
ref : str, default: "HEAD"
|
|
30
|
+
Branch, tag, or commit hash to use.
|
|
31
|
+
notebook_path : str, optional
|
|
32
|
+
Path to a Jupyter notebook file to open.
|
|
33
|
+
"""
|
|
34
|
+
url = _BASE_URL / "gh" / user / repo / ref
|
|
35
|
+
if notebook_path is not None:
|
|
36
|
+
url.queries["labpath"] = notebook_path
|
|
37
|
+
return url
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def gist(
|
|
41
|
+
user: str,
|
|
42
|
+
gist_id: str,
|
|
43
|
+
ref: str = "HEAD",
|
|
44
|
+
notebook_path: str | None = None,
|
|
45
|
+
) -> _pylinks.url.URL:
|
|
46
|
+
"""Create a Binder URL for a GitHub Gist.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
user : str
|
|
51
|
+
GitHub username.
|
|
52
|
+
gist_id : str
|
|
53
|
+
GitHub Gist ID.
|
|
54
|
+
ref : str, default: "HEAD"
|
|
55
|
+
Commit hash to use.
|
|
56
|
+
notebook_path : str, optional
|
|
57
|
+
Path to a Jupyter notebook file to open.
|
|
58
|
+
"""
|
|
59
|
+
url = _BASE_URL / "gist" / user / gist_id / ref
|
|
60
|
+
if notebook_path is not None:
|
|
61
|
+
url.queries["labpath"] = notebook_path
|
|
62
|
+
return url
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def git(
|
|
66
|
+
url: str,
|
|
67
|
+
ref: str = "HEAD",
|
|
68
|
+
notebook_path: str | None = None,
|
|
69
|
+
) -> _pylinks.url.URL:
|
|
70
|
+
"""Create a Binder URL for a Git repository.
|
|
71
|
+
|
|
72
|
+
Parameters
|
|
73
|
+
----------
|
|
74
|
+
url : str
|
|
75
|
+
URL of the Git repository.
|
|
76
|
+
ref : str, default: "HEAD"
|
|
77
|
+
Branch, tag, or commit hash to use.
|
|
78
|
+
notebook_path : str, optional
|
|
79
|
+
Path to a Jupyter notebook file to open.
|
|
80
|
+
"""
|
|
81
|
+
url = _BASE_URL / "git" / url / ref
|
|
82
|
+
if notebook_path is not None:
|
|
83
|
+
url.queries["labpath"] = notebook_path
|
|
84
|
+
return url
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def gitlab(
|
|
88
|
+
user: str,
|
|
89
|
+
repo: str,
|
|
90
|
+
ref: str = "HEAD",
|
|
91
|
+
notebook_path: str | None = None,
|
|
92
|
+
) -> _pylinks.url.URL:
|
|
93
|
+
"""Create a Binder URL for a GitLab repository.
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
user : str
|
|
98
|
+
GitLab username.
|
|
99
|
+
project : str
|
|
100
|
+
GitLab repository name.
|
|
101
|
+
ref : str, default: "HEAD"
|
|
102
|
+
Branch, tag, or commit hash to use.
|
|
103
|
+
notebook_path : str, optional
|
|
104
|
+
Path to a Jupyter notebook file to open.
|
|
105
|
+
"""
|
|
106
|
+
url = _BASE_URL / "gl" / user / repo / ref
|
|
107
|
+
if notebook_path is not None:
|
|
108
|
+
url.queries["labpath"] = notebook_path
|
|
109
|
+
return url
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def zenodo(
|
|
113
|
+
doi: str,
|
|
114
|
+
notebook_path: str | None = None,
|
|
115
|
+
) -> _pylinks.url.URL:
|
|
116
|
+
"""Create a Binder URL for a Zenodo repository.
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
doi : str
|
|
121
|
+
Zenodo DOI.
|
|
122
|
+
notebook_path : str, optional
|
|
123
|
+
Path to a Jupyter notebook file to open.
|
|
124
|
+
"""
|
|
125
|
+
url = _BASE_URL / "zenodo" / doi
|
|
126
|
+
if notebook_path is not None:
|
|
127
|
+
url.queries["labpath"] = notebook_path
|
|
128
|
+
return url
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def figshare(
|
|
132
|
+
doi: str,
|
|
133
|
+
notebook_path: str | None = None,
|
|
134
|
+
) -> _pylinks.url.URL:
|
|
135
|
+
"""Create a Binder URL for a Figshare repository.
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
doi : str
|
|
140
|
+
Figshare DOI.
|
|
141
|
+
notebook_path : str, optional
|
|
142
|
+
Path to a Jupyter notebook file to open.
|
|
143
|
+
"""
|
|
144
|
+
url = _BASE_URL / "figshare" / doi
|
|
145
|
+
if notebook_path is not None:
|
|
146
|
+
url.queries["labpath"] = notebook_path
|
|
147
|
+
return url
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def hydroshare(
|
|
151
|
+
resource_id: str,
|
|
152
|
+
notebook_path: str | None = None,
|
|
153
|
+
) -> _pylinks.url.URL:
|
|
154
|
+
"""Create a Binder URL for a HydroShare resource.
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
resource_id : str
|
|
159
|
+
HydroShare resource ID.
|
|
160
|
+
notebook_path : str, optional
|
|
161
|
+
Path to a Jupyter notebook file to open.
|
|
162
|
+
"""
|
|
163
|
+
url = _BASE_URL / "hydroshare" / resource_id
|
|
164
|
+
if notebook_path is not None:
|
|
165
|
+
url.queries["labpath"] = notebook_path
|
|
166
|
+
return url
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def dataverse(
|
|
170
|
+
doi: str,
|
|
171
|
+
notebook_path: str | None = None,
|
|
172
|
+
) -> _pylinks.url.URL:
|
|
173
|
+
"""Create a Binder URL for a Dataverse repository.
|
|
174
|
+
|
|
175
|
+
Parameters
|
|
176
|
+
----------
|
|
177
|
+
doi : str
|
|
178
|
+
Dataverse DOI.
|
|
179
|
+
notebook_path : str, optional
|
|
180
|
+
Path to a Jupyter notebook file to open.
|
|
181
|
+
"""
|
|
182
|
+
url = _BASE_URL / "dataverse" / doi
|
|
183
|
+
if notebook_path is not None:
|
|
184
|
+
url.queries["labpath"] = notebook_path
|
|
185
|
+
return url
|
|
@@ -7,11 +7,10 @@ from typing import Optional
|
|
|
7
7
|
|
|
8
8
|
# Non-standard libraries
|
|
9
9
|
import requests
|
|
10
|
-
|
|
11
|
-
from pylinks.url import URL
|
|
10
|
+
import pylinks as _pylinks
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
BASE_URL = url(url="https://anaconda.org")
|
|
13
|
+
BASE_URL = _pylinks.url.create(url="https://anaconda.org")
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class Package:
|
|
@@ -37,7 +36,7 @@ class Package:
|
|
|
37
36
|
)
|
|
38
37
|
self._name = name
|
|
39
38
|
self._channel = channel
|
|
40
|
-
if validate is True or (validate is None and not settings.offline_mode):
|
|
39
|
+
if validate is True or (validate is None and not _pylinks.settings.offline_mode):
|
|
41
40
|
requests.get(str(self.homepage)).raise_for_status()
|
|
42
41
|
|
|
43
42
|
def __repr__(self):
|
|
@@ -57,7 +56,7 @@ class Package:
|
|
|
57
56
|
return self._channel
|
|
58
57
|
|
|
59
58
|
@property
|
|
60
|
-
def homepage(self) -> URL:
|
|
59
|
+
def homepage(self) -> _pylinks.url.URL:
|
|
61
60
|
"""URL of the package homepage."""
|
|
62
61
|
return BASE_URL / self.channel / self.name
|
|
63
62
|
|
|
@@ -7,11 +7,10 @@ from typing import Literal, Optional
|
|
|
7
7
|
|
|
8
8
|
# Non-standard libraries
|
|
9
9
|
import requests
|
|
10
|
-
|
|
11
|
-
from pylinks.url import URL
|
|
10
|
+
import pylinks as _pylinks
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
BASE_URL = url(url="https://github.com")
|
|
13
|
+
BASE_URL = _pylinks.url.create(url="https://github.com")
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class User:
|
|
@@ -33,7 +32,7 @@ class User:
|
|
|
33
32
|
"GitHub usernames can only contain alphanumeric characters and dashes."
|
|
34
33
|
)
|
|
35
34
|
self._name = name
|
|
36
|
-
if validate is True or (validate is None and not settings.offline_mode):
|
|
35
|
+
if validate is True or (validate is None and not _pylinks.settings.offline_mode):
|
|
37
36
|
requests.get(str(self.homepage)).raise_for_status()
|
|
38
37
|
return
|
|
39
38
|
|
|
@@ -49,7 +48,7 @@ class User:
|
|
|
49
48
|
return self._name
|
|
50
49
|
|
|
51
50
|
@property
|
|
52
|
-
def homepage(self) -> URL:
|
|
51
|
+
def homepage(self) -> _pylinks.url.URL:
|
|
53
52
|
"""URL of the GitHub user's homepage."""
|
|
54
53
|
return BASE_URL / self.name
|
|
55
54
|
|
|
@@ -88,7 +87,7 @@ class Repo:
|
|
|
88
87
|
raise ValueError(
|
|
89
88
|
'GitHub repository names can only contain "_", "-", ".", and alphanumeric characters.'
|
|
90
89
|
)
|
|
91
|
-
if validate is True or (validate is None and not settings.offline_mode):
|
|
90
|
+
if validate is True or (validate is None and not _pylinks.settings.offline_mode):
|
|
92
91
|
requests.get(str(self.homepage)).raise_for_status()
|
|
93
92
|
return
|
|
94
93
|
|
|
@@ -109,11 +108,11 @@ class Repo:
|
|
|
109
108
|
return self._name
|
|
110
109
|
|
|
111
110
|
@property
|
|
112
|
-
def homepage(self) -> URL:
|
|
111
|
+
def homepage(self) -> _pylinks.url.URL:
|
|
113
112
|
"""URL of the repository's homepage."""
|
|
114
113
|
return self.user.homepage / self.name
|
|
115
114
|
|
|
116
|
-
def workflow(self, filename: str) -> URL:
|
|
115
|
+
def workflow(self, filename: str) -> _pylinks.url.URL:
|
|
117
116
|
"""
|
|
118
117
|
URL of a GitHub Actions workflow in the repository.
|
|
119
118
|
|
|
@@ -124,7 +123,7 @@ class Repo:
|
|
|
124
123
|
"""
|
|
125
124
|
return self.homepage / "actions/workflows" / filename
|
|
126
125
|
|
|
127
|
-
def workflow_run(self, run_id: str) -> URL:
|
|
126
|
+
def workflow_run(self, run_id: str) -> _pylinks.url.URL:
|
|
128
127
|
"""
|
|
129
128
|
URL of the summary page of a specific GitHub Actions workflow run in the repository.
|
|
130
129
|
|
|
@@ -137,7 +136,7 @@ class Repo:
|
|
|
137
136
|
|
|
138
137
|
def pr_issues(
|
|
139
138
|
self, pr: bool = True, closed: Optional[bool] = None, label: Optional[str] = None
|
|
140
|
-
) -> URL:
|
|
139
|
+
) -> _pylinks.url.URL:
|
|
141
140
|
"""
|
|
142
141
|
URL of pull requests or issues in the repository.
|
|
143
142
|
|
|
@@ -162,11 +161,11 @@ class Repo:
|
|
|
162
161
|
url.queries["q"] += f"+label:{label}"
|
|
163
162
|
return url
|
|
164
163
|
|
|
165
|
-
def commit(self, commit_hash: str) -> URL:
|
|
164
|
+
def commit(self, commit_hash: str) -> _pylinks.url.URL:
|
|
166
165
|
"""URL of a specific commit in the repository."""
|
|
167
166
|
return self.homepage / "commit" / commit_hash
|
|
168
167
|
|
|
169
|
-
def releases(self, tag: Optional[str | Literal["latest"]] = None) -> URL:
|
|
168
|
+
def releases(self, tag: Optional[str | Literal["latest"]] = None) -> _pylinks.url.URL:
|
|
170
169
|
"""
|
|
171
170
|
URL of the releases overview page, or a specific release.
|
|
172
171
|
|
|
@@ -186,11 +185,24 @@ class Repo:
|
|
|
186
185
|
return base_url / "tag" / tag
|
|
187
186
|
|
|
188
187
|
@property
|
|
189
|
-
def commits(self) -> URL:
|
|
188
|
+
def commits(self) -> _pylinks.url.URL:
|
|
190
189
|
"""URL of commits page."""
|
|
191
190
|
return self.homepage / "commits"
|
|
192
191
|
|
|
193
|
-
def
|
|
192
|
+
def compare(self, base: str, head: str) -> _pylinks.url.URL:
|
|
193
|
+
"""
|
|
194
|
+
URL of a comparison between two references, i.e., branches, tags, or hashes.
|
|
195
|
+
|
|
196
|
+
Parameters
|
|
197
|
+
----------
|
|
198
|
+
base : str
|
|
199
|
+
The base reference.
|
|
200
|
+
head : str
|
|
201
|
+
The head reference.
|
|
202
|
+
"""
|
|
203
|
+
return self.homepage / "compare" / f"{base}...{head}"
|
|
204
|
+
|
|
205
|
+
def discussions(self, category: Optional[str] = None) -> _pylinks.url.URL:
|
|
194
206
|
"""
|
|
195
207
|
URL of discussions page, or a specific discussion category page.
|
|
196
208
|
|
|
@@ -248,7 +260,7 @@ class Branch:
|
|
|
248
260
|
raise ValueError(
|
|
249
261
|
'GitHub branch names can only contain "_", "-", ".", "/", and alphanumeric characters.'
|
|
250
262
|
)
|
|
251
|
-
if validate is True or (validate is None and not settings.offline_mode):
|
|
263
|
+
if validate is True or (validate is None and not _pylinks.settings.offline_mode):
|
|
252
264
|
requests.get(str(self.homepage)).raise_for_status()
|
|
253
265
|
return
|
|
254
266
|
|
|
@@ -258,7 +270,7 @@ class Branch:
|
|
|
258
270
|
return self._repo
|
|
259
271
|
|
|
260
272
|
@property
|
|
261
|
-
def homepage(self) -> URL:
|
|
273
|
+
def homepage(self) -> _pylinks.url.URL:
|
|
262
274
|
"""URL of the branch's homepage."""
|
|
263
275
|
return self.repo.homepage / "tree" / self.name
|
|
264
276
|
|
|
@@ -267,7 +279,7 @@ class Branch:
|
|
|
267
279
|
"""Name of the branch."""
|
|
268
280
|
return self._name
|
|
269
281
|
|
|
270
|
-
def workflow(self, filename: str) -> URL:
|
|
282
|
+
def workflow(self, filename: str) -> _pylinks.url.URL:
|
|
271
283
|
"""
|
|
272
284
|
URL of a GitHub Actions workflow for this specific branch.
|
|
273
285
|
|
|
@@ -280,11 +292,11 @@ class Branch:
|
|
|
280
292
|
url.queries = {"query": f"branch:{self.name}"}
|
|
281
293
|
return url
|
|
282
294
|
|
|
283
|
-
def file(self, filename: str, raw: bool = False) -> URL:
|
|
295
|
+
def file(self, filename: str, raw: bool = False) -> _pylinks.url.URL:
|
|
284
296
|
"""URL of a specific file in the branch."""
|
|
285
297
|
if raw:
|
|
286
298
|
return (
|
|
287
|
-
url("https://raw.githubusercontent.com")
|
|
299
|
+
_pylinks.url.create("https://raw.githubusercontent.com")
|
|
288
300
|
/ self.repo.user.name
|
|
289
301
|
/ self.repo.name
|
|
290
302
|
/ self.name
|
|
@@ -293,7 +305,7 @@ class Branch:
|
|
|
293
305
|
return self.homepage / filename
|
|
294
306
|
|
|
295
307
|
@property
|
|
296
|
-
def commits(self) -> URL:
|
|
308
|
+
def commits(self) -> _pylinks.url.URL:
|
|
297
309
|
"""URL of commits page for this branch."""
|
|
298
310
|
return self.repo.homepage / "commits" / self.name
|
|
299
311
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""URLs for the Libraries.io website."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# Non-standard libraries
|
|
5
|
+
import requests
|
|
6
|
+
import pylinks as _pylinks
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
BASE_URL = _pylinks.url.create(url="https://libraries.io")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Package:
|
|
13
|
+
"""A Libraries.IO package site."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, platform: str, package: str, validate: bool | None = None):
|
|
16
|
+
"""
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
platform : str
|
|
20
|
+
Name of the platform where the package is distributed, e.g. 'pypi', 'npm', etc.
|
|
21
|
+
package : str
|
|
22
|
+
Name of the package.
|
|
23
|
+
validate : bool, default: None
|
|
24
|
+
Whether to validate the URL online (requires an active internet connection).
|
|
25
|
+
If set to None (default), the global default value defined in `pylinks.OFFLINE_MODE` is used.
|
|
26
|
+
"""
|
|
27
|
+
if not isinstance(platform, str):
|
|
28
|
+
raise TypeError(f"`platform` must be a string, not {type(platform)}.")
|
|
29
|
+
if not isinstance(package, str):
|
|
30
|
+
raise TypeError(f"`package` must be a string, not {type(package)}.")
|
|
31
|
+
self._platform = platform
|
|
32
|
+
self._package = package
|
|
33
|
+
if validate is True or (validate is None and not _pylinks.settings.offline_mode):
|
|
34
|
+
requests.get(str(self.homepage)).raise_for_status()
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def platform(self) -> str:
|
|
39
|
+
"""Name of the platform."""
|
|
40
|
+
return self._platform
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def package(self) -> str:
|
|
44
|
+
"""Name of the package."""
|
|
45
|
+
return self._package
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def homepage(self) -> _pylinks.url.URL:
|
|
49
|
+
"""URL of the package's homepage."""
|
|
50
|
+
return BASE_URL / self._platform / self._package
|
|
51
|
+
|
|
52
|
+
def dependencies(self, version: str) -> _pylinks.url.URL:
|
|
53
|
+
"""URL of the webpage showing the dependencies of the package."""
|
|
54
|
+
return self.homepage / version / "tree"
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def source_rank(self) -> _pylinks.url.URL:
|
|
58
|
+
"""URL of the webpage showing the source rank of the package."""
|
|
59
|
+
return self.homepage / "sourcerank"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def package(
|
|
63
|
+
platform: str,
|
|
64
|
+
package: str,
|
|
65
|
+
validate: bool | None = None,
|
|
66
|
+
):
|
|
67
|
+
return Package(platform=platform, package=package, validate=validate)
|
|
@@ -7,11 +7,10 @@ from typing import Optional
|
|
|
7
7
|
|
|
8
8
|
# Non-standard libraries
|
|
9
9
|
import requests
|
|
10
|
-
|
|
11
|
-
from pylinks.url import URL
|
|
10
|
+
import pylinks as _pylinks
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
BASE_URL = url("https://pypi.org")
|
|
13
|
+
BASE_URL = _pylinks.url.create("https://pypi.org")
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class Package:
|
|
@@ -34,7 +33,7 @@ class Package:
|
|
|
34
33
|
"Distribution name is invalid; see https://peps.python.org/pep-0508/#names."
|
|
35
34
|
)
|
|
36
35
|
self._name = name
|
|
37
|
-
if validate is True or (validate is None and not settings.offline_mode):
|
|
36
|
+
if validate is True or (validate is None and not _pylinks.settings.offline_mode):
|
|
38
37
|
requests.get(str(self.homepage)).raise_for_status()
|
|
39
38
|
|
|
40
39
|
@property
|
|
@@ -43,7 +42,7 @@ class Package:
|
|
|
43
42
|
return self._name
|
|
44
43
|
|
|
45
44
|
@property
|
|
46
|
-
def homepage(self) -> URL:
|
|
45
|
+
def homepage(self) -> _pylinks.url.URL:
|
|
47
46
|
"""URL of the package homepage."""
|
|
48
47
|
return BASE_URL / "project" / self.name
|
|
49
48
|
|
|
@@ -6,11 +6,10 @@ from typing import Optional
|
|
|
6
6
|
|
|
7
7
|
# Non-standard libraries
|
|
8
8
|
import requests
|
|
9
|
-
|
|
10
|
-
from pylinks.url import URL
|
|
9
|
+
import pylinks as _pylinks
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
BASE_URL = url(url="https://readthedocs.org")
|
|
12
|
+
BASE_URL = _pylinks.url.create(url="https://readthedocs.org")
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class Project:
|
|
@@ -29,7 +28,7 @@ class Project:
|
|
|
29
28
|
if not isinstance(name, str):
|
|
30
29
|
raise TypeError(f"`name` must be a string, not {type(name)}.")
|
|
31
30
|
self._name = name
|
|
32
|
-
if validate is True or (validate is None and not settings.offline_mode):
|
|
31
|
+
if validate is True or (validate is None and not _pylinks.settings.offline_mode):
|
|
33
32
|
requests.get(str(self.project_home)).raise_for_status()
|
|
34
33
|
return
|
|
35
34
|
|
|
@@ -39,19 +38,19 @@ class Project:
|
|
|
39
38
|
return self._name
|
|
40
39
|
|
|
41
40
|
@property
|
|
42
|
-
def project_home(self) -> URL:
|
|
41
|
+
def project_home(self) -> _pylinks.url.URL:
|
|
43
42
|
"""URL of the project's homepage. This is not the homepage of the website."""
|
|
44
43
|
return BASE_URL / "projects" / self.name
|
|
45
44
|
|
|
46
45
|
@property
|
|
47
|
-
def build_status(self) -> URL:
|
|
46
|
+
def build_status(self) -> _pylinks.url.URL:
|
|
48
47
|
"""URL of the webpage showing an overview of the website's build status."""
|
|
49
48
|
return self.project_home / "builds"
|
|
50
49
|
|
|
51
50
|
@property
|
|
52
|
-
def homepage(self) -> URL:
|
|
51
|
+
def homepage(self) -> _pylinks.url.URL:
|
|
53
52
|
"""URL of the website's homepage."""
|
|
54
|
-
return url(f"https://{self.name}.readthedocs.io")
|
|
53
|
+
return _pylinks.url.create(f"https://{self.name}.readthedocs.io")
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
def project(
|
|
@@ -14,7 +14,7 @@ class URL:
|
|
|
14
14
|
def __init__(
|
|
15
15
|
self,
|
|
16
16
|
base: str,
|
|
17
|
-
queries: Optional[dict[str, str | bytes | None]] = None,
|
|
17
|
+
queries: Optional[dict[str, str | bytes | bool | None]] = None,
|
|
18
18
|
fragment: Optional[str] = None,
|
|
19
19
|
quote_safe: Optional[str] = "",
|
|
20
20
|
query_delimiter: str = "&",
|
|
@@ -142,7 +142,7 @@ class URL:
|
|
|
142
142
|
webbrowser.open(url=str(self), new=new, autoraise=autoraise)
|
|
143
143
|
|
|
144
144
|
|
|
145
|
-
def
|
|
145
|
+
def create(
|
|
146
146
|
url: str,
|
|
147
147
|
queries: Optional[dict[str, str | bytes | None]] = None,
|
|
148
148
|
fragment: Optional[str] = None,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from . import binder, conda, github, pypi, readthedocs
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|