Coverage for app/venv/lib/python3.14/site-packages/weblate/accounts/management/commands/importuserdata.py: 0%
59 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
1# Copyright © Michal Čihař <michal@weblate.org>
2#
3# SPDX-License-Identifier: GPL-3.0-or-later
4from __future__ import annotations
6import json
7from pathlib import Path
8from typing import TYPE_CHECKING
10from django.core.management.base import CommandError
12from weblate.auth.models import User
13from weblate.lang.models import Language
14from weblate.trans.models import Project
15from weblate.utils.management.base import BaseCommand
17if TYPE_CHECKING:
18 from django.core.management.base import CommandParser
21class Command(BaseCommand):
22 help = "imports userdata from JSON dump of database"
24 def add_arguments(self, parser: CommandParser) -> None:
25 parser.add_argument(
26 "json-file",
27 type=Path,
28 help="JSON file containing user data to import",
29 )
31 @staticmethod
32 def import_watched(profile, userprofile) -> None:
33 """Import user subscriptions."""
34 # Add subscriptions
35 for subscription in userprofile["watched"]:
36 try:
37 profile.watched.add(Project.objects.get(slug=subscription))
38 except Project.DoesNotExist:
39 continue
41 @staticmethod
42 def update_languages(profile, userprofile) -> None:
43 """Update user language preferences."""
44 profile.language = userprofile["language"]
45 for lang in userprofile["secondary_languages"]:
46 profile.secondary_languages.add(Language.objects.auto_get_or_create(lang))
47 for lang in userprofile["languages"]:
48 profile.languages.add(Language.objects.auto_get_or_create(lang))
50 def handle_compat(self, data) -> None:
51 """Compatibility with pre 3.6 dumps."""
52 if "basic" in data:
53 return
54 data["basic"] = {"username": data["username"]}
55 data["profile"] = {
56 "translated": data["translated"],
57 "suggested": data["suggested"],
58 "language": data["language"],
59 "uploaded": data.get("uploaded", 0),
60 "secondary_languages": data["secondary_languages"],
61 "languages": data["languages"],
62 "watched": data["subscriptions"],
63 }
65 def handle(self, **options) -> None:
66 """
67 Create default set of groups.
69 Also ptionally updates them and moves users around to default group.
70 """
71 try:
72 with options["json-file"].open("r") as handle:
73 userdata = json.load(handle)
74 except OSError as error:
75 msg = f"Could not open file: {error}"
76 raise CommandError(msg) from error
78 for userprofile in userdata:
79 self.handle_compat(userprofile)
80 username = userprofile["basic"]["username"]
81 try:
82 user = User.objects.get(username=username)
83 update = False
84 profile = user.profile
85 if not profile.language:
86 update = True
88 # Merge stats
89 profile.translated += userprofile["profile"]["translated"]
90 profile.suggested += userprofile["profile"]["suggested"]
91 profile.uploaded += userprofile["profile"]["uploaded"]
93 # Update fields if we should
94 if update:
95 self.update_languages(profile, userprofile["profile"])
97 # Add subscriptions
98 self.import_watched(profile, userprofile["profile"])
100 profile.save()
101 except User.DoesNotExist:
102 self.stderr.write(f"User not found: {username}\n")