Coverage for src/ptf/model_helpers.py: 73%

486 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-05 09:56 +0000

1import datetime 

2import itertools 

3import random 

4import re 

5import unicodedata 

6 

7import dateutil.parser 

8from unidecode import unidecode 

9 

10from django.conf import settings 

11from django.http import Http404 

12from django.shortcuts import get_list_or_404 

13from django.utils import timezone 

14 

15# from .models import ResourceInSpecialIssue 

16from .models import Article 

17from .models import Author 

18from .models import BibItem 

19from .models import BibItemId 

20from .models import Collection 

21from .models import Container 

22from .models import ExtId 

23from .models import ExtLink 

24from .models import Provider 

25from .models import PtfSite 

26from .models import Publisher 

27from .models import RelatedObject 

28from .models import RelationName 

29from .models import Relationship 

30from .models import Resource 

31from .models import ResourceInSpecialIssue 

32from .models import SiteMembership 

33from .models import XmlBase 

34from .site_register import SITE_REGISTER 

35 

36########################################################################## 

37# 

38# Get functions 

39# 

40########################################################################## 

41 

42 

43def get_first_last_years(year): 

44 the_array = year.split("-") 

45 

46 fyear = the_array[0] 

47 lyear = the_array[1] if len(the_array) > 1 else fyear 

48 

49 return fyear, lyear 

50 

51 

52def get_provider_by_name(name): 

53 if name == "numdam": 

54 name = "mathdoc" 

55 

56 provider = Provider.objects.get(name=name) 

57 return provider 

58 

59 

60def get_provider(pid_type): 

61 provider = Provider.objects.get(pid_type=pid_type) 

62 return provider 

63 

64 

65def get_publisher(name): 

66 try: 

67 key = make_key(name) 

68 publisher = Publisher.objects.get(pub_key=key) 

69 except Publisher.DoesNotExist: 

70 publisher = None 

71 return publisher 

72 

73 

74def get_or_create_site(site_id, acro=None): 

75 try: 

76 site = PtfSite.objects.get(id=site_id) 

77 except PtfSite.DoesNotExist: 

78 site = PtfSite.objects.create(id=site_id, name=acro, domain=acro, acro=acro) 

79 return site 

80 

81 

82def get_journals(): 

83 journals = Collection.objects.filter(sites__id=settings.SITE_ID, coltype="journal") 

84 return journals.all() 

85 

86 

87def get_actas(): 

88 actas = Collection.objects.filter(sites__id=settings.SITE_ID, coltype="acta") 

89 return actas.all() 

90 

91 

92def get_lectures(): 

93 lectures = Collection.objects.filter(sites__id=settings.SITE_ID, coltype="lecture-notes") 

94 return lectures.all() 

95 

96 

97def get_proceedings(): 

98 proceedings = Collection.objects.filter(sites__id=settings.SITE_ID, coltype="proceeding") 

99 return proceedings.all() 

100 

101 

102def get_collection_of_books(with_lectures=False): 

103 filters = ["book-series"] 

104 if with_lectures: 

105 filters.append("lecture-notes") 

106 

107 book_series = Collection.objects.filter(sites__id=settings.SITE_ID, coltype__in=filters) 

108 return book_series.all() 

109 

110 

111def get_books(): 

112 return Container.objects.filter( 

113 sites__id=settings.SITE_ID, 

114 my_collection__coltype__in=["book-series", "lecture-notes", "book-edited-book"], 

115 ) 

116 

117 

118def get_collection_of_thesis(): 

119 theses = Collection.objects.filter(sites__id=settings.SITE_ID, coltype="thesis") 

120 return theses.all() 

121 

122 

123def get_theses(): 

124 theses = Container.objects.filter(sites__id=settings.SITE_ID, my_collection__coltype="thesis") 

125 return theses.all() 

126 

127 

128# TODO require the provider in the get_ functions as it serves as a namespace 

129 

130 

131def get_collection(pid, sites=True, prefetch=False): 

132 try: 

133 if sites: 

134 col = Collection.objects.get(pid=pid, sites__id=settings.SITE_ID) 

135 else: 

136 col = Collection.objects.get(pid=pid) 

137 except Collection.DoesNotExist: 

138 col = None 

139 return col 

140 

141 

142def get_volumes_in_collection(collection): 

143 """ 

144 used by issue-list.html and oai gallica 

145 return list of issues by volume if volume_int exist or by date 

146 return list of publishers GROUP BY name with date 

147 @param collection: 

148 @return: 

149 

150 """ 

151 

152 items = ( 

153 collection.content.filter(sites__id=settings.SITE_ID) 

154 .exclude(ctype="issue_special") 

155 .order_by("-vseries_int", "-year", "-volume_int", "number_int") 

156 .all() 

157 ) 

158 

159 if collection.collectionmembership_set.count() > 0: 159 ↛ 160line 159 didn't jump to line 160

160 col_membsership_qs = ( 

161 collection.collectionmembership_set.filter(container__sites__id=settings.SITE_ID) 

162 .exclude(ctype="issue_special") 

163 .order_by("-vseries_int", "-volume_int", "number_int") 

164 .all() 

165 ) 

166 joined = itertools.chain(items, col_membsership_qs) 

167 

168 def sorter(dict_): 

169 return ( 

170 dict_.vseries_int, 

171 dict_.year if hasattr(dict_, "year") else dict_.container.year, 

172 dict_.volume_int, 

173 dict_.number_int, 

174 ) 

175 

176 items = sorted(joined, key=sorter, reverse=True) 

177 

178 # items is now a collection of Container and/or CollectionMembership 

179 

180 issue_to_appear_pid = "" 

181 if hasattr(settings, "ISSUE_TO_APPEAR_PID"): 181 ↛ 182line 181 didn't jump to line 182 because the condition on line 181 was never true

182 issue_to_appear_pid = settings.ISSUE_TO_APPEAR_PID 

183 

184 issues_in_vseries = [] 

185 volumes_in_vseries = [] 

186 issues_in_volume = [] 

187 publishers = [] 

188 results_vseries = "-1" 

189 results_volume = "-1" 

190 results_year = "-1" 

191 results_fyear = results_lyear = -1 

192 volume_count = 0 

193 max_volume_count = 0 

194 max_width = 0 

195 width = 0 

196 for item in items: 

197 width += len(item.number) 

198 if hasattr(item, "container"): 198 ↛ 213line 198 didn't jump to line 213 because the condition on line 198 was always true

199 issue = item.container 

200 # The issue-list template use issue properties to display the list of issues 

201 # Replace the values with those of the CollectionMembership for the display 

202 issue.veries = item.vseries 

203 issue.volume = item.volume 

204 issue.number = item.number 

205 issue.vseries_int = item.vseries_int 

206 issue.volume_int = item.volume_int 

207 issue.number_int = item.number_int 

208 

209 year = issue.year 

210 vseries = item.vseries 

211 volume = item.volume 

212 else: 

213 issue = item 

214 year = issue.year 

215 vseries = issue.vseries 

216 volume = issue.volume 

217 

218 if issue.pid != issue_to_appear_pid: 218 ↛ 196line 218 didn't jump to line 196 because the condition on line 218 was always true

219 fyear, lyear = get_first_last_years(year) 

220 fyear = int(fyear) 

221 lyear = int(lyear) 

222 

223 # new volume found, we need to add issues_in_volume in the current volumes_in_veries 

224 if ( 224 ↛ 254line 224 didn't jump to line 254

225 results_volume != volume 

226 or (results_volume == "" and results_year != year) 

227 # or (results_volume == volume and results_year != year) 

228 ): 

229 # The first time, we simply add the issue in issues_in_volume (see below) 

230 # But we do not append in volumes_in_vseries 

231 if results_volume != "-1": 231 ↛ 232line 231 didn't jump to line 232 because the condition on line 231 was never true

232 volumes_in_vseries.append( 

233 { 

234 "volume": results_volume, 

235 "fyear": results_fyear, 

236 "lyear": results_lyear, 

237 "issues": issues_in_volume, 

238 } 

239 ) 

240 # Clear issues_in_volume to prepare a new volume 

241 issues_in_volume = [] 

242 

243 # Set the current volume info 

244 results_volume = volume 

245 results_year = year 

246 results_fyear = fyear 

247 results_lyear = lyear 

248 volume_count += 1 

249 if width > max_width: 249 ↛ 251line 249 didn't jump to line 251 because the condition on line 249 was always true

250 max_width = width 

251 width = 0 

252 

253 # New vseries found, we need to add volumes_in_vseries to the current vseries 

254 if results_vseries != vseries: 254 ↛ 266line 254 didn't jump to line 266 because the condition on line 254 was always true

255 # The first time, we do not append in issues_in_vseries. 

256 # We simply set the vseries info and add the issues in issues_in_volume below 

257 if results_vseries != "-1": 257 ↛ 258line 257 didn't jump to line 258 because the condition on line 257 was never true

258 issues_in_vseries.append( 

259 {"vseries": results_vseries, "volumes": volumes_in_vseries} 

260 ) 

261 volumes_in_vseries = [] 

262 results_vseries = vseries 

263 max_volume_count = max(0, volume_count) 

264 volume_count = 0 

265 

266 issues_in_volume.append(issue) 

267 

268 # we have to create a list of publishers with date - for Gallica OAI 

269 if issue.my_publisher: 269 ↛ 196line 269 didn't jump to line 196 because the condition on line 269 was always true

270 if publishers: 270 ↛ 271line 270 didn't jump to line 271 because the condition on line 270 was never true

271 item = publishers[-1] 

272 if issue.my_publisher.pub_name != item["name"]: 

273 item = { 

274 "name": issue.my_publisher.pub_name, 

275 "fyear": fyear, 

276 "lyear": lyear, 

277 } 

278 publishers.append(item) 

279 else: 

280 if fyear < item["fyear"]: 

281 item["fyear"] = fyear 

282 if lyear > item["lyear"]: 

283 item["lyear"] = lyear 

284 else: 

285 publishers.insert( 

286 0, {"name": issue.my_publisher.pub_name, "fyear": fyear, "lyear": lyear} 

287 ) 

288 

289 # At the end of the loop, we need to append the remaining issues_in_volume 

290 # then volumes_in_vseries 

291 if results_volume != "-1" and issues_in_volume: 291 ↛ 302line 291 didn't jump to line 302 because the condition on line 291 was always true

292 volumes_in_vseries.append( 

293 { 

294 "volume": results_volume, 

295 "fyear": results_fyear, 

296 "lyear": results_lyear, 

297 "issues": issues_in_volume, 

298 } 

299 ) 

300 # volume_count += 1 

301 

302 if results_vseries != "-1" and volumes_in_vseries: 302 ↛ 306line 302 didn't jump to line 306

303 issues_in_vseries.append({"vseries": results_vseries, "volumes": volumes_in_vseries}) 

304 max_volume_count = max(0, volume_count) 

305 

306 context = { 

307 "sorted_issues": issues_in_vseries, 

308 "volume_count": max_volume_count, 

309 "publishers": publishers, 

310 "max_width": max_width, 

311 } 

312 

313 return context 

314 

315 

316def get_container(pid, prefetch=False, sites=True): 

317 try: 

318 if prefetch: 

319 container = ( 

320 Container.objects.filter(sites__id=settings.SITE_ID, pid=pid) 

321 .prefetch_for_toc() 

322 .first() 

323 ) 

324 else: 

325 if sites: 325 ↛ 328line 325 didn't jump to line 328 because the condition on line 325 was always true

326 container = Container.objects.get(sites__id=settings.SITE_ID, pid=pid) 

327 else: 

328 container = Container.objects.get(pid=pid) 

329 

330 except Container.DoesNotExist: 

331 container = None 

332 return container 

333 

334 

335def get_book_serie(pid): 

336 try: 

337 book_serie = Collection.objects.get( 

338 pid=pid, coltype="book-series", sites__id=settings.SITE_ID 

339 ) 

340 except Collection.DoesNotExist: 

341 book_serie = None 

342 return book_serie 

343 

344 

345def get_issues_count_in_collection(pid): 

346 try: 

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

348 issues = Container.objects.filter(my_collection=collection).count() 

349 return issues 

350 except Exception: 

351 pass 

352 

353 

354def get_issues_in_volume(vid, is_cr=False, general_articles=False): 

355 # 08/09/2022: vid is no longer built (see get_vid in models.py) 

356 # It is now the pid of the first issue of the volume 

357 first_issue = get_container(vid) 

358 if first_issue is None: 

359 raise Http404 

360 

361 collection = first_issue.get_collection() 

362 year = first_issue.year 

363 vseries = first_issue.vseries 

364 volume = first_issue.volume 

365 

366 if is_cr: 

367 year_int = int(year) 

368 if year_int > 2020 and collection.pid not in ["CRMATH", "CRBIOL"]: 368 ↛ 371line 368 didn't jump to line 371 because the condition on line 368 was never true

369 # CRAS: Les thématiques à partir de 2021 ont un number en "T1", "T2",... 

370 # On trie par number pour avoir les thématiques isolés des autres 

371 queryset = Container.objects.order_by("number") 

372 elif year_int > 2022 and collection.pid == "CRBIOL": 

373 queryset = Container.objects.order_by("number") 

374 else: 

375 queryset = Container.objects.order_by("number_int") 

376 if general_articles: 

377 queryset = queryset.filter(title_html="") 

378 else: 

379 queryset = Container.objects.order_by("number_int") 

380 queryset = queryset.filter( 

381 my_collection__pid=collection.pid, year=year, vseries=vseries, volume=volume 

382 ).prefetch_for_toc() 

383 issues = get_list_or_404(queryset) 

384 

385 if is_cr and ( 

386 (year_int > 2020 and collection.pid != "CRBIOL") 

387 or (year_int > 2022 and collection.pid == "CRBIOL") 

388 ): 

389 issues_articles = [] 

390 grouped_articles = [] 

391 grouped_issue_articles = {"issue": None, "articles": grouped_articles} 

392 for issue in issues: 

393 if len(issue.title_html) == 0: 393 ↛ 397line 393 didn't jump to line 397 because the condition on line 393 was always true

394 grouped_articles.extend(issue.article_set.all().order_by_sequence()) 

395 grouped_issue_articles["issue"] = issue 

396 else: 

397 issues_articles.append( 

398 { 

399 "issue": issue, 

400 "articles": issue.article_set.all().order_by_published_date() 

401 if settings.SORT_ARTICLES_BY_DATE 

402 else issue.article_set.all().order_by_sequence(), 

403 } 

404 ) 

405 if grouped_issue_articles["issue"] is not None: 405 ↛ 418line 405 didn't jump to line 418 because the condition on line 405 was always true

406 issues_articles.insert(0, grouped_issue_articles) 

407 else: 

408 issues_articles = [ 

409 { 

410 "issue": issue, 

411 "articles": issue.article_set.all().order_by_published_date() 

412 if settings.SORT_ARTICLES_BY_DATE 

413 else issue.article_set.all().order_by_sequence(), 

414 } 

415 for issue in issues 

416 ] 

417 

418 return issues_articles, collection 

419 

420 

421def get_resource_in_special_issue_by_doi(doi): 

422 try: 

423 resource_in_special_issue = ResourceInSpecialIssue.objects.get(resource_doi=doi) 

424 except ResourceInSpecialIssue.DoesNotExist: 

425 resource_in_special_issue = None 

426 return resource_in_special_issue 

427 

428 

429def get_article(pid: str, prefetch=False, sites=True) -> Article | None: 

430 try: 

431 if prefetch: 

432 article = ( 

433 Article.objects.filter(sites__id=settings.SITE_ID, pid=pid).prefetch_all().first() 

434 ) 

435 else: 

436 if sites: 436 ↛ 439line 436 didn't jump to line 439 because the condition on line 436 was always true

437 article = Article.objects.get(sites__id=settings.SITE_ID, pid=pid) 

438 else: 

439 article = Article.objects.get(pid=pid) 

440 

441 except Article.DoesNotExist: 

442 article = None 

443 return article 

444 

445 

446def get_article_by_doi(doi, prefetch=False): 

447 try: 

448 if prefetch: 

449 article = ( 

450 Article.objects.filter(sites__id=settings.SITE_ID, doi=doi).prefetch_all().first() 

451 ) 

452 else: 

453 article = Article.objects.get(sites__id=settings.SITE_ID, doi=doi) 

454 

455 except Article.DoesNotExist: 

456 article = None 

457 return article 

458 

459 

460def get_articles(): 

461 article_qs = Article.objects.filter(sites__id=settings.SITE_ID).exclude( 

462 classname="TranslatedArticle" 

463 ) 

464 return article_qs 

465 

466 

467def get_articles_by_deployed_date(): 

468 sitemembership_qs = SiteMembership.objects.filter( 

469 site__id=settings.SITE_ID, resource__classname="Article" 

470 ).order_by("-deployed", "-seq") 

471 

472 articles = [sm.resource.cast() for sm in sitemembership_qs] 

473 return articles 

474 

475 

476def get_articles_by_published_date(): 

477 article_qs = Article.objects.filter(sites__id=settings.SITE_ID).exclude( 

478 classname="TranslatedArticle" 

479 ) 

480 if hasattr(settings, "ISSUE_TO_APPEAR_PID"): 

481 article_qs = article_qs.exclude(my_container__pid=settings.ISSUE_TO_APPEAR_PID) 

482 article_qs = article_qs.order_by("-date_published", "-seq") 

483 

484 return article_qs 

485 

486 

487def get_xmlbase(base): 

488 try: 

489 xmlbase = XmlBase.objects.get(base=base) 

490 except XmlBase.DoesNotExist: 

491 xmlbase = None 

492 return xmlbase 

493 

494 

495# RelationName are created with a fixture (see app/ptf/apps/ptf/fixtures/initial_data.json 

496# Example { "left" : "follows", "right" : "followed-by" } 

497# A related-article of an article has 1 relation name (ex "follows" or "followed-by") 

498# You need to know if the relation was stored in the left or right attribute of a RelationName, 

499# so that you can create/search the Relationship with the correct object/subject. 

500# Ex: with A "follows" B, A is the subject and B the object because "follows" is a RelationName.left attribute 

501# with A "followed-by" B, A is the object the B the subject because 

502# "followed-by" is a RelationName.right attribute 

503def get_relationname_left(left_name): 

504 try: 

505 relationname = RelationName.objects.get(left=left_name) 

506 except RelationName.DoesNotExist: 

507 relationname = None 

508 

509 return relationname 

510 

511 

512def get_relationname_right(right_name): 

513 try: 

514 relationname = RelationName.objects.get(right=right_name) 

515 except RelationName.DoesNotExist: 

516 relationname = None 

517 

518 return relationname 

519 

520 

521# See comments about RelationName above 

522def get_relationship(subject_pid, object_pid, relationname): 

523 try: 

524 relationship = Relationship.objects.get( 

525 subject_pid=subject_pid, object_pid=object_pid, rel_info=relationname 

526 ) 

527 except Relationship.DoesNotExist: 

528 relationship = None 

529 

530 return relationship 

531 

532 

533def get_extid(resource, id_type): 

534 extid = None 

535 extids = ExtId.objects.filter(resource=resource, id_type=id_type) 

536 if extids.count() > 0: 

537 extid = extids.first() 

538 

539 return extid 

540 

541 

542def get_bibitemid(bibitem, id_type): 

543 bibitemid = None 

544 bibitemids = BibItemId.objects.filter(bibitem=bibitem, id_type=id_type) 

545 if bibitemids.count() > 0: 545 ↛ 548line 545 didn't jump to line 548 because the condition on line 545 was always true

546 bibitemid = bibitemids.first() 

547 

548 return bibitemid 

549 

550 

551def get_bibitem_by_seq(article, seq): 

552 try: 

553 bibitem = article.bibitem_set.get(sequence=seq) 

554 except BibItem.DoesNotExist: 

555 bibitem = None 

556 return bibitem 

557 

558 

559def get_extlink(**filters): 

560 try: 

561 extlink = ExtLink.objects.get(**filters) 

562 except ExtLink.DoesNotExist: 

563 extlink = None 

564 return extlink 

565 

566 

567def get_related_object(**filters): 

568 """ 

569 Return RelatedObject with filters pass by params (all are optionals) 

570 resource, base, rel, mimetype, location, metadata, seq 

571 Check models.py for the params of a RelatedObject 

572 """ 

573 try: 

574 related_object = RelatedObject.objects.get(**filters) 

575 related_object.select_related() 

576 except RelatedObject.DoesNotExist: 

577 related_object = None 

578 return related_object 

579 

580 

581def get_authors_by_letter(first_letter): 

582 try: 

583 authors = Author.objects.filter(first_letter=first_letter).order_by("name") 

584 except Author.DoesNotExist: 

585 authors = None 

586 return authors 

587 

588 

589def make_key(string): 

590 n_string = unicodedata.normalize("NFKD", string).encode("ascii", "ignore").decode("ascii") 

591 n_string = re.sub(r"[^\w\s-]", "", n_string).strip().lower() 

592 n_string = re.sub(r"[-\s]+", "-", n_string) 

593 if len(n_string) > 64: 

594 n_string = n_string[:64] 

595 

596 return n_string if n_string else unidecode(string) 

597 

598 

599def get_resource(pid: str, prefetch=False) -> Resource | None: 

600 try: 

601 if prefetch: 

602 resource = ( 

603 Resource.objects.filter(sites__id=settings.SITE_ID, pid=pid).prefetch_all().first() 

604 ) 

605 else: 

606 resource = Resource.objects.get(pid=pid, sites__id=settings.SITE_ID) 

607 except Resource.DoesNotExist: 

608 resource = None 

609 return resource 

610 

611 

612def get_resource_by_doi(doi, prefetch=False): 

613 try: 

614 if prefetch: 614 ↛ 615line 614 didn't jump to line 615

615 resource = ( 

616 Resource.objects.filter(sites__id=settings.SITE_ID, doi=doi).prefetch_all().first() 

617 ) 

618 else: 

619 resource = Resource.objects.get(sites__id=settings.SITE_ID, doi=doi) 

620 

621 except Resource.DoesNotExist: 

622 resource = None 

623 return resource 

624 

625 

626def get_random_containers(): 

627 # TODO get the newest containers only 

628 

629 containers = Container.objects.all() 

630 random_list = random.sample(containers, 6) 

631 

632 return random_list 

633 

634 

635def parse_date_str(date_str): 

636 """ 

637 @param date_str:a string representing a date. Ex: "2017-01-10T18:24:58.202+01:00", "2017-05-03" 

638 @return:a localized datetime object (localized means that the date has a timezone) 

639 """ 

640 the_date = dateutil.parser.parse(date_str) 

641 if not timezone.is_aware(the_date): 

642 the_date = timezone.make_aware(the_date, datetime.UTC) 

643 return the_date 

644 

645 

646def get_issue_to_appear(colid): 

647 """ 

648 Some journals want to display "articles to appear" with articles that have been accepted but are not yet 

649 finalized (pages start at 1). ex: AIF 

650 :param pid: 

651 :return: The container object of articles to appear 

652 """ 

653 pid = "" 

654 

655 if hasattr(settings, "ISSUE_TO_APPEAR_PIDS"): 

656 if colid in settings.ISSUE_TO_APPEAR_PIDS: 

657 pid = settings.ISSUE_TO_APPEAR_PIDS[colid] 

658 

659 container = get_container(pid=pid, prefetch=True) 

660 return container 

661 

662 

663def get_number_from_doi(doi): 

664 value = 0 

665 

666 try: 

667 index = doi.rfind(".") 

668 index += 1 

669 if index > 0: 

670 str_value = doi[index:] 

671 value = int(str_value) 

672 except BaseException: 

673 pass 

674 

675 return value 

676 

677 

678def get_site_mersenne(collection_pid): 

679 key = collection_pid.lower() 

680 

681 # TODO refactor smai-jcm, centre_mersenne to have collection_pid == key 

682 # Do not use a find here, we want an access time in O(1) 

683 if key == "smai-jcm": 683 ↛ 684line 683 didn't jump to line 684 because the condition on line 683 was never true

684 key = "smai" 

685 elif key == "mersenne": 685 ↛ 686line 685 didn't jump to line 686 because the condition on line 685 was never true

686 key = "centre_mersenne" 

687 elif key == "malsm": 687 ↛ 688line 687 didn't jump to line 688 because the condition on line 687 was never true

688 key = "mbk" 

689 

690 try: 

691 site_item = settings.SITE_REGISTER[key] 

692 except KeyError: 

693 return None 

694 site_id = site_item["site_id"] 

695 site_acro = key 

696 

697 return get_or_create_site(site_id, site_acro) 

698 

699 

700########################################################################## 

701# 

702# Update functions 

703# 

704########################################################################## 

705def post_resource_updated(resource): 

706 """ 

707 A resource is modified (ex: matching), the last_modified date of its container has to be updated. 

708 :param resource: 

709 :return: 

710 """ 

711 obj = resource.cast() 

712 container = obj.get_container() 

713 if container: 713 ↛ exitline 713 didn't return from function 'post_resource_updated' because the condition on line 713 was always true

714 container.last_modified = timezone.now() 

715 container.save() 

716 

717 

718def update_deployed_date(resource, site, deployed_date_in_prod_to_restore=None, file_=None): 

719 """ 

720 Used by ptf_tools during DeployJatsIssue 

721 

722 Update the SiteMembership deployed_date of container/site based on the production website. 

723 - If there is no deployed_date in ptf_tools (not yet in prod), we create one. 

724 - with deployed_date_in_prod if it's not None (case when we restore data), or 

725 - with now if deployed_date_in_prod is None (first deploy in prod) 

726 - If the last_modified date of the container in ptf_tools is > deployed_date_in_prod 

727 (we have a new version in ptf_tools), we update deployed_date_in_prod with now(), 

728 - else we update deployed_date with deployed_date_in_prod 

729 (Normally, they should be equal) 

730 

731 :param resource: 

732 :param site: 

733 :param deployed_date_in_prod_to_restore: 

734 :param file_ file object to log info 

735 :return: 

736 """ 

737 

738 def get_deployed_date_in_prod(resource_, site_): 

739 deployed_date_in_prod = None 

740 try: 

741 membership = SiteMembership.objects.get(resource=resource_, site=site_) 

742 deployed_date_in_prod = membership.deployed 

743 except SiteMembership.DoesNotExist: 

744 pass 

745 

746 return deployed_date_in_prod 

747 

748 def update_or_create(resource_, site_, deployed): 

749 try: 

750 membership = SiteMembership.objects.get(resource=resource_, site=site_) 

751 membership.deployed = deployed 

752 except SiteMembership.DoesNotExist: 

753 membership = SiteMembership(resource=resource_, site=site_, deployed=deployed) 

754 membership.save() 

755 

756 container = article = None 

757 

758 if resource.classname == "Article": 758 ↛ 759line 758 didn't jump to line 759 because the condition on line 758 was never true

759 article = resource 

760 container = article.my_container 

761 else: 

762 container = resource 

763 

764 existing_deployed_date = get_deployed_date_in_prod(container, site) 

765 

766 # If we restore deployed_date, force the new value to the restored value 

767 if deployed_date_in_prod_to_restore: 

768 new_deployed_date = deployed_date_in_prod_to_restore 

769 else: 

770 # Get the existing deployed_date_in_prod (from SiteMembership) 

771 new_deployed_date = existing_deployed_date 

772 

773 # If there is no value of if the current version (last_modified) is newer, update the date 

774 if new_deployed_date is None or container.last_modified > new_deployed_date: 774 ↛ 779line 774 didn't jump to line 779 because the condition on line 774 was always true

775 new_deployed_date = timezone.now() 

776 

777 # Set the new value to the entire container/articles (+ collection) 

778 

779 if file_: 779 ↛ 780line 779 didn't jump to line 780 because the condition on line 779 was never true

780 file_.write( 

781 "{}. Date to restore: {}. Container.last_modified: {}, Existing date {}. New date {}\n".format( 

782 container.pid, 

783 deployed_date_in_prod_to_restore, 

784 container.last_modified, 

785 existing_deployed_date, 

786 new_deployed_date, 

787 ) 

788 ) 

789 

790 update_or_create(container, site, new_deployed_date) 

791 update_or_create(container.get_collection(), site, new_deployed_date) 

792 

793 if article is not None: 793 ↛ 794line 793 didn't jump to line 794 because the condition on line 793 was never true

794 update_or_create(article, site, new_deployed_date) 

795 else: 

796 for article in container.article_set.all(): 

797 update_or_create(article, site, new_deployed_date) 

798 

799 

800def assign_doi(pid): 

801 """ 

802 In the Mersenne process, articles imported for the first time receive a DOI. 

803 Thus function creates a new DOI, based on the last doi stored in the Collection object. 

804 :param pid: 

805 :return: A new DOI, equal to 10.5802/@pid.(last_doi + 1) 

806 """ 

807 collection = get_collection(pid) 

808 

809 if collection is None: 809 ↛ 810line 809 didn't jump to line 810 because the condition on line 809 was never true

810 return None 

811 

812 last_doi = collection.last_doi + 1 

813 collection.last_doi = last_doi 

814 collection.save() 

815 

816 doi = "10.5802/" + pid.lower() + "." + str(last_doi) 

817 return doi 

818 

819 

820# TODO make a command ? 

821 

822 

823def add_or_update_extid( 

824 resource, id_type, id_value, checked, false_positive, update_last_modified=True 

825): 

826 from ptf.cmds import database_cmds 

827 

828 if id_value: 828 ↛ exitline 828 didn't return from function 'add_or_update_extid' because the condition on line 828 was always true

829 extid = get_extid(resource, id_type) 

830 if extid: 

831 if not extid.checked: 831 ↛ 832line 831 didn't jump to line 832 because the condition on line 831 was never true

832 extid.id_value = id_value 

833 extid.checked = checked 

834 extid.false_positive = false_positive 

835 extid.save() 

836 else: 

837 cmd = database_cmds.addExtIdDatabaseCmd( 

838 { 

839 "id_type": id_type, 

840 "id_value": id_value, 

841 "checked": checked, 

842 "false_positive": false_positive, 

843 } 

844 ) 

845 cmd.set_resource(resource) 

846 cmd.do() 

847 

848 # last_modified is not modified during data restoration (importExtraDataPtfCmd) 

849 if update_last_modified: 849 ↛ 850line 849 didn't jump to line 850 because the condition on line 849 was never true

850 post_resource_updated(resource) 

851 

852 

853def add_or_update_bibitemid( 

854 bibitem, id_type, id_value, checked, false_positive, update_last_modified=True 

855): 

856 from ptf.cmds import database_cmds 

857 from ptf.cmds import xml_cmds 

858 

859 if id_value: 859 ↛ exitline 859 didn't return from function 'add_or_update_bibitemid' because the condition on line 859 was always true

860 bibitemid = get_bibitemid(bibitem, id_type) 

861 if bibitemid: 861 ↛ 867line 861 didn't jump to line 867 because the condition on line 861 was always true

862 bibitemid.id_value = id_value 

863 bibitemid.checked = checked 

864 bibitemid.false_positive = false_positive 

865 bibitemid.save() 

866 else: 

867 cmd = database_cmds.addBibItemIdDatabaseCmd( 

868 { 

869 "id_type": id_type, 

870 "id_value": id_value, 

871 "checked": checked, 

872 "false_positive": false_positive, 

873 } 

874 ) 

875 cmd.set_bibitem(bibitem) 

876 cmd.do() 

877 

878 # Update citation_xml|html|tex 

879 cmd = xml_cmds.updateBibitemCitationXmlCmd() 

880 cmd.set_bibitem(bibitem) 

881 cmd.do() 

882 

883 # last_modified is not modified during data restoration (importExtraDataPtfCmd) 

884 if update_last_modified: 

885 post_resource_updated(bibitem.resource) 

886 

887 

888def get_site_id(collection_id): 

889 result = [v for k, v in SITE_REGISTER.items() if v["collection_pid"] == collection_id] 

890 return result[0]["site_id"] if result else "" 

891 

892 

893def get_collection_id(site_id): 

894 result = [v for k, v in SITE_REGISTER.items() if v["site_id"] == site_id] 

895 return result[0]["collection_pid"] if result else "" 

896 

897 

898def is_site_en_only(site_id): 

899 result = [v for k, v in SITE_REGISTER.items() if v["site_id"] == site_id] 

900 return result[0]["en_only"] if result else False 

901 

902 

903def is_site_fr_only(site_id): 

904 result = [v for k, v in SITE_REGISTER.items() if v["site_id"] == site_id] 

905 return result[0]["fr_only"] if result and "fr_only" in result[0] else False