From 8315c665bd28a97fa799d98b2f7eff69c5ceae72 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Mon, 20 May 2024 10:21:52 -0300 Subject: [PATCH] feat: copy 1wg-charters files into place (#7431) * feat: copy 1wg-charters* into other places * test: update test * test: test no-copy operation * style: Black * fix: Skip copy if dest is a non-dir * chore: de-lint --- ietf/group/tasks.py | 34 ++++++++++++++++-- ietf/group/tests_info.py | 75 ++++++++++++++++++++++++++++++++++++---- ietf/settings.py | 1 + 3 files changed, 100 insertions(+), 10 deletions(-) diff --git a/ietf/group/tasks.py b/ietf/group/tasks.py index c35674ac3..f7717616d 100644 --- a/ietf/group/tasks.py +++ b/ietf/group/tasks.py @@ -2,12 +2,16 @@ # # Celery task definitions # +import shutil + from celery import shared_task from pathlib import Path from django.conf import settings from django.template.loader import render_to_string +from ietf.utils import log + from .models import Group from .utils import fill_in_charter_info, fill_in_wg_drafts, fill_in_wg_roles @@ -15,7 +19,11 @@ from .utils import fill_in_charter_info, fill_in_wg_drafts, fill_in_wg_roles @shared_task def generate_wg_charters_files_task(): areas = Group.objects.filter(type="area", state="active").order_by("name") - groups = Group.objects.filter(type="wg", state="active").exclude(parent=None).order_by("acronym") + groups = ( + Group.objects.filter(type="wg", state="active") + .exclude(parent=None) + .order_by("acronym") + ) for group in groups: fill_in_charter_info(group) fill_in_wg_roles(group) @@ -23,11 +31,31 @@ def generate_wg_charters_files_task(): for area in areas: area.groups = [g for g in groups if g.parent_id == area.pk] charter_path = Path(settings.CHARTER_PATH) - (charter_path / "1wg-charters.txt").write_text( + charters_file = charter_path / "1wg-charters.txt" + charters_file.write_text( render_to_string("group/1wg-charters.txt", {"areas": areas}), encoding="utf8", ) - (charter_path / "1wg-charters-by-acronym.txt").write_text( + charters_by_acronym_file = charter_path / "1wg-charters-by-acronym.txt" + charters_by_acronym_file.write_text( render_to_string("group/1wg-charters-by-acronym.txt", {"groups": groups}), encoding="utf8", ) + + charter_copy_dest = getattr(settings, "CHARTER_COPY_PATH", None) + if charter_copy_dest is not None: + if not Path(charter_copy_dest).is_dir(): + log.log( + f"Error copying 1wg-charter files to {charter_copy_dest}: it does not exist or is not a directory" + ) + else: + try: + shutil.copy2(charters_file, charter_copy_dest) + except IOError as err: + log.log(f"Error copying {charters_file} to {charter_copy_dest}: {err}") + try: + shutil.copy2(charters_by_acronym_file, charter_copy_dest) + except IOError as err: + log.log( + f"Error copying {charters_by_acronym_file} to {charter_copy_dest}: {err}" + ) diff --git a/ietf/group/tests_info.py b/ietf/group/tests_info.py index 42171bd1b..777671db9 100644 --- a/ietf/group/tests_info.py +++ b/ietf/group/tests_info.py @@ -17,6 +17,7 @@ import debug # pyflakes:ignore from django.conf import settings from django.test import RequestFactory +from django.test.utils import override_settings from django.urls import reverse as urlreverse from django.urls import NoReverseMatch from django.utils import timezone @@ -57,7 +58,7 @@ def pklist(docs): return [ str(doc.pk) for doc in docs.all() ] class GroupPagesTests(TestCase): - settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['CHARTER_PATH'] + settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['CHARTER_PATH', 'CHARTER_COPY_PATH'] def test_active_groups(self): area = GroupFactory.create(type_id='area') @@ -170,28 +171,88 @@ class GroupPagesTests(TestCase): self.assertEqual(r.status_code, 404) def test_generate_wg_charters_files_task(self): - group = CharterFactory(group__type_id='wg',group__parent=GroupFactory(type_id='area')).group - RoleFactory(group=group,name_id='chair',person=PersonFactory()) - RoleFactory(group=group,name_id='ad',person=PersonFactory()) + group = CharterFactory( + group__type_id="wg", group__parent=GroupFactory(type_id="area") + ).group + RoleFactory(group=group, name_id="chair", person=PersonFactory()) + RoleFactory(group=group, name_id="ad", person=PersonFactory()) chair = Email.objects.filter(role__group=group, role__name="chair")[0] ( Path(settings.CHARTER_PATH) / f"{group.charter.name}-{group.charter.rev}.txt" - ).write_text("This is a charter.") + ).write_text("This is a charter.") generate_wg_charters_files_task() - wg_charters_contents = (Path(settings.CHARTER_PATH) / "1wg-charters.txt").read_text(encoding="utf8") + wg_charters_contents = (Path(settings.CHARTER_PATH) / "1wg-charters.txt").read_text( + encoding="utf8" + ) self.assertIn(group.acronym, wg_charters_contents) self.assertIn(group.name, wg_charters_contents) self.assertIn(group.ad_role().person.plain_name(), wg_charters_contents) self.assertIn(chair.address, wg_charters_contents) self.assertIn("This is a charter.", wg_charters_contents) + wg_charters_copy = ( + Path(settings.CHARTER_COPY_PATH) / "1wg-charters.txt" + ).read_text(encoding="utf8") + self.assertEqual(wg_charters_copy, wg_charters_contents) - wg_charters_by_acronym_contents = (Path(settings.CHARTER_PATH) / "1wg-charters-by-acronym.txt").read_text(encoding="utf8") + wg_charters_by_acronym_contents = ( + Path(settings.CHARTER_PATH) / "1wg-charters-by-acronym.txt" + ).read_text(encoding="utf8") self.assertIn(group.acronym, wg_charters_by_acronym_contents) self.assertIn(group.name, wg_charters_by_acronym_contents) self.assertIn(group.ad_role().person.plain_name(), wg_charters_by_acronym_contents) self.assertIn(chair.address, wg_charters_by_acronym_contents) self.assertIn("This is a charter.", wg_charters_by_acronym_contents) + wg_charters_by_acronymcopy = ( + Path(settings.CHARTER_COPY_PATH) / "1wg-charters-by-acronym.txt" + ).read_text(encoding="utf8") + self.assertEqual(wg_charters_by_acronymcopy, wg_charters_by_acronym_contents) + + def test_generate_wg_charters_files_task_without_copy(self): + """Test disabling charter file copying + + Note that these tests mostly check that errors are not encountered. Because they unset + the CHARTER_COPY_PATH or set it to a non-directory destination, it's not clear where to + look to see whether the files were (incorrectly) copied somewhere. + """ + group = CharterFactory( + group__type_id="wg", group__parent=GroupFactory(type_id="area") + ).group + ( + Path(settings.CHARTER_PATH) / f"{group.charter.name}-{group.charter.rev}.txt" + ).write_text("This is a charter.") + + # No directory set + with override_settings(): + del settings.CHARTER_COPY_PATH + generate_wg_charters_files_task() + # n.b., CHARTER_COPY_PATH is set again outside the with block + self.assertTrue((Path(settings.CHARTER_PATH) / "1wg-charters.txt").exists()) + self.assertFalse((Path(settings.CHARTER_COPY_PATH) / "1wg-charters.txt").exists()) + self.assertTrue( + (Path(settings.CHARTER_PATH) / "1wg-charters-by-acronym.txt").exists() + ) + self.assertFalse( + (Path(settings.CHARTER_COPY_PATH) / "1wg-charters-by-acronym.txt").exists() + ) + (Path(settings.CHARTER_PATH) / "1wg-charters.txt").unlink() + (Path(settings.CHARTER_PATH) / "1wg-charters-by-acronym.txt").unlink() + + # Set to a file, not a directory + not_a_dir = Path(settings.CHARTER_COPY_PATH) / "not-a-dir.txt" + not_a_dir.write_text("Not a dir") + with override_settings(CHARTER_COPY_PATH=str(not_a_dir)): + generate_wg_charters_files_task() + # n.b., CHARTER_COPY_PATH is set again outside the with block + self.assertTrue((Path(settings.CHARTER_PATH) / "1wg-charters.txt").exists()) + self.assertFalse((Path(settings.CHARTER_COPY_PATH) / "1wg-charters.txt").exists()) + self.assertTrue( + (Path(settings.CHARTER_PATH) / "1wg-charters-by-acronym.txt").exists() + ) + self.assertFalse( + (Path(settings.CHARTER_COPY_PATH) / "1wg-charters-by-acronym.txt").exists() + ) + self.assertEqual(not_a_dir.read_text(), "Not a dir") def test_chartering_groups(self): group = CharterFactory(group__type_id='wg',group__parent=GroupFactory(type_id='area'),states=[('charter','intrev')]).group diff --git a/ietf/settings.py b/ietf/settings.py index 91c1ef205..8bb264bd6 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -670,6 +670,7 @@ INTERNET_DRAFT_PATH = '/a/ietfdata/doc/draft/repository' INTERNET_DRAFT_PDF_PATH = '/a/www/ietf-datatracker/pdf/' RFC_PATH = '/a/www/ietf-ftp/rfc/' CHARTER_PATH = '/a/ietfdata/doc/charter/' +CHARTER_COPY_PATH = '/a/www/ietf-ftp/ietf' # copy 1wg-charters files here if set BOFREQ_PATH = '/a/ietfdata/doc/bofreq/' CONFLICT_REVIEW_PATH = '/a/ietfdata/doc/conflict-review' STATUS_CHANGE_PATH = '/a/ietfdata/doc/status-change'