Skip to content

Commit 65f8785

Browse files
committed
chore: formatting/pydoc fixes
1 parent 426ae7a commit 65f8785

File tree

4 files changed

+53
-20
lines changed

4 files changed

+53
-20
lines changed

invenio_vcs/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@
5757

5858

5959
def get_provider_list(app=current_app) -> list["RepositoryServiceProviderFactory"]:
60+
"""Get a list of configured VCS provider factories."""
6061
return app.config["VCS_PROVIDERS"]
6162

6263

6364
def get_provider_by_id(id: str) -> "RepositoryServiceProviderFactory":
65+
"""Get a specific VCS provider by its registered ID."""
6466
providers = get_provider_list()
6567
for provider in providers:
6668
if id == provider.id:

invenio_vcs/oauth/handlers.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323

2424

2525
class OAuthHandlers:
26+
"""Provider-agnostic handler overrides to ensure VCS events are executed at certain points throughout the OAuth lifecyle."""
27+
2628
def __init__(self, provider_factory: "RepositoryServiceProviderFactory") -> None:
29+
"""Instance are non-user-specific."""
2730
self.provider_factory = provider_factory
2831

2932
def account_setup_handler(self, remote, token, resp):

invenio_vcs/receivers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class VCSReceiver(Receiver):
4242
"""Handle incoming notification from GitHub on a new release."""
4343

4444
def __init__(self, receiver_id):
45+
"""Constructor."""
4546
super().__init__(receiver_id)
4647
self.provider_factory = get_provider_by_id(receiver_id)
4748

invenio_vcs/service.py

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# -*- coding: utf-8 -*-
2+
# This file is part of Invenio.
3+
# Copyright (C) 2025 CERN.
4+
#
5+
# Invenio is free software; you can redistribute it and/or modify it
6+
# under the terms of the MIT License; see LICENSE file for more details.
7+
"""Higher-level operations for the view handlers and upstream code to use."""
8+
19
from abc import abstractmethod
210
from contextlib import contextmanager
311
from dataclasses import asdict
@@ -11,8 +19,7 @@
1119
from invenio_i18n import gettext as _
1220
from invenio_oauth2server.models import Token as ProviderToken
1321
from invenio_oauthclient import oauth_link_external_id
14-
from invenio_oauthclient.models import RemoteAccount
15-
from sqlalchemy import delete, select
22+
from sqlalchemy import delete
1623
from sqlalchemy.exc import NoResultFound
1724
from werkzeug.utils import cached_property
1825

@@ -43,21 +50,31 @@
4350

4451

4552
class VCSService:
53+
"""
54+
High level glue operations that operate on both the VCS and the DB.
55+
56+
Because provider instances are user-specific, this class is too.
57+
"""
58+
4659
def __init__(self, provider: "RepositoryServiceProvider") -> None:
60+
"""Please construct the service using the `for_provider_and_user` method instead."""
4761
self.provider = provider
4862

4963
@staticmethod
5064
def for_provider_and_user(provider_id: str, user_id: int):
65+
"""Construct VCSService for a locally configured provider and a user with a DB-queried access token."""
5166
return VCSService(get_provider_by_id(provider_id).for_user(user_id))
5267

5368
@staticmethod
5469
def for_provider_and_token(provider_id: str, user_id: int, access_token: str):
70+
"""Construct VCSService for a locally configured provider and a user with a predefined access token."""
5571
return VCSService(
5672
get_provider_by_id(provider_id).for_access_token(user_id, access_token)
5773
)
5874

5975
@cached_property
6076
def is_authenticated(self):
77+
"""Whether we have a valid VCS API token for the user. Should (almost) always return True."""
6178
return self.provider.session_token is not None
6279

6380
@property
@@ -102,7 +119,7 @@ def get_repo_latest_release(self, repo):
102119
return current_vcs.release_api_class(release_object, self.provider)
103120

104121
def list_repo_releases(self, repo):
105-
# Retrieve releases and sort them by creation date
122+
"""Retrieve releases and sort them by creation date."""
106123
release_instances = []
107124
for release_object in repo.releases.order_by(Release.created):
108125
release_instances.append(
@@ -111,6 +128,7 @@ def list_repo_releases(self, repo):
111128
return release_instances
112129

113130
def get_repo_default_branch(self, repo_id):
131+
"""Return the locally-synced default branch."""
114132
db_repo = self.user_available_repositories.filter(
115133
Repository.provider_id == repo_id
116134
).first()
@@ -121,7 +139,7 @@ def get_repo_default_branch(self, repo_id):
121139
return db_repo.default_branch
122140

123141
def get_last_sync_time(self):
124-
"""Retrieves the last sync delta time from github's client extra data.
142+
"""Retrieves the last sync delta time from VCS's client extra data.
125143
126144
Time is computed as the delta between now and the last sync time.
127145
"""
@@ -156,7 +174,7 @@ def check_repo_access_permissions(self, repo: Repository):
156174
Repo has access if any of the following is True:
157175
158176
- user is the owner of the repo
159-
- user has access to the repo in GitHub (stored in RemoteAccount.extra_data.repos)
177+
- user has access to the repo in the VCS
160178
"""
161179
if self.provider.user_id and repo:
162180
user_is_collaborator = any(
@@ -179,6 +197,7 @@ def check_repo_access_permissions(self, repo: Repository):
179197
def sync_repo_users(self, db_repo: Repository):
180198
"""
181199
Synchronises the member users of the repository.
200+
182201
This retrieves a list of the IDs of users from the VCS who have sufficient access to the
183202
repository (i.e. being able to access all details and create/manage webhooks).
184203
The user IDs are compared locally to find Invenio users who have connected their VCS account.
@@ -187,7 +206,6 @@ def sync_repo_users(self, db_repo: Repository):
187206
188207
:return: boolean of whether any changed were made to the DB
189208
"""
190-
191209
vcs_user_ids = self.provider.list_repository_user_ids(db_repo.provider_id)
192210
if vcs_user_ids is None:
193211
return
@@ -235,8 +253,8 @@ def sync(self, hooks=True, async_hooks=True):
235253
236254
.. note::
237255
238-
Syncing happens from GitHub's direction only. This means that we
239-
consider the information on GitHub as valid, and we overwrite our
256+
Syncing happens from the VCS' direction only. This means that we
257+
consider the information on VCS as valid, and we overwrite our
240258
own state based on this information.
241259
"""
242260
vcs_repos = self.provider.list_repositories()
@@ -330,13 +348,13 @@ def _sync_hooks(self, repo_ids, asynchronous=True):
330348
)
331349

332350
def sync_repo_hook(self, repo_id):
333-
"""Sync a GitHub repo's hook with the locally stored repo."""
351+
"""Sync a VCS repo's hook with the locally stored repo."""
334352
# Get the hook that we may have set in the past
335353
hook = self.provider.get_first_valid_webhook(repo_id)
336354
vcs_repo = self.provider.get_repository(repo_id)
337355
assert vcs_repo is not None
338356

339-
# If hook on GitHub exists, get or create corresponding db object and
357+
# If hook on the VCS exists, get or create corresponding db object and
340358
# enable the hook. Otherwise remove the old hook information.
341359
db_repo = Repository.get(self.provider.factory.id, provider_id=repo_id)
342360

@@ -359,17 +377,17 @@ def sync_repo_hook(self, repo_id):
359377
self.mark_repo_disabled(db_repo)
360378

361379
def mark_repo_disabled(self, db_repo: Repository):
362-
"""Disables an user repository."""
380+
"""Marks a repository as disabled."""
363381
db_repo.hook = None
364382
db_repo.enabled_by_id = None
365383

366384
def mark_repo_enabled(self, db_repo: Repository, hook_id: str):
367-
"""Enables an user repository."""
385+
"""Marks a repository as enabled."""
368386
db_repo.hook = hook_id
369387
db_repo.enabled_by_id = self.provider.user_id
370388

371389
def init_account(self):
372-
"""Setup a new GitHub account."""
390+
"""Setup a new VCS account."""
373391
if not self.provider.remote_account:
374392
raise RemoteAccountNotFound(
375393
self.provider.user_id, _("Remote account was not found for user.")
@@ -405,6 +423,7 @@ def init_account(self):
405423
db.session.add(self.provider.remote_account)
406424

407425
def enable_repository(self, repository_id):
426+
"""Creates the hook for a repository and marks it as enabled."""
408427
db_repo = self.user_available_repositories.filter(
409428
Repository.provider_id == repository_id
410429
).first()
@@ -421,6 +440,7 @@ def enable_repository(self, repository_id):
421440
return True
422441

423442
def disable_repository(self, repository_id, hook_id=None):
443+
"""Deletes the hook for a repository and marks it as disabled."""
424444
db_repo = self.user_available_repositories.filter(
425445
Repository.provider_id == repository_id
426446
).first()
@@ -441,7 +461,14 @@ def disable_repository(self, repository_id, hook_id=None):
441461

442462

443463
class VCSRelease:
444-
"""A GitHub release."""
464+
"""
465+
Represents a release and common high-level operations that can be performed on it.
466+
467+
This class is often overriden upstream (e.g. in `invenio-rdm-records`) to specify
468+
what a 'publish' event should do on a given Invenio implementation.
469+
This module does not attempt to publish a record or anything similar, as `invenio-vcs`
470+
is designed to work on any Invenio instance (not just RDM).
471+
"""
445472

446473
def __init__(self, release: Release, provider: "RepositoryServiceProvider"):
447474
"""Constructor."""
@@ -466,6 +493,7 @@ def payload(self):
466493

467494
@cached_property
468495
def _generic_release_and_repo(self):
496+
"""Converts the VCS-specific payload into a tuple of (GenericRelease, GenericRepository)."""
469497
return self.provider.factory.webhook_event_to_generic(self.payload)
470498

471499
@cached_property
@@ -514,10 +542,9 @@ def user_identity(self):
514542
def contributors(self):
515543
"""Get list of contributors to a repository.
516544
517-
The list of contributors is fetched from Github API, filtered for type "User" and sorted by contributions.
545+
The list of contributors is fetched from the VCS, filtered for type "User" and sorted by contributions.
518546
519547
:returns: a generator of objects that contains contributors information.
520-
:raises UnexpectedGithubResponse: when Github API returns a status code other than 200.
521548
"""
522549
max_contributors = current_app.config.get("VCS_MAX_CONTRIBUTORS_NUMBER", 30)
523550
return self.provider.list_repository_contributors(
@@ -581,17 +608,17 @@ def release_published(self):
581608

582609
@contextmanager
583610
def fetch_zipball_file(self):
584-
"""Fetch release zipball file using the current github session."""
611+
"""Fetch release zipball file using the current VCS session."""
585612
timeout = current_app.config.get("VCS_ZIPBALL_TIMEOUT", 300)
586613
zipball_url = self.resolve_zipball_url()
587614
return self.provider.fetch_release_zipball(zipball_url, timeout)
588615

589616
def publish(self):
590-
"""Publish a GitHub release."""
617+
"""Publish a VCS release."""
591618
raise NotImplementedError
592619

593620
def process_release(self):
594-
"""Processes a github release."""
621+
"""Processes a VCS release."""
595622
raise NotImplementedError
596623

597624
def resolve_record(self):
@@ -616,5 +643,5 @@ def badge_value(self):
616643

617644
@property
618645
def record_url(self):
619-
"""Release self url (e.g. github HTML url)."""
646+
"""Release self url (e.g. VCS HTML url)."""
620647
raise NotImplementedError

0 commit comments

Comments
 (0)