Coverage for portality / lcc.py: 58%

98 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-05 00:09 +0100

1""" 

2~~LCC:Data->LCCXML:Data~~ 

3""" 

4from portality.lib import paths 

5from portality.models import LCC 

6from portality.core import prepare_type 

7 

8 

9def loadLCC(source=None): 

10 # use delayed imports, as this code will only rarely be run 

11 import os 

12 from lxml import etree 

13 

14 if source is None: 

15 source = paths.rel2abs(__file__, "..", "lccSubjects.xml") 

16 

17 doc = etree.parse(open(source)) 

18 root = doc.getroot() 

19 

20 nodes = {} 

21 tree = {"name": "LCC", "children": []} 

22 cpmap = {} 

23 

24 for element in root.findall("subject"): 

25 nel = element.find("name") 

26 cel = element.find("code") 

27 pel = element.find("parent") 

28 

29 if nel is None: 

30 continue 

31 

32 name = nel.text 

33 code = None 

34 parent = None 

35 if cel is not None: 

36 code = cel.text 

37 if pel is not None: 

38 parent = pel.text 

39 

40 node = {"name": name} 

41 if code is not None: 

42 node["code"] = code 

43 

44 nodes[name] = node 

45 

46 if parent is None: 

47 tree["children"].append(node) 

48 else: 

49 cpmap[name] = parent 

50 

51 for child, parent in cpmap.items(): 

52 cn = nodes.get(child) 

53 pn = nodes.get(parent) 

54 if cn is None or pn is None: 

55 continue 

56 if "children" not in pn: 

57 pn["children"] = [] 

58 pn["children"].append(cn) 

59 

60 lcc = LCC(**tree) 

61 

62 # Initialise the LCC index correctly if it doesn't exist - otherwise it'll be created badly on save 

63 prepare_type(lcc.__type__) 

64 lcc.save() 

65 

66 

67def lcc2choices(thelcc, level=-2): 

68 level += 1 

69 level_indicator = '--' 

70 if 'children' in thelcc: 

71 results = [] 

72 if thelcc['name'] != 'LCC': 

73 # don't want the root + it doesn't have a code 

74 results += [(thelcc['code'], level_indicator * level + thelcc['name'])] 

75 for child in thelcc['children']: 

76 results += lcc2choices(child, level=level) 

77 return results 

78 else: 

79 # this is a leaf 

80 if 'code' not in thelcc: 

81 if thelcc['name'] == 'TMP': 

82 # some weird leaf element at 1st level of the tree 

83 # don't want to generate a choice for it, just ignore 

84 return [] 

85 return [(thelcc['code'], level_indicator * level + thelcc['name'])] 

86 

87 

88def lcc2jstree(thelcc): 

89 if 'children' in thelcc: 

90 results = [] 

91 if thelcc['name'] == 'LCC': 

92 for child in thelcc['children']: 

93 results += lcc2jstree(child) 

94 else: 

95 # don't want the root + it doesn't have a code 

96 newnode = { 

97 "id": thelcc['code'], 

98 "text": thelcc['name'], 

99 "children": [] 

100 } 

101 for child in thelcc['children']: 

102 newnode['children'] += lcc2jstree(child) 

103 results.append(newnode) 

104 

105 return results 

106 else: 

107 # this is a leaf 

108 if 'code' not in thelcc: 

109 if thelcc['name'] == 'TMP': 

110 # some weird leaf element at 1st level of the tree 

111 # don't want to generate a choice for it, just ignore 

112 return [] 

113 return [ 

114 { 

115 "id": thelcc['code'], 

116 "text": thelcc['name'], 

117 "children": [] 

118 } 

119 ] 

120 

121 

122def lcc2flat_code_index(thelcc): 

123 if 'children' in thelcc: 

124 results = {} 

125 if thelcc['name'] != 'LCC': 

126 # don't want the root + it doesn't have a code 

127 results.update({thelcc['code']: thelcc['name']}) 

128 for child in thelcc['children']: 

129 results.update(lcc2flat_code_index(child)) 

130 return results 

131 else: 

132 # this is a leaf 

133 if 'code' not in thelcc: 

134 if thelcc['name'] == 'TMP': 

135 # some weird leaf element at 1st level of the tree 

136 # don't want to generate a choice for it, just ignore 

137 return {} 

138 return {thelcc['code']: thelcc['name']} 

139 

140 

141lcc = LCC.pull('lcc') 

142if not lcc: 

143 loadLCC() 

144lcc = LCC.pull('lcc') 

145lcc_choices = [] 

146lcc_jstree = [] 

147lcc_index_by_code = {} 

148if lcc: 

149 lcc_choices = lcc2choices(lcc) 

150 lcc_jstree = lcc2jstree(lcc) 

151 lcc_index_by_code = lcc2flat_code_index(lcc) 

152 

153 

154def lookup_code(code): 

155 return lcc_index_by_code.get(code)