mkdocstrings-github 0.2.4__py3-none-any.whl → 0.2.6__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocstrings-github
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: A GitHub Action handler for mkdocstrings
5
5
  Author-email: Mark Hu <watermarkhu@gmail.com>
6
6
  License: MIT
@@ -1,7 +1,7 @@
1
1
  mkdocstrings_handlers/github/__init__.py,sha256=0WdFUIq4Xu2ZFtlZNIYCQSoqcx3Ot9Wv41_X_dwbFww,248
2
- mkdocstrings_handlers/github/config.py,sha256=b2sZiRehEtg27ZUbPmUld8SlsGUYE5f1qLFuq1cWjlU,6220
3
- mkdocstrings_handlers/github/handler.py,sha256=MD0XmG2vsvsslUpFl1qB6bpiW28jRUNjG2lGkrFNIxs,11251
4
- mkdocstrings_handlers/github/objects.py,sha256=qkRGcwwYCHsrc9JEmujnvIt00_B1y5cR0vGS5NRkuSg,7028
2
+ mkdocstrings_handlers/github/config.py,sha256=IxD1AiaQf3wC2cRabi3wUriimZDOhFOmpWw5CB-jSb4,6277
3
+ mkdocstrings_handlers/github/handler.py,sha256=gNmKpMfr1xc6WIlCZh3J3Oz9BAKDKvAsPJZt2C2oJWg,10813
4
+ mkdocstrings_handlers/github/objects.py,sha256=JDkY7mg_LGlIEwZHP2wSd8ZkB6RVtRsu_JEpwV-PikQ,7069
5
5
  mkdocstrings_handlers/github/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  mkdocstrings_handlers/github/rendering.py,sha256=8h5Zn62b3od9Dj3MNvMtAGg_ZyyLfJKv2Z2qGdFaKG8,2329
7
7
  mkdocstrings_handlers/github/templates/material/action.html.jinja,sha256=87NCgz-zY16rU7tEmJETJ0gLwdzxoBrqLtp9vsVCsiw,2435
@@ -11,7 +11,7 @@ mkdocstrings_handlers/github/templates/material/outputs.html.jinja,sha256=ePu1v8
11
11
  mkdocstrings_handlers/github/templates/material/secrets.html.jinja,sha256=92ynVoZinsLEp7_sFS3mL2E2ngOXPPAtXzGAuGFvhmY,2782
12
12
  mkdocstrings_handlers/github/templates/material/style.css,sha256=R2hh1RfHwJ6XNT4YQl_txNkNXcPBZJMCBZn5kQEMQ6M,962
13
13
  mkdocstrings_handlers/github/templates/material/workflow.html.jinja,sha256=E1VUi2w7_NDkpS9VNrWRV52hhyhQvnKUrjPbV_j0Qcg,3312
14
- mkdocstrings_github-0.2.4.dist-info/METADATA,sha256=1pzvDfDEgY43O-Itmcg-1OEae8vJNabUf5esgLT28II,3125
15
- mkdocstrings_github-0.2.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- mkdocstrings_github-0.2.4.dist-info/licenses/LICENSE,sha256=5enZtJ4zSp0Ps3jTqFQ4kadcx62BhgTaDNPrXWb3g3E,1069
17
- mkdocstrings_github-0.2.4.dist-info/RECORD,,
14
+ mkdocstrings_github-0.2.6.dist-info/METADATA,sha256=bJFvjA8hX48033Nzh6foiStVEZ-YOCNGt2rje03pKmo,3125
15
+ mkdocstrings_github-0.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ mkdocstrings_github-0.2.6.dist-info/licenses/LICENSE,sha256=5enZtJ4zSp0Ps3jTqFQ4kadcx62BhgTaDNPrXWb3g3E,1069
17
+ mkdocstrings_github-0.2.6.dist-info/RECORD,,
@@ -173,7 +173,7 @@ class GitHubConfig(BaseModel):
173
173
 
174
174
  hostname: str = Field(
175
175
  default="github.com",
176
- description="The hostname of the GitHub instance to use.",
176
+ description="The hostname of the GitHub instance to use. This is only needed for GitHub Enterprise installations.",
177
177
  )
178
178
 
179
179
  repo: str = Field(
@@ -74,103 +74,13 @@ class GitHubHandler(BaseHandler):
74
74
  self.major: str = ""
75
75
  self.semver: str = ""
76
76
 
77
- # Only run GitHub releases code if not running under pytest
78
- if (
77
+ # Only run GitHub releases code if required and not in testing
78
+ not_testing = "pytest" not in sys.modules
79
+ no_custom_tags = (
79
80
  rendering.ENV_MAJOR_TAG not in os.environ or rendering.ENV_SEMVER_TAG not in os.environ
80
- ) and "pytest" not in sys.modules:
81
- # Use PyGitHub to find last GitHub releases with tags matching vX.X.X and vX
82
-
83
- gh_host = os.environ.get("GH_HOST", config.hostname)
84
- # Construct base_url for GitHub API.
85
- #
86
- # Expected formats for GH_HOST/config.hostname:
87
- # - Full API URL (e.g., 'https://github.company.com/api/v3') [RECOMMENDED for GitHub Enterprise]
88
- # - Hostname (e.g., 'github.com' or 'github.company.com')
89
- # - API subdomain (e.g., 'api.github.com')
90
- #
91
- # If a full URL is provided, it is used as-is.
92
- # If the value contains '/api/', it is assumed to be a full API endpoint and used as-is (with protocol if missing).
93
- # Otherwise, the code falls back to public GitHub conventions.
94
- if gh_host.startswith(("http://", "https://")):
95
- base_url = gh_host
96
- elif "/api/" in gh_host:
97
- # If protocol is missing, default to https
98
- base_url = f"https://{gh_host}"
99
- elif gh_host.startswith("api."):
100
- base_url = f"https://{gh_host}"
101
- else:
102
- # Warn user about possible misconfiguration for GitHub Enterprise
103
- _logger.warning(
104
- "The GH_HOST/config.hostname value '%s' does not appear to be a full API endpoint. "
105
- "For GitHub Enterprise, you may need to specify the full API URL (e.g., 'https://github.company.com/api/v3').",
106
- gh_host,
107
- )
108
- base_url = f"https://api.{gh_host}"
109
-
110
- if (token_key := "GH_TOKEN") in os.environ:
111
- gh = Github(base_url=base_url, auth=Auth.Token(os.environ[token_key]))
112
- elif (token_key := "GITHUB_TOKEN") in os.environ:
113
- gh = Github(base_url=base_url, auth=Auth.Token(os.environ[token_key]))
114
- else:
115
- try:
116
- gh = Github(base_url=base_url, auth=Auth.NetrcAuth())
117
- except RuntimeError:
118
- try:
119
- token = subprocess.check_output(
120
- ["gh", "auth", "token"], text=True, env=os.environ
121
- ).strip()
122
- if token:
123
- gh = Github(base_url=base_url, auth=Auth.Token(token))
124
- else:
125
- raise RuntimeError("No token from gh auth token")
126
- except Exception:
127
- _logger.warning(
128
- "Could not authenticate with GitHub to get releases. "
129
- "Consider setting .netrc, environment variable GH_TOKEN, "
130
- "or using GitHub CLI (`gh auth login`) to get GitHub releases.",
131
- )
132
- gh = Github(base_url=base_url)
133
-
134
- owner, repo_name = self.config.repo.split("/", 1)
135
- gh_repo = gh.get_repo(f"{owner}/{repo_name}")
136
- releases = list(gh_repo.get_releases())
137
- for release in releases:
138
- tag = release.tag_name
139
- if not self.semver and SEMVER_PATTERN.match(tag):
140
- self.semver = tag
141
- if not self.major and MAJOR_PATTERN.match(tag):
142
- self.major = tag
143
- if self.semver and self.major:
144
- break
145
-
146
- if not self.semver or not self.major:
147
- if not self.semver and not self.major:
148
- messages = ("'vX.X.X' and 'vX'", "'semver and major'")
149
- elif not self.semver:
150
- messages = ("'vX.X.X'", "'semver'")
151
- else: # not self.major
152
- messages = ("'vX'", "'major'")
153
- _logger.warning(
154
- "Could not find suitable GitHub releases for repo '%s'. "
155
- "Make sure there are releases with tags matching %s, "
156
- "if you wish to use option signature_version %s.",
157
- self.config.repo,
158
- messages[0],
159
- messages[1],
160
- )
161
-
162
- if self.config.repo == ".":
163
- url = next(repo.remote("origin").urls)
164
- match = re.search(r"github.com[:/](?P<owner>[^/]+)/(?P<repo>[^/.]+)", url)
165
- if match:
166
- self.config.repo = f"{match.group('owner')}/{match.group('repo')}"
167
- else:
168
- _logger.warning(
169
- "Could not determine GitHub repository automatically from git remote URL '%s'. "
170
- "Make sure the remote URL is a GitHub URL, "
171
- "or set the 'repo' option in the configuration.",
172
- url,
173
- )
81
+ )
82
+ if not_testing and no_custom_tags:
83
+ self.get_releases()
174
84
 
175
85
  # Glob all workflow YAML files using pathlib
176
86
  working_tree_dir = Path(repo.working_tree_dir)
@@ -197,6 +107,98 @@ class GitHubHandler(BaseHandler):
197
107
  if action is not None:
198
108
  self.actions[action_file] = action
199
109
 
110
+ def get_releases(self) -> None:
111
+ gh_host = os.environ.get("GH_HOST", self.config.hostname)
112
+ if gh_host.startswith(("http://", "https://")):
113
+ base_url = gh_host
114
+ elif "/api/" in gh_host:
115
+ # If protocol is missing, default to https
116
+ base_url = f"https://{gh_host}"
117
+ elif gh_host.startswith("api."):
118
+ base_url = f"https://{gh_host}"
119
+ else:
120
+ base_url = f"https://api.{gh_host}"
121
+
122
+ _logger.debug(f"Using GitHub API base URL: {base_url}")
123
+
124
+ if (token_key := "GH_TOKEN") in os.environ:
125
+ gh = Github(base_url=base_url, auth=Auth.Token(os.environ[token_key]))
126
+ _logger.debug(f"Using GitHub authentication from environment variable {token_key}")
127
+ elif (token_key := "GITHUB_TOKEN") in os.environ:
128
+ gh = Github(base_url=base_url, auth=Auth.Token(os.environ[token_key]))
129
+ _logger.debug(f"Using GitHub authentication from environment variable {token_key}")
130
+ else:
131
+ try:
132
+ gh = Github(base_url=base_url, auth=Auth.NetrcAuth())
133
+ _logger.debug("Using GitHub authentication from .netrc")
134
+ except RuntimeError:
135
+ try:
136
+ token = subprocess.check_output(
137
+ ["gh", "auth", "token"], text=True, env=os.environ
138
+ ).strip()
139
+ if token:
140
+ gh = Github(base_url=base_url, auth=Auth.Token(token))
141
+ _logger.debug("Using GitHub authentication from gh cli.")
142
+ else:
143
+ raise RuntimeError("No token from gh auth token")
144
+ except Exception:
145
+ _logger.warning(
146
+ "Could not authenticate with GitHub to get releases. "
147
+ "Consider setting .netrc, environment variable GH_TOKEN, "
148
+ "or using GitHub CLI (`gh auth login`) to get GitHub releases.",
149
+ )
150
+ gh = Github(base_url=base_url)
151
+
152
+ # Determine owner and repo name
153
+ if "/" in self.config.repo:
154
+ owner, repo_name = self.config.repo.split("/", 1)
155
+ else:
156
+ # Try each remote to find a valid GitHub owner/repo
157
+ owner = None
158
+ repo_name = None
159
+ for remote in self.repo.remotes:
160
+ for url in remote.urls:
161
+ match = re.search(
162
+ r"(?P<host>[\w\.-]+)[/:](?P<owner>[^/]+)/(?P<repo>[^/.]+?)(?:\.git)?$",
163
+ url,
164
+ )
165
+ if match:
166
+ owner = match.group("owner")
167
+ repo_name = match.group("repo")
168
+ break
169
+ if owner and repo_name:
170
+ break
171
+ if not (owner and repo_name):
172
+ raise PluginError(
173
+ f"Could not determine GitHub repository owner/name from config.repo='{self.config.repo}' or any git remote URL."
174
+ )
175
+ self.config.repo = f"{owner}/{repo_name}"
176
+
177
+ # Get releases
178
+ gh_repo = gh.get_repo(f"{owner}/{repo_name}")
179
+ releases = list(gh_repo.get_releases())
180
+ for release in releases:
181
+ tag = release.tag_name
182
+ if not self.semver and SEMVER_PATTERN.match(tag):
183
+ self.semver = tag
184
+ if not self.major and MAJOR_PATTERN.match(tag):
185
+ self.major = tag
186
+ if self.semver and self.major:
187
+ break
188
+
189
+ if not self.semver or not self.major:
190
+ if not self.semver and not self.major:
191
+ messages = ("'vX.X.X' and 'vX'", "'semver and major'")
192
+ elif not self.semver:
193
+ messages = ("'vX.X.X'", "'semver'")
194
+ else: # not self.major
195
+ messages = ("'vX'", "'major'")
196
+ _logger.warning(
197
+ f"Could not find suitable GitHub releases for repo '{self.config.repo}'. "
198
+ f"Make sure there are releases with tags matching {messages[0]}, "
199
+ f"if you wish to use option signature_version {messages[1]}.",
200
+ )
201
+
200
202
  def get_options(self, local_options: Mapping[str, Any]) -> HandlerOptions:
201
203
  """Get combined default, global and local options.
202
204
 
@@ -196,7 +196,6 @@ class Workflow:
196
196
 
197
197
  if "on" not in data or "workflow_call" not in data["on"]:
198
198
  return None
199
- call = data["on"]["workflow_call"]
200
199
 
201
200
  workflow = Workflow(
202
201
  file=file,
@@ -205,13 +204,15 @@ class Workflow:
205
204
  name=_get_member(data, "name", "Workflow must have a name"),
206
205
  description=_get_member(data, "description", default=""),
207
206
  )
208
- for key, value in call.get("inputs", {}).items():
209
- workflow.inputs.append(Input.from_data(key, **value))
210
- for key, value in call.get("outputs", {}).items():
211
- workflow.outputs.append(Output.from_data(key, **value))
212
- for key, value in call.get("secrets", {}).items():
213
- workflow.secrets.append(Secret.from_data(key, **value))
214
207
 
208
+ call = data["on"]["workflow_call"]
209
+ if call:
210
+ for key, value in call.get("inputs", {}).items():
211
+ workflow.inputs.append(Input.from_data(key, **value))
212
+ for key, value in call.get("outputs", {}).items():
213
+ workflow.outputs.append(Output.from_data(key, **value))
214
+ for key, value in call.get("secrets", {}).items():
215
+ workflow.secrets.append(Secret.from_data(key, **value))
215
216
  for key, label in data.get("permissions", {}).items():
216
217
  workflow.permissions[key] = PermissionLevel.from_label(label)
217
218
  for job in data.get("jobs", {}).values():