Skip to content

Commit fa56ab3

Browse files
committed
chore: documentation and some cleaning
1 parent 14e5131 commit fa56ab3

File tree

1 file changed

+74
-20
lines changed
  • openedx/features/wikimedia_features/wikimedia_general/management/commands

1 file changed

+74
-20
lines changed

openedx/features/wikimedia_features/wikimedia_general/management/commands/sync_usernames.py

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,30 @@
88
from django.db.models.functions import Concat
99
from django.core.management.base import BaseCommand
1010

11-
1211
log = getLogger(__name__)
1312
User = get_user_model()
1413

1514

1615
class Command(BaseCommand):
17-
""" """
16+
"""
17+
Django management command to sync user usernames with Wikimedia usernames.
18+
19+
This command matches the usernames in the local database with the Wikimedia
20+
usernames, and updates the local usernames if they differ from the ones provided
21+
by Wikimedia.
22+
"""
1823

1924
help = "Matches the usernames with Wikimedia and updates the changed ones in Wikilearn"
2025

2126
def add_arguments(self, parser):
27+
"""
28+
Adds command-line arguments to the management command.
29+
30+
Arguments:
31+
parser (ArgumentParser): The argument parser to which arguments should be added.
32+
- usernames (list): List of specific usernames to sync. If not provided,
33+
all usernames will be checked and synced.
34+
"""
2235
parser.add_argument(
2336
"usernames",
2437
nargs="*",
@@ -28,29 +41,39 @@ def add_arguments(self, parser):
2841

2942
def handle(self, *args, **options):
3043
"""
31-
Get all TPA users whose usernames were cleaned and filter by usernames if provided.
32-
Get their usernames from the third party provider in this case wikimedia
33-
and update their username in Wikilearn.
44+
Main entry point for the command.
45+
46+
Retrieves the users whose usernames need to be checked and updated.
47+
Filters the users if specific usernames are provided. Logs the process and
48+
prints the statistics of the operation.
49+
50+
Arguments:
51+
args: Additional positional arguments.
52+
options: Command-line options, including the list of usernames.
3453
"""
3554
usernames = options["usernames"]
3655
users = self._get_tpa_users()
3756

3857
if usernames:
3958
users = users.filter(username__in=usernames)
40-
59+
4160
total = users.count()
4261

43-
log.info("Syncing %s users with wikimedia usernames", total)
62+
log.info("Syncing %s users with Wikimedia usernames", total)
4463

4564
stats = self._update_user_with_wikimedia_username(users)
4665
self._print_stats(total, stats)
4766

48-
def _get_tpa_users(self):
67+
def _get_tpa_users(self) -> QuerySet[User]:
4968
"""
50-
Gets all the platform users who registered with the third party provider.
69+
Retrieves users who registered with the third-party authentication (TPA) provider.
70+
71+
These are users whose usernames need to be potentially updated based on
72+
Wikimedia usernames. Excludes users whose first name is missing or whose
73+
username already matches their wiki_username.
5174
52-
It is assumed that users without first name were registered before TPA was required.
53-
Also excludes where username is the combination first and last name already.
75+
Returns:
76+
QuerySet[User]: A queryset of users to be processed.
5477
"""
5578
users = (
5679
User.objects.select_related("profile")
@@ -66,15 +89,27 @@ def _get_tpa_users(self):
6689
.exclude(first_name="")
6790
.exclude(
6891
username=F("wiki_username")
69-
) # because no point in updating username with wiki_username later if it is already same.
92+
) # Excludes users whose username already matches the computed wiki_username.
7093
)
7194

7295
return users
7396

7497
def _update_user_with_wikimedia_username(self, users: QuerySet[User]) -> dict:
7598
"""
76-
Checks if "wiki_username" was the original username provided by Wikimedia
77-
and updates the Wikilearn username with it.
99+
Updates the usernames of users based on their Wikimedia username.
100+
101+
This method checks if the current username matches the Wikimedia username.
102+
If the usernames differ, the local username is updated. It logs each operation
103+
and returns statistics of the update process.
104+
105+
Arguments:
106+
users (QuerySet[User]): A queryset of users to be processed.
107+
108+
Returns:
109+
dict: A dictionary containing statistics about the update process.
110+
- correct_username: Number of usernames that were already correct.
111+
- updated_username: Number of usernames that were updated.
112+
- skipped_username: Number of usernames that were skipped.
78113
"""
79114
total = len(users)
80115
stats = {
@@ -85,23 +120,29 @@ def _update_user_with_wikimedia_username(self, users: QuerySet[User]) -> dict:
85120
for i, user in enumerate(users):
86121
index = i + 1
87122
if self._username_exists(user.username):
88-
# This check is to avoid updating username if it is already same as Wikimedia's.
89-
log.info(f'{index}/{total}: SKIPPED: {user.username} is CORRECT')
123+
# This check is to avoid updating username if it is already correct according to Wikimedia.
124+
log.info(f"{index}/{total}: SKIPPED: {user.username} is CORRECT")
90125
stats["correct_username"] += 1
91126
elif self._username_exists(user.wiki_username):
92127
log.info(f"{index}/{total}: UPDATING: {user.username} with {user.wiki_username}")
93128
self._update_user(user)
94129
stats["updated_username"] += 1
95130
else:
96-
# This means both the username and our guess (first_name+last_name) is wrong.
97-
log.info(f'{index}/{total}: SKIPPED: {user.username}')
131+
# This means both the username and the computed wiki_username are incorrect.
132+
log.info(f"{index}/{total}: SKIPPED: {user.username}")
98133
stats["skipped_username"] += 1
99-
134+
100135
return stats
101136

102137
def _username_exists(self, username: str) -> bool:
103138
"""
104-
Checks if username exists in the Wikimedia's global account.
139+
Checks if a username exists in Wikimedia's global account database.
140+
141+
Arguments:
142+
username (str): The username to be checked.
143+
144+
Returns:
145+
bool: True if the username exists in Wikimedia, False otherwise.
105146
"""
106147
USERNAME_VERIFY_URL = f"https://en.wikipedia.org/wiki/Special:CentralAuth?target={username}"
107148
ERROR_MSG = "There is no global account for"
@@ -111,10 +152,23 @@ def _username_exists(self, username: str) -> bool:
111152
return ERROR_MSG not in response.text
112153

113154
def _update_user(self, user: User):
155+
"""
156+
Updates the username of a user in the local database.
157+
158+
Arguments:
159+
user (User): The user object whose username is to be updated.
160+
"""
114161
user.username = user.wiki_username
115162
user.save()
116163

117164
def _print_stats(self, total: int, stats: dict):
165+
"""
166+
Prints statistics about the update process.
167+
168+
Arguments:
169+
total (int): The total number of users processed.
170+
stats (dict): A dictionary containing statistics about the update process.
171+
"""
118172
log.info(f"Total mismatched users: {total}")
119173
log.info(f"Correct usernames: {stats['correct_username']}")
120174
log.info(f"Updated usernames: {stats['updated_username']}")

0 commit comments

Comments
 (0)