From a0c0e75b624bdca4167dcf49ff7ec9e52f963754 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Mon, 18 Dec 2023 02:42:00 -0500 Subject: [PATCH] Move to pandoc for rendering sponsorship contracts --- Aptfile | 5 + Dockerfile | 32 +- base-requirements.txt | 7 +- pydotorg/settings/base.py | 1 - sponsors/contracts.py | 79 +++++ sponsors/pandoc_filters/__init__.py | 0 sponsors/pandoc_filters/pagebreak.py | 90 ++++++ sponsors/pdf.py | 70 ----- sponsors/tests/test_contracts.py | 34 +++ sponsors/tests/test_pdf.py | 73 ----- sponsors/use_cases.py | 2 +- sponsors/views_admin.py | 2 +- .../sponsors/admin/contract-template.docx | Bin 15199 -> 0 bytes .../sponsors/admin/contracts/reference.docx | Bin 0 -> 10231 bytes .../admin/contracts/sponsorship-agreement.md | 195 ++++++++++++ .../sponsors/admin/preview-contract.html | 283 ------------------ 16 files changed, 439 insertions(+), 434 deletions(-) create mode 100644 Aptfile create mode 100644 sponsors/contracts.py create mode 100644 sponsors/pandoc_filters/__init__.py create mode 100644 sponsors/pandoc_filters/pagebreak.py delete mode 100644 sponsors/pdf.py create mode 100644 sponsors/tests/test_contracts.py delete mode 100644 sponsors/tests/test_pdf.py delete mode 100644 templates/sponsors/admin/contract-template.docx create mode 100644 templates/sponsors/admin/contracts/reference.docx create mode 100644 templates/sponsors/admin/contracts/sponsorship-agreement.md delete mode 100644 templates/sponsors/admin/preview-contract.html diff --git a/Aptfile b/Aptfile new file mode 100644 index 000000000..bc0db6c25 --- /dev/null +++ b/Aptfile @@ -0,0 +1,5 @@ +pandoc +texlive-latex-base +texlive-latex-recommended +texlive-fonts-recommended +lmodern diff --git a/Dockerfile b/Dockerfile index 4d1046a98..aec467d40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,39 @@ FROM python:3.9-bullseye ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 + +# By default, Docker has special steps to avoid keeping APT caches in the layers, which +# is good, but in our case, we're going to mount a special cache volume (kept between +# builds), so we WANT the cache to persist. +RUN set -eux; \ + rm -f /etc/apt/apt.conf.d/docker-clean; \ + echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache; + +# Install System level build requirements, this is done before +# everything else because these are rarely ever going to change. +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + set -x \ + && apt-get update \ + && apt-get install --no-install-recommends -y \ + pandoc \ + texlive-latex-base \ + texlive-latex-recommended \ + texlive-fonts-recommended \ + lmodern + RUN mkdir /code WORKDIR /code + COPY dev-requirements.txt /code/ COPY base-requirements.txt /code/ -RUN pip install -r dev-requirements.txt + +RUN pip --no-cache-dir --disable-pip-version-check install --upgrade pip setuptools wheel + +RUN --mount=type=cache,target=/root/.cache/pip \ + set -x \ + && pip --disable-pip-version-check \ + install \ + -r dev-requirements.txt + COPY . /code/ diff --git a/base-requirements.txt b/base-requirements.txt index 9ddabf236..515ceffae 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -44,12 +44,11 @@ django-filter==2.4.0 django-ordered-model==3.4.3 django-widget-tweaks==1.4.8 django-countries==7.2.1 -xhtml2pdf==0.2.5 -django-easy-pdf3==0.1.2 num2words==0.5.10 django-polymorphic==3.0.0 sorl-thumbnail==12.7.0 -docxtpl==0.12.0 -reportlab==3.6.6 django-extensions==3.1.4 django-import-export==2.7.1 + +pypandoc==1.12 +panflute==1.12 diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 25874dd5d..ccbf3acab 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -173,7 +173,6 @@ 'ordered_model', 'widget_tweaks', 'django_countries', - 'easy_pdf', 'sorl.thumbnail', 'banners', diff --git a/sponsors/contracts.py b/sponsors/contracts.py new file mode 100644 index 000000000..983cc3ae2 --- /dev/null +++ b/sponsors/contracts.py @@ -0,0 +1,79 @@ +import os +import tempfile + +from django.http import HttpResponse +from django.template.loader import render_to_string +from django.utils.dateformat import format + +import pypandoc + +dirname = os.path.dirname(__file__) +DOCXPAGEBREAK_FILTER = os.path.join(dirname, "pandoc_filters/pagebreak.py") + + +def _clean_split(text, separator="\n"): + return [ + t.replace("-", "").strip() + for t in text.split("\n") + if t.replace("-", "").strip() + ] + + +def _contract_context(contract, **context): + start_date = contract.sponsorship.start_date + context.update( + { + "contract": contract, + "start_date": start_date, + "start_day_english_suffix": format(start_date, "S"), + "sponsor": contract.sponsorship.sponsor, + "sponsorship": contract.sponsorship, + "benefits": _clean_split(contract.benefits_list.raw), + "legal_clauses": _clean_split(contract.legal_clauses.raw), + } + ) + return context + + +def render_contract_to_pdf_response(request, contract, **context): + response = HttpResponse( + render_contract_to_pdf_file(contract, **context), content_type="application/pdf" + ) + return response + + +def render_contract_to_pdf_file(contract, **context): + with tempfile.NamedTemporaryFile() as docx_file: + with tempfile.NamedTemporaryFile(suffix=".pdf") as pdf_file: + docx_file.write(render_contract_to_docx_file(contract, **context)) + pdf = pypandoc.convert_file( + docx_file.name, "pdf", outputfile=pdf_file.name, format="docx" + ) + return pdf_file.read() + + +def render_contract_to_docx_response(request, contract, **context): + response = HttpResponse( + render_contract_to_docx_file(contract, **context), + content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ) + response[ + "Content-Disposition" + ] = f"attachment; filename=sponsorship-contract-{contract.sponsorship.sponsor.name.replace(' ', '-')}.docx" + return response + + +def render_contract_to_docx_file(contract, **context): + template = "sponsors/admin/contracts/sponsorship-agreement.md" + reference = "sponsors/admin/contracts/reference.docx" + context = _contract_context(contract, **context) + markdown = render_to_string(template, context) + with tempfile.NamedTemporaryFile() as docx_file: + docx = pypandoc.convert_text( + markdown, + "docx", + outputfile=docx_file.name, + format="md", + filters=[DOCXPAGEBREAK_FILTER], + ) + return docx_file.read() diff --git a/sponsors/pandoc_filters/__init__.py b/sponsors/pandoc_filters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/sponsors/pandoc_filters/pagebreak.py b/sponsors/pandoc_filters/pagebreak.py new file mode 100644 index 000000000..525b89c57 --- /dev/null +++ b/sponsors/pandoc_filters/pagebreak.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ------------------------------------------------------------------------------ +# Source: https://github.com/pandocker/pandoc-docx-pagebreak-py/ +# Revision: c8cddccebb78af75168da000a3d6ac09349bef73 +# ------------------------------------------------------------------------------ +# MIT License +# +# Copyright (c) 2018 pandocker +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# ------------------------------------------------------------------------------ + +""" pandoc-docx-pagebreakpy +Pandoc filter to insert pagebreak as openxml RawBlock +Only for docx output + +Trying to port pandoc-doc-pagebreak +- https://github.com/alexstoick/pandoc-docx-pagebreak +""" + +import panflute as pf + + +class DocxPagebreak(object): + pagebreak = pf.RawBlock("", format="openxml") + sectionbreak = pf.RawBlock("", + format="openxml") + toc = pf.RawBlock(r""" + + + + + + TOC \o "1-3" \h \z \u + + + + + + +""", format="openxml") + + def action(self, elem, doc): + if isinstance(elem, pf.RawBlock): + if elem.text == r"\newpage": + if (doc.format == "docx"): + pf.debug("Page Break") + elem = self.pagebreak + # elif elem.text == r"\newsection": + # if (doc.format == "docx"): + # pf.debug("Section Break") + # elem = self.sectionbreak + # else: + # elem = [] + elif elem.text == r"\toc": + if (doc.format == "docx"): + pf.debug("Table of Contents") + para = [pf.Para(pf.Str("Table"), pf.Space(), pf.Str("of"), pf.Space(), pf.Str("Contents"))] + div = pf.Div(*para, attributes={"custom-style": "TOC Heading"}) + elem = [div, self.toc] + else: + elem = [] + return elem + + +def main(doc=None): + dp = DocxPagebreak() + return pf.run_filter(dp.action, doc=doc) + + +if __name__ == "__main__": + main() diff --git a/sponsors/pdf.py b/sponsors/pdf.py deleted file mode 100644 index 5188b8290..000000000 --- a/sponsors/pdf.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -This module is a wrapper around django-easy-pdf so we can reuse code -""" -import io -import os -from django.conf import settings -from django.http import HttpResponse -from django.utils.dateformat import format - -from docxtpl import DocxTemplate -from easy_pdf.rendering import render_to_pdf_response, render_to_pdf - -from markupfield_helpers.helpers import render_md -from django.utils.html import mark_safe - - -def _clean_split(text, separator='\n'): - return [ - t.replace('-', '').strip() - for t in text.split('\n') - if t.replace('-', '').strip() - ] - - -def _contract_context(contract, **context): - start_date = contract.sponsorship.start_date - context.update({ - "contract": contract, - "start_date": start_date, - "start_day_english_suffix": format(start_date, "S"), - "sponsor": contract.sponsorship.sponsor, - "sponsorship": contract.sponsorship, - "benefits": _clean_split(contract.benefits_list.raw), - "legal_clauses": _clean_split(contract.legal_clauses.raw), - }) - return context - - -def render_contract_to_pdf_response(request, contract, **context): - template = "sponsors/admin/preview-contract.html" - context = _contract_context(contract, **context) - return render_to_pdf_response(request, template, context) - - -def render_contract_to_pdf_file(contract, **context): - template = "sponsors/admin/preview-contract.html" - context = _contract_context(contract, **context) - return render_to_pdf(template, context) - - -def _gen_docx_contract(output, contract, **context): - template = os.path.join(settings.TEMPLATES_DIR, "sponsors", "admin", "contract-template.docx") - doc = DocxTemplate(template) - context = _contract_context(contract, **context) - doc.render(context) - doc.save(output) - return output - - -def render_contract_to_docx_response(request, contract, **context): - response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document') - response['Content-Disposition'] = 'attachment; filename=contract.docx' - return _gen_docx_contract(output=response, contract=contract, **context) - - -def render_contract_to_docx_file(contract, **context): - fp = io.BytesIO() - fp = _gen_docx_contract(output=fp, contract=contract, **context) - fp.seek(0) - return fp.read() diff --git a/sponsors/tests/test_contracts.py b/sponsors/tests/test_contracts.py new file mode 100644 index 000000000..c41b048fb --- /dev/null +++ b/sponsors/tests/test_contracts.py @@ -0,0 +1,34 @@ +from datetime import date +from model_bakery import baker +from unittest.mock import patch, Mock + +from django.http import HttpRequest +from django.test import TestCase +from django.utils.dateformat import format + +from sponsors.contracts import render_contract_to_docx_response + + +class TestRenderContract(TestCase): + def setUp(self): + self.contract = baker.make_recipe("sponsors.tests.empty_contract", sponsorship__start_date=date.today()) + self.context = { + "contract": self.contract, + "start_date": self.contract.sponsorship.start_date, + "start_day_english_suffix": format(self.contract.sponsorship.start_date, "S"), + "sponsor": self.contract.sponsorship.sponsor, + "sponsorship": self.contract.sponsorship, + "benefits": [], + "legal_clauses": [], + } + + # DOCX unit test + def test_render_response_with_docx_attachment(self): + request = Mock(HttpRequest) + response = render_contract_to_docx_response(request, self.contract) + + self.assertEqual(response.get("Content-Disposition"), "attachment; filename=sponsorship-contract-Sponsor.docx") + self.assertEqual( + response.get("Content-Type"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + ) diff --git a/sponsors/tests/test_pdf.py b/sponsors/tests/test_pdf.py deleted file mode 100644 index ec929d05e..000000000 --- a/sponsors/tests/test_pdf.py +++ /dev/null @@ -1,73 +0,0 @@ -from datetime import date -from docxtpl import DocxTemplate -from markupfield_helpers.helpers import render_md -from model_bakery import baker -from pathlib import Path -from unittest.mock import patch, Mock - -from django.conf import settings -from django.http import HttpResponse, HttpRequest -from django.template.loader import render_to_string -from django.test import TestCase -from django.utils.html import mark_safe -from django.utils.dateformat import format - -from sponsors.pdf import render_contract_to_pdf_file, render_contract_to_pdf_response, render_contract_to_docx_response - - -class TestRenderContract(TestCase): - def setUp(self): - self.contract = baker.make_recipe("sponsors.tests.empty_contract", sponsorship__start_date=date.today()) - text = f"{self.contract.benefits_list.raw}\n\n**Legal Clauses**\n{self.contract.legal_clauses.raw}" - html = render_md(text) - self.context = { - "contract": self.contract, - "start_date": self.contract.sponsorship.start_date, - "start_day_english_suffix": format(self.contract.sponsorship.start_date, "S"), - "sponsor": self.contract.sponsorship.sponsor, - "sponsorship": self.contract.sponsorship, - "benefits": [], - "legal_clauses": [], - } - self.template = "sponsors/admin/preview-contract.html" - - # PDF unit tests - @patch("sponsors.pdf.render_to_pdf") - def test_render_pdf_using_django_easy_pdf(self, mock_render): - mock_render.return_value = "pdf content" - - content = render_contract_to_pdf_file(self.contract) - - self.assertEqual(content, "pdf content") - mock_render.assert_called_once_with(self.template, self.context) - - @patch("sponsors.pdf.render_to_pdf_response") - def test_render_response_using_django_easy_pdf(self, mock_render): - response = Mock(HttpResponse) - mock_render.return_value = response - - request = Mock(HttpRequest) - content = render_contract_to_pdf_response(request, self.contract) - - self.assertEqual(content, response) - mock_render.assert_called_once_with(request, self.template, self.context) - - # DOCX unit test - @patch("sponsors.pdf.DocxTemplate") - def test_render_response_with_docx_attachment(self, MockDocxTemplate): - template = Path(settings.TEMPLATES_DIR) / "sponsors" / "admin" / "contract-template.docx" - self.assertTrue(template.exists()) - mocked_doc = Mock(DocxTemplate) - MockDocxTemplate.return_value = mocked_doc - - request = Mock(HttpRequest) - response = render_contract_to_docx_response(request, self.contract) - - MockDocxTemplate.assert_called_once_with(str(template.resolve())) - mocked_doc.render.assert_called_once_with(self.context) - mocked_doc.save.assert_called_once_with(response) - self.assertEqual(response.get("Content-Disposition"), "attachment; filename=contract.docx") - self.assertEqual( - response.get("Content-Type"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.document" - ) diff --git a/sponsors/use_cases.py b/sponsors/use_cases.py index 95b2d267e..3aef9d989 100644 --- a/sponsors/use_cases.py +++ b/sponsors/use_cases.py @@ -3,7 +3,7 @@ from sponsors import notifications from sponsors.models import Sponsorship, Contract, SponsorContact, SponsorEmailNotificationTemplate, SponsorshipBenefit, \ SponsorshipPackage -from sponsors.pdf import render_contract_to_pdf_file, render_contract_to_docx_file +from sponsors.contracts import render_contract_to_pdf_file, render_contract_to_docx_file class BaseUseCaseWithNotifications: diff --git a/sponsors/views_admin.py b/sponsors/views_admin.py index 8968da1b7..e15d50f02 100644 --- a/sponsors/views_admin.py +++ b/sponsors/views_admin.py @@ -14,7 +14,7 @@ from sponsors.forms import SponsorshipReviewAdminForm, SponsorshipsListForm, SignedSponsorshipReviewAdminForm, \ SendSponsorshipNotificationForm, CloneApplicationConfigForm from sponsors.exceptions import InvalidStatusException -from sponsors.pdf import render_contract_to_pdf_response, render_contract_to_docx_response +from sponsors.contracts import render_contract_to_pdf_response, render_contract_to_docx_response from sponsors.models import Sponsorship, SponsorBenefit, EmailTargetable, SponsorContact, BenefitFeature, \ SponsorshipCurrentYear, SponsorshipBenefit, SponsorshipPackage diff --git a/templates/sponsors/admin/contract-template.docx b/templates/sponsors/admin/contract-template.docx deleted file mode 100644 index 5bdc44525a4d15367bcaad989f5d63ba6c278233..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15199 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 diff --git a/templates/sponsors/admin/contracts/reference.docx b/templates/sponsors/admin/contracts/reference.docx new file mode 100644 index 0000000000000000000000000000000000000000..ea5c5841f5ae26411e8c032912d5906a115804d0 GIT binary patch literal 10231 zcmZ`z2?WR)u*b?solFuSq>To8v+Ue0m6hYM$^8y^Vks*0)hq}0s;#H0zy{|Z0iKF zbuv(Qw*xuqF}c}T*J||J`m+F|7H)!(pE(p0B0Wux9?mdMO=6I3FE*CeqO$9Xa7e}m^tS&_%}fCpylW2x3j zIz^?zH^MQB8k67`ZO&NvI(?@<{_q2ne$6#!T;S6TIevKMhT&vC`(`!+%e(pU1IbTo z4DT%OUKYk7?jTXaswT~9cw_EnA&~S%^hX|c3(a7P&IlNlzG)DU{;Gzp4+0Da^m1i| zM1f03Z*UXH-b+`0$Xz@_R7ly86*U7DBF3nH7|}%p0y3Cl3^pGWg;>t z8C9@!%*&7ulW~lmbqiW1dk?2#;~HzXT{5qzx_%-5v80Q~U8r{mS)?#P9@ZZW9fkD8 z1l*l>`6#_s;em5^5(5%0W^Qp1b1Yfm*>7Mr3>GPOzn3ZlHGJ`}%MM_Bkj$OdxQ0+6 zP8^*V3hUVbtmfp|>Yd)zb2Z<>DgP0p0tr!=sne}R$(vLs&{^uXMZUq;O?>t-c!j+X=aejwkWe0pCVJ7m0-mPd zV(ZE@dOe*Gs8m?{L59v>G(P)L``=n<>MT?Zn9@fo$93?%3NIC(rY za%hIx@^jbb42_lGTufr_b1Vjjr39r7)JO|t_K7k{seSq0m)J5`FZ_Fjv72W5=&m!r z>MV-GmmhY3a#Te;f~g7>&4;gS#E!tGft`UFYb*VP)a?DF;h}=JG3#xY2O$c76M$kqW@)9Y7$2XOH$#@)=FLfV*rs6V^JBw0{nd(6?bpG%;}n z^4N$C!^`k4`m|aUr;Rl&BlKSLMC~N17w1^UklE=IHj7Int$%9&3diVCL$S%x9UW$iFcE#A*8S9h2!Q!hax_l)<7%@NE7brv7@9NuPwSv>BrRyJGr|YjX`oD>8;_T=Iw)vIoBLc`BEZ70-&8-xsU^NnP z*-562L*-?$clVIP%|I^3t5qTlCs+Qjr*`{Sd$^S%Ye~w3Vk)wb7KIu1Q|Bvs7uDFr zs8?n{7)Dpac}{IF3mdJbN>>k&WXs2~vs3%7b^ZE(E@bMJA>J%B1Vl60-}&JRb}(gr zT8*>KQ^omf8AnO;4k>@-#{)LXHR4Kr;pE#`TlVHYs-!C&+>SBwE@IQkuU^#EQWjsAlz2hlL>Lb9Cnu7mzzjrZq8*AxbKC}297 z21=+H>!k9f=nJPkcLFp-iFs-{8HzGk6xxjqY)<`=HYH!97?5aG&q~E=#yf0@kVSga zT{<=f1PXauS?G8Kbb1VKO&IC$28huP+ToY4Xc~ap395J;9c^s5r^rLQRmyZeMZwFJ z!6XsIF1MLJes%IXIKGO&3&^d}T&{>y0wju1a8}RYBs<5Hu8-Oqr}B3Ky%^m!WyH)Hxk*Broy+<>QH#P@JLN$-Yx=c2B^-0#~FtVEoo0(@o2^8|LZIP%bD=0g< z^z&cj+-9j0eAN`_Tz+sFW+W)dE%ETI-2y@*qagzie%b=+KMK*AEHA#w$)@x+EN5&# z2=`yuKg9l|IwP`zMb&%Vt`cR{LrUk@>k;`rtgp|YQ4Ax78B081yaLdutga|QPr~hQ zK97wK#(Zq^H4pH%P!zJBKyMmDkJt;U+m+h>oHI1YVl zX@W|ZM_lNR}SBVK~N!ffCy084H~<>`93mzFEtJxY> z-xU4U{(DDBdiBQA0#L(olb*Qrp?>%H=aJXIIX1!l8MNZdd!a862?I8ZY(**F?HbjI zFvFZW?z2WV&7_RZUb|&oBE5>Wy1|dDZ9bcDxJsKJciyzt`SEqd2QCC#Qg;oPR~aZ9(GR^iV=v1yE|#PQX%(WLihrYFrAvbt zwwDu*tQb(K7v5W!O~7gwqo`e`f>ruMrbe|$qs&ykHgL+VF02<3%Yw7vYvK|ooeqc` zAs_f|{#@E@*w~~mBs!UQZ9bYo9N&1&YUwT-RA1Lcr;?mp&Zs9Q$~{&tPA%~oDHPcI!e;_?C5;jr(? znf5K6tWwQ`^@3fatxn{;&@Xph0hWCt?1Uz((f|_ge0y+LF zOtFKu9V`HeYfp(y0qz=A4GAi1R0)U?y6*lFWHi&K`6j5G`!F+)oCpXq#w8SQ z$iGIOM>Z{w7t$^>L;0lr`67&C{c*R;oqzpiHhpvU$8@e+akA=Hlsi<;6JRaHIjRQaL8?%gDXTi!Q(eh~;u5p@B-;*=T_9PNE0 z7qhQy*|Bm3Es%f42$_u^ZSiTFIs8M)er-1su+3jJ_wNvmw}*C;1K`#?GAP`X6g;$W z-!91QVL6crhrj(0PRUMl{H;9C-UwY+RFQ)HF^D~#X_e)5HMPsGuKgTWcGZgE&W{`% zgKOOfI;NdvIy!%d8L2Xdwrbf@d}9<@Sx$f0VGop<9i1o`-femTQ_+2>tjeKze-+Y{ zZ81L=eFl^gql%NXN==T*3s~3?F%b)TQI{!J^bvpLHyqa8;`)s0s3QQjtI81~Wo8hM ztg-i}L?Z^Ty|I#t3^{tlX0xhDr#tiJ_9RqM#qJRAUO6NGv+INM^6Y}mTlhac!8)+A z8}O8^HVFU9R$FHqW01pJTl2rNwL4+>=~EY__rwD!?mqccTPObNb>Sq((U<^4K#hbf zlq}TIiZ`0S%MmcSVN*2tq5c~gLdx{^K+>#AVUdn$Uk1jeipms-T9M#x0c@aFqupA< zBsYEz9dCF=E?TffEoNStLfuout(IP_y{rt`V#4TNW<;-aqdHji(OD$kPkO{oSlZ8B zAF(Dd^;YC<65d_T)=HI~4Aka22noY`xsRINq)|=3skAyfvK95f-=+q||&V!f#v+(-fz&(THI$y~DMp1a%7pFVun$MTou46;$BZ(P? zyf0!}8;rMc0Ah>D6e4{M}Ei7c43kU0Ftt&*}Xs3rO(U_S9x=a9KkB>L;jL@G!LnyM` zsC!D?TeyF5Mn{m7(^JU)PG1c z)26-hlZ8raHT>kgkX?@wSIwr4^Se(mBB&MtCpNadXiz3f3w;bVm4<_vt{Dt-3riGyT!Pw~cxc27Iv zSbZznal48H-r`&(Wec*N0h0~l0*{Zt&IhW#X&J!S@B^nLtb!_(!#?HF^Rsl0{@ z61XErrQRBaPxiD^*0muAqfi(GRJ)gZhY=SA|3s5mSn^~)MkH7jNF?m3a-h|sUd9?! zHJ8np?d{H`=BWy_dp}b;SiQ9vnDJim)Tb|ik$N$z5-jzIr_=o~ zR;o!#_7eeqm8~fK-DfN{(KbE2~9uP`3977`!deP_`-#RB+VhP={VX3SD=2kq1*QW zExf)QqVS%KvhH+F+;zLM8iVh8?lxG@?a;U@fmF9{&P53w&uBcNb1uW-TQQ5 z|A!K}f{fMvmFIeqd}vRVRQx`*!$HZK77%)lp|DGl+Xg9LMU`L;-mJxp92FH2;ko!O zsm95C(uMSqAyD?%krDO-q!iI-*%k27F;xmLJ@lTjzZ5zhE3o}_rr)CM2pwa9D#y?o z>Q;lW;a%6R!Uq0}S|j35!O(!p!!%wCFZGo<@&ozclLmXVdMj6qea(nDqy1qd^Zj|p zF&%g^{i0UB%Vz{nx_ecs`f0l=@IyeL|7SIhPVUx!Q-UL1UB?A(Z10ou)0^h4^l16F zLD8V(B-<25(`)THsHwRGP0Xylas!zbLqs`zyX34vBHkTo-cL%rF`jOZXHxjwO3}(6 za(oxx%{r0byU$6D8?On<_k!<_d(puw<>ho9XyncfZsO(rZF+3D23&+wx*dQqSMETJ zoncl)$ZrZ&7HhY}?x(mO#Q@2Yaa&GiLKwLBXN9|%-BSuux|#$w5g}w)ha$3#wnow6 zcu?4lWGmcgvtzw0jH&(_Z3UUqgpDug7=fU!lK7flZsRF!1L%Dq$JWa>U!rV;Sf$Qj zicgN@nby)6v>>MLDAhy=#Qm7y>;Rea86fX zVt}xs$Fj_%T+A#EZtS=08LAj;G~2WRUTFBf$a>9pip2U>$9RGvL`I-##jZOcF|L<( zt634Ii2HkV>1jfS{lIX1>S~9U?pO0TjP!m60w9)sq#WuzOX~vY^UwlAnZbp9e~sW` z!e!yb6iKraJlM11xUv_1j&yNS=7y2lHf=jh;XdU!?2<0Q>Q^IpX z{uP3N6_`1X8g&H3t1`?iv6qJWNWo1lZ8gb+Ey|mY$8X~95lTL9=|iSg{{W_CcC%U8 zP@VwFqgc%_%*GCH0nE2yH9 z21qz-Tw39^BR+x!XTpgtmPdHyZ=+k1EC@egED;$y&mvn?<=3b_TD`h|-A`bK5~R@+ zXSc{x5S&rwAxpn$wh}}3<3vU<{KFmBR~L;J7SvrSvWQ06#g-OlrDYj}Sj_{A9ASqg z>GX;DmtKT$79Vq7+LxE*yZVQqBQ7gXYxR|7yQERp&DE+*Z~<3}%M{a^c6zJ}yVmH5 zC8XoNDFG29nuK3|lg<*mm@*@tZO9;X>RPJSH+zj;Tw9iBxQ?du+Ia)G=L%z7jYQy> zK|Z5`Tt?OHGOe72ha4}D{8~u{(Y(G@mg+FEtXcn<2?n`|QPmi%yZ^Gwpd=XRp8xd@ z&%ZQKuoB~rv)ch^o*%jh^(w%CXHXkOHNo^2miZnzIEPtxIAJ1ZJu)p*)vjpaoQsOR zP1&N3I(7~e`ZlLZfGqe?SsWYw{q_lzM9eypkMO#(hO2z$3&R@_&PZlESz&POz~NT3 zK-|)oB`<$RX~WH=*Dfwti+v9=AP*0qB?zK$N z+<1A?~&zEOE#v&$`4h}Lzy@T8TI(5YN0548nK6A99F>_Og8HQYfzjAr% zrg3I*K0qy~3ra)ux_DP$KLvFXwsKPh>Por7OFKh@*%rE8-g-t!PX{-n=$^hKG+`ki zi2qaH{%*?rTg?2`psAf2RDF^%-miOQP{cOF6wO4c?MkNYbwq4H=h`*M_k&{8^1xth z*@DS{6o#Y>VnH_F;W|8$TNo2vYPDo>R%&u&jk+quJ*l4#)t?uwE8YDgbDFw2OY6Ey zKXT@wW_z0s;i4kgQs#+#QKh5g{vxNwJ{$&J?#uYit$WB5ZkWj|=11KKi zE1a=r9r^0Shrl(Rbuf!MJ|^+P3qJPS3g2gZ9bem0yppeLTqrz^iQsO0 zF?u9w?-;2PfsG|mB0{cyr&9hKFx6G)8RD2@*7CSrfun~;9v1&Kg5cA9_{Xe&poJGnmFx$e-|e6C8*aYxa=gp%^!=) zpYs7?k~P-vwF}gQEL>K63V+czqqgsgZAnDsm4K12HPx|=?e>cJ470)(dgJBumso#N zK!JFq8iFU%boaDeod2xY$pT~pV*Yh!{iTm2INoOnpKCaFW)HNcnX#{{WG#MUi_ zzJiy^P2YLgmYZnt+~THK1F%NEU8+qDLq*P<%Mpz9FLUgjOK#+DC z;xe2?3XtZsPVsOcJP+d#sr2N^V(=41(>AIIcre2pP9eB1TnsDZQN{Ksq4f-V+l1=GD;#q|%eyKieBeAVEe3^aXg1*AniJ zLS1cxnhY^i#AbrUF1cQ8qdaC71~cH}$(zsVx7O%cT9^?g`1-eJ3fakqAVCT!y*ps= zUF?jUq|dc1IJDP(*SgNRfDEG`W))Jga&WnH`7%obb3yKdqDg7{{gx>(U7}$jXA^CWMt7 zYg)*cgUW08!PdzY7t|hKMUS)P9Up-^m>;*Bi+Jd*B|y8h)5WNapLc_JucWgm zGkh*@uJfZZd>-b>R)sj$>+y*XZZIMN@Lb~Zt+C8Yh$5329ZKW8$nXIa?jb`(brHI^>mRew7C{j;zzeY>`Tc)H? z%6^*w0(!*$J#rzbJeKz29BmC*c4%RfxEUE7tt3?L$u6WQ&5B+){n>ImX-=vlOhcFm zy0N37q#MIfi4}JYVlshETw%Gm#SYr8im`e{1X{6jqdYk)l0+`%aIxJ>L(@7!N%5eS z_Y@q2UxZBbsZZbZ<-!Lmvz%h=NKPkv^5A`xUyiHzd5V72PB74d$EHqTJ-nEFd_}6 z%P8kd*L5vstM~*Tx5xQr3hGT6!mUgy1!ke}QXDea$Xba6+=&#w>BY@F+$a2Kp>75D zmuqd&b8S>zFWhD6Ack8i&0)#+wIpIV`4^WB=PmzKRxI+RziKh-l+i8Lirm>27Sf>*-Y8B^qktP?CM~i_(Et)qq?{$XShA zRgB^yE4_Dm&WeF=R5HHJ>^d5hj?NgroP~S8cMUh9!_F1!5lt=>;mu@}o>reom!FmY z@`E7Tu$3ThX+4(Ob-2sdEG@1C6B}k`CQMDKwF0ZsCWTojQu!}4;-pENCUMff{71CW zF!r)r)f4-{9CMk`) zC|@vQHp5q->BD-(zQy7rl@C?#=T8tQ#>3^RQDzMl=e1FNOibIYdv zV}Zs%Fq#TDG}w}(DIBOd8h~M$J8wRV@1tm-10KV>ems=ZX*qXVIG;w9wLL-ct5Iyi z1ySTykx>J$0_8~&;@IBeM_Y;2GQ@a4rV@ss)#4@~_7my@LIsE+0ztD_Krsu=&GdAN z;Uw2SPxsB3^GG%Pq1eMmd=d&aS-dkHLMY@961x2+S?|L_suirPiBTR0gOaa!T(ea* z?iq-Tbys0(nvEWuOSM1-GuWI~OSWGwQ^q&oQv1T-q=if=dxt2uFkHm1O>y3zLy*gz zi@q=j?cUVVSss6o13joox2dvVd_qaX z$y4d&YJz4qUB8(dh17f})1W7*nh&QB4ZjtJJIA(HdY6XR{Q$}{;NYh2S2Cvzrh?t|A7A=lK {{sponsor.primary_contact.name}} + > {{sponsor.name}} + > {{sponsor.mailing_address_line_1}}{%if sponsor.mailing_address_line_2%} + > {{sponsor.mailing_address_line_2 }}{% endif %} + > {{sponsor.city}}, {{sponsor.state}} {{sponsor.postal_code}} {{sponsor.country}} + > Facsimile: {{sponsor.primary_contact.phone}} + > Email: {{sponsor.primary_contact.email}} + + If to the PSF: + + > Deb Nicholson + > Executive Director + > Python Software Foundation + > 9450 SW Gemini Dr. ECM # 90772 + > Beaverton, OR 97008 USA + > Facsimile: +1 (858) 712-8966 + > Email: deb@python.org + + With a copy to: + + > Archer & Greiner, P.C. + > Attention: Noel Fleming + > Three Logan Square + > 1717 Arch Street, Suite 3500 + > Philadelphia, PA 19103 USA + > Facsimile: (215) 963-9999 + > Email: nfleming@archerlaw.com + + Notices given by registered or certified mail shall be deemed as given on the delivery date shown on the return receipt, and notices given in any other manner shall be deemed as given when received. + +1. [**Governing Law; Jurisdiction**]{.underline} This Agreement shall be construed in accordance with the laws of the State of Delaware, without regard to its conflicts of law principles. Jurisdiction and venue for litigation of any dispute, controversy, or claim arising out of or in connection with this Agreement shall be only in a United States federal court in Delaware or a Delaware state court having subject matter jurisdiction. Each of the Parties hereto hereby expressly submits to the personal jurisdiction of the foregoing courts located in Delaware and hereby waives any objection or defense based on personal jurisdiction or venue that might otherwise be asserted to proceedings in such courts. + +1. [**Force Majeure**]{.underline} The PSF shall not be liable for any failure or delay in performing its obligations hereunder if such failure or delay is due in whole or in part to any cause beyond its reasonable control or the reasonable control of its contractors, agents, or suppliers, including, but not limited to, strikes, or other labor disturbances, acts of God, acts of war or terror, floods, sabotage, fire, natural, or other disasters, including pandemics. To the extent the PSF is unable to substantially perform hereunder due to any cause beyond its control as contemplated herein, it may terminate this Agreement as it may decide in its sole discretion. To the extent the PSF so terminates the Agreement, Sponsor releases the PSF and waives any claims for damages or compensation on account of such termination. + +1. [**No Waiver**]{.underline} A waiver of any breach of any provision of this Agreement shall not be deemed a waiver of any repetition of such breach or in any manner affect any other terms of this Agreement. + +1. [**Limitation of Damages**]{.underline} Except as otherwise provided herein, neither Party shall be liable to the other for any consequential, incidental, or punitive damages for any claims arising directly or indirectly out of this Agreement. + +1. [**Cumulative Remedies**]{.underline} All rights and remedies provided in this Agreement are cumulative and not exclusive, and the exercise by either Party of any right or remedy does not preclude the exercise of any other rights or remedies that may now or subsequently be available at law, in equity, by statute, in any other agreement between the Parties, or otherwise. + +1. [**Captions**]{.underline} The captions and headings are included herein for convenience and do not constitute a part of this Agreement. + +1. [**Amendments**]{.underline} No addition to or change in the terms of this Agreement will be binding on any Party unless set forth in writing and executed by both Parties. + +1. [**Counterparts**]{.underline} This Agreement may be executed in one or more counterparts, each of which shall be deemed an original and all of which shall be taken together and deemed to be one instrument. A signed copy of this Agreement delivered by facsimile, electronic mail, or other means of electronic transmission shall be deemed to have the same legal effect as delivery of an original signed copy of this Agreement. + +1. [**Entire Agreement**]{.underline} This Agreement (including the Exhibits) sets forth the entire agreement of the Parties and supersedes all prior oral or written agreements or understandings between the Parties as to the subject matter of this Agreement. Except as otherwise expressly provided herein, neither Party is relying upon any warranties, representations, assurances, or inducements of the other Party. + +  + + +::: {.center} +**[Signature Page Follows]** +::: + +::: {.page-break} +\newpage +::: + +## SPONSORSHIP AGREEMENT + +**IN WITNESS WHEREOF**, the Parties hereto have duly executed this **Sponsorship Agreement** as of the **Effective Date**. + +  + +**PSF**: +**PYTHON SOFTWARE FOUNDATION**, +a Delaware non profit corporation + +  + +By:         ________________________________ +Name:   Loren Crary +Title:     Director of Resource Development + +  + +  + +**SPONSOR**: +**{{sponsor.name|upper}}**, +a {{sponsor.state}} entity + +  + +By:         ________________________________ +Name:   ________________________________ +Title:     ________________________________ + +::: {.page-break} +\newpage +::: + +## SPONSORSHIP AGREEMENT + +### EXHIBIT A + +1. [**Sponsorship**]{.underline} During the Term of this Agreement, in return for the Sponsorship Payment, the PSF agrees to identify and acknowledge Sponsor as a {{sponsorship.year}} {{sponsorship.level_name}} Sponsor of the Programs and of the PSF, in accordance with the United States Internal Revenue Service guidance applicable to qualified sponsorship payments. + + Acknowledgments of appreciation for the Sponsorship Payment may identify and briefly describe Sponsor and its products or product lines in neutral terms and may include Sponsor’s name, logo, well-established slogan, locations, telephone numbers, or website addresses, but such acknowledgments shall not include (a) comparative or qualitative descriptions of Sponsor’s products, services, or facilities; (b) price information or other indications of savings or value associated with Sponsor’s products or services; (c) a call to action; (d) an endorsement; or (e) an inducement to buy, sell, or use Sponsor’s products or services. Any such acknowledgments will be created, or subject to prior review and approval, by the PSF. + + The PSF’s acknowledgment may include the following: + + - [**Display of Logo**]{.underline} The PSF will display Sponsor’s logo and other agreed-upon identifying information on www.python.org, and on any marketing and promotional media made by the PSF in connection with the Programs, solely for the purpose of acknowledging Sponsor as a sponsor of the Programs in a manner (placement, form, content, etc.) reasonably determined by the PSF in its sole discretion. Sponsor agrees to provide all the necessary content and materials for use in connection with such display. + + - Additional acknowledgment as provided in Sponsor Benefits. + +1. [**Sponsorship Payment**]{.underline} The amount of Sponsorship Payment shall be {{sponsorship.verbose_sponsorship_fee|title}} USD ($ {{sponsorship.sponsorship_fee}}). The Sponsorship Payment is due within thirty (30) days of the Effective Date. To the extent that any portion of a payment under this section would not (if made as a Separate payment) be deemed a qualified sponsorship payment under IRC § 513(i), such portion shall be deemed and treated as separate from the qualified sponsorship payment. + +1. [**Receipt of Payment**]{.underline} Sponsor must submit full payment in order to secure Sponsor Benefits. + +1. [**Refunds**]{.underline} The PSF does not offer refunds for sponsorships. The PSF may cancel the event(s) or any part thereof. In that event, the PSF shall determine and refund to Sponsor the proportionate share of the balance of the aggregate Sponsorship fees applicable to event(s) received which remain after deducting all expenses incurred by the PSF. + +1. [**Sponsor Benefits**]{.underline} Sponsor Benefits per the Agreement are: + + 1. Acknowledgement as described under "Sponsorship" above. + +{%for benefit in benefits%} 1. {{benefit}} +{%endfor%} + +{%if legal_clauses%}1. Legal Clauses. Related legal clauses are: + +{%for clause in legal_clauses%} 1. {{clause}} +{%endfor%}{%endif%} diff --git a/templates/sponsors/admin/preview-contract.html b/templates/sponsors/admin/preview-contract.html deleted file mode 100644 index f89fd02b0..000000000 --- a/templates/sponsors/admin/preview-contract.html +++ /dev/null @@ -1,283 +0,0 @@ -{% extends "easy_pdf/base.html" %} -{% load humanize %} - -{% block extra_style %} - -{% endblock %} - -{% block content %} -

SPONSORSHIP AGREEMENT

- -

THIS SPONSORSHIP AGREEMENT (the “Agreement”) is entered into and made -effective as of the {{ start_date|date:"dS" }} day of {{ start_date|date:"F, Y"}} (the “Effective Date”), by and between -Python Software Foundation (the “PSF”), a Delaware nonprofit corporation, and {{ sponsor.name|upper }} (“Sponsor”), a {{ sponsor.state }} corporation. Each of the PSF and Sponsor are -hereinafter sometimes individually referred to as a “Party” and collectively as the “Parties”.

- -

RECITALS

- -

WHEREAS, the PSF is a tax-exempt charitable organization (EIN 04-3594598) whose -mission is to promote, protect, and advance the Python programming language, and to support -and facilitate the growth of a diverse and international community of Python programmers (the -“Programs”);

- -

WHEREAS, Sponsor is {{ contract.sponsor_info}}; and

- -

WHEREAS, Sponsor wishes to support the Programs by making a contribution to the -PSF.

- -

AGREEMENT

- -

NOW, THEREFORE, in consideration of the foregoing and the mutual covenants -contained herein, and for other good and valuable consideration, the receipt and sufficiency of -which are hereby acknowledged, the Parties hereto agree as follows:

- -
    -
  1. Recitals Incorporated. Each of the above Recitals is incorporated into and is made a part of this Agreement.
  2. - -
  3. Exhibits Incorporated by Reference. All exhibits referenced in this Agreement are incorporated herein as integral parts of this Agreement and shall be considered reiterated herein as fully as if such provisions had been set forth verbatim in this Agreement.
  4. - -
  5. Sponsorship Payment. In consideration for the right to sponsor the PSF and its Programs, and to be acknowledged by the PSF as a sponsor in the manner described herein, Sponsor shall make a contribution to the PSF (the “Sponsorship Payment”) in the amount shown in Exhibit A.
  6. - -
  7. Acknowledgement of Sponsor. In return for the Sponsorship Payment, Sponsor will be entitled to receive the sponsorship package described in Exhibit A attached hereto (the “Sponsor Benefits”).
  8. - -
  9. Intellectual Property. The PSF is the sole owner of all right, title, and interest to all the PSF information, including the PSF’s logo, trademarks, trade names, and copyrighted information, unless otherwise provided.
  10. - -
      -
    1. Grant of License by the PSF. The PSF hereby grants to Sponsor a limited, non-exclusive license to use certain of the PSF’s intellectual property, including the PSF’s name, acronym, and logo (collectively, the “PSF Intellectual Property”), solely in connection with promotion of Sponsor’s sponsorship of the Programs. Sponsor agrees that it shall not use the PSF’s Property in a manner that states or implies that the PSF endorses Sponsor (or Sponsor’s products or services). The PSF retains the right, in its sole and absolute discretion, to review and approve in advance all uses of the PSF Intellectual Property, which approval shall not be unreasonably withheld.
    2. - -
    3. Grant of License by Sponsor. Sponsor hereby grants to the PSF a limited, non-exclusive license to use certain of Sponsor’s intellectual property, including names, trademarks, and copyrights (collectively, “Sponsor Intellectual Property”), solely to identify Sponsor as a sponsor of the Programs and the PSF. Sponsor retains the right to review and approve in advance all uses of the Sponsor Intellectual Property, which approval shall not be unreasonably withheld.
    4. -
    - - -
  11. Term. The Term of this Agreement will begin on {{ start_date|date:"dS, F Y"}} and continue for a period of one (1) year. The Agreement may be renewed for one (1) year by written notice from Sponsor to the PSF.
  12. - -
  13. Termination. The Agreement may be terminated (i) by either Party for any reason upon sixty (60) days prior written notice to the other Party; (ii) if one Party notifies the other Party that the other Party is in material breach of its obligations under this Agreement and such breach (if curable) is not cured with fifteen (15) days of such notice; (iii) if both Parties agree to terminate by mutual written consent; or (iv) if any of Sponsor information is found or is reasonably alleged to violate the rights of a third party. The PSF shall also have the unilateral right to terminate this Agreement at any time if it reasonably determines that it would be detrimental to the reputation and goodwill of the PSF or the Programs to continue to accept or use funds from Sponsor. Upon expiration or termination, no further use may be made by either Party of the other’s name, marks, logo or other intellectual property without the express prior written authorization of the other Party.
  14. - -
  15. Code of Conduct. Sponsor and all of its representatives shall conduct themselves at all times in accordance with the Python Software Foundation Code of Conduct (https://www.python.org/psf/codeofconduct) and/or the PyCon Code of Conduct (https://us.pycon.org/2021/about/code-of-conduct/), as applicable. The PSF reserves the right to eject from any event any Sponsor or representative violating those standards.
  16. - -
  17. Deadlines. Company logos, descriptions, banners, advertising pages, tote bag inserts and similar items and information must be provided by the applicable deadlines for inclusion in the promotional materials for the PSF.
  18. - -
  19. Assignment of Space. If the Sponsor Benefits in Exhibit A include a booth or other display space, the PSF shall assign display space to Sponsor for the period of the display. Location assignments will be on a first-come, first-served basis and will be made solely at the discretion of the PSF. Failure to use a reserved space will result in penalties (up to 50% of your Sponsorship Payment).
  20. - -
  21. Job Postings. Sponsor will ensure that any job postings to be published by the PSF on Sponsor’s behalf comply with all applicable municipal, state, provincial, and federal laws.
  22. - -
  23. Representations and Warranties. Each Party represents and warrants for the benefit of the other Party that it has the legal authority to enter into this Agreement and is able to comply with the terms herein. Sponsor represents and warrants for the benefit of the PSF that it has full right and title to the Sponsor Intellectual Property to be provided under this Agreement and is not under any obligation to any party that restricts the Sponsor Intellectual Property or would prevent Sponsor’s performance under this Agreement.
  24. - -
  25. Successors and Assigns. This Agreement and all the terms and provisions hereof shall be binding upon and inure to the benefit of the Parties and their respective legal representatives, heirs, successors, and/or assigns. The transfer, or any attempted assignment or transfer, of all or any portion of this Agreement by a Party without the prior written consent of the other Party shall be null and void and of no effect.
  26. - -
  27. No Third-Party Beneficiaries. This Agreement is not intended to benefit and shall not be construed to confer upon any person, other than the Parties, any rights, remedies, or other benefits, including but not limited to third-party beneficiary rights.
  28. - -
  29. Severability. If any one or more of the provisions of this Agreement shall be held to be invalid, illegal, or unenforceable, the validity, legality, or enforceability of the remaining provisions of this Agreement shall not be affected thereby. To the extent permitted by applicable law, each Party waives any provision of law which renders any provision of this Agreement invalid, illegal, or unenforceable in any respect.
  30. - -
  31. Confidential Information. As used herein, “Confidential Information” means all confidential information disclosed by a Party (“Disclosing Party”) to the other Party (“Receiving Party”), whether orally or in writing, that is designated as confidential or that reasonably should be understood to be confidential given the nature of the information. Each Party agrees: (a) to observe complete confidentiality with respect to the Confidential Information of the Disclosing Party; (b) not to disclose, or permit any third party or entity access to disclose, the Confidential Information (or any portion thereof) of the Disclosing Party without prior written permission of Disclosing Party; and (c) to ensure that any employees, or any third parties who receive access to the Confidential Information, are advised of the confidential and proprietary nature thereof and are prohibited from disclosing the Confidential Information and using the Confidential Information other than for the benefit of the Receiving Party in accordance with this Agreement. Without limiting the foregoing, each Party shall use the same degree of care that it uses to protect the confidentiality of its own confidential information of like kind, but in no event less than reasonable care. Neither Party shall have any liability with respect to Confidential Information to the extent such information: (w) is or becomes publicly available (other than through a breach of this Agreement); (x) is or becomes available to the Receiving Party on a non-confidential basis, provided that the source of such information was not known by the Receiving Party (after such inquiry as would be reasonable in the circumstances) to be the subject of a confidentiality agreement or other legal or contractual obligation of confidentiality with respect to such information; (y) is developed by the Receiving Party independently and without reference to information provided by the Disclosing Party; or (z) is required to be disclosed by law or court order, provided the Receiving Party gives the Disclosing Party prior notice of such compelled disclosure (to the extent legally permitted) and reasonable assistance, at the Disclosing Party’s cost.
  32. - -
  33. Independent Contractors. Nothing contained herein shall constitute or be construed as the creation of any partnership, agency, or joint venture relationship between the Parties. Neither of the Parties shall have the right to obligate or bind the other Party in any manner whatsoever, and nothing herein contained shall give or is intended to give any rights of any kind to any third party. The relationship of the Parties shall be as independent contractors.
  34. - -
  35. Indemnification. Sponsor agrees to indemnify and hold harmless the PSF, its officers, directors, employees, and agents, for any and all claims, losses, damages, liabilities, judgments, or settlements, including reasonable attorneys’ fees, costs (including costs associated with any official investigations or inquiries) and other expenses, incurred on account of Sponsor’s acts or omissions in connection with the performance of this Agreement or breach of this Agreement or with respect to the manufacture, marketing, sale, or dissemination of any of Sponsor’s products or services. The PSF shall have no liability to Sponsor with respect to its participation in this Agreement or receipt of the Sponsorship Payment, except for intentional or willful acts of the PSF or its employees or agents. The rights and responsibilities established in this section shall survive indefinitely beyond the term of this Agreement.
  36. - -
  37. - Notices. All notices or other communications to be given or delivered under the provisions of this Agreement shall be in writing and shall be mailed by certified or registered mail, return receipt requested, or given or delivered by reputable courier, facsimile, or electronic mail to the Party to receive notice at the following addresses or at such other address as any Party may by notice direct in accordance with this Section: - -
    -
    -

    If to Sponsor:

    -
    -

    {{ sponsor.primary_contact.name }}

    -

    {{ sponsor.name }}

    -

    {{ sponsor.mailing_address_line_1 }}

    - {% if sponsor.mailing_address_line_2 %} -

    {{ sponsor.mailing_address_line_2 }}

    - {% endif %} -

    Facsimile: {{ sponsor.primary_contact.phone }}

    -

    Email: {{ sponsor.primary_contact.email }}

    -
    -

    If to the PSF:

    -
    -

    Ewa Jodlowska

    -

    Executive Director

    -

    Python Software Foundation

    -

    9450 SW Gemini Dr. ECM # 90772

    -

    Beaverton, OR 97008 USA

    -

    Facsimile: +1 (858) 712-8966

    -

    Email: ewa@python.org

    -
    -

    With a copy to:

    -

    Fleming Petenko Law

    -

    1800 John F. Kennedy Blvd

    -

    Suite 904

    -

    Philadelphia, PA 19103 USA

    -

    Facsimile: (267) 422-9864

    -

    Email: info@nonprofitlawllc.com

    -
    -
    -

    Notices given by registered or certified mail shall be deemed as given on the delivery date shown on the return receipt, and notices given in any other manner shall be deemed as given when received.

    -
  38. - -
  39. Governing Law; Jurisdiction. This Agreement shall be construed in accordance with the laws of the State of Delaware, without regard to its conflicts of law principles. Jurisdiction and venue for litigation of any dispute, controversy, or claim arising out of or in connection with this Agreement shall be only in a United States federal court in Delaware or a Delaware state court having subject matter jurisdiction. Each of the Parties hereto hereby expressly submits to the personal jurisdiction of the foregoing courts located in Delaware and hereby waives any objection or defense based on personal jurisdiction or venue that might otherwise be asserted to proceedings in such courts.
  40. - -
  41. Force Majeure. The PSF shall not be liable for any failure or delay in performing its obligations hereunder if such failure or delay is due in whole or in part to any cause beyond its reasonable control or the reasonable control of its contractors, agents, or suppliers, including, but not limited to, strikes, or other labor disturbances, acts of God, acts of war or terror, floods, sabotage, fire, natural, or other disasters, including pandemics. To the extent the PSF is unable to substantially perform hereunder due to any cause beyond its control as contemplated herein, it may terminate this Agreement as it may decide in its sole discretion. To the extent the PSF so terminates the Agreement, Sponsor releases the PSF and waives any claims for damages or compensation on account of such termination.
  42. - -
  43. No Waiver. A waiver of any breach of any provision of this Agreement shall not be deemed a waiver of any repetition of such breach or in any manner affect any other terms of this Agreement.
  44. - -
  45. Limitation of Damages. Except as otherwise provided herein, neither Party shall be liable to the other for any consequential, incidental, or punitive damages for any claims arising directly or indirectly out of this Agreement.
  46. - -
  47. Cumulative Remedies. All rights and remedies provided in this Agreement are cumulative and not exclusive, and the exercise by either Party of any right or remedy does not preclude the exercise of any other rights or remedies that may now or subsequently be available at law, in equity, by statute, in any other agreement between the Parties, or otherwise.
  48. - -
  49. Captions. The captions and headings are included herein for convenience and do not constitute a part of this Agreement.
  50. - -
  51. Amendments. No addition to or change in the terms of this Agreement will be binding on any Party unless set forth in writing and executed by both Parties.
  52. - -
  53. Counterparts. This Agreement may be executed in one or more counterparts, each of which shall be deemed an original and all of which shall be taken together and deemed to be one instrument. A signed copy of this Agreement delivered by facsimile, electronic mail, or other means of electronic transmission shall be deemed to have the same legal effect as delivery of an original signed copy of this Agreement.
  54. - -
  55. Entire Agreement. This Agreement (including the Exhibits) sets forth the entire agreement of the Parties and supersedes all prior oral or written agreements or understandings between the Parties as to the subject matter of this Agreement. Except as otherwise expressly provided herein, neither Party is relying upon any warranties, representations, assurances, or inducements of the other Party.
  56. -
- -

[Signature Page Follows]

-
- -

SPONSORSHIP AGREEMENT

- - -

IN WITNESS WHEREOF, the Parties hereto have duly executed this __________________ Agreement as of the Effective Date.

- -
-

PSF:

-

PYTHON SOFTWARE FOUNDATION,

-

a Delaware nonprofit corporation

- -
-
- -

By: - ___________________________________

-
-

Ewa Jodlowska

-

Executive Director

-
- -
-
- -

SPONSOR:

-

______________________________________,

-

a {{ sponsor.state }} entity.

-
-

By: ___________________________________

- -
-
- -

SPONSORSHIP AGREEMENT

- -

EXHIBIT A

- -
    -
  1. Sponsorship. During the Term of this Agreement, in return for the Sponsorship Payment, the PSF agrees to identify and acknowledge Sponsor as a {{ start_date|date:'Y' }} {{ sponsorship.level_name }} Sponsor of the Programs and of the PSF, in accordance with the United States Internal Revenue Service guidance applicable to qualified sponsorship payments.
  2. - -

    Acknowledgments of appreciation for the Sponsorship Payment may identify and briefly describe Sponsor and its products or product lines in neutral terms and may include Sponsor’s name, logo, well-established slogan, locations, telephone numbers, or website addresses, but such acknowledgments shall not include (a) comparative or qualitative descriptions of Sponsor’s products, services, or facilities; (b) price information or other indications of savings or value associated with Sponsor’s products or services; (c) a call to action; (d) an endorsement; or (e) an inducement to buy, sell, or use Sponsor’s products or services. Any such acknowledgments will be created, or subject to prior review and approval, by the PSF.

    - -

    The PSF’s acknowledgment may include the following:

    - -
      -
    1. Display of Logo. The PSF will display Sponsor’s logo and other agreed-upon identifying information on www.python.org, and on any marketing and promotional media made by the PSF in connection with the Programs, solely for the purpose of acknowledging Sponsor as a sponsor of the Programs in a manner (placement, form, content, etc.) reasonably determined by the PSF in its sole discretion. Sponsor agrees to provide all the necessary content and materials for use in connection with such display.
    2. - -
    3. [Other use or Acknowledgement.]
    4. -
    - -
  3. Sponsorship Payment. The amount of Sponsorship Payment shall be {{ sponsorship.verbose_sponsorship_fee|title }} USD ($ {{ sponsorship.sponsorship_fee|intcomma }}). The Sponsorship Payment is due within thirty (30) days of the Effective Date. To the extent that any portion of a payment under this section would not (if made as a Separate payment) be deemed a qualified sponsorship payment under IRC § 513(i), such portion shall be deemed and treated as separate from the qualified sponsorship payment.
  4. - -
  5. Receipt of Payment. Sponsor must submit full payment in order to secure Sponsor Benefits.
  6. - -
  7. Refunds. The PSF does not offer refunds for sponsorships. The PSF may cancel the event(s) or any part thereof. In that event, the PSF shall determine and refund to Sponsor the proportionate share of the balance of the aggregate Sponsorship fees applicable to event(s) received which remain after deducting all expenses incurred by the PSF.
  8. - -
  9. Sponsor Benefits. Sponsor Benefits per the Agreement are:
  10. - -
      -
    1. Acknowledgement as described under “Sponsorship” above.
    2. - {% for benefit in benefits %} -
    3. {{ benefit }}
    4. - {% endfor %} -
    - - - {% if legal_clauses %} -
  11. Legal Clauses. Related legal clauses are:
  12. -
      - {% for clause in legal_clauses %} -
    1. {{ clause }}
    2. - {% endfor %} -
    - {% endif %} -
- -{% endblock %}