refactor: Do not use canonical_name() for charters (#5818)

* fix: Enforce naming of charter docs in submit()

* style: Reformat submit() with Black

* refactor: Remove redundant check of charter name

* style: Reformat charter_with_milestones_txt with Black

* refactor: Drop canonical_name, use Path in charter_with_milestones_txt

* style: Reformat review_announcement_text() with Black

* style: Reformat action_announcement_text() with Black

* refactor: Change uses of charter.canonical_name() to charter.name

* refactor: Skip docialias when retrieving charter

* refactor: Change canonical_name() to name in utils_charter.py

* refactor: Use Path in read_charter_text()

* refactor: Drop canonical_name, minor refactor of tests_charter.py

* refactor: charter.name instead of canonical_name in milestones.py

* refactor: charter.name instead of canonical_name in tests_info.py

* refactor: Remove unused functions in ietf/secr/utils/groups.py

* refactor: charter.canonical_name -> charter.name in templates

* refactor: Remove charter handling from canonical_name

Temporarily raise an exception for testing

* refactor: Refactor get_charter_text() without canonical_name

* refactor: Remove raise when canonical_name called on a charter

* fix: Add back missing ".txt" extension

* test: Test rejection of invalid charter names
This commit is contained in:
Jennifer Richards 2023-06-14 10:32:21 -03:00 committed by GitHub
parent 4eaaa264f7
commit c8dcda0fae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 256 additions and 168 deletions

View file

@ -856,12 +856,6 @@ class Document(DocumentInfo):
a = self.docalias.filter(name__startswith="rfc").order_by('-name').first()
if a:
name = a.name
elif self.type_id == "charter":
from ietf.doc.utils_charter import charter_name_for_group # Imported locally to avoid circular imports
try:
name = charter_name_for_group(self.chartered_group)
except Group.DoesNotExist:
pass
self._canonical_name = name
return self._canonical_name

View file

@ -88,10 +88,7 @@ class EditCharterTests(TestCase):
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['CHARTER_PATH']
def write_charter_file(self, charter):
with (Path(settings.CHARTER_PATH) /
("%s-%s.txt" % (charter.canonical_name(), charter.rev))
).open("w") as f:
f.write("This is a charter.")
(Path(settings.CHARTER_PATH) / f"{charter.name}-{charter.rev}.txt").write_text("This is a charter.")
def test_startstop_process(self):
CharterFactory(group__acronym='mars')
@ -509,8 +506,13 @@ class EditCharterTests(TestCase):
self.assertEqual(charter.rev, next_revision(prev_rev))
self.assertTrue("new_revision" in charter.latest_event().type)
with (Path(settings.CHARTER_PATH) / (charter.canonical_name() + "-" + charter.rev + ".txt")).open(encoding='utf-8') as f:
self.assertEqual(f.read(), "Windows line\nMac line\nUnix line\n" + utf_8_snippet.decode('utf-8'))
file_contents = (
Path(settings.CHARTER_PATH) / (charter.name + "-" + charter.rev + ".txt")
).read_text("utf-8")
self.assertEqual(
file_contents,
"Windows line\nMac line\nUnix line\n" + utf_8_snippet.decode("utf-8"),
)
def test_submit_initial_charter(self):
group = GroupFactory(type_id='wg',acronym='mars',list_email='mars-wg@ietf.org')
@ -538,6 +540,24 @@ class EditCharterTests(TestCase):
group = Group.objects.get(pk=group.pk)
self.assertEqual(group.charter, charter)
def test_submit_charter_with_invalid_name(self):
self.client.login(username="secretary", password="secretary+password")
ietf_group = GroupFactory(type_id="wg")
for bad_name in ("charter-irtf-{}", "charter-randomjunk-{}", "charter-ietf-thisisnotagroup"):
url = urlreverse("ietf.doc.views_charter.submit", kwargs={"name": bad_name.format(ietf_group.acronym)})
r = self.client.get(url)
self.assertEqual(r.status_code, 404, f"GET of charter named {bad_name} should 404")
r = self.client.post(url, {})
self.assertEqual(r.status_code, 404, f"POST of charter named {bad_name} should 404")
irtf_group = GroupFactory(type_id="rg")
for bad_name in ("charter-ietf-{}", "charter-whatisthis-{}", "charter-irtf-thisisnotagroup"):
url = urlreverse("ietf.doc.views_charter.submit", kwargs={"name": bad_name.format(irtf_group.acronym)})
r = self.client.get(url)
self.assertEqual(r.status_code, 404, f"GET of charter named {bad_name} should 404")
r = self.client.post(url, {})
self.assertEqual(r.status_code, 404, f"POST of charter named {bad_name} should 404")
def test_edit_review_announcement_text(self):
area = GroupFactory(type_id='area')
RoleFactory(name_id='ad',group=area,person=Person.objects.get(user__username='ad'))

View file

@ -3,11 +3,12 @@
import datetime
import io
import os
import re
import shutil
from pathlib import Path
from django.conf import settings
from django.urls import reverse as urlreverse
from django.template.loader import render_to_string
@ -62,10 +63,9 @@ def next_approved_revision(rev):
return "%#02d" % (int(m.group('major')) + 1)
def read_charter_text(doc):
filename = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev))
filename = Path(settings.CHARTER_PATH) / f"{doc.name}-{doc.rev}.txt"
try:
with io.open(filename, 'r') as f:
return f.read()
return filename.read_text()
except IOError:
return "Error: couldn't read charter text"
@ -92,8 +92,8 @@ def change_group_state_after_charter_approval(group, by):
def fix_charter_revision_after_approval(charter, by):
# according to spec, 00-02 becomes 01, so copy file and record new revision
try:
old = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), charter.rev))
new = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev)))
old = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.name, charter.rev))
new = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.name, next_approved_revision(charter.rev)))
shutil.copy(old, new)
except IOError:
log("There was an error copying %s to %s" % (old, new))
@ -101,7 +101,7 @@ def fix_charter_revision_after_approval(charter, by):
events = []
e = NewRevisionDocEvent(doc=charter, by=by, type="new_revision")
e.rev = next_approved_revision(charter.rev)
e.desc = "New version available: <b>%s-%s.txt</b>" % (charter.canonical_name(), e.rev)
e.desc = "New version available: <b>%s-%s.txt</b>" % (charter.name, e.rev)
e.save()
events.append(e)

View file

@ -3,11 +3,11 @@
import datetime
import io
import json
import os
import textwrap
from pathlib import Path
from django.http import HttpResponseRedirect, HttpResponseNotFound, Http404
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse as urlreverse
@ -32,7 +32,7 @@ from ietf.doc.utils_charter import ( historic_milestones_for_charter,
generate_ballot_writeup, generate_issue_ballot_mail, next_revision,
derive_new_work_text,
change_group_state_after_charter_approval, fix_charter_revision_after_approval,
split_charter_name)
split_charter_name, charter_name_for_group)
from ietf.doc.mails import email_state_changed, email_charter_internal_review
from ietf.group.mails import email_admin_re_charter
from ietf.group.models import Group, ChangeStateGroupEvent, MilestoneGroupEvent
@ -42,6 +42,7 @@ from ietf.ietfauth.utils import has_role, role_required
from ietf.name.models import GroupStateName
from ietf.person.models import Person
from ietf.utils.history import find_history_active_at
from ietf.utils.log import assertion
from ietf.utils.mail import send_mail_preformatted
from ietf.utils.textupload import get_cleaned_text_file_content
from ietf.utils.response import permission_denied
@ -362,38 +363,41 @@ class UploadForm(forms.Form):
@login_required
def submit(request, name, option=None):
if not name.startswith('charter-'):
raise Http404
# Charters are named "charter-<ietf|irtf>-<group acronym>"
charter = Document.objects.filter(type="charter", name=name).first()
if charter:
group = charter.group
charter_canonical_name = charter.canonical_name()
assertion("charter.name == charter_name_for_group(group)")
charter_rev = charter.rev
else:
top_org, group_acronym = split_charter_name(name)
group = get_object_or_404(Group, acronym=group_acronym)
charter_canonical_name = name
if name != charter_name_for_group(group):
raise Http404 # do not allow creation of misnamed charters
charter_rev = "00-00"
if not can_manage_all_groups_of_type(request.user, group.type_id) or not group.features.has_chartering_process:
if (
not can_manage_all_groups_of_type(request.user, group.type_id)
or not group.features.has_chartering_process
):
permission_denied(request, "You don't have permission to access this view.")
path = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (charter_canonical_name, charter_rev))
not_uploaded_yet = charter_rev.endswith("-00") and not os.path.exists(path)
charter_filename = Path(settings.CHARTER_PATH) / f"{name}-{charter_rev}.txt"
not_uploaded_yet = charter_rev.endswith("-00") and not charter_filename.exists()
if not_uploaded_yet or not charter:
# this case is special - we recently chartered or rechartered and have no file yet
next_rev = charter_rev
else:
# search history for possible collisions with abandoned efforts
prev_revs = list(charter.history_set.order_by('-time').values_list('rev', flat=True))
prev_revs = list(
charter.history_set.order_by("-time").values_list("rev", flat=True)
)
next_rev = next_revision(charter.rev)
while next_rev in prev_revs:
next_rev = next_revision(next_rev)
if request.method == 'POST':
if request.method == "POST":
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
# Also save group history so we can search for it
@ -408,9 +412,11 @@ def submit(request, name, option=None):
abstract=group.name,
rev=next_rev,
)
DocAlias.objects.create(name=charter.name).docs.add(charter)
DocAlias.objects.create(name=name).docs.add(charter)
charter.set_state(State.objects.get(used=True, type="charter", slug="notrev"))
charter.set_state(
State.objects.get(used=True, type="charter", slug="notrev")
)
group.charter = charter
group.save()
@ -418,56 +424,74 @@ def submit(request, name, option=None):
charter.rev = next_rev
events = []
e = NewRevisionDocEvent(doc=charter, by=request.user.person, type="new_revision")
e.desc = "New version available: <b>%s-%s.txt</b>" % (charter.canonical_name(), charter.rev)
e = NewRevisionDocEvent(
doc=charter, by=request.user.person, type="new_revision"
)
e.desc = "New version available: <b>%s-%s.txt</b>" % (
charter.name,
charter.rev,
)
e.rev = charter.rev
e.save()
events.append(e)
# Save file on disk
filename = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (charter.canonical_name(), charter.rev))
with io.open(filename, 'w', encoding='utf-8') as destination:
if form.cleaned_data['txt']:
destination.write(form.cleaned_data['txt'])
charter_filename = charter_filename.with_name(
f"{name}-{charter.rev}.txt"
) # update rev
with charter_filename.open("w", encoding="utf-8") as destination:
if form.cleaned_data["txt"]:
destination.write(form.cleaned_data["txt"])
else:
destination.write(form.cleaned_data['content'])
destination.write(form.cleaned_data["content"])
if option in ['initcharter','recharter'] and charter.ad == None:
charter.ad = getattr(group.ad_role(),'person',None)
if option in ["initcharter", "recharter"] and charter.ad == None:
charter.ad = getattr(group.ad_role(), "person", None)
charter.save_with_history(events)
if option:
return redirect('ietf.doc.views_charter.change_state', name=charter.name, option=option)
return redirect(
"ietf.doc.views_charter.change_state",
name=charter.name,
option=option,
)
else:
return redirect("ietf.doc.views_doc.document_main", name=charter.name)
else:
init = { "content": "" }
init = {"content": ""}
if not_uploaded_yet and charter:
# use text from last approved revision
last_approved = charter.rev.split("-")[0]
h = charter.history_set.filter(rev=last_approved).order_by("-time", "-id").first()
h = (
charter.history_set.filter(rev=last_approved)
.order_by("-time", "-id")
.first()
)
if h:
charter_canonical_name = h.canonical_name()
charter_rev = h.rev
filename = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (charter_canonical_name, charter_rev))
assertion("h.name == charter_name_for_group(group)")
charter_filename = charter_filename.with_name(
f"{name}-{h.rev}.txt"
) # update rev
try:
with io.open(filename, 'r') as f:
init["content"] = f.read()
init["content"] = charter_filename.read_text()
except IOError:
pass
form = UploadForm(initial=init)
fill_in_charter_info(group)
return render(request, 'doc/charter/submit.html', {
'form': form,
'next_rev': next_rev,
'group': group,
'name': name,
})
return render(
request,
"doc/charter/submit.html",
{
"form": form,
"next_rev": next_rev,
"group": group,
"name": name,
},
)
class ActionAnnouncementTextForm(forms.Form):
announcement_text = forms.CharField(widget=forms.Textarea, required=True, strip=False)
@ -484,7 +508,7 @@ class ReviewAnnouncementTextForm(forms.Form):
return self.cleaned_data["announcement_text"].replace("\r", "")
@role_required('Area Director','Secretariat')
@role_required("Area Director", "Secretariat")
def review_announcement_text(request, name):
"""Editing of review announcement text"""
charter = get_object_or_404(Document, type="charter", name=name)
@ -493,7 +517,9 @@ def review_announcement_text(request, name):
by = request.user.person
existing = charter.latest_event(WriteupDocEvent, type="changed_review_announcement")
existing_new_work = charter.latest_event(WriteupDocEvent, type="changed_new_work_text")
existing_new_work = charter.latest_event(
WriteupDocEvent, type="changed_new_work_text"
)
if not existing:
(existing, existing_new_work) = default_review_text(group, charter, by)
@ -506,19 +532,23 @@ def review_announcement_text(request, name):
existing_new_work.by = by
existing_new_work.type = "changed_new_work_text"
existing_new_work.desc = "%s review text was changed" % group.type.name
existing_new_work.text = derive_new_work_text(existing.text,group)
existing_new_work.text = derive_new_work_text(existing.text, group)
existing_new_work.time = timezone.now()
form = ReviewAnnouncementTextForm(initial=dict(announcement_text=escape(existing.text),new_work_text=escape(existing_new_work.text)))
form = ReviewAnnouncementTextForm(
initial=dict(
announcement_text=escape(existing.text),
new_work_text=escape(existing_new_work.text),
)
)
if request.method == 'POST':
if request.method == "POST":
form = ReviewAnnouncementTextForm(request.POST)
if "save_text" in request.POST and form.is_valid():
now = timezone.now()
events = []
t = form.cleaned_data['announcement_text']
t = form.cleaned_data["announcement_text"]
if t != existing.text:
e = WriteupDocEvent(doc=charter, rev=charter.rev)
e.by = by
@ -532,11 +562,11 @@ def review_announcement_text(request, name):
existing.save()
events.append(existing)
t = form.cleaned_data['new_work_text']
t = form.cleaned_data["new_work_text"]
if t != existing_new_work.text:
e = WriteupDocEvent(doc=charter, rev=charter.rev)
e.by = by
e.type = "changed_new_work_text"
e.type = "changed_new_work_text"
e.desc = "%s new work message text was changed" % (group.type.name)
e.text = t
e.time = now
@ -549,33 +579,71 @@ def review_announcement_text(request, name):
charter.save_with_history(events)
if request.GET.get("next", "") == "approve":
return redirect('ietf.doc.views_charter.approve', name=charter.canonical_name())
return redirect(
"ietf.doc.views_charter.approve", name=charter.name
)
return redirect('ietf.doc.views_doc.document_writeup', name=charter.canonical_name())
return redirect(
"ietf.doc.views_doc.document_writeup", name=charter.name
)
if "regenerate_text" in request.POST:
(existing, existing_new_work) = default_review_text(group, charter, by)
existing.save()
existing_new_work.save()
form = ReviewAnnouncementTextForm(initial=dict(announcement_text=escape(existing.text),
new_work_text=escape(existing_new_work.text)))
form = ReviewAnnouncementTextForm(
initial=dict(
announcement_text=escape(existing.text),
new_work_text=escape(existing_new_work.text),
)
)
if any(x in request.POST for x in ['send_annc_only','send_nw_only','send_both']) and form.is_valid():
if any(x in request.POST for x in ['send_annc_only','send_both']):
parsed_msg = send_mail_preformatted(request, form.cleaned_data['announcement_text'])
messages.success(request, "The email To: '%s' with Subject: '%s' has been sent." % (parsed_msg["To"],parsed_msg["Subject"],))
if any(x in request.POST for x in ['send_nw_only','send_both']):
parsed_msg = send_mail_preformatted(request, form.cleaned_data['new_work_text'])
messages.success(request, "The email To: '%s' with Subject: '%s' has been sent." % (parsed_msg["To"],parsed_msg["Subject"],))
return redirect('ietf.doc.views_doc.document_writeup', name=charter.name)
if (
any(
x in request.POST
for x in ["send_annc_only", "send_nw_only", "send_both"]
)
and form.is_valid()
):
if any(x in request.POST for x in ["send_annc_only", "send_both"]):
parsed_msg = send_mail_preformatted(
request, form.cleaned_data["announcement_text"]
)
messages.success(
request,
"The email To: '%s' with Subject: '%s' has been sent."
% (
parsed_msg["To"],
parsed_msg["Subject"],
),
)
if any(x in request.POST for x in ["send_nw_only", "send_both"]):
parsed_msg = send_mail_preformatted(
request, form.cleaned_data["new_work_text"]
)
messages.success(
request,
"The email To: '%s' with Subject: '%s' has been sent."
% (
parsed_msg["To"],
parsed_msg["Subject"],
),
)
return redirect("ietf.doc.views_doc.document_writeup", name=charter.name)
return render(request, 'doc/charter/review_announcement_text.html',
dict(charter=charter,
back_url=urlreverse('ietf.doc.views_doc.document_writeup', kwargs=dict(name=charter.name)),
announcement_text_form=form,
))
return render(
request,
"doc/charter/review_announcement_text.html",
dict(
charter=charter,
back_url=urlreverse(
"ietf.doc.views_doc.document_writeup", kwargs=dict(name=charter.name)
),
announcement_text_form=form,
),
)
@role_required('Area Director','Secretariat')
@role_required("Area Director", "Secretariat")
def action_announcement_text(request, name):
"""Editing of action announcement text"""
charter = get_object_or_404(Document, type="charter", name=name)
@ -590,16 +658,18 @@ def action_announcement_text(request, name):
if not existing:
raise Http404
form = ActionAnnouncementTextForm(initial=dict(announcement_text=escape(existing.text)))
form = ActionAnnouncementTextForm(
initial=dict(announcement_text=escape(existing.text))
)
if request.method == 'POST':
if request.method == "POST":
form = ActionAnnouncementTextForm(request.POST)
if "save_text" in request.POST and form.is_valid():
t = form.cleaned_data['announcement_text']
t = form.cleaned_data["announcement_text"]
if t != existing.text:
e = WriteupDocEvent(doc=charter, rev=charter.rev)
e.by = by
e.type = "changed_action_announcement"
e.type = "changed_action_announcement"
e.desc = "%s action text was changed" % group.type.name
e.text = t
e.save()
@ -607,25 +677,46 @@ def action_announcement_text(request, name):
existing.save()
if request.GET.get("next", "") == "approve":
return redirect('ietf.doc.views_charter.approve', name=charter.canonical_name())
return redirect(
"ietf.doc.views_charter.approve", name=charter.name
)
return redirect('ietf.doc.views_doc.document_writeup', name=charter.canonical_name())
return redirect(
"ietf.doc.views_doc.document_writeup", name=charter.name
)
if "regenerate_text" in request.POST:
e = default_action_text(group, charter, by)
e.save()
form = ActionAnnouncementTextForm(initial=dict(announcement_text=escape(e.text)))
form = ActionAnnouncementTextForm(
initial=dict(announcement_text=escape(e.text))
)
if "send_text" in request.POST and form.is_valid():
parsed_msg = send_mail_preformatted(request, form.cleaned_data['announcement_text'])
messages.success(request, "The email To: '%s' with Subject: '%s' has been sent." % (parsed_msg["To"],parsed_msg["Subject"],))
return redirect('ietf.doc.views_doc.document_writeup', name=charter.name)
parsed_msg = send_mail_preformatted(
request, form.cleaned_data["announcement_text"]
)
messages.success(
request,
"The email To: '%s' with Subject: '%s' has been sent."
% (
parsed_msg["To"],
parsed_msg["Subject"],
),
)
return redirect("ietf.doc.views_doc.document_writeup", name=charter.name)
return render(request, 'doc/charter/action_announcement_text.html',
dict(charter=charter,
back_url=urlreverse('ietf.doc.views_doc.document_writeup', kwargs=dict(name=charter.name)),
announcement_text_form=form,
))
return render(
request,
"doc/charter/action_announcement_text.html",
dict(
charter=charter,
back_url=urlreverse(
"ietf.doc.views_doc.document_writeup", kwargs=dict(name=charter.name)
),
announcement_text_form=form,
),
)
class BallotWriteupForm(forms.Form):
ballot_writeup = forms.CharField(widget=forms.Textarea, required=True, strip=False)
@ -806,33 +897,37 @@ def approve(request, name):
dict(charter=charter,
announcement=escape(announcement)))
def charter_with_milestones_txt(request, name, rev):
charter = get_object_or_404(Document, type="charter", docalias__name=name)
revision_event = charter.latest_event(NewRevisionDocEvent, type="new_revision", rev=rev)
def charter_with_milestones_txt(request, name, rev):
charter = get_object_or_404(Document, type="charter", name=name)
revision_event = charter.latest_event(
NewRevisionDocEvent, type="new_revision", rev=rev
)
if not revision_event:
return HttpResponseNotFound("Revision %s not found in database" % rev)
# read charter text
c = find_history_active_at(charter, revision_event.time) or charter
filename = '%s-%s.txt' % (c.canonical_name(), rev)
charter_text = ""
filename = Path(settings.CHARTER_PATH) / f"{c.name}-{rev}.txt"
try:
with io.open(os.path.join(settings.CHARTER_PATH, filename), 'r') as f:
charter_text = force_str(f.read(), errors='ignore')
with filename.open() as f:
charter_text = force_str(f.read(), errors="ignore")
except IOError:
charter_text = "Error reading charter text %s" % filename
charter_text = f"Error reading charter text {filename.name}"
milestones = historic_milestones_for_charter(charter, rev)
# wrap the output nicely
wrapper = textwrap.TextWrapper(initial_indent="", subsequent_indent=" " * 11, width=80, break_long_words=False)
wrapper = textwrap.TextWrapper(
initial_indent="", subsequent_indent=" " * 11, width=80, break_long_words=False
)
for m in milestones:
m.desc_filled = wrapper.fill(m.desc)
return render(request, 'doc/charter/charter_with_milestones.txt',
dict(charter_text=charter_text,
milestones=milestones),
content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET)
return render(
request,
"doc/charter/charter_with_milestones.txt",
dict(charter_text=charter_text, milestones=milestones),
content_type="text/plain; charset=%s" % settings.DEFAULT_CHARSET,
)

View file

@ -369,7 +369,7 @@ def edit_milestones(request, acronym, group_type=None, milestone_set="current"):
email_milestones_changed(request, group, changes, states)
if milestone_set == "charter":
return redirect('ietf.doc.views_doc.document_main', name=group.charter.canonical_name())
return redirect('ietf.doc.views_doc.document_main', name=group.charter.name)
else:
return HttpResponseRedirect(group.about_url())
else:

View file

@ -117,8 +117,9 @@ class GroupPagesTests(TestCase):
chair = Email.objects.filter(role__group=group, role__name="chair")[0]
with (Path(settings.CHARTER_PATH) / ("%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev))).open("w") as f:
f.write("This is a charter.")
(
Path(settings.CHARTER_PATH) / f"{group.charter.name}-{group.charter.rev}.txt"
).write_text("This is a charter.")
url = urlreverse('ietf.group.views.wg_summary_area', kwargs=dict(group_type="wg"))
r = self.client.get(url)
@ -264,8 +265,9 @@ class GroupPagesTests(TestCase):
group = CharterFactory().group
draft = WgDraftFactory(group=group)
with (Path(settings.CHARTER_PATH) / ("%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev))).open("w") as f:
f.write("This is a charter.")
(
Path(settings.CHARTER_PATH) / f"{group.charter.name}-{group.charter.rev}.txt"
).write_text("This is a charter.")
milestone = GroupMilestone.objects.create(
group=group,
@ -674,8 +676,9 @@ class GroupEditTests(TestCase):
self.assertTrue(len(q('form .is-invalid')) > 0)
# edit info
with (Path(settings.CHARTER_PATH) / ("%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev))).open("w") as f:
f.write("This is a charter.")
(
Path(settings.CHARTER_PATH) / f"{group.charter.name}-{group.charter.rev}.txt"
).write_text("This is a charter.")
area = group.parent
ad = Person.objects.get(name="Areað Irector")
state = GroupStateName.objects.get(slug="bof")
@ -717,7 +720,9 @@ class GroupEditTests(TestCase):
self.assertEqual(group.list_archive, "archive.mars")
self.assertEqual(group.description, '')
self.assertTrue((Path(settings.CHARTER_PATH) / ("%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev))).exists())
self.assertTrue(
(Path(settings.CHARTER_PATH) / f"{group.charter.name}-{group.charter.rev}.txt").exists()
)
self.assertEqual(len(outbox), 2)
self.assertTrue('Personnel change' in outbox[0]['Subject'])
for prefix in ['ad1','ad2','aread','marschairman','marsdelegate']:

View file

@ -2,8 +2,7 @@
# -*- coding: utf-8 -*-
import io
import os
from pathlib import Path
from django.db.models import Q
from django.shortcuts import get_object_or_404
@ -55,15 +54,14 @@ def get_charter_text(group):
if (h.rev > c.rev and not (c_appr and not h_appr)) or (h_appr and not c_appr):
c = h
filename = os.path.join(c.get_file_path(), "%s-%s.txt" % (c.canonical_name(), c.rev))
filename = Path(c.get_file_path()) / f"{c.name}-{c.rev}.txt"
try:
with io.open(filename, 'rb') as f:
text = f.read()
try:
text = text.decode('utf8')
except UnicodeDecodeError:
text = text.decode('latin1')
return text
text = filename.read_bytes()
try:
text = text.decode('utf8')
except UnicodeDecodeError:
text = text.decode('latin1')
return text
except IOError:
return 'Error Loading Group Charter'

View file

@ -3,11 +3,8 @@
# Python imports
import io
import os
# Django imports
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
# Datatracker imports
@ -15,27 +12,6 @@ from ietf.group.models import Group
from ietf.ietfauth.utils import has_role
def current_nomcom():
qs = Group.objects.filter(acronym__startswith='nomcom',state__slug="active").order_by('-time')
if qs.count():
return qs[0]
else:
return None
def get_charter_text(group):
'''
Takes a group object and returns the text or the group's charter as a string
'''
charter = group.charter
path = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (charter.canonical_name(), charter.rev))
f = io.open(path,'r')
text = f.read()
f.close()
return text
def get_my_groups(user,conclude=False):
'''
Takes a Django user object (from request)

View file

@ -21,7 +21,7 @@
</button>
{% if user|has_role:"Secretariat" %}
<a class="btn btn-primary"
href="{% url 'ietf.doc.views_charter.approve' name=charter.canonical_name %}">
href="{% url 'ietf.doc.views_charter.approve' name=charter.name %}">
Charter approval page
</a>
{% endif %}

View file

@ -2,16 +2,16 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load django_bootstrap5 %}
{% block title %}Approve {{ charter.canonical_name }}{% endblock %}
{% block title %}Approve {{ charter.name }}{% endblock %}
{% block content %}
{% origin %}
<h1>Approve {{ charter.canonical_name }}-{{ charter.rev }}</h1>
<h1>Approve {{ charter.name }}-{{ charter.rev }}</h1>
<form class="mt-3" method="post">
{% csrf_token %}
<pre class="border p-3">{{ announcement }}</pre>
<button type="submit" class="btn btn-primary">Send announcement, close ballot &amp; update revision</button>
<a class="btn btn-warning"
href="{% url "ietf.doc.views_charter.action_announcement_text" name=charter.canonical_name %}?next=approve">
href="{% url "ietf.doc.views_charter.action_announcement_text" name=charter.name %}?next=approve">
Edit/regenerate announcement
</a>
<a class="btn btn-secondary float-end"

View file

@ -2,20 +2,20 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load django_bootstrap5 %}
{% block title %}Change responsible AD for {{ charter.canonical_name }}-{{ charter.rev }}{% endblock %}
{% block title %}Change responsible AD for {{ charter.name }}-{{ charter.rev }}{% endblock %}
{% block content %}
{% origin %}
<h1>
Change responsible AD
<br>
<small class="text-muted">{{ charter.canonical_name }}-{{ charter.rev }}</small>
<small class="text-muted">{{ charter.name }}-{{ charter.rev }}</small>
</h1>
<form class="mt-3" enctype="multipart/form-data" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<button type="submit" class="btn btn-primary">Submit</button>
<a class="btn btn-secondary float-end"
href="{% url "ietf.doc.views_doc.document_main" name=charter.canonical_name %}">
href="{% url "ietf.doc.views_doc.document_main" name=charter.name %}">
Back
</a>
</form>

View file

@ -14,8 +14,8 @@
<a class="btn btn-primary" href="{{ group.about_url }}">{{ group.acronym }} {{ group.type.name }}</a>
{% if group.charter %}
<a class="btn btn-primary"
href="{% url "ietf.doc.views_doc.document_main" name=group.charter.canonical_name %}">
{{ group.charter.canonical_name }}
href="{% url "ietf.doc.views_doc.document_main" name=group.charter.name %}">
{{ group.charter.name }}
</a>
{% endif %}
{% if can_change_uses_milestone_dates %}
@ -106,7 +106,7 @@
</div>
</div>
<a class="btn btn-secondary float-end"
href="{% if milestone_set == "charter" %}{% url "ietf.doc.views_doc.document_main" name=group.charter.canonical_name %}{% else %}{{ group.about_url }}{% endif %}">
href="{% if milestone_set == "charter" %}{% url "ietf.doc.views_doc.document_main" name=group.charter.name %}{% else %}{{ group.about_url }}{% endif %}">
Cancel
</a>
<button class="btn btn-primary hidden"