Coverage for src/crawler/cmds/xml_cmds.py: 18%

79 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-09-23 14:47 +0000

1import logging 

2import math 

3 

4from django.core.exceptions import ObjectDoesNotExist 

5from django.db.models import Q 

6from ptf.cmds.xml_cmds import ( 

7 addOrUpdateBookXmlCmd, 

8 addOrUpdateContainerXmlCmd, 

9 addOrUpdateIssueXmlCmd, 

10 importEntireCollectionXmlCmd, 

11) 

12from ptf.models import Collection, CollectionMembership, Container 

13 

14from crawler.models import ContainerSource 

15 

16logger = logging.getLogger(__name__) 

17 

18 

19def add_source_to_container(source_domain: str, container: Container, disabled=True): 

20 from crawler import factory 

21 

22 source_cls = factory.get_crawler_class(source_domain) 

23 if not source_cls: 

24 logger.warning( 

25 f"Couldn't insert source {source_domain} to container : source not implemented" 

26 ) 

27 return False 

28 

29 source = source_cls.get_or_create_source() 

30 try: 

31 container.origin.delete() 

32 except ObjectDoesNotExist: 

33 pass 

34 ContainerSource.objects.get_or_create(source=source, container=container, disabled=disabled) 

35 logger.debug(f"Source {source_domain} successfully added to container {container.pid}") 

36 return True 

37 

38 

39def update_collection_years(pid): 

40 collection = Collection.objects.get(pid=pid) 

41 parent = collection.parent 

42 

43 if parent is None: 

44 qs = Container.objects.filter(my_collection__pid=pid, origin__disabled=False) 

45 collection_to_update = collection 

46 else: 

47 qs = Container.objects.filter( 

48 Q(my_collection__pid=pid) | Q(my_collection__parent__pid=pid), 

49 origin__disabled=False, 

50 ) 

51 collection_to_update = parent 

52 

53 qs_member = CollectionMembership.objects.filter(collection__pid=collection_to_update.pid) 

54 qs = [*(cm.container for cm in qs_member), *qs] 

55 

56 max_year = -math.inf 

57 min_year = math.inf 

58 for container in qs: 

59 fyear = container.fyear 

60 lyear = container.lyear or 0 

61 max_year = max(lyear, max_year) 

62 min_year = min(fyear, min_year) 

63 if min_year == math.inf: 

64 min_year = 0 

65 if max_year == -math.inf: 

66 max_year = 0 

67 

68 collection_to_update.fyear = int(min_year) 

69 collection_to_update.lyear = int(max_year) 

70 

71 collection_to_update.save(update_fields=["fyear", "lyear"]) 

72 

73 

74class addOrUpdateGDMLIssueXmlCmd(addOrUpdateIssueXmlCmd): 

75 def internal_do(self): 

76 obj = super().internal_do() 

77 if not obj or not self.xissue: 

78 logger.debug("Skipping source insertion : database object or xissue is not set") 

79 return obj 

80 

81 source_str = self.xissue.source 

82 if not source_str: 

83 if not self.add_link_to_source: 

84 logger.debug( 

85 "Skipping source insertion : add_link_to_source is false and xissue.source is None" 

86 ) 

87 return obj 

88 source_str = "NUMDAM" 

89 

90 add_source_to_container(source_str, obj) 

91 self.update_collection_years(self.xissue.journal.pid) 

92 return obj 

93 

94 

95class addOrUpdateGDMLBookXmlCmd(addOrUpdateBookXmlCmd): 

96 def internal_do(self): 

97 obj = super().internal_do() 

98 if not obj or not self.xbook: 

99 logger.debug( 

100 "Skipping source insertion : no database object was returned or xbook is None" 

101 ) 

102 return obj 

103 

104 source_str = self.xbook.source 

105 if not source_str: 

106 if not self.add_link_to_source: 

107 logger.debug( 

108 "Skipping source insertion : add_link_to_source is false and xbook.source is None" 

109 ) 

110 return obj 

111 source_str = "NUMDAM" 

112 

113 add_source_to_container(source_str, obj) 

114 return obj 

115 

116 

117class addOrUpdateGDMLContainerXmlCmd(addOrUpdateContainerXmlCmd): 

118 addOrUpdateIssueXmlCmdOverride = addOrUpdateGDMLIssueXmlCmd 

119 addOrUpdateBookXmlCmdOverride = addOrUpdateGDMLBookXmlCmd 

120 

121 

122importEntireCollectionXmlCmd.addOrUpdateContainerXmlCmdOverride = addOrUpdateGDMLContainerXmlCmd