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

1# Copyright © Michal Čihař <michal@weblate.org> 

2# 

3# SPDX-License-Identifier: GPL-3.0-or-later 

4from __future__ import annotations 

5 

6import json 

7from pathlib import Path 

8from typing import TYPE_CHECKING 

9 

10from django.core.management.base import CommandError 

11 

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 

16 

17if TYPE_CHECKING: 

18 from django.core.management.base import CommandParser 

19 

20 

21class Command(BaseCommand): 

22 help = "imports userdata from JSON dump of database" 

23 

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 ) 

30 

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 

40 

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)) 

49 

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 } 

64 

65 def handle(self, **options) -> None: 

66 """ 

67 Create default set of groups. 

68 

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 

77 

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 

87 

88 # Merge stats 

89 profile.translated += userprofile["profile"]["translated"] 

90 profile.suggested += userprofile["profile"]["suggested"] 

91 profile.uploaded += userprofile["profile"]["uploaded"] 

92 

93 # Update fields if we should 

94 if update: 

95 self.update_languages(profile, userprofile["profile"]) 

96 

97 # Add subscriptions 

98 self.import_watched(profile, userprofile["profile"]) 

99 

100 profile.save() 

101 except User.DoesNotExist: 

102 self.stderr.write(f"User not found: {username}\n")