From 03452480e402d8c3c6410e2315374559bd4a8872 Mon Sep 17 00:00:00 2001 From: "Ernest W. Durbin III" Date: Thu, 12 Nov 2020 08:03:50 -0500 Subject: [PATCH 001/235] Check package only benefits as well (#1670) (#1671) A package only benefit's checkbox is rendered in the HTML with the disabled attribute. Because of that, the click event wasn't being triggered by the browser. This fix turn off and on this attribute so the click event can happen. Co-authored-by: Bernardo Fontes --- static/js/sponsors/applicationForm.js | 14 ++++++++++++-- templates/sponsors/sponsorship_benefits_form.html | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/static/js/sponsors/applicationForm.js b/static/js/sponsors/applicationForm.js index 558afb142..56189e374 100644 --- a/static/js/sponsors/applicationForm.js +++ b/static/js/sponsors/applicationForm.js @@ -17,12 +17,17 @@ $(document).ready(function(){ checkboxesContainer.find(':checkbox').each(function(){ $(this).prop('checked', false); + let packageOnlyBenefit = $(this).attr("package_only"); + if (packageOnlyBenefit) $(this).attr("disabled", true); }); let packageInfo = $("#package_benefits_" + package); packageInfo.children().each(function(){ let benefit = $(this).html() - checkboxesContainer.find(`[value=${benefit}]`).trigger("click"); + let benefitInput = checkboxesContainer.find(`[value=${benefit}]`); + let packageOnlyBenefit = benefitInput.attr("package_only"); + benefitInput.removeAttr("disabled"); + benefitInput.trigger("click"); }); let url = $("#cost_container").attr("calculate_cost_url"); @@ -38,7 +43,12 @@ $(document).ready(function(){ if (costLabel.html() != "Updating cost...") costLabel.html("Submit your application and we'll get in touch..."); let active = checkboxesContainer.find(`[value=${benefit}]`).prop("checked"); - if (!active) return; + if (!active) { + let packageOnlyBenefit = $(this).attr("package_only"); + if (packageOnlyBenefit) $(this).attr("disabled", true); + return; + } + $(`#conflicts_with_${benefit}`).children().each(function(){ let conflictId = $(this).html(); diff --git a/templates/sponsors/sponsorship_benefits_form.html b/templates/sponsors/sponsorship_benefits_form.html index f91e62351..27a85ad73 100644 --- a/templates/sponsors/sponsorship_benefits_form.html +++ b/templates/sponsors/sponsorship_benefits_form.html @@ -48,7 +48,7 @@

{{ field.label }}

{% for benefit in field.field.queryset %}
  • + {% if sp.unlocked and sp.status != sp.APPLIED %} +
  • + Lock +
  • + {% endif %} + + {% if sp.locked and sp.status == sp.FINALIZED %} +
  • + Unlock +
  • + {% endif %} + {% endwith %} {{ block.super }} diff --git a/templates/sponsors/admin/unlock.html b/templates/sponsors/admin/unlock.html new file mode 100644 index 000000000..bca6c853d --- /dev/null +++ b/templates/sponsors/admin/unlock.html @@ -0,0 +1,35 @@ +{% extends 'admin/base_site.html' %} +{% load i18n static sponsors %} + +{% block extrastyle %}{{ block.super }}{% endblock %} + +{% block title %}Unlock Finalized Sponsorship {{ sponsorship }} | python.org{% endblock %} + +{% block breadcrumbs %} + +{% endblock %} + +{% block content %} +

    Unlock Finalized Sponsorship

    +

    Please review the sponsorship application and click in the Unlock button if you want to proceed.

    +
    +
    +{% csrf_token %} + +
    {% full_sponsorship sponsorship display_fee=True %}
    + + + +
    + +
    + +
    +
    +
    {% endblock %} From 49a1e2a4c5f68d809d64f1837241b22d57322ed1 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Mon, 6 Mar 2023 07:38:42 -0500 Subject: [PATCH 008/235] bump rate limit for api --- pydotorg/settings/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index d5eb568a6..22a8ae71e 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -309,7 +309,7 @@ ), 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', - 'user': '1000/day', + 'user': '3000/day', }, } From 88d42f786f857a30ab3e29fffd39a2e05e9d2f62 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Sat, 18 Mar 2023 08:19:52 -0400 Subject: [PATCH 009/235] sponsorship form: fix rendering of application form When benefits are configured for packages that are to the right of packages that *do not* have a benefit, we should correctly render. This was effectively "gravity left" for the icons on the application. --- templates/sponsors/sponsorship_benefits_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/sponsors/sponsorship_benefits_form.html b/templates/sponsors/sponsorship_benefits_form.html index 9b35a9ff8..309bac057 100644 --- a/templates/sponsors/sponsorship_benefits_form.html +++ b/templates/sponsors/sponsorship_benefits_form.html @@ -96,7 +96,7 @@

    {{ benefit.name }}

    {% for package in form.fields.package.queryset %}
    - {% if forloop.counter <= benefit.num_packages %} + {% if benefit in package.benefits.all %} Date: Tue, 21 Mar 2023 05:13:25 -0400 Subject: [PATCH 010/235] enable customizing admin (#2263) psf staff spend a lot of time between us.pycon.org and python.org django admin this enables configuration of a different theme for python.org so its easier to differentiate. thanks to @swiencks for pointing out how easy to confuse they are. --- base-requirements.txt | 5 ++++- pydotorg/settings/base.py | 15 ++++++++++++--- pydotorg/settings/heroku.py | 12 ------------ templates/admin/base_site.html | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/base-requirements.txt b/base-requirements.txt index 4832f0ee6..b19aacc93 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -1,11 +1,14 @@ dj-database-url==0.5.0 django-pipeline==2.0.6 django-sitetree==1.17.0 +django-apptemplates==1.5 +django-admin-interface==0.24.2 +django-translation-aliases==0.1.0 Django==2.2.24 docutils==0.12 Markdown==3.3.4 cmarkgfm==0.6.0 -Pillow==8.3.1 +Pillow==9.4.0 psycopg2-binary==2.8.6 python3-openid==3.2.0 python-decouple==3.4 diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 22a8ae71e..4bd30b408 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -94,8 +94,12 @@ 'DIRS': [ TEMPLATES_DIR, ], - 'APP_DIRS': True, 'OPTIONS': { + 'loaders': [ + 'apptemplates.Loader', + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + ], 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.i18n', @@ -151,10 +155,14 @@ 'django.contrib.redirects', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.humanize', + + 'admin_interface', + 'colorfield', 'django.contrib.admin', 'django.contrib.admindocs', - 'django.contrib.humanize', + 'django_translation_aliases', 'pipeline', 'sitetree', 'imagekit', @@ -288,7 +296,8 @@ ### SecurityMiddleware -X_FRAME_OPTIONS = 'DENY' +X_FRAME_OPTIONS = 'SAMEORIGIN' +SILENCED_SYSTEM_CHECKS = ["security.W019"] ### django-rest-framework diff --git a/pydotorg/settings/heroku.py b/pydotorg/settings/heroku.py index 5adff485c..4a0e4cc35 100644 --- a/pydotorg/settings/heroku.py +++ b/pydotorg/settings/heroku.py @@ -20,18 +20,6 @@ } } -HAYSTACK_SEARCHBOX_SSL_URL = config( - 'SEARCHBOX_SSL_URL' -) - -HAYSTACK_CONNECTIONS = { - 'default': { - 'ENGINE': 'haystack.backends.elasticsearch5_backend.Elasticsearch5SearchEngine', - 'URL': HAYSTACK_SEARCHBOX_SSL_URL, - 'INDEX_NAME': 'haystack-prod', - }, -} - SECRET_KEY = config('SECRET_KEY') ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv()) diff --git a/templates/admin/base_site.html b/templates/admin/base_site.html index 85ef099d7..ce757a4d2 100644 --- a/templates/admin/base_site.html +++ b/templates/admin/base_site.html @@ -1,4 +1,4 @@ -{% extends "admin/base.html" %} +{% extends "admin_interface:admin/base_site.html" %} {% load i18n %} {% block title %}{{ title }} | {% trans 'python.org' %}{% endblock %} From 55b298dd73a82ce55c46acbb48bf1d477b462fde Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Tue, 21 Mar 2023 05:59:24 -0400 Subject: [PATCH 011/235] revert inadvertently committed. was headed this direction while responding to https://status.python.org/incidents/kwsfwt5q4rg1 --- pydotorg/settings/heroku.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pydotorg/settings/heroku.py b/pydotorg/settings/heroku.py index 4a0e4cc35..5adff485c 100644 --- a/pydotorg/settings/heroku.py +++ b/pydotorg/settings/heroku.py @@ -20,6 +20,18 @@ } } +HAYSTACK_SEARCHBOX_SSL_URL = config( + 'SEARCHBOX_SSL_URL' +) + +HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'haystack.backends.elasticsearch5_backend.Elasticsearch5SearchEngine', + 'URL': HAYSTACK_SEARCHBOX_SSL_URL, + 'INDEX_NAME': 'haystack-prod', + }, +} + SECRET_KEY = config('SECRET_KEY') ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv()) From 0422be5e0f4241475abc8062eaeb04cf05ce7392 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Fri, 12 May 2023 13:41:49 -0400 Subject: [PATCH 012/235] add notes regarding basic membership (#2271) --- templates/includes/authenticated.html | 4 ++-- templates/users/membership_form.html | 12 ++++++++++++ templates/users/user_detail.html | 18 +++++++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/templates/includes/authenticated.html b/templates/includes/authenticated.html index bdd2c671e..82d5b38f6 100644 --- a/templates/includes/authenticated.html +++ b/templates/includes/authenticated.html @@ -7,9 +7,9 @@
  • Edit your user profile
  • Change your password
  • {% if request.user.has_membership %} -
  • Edit your PSF membership
  • +
  • Edit your PSF Basic membership
  • {% else %} -
  • Become a PSF member
  • +
  • Become a PSF Basic member
  • {% endif %} {% if request.user.sponsorships %}
  • Sponsorships diff --git a/templates/users/membership_form.html b/templates/users/membership_form.html index cef557897..ecc032467 100644 --- a/templates/users/membership_form.html +++ b/templates/users/membership_form.html @@ -19,6 +19,18 @@

    Register to become a PSF Basic Member

    {% endif %}
    +

    + Basic membership is not a voting membership class.
    For more information see Article IV + of the PSF Bylaws. +

    +

    + All other membership classes are recorded on psfmember.org.
    + Please log in there and review your user profile + to see your membership status.
    + If you believe you are a member but do not have an account on psfmember.org, please + create an account and verify your + email, then email psf-donations@python.org to get your account linked to your membership. +

    For more information and to sign up for other kinds of PSF membership, visit our Membership Page.

    diff --git a/templates/users/user_detail.html b/templates/users/user_detail.html index f584af139..ce2f5ee90 100644 --- a/templates/users/user_detail.html +++ b/templates/users/user_detail.html @@ -21,7 +21,23 @@

    Name: {% firstof object.get_full_name object %}

  • {% comment %} From c4ee749942227ca75c8e670546afe67232d647b2 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 3 Aug 2023 15:12:29 -0400 Subject: [PATCH 020/235] Update feature_request.md --- .github/ISSUE_TEMPLATE/feature_request.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 316039ee5..514274e5f 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -8,11 +8,10 @@ This is the repository and issue tracker for https://www.python.org website. If you're looking to file an issue with CPython itself, please go to -https://bugs.python.org +https://github.com/python/cpython/issues/new/choose Issues related to Python's documentation (https://docs.python.org) can -also be filed in https://bugs.python.org, by selecting the -"Documentation" component. +also be filed at https://github.com/python/cpython/issues/new?assignees=&labels=docs&template=documentation.md. --> **Is your feature request related to a problem? Please describe.** From ad5e23fc4f6d5d26386f6a355096c459580ed0ad Mon Sep 17 00:00:00 2001 From: Michael Cohen Date: Tue, 14 Nov 2023 05:30:01 -0800 Subject: [PATCH 021/235] Update python.org socialize menu to include a link to the PSF Mastodon account (#2323) * Update python.org socialize menu to include a link to the PSF Mastodon account Updated socialize menu to include a link to the official PSF Mastodon account. Details: - Added Mastodon icon to Pythonicon font family. Used IcoMoon to generate icons - Updated all related CSS and Sass files - Updated the socialize menu in the base.html template To see all rendered Pythonicon fonts, open `static/fonts/demo.html` * Updated help and close icons unicodes Help icon is now assigned unicode `\3f` (`?`). Close icon is now assigned unicode `\58` (`X`). Required regenerating fonts and updating CSS + Sass files. --- static/fonts/Pythonicon.eot | Bin 14020 -> 12628 bytes static/fonts/Pythonicon.json | 1906 ++++++++++++++++++++-------------- static/fonts/Pythonicon.svg | 84 +- static/fonts/Pythonicon.ttf | Bin 13840 -> 12452 bytes static/fonts/Pythonicon.woff | Bin 13916 -> 12528 bytes static/fonts/demo.html | 601 +++++++++++ static/fonts/demo/demo.css | 155 +++ static/fonts/demo/demo.js | 30 + static/fonts/index.html | 410 -------- static/fonts/style.css | 192 ++-- static/sass/_fonts.scss | 97 +- static/sass/style.css | 266 ++--- static/sass/style.scss | 2 +- templates/base.html | 5 +- 14 files changed, 2233 insertions(+), 1515 deletions(-) mode change 100755 => 100644 static/fonts/Pythonicon.eot mode change 100755 => 100644 static/fonts/Pythonicon.json mode change 100755 => 100644 static/fonts/Pythonicon.svg mode change 100755 => 100644 static/fonts/Pythonicon.ttf mode change 100755 => 100644 static/fonts/Pythonicon.woff create mode 100644 static/fonts/demo.html create mode 100644 static/fonts/demo/demo.css create mode 100644 static/fonts/demo/demo.js delete mode 100644 static/fonts/index.html diff --git a/static/fonts/Pythonicon.eot b/static/fonts/Pythonicon.eot old mode 100755 new mode 100644 index db8f2b452a8ee11b20fbaf60cba52cd5bda1ea62..f36815ed5b87531373e95e1be7916f592e2a14d9 GIT binary patch literal 12628 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 literal 14020 zcmcJ03zQtyd1l?Z^{%e!uCA`GeosH9r)Nf^(Y$(Envq(gK?w2G@)X1vNeB?KLC6S# z20fh>dY@f;rv|j&1x{$Ge#9APcfylX%aGcYRF!SR0(+^?DDxIf)&!OxNu9 zS9gyF(F5efTQgPn*1fmx!l>kufAz-lvv2mq%NL$~ z>*kWeLE&EEF5y<;4&i{XU)UR_hfr+`R|q!?`-HoN+k`#BohV5P*P!H1;SkzU>!L6w zjN+!6)p|iC&C3*y3tSl6apk%R`%C|DIZFN<_wK#7?>YF@y$tUxhxhCE?KyN1X$+lm1 z5p5@_pC@m-WAC2deCmH<@>40iUvvAO!v}>8;$PvN>Wc^V+r|g%)B-5$gTV8WQ@s%1sy@Wr0T9`YhZ83Z& zMAC=}JPA?>K@zqjwFM1GRxpRn!nLm`uS8y{EiIwE{Vu$sy<#sdExok#+|uVWQif;5 z@M|!9MRY|u#%gS!L1@IK(~^K$rG&ijKCHb|wnfiL6vWBWL{qFgQ=?*qSL&0V zYjZXH_bTYPBQ02+^EU9%*C%VE^)4Cx-2_>KCaukEJ}(b84*jZu3A%T zjatKR_^QvvbEihrZT#Wmk1zl8Grd;O+O^yO8N!*2TLjLI3&Yr!|62H@@IB0c@U)(f zSH?m#ct9ZFKR$^fLL)DSNCKYD;;w_EE}BBzRv4ky=9OVSu6q91j2O1UXMW8s@Xf3# z4yQD9E4Ll}(tZxmijvItf9dG9E3;$$-XBYko-g;^lJ1O=m5!(Gaa{+O3q!aTK$=j$a|FMnt(s(Im$2V}H*$7numk0%qG& z5IL7n#5sGbI?=uO)ZUq~`SX)bb#TP@M+U1-^8ER+nZ2hj4qo80EXr0aZus@t&85=j z*}8AUV-^Z!5cBGFY}y^D_B)sl+jZ?OEJSqrs{`)$(!qkF%S>D+>SjdwyLU4YGn5ro z0_~D$6?v4eVU%0L@LisTlqF7M^KW96Ix&exlT8iOSoec&2jcC~ zzP`R_w2;qQ1M4#StHINmv07f$G)-5MeM6ZmQbW^)SJP{Xu3K7@dP$E(R5cRQyQ#QS zadWlIbz!Sir&VtKOtYL^Q%bzbZq8J*37xLsL)~w>DgQR17-$z&uP~T-S0P$hTPSZ> zKU>L+6yvw&r-xE*X(au#)NnB=eJUK)q0yai^uMD<@9ArVjZ!~L)e4@f=}b42M81a3 zoZ?6}w|;i6KbSrDQ@~#ZZ+H>B;YIL5tMY%U4SW^kt2ge(%4p2OOn6EecMFulCC9ax=% zm5h%~rC42FAwMb{9H}xkELMmvHuCY3!?C22yu2oQt9$gQ)=N%_FCor1gF_8~lZMU+Wa5Vg5+4$gs^@-|QbRSifN7tkz_U zi(PpmZf#{$T`f(Y-{1eYzdF76nE0!8M~}_V2PbjQ&mWzi7hexf1AXAH^Mc0zJwE~& zToTp`JA~`8IueT{6^WY?uSM^?;e%=5=G)=z#Tzza!{J7$HX*>7=^<-y~apga~fRdC& zeT)NH5|XAw~2=VFBK?C$>7a!&kQYiFgoE}LD~tcaiM=7JsfY}skHx(mhD$#5$r5L)#C0#dUC1U7Y7ZpvDz_3L-Gmz3E;L?yYo85wEI>pgkYAE8` zs^+AfSURT3M%2g}K%HvE4Wt@Ulg|;CSUD-0=y96UxwC6s^PTUozy8a=4Ay-*-Zz|f ziz!DcYEjGJYCM^Zr3UjcaJBY7INTJ2Y?DkYswD>taR>}3NRlM6q?*W9Jby6nJQ-nz z-_z}kDYAUamraI z_)%uGoJf>MGhFWG&X9JXd#Q|d(#oVfoz#TW-AZ<)YB`4CSSq`+Tha(sonZ145DcmY-;^- z;XJz6!tTQnHH@gyZVexyo(7l-&=CvZB9{w~37EC)+!!F$`_IBgMxjRoYQ9HenrFJoNZUk8SPSFp}{G>U|>{ ztDq;wqshFZShlU^ys~ddQnEPcp*&GaLMIMie%woa4gQB7^DQf;^GH0Qdil7Po8B?G z_VP{rr45&@g=(kEimAyWC>45<%&VK$q>A;e{eLrlzLSaT?8#H(r|{1%iuVoq5XEt) zFqGnoqHxP|-3Yi7W1nDdd0j3$UQMz@WnDH0&5^y_OM(TTc8dA5X+W9RRo8XoXrWX~ z<=2m7MkkcpFF?Rn#aFRX#)0cvuhLS3@Yl4@>xqvF?g42sHz4TyL_B@E* zgbpp(&EikplVID9T2%AM#>xu9#CcElY{cQ_E8mT&@KzNS$!}PnpG5DFu z;LnVHrLTXA9o^6im91U0i@Lk%ouvHQ^6ZYat(U~UwL50Ze7H6f{4m`rw*F~yrcc{o ziPwI=7nT;kOPh!|qedJOn<{wwg3H(L*jRzEx`###HUUqna2R^XLwo@;dMJeFO>js& zLXxT3md{=3;J>K=HEIF;YBH4L#Gt}V_X9O#W2g)zRHYieLM0=aPmfMJUxh@U^c(oR z;X~NhMV1`M#bUXEWH)`i%W%4BGMY_!8rizvc8hCLt$*lNbkiiMx!;DN!Zk0IjWV~m zemKP@Qp4+u?7ofret*YhzrSx|YNR>f>^2gKgfTvDdS1fV?F=+WQp{U9I87o)+^*X< zrBx;37~w`gaFah+aH?-=;1mY^n+~Y9Z7GHmQObU8s_?`Ug{hh^Uf5-rPG8p7zxX(r zA!p9e^YJh0ezwm6UZfTNgg&8PSObjoq-xdoY7Nh=xDDQ@H)?f%6*oc9IC5lZ>7$o? z{?gCCde1$tz1G{z4-VXR+rc0G=wNW2cn@nmwD;h?eFtBB5%aN^_gzX@3%zb9_T78o zq`F)9J>eMS+y{k^3ZGbIj%s(ubvIn)Z40ng2t~IPsz!VgJa?AiAus2`*YE+oh=gQg zxvICDL|wU6Xr}~kTflx0Y+AWtzV*l>fAz>Ct;fOyIs69`kK{(`>FMyLx8LFFcftc! z@{GktX?L=p1SR4J;=K>!`W`*#3O@O8-}Im#=7E-TbnH#SRd6l710B0j^V@25DER(` zdNyfMcRa;axEn|v{_QH;aA2tXiw8(oqmJLHzP-}+SOcx0H(WdrqEChecu{C*EE^+o zK}@_sDWH}O6{_}X2FMDdVuh*kMze%n0cD`O3`$9~OMiOsmA5uRHZ7YK%Z5hq{grmf zPv9w$c^CL0j3Dz5eC54wutLa3+18^{!T`CMdvX-H1l`L`GRzQGJpcb>bbBo-=phiz&maHp-@^H?x`@Duu|SiwU@B z;1Bb|EKDJmP}FDhbX|1mMPV9dUiYdKx$^8tCd;<>67Em!SEA9V(t>8CSZ${vt@QmPpSTm{nU3W>?PMMWEJ#Fz0=iy z-3`~*Fv4;Jz>b6OI{eFgEQB5W{%;Gp-zJcL{o8{_Q2b}D9KPEQEtB3dFB~SD;7uyX zn@ro@rhrFUK4^?cg~R^t`sF(oHEgkt)6SD&SC^pqhsHzO=zzCx+3(l>fQU=ntyzYm z7^I%H(}ixPo3a~wkywyE&nsu*GT5G~q>43<+0U!qK%eQS(w3FUWUNGgHWtnHC!SBQ zEhogg)L63M1wVM+$yMCk%HL=(=30nzqsxd!@9agf;~pJf1Blp7AhdqCAq4lhurk7BIJEO=X&@ z#M8yZGc@Hyd2M!UcHJmE ztHd+L%Ig`t@MF2q^W?+08{2qRSIzNpd|n|ptO|=f#I_nbWr-@#*9_eMAPlgSQ4a1B z-f+N?VjGr)8g7C2F`^!@r!WJh*2^)Q!TFCIh8`C`6!FMY;6=J=u-MIYQ+9tZnz)=4 zSvc8oN!Gwbvp=G#rYgZJD|7NbD5}C3eBKhb6PCgy8CIes>QOJW{8UtHs32GQ%-~2q z>%(zf%fWLY<1^r1k3qEBO9sx&1q5@|YdG;Z7;iGXXmHxQMqlH2t8oHvn7%Nq( zE-B#nMzsByE?x{DNF>tsh4f6>-Mz>wcwYp_(si67a8XYW77~i6Yca>szaZeOR?jm2r5<<$H>w zlP=HoWw6?~6H^UQcJsBgj#CSaY0$wyxb);utv|-O1|F~JE>5TzyiO5-pfd^+P1sqY znM@{4*?{@WMQ32mSQZ}>J&QsaHt$dQH*kClpI>M}g~xtm>4a_{*8?pOv2`@zM*SRL zoG1XFh7o#`+Ue>3*)7_~$9FaSp_%^8`!5;3_~cW2_da#<;^9l)vzZ-*?;y$+ zqCf)Wf_ciZAAHQ;eDT$z+mG#P(AT3^U%c7>Snj$zAH0Y@qz*26@XqV#ka&gsCEflq z97Xrm3|ME@MC0Kqs@ODLlTWRmRVdZT)hc?s-Giay6FcdYqPJPI_;oT9yPZ>No2g9J z9@<{-leCETu%ya->bk>QZSo99(%`aJfBcR)8tmhA7Pj*fFB}SaFNFy#>rilX^wdK* zoO*EUg_bXwD52pyxr$x3YyThZ*byJxvTpx;+%xz+c5lTg5aA^``oNCCxe@;X)k;|N z4-npj4?u5{a3<{vKKvo=`Q*V1LbSMb)vtPunp~5Kg_6^yURC+=#n;IKWq~M?3+`yE zwJ5yy8VgPb&vjge5G=v7-{ca#$}J{vY9DM_JbLv1{^tJsTf6^=-re%r%pdP2x?gdI zTU-q$@cvZb1nNxyTY{4d?0$Ca*;N;Rn$59e!HIV?7NgUTI(B!@qvD_ybUN!j*y53A z+0ljI0SxvI*XEWyoq0Hp={epE;2OHJdJosy)?RsV@*S;BXOn>Bm+;``&{s z9&7v5+G`^pL)RWS58)?|u7bOj`ySSkSnj%R!lQ;ss6;Nvi|nY-ecIs;WKVUOgGXJ| zCJPXcAVCtz!z3CzM>`=e>20+K@MtDsnu$!*O1YMJyI2_8 z+<$_@W8ZMHu0d_-8^g^y4HR-}NnbF#fAd%Y?JYNDb-N&Ms@Txtu4{A$S_N{?bvq`e zunQc&+b_BPE1TA4L=Axuro1astPUr;oh65>#mFw%v}~L~wP)S>O=j(;3W@D*59n+c z3El1pM0Z>mgiZ7lezy?E&MrW=g|-Qh;Vv-R$!wq|htVWzr3QnI|0MWw^3p4|JHemi z#I@Hp#oLEK^@{`L)@Ah@whawkuxpwEI$m$JPM^kDO<@~f z;Pc4o;3a}vwU}2`Cg2ocMufo>`bbGPkfW7d#gx?YVd9 zDgk+NFQ}^H>RZOX+sl>ZCfkCsmJA(+wE}B0*xTeC9K|s?6tRJ3JBp&o5m}*5Ct)2T z6~EFwuIi>&^-`inq}jt?JybbwZezBzr8$$yjt>?z!v$3p#w#uZ4J3?g#nNMii?7)| zsmIrzHyAJXWlei;FTc7xFkFI z1cO^XO)8bB^o>mCi8|v`v&~!;lwpq%UQ_A~l89JuS z*$*vELF|CSRN0x^aZOE+J5d-baFA4R7RQ<9#1p0x!B)}}@latCMZ=D1dNcx1F^F*J zWH?5`0V6A1aNcx8#fhCBi^Za?&#m;Ykw0z~HQ^aV*5J_6Pp9;+#rpevD4lT2s#@?c zS7eF(wbob6N=iHtR}v0pM5BTqv3sFzDx#H6C3RRmnyh%4oF&8cD@%q76Dj7UOw&)g znier(f0+?m$3PB_OY^>@^i_(=OxKCu_2JV#>Vb1Vl;NRLd3Fl{%`#-0ad!J#VLW*7UySj)-;8ncX|!Vq zInHH@@M}z9mrvGI8Fx=jlhrC}#hr93ayKLX?vdu^;Lf>XQOuu3$Ju2ESLNPYxb~s# z5A0+=9QgX+O<&*hl^fZ=`Q8bW{tSwSx6zpvX`o=UWKw>1nIwc5!3rn~M%>ni_ z@qIK5eSK(&Y#|Jff)F6$r1wyPXh4Ce4S;D;QIn{(Q;j^@(Wvd_P2z&cDg}{BFc189 zCWTXTQd+1?EUT0a*)b39W$U(;2fp zUO2n%kQghhMM^U|J5=`#6M;S0S>)MjMQ2CV_}B5y%U7XB;p(+%FfC!LS+%?QZ+|i^+ED=#6k%+7#_70*X>Y5Q)h*8z{Y#g~o zRm1a=h-RhHh(qh~xP!1ioFpJHO_aP^IS07{Q4vYP_Yg`K2@!5eG@Y>EP=IqqvrHWh z7I;7;({>D1hlrAGgej8xhm&#Zv`$Kb5zgME(v&?#r%LR=!8H&6r-0BOsz#C6qhY!gN;;3tJ3 zAW(8Ek&eQ{i0~ASS?dWe89}%f;%su|nuh{F8B3LPCmz>BE*5$)%%tZTDh~BSAVpz0 zM@&QvOA$Yrz+rv_08PXqQn&`gMO-g|0Aa+CXE-8t5xqmsOwy7NT8z*gMN*vvfGmoN zBHNB@0{IAlB8L#5?3rN{CO`@IQZ`qJfnkCum~5(g49G_<2&TP!gf%Gb7pB2?5$o@- zMCF*5u|t?8hig>_ooZehr^5MkLN&;A4++6aL8ux@-!~%&6@rLO8ti8`eDH%ee0Kl- z&j$B_)RyhtVA(gldOE(cVmj?`kAO=0RjfW5{rSR4#F@Pw7iHK zjm5NRU$Nwb#sUKz5T)dLrVJk~*AUByz|5Sbz*WV$ffx=1y+8wzWEIqva5dGSC|q3* z-BG0b5k*ry$eIWgy;2V6H@Xvxs@y~vl>x0!!5|3};ZwS7r94N~Q`vkJ^Nq?@E?>Yx zOjAb4k;$XwQqi_ts5^vqc20z8?l@R&zA1^ zq)9~)(FXs7CTodQE^3&fX6WgBF&0KhQ4o-VnGS&#RLRa`@NghN$F=NYsT}1dITJCV zHYmcNZ@6tzx=JB(;Te~ia2<`{jvb81DFD^c!$qTO1mlv6EhJSO(omcW=A@dIia>S1 z4)Asppm7x{n8@J{)MJR_0=PA$4GM}gQ=$Hu9tKejKsQ7cP~R8Tp#OzvWQ1JUjbJ*o z>kaS^ONnNDS5smLQippdZGt656-hU+kiNbG1PlnrDggBa2p-}ojD}?~M9Am{T!BV3 zmr4L`GR2i46p%5?cXY-gUM>bdJ25^DfdaWg(NTZ}O-mQbaY>1gPA?0^rEl{8j@S!H zaNsk{LgouDqWc_|)VxLsk|2Eb!!ml@f9ljxQLk)SKN?${kBzS1Qn}{TsqcmVEC`OW zldUsxMET^_A%=UVby7TfG=R&B%`cL5M=_^edp|Ff!d!O zmdbEGkORUoS;JKkbKtJx*9s0Xs~Y_8q08B%8@zxMyUl8FTGQB;;90iN`ipt?jm@L~ zZte>kwxlkNZtZPzx4ty<zB|N1~zY2K9Ju0 ztB+x7NX@B7YSm7K%!>Rx%HW0*Sf|ZWr_JF`O5ai&y1RXRbVXhHY+uy>xpz4BAlf(2 ze!n~q5oJXx4=+Rbx5D4De-yvQ%lr?djBLyQLHU@npx&ZQXuqd#)4yw6Z#-#kGtWdm zYe(!`?I5}}`cQNs`s>(8>?UWzxz+hde8!zhj3kby`cv1ZUO=w|+hOqqiUGmZgYZSEp5a=w(}h2Bb~g2{QEk28Tn)auU`L^9>?;lq6{vlS+wg>OM>()CC?B9FGfkUhOO6!fk x^Xl1&Z~=b#bs+rp*B<;@>}KI6p(xx4XGu}GF#OHfrEtU3Z^FWr({t79{{hV$jobhL diff --git a/static/fonts/Pythonicon.json b/static/fonts/Pythonicon.json old mode 100755 new mode 100644 index 05f5b6a8b..ddcdbc09f --- a/static/fonts/Pythonicon.json +++ b/static/fonts/Pythonicon.json @@ -1,787 +1,1121 @@ { - "IcoMoonType": "selection", - "icons": [ - { - "icon": { - "paths": [ - "M1024 429.256c0-200.926-58.792-363.938-131.482-365.226 0.292-0.006 0.578-0.030 0.872-0.030h-82.942c0 0-194.8 146.336-475.23 203.754-8.56 45.292-14.030 99.274-14.030 161.502 0 62.228 5.466 116.208 14.030 161.5 280.428 57.418 475.23 203.756 475.23 203.756h82.942c-0.292 0-0.578-0.024-0.872-0.032 72.696-1.288 131.482-164.298 131.482-365.224zM864.824 739.252c-9.382 0-19.532-9.742-24.746-15.548-12.63-14.064-24.792-35.96-35.188-63.328-23.256-61.232-36.066-143.31-36.066-231.124 0-87.81 12.81-169.89 36.066-231.122 10.394-27.368 22.562-49.266 35.188-63.328 5.214-5.812 15.364-15.552 24.746-15.552 9.38 0 19.536 9.744 24.744 15.552 12.634 14.064 24.796 35.958 35.188 63.328 23.258 61.23 36.068 143.312 36.068 231.122 0 87.804-12.81 169.888-36.068 231.124-10.39 27.368-22.562 49.264-35.188 63.328-5.208 5.806-15.36 15.548-24.744 15.548zM251.812 429.256c0-51.95 3.81-102.43 11.052-149.094-47.372 6.554-88.942 10.324-140.34 10.324-67.058 0-67.058 0-67.058 0l-55.466 94.686v88.17l55.46 94.686c0 0 0 0 67.060 0 51.398 0 92.968 3.774 140.34 10.324-7.236-46.664-11.048-97.146-11.048-149.096zM368.15 642.172l-127.998-24.51 81.842 321.544c4.236 16.634 20.744 25.038 36.686 18.654l118.556-47.452c15.944-6.376 22.328-23.964 14.196-39.084l-123.282-229.152zM864.824 548.73c-3.618 0-7.528-3.754-9.538-5.992-4.87-5.42-9.556-13.86-13.562-24.408-8.962-23.6-13.9-55.234-13.9-89.078 0-33.844 4.938-65.478 13.9-89.078 4.006-10.548 8.696-18.988 13.562-24.408 2.010-2.24 5.92-5.994 9.538-5.994 3.616 0 7.53 3.756 9.538 5.994 4.87 5.42 9.556 13.858 13.56 24.408 8.964 23.598 13.902 55.234 13.902 89.078 0 33.842-4.938 65.478-13.902 89.078-4.004 10.548-8.696 18.988-13.56 24.408-2.008 2.238-5.92 5.992-9.538 5.992z" - ], - "tags": [ - "bullhorn", - "megaphone", - "announcement", - "advertisement", - "news" - ], - "grid": 16 - }, - "properties": { - "order": 1, - "id": 28, - "prevSize": 32, - "code": 58880, - "name": "bullhorn", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M620.62 12.098c-40.884-6.808-83.266-9.918-123.999-9.728-40.695 0.19-79.569 3.622-113.74 9.728-100.693 17.806-118.993 54.974-118.993 123.657v90.738h238.004v30.208h-327.282c-69.177 0-129.764 41.624-148.689 120.68-21.883 90.662-22.85 147.266 0 241.873 16.934 70.466 57.287 120.68 126.502 120.68h81.787v-108.753c0-78.583 68.001-147.797 148.67-147.797h237.739c66.143 0 118.955-54.556 118.955-120.984v-226.664c-0-64.455-54.405-112.905-118.955-123.639zM395.681 166.021c-24.671 0-44.658-20.215-44.658-45.227 0-25.050 19.987-45.473 44.658-45.473 24.557 0 44.658 20.423 44.658 45.473 0.019 24.993-20.082 45.227-44.658 45.227z", - "M995.157 394.923c-17.067-68.798-49.74-120.623-118.955-120.623h-89.335v105.662c0 82.034-69.48 150.945-148.67 150.945h-237.72c-65.119 0-118.974 55.732-118.974 120.927v226.588c0 64.493 56.073 102.438 118.974 120.946 75.34 22.13 147.589 26.131 237.739 0 59.885-17.332 118.993-52.281 118.993-120.946v-90.738h-237.701v-30.189h356.712c69.139 0 94.967-48.242 118.955-120.642 24.841-74.562 23.799-146.242-0.019-241.929zM625.417 848.194c24.652 0 44.639 20.177 44.639 45.189 0 25.145-19.987 45.454-44.639 45.454-24.614 0-44.658-20.309-44.658-45.454 0-24.993 20.063-45.189 44.658-45.189z" - ], - "grid": 0, - "tags": [ - "python-alt" - ] - }, - "properties": { - "order": 2, - "id": 0, - "prevSize": 24, - "code": 58881, - "name": "python-alt", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.37-2.37h-521.481c-138.221 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.038 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.076-251.259-251.259-251.259zM958.369 763.183c0 100.447-95.63 195.489-195.508 195.489h-502.348c-97.033 0-195.527-95.042-195.527-195.489v-65.479h893.364v65.479zM958.369 636.075h-893.364v-253.649h893.364v253.649zM958.369 320.796h-893.364v-59.999c0-96.446 96.104-195.489 195.527-195.489h502.348c99.878 0 195.508 99.044 195.508 195.489v59.999zM383.924 223.611h260.741v-61.63h-260.741v61.63zM644.665 479.611h-260.741v61.63h260.741v-61.63zM644.665 797.26h-260.741v61.63h260.741v-61.63z" - ], - "grid": 0, - "tags": [ - "pypi" - ] - }, - "properties": { - "order": 3, - "id": 0, - "prevSize": 24, - "code": 58882, - "name": "pypi", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M957.63 189.212v574.805c0 94.853-64 128.531-64 128.531s0-730.624 0-895.962l-893.63 1.043v771.66c0 138.221 113.076 251.259 251.259 251.259h519.111c138.183 0 251.259-113.038 251.259-251.259v-580.286l-64 0.209zM831.393 930.74c0 0-25.998 23.514-72.59 23.514 0 0-426.515 1.157-497.436 1.157-91.041 0-196.058-97.527-196.058-192.891s0.967-700.094 0.967-700.094h765.118v868.314z", - "M770.37 173.511v-47.407h-636.833v125.63h636.833z", - "M133.537 378.937h315.24v65.574h-315.24v-65.574z", - "M133.537 761.363h635.24v65.574h-635.24v-65.574z", - "M133.537 506.937h315.24v65.574h-315.24v-65.574z", - "M133.537 632.567h315.24v65.574h-315.24v-65.574z", - "M770.37 630.215v-251.278h-259.963v320.019h259.963z" - ], - "grid": 0, - "tags": [ - "news" - ] - }, - "properties": { - "order": 4, - "id": 0, - "prevSize": 32, - "code": 58883, - "name": "news", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M508.207 66.882c-244.452 0-442.615 198.163-442.615 442.615 0 244.452 198.163 442.615 442.615 442.615 244.471 0 442.615-198.163 442.615-442.615-0-244.452-198.201-442.615-442.615-442.615zM164.485 424.467l-22.414-22.414c22.225-75.928 67.508-141.862 127.526-190.18l34.266 127.829c-53.134 17.010-100.712 46.364-139.378 84.764zM409.335 764.188c-52.679 0-95.384-42.705-95.384-95.403 0-38.116 22.528-70.751 54.898-86.016l42.648-197.879 45.378 201.709c28.463 16.479 47.825 46.952 47.825 82.185-0.019 52.698-42.705 95.403-95.365 95.403zM409.335 323.205c-23.571 0-46.554 2.408-68.779 6.884l-38.116-142.241c59.335-38.153 129.934-60.283 205.767-60.283 35.992 0 70.751 5.139 103.765 14.45l-83.778 202.278c-37.111-13.502-77.065-21.087-118.86-21.087zM731.932 540.52c-32.18-79.189-92.615-143.834-168.77-181.476l84.897-204.971c131.641 51.883 227.48 174.839 240.375 321.612l-156.501 64.834z" - ], - "grid": 0, - "tags": [ - "moderate" - ] - }, - "properties": { - "order": 5, - "id": 0, - "prevSize": 32, - "code": 58884, - "name": "moderate", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M855.249 128.341c23.211 0 42.78 19.608 42.78 42.78v680.941c0 23.211-19.57 42.78-42.78 42.78h-680.96c-23.192 0-42.78-19.57-42.78-42.78v-680.941c0-23.192 19.608-42.78 42.78-42.78h680.96M855.249 0h-680.96c-94.113 0-171.122 77.009-171.122 171.122v680.941c0 94.132 77.009 171.122 171.122 171.122h680.941c94.132 0 171.122-77.009 171.122-171.122v-680.941c0.019-94.094-76.99-171.122-171.103-171.122v0z", - "M421.812 682.401v-205.464h-118.519v205.464h-64.853v-464.915h64.853v203.321h118.519v-203.321h65.593v464.934h-65.593z", - "M666.131 839.054c-76.516 0-124.549-49.512-124.549-115.105 0-51.010 27.629-84.556 56.813-96.18l-29.886-32.047c0.702-21.144 16.043-40.789 32.047-49.55-26.226-19.646-42.249-48.792-42.249-90.321 0-64.152 41.51-110.099 104.922-110.099 15.322 0 26.965 2.219 35.707 5.12 10.942 3.622 22.604 5.803 37.129 5.803 16.043 0 31.346-5.803 40.088-11.605l8.761 51.75c-4.399 3.622-17.503 8.021-26.965 8.021 5.784 10.923 10.183 29.146 10.183 51.029 0 59.752-37.888 108.544-102.040 110.023-21.106 0-33.527 5.784-33.527 18.223 0 4.361 3.66 11.643 11.681 14.601l63.374 21.826c51.75 17.484 81.636 53.21 81.636 110.080 0.038 61.080-48.052 108.43-123.127 108.43zM690.195 671.497l-40.808-11.7c-31.308 2.939-51.75 26.245-51.75 64.834 0 33.545 22.604 65.65 67.755 65.65 43.748 0 65.612-30.625 65.612-59.733 0.019-27.743-13.843-51.75-40.808-59.051zM663.249 394.562c-27.743 0-48.090 26.965-48.090 61.25 0 34.949 20.347 61.175 48.090 61.175 26.226 0 48.773-26.226 48.773-61.175 0.019-34.285-20.347-61.25-48.773-61.25z" - ], - "grid": 0, - "tags": [ - "mercurial" - ] - }, - "properties": { - "order": 6, - "id": 0, - "prevSize": 32, - "code": 58885, - "name": "mercurial", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M899.167 678.665l-291.499 50.157v29.412c0 45.151-50.498 81.655-94.872 81.655-44.582 0-94.834-36.504-94.834-81.655v-29.412l-291.537-50.157c-69.101 0-125.63-63.962-125.63-63.962v282.074c0 69.12 56.529 125.63 125.63 125.63h772.741c69.101 0 125.63-56.51 125.63-125.63v-282.074c0 0-56.529 63.962-125.63 63.962z", - "M899.167 254.369h-194.37v-66.37c0.19-36.030-11.397-69.367-35.366-92.35-23.893-23.059-57.079-33.413-92.634-33.28h-130.37c-35.593-0.114-68.779 10.221-92.653 33.28-24.007 22.983-35.556 56.32-35.366 92.35v66.37h-191.981c-69.101 0-125.63 56.529-125.63 125.63v128c0 69.12 56.529 125.63 125.63 125.63l339.039 56.168v52.338c0 26.491 21.163 47.938 47.332 47.938 26.055 0 47.369-21.447 47.369-47.938v-52.357l339.001-56.149c69.101 0 125.63-56.51 125.63-125.63v-128c0-69.101-56.529-125.63-125.63-125.63zM384.777 187.999c0.19-23.268 6.466-36.143 15.019-44.582 8.704-8.306 22.907-14.601 46.63-14.715h130.37c23.666 0.114 37.907 6.391 46.573 14.715 8.571 8.439 14.81 21.314 15.057 44.582-0.019 21.902-0.019 45.416-0.019 66.37h-253.63c0-20.954 0-44.468 0-66.37z" - ], - "grid": 0, - "tags": [ - "jobs" - ] - }, - "properties": { - "order": 7, - "id": 0, - "prevSize": 32, - "code": 58886, - "name": "jobs", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M772.741-0.019h-521.481c-138.183 0-251.259 113.076-251.259 251.278v521.481c0 138.183 113.076 251.259 251.259 251.259h521.481c138.221 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.038-251.278-251.259-251.278zM593.029 896.777h-185.401v-189.573h185.401v189.573zM748.791 409.429c-14.639 24.652-44.601 54.746-89.809 90.283-31.497 24.955-51.39 44.999-59.639 60.113-8.287 15.132-12.383 55.751-12.383 80.1h-177.778v-38.703c0-30.246 3.432-54.803 10.297-73.671 6.865-18.887 17.048-36.087 30.625-51.693 13.577-15.588 44.051-43.046 91.458-82.318 25.259-20.594 37.888-39.462 37.888-56.604s-5.082-30.473-15.208-39.993c-10.126-9.5-25.505-14.26-46.080-14.26-22.168 0-40.467 7.339-54.955 21.978-14.526 14.658-23.78 40.22-27.838 76.724l-181.495-22.452c6.239-66.731 30.473-120.453 72.742-161.166 42.268-40.695 107.046-61.042 194.351-61.042 68.001 0 122.861 14.184 164.693 42.572 56.737 38.362 85.106 89.505 85.106 153.429-0 26.51-7.301 52.072-21.978 76.705z" - ], - "grid": 0, - "tags": [ - "help" - ] - }, - "properties": { - "order": 8, - "id": 0, - "prevSize": 32, - "code": 63, - "name": "help", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M129.271 383.507l383.166 382.805 380.075-382.805h-190.255v-320.076h-382.085v320.076z", - "M736.484 635.657l-224.047 225.47-225.375-225.185h-288.161v135.149c0 138.202 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.057 251.259-251.259v-135.149l-286.417-0.284z" - ], - "grid": 0, - "tags": [ - "download" - ] - }, - "properties": { - "order": 10, - "id": 0, - "prevSize": 32, - "code": 58889, - "name": "download", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M731.439 149.751l-25.031 39.329-90.529-57.628-186.292 292.636 39.974 25.467 160.825-252.644 50.574 32.161-331.473 520.742 9.937 51.333-36.162 57.666 6.201 30.853 30.891-7.623 35.669-56.889 52.148-12.516 381.933-600.064z", - "M772.741-2.37h-521.481c-138.202 0-251.259 113.057-251.259 251.259v521.481c0 138.183 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.076-251.259-251.259-251.259zM99.366 811.179c-26.169 0-47.332-21.447-47.332-47.919 0-26.624 21.163-48.223 47.332-48.223 26.055 0 47.369 21.599 47.369 48.223-0.019 26.472-21.314 47.919-47.369 47.919zM99.366 557.549c-26.169 0-47.332-21.447-47.332-47.938 0-26.605 21.163-48.223 47.332-48.223 26.055 0 47.369 21.618 47.369 48.223-0.019 26.491-21.314 47.938-47.369 47.938zM99.366 303.919c-26.169 0-47.332-21.428-47.332-47.938 0-26.605 21.163-48.223 47.332-48.223 26.055 0 47.369 21.618 47.369 48.223-0.019 26.51-21.314 47.938-47.369 47.938zM955.259 735.365c0 119.637-97.887 217.524-217.524 219.895l-543.365-1.745v-886.689l543.365-0.455c119.637 0 217.524 97.887 217.524 217.524v451.47z" - ], - "grid": 0, - "tags": [ - "documentation" - ] - }, - "properties": { - "order": 11, - "id": 0, - "prevSize": 32, - "code": 58890, - "name": "documentation", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M512.986 682.989c57.647 0 104.277-46.592 104.277-104.183 0-57.496-46.63-104.145-104.277-104.145-57.458 0-104.164 46.649-104.164 104.145 0.019 57.591 46.706 104.183 104.164 104.183", - "M763.733 711.32c45.378 0 82.072-36.674 82.072-81.996 0-45.265-36.712-81.958-82.072-81.958-45.189 0-81.996 36.712-81.996 81.958 0 45.321 36.826 81.996 81.996 81.996", - "M785.749 748.791c-39.045 0-73.519 17.863-95.004 45.303 7.851 16.839 12.231 35.423 12.231 54.955v110.042h200.666v-99.556c-0.019-61.156-52.717-110.744-117.893-110.744", - "M260.305 711.32c45.189 0 81.996-36.674 81.996-81.996 0-45.265-36.807-81.958-81.996-81.958-45.359 0-82.091 36.712-82.091 81.958-0 45.321 36.731 81.996 82.091 81.996", - "M238.308 748.791c-65.195 0-117.893 49.569-117.893 110.744v99.556h200.666v-110.042c0-19.532 4.38-38.135 12.212-54.955-21.466-27.42-55.96-45.303-94.985-45.303", - "M512.986 714.562c-84.689 0-153.259 64.417-153.259 143.91v162.437h306.498v-162.437c0-79.493-68.494-143.91-153.24-143.91", - "M891.847 129.119c0-70.068-169.491-126.919-379.051-126.919-208.896-0-378.728 56.851-378.728 126.919 0 44.108 67.167 82.906 168.903 105.662l-16.801 173.018 96.332-159.611c25.429 3.129 52.072 5.385 79.72 6.637l49.247 193.858 49.19-193.726c28.729-1.214 56.358-3.527 82.697-6.751l96.332 159.592-16.801-172.999c101.888-22.737 168.96-61.554 168.96-105.681z" - ], - "grid": 0, - "tags": [ - "community" - ] - }, - "properties": { - "order": 12, - "id": 0, - "prevSize": 32, - "code": 58891, - "name": "community", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M772.741-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM316.151 402.015l-124.947 108.241 124.947 108.241v112.242l-254.521-220.482 254.521-220.482v112.242zM461.577 825.135l-76.383-0.265 170.591-630.803 77.103-0.91-171.311 631.979zM699.164 725.94v-112.242l119.41-103.443-119.41-103.443v-112.242l248.984 215.685-248.984 215.685z" - ], - "grid": 0, - "tags": [ - "code" - ] - }, - "properties": { - "order": 13, - "id": 0, - "prevSize": 32, - "code": 58892, - "name": "code", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.37-2.37h-521.481c-138.183 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.076 251.259 251.259 251.259h521.481c138.221 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.038-251.259-251.259-251.259zM825.742 670.758l-155.117 155.098-160.18-160.18-160.199 160.218-155.136-155.136 160.199-160.218-160.199-160.218 155.136-155.098 160.18 160.199 160.18-160.199 155.117 155.098-160.18 160.218 160.199 160.218z" - ], - "grid": 0, - "tags": [ - "close" - ] - }, - "properties": { - "order": 14, - "id": 0, - "prevSize": 32, - "code": 88, - "name": "close", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.076-251.259-251.259-251.259zM765.63 82.849c26.586 0 48.223 21.144 48.223 47.332 0 26.036-21.637 47.351-48.223 47.351-26.472 0-47.919-21.314-47.919-47.351 0-26.188 21.447-47.332 47.919-47.332zM512 82.849c26.586 0 48.223 21.144 48.223 47.332 0 26.036-21.637 47.351-48.223 47.351-26.491 0-47.919-21.314-47.919-47.351 0-26.188 21.428-47.332 47.919-47.332zM258.37 82.849c26.605 0 48.223 21.144 48.223 47.332 0 26.036-21.618 47.351-48.223 47.351-26.491 0-47.919-21.314-47.919-47.351 0-26.188 21.428-47.332 47.919-47.332zM732.843 953.666h-451.47c-119.637 0-217.524-97.887-219.895-217.524l1.745-479.365h886.689l0.455 479.365c0 119.637-97.887 217.524-217.524 217.524z", - "M533.561 320.796h150.528v146.963h-150.528v-146.963z", - "M737.583 320.796h150.528v146.963h-150.528v-146.963z", - "M125.44 534.111h150.528v146.963h-150.528v-146.963z", - "M329.5 534.111h150.528v146.963h-150.528v-146.963z", - "M533.561 534.111h150.528v146.963h-150.528v-146.963z", - "M737.583 534.111h150.528v146.963h-150.528v-146.963z", - "M275.968 894.407v-146.963h-150.528c0 82.887 83.209 146.963 150.528 146.963z", - "M329.5 747.444h150.528v146.963h-150.528v-146.963z", - "M533.561 747.444h150.528v146.963h-150.528v-146.963z" - ], - "grid": 0, - "tags": [ - "calendar" - ] - }, - "properties": { - "order": 15, - "id": 0, - "prevSize": 32, - "code": 58894, - "name": "calendar", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M508.207 66.882c-244.452 0-442.615 198.163-442.615 442.615 0 244.452 198.163 442.615 442.615 442.615 244.471 0 442.615-198.163 442.615-442.615-0-244.452-198.201-442.615-442.615-442.615zM164.485 424.467l-22.414-22.414c22.225-75.928 67.508-141.862 127.526-190.18l34.266 127.829c-53.134 17.010-100.712 46.364-139.378 84.764zM409.335 764.188c-52.679 0-95.384-42.705-95.384-95.403 0-9.956 1.972-19.38 4.798-28.425l-111.426-172.677 174.364 110.327c8.799-2.693 17.958-4.551 27.648-4.551 52.66 0 95.346 42.705 95.346 95.327 0 52.698-42.686 95.403-95.346 95.403zM409.335 323.205c-23.571 0-46.554 2.408-68.779 6.884l-38.116-142.241c59.335-38.153 129.934-60.283 205.767-60.283 35.992 0 70.751 5.139 103.765 14.45l-83.778 202.278c-37.111-13.502-77.065-21.087-118.86-21.087zM731.932 540.52c-32.18-79.189-92.615-143.834-168.77-181.476l84.897-204.971c131.641 51.883 227.48 174.839 240.375 321.612l-156.501 64.834z" - ], - "grid": 0, - "tags": [ - "beginner" - ] - }, - "properties": { - "order": 16, - "id": 0, - "prevSize": 32, - "code": 58895, - "name": "beginner", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M508.207 66.882c-244.452 0-442.615 198.163-442.615 442.615 0 244.452 198.163 442.615 442.615 442.615 244.471 0 442.615-198.163 442.615-442.615-0-244.452-198.201-442.615-442.615-442.615zM508.207 127.583c35.992 0 70.751 5.139 103.765 14.45l-83.778 202.278c-37.092-13.521-77.047-21.087-118.86-21.087-23.571 0-46.554 2.408-68.779 6.884l-38.116-142.241c59.335-38.153 129.934-60.283 205.767-60.283zM164.485 424.467l-22.414-22.414c22.225-75.928 67.508-141.862 127.526-190.18l34.266 127.829c-53.134 17.010-100.712 46.364-139.378 84.764zM502.253 647.964c1.498 6.713 2.427 13.653 2.427 20.821 0 52.698-42.686 95.403-95.346 95.403-52.679 0-95.384-42.705-95.384-95.403 0-52.622 42.705-95.327 95.384-95.327 12.459 0 24.292 2.56 35.195 6.884l169.851-109.625-112.128 177.247zM731.932 540.52c-32.18-79.189-92.615-143.834-168.77-181.476l84.897-204.971c131.641 51.883 227.48 174.839 240.375 321.612l-156.501 64.834z" - ], - "grid": 0, - "tags": [ - "advanced" - ] - }, - "properties": { - "order": 17, - "id": 0, - "prevSize": 32, - "code": 58896, - "name": "advanced", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM197.215 189.212h279.078v-61.231h71.149v61.231h286.189v194.75h-286.189v61.668h-71.149v-61.687h-279.078l-103.329-96.18 103.329-98.551zM824.149 701.175h-276.708v255.64h-71.149v-255.64h-281.448v-193.517h629.305l103.367 97.337-103.367 96.18z" - ], - "grid": 0, - "tags": [ - "sitemap" - ] - }, - "properties": { - "order": 18, - "id": 0, - "prevSize": 32, - "code": 58897, - "name": "sitemap", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M190.843 190.445c-78.431 78.507-78.431 205.577-0.038 284.027 78.412 78.374 205.596 78.412 284.008-0.019s78.412-205.559-0.038-283.951c-78.374-78.431-205.521-78.431-283.932-0.057zM442.216 358.343c-0.095-75.34-60.966-136.211-136.23-136.306v-26.795c90.055 0 163.025 73.045 163.1 163.119h-26.871zM770.37-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM944.242 838.447l-104.695 104.676c-15.663 15.701-41.169 15.663-56.87-0.019l-253.421-253.421c-15.701-15.72-15.701-41.188 0-56.908l27.781-27.781-61.857-61.876c-104.448 80.668-254.843 73.311-350.587-22.433-103.993-103.974-103.993-272.517 0-376.491 103.955-103.936 272.517-103.936 376.491 0.019 95.441 95.46 103.007 245.286 23.078 349.677l61.971 61.952 27.8-27.8c15.72-15.663 41.207-15.644 56.908 0l253.402 253.44c15.72 15.758 15.739 41.244 0 56.965z" - ], - "grid": 0, - "tags": [ - "search" - ] - }, - "properties": { - "order": 19, - "id": 0, - "prevSize": 32, - "code": 58898, - "name": "search", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M190.843 190.445c-78.431 78.507-78.431 205.577-0.038 284.027 78.412 78.374 205.596 78.412 284.008-0.019s78.412-205.559-0.038-283.951c-78.374-78.431-205.521-78.431-283.932-0.057zM442.216 358.343c-0.095-75.34-60.966-136.211-136.23-136.306v-26.795c90.055 0 163.025 73.045 163.1 163.119h-26.871zM944.242 838.447l-104.695 104.676c-15.663 15.701-41.169 15.663-56.87-0.019l-253.421-253.421c-15.701-15.72-15.701-41.188 0-56.908l27.781-27.781-61.857-61.876c-104.448 80.668-254.843 73.311-350.587-22.433-103.993-103.974-103.993-272.517 0-376.491 103.955-103.936 272.517-103.936 376.491 0.019 95.441 95.46 103.007 245.286 23.078 349.677l61.971 61.952 27.8-27.8c15.72-15.663 41.207-15.644 56.908 0l253.402 253.44c15.72 15.758 15.739 41.244 0 56.965z" - ], - "grid": 0, - "tags": [ - "search-alt" - ] - }, - "properties": { - "order": 20, - "id": 0, - "prevSize": 32, - "code": 58899, - "name": "search-alt", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M607.991 863.573c20.309 0 36.788-16.744 36.788-37.509 0-20.632-16.479-37.262-36.788-37.262-20.29 0-36.807 16.631-36.807 37.262 0 20.764 16.517 37.509 36.807 37.509zM418.475 151.249c-20.328 0-36.826 16.858-36.826 37.528 0 20.613 16.498 37.3 36.826 37.3 20.309 0 36.864-16.687 36.845-37.3-0-20.67-16.555-37.528-36.845-37.528zM772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.038 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM285.279 609.735v89.714h-67.47c-57.079 0-90.377-41.434-104.334-99.556-18.849-78.014-18.053-124.719 0-199.509 15.607-65.195 65.593-99.537 122.652-99.537h269.995v-24.917h-196.343v-74.847c0-56.623 15.113-87.305 98.152-101.983 28.179-5.025 60.245-7.87 93.81-8.021 33.583-0.171 68.57 2.389 102.305 8.021 53.267 8.856 98.152 48.83 98.152 101.964v186.956c0 54.803-43.596 99.802-98.152 99.802h-196.134c-66.541 0.019-122.633 57.135-122.633 121.913zM912.991 614.438c-19.816 59.733-41.112 99.556-98.152 99.556h-294.21v24.879h196.077v74.828c0 56.642-48.735 85.466-98.152 99.783-74.373 21.542-133.973 18.242-196.115 0-51.902-15.284-98.133-46.573-98.133-99.783v-186.899c0-53.779 44.411-99.764 98.133-99.764h196.096c65.308 0 122.633-56.832 122.633-124.492v-87.173h73.69c57.116 0 84.044 42.761 98.152 99.518 19.627 78.943 20.48 138.069-0.019 199.547z" - ], - "grid": 0, - "tags": [ - "python" - ] - }, - "properties": { - "order": 21, - "id": 0, - "prevSize": 32, - "code": 58900, - "name": "python", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M653.672 373.077c-32.521 0-58.861 26.908-58.861 59.98 0 32.977 26.34 59.62 58.861 59.62 32.446 0 58.899-26.624 58.899-59.62 0-33.071-26.453-59.98-58.899-59.98zM393.216 373.077c-32.54 0-58.88 26.908-58.88 59.98 0 32.977 26.34 59.62 58.88 59.62 32.351 0 58.88-26.624 58.88-59.62 0-33.071-26.529-59.98-58.88-59.98zM772.741-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM853.807 399.474c0 32.275-4.248 60.568-12.117 85.694l-2.882 9.14c-1.517 4.21-3.413 8.533-5.367 12.933l-4.229 9.083c-33.849 67.413-101.812 105.472-198.58 120.396l-11.719 1.801 7.927 8.761c19.361 21.39 28.843 43.653 30.303 67.47v171.672c0.057 13.502 5.404 24.614 13.672 33.887-34.854-2.313-58.785-15.227-58.823-37.054v-143.019c0-18.773-17.73-20.518-20.006-20.518-0.796 0-1.441 0.114-1.877 0.209l-4.798 1.176v5.006c0 0 0 153.6 0 169.586-0.19 11.928 2.465 22.509 9.178 31.801-38.381-1.877-53.267-19.589-53.855-40.695 0 0.038 0-147.949 0-156.331 0-8.306-7.471-12.667-13.047-12.667-5.784 0-13.16 4.399-13.16 12.667-0.038 8.268-0.038 164.087-0.038 164.087-0.74 23.097-24.102 31.801-56.548 32.787 5.158-7.301 9.254-16.194 9.235-28.065v-180.053l-6.808 0.531c-0.171 0-19.001 1.365-19.589 20.461v146.792c-0.057 18.318-21.011 36.75-54.405 38.4 6.428-8.078 10.335-18.375 10.202-30.663v-119.182h-57.742c-107.179 1.138-101.224-97.261-162.854-146.66 56.737 6.713 80.801 85.845 155.003 87.685 45.359 0 56.623 0 56.623 0h5.575l0.702-5.537c3.3-25.335 15.55-47.388 39.367-66.807l11.681-9.576-14.905-1.669c-105.946-12.629-176.981-51.655-213.883-117.153l-5.082-9.121c-1.953-3.906-3.812-8.363-5.727-13.028l-3.565-9.14c-9.633-26.624-14.943-57.135-15.436-91.61-0.019-1.46-0.019-2.788-0.019-4.172 0.057-58.482 16.194-110.345 56.908-153.562l2.446-2.655-0.891-3.356c-5.348-20.196-7.813-40.505-7.889-60.928 0.038-24.804 3.812-49.778 10.923-75.055 46.364 2.958 93.544 19.342 141.919 52.034l2.219 1.46 2.655-0.569c39.633-8.647 79.379-12.705 119.068-12.705 41.036 0 82.072 4.38 123.089 12.705l2.731 0.512 2.257-1.555c41.358-29.374 87.381-46.611 138.847-51.712 8.495 28.786 13.464 57.534 13.464 86.13 0 12.971-0.967 25.96-3.148 38.969l-0.436 2.788 1.82 2.238c37.395 46.156 60.928 101.205 61.705 172.544-0.133 1.081-0.095 2.276-0.095 3.413z" - ], - "grid": 0, - "tags": [ - "github" - ] - }, - "properties": { - "order": 22, - "id": 0, - "prevSize": 32, - "code": 58901, - "name": "github", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M511.924 578.37c33.489 0 60.7-24.367 60.7-63.147v-445.8c0-38.836-27.231-63.109-60.7-63.109-33.527 0-60.681 24.273-60.681 63.109v445.8c0 38.779 27.174 63.147 60.681 63.147zM703.924 104.107v146.015c95.554 62.407 158.853 169.965 158.853 292.599 0 193.214-156.691 349.886-349.98 349.886-193.308 0-350.018-156.672-350.018-349.886 0-122.292 62.957-229.623 158.056-292.124v-146.053c-168.77 74.012-286.853 242.157-286.853 438.272 0 264.439 214.376 478.815 478.815 478.815 264.42 0 478.796-214.376 478.796-478.815 0-196.418-118.424-364.904-287.668-438.708z" - ], - "grid": 0, - "tags": [ - "get-started" - ] - }, - "properties": { - "order": 23, - "id": 0, - "prevSize": 32, - "code": 58902, - "name": "get-started", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.37 0h-521.481c-138.202 0-251.259 113.057-251.259 251.259v521.481c0 138.183 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.076-251.259-251.259-251.259zM299.255 842.183c-65.043 0-117.76-52.698-117.76-117.741s52.717-117.741 117.76-117.741c65.005 0 117.722 52.698 117.722 117.741s-52.736 117.741-117.722 117.741zM611.745 827.923h-145.351c18.679-30.113 29.62-65.479 29.62-103.481 0-108.658-88.102-196.817-196.76-196.817-39.993 0-77.084 12.004-108.146 32.484v-146.508c33.906-11.795 70.182-18.565 108.146-18.66 181.931 0.322 329.14 147.551 329.463 329.481-0.095 36.162-6.163 70.903-16.972 103.5zM843.036 827.923h-149.030c8.666-33.109 13.786-67.698 13.786-103.519-0.057-225.64-182.936-408.5-408.519-408.519-37.528 0-73.633 5.48-108.146 14.943v-149.352c34.987-6.903 71.111-10.638 108.146-10.638 305.759 0 553.567 247.865 553.567 553.567-0.019 35.366-3.508 69.973-9.804 103.519z" - ], - "grid": 0, - "tags": [ - "feed" - ] - }, - "properties": { - "order": 24, - "id": 0, - "prevSize": 32, - "code": 58903, - "name": "feed", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM677.812 507.563h-105.453v381.952h-157.999v-381.952h-79v-131.622h79v-79.038c0-107.368 44.601-171.255 171.179-171.255h105.472v131.641h-65.896c-49.323 0-52.584 18.413-52.584 52.717l-0.19 65.934h119.448l-13.976 131.622z" - ], - "grid": 0, - "tags": [ - "facebook" - ] - }, - "properties": { - "order": 25, - "id": 0, - "prevSize": 32, - "code": 58904, - "name": "facebook", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M896 188.056h-772.741c-69.101 0-125.63 56.529-125.63 125.63v5.177l509.63 253.193 514.37-255.545v-2.825c0-69.101-56.529-125.63-125.63-125.63zM1021.63 635.032v-252.169l-253.175 125.781 253.175 126.388zM-2.37 385.233v248.225l249.211-124.416-249.211-123.809zM507.259 638.426l-192.341-95.554-317.269 157.582c0.209 68.93 56.642 125.231 125.611 125.231h772.741c68.437 0 124.492-55.505 125.535-123.714l-321.138-159.497-193.138 95.953z" - ], - "grid": 0, - "tags": [ - "email" - ] - }, - "properties": { - "order": 26, - "id": 0, - "prevSize": 32, - "code": 58905, - "name": "email", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.37-2.37h-521.481c-138.183 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.076 251.259 251.259 251.259h521.481c138.202 0 251.278-113.057 251.278-251.259v-521.481c0-138.183-113.076-251.259-251.278-251.259zM705.252 507.885v320.057h-382.066v-320.057h-190.255l380.094-382.824 383.166 382.824h-190.938z" - ], - "grid": 0, - "tags": [ - "arrow-up" - ] - }, - "properties": { - "order": 27, - "id": 0, - "prevSize": 32, - "code": 58906, - "name": "arrow-up", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.37-2.37h-521.481c-138.221 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.038 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.076-251.259-251.259-251.259zM511.374 896.19v-190.938h-320.076v-382.066h320.076v-190.255l382.824 380.075-382.824 383.185z" - ], - "grid": 0, - "tags": [ - "arrow-right" - ] - }, - "properties": { - "order": 28, - "id": 0, - "prevSize": 32, - "code": 58907, - "name": "arrow-right", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.37-2.389h-521.481c-138.183 0-251.259 113.076-251.259 251.278v521.481c0 138.183 113.076 251.259 251.259 251.259h521.481c138.221 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.038-251.278-251.259-251.278zM827.961 696.073h-320.076v190.255l-382.824-380.094 382.824-383.166v190.919h320.076v382.085z" - ], - "grid": 0, - "tags": [ - "arrow-left" - ] - }, - "properties": { - "order": 29, - "id": 0, - "prevSize": 32, - "code": 58908, - "name": "arrow-left", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.389-2.37h-521.481c-138.202 0-251.278 113.038-251.278 251.259v521.481c0 138.183 113.076 251.259 251.278 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.221-113.076-251.259-251.259-251.259zM506.254 894.18l-383.166-382.805h190.9v-320.076h382.085v320.076h190.255l-380.075 382.805z" - ], - "grid": 0, - "tags": [ - "arrow-down" - ] - }, - "properties": { - "order": 30, - "id": 0, - "prevSize": 32, - "code": 58909, - "name": "arrow-down", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.038 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM309.627 826.273c-99.859 0-180.812-80.953-180.812-180.793 0-99.821 80.953-180.774 180.812-180.774 27.364 0 53.267 6.277 76.535 17.18l-54.689 94.701c-6.884-2.238-14.241-3.451-21.845-3.451-39.936 0-72.325 32.37-72.325 72.306s32.389 72.344 72.325 72.344c35.537 0 65.062-25.714 71.111-59.506h109.037c-6.618 93.848-84.632 167.993-180.148 167.993zM438.234 306.593c0 19.456 7.737 37.035 20.215 50.081l-55.068 95.308c-44.563-32.92-73.652-85.694-73.652-145.389 0-99.821 80.953-180.774 180.812-180.774 99.84 0 180.774 80.934 180.774 180.774 0 59.582-28.937 112.318-73.406 145.237l-55.049-95.384c12.364-13.009 20.044-30.492 20.044-49.854 0-39.936-32.446-72.325-72.344-72.325-39.936 0-72.325 32.389-72.325 72.325zM708.475 826.216c-95.554 0-173.549-74.145-180.148-167.955h109.037c6.030 33.83 35.556 59.525 71.111 59.525 39.898 0 72.287-32.37 72.287-72.325 0-39.917-32.37-72.287-72.287-72.287-6.599 0-12.99 0.967-19.039 2.636l-54.917-95.175c22.585-10.145 47.597-15.948 73.956-15.948 99.859 0 180.774 80.934 180.774 180.755s-80.915 180.774-180.774 180.774z" - ], - "grid": 0, - "tags": [ - "freenode" - ] - }, - "properties": { - "order": 31, - "id": 0, - "prevSize": 32, - "code": 58910, - "name": "freenode", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M990.701 763.98l-336.175-688.014c-58.69-104.41-224.616-92.558-269.483-1.214l-345.353 690.479c-74.828 142.279-0.929 258.769 164.162 258.769h620.165c165.073 0 240.090-117.020 166.684-260.020zM607.744 891.259h-185.401v-189.573h185.401v189.573zM610.057 384l-33.716 253.080h-122.728l-33.185-253.080v-192h189.63v192z" - ], - "grid": 0, - "tags": [ - "alert" - ] - }, - "properties": { - "order": 32, - "id": 0, - "prevSize": 32, - "code": 58911, - "name": "alert", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M61.554 313.685l450.37-187.259 445.63 187.259-445.63 189.63z", - "M511.924 569.666l-297.415-125.212-152.955 63.602 450.37 189.611 445.63-189.611-151.343-63.602z", - "M511.924 761.666l-297.415-125.231-152.955 63.602 450.37 189.63 445.63-189.63-151.343-63.602z" - ], - "grid": 0, - "tags": [ - "versions" - ] - }, - "properties": { - "order": 33, - "id": 0, - "prevSize": 32, - "code": 58912, - "name": "versions", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M688.583 286.227c-24.728 0-44.715 20.461-44.715 45.587 0 25.012 19.987 45.246 44.715 45.246 24.595 0 44.753-20.252 44.734-45.246 0.019-25.126-20.139-45.587-44.734-45.587zM772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM816.488 392.021c10.449 231.519-162.588 475.136-468.158 475.136-92.956 0-179.428-27.269-252.302-73.937 87.324 10.278 174.497-13.995 243.674-68.134-72.002-1.365-132.836-48.962-153.771-114.328 25.79 4.93 51.181 3.489 74.354-2.769-79.132-15.929-133.803-87.268-132.001-163.499 22.168 12.288 47.597 19.759 74.562 20.556-73.311-48.962-94.094-145.768-50.972-219.705 81.18 99.537 202.505 165.092 339.285 171.918-24.064-102.912 54.101-202.107 160.275-202.107 47.369 0 90.112 20.025 120.187 52.034 37.509-7.396 112.924-60.833 144.706-79.682-12.288 38.438-78.26 119.353-112.299 139.7 33.375-3.944 92.786 5.613 122.292-7.509-22.092 33.015-77.596 49.133-109.833 72.325z" - ], - "grid": 0, - "tags": [ - "twitter" - ] - }, - "properties": { - "order": 34, - "id": 0, - "prevSize": 32, - "code": 58913, - "name": "twitter", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M770.37-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM382.028 837.385c-11.169 5.329-34.076 3.375-54.537 3.375h-114.65c-35.631 0-68.191 1.517-75.7-23.381-6.106-20.271-1.119-64.645-1.119-89.050v-180.319c0-42.856-9.273-100.58 23.362-110.213 11.548-3.432 31.744-1.1 46.763-1.1h47.863c44.297 0 91.913-7.111 109.682 15.113l34.114 364.961c-2.484 8.875-7.377 16.631-15.777 20.613zM857.335 628.11c34.816 21.656 18.413 91.231-14.488 102.419 19.475 16.194 13.103 52.527 0 67.906-45.796 53.779-181.305 37.831-284.937 37.831-23.438 0-48.109 2.788-64.55 0-15.246-2.617-26.662-11.264-38.381-19.589l-35.252-377.268c6.163-10.714 11.89-21.751 14.658-26.131 21.883-34.683 44.582-68.248 73.444-93.506 14.829-12.971 32.635-20.271 51.219-32.275 23.324-15.095 56.699-58.615 60.113-93.487 1.384-14.526-2.882-39.481 3.319-52.357 5.803-11.947 29.715-27.572 50.119-21.125 23.59 7.452 42.174 45.435 44.544 75.719 2.332 30.549-3.11 62.995-15.607 83.437-13.464 22.035-28.236 30.587-36.731 47.863-7.49 15.208-9.956 28.046-12.25 52.319 79.929 4.855 201.216-13.388 233.775 41.188 17.446 29.26-6.22 85.257-30.075 96.825 43.899 14.715 42.344 93.62 1.081 110.232zM258.181 686.478c-26.188 0-47.332 21.618-47.332 48.223 0 26.491 21.144 47.919 47.332 47.919 26.036 0 47.351-21.428 47.351-47.919-0-26.605-21.314-48.223-47.351-48.223z" - ], - "grid": 0, - "tags": [ - "thumbs-up" - ] - }, - "properties": { - "order": 35, - "id": 0, - "prevSize": 32, - "code": 58914, - "name": "thumbs-up", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M248.889 1024h521.481c138.202 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.057-251.278-251.259-251.278h-521.481c-138.183 0-251.259 113.076-251.259 251.278v521.481c0 138.183 113.076 251.259 251.259 251.259zM637.231 186.596c11.169-5.329 34.076-3.375 54.537-3.375h114.65c35.631 0 68.191-1.517 75.7 23.381 6.106 20.271 1.119 64.645 1.119 89.050v180.319c0 42.856 9.254 100.58-23.362 110.213-11.548 3.432-31.744 1.1-46.763 1.1h-47.863c-44.297 0-91.932 7.092-109.682-15.113l-34.114-364.961c2.484-8.875 7.358-16.631 15.777-20.613zM161.925 395.871c-34.816-21.656-18.413-91.231 14.488-102.419-19.475-16.194-13.103-52.527 0-67.906 45.796-53.779 181.305-37.831 284.937-37.831 23.438 0 48.109-2.788 64.55 0 15.246 2.617 26.643 11.264 38.381 19.589l35.252 377.268c-6.163 10.714-11.89 21.751-14.658 26.131-21.883 34.683-44.582 68.248-73.444 93.506-14.829 12.971-32.635 20.271-51.219 32.275-23.324 15.095-56.699 58.615-60.113 93.487-1.384 14.526 2.882 39.481-3.319 52.357-5.803 11.947-29.715 27.572-50.119 21.125-23.59-7.452-42.174-45.435-44.544-75.719-2.332-30.549 3.11-62.995 15.607-83.437 13.464-22.035 28.236-30.587 36.731-47.863 7.49-15.208 9.956-28.046 12.25-52.319-79.929-4.855-201.216 13.388-233.775-41.188-17.446-29.26 6.22-85.257 30.075-96.825-43.899-14.715-42.344-93.62-1.081-110.232zM761.079 512.815c26.188 0 47.332-21.618 47.332-48.223 0-26.491-21.144-47.919-47.332-47.919-26.036 0-47.351 21.428-47.351 47.919 0 26.605 21.314 48.223 47.351 48.223z" - ], - "grid": 0, - "tags": [ - "thumbs-down" - ] - }, - "properties": { - "order": 36, - "id": 0, - "prevSize": 32, - "code": 58915, - "name": "thumbs-down", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M630.139 539.212h124.511l-61.668-234.837-62.843 234.837zM231.993 596.082h64.076l-31.611-147.399-32.465 147.399zM772.741-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM344.955 763.354l-27.989-95.782h-106.97l-29.639 95.782h-88.235l135.604-422.798h72.306l131.736 422.798h-86.812zM820.452 764.321l-37.66-128.872h-182.234l-39.898 128.872h-99.631l182.5-568.984h97.318l177.304 568.984h-97.697z" - ], - "grid": 0, - "tags": [ - "text-resize" - ] - }, - "properties": { - "order": 37, - "id": 0, - "prevSize": 32, - "code": 58916, - "name": "text-resize", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M593.427 476.824l128.91-93.867h-152.292l-58.482-140.383-46.895 140.383h-152.102l128.74 93.867-58.615 163.859 128.872-105.396 128.683 105.396-46.82-163.859zM479.327 865.754c-12.535-1.271-24.86-3.167-36.997-5.613 7.073-44.146-1.764-89.695-16.498-124.511-15.607-35.157-33.849-51.333-57.192-54.177-18.489 38.153-29.582 81.408-16.308 120.282 5.158 16.137 14.45 29.449 26.207 39.671-41.719-16.194-79.796-39.519-113.076-68.267 22.812-30.208 36.978-67.186 41.908-100.902 4.741-36.807-2.2-61.402-19.191-78.412-30.417 20.992-57.116 51.086-64.455 90.491-3.527 17.048-2.503 33.773 1.801 49.019-22.206-25.638-41.131-54.101-56.092-84.935 28.236-13.843 51.731-39.177 66.238-67.584 14.791-30.398 16.251-57.742 7.945-83.437-29.961 2.996-59.62 17.105-77.122 48.811-10.638 18.413-14.962 40.183-13.824 61.478-14.127-40.258-22.168-83.399-22.168-128.493 0-6.618 0.531-13.103 0.853-19.646 25.998 3.508 52.698-5.803 74.183-24.026 22.528-20.063 34.456-46.061 39.31-75.34-23.192-13.179-50.991-15.455-76.724 4.134-12.25 8.913-22.225 21.921-29.544 36.978 8.325-40.865 22.831-79.493 42.894-114.593 18.148 16.005 42.837 20.499 69.044 13.767 28.027-7.851 52.11-26.719 74.088-50.574-11.093-21.732-33.052-36.257-64.645-30.91-16.194 2.295-32.465 9.956-47.028 21.371 24.595-31.479 53.893-58.994 86.907-81.617 9.69 17.92 30.644 27.553 60.226 27.667 31.953-0.474 68.191-11.074 107.501-24.595-0.076-19.646-17.692-36.409-54.632-39.974-17.863-2.105-37.755-0.171-57.325 5.101 26.889-12.497 55.315-22.281 85.125-28.388 8.875-1.839 14.583-10.468 12.781-19.342-1.839-8.875-10.468-14.583-19.342-12.781-24.595 5.044-48.375 12.269-71.206 21.39 9.406-6.751 18.508-13.634 26.984-20.651 30.758-24.538 45.189-46.459 35.821-64.512-55.334 7.433-104.638 31.004-130.522 60.738-22.964 27.288-24.102 51.693-13.786 68.267-30.929 21.182-58.918 46.251-83.153 74.695 5.385-11.7 10.297-23.514 13.995-35.518 11.34-35.233 10.031-64-6.903-81.56-39.045 24.424-68.551 64.417-76.079 103.424-6.542 36.466 5.329 62.445 24.329 76.667-20.385 35.404-35.385 74.202-44.809 115.124-1.517-14.962-3.982-29.772-8.344-44.070-10.543-35.631-29.355-60.113-55.031-66.844-19.608 41.169-24.311 91.212-10.012 128.133 13.426 33.849 37.945 49 63.431 50.953-0.55 8.799-1.176 17.598-1.176 26.529 0 40.638 5.803 79.91 16.536 117.077-7.396-9.766-15.436-19.058-25.012-27.117-27.117-23.381-58.311-32.939-87.704-23.040-0.076 47.18 17.958 93.431 48.981 115.845 29.62 20.992 62.123 16.915 89.41 0.607 21.713 44.772 51.124 85.011 86.509 119.239-20.366-15.986-44.525-26.377-72.761-29.696-37.092-4.722-73.652 5.215-101.205 31.991 17.427 43.71 54.367 75.985 95.706 77.748 42.060 1.422 76.023-26.169 97.811-61.762-1.062-1.176-2.2-2.219-3.3-3.356 44.734 38.969 97.564 68.93 155.913 86.319-25.998 1.062-51.75 7.964-77.483 21.732-38.628 20.442-69.006 53.039-81.806 94.265 40.031 26.377 95.516 30.53 138.505 5.139 41.434-24.841 59.525-68.077 61.497-111.332 12.079 2.332 24.311 4.248 36.75 5.499 0.55 0.057 1.1 0.076 1.65 0.076 8.306 0 15.436-6.258 16.289-14.715 0.872-8.988-5.689-17.048-14.677-17.939zM934.817 569.154c-9.595 8.078-17.673 17.37-25.050 27.174 10.752-37.186 16.536-76.478 16.555-117.134 0-8.951-0.626-17.749-1.176-26.548 25.505-1.953 50.024-17.086 63.469-50.953 14.298-36.921 9.595-86.945-10.012-128.133-25.676 6.732-44.506 31.213-55.031 66.844-4.38 14.317-6.827 29.165-8.306 44.127-9.425-40.96-24.443-79.777-44.828-115.2 19.001-14.222 30.891-40.201 24.348-76.686-7.509-39.007-37.035-79-76.079-103.424-16.953 17.56-18.242 46.327-6.903 81.56 3.679 12.023 8.609 23.874 14.014 35.593-24.235-28.482-52.243-53.589-83.191-74.771 10.335-16.574 9.178-40.979-13.786-68.267-25.884-29.734-75.188-53.305-130.522-60.738-9.368 18.053 5.063 39.974 35.821 64.512 8.495 7.035 17.636 13.919 27.060 20.708-22.869-9.121-46.668-16.384-71.301-21.409-8.875-1.839-17.541 3.906-19.361 12.781-1.801 8.837 3.925 17.503 12.8 19.323 29.81 6.106 58.216 15.872 85.125 28.388-19.57-5.272-39.462-7.187-57.325-5.101-36.94 3.565-54.556 20.328-54.632 39.974 39.31 13.502 75.548 24.102 107.501 24.595 29.582-0.114 50.536-9.747 60.226-27.667 32.958 22.604 62.236 50.1 86.831 81.541-14.564-11.378-30.815-19.001-46.971-21.314-31.592-5.329-53.551 9.197-64.645 30.91 21.978 23.874 46.080 42.724 74.088 50.574 26.188 6.732 50.897 2.238 69.025-13.748 20.044 35.081 34.532 73.652 42.856 114.479-7.32-15.019-17.256-27.989-29.487-36.883-25.714-19.589-53.532-17.313-76.724-4.134 4.855 29.279 16.801 55.277 39.31 75.34 21.466 18.204 48.166 27.534 74.145 24.045 0.341 6.542 0.872 13.028 0.872 19.646 0 45.056-8.040 88.14-22.13 128.398 1.119-21.276-3.224-43.027-13.824-61.383-17.522-31.706-47.161-45.815-77.122-48.811-8.306 25.695-6.846 53.058 7.945 83.437 14.507 28.407 37.983 53.741 66.2 67.584-14.943 30.796-33.868 59.24-56.055 84.859 4.305-15.208 5.31-31.934 1.801-48.943-7.358-39.405-34.039-69.499-64.455-90.491-16.991 16.991-23.931 41.586-19.191 78.412 4.93 33.716 19.115 70.694 41.889 100.883-33.28 28.748-71.339 52.053-113.038 68.267 11.757-10.221 21.011-23.514 26.188-39.652 13.255-38.874 2.162-82.129-16.308-120.282-23.324 2.844-41.567 19.039-57.192 54.177-14.715 34.816-23.571 80.365-16.479 124.511-12.174 2.427-24.5 4.343-37.035 5.613-9.026 0.91-15.55 8.951-14.639 17.977 0.872 8.439 8.021 14.734 16.327 14.734 0.531 0 1.1-0.038 1.65-0.095v-0.038c12.421-1.252 24.671-3.167 36.75-5.499 1.972 43.255 20.063 86.49 61.478 111.332 42.989 25.391 98.456 21.22 138.505-5.139-12.819-41.225-43.179-73.823-81.806-94.265-25.733-13.786-51.503-20.689-77.521-21.732 58.425-17.427 111.313-47.407 156.084-86.471-1.157 1.176-2.332 2.276-3.451 3.508 21.788 35.593 55.751 63.185 97.811 61.762 41.339-1.764 78.279-34.039 95.706-77.748-27.553-26.757-64.114-36.712-101.205-31.991-28.274 3.356-52.489 13.748-72.875 29.772 35.404-34.247 64.872-74.505 86.585-119.334 27.288 16.289 59.771 20.404 89.429-0.588 31.023-22.433 49.057-68.665 48.981-115.845-29.412-9.88-60.606-0.322-87.723 23.078z" - ], - "grid": 0, - "tags": [ - "success-stories" - ] - }, - "properties": { - "order": 38, - "id": 0, - "prevSize": 32, - "code": 58917, - "name": "success-stories", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M124.113 449.574h132.741v385.574h-132.741v-385.574z", - "M250.539 1023.204h521.481c93.127 0 174.668-51.465 218.055-127.241h-957.611c43.387 75.776 124.947 127.241 218.074 127.241z", - "M336.915 196.741h132.741v638.426h-132.741v-638.426z", - "M549.736 323.148h132.741v512h-132.741v-512z", - "M762.539 1.574h132.741v833.574h-132.741v-833.574z" - ], - "grid": 0, - "tags": [ - "statistics" - ] - }, - "properties": { - "order": 39, - "id": 0, - "prevSize": 32, - "code": 58918, - "name": "statistics", - "ligatures": "" - } - }, - { - "icon": { - "paths": [ - "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM376.055 250.842l269.065 175.066-36.693 57.989-273.484-168.107 41.112-64.948zM295.291 404.082l307.352 92.748-18.982 65.953-309.627-84.764 21.257-73.937zM260.437 551.064l319.052 35.821-6.789 68.248-319.848-27.553 7.585-76.516zM252.587 680.562h321.024v76.895h-321.024v-76.895zM698.804 890.558h-570.728v-351.118h65.517v290.873h441.799v-290.873h63.412v351.118zM653.047 419.176l-178.745-266.676 64.398-41.927 171.823 271.151-57.477 37.452zM717.577 378.709l-23.742-320.133 76.743-4.665 15.493 320.626-68.494 4.172z" - ], - "grid": 0, - "tags": [ - "stack-overflow" - ] - }, - "properties": { - "order": 40, - "id": 0, - "prevSize": 32, - "code": 58919, - "name": "stack-overflow", - "ligatures": "" - } - } - ], - "height": 1024, - "metadata": { - "name": "pythonicons" - } -} + "IcoMoonType": "selection", + "icons": [ + { + "icon": { + "paths": [ + "M1024 429.256c0-200.926-58.792-363.938-131.482-365.226 0.292-0.006 0.578-0.030 0.872-0.030h-82.942c0 0-194.8 146.336-475.23 203.754-8.56 45.292-14.030 99.274-14.030 161.502 0 62.228 5.466 116.208 14.030 161.5 280.428 57.418 475.23 203.756 475.23 203.756h82.942c-0.292 0-0.578-0.024-0.872-0.032 72.696-1.288 131.482-164.298 131.482-365.224zM864.824 739.252c-9.382 0-19.532-9.742-24.746-15.548-12.63-14.064-24.792-35.96-35.188-63.328-23.256-61.232-36.066-143.31-36.066-231.124 0-87.81 12.81-169.89 36.066-231.122 10.394-27.368 22.562-49.266 35.188-63.328 5.214-5.812 15.364-15.552 24.746-15.552 9.38 0 19.536 9.744 24.744 15.552 12.634 14.064 24.796 35.958 35.188 63.328 23.258 61.23 36.068 143.312 36.068 231.122 0 87.804-12.81 169.888-36.068 231.124-10.39 27.368-22.562 49.264-35.188 63.328-5.208 5.806-15.36 15.548-24.744 15.548zM251.812 429.256c0-51.95 3.81-102.43 11.052-149.094-47.372 6.554-88.942 10.324-140.34 10.324-67.058 0-67.058 0-67.058 0l-55.466 94.686v88.17l55.46 94.686c0 0 0 0 67.060 0 51.398 0 92.968 3.774 140.34 10.324-7.236-46.664-11.048-97.146-11.048-149.096zM368.15 642.172l-127.998-24.51 81.842 321.544c4.236 16.634 20.744 25.038 36.686 18.654l118.556-47.452c15.944-6.376 22.328-23.964 14.196-39.084l-123.282-229.152zM864.824 548.73c-3.618 0-7.528-3.754-9.538-5.992-4.87-5.42-9.556-13.86-13.562-24.408-8.962-23.6-13.9-55.234-13.9-89.078 0-33.844 4.938-65.478 13.9-89.078 4.006-10.548 8.696-18.988 13.562-24.408 2.010-2.24 5.92-5.994 9.538-5.994 3.616 0 7.53 3.756 9.538 5.994 4.87 5.42 9.556 13.858 13.56 24.408 8.964 23.598 13.902 55.234 13.902 89.078 0 33.842-4.938 65.478-13.902 89.078-4.004 10.548-8.696 18.988-13.56 24.408-2.008 2.238-5.92 5.992-9.538 5.992z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "bullhorn", + "megaphone", + "announcement", + "advertisement", + "news" + ], + "grid": 16 + }, + "attrs": [], + "properties": { + "order": 1, + "id": 0, + "prevSize": 32, + "code": 58880, + "name": "bullhorn", + "ligatures": "" + }, + "setIdx": 0, + "setId": 0, + "iconIdx": 0 + }, + { + "icon": { + "paths": [ + "M620.62 12.098c-40.884-6.808-83.266-9.918-123.999-9.728-40.695 0.19-79.569 3.622-113.74 9.728-100.693 17.806-118.993 54.974-118.993 123.657v90.738h238.004v30.208h-327.282c-69.177 0-129.764 41.624-148.689 120.68-21.883 90.662-22.85 147.266 0 241.873 16.934 70.466 57.287 120.68 126.502 120.68h81.787v-108.753c0-78.583 68.001-147.797 148.67-147.797h237.739c66.143 0 118.955-54.556 118.955-120.984v-226.664c-0-64.455-54.405-112.905-118.955-123.639zM395.681 166.021c-24.671 0-44.658-20.215-44.658-45.227 0-25.050 19.987-45.473 44.658-45.473 24.557 0 44.658 20.423 44.658 45.473 0.019 24.993-20.082 45.227-44.658 45.227z", + "M995.157 394.923c-17.067-68.798-49.74-120.623-118.955-120.623h-89.335v105.662c0 82.034-69.48 150.945-148.67 150.945h-237.72c-65.119 0-118.974 55.732-118.974 120.927v226.588c0 64.493 56.073 102.438 118.974 120.946 75.34 22.13 147.589 26.131 237.739 0 59.885-17.332 118.993-52.281 118.993-120.946v-90.738h-237.701v-30.189h356.712c69.139 0 94.967-48.242 118.955-120.642 24.841-74.562 23.799-146.242-0.019-241.929zM625.417 848.194c24.652 0 44.639 20.177 44.639 45.189 0 25.145-19.987 45.454-44.639 45.454-24.614 0-44.658-20.309-44.658-45.454 0-24.993 20.063-45.189 44.658-45.189z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "python-alt" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 2, + "id": 0, + "prevSize": 24, + "code": 58881, + "name": "python-alt", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 0 + }, + { + "icon": { + "paths": [ + "M770.37-2.37h-521.481c-138.221 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.038 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.076-251.259-251.259-251.259zM958.369 763.183c0 100.447-95.63 195.489-195.508 195.489h-502.348c-97.033 0-195.527-95.042-195.527-195.489v-65.479h893.364v65.479zM958.369 636.075h-893.364v-253.649h893.364v253.649zM958.369 320.796h-893.364v-59.999c0-96.446 96.104-195.489 195.527-195.489h502.348c99.878 0 195.508 99.044 195.508 195.489v59.999zM383.924 223.611h260.741v-61.63h-260.741v61.63zM644.665 479.611h-260.741v61.63h260.741v-61.63zM644.665 797.26h-260.741v61.63h260.741v-61.63z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "pypi" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 3, + "id": 1, + "prevSize": 24, + "code": 58882, + "name": "pypi", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 1 + }, + { + "icon": { + "paths": [ + "M957.63 189.212v574.805c0 94.853-64 128.531-64 128.531s0-730.624 0-895.962l-893.63 1.043v771.66c0 138.221 113.076 251.259 251.259 251.259h519.111c138.183 0 251.259-113.038 251.259-251.259v-580.286l-64 0.209zM831.393 930.74c0 0-25.998 23.514-72.59 23.514 0 0-426.515 1.157-497.436 1.157-91.041 0-196.058-97.527-196.058-192.891s0.967-700.094 0.967-700.094h765.118v868.314z", + "M770.37 173.511v-47.407h-636.833v125.63h636.833z", + "M133.537 378.937h315.24v65.574h-315.24v-65.574z", + "M133.537 761.363h635.24v65.574h-635.24v-65.574z", + "M133.537 506.937h315.24v65.574h-315.24v-65.574z", + "M133.537 632.567h315.24v65.574h-315.24v-65.574z", + "M770.37 630.215v-251.278h-259.963v320.019h259.963z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "news" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 4, + "id": 2, + "prevSize": 24, + "code": 58883, + "name": "news", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 2 + }, + { + "icon": { + "paths": [ + "M508.207 66.882c-244.452 0-442.615 198.163-442.615 442.615 0 244.452 198.163 442.615 442.615 442.615 244.471 0 442.615-198.163 442.615-442.615-0-244.452-198.201-442.615-442.615-442.615zM164.485 424.467l-22.414-22.414c22.225-75.928 67.508-141.862 127.526-190.18l34.266 127.829c-53.134 17.010-100.712 46.364-139.378 84.764zM409.335 764.188c-52.679 0-95.384-42.705-95.384-95.403 0-38.116 22.528-70.751 54.898-86.016l42.648-197.879 45.378 201.709c28.463 16.479 47.825 46.952 47.825 82.185-0.019 52.698-42.705 95.403-95.365 95.403zM409.335 323.205c-23.571 0-46.554 2.408-68.779 6.884l-38.116-142.241c59.335-38.153 129.934-60.283 205.767-60.283 35.992 0 70.751 5.139 103.765 14.45l-83.778 202.278c-37.111-13.502-77.065-21.087-118.86-21.087zM731.932 540.52c-32.18-79.189-92.615-143.834-168.77-181.476l84.897-204.971c131.641 51.883 227.48 174.839 240.375 321.612l-156.501 64.834z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "moderate" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 5, + "id": 3, + "prevSize": 24, + "code": 58884, + "name": "moderate", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 3 + }, + { + "icon": { + "paths": [ + "M855.249 128.341c23.211 0 42.78 19.608 42.78 42.78v680.941c0 23.211-19.57 42.78-42.78 42.78h-680.96c-23.192 0-42.78-19.57-42.78-42.78v-680.941c0-23.192 19.608-42.78 42.78-42.78h680.96M855.249 0h-680.96c-94.113 0-171.122 77.009-171.122 171.122v680.941c0 94.132 77.009 171.122 171.122 171.122h680.941c94.132 0 171.122-77.009 171.122-171.122v-680.941c0.019-94.094-76.99-171.122-171.103-171.122v0z", + "M421.812 682.401v-205.464h-118.519v205.464h-64.853v-464.915h64.853v203.321h118.519v-203.321h65.593v464.934h-65.593z", + "M666.131 839.054c-76.516 0-124.549-49.512-124.549-115.105 0-51.010 27.629-84.556 56.813-96.18l-29.886-32.047c0.702-21.144 16.043-40.789 32.047-49.55-26.226-19.646-42.249-48.792-42.249-90.321 0-64.152 41.51-110.099 104.922-110.099 15.322 0 26.965 2.219 35.707 5.12 10.942 3.622 22.604 5.803 37.129 5.803 16.043 0 31.346-5.803 40.088-11.605l8.761 51.75c-4.399 3.622-17.503 8.021-26.965 8.021 5.784 10.923 10.183 29.146 10.183 51.029 0 59.752-37.888 108.544-102.040 110.023-21.106 0-33.527 5.784-33.527 18.223 0 4.361 3.66 11.643 11.681 14.601l63.374 21.826c51.75 17.484 81.636 53.21 81.636 110.080 0.038 61.080-48.052 108.43-123.127 108.43zM690.195 671.497l-40.808-11.7c-31.308 2.939-51.75 26.245-51.75 64.834 0 33.545 22.604 65.65 67.755 65.65 43.748 0 65.612-30.625 65.612-59.733 0.019-27.743-13.843-51.75-40.808-59.051zM663.249 394.562c-27.743 0-48.090 26.965-48.090 61.25 0 34.949 20.347 61.175 48.090 61.175 26.226 0 48.773-26.226 48.773-61.175 0.019-34.285-20.347-61.25-48.773-61.25z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "mercurial" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 6, + "id": 4, + "prevSize": 24, + "code": 58885, + "name": "mercurial", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 4 + }, + { + "icon": { + "paths": [ + "M899.167 678.665l-291.499 50.157v29.412c0 45.151-50.498 81.655-94.872 81.655-44.582 0-94.834-36.504-94.834-81.655v-29.412l-291.537-50.157c-69.101 0-125.63-63.962-125.63-63.962v282.074c0 69.12 56.529 125.63 125.63 125.63h772.741c69.101 0 125.63-56.51 125.63-125.63v-282.074c0 0-56.529 63.962-125.63 63.962z", + "M899.167 254.369h-194.37v-66.37c0.19-36.030-11.397-69.367-35.366-92.35-23.893-23.059-57.079-33.413-92.634-33.28h-130.37c-35.593-0.114-68.779 10.221-92.653 33.28-24.007 22.983-35.556 56.32-35.366 92.35v66.37h-191.981c-69.101 0-125.63 56.529-125.63 125.63v128c0 69.12 56.529 125.63 125.63 125.63l339.039 56.168v52.338c0 26.491 21.163 47.938 47.332 47.938 26.055 0 47.369-21.447 47.369-47.938v-52.357l339.001-56.149c69.101 0 125.63-56.51 125.63-125.63v-128c0-69.101-56.529-125.63-125.63-125.63zM384.777 187.999c0.19-23.268 6.466-36.143 15.019-44.582 8.704-8.306 22.907-14.601 46.63-14.715h130.37c23.666 0.114 37.907 6.391 46.573 14.715 8.571 8.439 14.81 21.314 15.057 44.582-0.019 21.902-0.019 45.416-0.019 66.37h-253.63c0-20.954 0-44.468 0-66.37z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "jobs" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 7, + "id": 5, + "prevSize": 24, + "code": 58886, + "name": "jobs", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 5 + }, + { + "icon": { + "paths": [ + "M772.741-0.019h-521.481c-138.183 0-251.259 113.076-251.259 251.278v521.481c0 138.183 113.076 251.259 251.259 251.259h521.481c138.221 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.038-251.278-251.259-251.278zM593.029 896.777h-185.401v-189.573h185.401v189.573zM748.791 409.429c-14.639 24.652-44.601 54.746-89.809 90.283-31.497 24.955-51.39 44.999-59.639 60.113-8.287 15.132-12.383 55.751-12.383 80.1h-177.778v-38.703c0-30.246 3.432-54.803 10.297-73.671 6.865-18.887 17.048-36.087 30.625-51.693 13.577-15.588 44.051-43.046 91.458-82.318 25.259-20.594 37.888-39.462 37.888-56.604s-5.082-30.473-15.208-39.993c-10.126-9.5-25.505-14.26-46.080-14.26-22.168 0-40.467 7.339-54.955 21.978-14.526 14.658-23.78 40.22-27.838 76.724l-181.495-22.452c6.239-66.731 30.473-120.453 72.742-161.166 42.268-40.695 107.046-61.042 194.351-61.042 68.001 0 122.861 14.184 164.693 42.572 56.737 38.362 85.106 89.505 85.106 153.429-0 26.51-7.301 52.072-21.978 76.705z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "help" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 8, + "id": 6, + "prevSize": 24, + "code": 63, + "name": "help", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 6 + }, + { + "icon": { + "paths": [ + "M129.271 383.507l383.166 382.805 380.075-382.805h-190.255v-320.076h-382.085v320.076z", + "M736.484 635.657l-224.047 225.47-225.375-225.185h-288.161v135.149c0 138.202 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.057 251.259-251.259v-135.149l-286.417-0.284z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "download" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 10, + "id": 7, + "prevSize": 24, + "code": 58889, + "name": "download", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 7 + }, + { + "icon": { + "paths": [ + "M731.439 149.751l-25.031 39.329-90.529-57.628-186.292 292.636 39.974 25.467 160.825-252.644 50.574 32.161-331.473 520.742 9.937 51.333-36.162 57.666 6.201 30.853 30.891-7.623 35.669-56.889 52.148-12.516 381.933-600.064z", + "M772.741-2.37h-521.481c-138.202 0-251.259 113.057-251.259 251.259v521.481c0 138.183 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.076-251.259-251.259-251.259zM99.366 811.179c-26.169 0-47.332-21.447-47.332-47.919 0-26.624 21.163-48.223 47.332-48.223 26.055 0 47.369 21.599 47.369 48.223-0.019 26.472-21.314 47.919-47.369 47.919zM99.366 557.549c-26.169 0-47.332-21.447-47.332-47.938 0-26.605 21.163-48.223 47.332-48.223 26.055 0 47.369 21.618 47.369 48.223-0.019 26.491-21.314 47.938-47.369 47.938zM99.366 303.919c-26.169 0-47.332-21.428-47.332-47.938 0-26.605 21.163-48.223 47.332-48.223 26.055 0 47.369 21.618 47.369 48.223-0.019 26.51-21.314 47.938-47.369 47.938zM955.259 735.365c0 119.637-97.887 217.524-217.524 219.895l-543.365-1.745v-886.689l543.365-0.455c119.637 0 217.524 97.887 217.524 217.524v451.47z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "documentation" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 11, + "id": 8, + "prevSize": 24, + "code": 58890, + "name": "documentation", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 8 + }, + { + "icon": { + "paths": [ + "M512.986 682.989c57.647 0 104.277-46.592 104.277-104.183 0-57.496-46.63-104.145-104.277-104.145-57.458 0-104.164 46.649-104.164 104.145 0.019 57.591 46.706 104.183 104.164 104.183", + "M763.733 711.32c45.378 0 82.072-36.674 82.072-81.996 0-45.265-36.712-81.958-82.072-81.958-45.189 0-81.996 36.712-81.996 81.958 0 45.321 36.826 81.996 81.996 81.996", + "M785.749 748.791c-39.045 0-73.519 17.863-95.004 45.303 7.851 16.839 12.231 35.423 12.231 54.955v110.042h200.666v-99.556c-0.019-61.156-52.717-110.744-117.893-110.744", + "M260.305 711.32c45.189 0 81.996-36.674 81.996-81.996 0-45.265-36.807-81.958-81.996-81.958-45.359 0-82.091 36.712-82.091 81.958-0 45.321 36.731 81.996 82.091 81.996", + "M238.308 748.791c-65.195 0-117.893 49.569-117.893 110.744v99.556h200.666v-110.042c0-19.532 4.38-38.135 12.212-54.955-21.466-27.42-55.96-45.303-94.985-45.303", + "M512.986 714.562c-84.689 0-153.259 64.417-153.259 143.91v162.437h306.498v-162.437c0-79.493-68.494-143.91-153.24-143.91", + "M891.847 129.119c0-70.068-169.491-126.919-379.051-126.919-208.896-0-378.728 56.851-378.728 126.919 0 44.108 67.167 82.906 168.903 105.662l-16.801 173.018 96.332-159.611c25.429 3.129 52.072 5.385 79.72 6.637l49.247 193.858 49.19-193.726c28.729-1.214 56.358-3.527 82.697-6.751l96.332 159.592-16.801-172.999c101.888-22.737 168.96-61.554 168.96-105.681z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "community" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 12, + "id": 9, + "prevSize": 24, + "code": 58891, + "name": "community", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 9 + }, + { + "icon": { + "paths": [ + "M772.741-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM316.151 402.015l-124.947 108.241 124.947 108.241v112.242l-254.521-220.482 254.521-220.482v112.242zM461.577 825.135l-76.383-0.265 170.591-630.803 77.103-0.91-171.311 631.979zM699.164 725.94v-112.242l119.41-103.443-119.41-103.443v-112.242l248.984 215.685-248.984 215.685z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "code" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 13, + "id": 10, + "prevSize": 24, + "code": 58892, + "name": "code", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 10 + }, + { + "icon": { + "paths": [ + "M770.37-2.37h-521.481c-138.183 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.076 251.259 251.259 251.259h521.481c138.221 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.038-251.259-251.259-251.259zM825.742 670.758l-155.117 155.098-160.18-160.18-160.199 160.218-155.136-155.136 160.199-160.218-160.199-160.218 155.136-155.098 160.18 160.199 160.18-160.199 155.117 155.098-160.18 160.218 160.199 160.218z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "close" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 14, + "id": 11, + "prevSize": 24, + "code": 88, + "name": "close", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 11 + }, + { + "icon": { + "paths": [ + "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.076-251.259-251.259-251.259zM765.63 82.849c26.586 0 48.223 21.144 48.223 47.332 0 26.036-21.637 47.351-48.223 47.351-26.472 0-47.919-21.314-47.919-47.351 0-26.188 21.447-47.332 47.919-47.332zM512 82.849c26.586 0 48.223 21.144 48.223 47.332 0 26.036-21.637 47.351-48.223 47.351-26.491 0-47.919-21.314-47.919-47.351 0-26.188 21.428-47.332 47.919-47.332zM258.37 82.849c26.605 0 48.223 21.144 48.223 47.332 0 26.036-21.618 47.351-48.223 47.351-26.491 0-47.919-21.314-47.919-47.351 0-26.188 21.428-47.332 47.919-47.332zM732.843 953.666h-451.47c-119.637 0-217.524-97.887-219.895-217.524l1.745-479.365h886.689l0.455 479.365c0 119.637-97.887 217.524-217.524 217.524z", + "M533.561 320.796h150.528v146.963h-150.528v-146.963z", + "M737.583 320.796h150.528v146.963h-150.528v-146.963z", + "M125.44 534.111h150.528v146.963h-150.528v-146.963z", + "M329.5 534.111h150.528v146.963h-150.528v-146.963z", + "M533.561 534.111h150.528v146.963h-150.528v-146.963z", + "M737.583 534.111h150.528v146.963h-150.528v-146.963z", + "M275.968 894.407v-146.963h-150.528c0 82.887 83.209 146.963 150.528 146.963z", + "M329.5 747.444h150.528v146.963h-150.528v-146.963z", + "M533.561 747.444h150.528v146.963h-150.528v-146.963z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "calendar" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 15, + "id": 12, + "prevSize": 24, + "code": 58894, + "name": "calendar", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 12 + }, + { + "icon": { + "paths": [ + "M508.207 66.882c-244.452 0-442.615 198.163-442.615 442.615 0 244.452 198.163 442.615 442.615 442.615 244.471 0 442.615-198.163 442.615-442.615-0-244.452-198.201-442.615-442.615-442.615zM164.485 424.467l-22.414-22.414c22.225-75.928 67.508-141.862 127.526-190.18l34.266 127.829c-53.134 17.010-100.712 46.364-139.378 84.764zM409.335 764.188c-52.679 0-95.384-42.705-95.384-95.403 0-9.956 1.972-19.38 4.798-28.425l-111.426-172.677 174.364 110.327c8.799-2.693 17.958-4.551 27.648-4.551 52.66 0 95.346 42.705 95.346 95.327 0 52.698-42.686 95.403-95.346 95.403zM409.335 323.205c-23.571 0-46.554 2.408-68.779 6.884l-38.116-142.241c59.335-38.153 129.934-60.283 205.767-60.283 35.992 0 70.751 5.139 103.765 14.45l-83.778 202.278c-37.111-13.502-77.065-21.087-118.86-21.087zM731.932 540.52c-32.18-79.189-92.615-143.834-168.77-181.476l84.897-204.971c131.641 51.883 227.48 174.839 240.375 321.612l-156.501 64.834z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "beginner" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 16, + "id": 13, + "prevSize": 24, + "code": 58895, + "name": "beginner", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 13 + }, + { + "icon": { + "paths": [ + "M508.207 66.882c-244.452 0-442.615 198.163-442.615 442.615 0 244.452 198.163 442.615 442.615 442.615 244.471 0 442.615-198.163 442.615-442.615-0-244.452-198.201-442.615-442.615-442.615zM508.207 127.583c35.992 0 70.751 5.139 103.765 14.45l-83.778 202.278c-37.092-13.521-77.047-21.087-118.86-21.087-23.571 0-46.554 2.408-68.779 6.884l-38.116-142.241c59.335-38.153 129.934-60.283 205.767-60.283zM164.485 424.467l-22.414-22.414c22.225-75.928 67.508-141.862 127.526-190.18l34.266 127.829c-53.134 17.010-100.712 46.364-139.378 84.764zM502.253 647.964c1.498 6.713 2.427 13.653 2.427 20.821 0 52.698-42.686 95.403-95.346 95.403-52.679 0-95.384-42.705-95.384-95.403 0-52.622 42.705-95.327 95.384-95.327 12.459 0 24.292 2.56 35.195 6.884l169.851-109.625-112.128 177.247zM731.932 540.52c-32.18-79.189-92.615-143.834-168.77-181.476l84.897-204.971c131.641 51.883 227.48 174.839 240.375 321.612l-156.501 64.834z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "advanced" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 17, + "id": 14, + "prevSize": 24, + "code": 58896, + "name": "advanced", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 14 + }, + { + "icon": { + "paths": [ + "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM197.215 189.212h279.078v-61.231h71.149v61.231h286.189v194.75h-286.189v61.668h-71.149v-61.687h-279.078l-103.329-96.18 103.329-98.551zM824.149 701.175h-276.708v255.64h-71.149v-255.64h-281.448v-193.517h629.305l103.367 97.337-103.367 96.18z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "sitemap" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 18, + "id": 15, + "prevSize": 24, + "code": 58897, + "name": "sitemap", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 15 + }, + { + "icon": { + "paths": [ + "M190.843 190.445c-78.431 78.507-78.431 205.577-0.038 284.027 78.412 78.374 205.596 78.412 284.008-0.019s78.412-205.559-0.038-283.951c-78.374-78.431-205.521-78.431-283.932-0.057zM442.216 358.343c-0.095-75.34-60.966-136.211-136.23-136.306v-26.795c90.055 0 163.025 73.045 163.1 163.119h-26.871zM770.37-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM944.242 838.447l-104.695 104.676c-15.663 15.701-41.169 15.663-56.87-0.019l-253.421-253.421c-15.701-15.72-15.701-41.188 0-56.908l27.781-27.781-61.857-61.876c-104.448 80.668-254.843 73.311-350.587-22.433-103.993-103.974-103.993-272.517 0-376.491 103.955-103.936 272.517-103.936 376.491 0.019 95.441 95.46 103.007 245.286 23.078 349.677l61.971 61.952 27.8-27.8c15.72-15.663 41.207-15.644 56.908 0l253.402 253.44c15.72 15.758 15.739 41.244 0 56.965z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "search" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 19, + "id": 16, + "prevSize": 24, + "code": 58898, + "name": "search", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 16 + }, + { + "icon": { + "paths": [ + "M190.843 190.445c-78.431 78.507-78.431 205.577-0.038 284.027 78.412 78.374 205.596 78.412 284.008-0.019s78.412-205.559-0.038-283.951c-78.374-78.431-205.521-78.431-283.932-0.057zM442.216 358.343c-0.095-75.34-60.966-136.211-136.23-136.306v-26.795c90.055 0 163.025 73.045 163.1 163.119h-26.871zM944.242 838.447l-104.695 104.676c-15.663 15.701-41.169 15.663-56.87-0.019l-253.421-253.421c-15.701-15.72-15.701-41.188 0-56.908l27.781-27.781-61.857-61.876c-104.448 80.668-254.843 73.311-350.587-22.433-103.993-103.974-103.993-272.517 0-376.491 103.955-103.936 272.517-103.936 376.491 0.019 95.441 95.46 103.007 245.286 23.078 349.677l61.971 61.952 27.8-27.8c15.72-15.663 41.207-15.644 56.908 0l253.402 253.44c15.72 15.758 15.739 41.244 0 56.965z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "search-alt" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 20, + "id": 17, + "prevSize": 24, + "code": 58899, + "name": "search-alt", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 17 + }, + { + "icon": { + "paths": [ + "M607.991 863.573c20.309 0 36.788-16.744 36.788-37.509 0-20.632-16.479-37.262-36.788-37.262-20.29 0-36.807 16.631-36.807 37.262 0 20.764 16.517 37.509 36.807 37.509zM418.475 151.249c-20.328 0-36.826 16.858-36.826 37.528 0 20.613 16.498 37.3 36.826 37.3 20.309 0 36.864-16.687 36.845-37.3-0-20.67-16.555-37.528-36.845-37.528zM772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.038 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM285.279 609.735v89.714h-67.47c-57.079 0-90.377-41.434-104.334-99.556-18.849-78.014-18.053-124.719 0-199.509 15.607-65.195 65.593-99.537 122.652-99.537h269.995v-24.917h-196.343v-74.847c0-56.623 15.113-87.305 98.152-101.983 28.179-5.025 60.245-7.87 93.81-8.021 33.583-0.171 68.57 2.389 102.305 8.021 53.267 8.856 98.152 48.83 98.152 101.964v186.956c0 54.803-43.596 99.802-98.152 99.802h-196.134c-66.541 0.019-122.633 57.135-122.633 121.913zM912.991 614.438c-19.816 59.733-41.112 99.556-98.152 99.556h-294.21v24.879h196.077v74.828c0 56.642-48.735 85.466-98.152 99.783-74.373 21.542-133.973 18.242-196.115 0-51.902-15.284-98.133-46.573-98.133-99.783v-186.899c0-53.779 44.411-99.764 98.133-99.764h196.096c65.308 0 122.633-56.832 122.633-124.492v-87.173h73.69c57.116 0 84.044 42.761 98.152 99.518 19.627 78.943 20.48 138.069-0.019 199.547z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "python" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 21, + "id": 18, + "prevSize": 24, + "code": 58900, + "name": "python", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 18 + }, + { + "icon": { + "paths": [ + "M653.672 373.077c-32.521 0-58.861 26.908-58.861 59.98 0 32.977 26.34 59.62 58.861 59.62 32.446 0 58.899-26.624 58.899-59.62 0-33.071-26.453-59.98-58.899-59.98zM393.216 373.077c-32.54 0-58.88 26.908-58.88 59.98 0 32.977 26.34 59.62 58.88 59.62 32.351 0 58.88-26.624 58.88-59.62 0-33.071-26.529-59.98-58.88-59.98zM772.741-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM853.807 399.474c0 32.275-4.248 60.568-12.117 85.694l-2.882 9.14c-1.517 4.21-3.413 8.533-5.367 12.933l-4.229 9.083c-33.849 67.413-101.812 105.472-198.58 120.396l-11.719 1.801 7.927 8.761c19.361 21.39 28.843 43.653 30.303 67.47v171.672c0.057 13.502 5.404 24.614 13.672 33.887-34.854-2.313-58.785-15.227-58.823-37.054v-143.019c0-18.773-17.73-20.518-20.006-20.518-0.796 0-1.441 0.114-1.877 0.209l-4.798 1.176v5.006c0 0 0 153.6 0 169.586-0.19 11.928 2.465 22.509 9.178 31.801-38.381-1.877-53.267-19.589-53.855-40.695 0 0.038 0-147.949 0-156.331 0-8.306-7.471-12.667-13.047-12.667-5.784 0-13.16 4.399-13.16 12.667-0.038 8.268-0.038 164.087-0.038 164.087-0.74 23.097-24.102 31.801-56.548 32.787 5.158-7.301 9.254-16.194 9.235-28.065v-180.053l-6.808 0.531c-0.171 0-19.001 1.365-19.589 20.461v146.792c-0.057 18.318-21.011 36.75-54.405 38.4 6.428-8.078 10.335-18.375 10.202-30.663v-119.182h-57.742c-107.179 1.138-101.224-97.261-162.854-146.66 56.737 6.713 80.801 85.845 155.003 87.685 45.359 0 56.623 0 56.623 0h5.575l0.702-5.537c3.3-25.335 15.55-47.388 39.367-66.807l11.681-9.576-14.905-1.669c-105.946-12.629-176.981-51.655-213.883-117.153l-5.082-9.121c-1.953-3.906-3.812-8.363-5.727-13.028l-3.565-9.14c-9.633-26.624-14.943-57.135-15.436-91.61-0.019-1.46-0.019-2.788-0.019-4.172 0.057-58.482 16.194-110.345 56.908-153.562l2.446-2.655-0.891-3.356c-5.348-20.196-7.813-40.505-7.889-60.928 0.038-24.804 3.812-49.778 10.923-75.055 46.364 2.958 93.544 19.342 141.919 52.034l2.219 1.46 2.655-0.569c39.633-8.647 79.379-12.705 119.068-12.705 41.036 0 82.072 4.38 123.089 12.705l2.731 0.512 2.257-1.555c41.358-29.374 87.381-46.611 138.847-51.712 8.495 28.786 13.464 57.534 13.464 86.13 0 12.971-0.967 25.96-3.148 38.969l-0.436 2.788 1.82 2.238c37.395 46.156 60.928 101.205 61.705 172.544-0.133 1.081-0.095 2.276-0.095 3.413z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "github" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 22, + "id": 19, + "prevSize": 24, + "code": 58901, + "name": "github", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 19 + }, + { + "icon": { + "paths": [ + "M511.924 578.37c33.489 0 60.7-24.367 60.7-63.147v-445.8c0-38.836-27.231-63.109-60.7-63.109-33.527 0-60.681 24.273-60.681 63.109v445.8c0 38.779 27.174 63.147 60.681 63.147zM703.924 104.107v146.015c95.554 62.407 158.853 169.965 158.853 292.599 0 193.214-156.691 349.886-349.98 349.886-193.308 0-350.018-156.672-350.018-349.886 0-122.292 62.957-229.623 158.056-292.124v-146.053c-168.77 74.012-286.853 242.157-286.853 438.272 0 264.439 214.376 478.815 478.815 478.815 264.42 0 478.796-214.376 478.796-478.815 0-196.418-118.424-364.904-287.668-438.708z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "get-started" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 23, + "id": 20, + "prevSize": 24, + "code": 58902, + "name": "get-started", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 20 + }, + { + "icon": { + "paths": [ + "M770.37 0h-521.481c-138.202 0-251.259 113.057-251.259 251.259v521.481c0 138.183 113.057 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.076-251.259-251.259-251.259zM299.255 842.183c-65.043 0-117.76-52.698-117.76-117.741s52.717-117.741 117.76-117.741c65.005 0 117.722 52.698 117.722 117.741s-52.736 117.741-117.722 117.741zM611.745 827.923h-145.351c18.679-30.113 29.62-65.479 29.62-103.481 0-108.658-88.102-196.817-196.76-196.817-39.993 0-77.084 12.004-108.146 32.484v-146.508c33.906-11.795 70.182-18.565 108.146-18.66 181.931 0.322 329.14 147.551 329.463 329.481-0.095 36.162-6.163 70.903-16.972 103.5zM843.036 827.923h-149.030c8.666-33.109 13.786-67.698 13.786-103.519-0.057-225.64-182.936-408.5-408.519-408.519-37.528 0-73.633 5.48-108.146 14.943v-149.352c34.987-6.903 71.111-10.638 108.146-10.638 305.759 0 553.567 247.865 553.567 553.567-0.019 35.366-3.508 69.973-9.804 103.519z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "feed" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 24, + "id": 21, + "prevSize": 24, + "code": 58903, + "name": "feed", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 21 + }, + { + "icon": { + "paths": [ + "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM677.812 507.563h-105.453v381.952h-157.999v-381.952h-79v-131.622h79v-79.038c0-107.368 44.601-171.255 171.179-171.255h105.472v131.641h-65.896c-49.323 0-52.584 18.413-52.584 52.717l-0.19 65.934h119.448l-13.976 131.622z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "facebook" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 25, + "id": 22, + "prevSize": 24, + "code": 58904, + "name": "facebook", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 22 + }, + { + "icon": { + "paths": [ + "M896 188.056h-772.741c-69.101 0-125.63 56.529-125.63 125.63v5.177l509.63 253.193 514.37-255.545v-2.825c0-69.101-56.529-125.63-125.63-125.63zM1021.63 635.032v-252.169l-253.175 125.781 253.175 126.388zM-2.37 385.233v248.225l249.211-124.416-249.211-123.809zM507.259 638.426l-192.341-95.554-317.269 157.582c0.209 68.93 56.642 125.231 125.611 125.231h772.741c68.437 0 124.492-55.505 125.535-123.714l-321.138-159.497-193.138 95.953z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "email" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 26, + "id": 23, + "prevSize": 24, + "code": 58905, + "name": "email", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 23 + }, + { + "icon": { + "paths": [ + "M770.37-2.37h-521.481c-138.183 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.076 251.259 251.259 251.259h521.481c138.202 0 251.278-113.057 251.278-251.259v-521.481c0-138.183-113.076-251.259-251.278-251.259zM705.252 507.885v320.057h-382.066v-320.057h-190.255l380.094-382.824 383.166 382.824h-190.938z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "arrow-up" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 27, + "id": 24, + "prevSize": 24, + "code": 58906, + "name": "arrow-up", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 24 + }, + { + "icon": { + "paths": [ + "M770.37-2.37h-521.481c-138.221 0-251.259 113.076-251.259 251.259v521.481c0 138.183 113.038 251.259 251.259 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.183-113.076-251.259-251.259-251.259zM511.374 896.19v-190.938h-320.076v-382.066h320.076v-190.255l382.824 380.075-382.824 383.185z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "arrow-right" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 28, + "id": 25, + "prevSize": 24, + "code": 58907, + "name": "arrow-right", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 25 + }, + { + "icon": { + "paths": [ + "M770.37-2.389h-521.481c-138.183 0-251.259 113.076-251.259 251.278v521.481c0 138.183 113.076 251.259 251.259 251.259h521.481c138.221 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.038-251.278-251.259-251.278zM827.961 696.073h-320.076v190.255l-382.824-380.094 382.824-383.166v190.919h320.076v382.085z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "arrow-left" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 29, + "id": 26, + "prevSize": 24, + "code": 58908, + "name": "arrow-left", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 26 + }, + { + "icon": { + "paths": [ + "M770.389-2.37h-521.481c-138.202 0-251.278 113.038-251.278 251.259v521.481c0 138.183 113.076 251.259 251.278 251.259h521.481c138.183 0 251.259-113.076 251.259-251.259v-521.481c0-138.221-113.076-251.259-251.259-251.259zM506.254 894.18l-383.166-382.805h190.9v-320.076h382.085v320.076h190.255l-380.075 382.805z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "arrow-down" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 30, + "id": 27, + "prevSize": 24, + "code": 58909, + "name": "arrow-down", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 27 + }, + { + "icon": { + "paths": [ + "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.038 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM309.627 826.273c-99.859 0-180.812-80.953-180.812-180.793 0-99.821 80.953-180.774 180.812-180.774 27.364 0 53.267 6.277 76.535 17.18l-54.689 94.701c-6.884-2.238-14.241-3.451-21.845-3.451-39.936 0-72.325 32.37-72.325 72.306s32.389 72.344 72.325 72.344c35.537 0 65.062-25.714 71.111-59.506h109.037c-6.618 93.848-84.632 167.993-180.148 167.993zM438.234 306.593c0 19.456 7.737 37.035 20.215 50.081l-55.068 95.308c-44.563-32.92-73.652-85.694-73.652-145.389 0-99.821 80.953-180.774 180.812-180.774 99.84 0 180.774 80.934 180.774 180.774 0 59.582-28.937 112.318-73.406 145.237l-55.049-95.384c12.364-13.009 20.044-30.492 20.044-49.854 0-39.936-32.446-72.325-72.344-72.325-39.936 0-72.325 32.389-72.325 72.325zM708.475 826.216c-95.554 0-173.549-74.145-180.148-167.955h109.037c6.030 33.83 35.556 59.525 71.111 59.525 39.898 0 72.287-32.37 72.287-72.325 0-39.917-32.37-72.287-72.287-72.287-6.599 0-12.99 0.967-19.039 2.636l-54.917-95.175c22.585-10.145 47.597-15.948 73.956-15.948 99.859 0 180.774 80.934 180.774 180.755s-80.915 180.774-180.774 180.774z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "freenode" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 31, + "id": 28, + "prevSize": 24, + "code": 58910, + "name": "freenode", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 28 + }, + { + "icon": { + "paths": [ + "M990.701 763.98l-336.175-688.014c-58.69-104.41-224.616-92.558-269.483-1.214l-345.353 690.479c-74.828 142.279-0.929 258.769 164.162 258.769h620.165c165.073 0 240.090-117.020 166.684-260.020zM607.744 891.259h-185.401v-189.573h185.401v189.573zM610.057 384l-33.716 253.080h-122.728l-33.185-253.080v-192h189.63v192z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "alert" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 32, + "id": 29, + "prevSize": 24, + "code": 58911, + "name": "alert", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 29 + }, + { + "icon": { + "paths": [ + "M61.554 313.685l450.37-187.259 445.63 187.259-445.63 189.63z", + "M511.924 569.666l-297.415-125.212-152.955 63.602 450.37 189.611 445.63-189.611-151.343-63.602z", + "M511.924 761.666l-297.415-125.231-152.955 63.602 450.37 189.63 445.63-189.63-151.343-63.602z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "versions" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 33, + "id": 30, + "prevSize": 24, + "code": 58912, + "name": "versions", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 30 + }, + { + "icon": { + "paths": [ + "M688.583 286.227c-24.728 0-44.715 20.461-44.715 45.587 0 25.012 19.987 45.246 44.715 45.246 24.595 0 44.753-20.252 44.734-45.246 0.019-25.126-20.139-45.587-44.734-45.587zM772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM816.488 392.021c10.449 231.519-162.588 475.136-468.158 475.136-92.956 0-179.428-27.269-252.302-73.937 87.324 10.278 174.497-13.995 243.674-68.134-72.002-1.365-132.836-48.962-153.771-114.328 25.79 4.93 51.181 3.489 74.354-2.769-79.132-15.929-133.803-87.268-132.001-163.499 22.168 12.288 47.597 19.759 74.562 20.556-73.311-48.962-94.094-145.768-50.972-219.705 81.18 99.537 202.505 165.092 339.285 171.918-24.064-102.912 54.101-202.107 160.275-202.107 47.369 0 90.112 20.025 120.187 52.034 37.509-7.396 112.924-60.833 144.706-79.682-12.288 38.438-78.26 119.353-112.299 139.7 33.375-3.944 92.786 5.613 122.292-7.509-22.092 33.015-77.596 49.133-109.833 72.325z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "twitter" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 34, + "id": 31, + "prevSize": 24, + "code": 58913, + "name": "twitter", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 31 + }, + { + "icon": { + "paths": [ + "M770.37-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM382.028 837.385c-11.169 5.329-34.076 3.375-54.537 3.375h-114.65c-35.631 0-68.191 1.517-75.7-23.381-6.106-20.271-1.119-64.645-1.119-89.050v-180.319c0-42.856-9.273-100.58 23.362-110.213 11.548-3.432 31.744-1.1 46.763-1.1h47.863c44.297 0 91.913-7.111 109.682 15.113l34.114 364.961c-2.484 8.875-7.377 16.631-15.777 20.613zM857.335 628.11c34.816 21.656 18.413 91.231-14.488 102.419 19.475 16.194 13.103 52.527 0 67.906-45.796 53.779-181.305 37.831-284.937 37.831-23.438 0-48.109 2.788-64.55 0-15.246-2.617-26.662-11.264-38.381-19.589l-35.252-377.268c6.163-10.714 11.89-21.751 14.658-26.131 21.883-34.683 44.582-68.248 73.444-93.506 14.829-12.971 32.635-20.271 51.219-32.275 23.324-15.095 56.699-58.615 60.113-93.487 1.384-14.526-2.882-39.481 3.319-52.357 5.803-11.947 29.715-27.572 50.119-21.125 23.59 7.452 42.174 45.435 44.544 75.719 2.332 30.549-3.11 62.995-15.607 83.437-13.464 22.035-28.236 30.587-36.731 47.863-7.49 15.208-9.956 28.046-12.25 52.319 79.929 4.855 201.216-13.388 233.775 41.188 17.446 29.26-6.22 85.257-30.075 96.825 43.899 14.715 42.344 93.62 1.081 110.232zM258.181 686.478c-26.188 0-47.332 21.618-47.332 48.223 0 26.491 21.144 47.919 47.332 47.919 26.036 0 47.351-21.428 47.351-47.919-0-26.605-21.314-48.223-47.351-48.223z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "thumbs-up" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 35, + "id": 32, + "prevSize": 24, + "code": 58914, + "name": "thumbs-up", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 32 + }, + { + "icon": { + "paths": [ + "M248.889 1024h521.481c138.202 0 251.259-113.076 251.259-251.259v-521.481c0-138.202-113.057-251.278-251.259-251.278h-521.481c-138.183 0-251.259 113.076-251.259 251.278v521.481c0 138.183 113.076 251.259 251.259 251.259zM637.231 186.596c11.169-5.329 34.076-3.375 54.537-3.375h114.65c35.631 0 68.191-1.517 75.7 23.381 6.106 20.271 1.119 64.645 1.119 89.050v180.319c0 42.856 9.254 100.58-23.362 110.213-11.548 3.432-31.744 1.1-46.763 1.1h-47.863c-44.297 0-91.932 7.092-109.682-15.113l-34.114-364.961c2.484-8.875 7.358-16.631 15.777-20.613zM161.925 395.871c-34.816-21.656-18.413-91.231 14.488-102.419-19.475-16.194-13.103-52.527 0-67.906 45.796-53.779 181.305-37.831 284.937-37.831 23.438 0 48.109-2.788 64.55 0 15.246 2.617 26.643 11.264 38.381 19.589l35.252 377.268c-6.163 10.714-11.89 21.751-14.658 26.131-21.883 34.683-44.582 68.248-73.444 93.506-14.829 12.971-32.635 20.271-51.219 32.275-23.324 15.095-56.699 58.615-60.113 93.487-1.384 14.526 2.882 39.481-3.319 52.357-5.803 11.947-29.715 27.572-50.119 21.125-23.59-7.452-42.174-45.435-44.544-75.719-2.332-30.549 3.11-62.995 15.607-83.437 13.464-22.035 28.236-30.587 36.731-47.863 7.49-15.208 9.956-28.046 12.25-52.319-79.929-4.855-201.216 13.388-233.775-41.188-17.446-29.26 6.22-85.257 30.075-96.825-43.899-14.715-42.344-93.62-1.081-110.232zM761.079 512.815c26.188 0 47.332-21.618 47.332-48.223 0-26.491-21.144-47.919-47.332-47.919-26.036 0-47.351 21.428-47.351 47.919 0 26.605 21.314 48.223 47.351 48.223z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "thumbs-down" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 36, + "id": 33, + "prevSize": 24, + "code": 58915, + "name": "thumbs-down", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 33 + }, + { + "icon": { + "paths": [ + "M630.139 539.212h124.511l-61.668-234.837-62.843 234.837zM231.993 596.082h64.076l-31.611-147.399-32.465 147.399zM772.741-0.019h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM344.955 763.354l-27.989-95.782h-106.97l-29.639 95.782h-88.235l135.604-422.798h72.306l131.736 422.798h-86.812zM820.452 764.321l-37.66-128.872h-182.234l-39.898 128.872h-99.631l182.5-568.984h97.318l177.304 568.984h-97.697z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "text-resize" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 37, + "id": 34, + "prevSize": 24, + "code": 58916, + "name": "text-resize", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 34 + }, + { + "icon": { + "paths": [ + "M593.427 476.824l128.91-93.867h-152.292l-58.482-140.383-46.895 140.383h-152.102l128.74 93.867-58.615 163.859 128.872-105.396 128.683 105.396-46.82-163.859zM479.327 865.754c-12.535-1.271-24.86-3.167-36.997-5.613 7.073-44.146-1.764-89.695-16.498-124.511-15.607-35.157-33.849-51.333-57.192-54.177-18.489 38.153-29.582 81.408-16.308 120.282 5.158 16.137 14.45 29.449 26.207 39.671-41.719-16.194-79.796-39.519-113.076-68.267 22.812-30.208 36.978-67.186 41.908-100.902 4.741-36.807-2.2-61.402-19.191-78.412-30.417 20.992-57.116 51.086-64.455 90.491-3.527 17.048-2.503 33.773 1.801 49.019-22.206-25.638-41.131-54.101-56.092-84.935 28.236-13.843 51.731-39.177 66.238-67.584 14.791-30.398 16.251-57.742 7.945-83.437-29.961 2.996-59.62 17.105-77.122 48.811-10.638 18.413-14.962 40.183-13.824 61.478-14.127-40.258-22.168-83.399-22.168-128.493 0-6.618 0.531-13.103 0.853-19.646 25.998 3.508 52.698-5.803 74.183-24.026 22.528-20.063 34.456-46.061 39.31-75.34-23.192-13.179-50.991-15.455-76.724 4.134-12.25 8.913-22.225 21.921-29.544 36.978 8.325-40.865 22.831-79.493 42.894-114.593 18.148 16.005 42.837 20.499 69.044 13.767 28.027-7.851 52.11-26.719 74.088-50.574-11.093-21.732-33.052-36.257-64.645-30.91-16.194 2.295-32.465 9.956-47.028 21.371 24.595-31.479 53.893-58.994 86.907-81.617 9.69 17.92 30.644 27.553 60.226 27.667 31.953-0.474 68.191-11.074 107.501-24.595-0.076-19.646-17.692-36.409-54.632-39.974-17.863-2.105-37.755-0.171-57.325 5.101 26.889-12.497 55.315-22.281 85.125-28.388 8.875-1.839 14.583-10.468 12.781-19.342-1.839-8.875-10.468-14.583-19.342-12.781-24.595 5.044-48.375 12.269-71.206 21.39 9.406-6.751 18.508-13.634 26.984-20.651 30.758-24.538 45.189-46.459 35.821-64.512-55.334 7.433-104.638 31.004-130.522 60.738-22.964 27.288-24.102 51.693-13.786 68.267-30.929 21.182-58.918 46.251-83.153 74.695 5.385-11.7 10.297-23.514 13.995-35.518 11.34-35.233 10.031-64-6.903-81.56-39.045 24.424-68.551 64.417-76.079 103.424-6.542 36.466 5.329 62.445 24.329 76.667-20.385 35.404-35.385 74.202-44.809 115.124-1.517-14.962-3.982-29.772-8.344-44.070-10.543-35.631-29.355-60.113-55.031-66.844-19.608 41.169-24.311 91.212-10.012 128.133 13.426 33.849 37.945 49 63.431 50.953-0.55 8.799-1.176 17.598-1.176 26.529 0 40.638 5.803 79.91 16.536 117.077-7.396-9.766-15.436-19.058-25.012-27.117-27.117-23.381-58.311-32.939-87.704-23.040-0.076 47.18 17.958 93.431 48.981 115.845 29.62 20.992 62.123 16.915 89.41 0.607 21.713 44.772 51.124 85.011 86.509 119.239-20.366-15.986-44.525-26.377-72.761-29.696-37.092-4.722-73.652 5.215-101.205 31.991 17.427 43.71 54.367 75.985 95.706 77.748 42.060 1.422 76.023-26.169 97.811-61.762-1.062-1.176-2.2-2.219-3.3-3.356 44.734 38.969 97.564 68.93 155.913 86.319-25.998 1.062-51.75 7.964-77.483 21.732-38.628 20.442-69.006 53.039-81.806 94.265 40.031 26.377 95.516 30.53 138.505 5.139 41.434-24.841 59.525-68.077 61.497-111.332 12.079 2.332 24.311 4.248 36.75 5.499 0.55 0.057 1.1 0.076 1.65 0.076 8.306 0 15.436-6.258 16.289-14.715 0.872-8.988-5.689-17.048-14.677-17.939zM934.817 569.154c-9.595 8.078-17.673 17.37-25.050 27.174 10.752-37.186 16.536-76.478 16.555-117.134 0-8.951-0.626-17.749-1.176-26.548 25.505-1.953 50.024-17.086 63.469-50.953 14.298-36.921 9.595-86.945-10.012-128.133-25.676 6.732-44.506 31.213-55.031 66.844-4.38 14.317-6.827 29.165-8.306 44.127-9.425-40.96-24.443-79.777-44.828-115.2 19.001-14.222 30.891-40.201 24.348-76.686-7.509-39.007-37.035-79-76.079-103.424-16.953 17.56-18.242 46.327-6.903 81.56 3.679 12.023 8.609 23.874 14.014 35.593-24.235-28.482-52.243-53.589-83.191-74.771 10.335-16.574 9.178-40.979-13.786-68.267-25.884-29.734-75.188-53.305-130.522-60.738-9.368 18.053 5.063 39.974 35.821 64.512 8.495 7.035 17.636 13.919 27.060 20.708-22.869-9.121-46.668-16.384-71.301-21.409-8.875-1.839-17.541 3.906-19.361 12.781-1.801 8.837 3.925 17.503 12.8 19.323 29.81 6.106 58.216 15.872 85.125 28.388-19.57-5.272-39.462-7.187-57.325-5.101-36.94 3.565-54.556 20.328-54.632 39.974 39.31 13.502 75.548 24.102 107.501 24.595 29.582-0.114 50.536-9.747 60.226-27.667 32.958 22.604 62.236 50.1 86.831 81.541-14.564-11.378-30.815-19.001-46.971-21.314-31.592-5.329-53.551 9.197-64.645 30.91 21.978 23.874 46.080 42.724 74.088 50.574 26.188 6.732 50.897 2.238 69.025-13.748 20.044 35.081 34.532 73.652 42.856 114.479-7.32-15.019-17.256-27.989-29.487-36.883-25.714-19.589-53.532-17.313-76.724-4.134 4.855 29.279 16.801 55.277 39.31 75.34 21.466 18.204 48.166 27.534 74.145 24.045 0.341 6.542 0.872 13.028 0.872 19.646 0 45.056-8.040 88.14-22.13 128.398 1.119-21.276-3.224-43.027-13.824-61.383-17.522-31.706-47.161-45.815-77.122-48.811-8.306 25.695-6.846 53.058 7.945 83.437 14.507 28.407 37.983 53.741 66.2 67.584-14.943 30.796-33.868 59.24-56.055 84.859 4.305-15.208 5.31-31.934 1.801-48.943-7.358-39.405-34.039-69.499-64.455-90.491-16.991 16.991-23.931 41.586-19.191 78.412 4.93 33.716 19.115 70.694 41.889 100.883-33.28 28.748-71.339 52.053-113.038 68.267 11.757-10.221 21.011-23.514 26.188-39.652 13.255-38.874 2.162-82.129-16.308-120.282-23.324 2.844-41.567 19.039-57.192 54.177-14.715 34.816-23.571 80.365-16.479 124.511-12.174 2.427-24.5 4.343-37.035 5.613-9.026 0.91-15.55 8.951-14.639 17.977 0.872 8.439 8.021 14.734 16.327 14.734 0.531 0 1.1-0.038 1.65-0.095v-0.038c12.421-1.252 24.671-3.167 36.75-5.499 1.972 43.255 20.063 86.49 61.478 111.332 42.989 25.391 98.456 21.22 138.505-5.139-12.819-41.225-43.179-73.823-81.806-94.265-25.733-13.786-51.503-20.689-77.521-21.732 58.425-17.427 111.313-47.407 156.084-86.471-1.157 1.176-2.332 2.276-3.451 3.508 21.788 35.593 55.751 63.185 97.811 61.762 41.339-1.764 78.279-34.039 95.706-77.748-27.553-26.757-64.114-36.712-101.205-31.991-28.274 3.356-52.489 13.748-72.875 29.772 35.404-34.247 64.872-74.505 86.585-119.334 27.288 16.289 59.771 20.404 89.429-0.588 31.023-22.433 49.057-68.665 48.981-115.845-29.412-9.88-60.606-0.322-87.723 23.078z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "success-stories" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 38, + "id": 35, + "prevSize": 24, + "code": 58917, + "name": "success-stories", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 35 + }, + { + "icon": { + "paths": [ + "M124.113 449.574h132.741v385.574h-132.741v-385.574z", + "M250.539 1023.204h521.481c93.127 0 174.668-51.465 218.055-127.241h-957.611c43.387 75.776 124.947 127.241 218.074 127.241z", + "M336.915 196.741h132.741v638.426h-132.741v-638.426z", + "M549.736 323.148h132.741v512h-132.741v-512z", + "M762.539 1.574h132.741v833.574h-132.741v-833.574z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "statistics" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 39, + "id": 36, + "prevSize": 24, + "code": 58918, + "name": "statistics", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 36 + }, + { + "icon": { + "paths": [ + "M772.741-2.37h-521.481c-138.202 0-251.259 113.076-251.259 251.259v521.481c0 138.202 113.057 251.278 251.259 251.278h521.481c138.183 0 251.259-113.076 251.259-251.278v-521.481c0-138.183-113.076-251.259-251.259-251.259zM376.055 250.842l269.065 175.066-36.693 57.989-273.484-168.107 41.112-64.948zM295.291 404.082l307.352 92.748-18.982 65.953-309.627-84.764 21.257-73.937zM260.437 551.064l319.052 35.821-6.789 68.248-319.848-27.553 7.585-76.516zM252.587 680.562h321.024v76.895h-321.024v-76.895zM698.804 890.558h-570.728v-351.118h65.517v290.873h441.799v-290.873h63.412v351.118zM653.047 419.176l-178.745-266.676 64.398-41.927 171.823 271.151-57.477 37.452zM717.577 378.709l-23.742-320.133 76.743-4.665 15.493 320.626-68.494 4.172z" + ], + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "stack-overflow" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 40, + "id": 37, + "prevSize": 24, + "code": 58919, + "name": "stack-overflow", + "ligatures": "" + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 37 + }, + { + "icon": { + "paths": [ + "M251.262-2.371c-138.202 0-251.258 113.076-251.258 251.258v521.48c0 138.202 113.058 251.277 251.258 251.277h521.477c138.182 0 251.262-113.076 251.262-251.277v-521.48c0-138.182-113.078-251.258-251.262-251.258h-521.477zM502.934 122h0.969c129.617 0 185.568 7.873 200.336 10.035 87.534 12.798 161.375 78.841 172.773 162.648v0.004c6.202 62.253 0.829 163.576 0.789 180.203 0 4.892-0.717 49.558-1.004 54.273-7.671 119.756-83.16 167.050-162.484 182.117-1.076 0.319-2.331 0.529-3.586 0.777-50.291 9.714-104.166 12.305-155.281 13.723-12.224 0.319-24.41 0.316-36.633 0.316-50.823 0.013-101.466-5.938-150.871-17.727-0.262-0.070-0.537-0.080-0.801-0.020-0.264 0.057-0.513 0.175-0.723 0.344s-0.375 0.385-0.484 0.629c-0.105 0.245-0.155 0.514-0.145 0.781 1.397 15.91 4.892 31.569 10.395 46.582 6.847 17.372 30.757 59.098 119.652 59.098 51.655 0.094 103.141-5.857 153.383-17.727 0.255-0.052 0.517-0.060 0.773 0 0.255 0.057 0.497 0.168 0.703 0.328s0.371 0.362 0.488 0.594c0.112 0.232 0.18 0.487 0.184 0.746v58.777c-0.009 0.277-0.081 0.552-0.211 0.797s-0.314 0.456-0.539 0.621c-16.417 11.77-38.751 18.474-57.785 24.465-8.435 2.623-16.968 4.925-25.594 6.91-78.419 17.666-160.26 13.396-236.363-12.336-71.081-24.675-143.632-85.156-161.555-157.832-9.571-39.35-16.314-79.317-20.18-119.609-5.592-60.658-6.059-121.457-8.461-182.363-1.685-42.471-0.713-88.773 8.355-130.535 18.855-84.799 96.563-144.142 181.66-156.586 14.768-2.163 42.587-10.035 172.238-10.035zM398.371 246.082c-36.885 0-66.6 12.831-89.254 37.824-21.961 25.053-32.941 58.853-32.941 101.395v208.203h83.34v-202.070c0.036-42.542 18.139-64.238 54.379-64.238 40.075 0 60.184 25.665 60.184 76.359v110.609h82.91v-110.609c0-50.695 20.074-76.359 60.148-76.359 36.455 0 54.375 21.696 54.375 64.238v202.070h83.414l0.070-208.203c0-42.566-10.979-76.366-32.941-101.395-22.726-24.993-52.44-37.824-89.289-37.824-42.62 0-74.884 16.237-96.391 48.676l-20.789 34.457-20.754-34.457c-21.507-32.439-53.77-48.676-96.461-48.676z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "grid": 0, + "tags": [ + "mastodon" + ] + }, + "attrs": [ + {} + ], + "properties": { + "order": 48, + "id": 38, + "name": "mastodon", + "prevSize": 24, + "code": 59648 + }, + "setIdx": 1, + "setId": 1, + "iconIdx": 38 + } + ], + "height": 1024, + "metadata": { + "name": "Pythonicon" + }, + "preferences": { + "showGlyphs": true, + "showQuickUse": true, + "showQuickUse2": true, + "showSVGs": true, + "fontPref": { + "prefix": "icon-", + "metadata": { + "fontFamily": "Pythonicon", + "majorVersion": 1, + "minorVersion": 0 + }, + "metrics": { + "emSize": 1024, + "baseline": 6.25, + "whitespace": 50 + }, + "embed": false, + "resetPoint": 58880 + }, + "imagePref": { + "prefix": "icon-", + "png": true, + "useClassSelector": true, + "color": 0, + "bgColor": 16777215, + "classSelector": ".icon" + }, + "historySize": 50, + "showCodes": true, + "gridSize": 16 + } +} \ No newline at end of file diff --git a/static/fonts/Pythonicon.svg b/static/fonts/Pythonicon.svg old mode 100755 new mode 100644 index 513b029b5..a7441c98a --- a/static/fonts/Pythonicon.svg +++ b/static/fonts/Pythonicon.svg @@ -3,48 +3,48 @@ Generated by IcoMoon - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/static/fonts/Pythonicon.ttf b/static/fonts/Pythonicon.ttf old mode 100755 new mode 100644 index 9d69d57a3ef6c89cfb368c4f053508dce434fde2..5c57bd93dec5139cb912d24a5bdc39cff829f1c2 GIT binary patch literal 12452 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 HTmAkYcoVmx literal 13840 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 literal 13916 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 + + + + IcoMoon Demo + + + + + +
    +

    Font Name: Pythonicon (Glyphs: 40)

    +
    +
    +

    Grid Size: 16

    +
    +
    + + icon-bullhorn +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    +

    Grid Size: Unknown

    +
    +
    + + icon-python-alt +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-pypi +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-news +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-moderate +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-mercurial +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-jobs +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-help +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-download +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-documentation +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-community +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-code +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-close +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-calendar +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-beginner +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-advanced +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-sitemap +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-search +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-search-alt +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-python +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-github +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-get-started +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-feed +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-facebook +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-email +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-arrow-up +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-arrow-right +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-arrow-left +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-arrow-down +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-freenode +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-alert +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-versions +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-twitter +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-thumbs-up +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-thumbs-down +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-text-resize +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-success-stories +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-statistics +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-stack-overflow +
    +
    + + +
    +
    + liga: + +
    +
    +
    +
    + + icon-mastodon +
    +
    + + +
    +
    + liga: + +
    +
    +
    + + +
    +

    Font Test Drive

    + + +
      +
    +
    + +
    +

    Generated by IcoMoon

    +
    + + + + diff --git a/static/fonts/demo/demo.css b/static/fonts/demo/demo.css new file mode 100644 index 000000000..932837ba3 --- /dev/null +++ b/static/fonts/demo/demo.css @@ -0,0 +1,155 @@ +body { + padding: 0; + margin: 0; + font-family: sans-serif; + font-size: 1em; + line-height: 1.5; + color: #555; + background: #fff; +} +h1 { + font-size: 1.5em; + font-weight: normal; +} +small { + font-size: .66666667em; +} +a { + color: #e74c3c; + text-decoration: none; +} +a:hover, a:focus { + box-shadow: 0 1px #e74c3c; +} +.bshadow0, input { + box-shadow: inset 0 -2px #e7e7e7; +} +input:hover { + box-shadow: inset 0 -2px #ccc; +} +input, fieldset { + font-family: sans-serif; + font-size: 1em; + margin: 0; + padding: 0; + border: 0; +} +input { + color: inherit; + line-height: 1.5; + height: 1.5em; + padding: .25em 0; +} +input:focus { + outline: none; + box-shadow: inset 0 -2px #449fdb; +} +.glyph { + font-size: 16px; + width: 15em; + padding-bottom: 1em; + margin-right: 4em; + margin-bottom: 1em; + float: left; + overflow: hidden; +} +.liga { + width: 80%; + width: calc(100% - 2.5em); +} +.talign-right { + text-align: right; +} +.talign-center { + text-align: center; +} +.bgc1 { + background: #f1f1f1; +} +.fgc1 { + color: #999; +} +.fgc0 { + color: #000; +} +p { + margin-top: 1em; + margin-bottom: 1em; +} +.mvm { + margin-top: .75em; + margin-bottom: .75em; +} +.mtn { + margin-top: 0; +} +.mtl, .mal { + margin-top: 1.5em; +} +.mbl, .mal { + margin-bottom: 1.5em; +} +.mal, .mhl { + margin-left: 1.5em; + margin-right: 1.5em; +} +.mhmm { + margin-left: 1em; + margin-right: 1em; +} +.mls { + margin-left: .25em; +} +.ptl { + padding-top: 1.5em; +} +.pbs, .pvs { + padding-bottom: .25em; +} +.pvs, .pts { + padding-top: .25em; +} +.unit { + float: left; +} +.unitRight { + float: right; +} +.size1of2 { + width: 50%; +} +.size1of1 { + width: 100%; +} +.clearfix:before, .clearfix:after { + content: " "; + display: table; +} +.clearfix:after { + clear: both; +} +.hidden-true { + display: none; +} +.textbox0 { + width: 3em; + background: #f1f1f1; + padding: .25em .5em; + line-height: 1.5; + height: 1.5em; +} +#testDrive { + display: block; + padding-top: 24px; + line-height: 1.5; +} +.fs0 { + font-size: 16px; +} +.fs1 { + font-size: 32px; +} +.fs2 { + font-size: 24px; +} + diff --git a/static/fonts/demo/demo.js b/static/fonts/demo/demo.js new file mode 100644 index 000000000..6f45f1c40 --- /dev/null +++ b/static/fonts/demo/demo.js @@ -0,0 +1,30 @@ +if (!('boxShadow' in document.body.style)) { + document.body.setAttribute('class', 'noBoxShadow'); +} + +document.body.addEventListener("click", function(e) { + var target = e.target; + if (target.tagName === "INPUT" && + target.getAttribute('class').indexOf('liga') === -1) { + target.select(); + } +}); + +(function() { + var fontSize = document.getElementById('fontSize'), + testDrive = document.getElementById('testDrive'), + testText = document.getElementById('testText'); + function updateTest() { + testDrive.innerHTML = testText.value || String.fromCharCode(160); + if (window.icomoonLiga) { + window.icomoonLiga(testDrive); + } + } + function updateSize() { + testDrive.style.fontSize = fontSize.value + 'px'; + } + fontSize.addEventListener('change', updateSize, false); + testText.addEventListener('input', updateTest, false); + testText.addEventListener('change', updateTest, false); + updateSize(); +}()); diff --git a/static/fonts/index.html b/static/fonts/index.html deleted file mode 100644 index 703c351ee..000000000 --- a/static/fonts/index.html +++ /dev/null @@ -1,410 +0,0 @@ - - - -Your Font/Glyphs - - - - - -
    -
    -
    -

    Your font contains the following glyphs

    -

    The generated SVG font can be imported back to IcoMoon for modification.

    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    -

    Class Names

    -
    - - -  icon-alert - - - -  icon-arrow-down - - - -  icon-arrow-left - - - -  icon-arrow-right - - - -  icon-arrow-up - - - -  icon-calendar - - - -  icon-close - - - -  icon-code - - - -  icon-documentation - - - -  icon-email - - - -  icon-facebook - - - -  icon-feed - - - -  icon-freenode - - - -  icon-get-started - - - -  icon-github - - - -  icon-help - - - -  icon-pypi - - - -  icon-python - - - -  icon-python-alt - - - -  icon-search - - - -  icon-sitemap - - - -  icon-stack-overflow - - - -  icon-statistics - - - -  icon-success-stories - - - -  icon-text-resize - - - -  icon-thumbs-down - - - -  icon-thumbs-up - - - -  icon-twitter - - - -  icon-versions - - - -  icon-community - - - -  icon-download - - - -  icon-news - - - -  icon-jobs - - - -  icon-beginner - - - -  icon-moderate - - - -  icon-advanced - - - -  icon-search-alt - -
    - -
    - - - diff --git a/static/fonts/style.css b/static/fonts/style.css index 2f45ac8b0..dd31e10f7 100644 --- a/static/fonts/style.css +++ b/static/fonts/style.css @@ -4,148 +4,144 @@ } @font-face { font-family: 'Pythonicon'; - src: url(data:application/x-font-woff;charset=utf-8;base64,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) format('woff'), - url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'); + src: url(data:application/x-font-woff;charset=utf-8;base64,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) format('woff'), + url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'); font-weight: normal; font-style: normal; } -/* Use the following CSS code if you want to use data attributes for inserting your icons */ -[data-icon]:before { - font-family: 'Pythonicon'; - content: attr(data-icon); - speak: none; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'Pythonicon' !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } -/* Use the following CSS code if you want to have a class per icon */ -/* -Instead of a list of all class selectors, -you can use the generic selector below, but it's slower: -[class*="icon-"]:before { -*/ -.icon-alert:before, .icon-arrow-down:before, .icon-arrow-left:before, .icon-arrow-right:before, .icon-arrow-up:before, .icon-calendar:before, .icon-close:before, .icon-code:before, .icon-documentation:before, .icon-email:before, .icon-facebook:before, .icon-feed:before, .icon-freenode:before, .icon-get-started:before, .icon-github:before, .icon-help:before, .icon-pypi:before, .icon-python:before, .icon-python-alt:before, .icon-search:before, .icon-sitemap:before, .icon-stack-overflow:before, .icon-statistics:before, .icon-success-stories:before, .icon-text-resize:before, .icon-thumbs-down:before, .icon-thumbs-up:before, .icon-twitter:before, .icon-versions:before, .icon-community:before, .icon-download:before, .icon-news:before, .icon-jobs:before, .icon-beginner:before, .icon-moderate:before, .icon-advanced:before, .icon-search-alt:before { - font-family: 'Pythonicon'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; +.icon-bullhorn:before { + content: "\e600"; } -.icon-alert:before { - content: "\e000"; +.icon-python-alt:before { + content: "\e601"; } -.icon-arrow-down:before { - content: "\e001"; +.icon-pypi:before { + content: "\e602"; } -.icon-arrow-left:before { - content: "\e002"; +.icon-news:before { + content: "\e603"; } -.icon-arrow-right:before { - content: "\e003"; +.icon-moderate:before { + content: "\e604"; } -.icon-arrow-up:before { - content: "\e004"; +.icon-mercurial:before { + content: "\e605"; } -.icon-calendar:before { - content: "\e005"; +.icon-jobs:before { + content: "\e606"; } -.icon-close:before { - content: "\e006"; +.icon-help:before { + content: "\3f"; } -.icon-code:before { - content: "\e007"; +.icon-download:before { + content: "\e609"; } .icon-documentation:before { - content: "\e008"; + content: "\e60a"; } -.icon-email:before { - content: "\e00a"; +.icon-community:before { + content: "\e60b"; } -.icon-facebook:before { - content: "\e00b"; +.icon-code:before { + content: "\e60c"; } -.icon-feed:before { - content: "\e00c"; +.icon-close:before { + content: "\58"; } -.icon-freenode:before { - content: "\e00d"; +.icon-calendar:before { + content: "\e60e"; } -.icon-get-started:before { - content: "\e00e"; +.icon-beginner:before { + content: "\e60f"; } -.icon-github:before { - content: "\e00f"; +.icon-advanced:before { + content: "\e610"; } -.icon-help:before { - content: "\e011"; +.icon-sitemap:before { + content: "\e611"; } -.icon-pypi:before { - content: "\e014"; +.icon-search:before { + content: "\e612"; +} +.icon-search-alt:before { + content: "\e613"; } .icon-python:before { - content: "\e015"; + content: "\e614"; } -.icon-python-alt:before { - content: "\e016"; +.icon-github:before { + content: "\e615"; } -.icon-search:before { - content: "\e017"; +.icon-get-started:before { + content: "\e616"; } -.icon-sitemap:before { - content: "\e018"; +.icon-feed:before { + content: "\e617"; } -.icon-stack-overflow:before { - content: "\e019"; +.icon-facebook:before { + content: "\e618"; } -.icon-statistics:before { - content: "\e01a"; +.icon-email:before { + content: "\e619"; } -.icon-success-stories:before { - content: "\e01b"; +.icon-arrow-up:before { + content: "\e61a"; } -.icon-text-resize:before { - content: "\e01c"; +.icon-arrow-right:before { + content: "\e61b"; } -.icon-thumbs-down:before { - content: "\e01d"; +.icon-arrow-left:before { + content: "\e61c"; } -.icon-thumbs-up:before { - content: "\e01e"; +.icon-arrow-down:before { + content: "\e61d"; } -.icon-twitter:before { - content: "\e01f"; +.icon-freenode:before { + content: "\e61e"; +} +.icon-alert:before { + content: "\e61f"; } .icon-versions:before { - content: "\e020"; + content: "\e620"; } -.icon-community:before { - content: "\e021"; +.icon-twitter:before { + content: "\e621"; } -.icon-download:before { - content: "\e009"; +.icon-thumbs-up:before { + content: "\e622"; } -.icon-news:before { - content: "\e012"; +.icon-thumbs-down:before { + content: "\e623"; } -.icon-jobs:before { - content: "\e013"; +.icon-text-resize:before { + content: "\e624"; } -.icon-beginner:before { - content: "\e022"; +.icon-success-stories:before { + content: "\e625"; } -.icon-moderate:before { - content: "\e023"; +.icon-statistics:before { + content: "\e626"; } -.icon-advanced:before { - content: "\e024"; +.icon-stack-overflow:before { + content: "\e627"; } -.icon-search-alt:before { - content: "\e025"; +.icon-mastodon:before { + content: "\e900"; } diff --git a/static/sass/_fonts.scss b/static/sass/_fonts.scss index 6154dcef1..a12d69881 100644 --- a/static/sass/_fonts.scss +++ b/static/sass/_fonts.scss @@ -5,134 +5,137 @@ */ -@font-face { + @font-face { font-family: 'Pythonicon'; - src: url('../fonts/Pythonicon.eot'); + src:url('../fonts/Pythonicon.eot'); } @font-face { font-family: 'Pythonicon'; - src: url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'), - url(data:application/font-woff;charset=utf-8;base64,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) format('woff'); + src: url(data:application/x-font-woff;charset=utf-8;base64,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) format('woff'), + url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'); font-weight: normal; font-style: normal; } - -.icon-megaphone:before { - content: "\e600"; + +.icon-bullhorn:before { + content: "\e600"; } .icon-python-alt:before { - content: "\e601"; + content: "\e601"; } .icon-pypi:before { - content: "\e602"; + content: "\e602"; } .icon-news:before { - content: "\e603"; + content: "\e603"; } .icon-moderate:before { - content: "\e604"; + content: "\e604"; } .icon-mercurial:before { - content: "\e605"; + content: "\e605"; } .icon-jobs:before { - content: "\e606"; + content: "\e606"; } .icon-help:before { - content: "\3f"; + content: "\3f"; } .icon-download:before { - content: "\e609"; + content: "\e609"; } .icon-documentation:before { - content: "\e60a"; + content: "\e60a"; } .icon-community:before { - content: "\e60b"; + content: "\e60b"; } .icon-code:before { - content: "\e60c"; + content: "\e60c"; } .icon-close:before { - content: "\58"; + content: "\58"; } .icon-calendar:before { - content: "\e60e"; + content: "\e60e"; } .icon-beginner:before { - content: "\e60f"; + content: "\e60f"; } .icon-advanced:before { - content: "\e610"; + content: "\e610"; } .icon-sitemap:before { - content: "\e611"; + content: "\e611"; } .icon-search-alt:before { - content: "\e612"; + content: "\e612"; } .icon-search:before { - content: "\e613"; + content: "\e613"; } .icon-python:before { - content: "\e614"; + content: "\e614"; } .icon-github:before { - content: "\e615"; + content: "\e615"; } .icon-get-started:before { - content: "\e616"; + content: "\e616"; } .icon-feed:before { - content: "\e617"; + content: "\e617"; } .icon-facebook:before { - content: "\e618"; + content: "\e618"; } .icon-email:before { - content: "\e619"; + content: "\e619"; } .icon-arrow-up:before { - content: "\e61a"; + content: "\e61a"; } .icon-arrow-right:before { - content: "\e61b"; + content: "\e61b"; } .icon-arrow-left:before { - content: "\e61c"; + content: "\e61c"; } .icon-arrow-down:before { - content: "\e61d"; + content: "\e61d"; } .icon-freenode:before { - content: "\e61e"; + content: "\e61e"; } .icon-alert:before { - content: "\e61f"; + content: "\e61f"; } .icon-versions:before { - content: "\e620"; + content: "\e620"; } .icon-twitter:before { - content: "\e621"; + content: "\e621"; } .icon-thumbs-up:before { - content: "\e622"; + content: "\e622"; } .icon-thumbs-down:before { - content: "\e623"; + content: "\e623"; } .icon-text-resize:before { - content: "\e624"; + content: "\e624"; } .icon-success-stories:before { - content: "\e625"; + content: "\e625"; } .icon-statistics:before { - content: "\e626"; + content: "\e626"; } .icon-stack-overflow:before { - content: "\e627"; + content: "\e627"; +} +.icon-mastodon:before { + content: "\e900"; } @@ -143,7 +146,7 @@ */ /*modernizr*/ .no-fontface, .no-svg, .no-generatedcontent { - .icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow { + .icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow, .icon-mastodon { &:before { display: none; @@ -159,7 +162,7 @@ /* Show in IE8: supports FontFace (eot) but not SVG. */ .ie8 { - .icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow { + .icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow, .icon-mastodon { &:before { display: inline; diff --git a/static/sass/style.css b/static/sass/style.css index 472737c2a..ad49c77b4 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -3391,7 +3391,7 @@ span.highlighted { */ /* ! ===== ICONS ===== */ /* Look inside _fonts.scss for most of the code. We declare this here so we can adjust as needed for specific elements. */ -.icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .errorlist:before, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow { +.icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .errorlist:before, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow, .icon-mastodon { font-family: 'Pythonicon'; speak: none; font-style: normal; @@ -3406,7 +3406,7 @@ span.highlighted { /* Hide a unicode fallback character when we supply it by default. * In fonts.scss, we hide the icon and show the fallback when other conditions are not met */ } - .icon-megaphone span, .icon-python-alt span, .icon-pypi span, .icon-news span, .icon-moderate span, .icon-mercurial span, .icon-jobs span, .icon-help span, .icon-download span, .icon-documentation span, .icon-community span, .icon-code span, .icon-close span, .icon-calendar span, .icon-beginner span, .icon-advanced span, .icon-sitemap span, .icon-search span, .icon-search-alt span, .icon-python span, .icon-github span, .icon-get-started span, .icon-feed span, .icon-facebook span, .icon-email span, .icon-arrow-up span, .icon-arrow-right span, .icon-arrow-left span, .icon-arrow-down span, .errorlist:before span, .icon-freenode span, .icon-alert span, .icon-versions span, .icon-twitter span, .icon-thumbs-up span, .icon-thumbs-down span, .icon-text-resize span, .icon-success-stories span, .icon-statistics span, .icon-stack-overflow span { + .icon-megaphone span, .icon-python-alt span, .icon-pypi span, .icon-news span, .icon-moderate span, .icon-mercurial span, .icon-jobs span, .icon-help span, .icon-download span, .icon-documentation span, .icon-community span, .icon-code span, .icon-close span, .icon-calendar span, .icon-beginner span, .icon-advanced span, .icon-sitemap span, .icon-search span, .icon-search-alt span, .icon-python span, .icon-github span, .icon-get-started span, .icon-feed span, .icon-facebook span, .icon-email span, .icon-arrow-up span, .icon-arrow-right span, .icon-arrow-left span, .icon-arrow-down span, .errorlist:before span, .icon-freenode span, .icon-alert span, .icon-versions span, .icon-twitter span, .icon-thumbs-up span, .icon-thumbs-down span, .icon-text-resize span, .icon-success-stories span, .icon-statistics span, .icon-stack-overflow span, .icon-mastodon span { display: none; } /* Keep this at the bottom since it will create a huge set of data */ @@ -3415,130 +3415,138 @@ span.highlighted { * Be sure to upgrade to at least 0.12.1 to have this work properly. * in Terminal, gem install compass --version '= 0.12.1' */ + @font-face { + font-family: 'Pythonicon'; + src:url('../fonts/Pythonicon.eot'); +} @font-face { - font-family: 'Pythonicon'; - src: url("../fonts/Pythonicon.eot"); } -@font-face { - font-family: 'Pythonicon'; - src: url(data:application/x-font-ttf;charset=utf-8;base64,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) format("truetype"), url(data:application/font-woff;charset=utf-8;base64,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) format("woff"); - font-weight: normal; - font-style: normal; } -.icon-megaphone:before { - content: "\e600"; } - -.icon-python-alt:before { - content: "\e601"; } - -.icon-pypi:before { - content: "\e602"; } - -.icon-news:before { - content: "\e603"; } - -.icon-moderate:before { - content: "\e604"; } - -.icon-mercurial:before { - content: "\e605"; } - -.icon-jobs:before { - content: "\e606"; } - -.icon-help:before { - content: "\3f"; } - -.icon-download:before { - content: "\e609"; } - -.icon-documentation:before { - content: "\e60a"; } - -.icon-community:before { - content: "\e60b"; } - -.icon-code:before { - content: "\e60c"; } - -.icon-close:before { - content: "\58"; } - -.icon-calendar:before { - content: "\e60e"; } - -.icon-beginner:before { - content: "\e60f"; } - -.icon-advanced:before { - content: "\e610"; } - -.icon-sitemap:before { - content: "\e611"; } - -.icon-search-alt:before { - content: "\e612"; } - -.icon-search:before { - content: "\e613"; } - -.icon-python:before { - content: "\e614"; } - -.icon-github:before { - content: "\e615"; } - -.icon-get-started:before { - content: "\e616"; } - -.icon-feed:before { - content: "\e617"; } - -.icon-facebook:before { - content: "\e618"; } - -.icon-email:before { - content: "\e619"; } - -.icon-arrow-up:before { - content: "\e61a"; } - -.icon-arrow-right:before { - content: "\e61b"; } - -.icon-arrow-left:before { - content: "\e61c"; } - -.icon-arrow-down:before, .errorlist:before { - content: "\e61d"; } - -.icon-freenode:before { - content: "\e61e"; } - -.icon-alert:before { - content: "\e61f"; } - -.icon-versions:before { - content: "\e620"; } - -.icon-twitter:before { - content: "\e621"; } - -.icon-thumbs-up:before { - content: "\e622"; } - -.icon-thumbs-down:before { - content: "\e623"; } - -.icon-text-resize:before { - content: "\e624"; } - -.icon-success-stories:before { - content: "\e625"; } - -.icon-statistics:before { - content: "\e626"; } + font-family: 'Pythonicon'; + src: url(data:application/x-font-woff;charset=utf-8;base64,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) format('woff'), + url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'); + font-weight: normal; + font-style: normal; +} -.icon-stack-overflow:before { - content: "\e627"; } + .icon-bullhorn:before { + content: "\e600"; + } + .icon-python-alt:before { + content: "\e601"; + } + .icon-pypi:before { + content: "\e602"; + } + .icon-news:before { + content: "\e603"; + } + .icon-moderate:before { + content: "\e604"; + } + .icon-mercurial:before { + content: "\e605"; + } + .icon-jobs:before { + content: "\e606"; + } + .icon-help:before { + content: "\3f"; + } + .icon-download:before { + content: "\e609"; + } + .icon-documentation:before { + content: "\e60a"; + } + .icon-community:before { + content: "\e60b"; + } + .icon-code:before { + content: "\e60c"; + } + .icon-close:before { + content: "\58"; + } + .icon-calendar:before { + content: "\e60e"; + } + .icon-beginner:before { + content: "\e60f"; + } + .icon-advanced:before { + content: "\e610"; + } + .icon-sitemap:before { + content: "\e611"; + } + .icon-search-alt:before { + content: "\e612"; + } + .icon-search:before { + content: "\e613"; + } + .icon-python:before { + content: "\e614"; + } + .icon-github:before { + content: "\e615"; + } + .icon-get-started:before { + content: "\e616"; + } + .icon-feed:before { + content: "\e617"; + } + .icon-facebook:before { + content: "\e618"; + } + .icon-email:before { + content: "\e619"; + } + .icon-arrow-up:before { + content: "\e61a"; + } + .icon-arrow-right:before { + content: "\e61b"; + } + .icon-arrow-left:before { + content: "\e61c"; + } + .icon-arrow-down:before, .errorlist:before { + content: "\e61d"; + } + .icon-freenode:before { + content: "\e61e"; + } + .icon-alert:before { + content: "\e61f"; + } + .icon-versions:before { + content: "\e620"; + } + .icon-twitter:before { + content: "\e621"; + } + .icon-thumbs-up:before { + content: "\e622"; + } + .icon-thumbs-down:before { + content: "\e623"; + } + .icon-text-resize:before { + content: "\e624"; + } + .icon-success-stories:before { + content: "\e625"; + } + .icon-statistics:before { + content: "\e626"; + } + .icon-stack-overflow:before { + content: "\e627"; + } + .icon-mastodon:before { + content: "\e900"; + } /* * Hide from anything that does not support FontFace (Opera Mini, Blackberry) @@ -3546,18 +3554,18 @@ span.highlighted { * or generated content */ /*modernizr*/ -.no-fontface .icon-megaphone, .no-fontface .icon-python-alt, .no-fontface .icon-pypi, .no-fontface .icon-news, .no-fontface .icon-moderate, .no-fontface .icon-mercurial, .no-fontface .icon-jobs, .no-fontface .icon-help, .no-fontface .icon-download, .no-fontface .icon-documentation, .no-fontface .icon-community, .no-fontface .icon-code, .no-fontface .icon-close, .no-fontface .icon-calendar, .no-fontface .icon-beginner, .no-fontface .icon-advanced, .no-fontface .icon-sitemap, .no-fontface .icon-search, .no-fontface .icon-search-alt, .no-fontface .icon-python, .no-fontface .icon-github, .no-fontface .icon-get-started, .no-fontface .icon-feed, .no-fontface .icon-facebook, .no-fontface .icon-email, .no-fontface .icon-arrow-up, .no-fontface .icon-arrow-right, .no-fontface .icon-arrow-left, .no-fontface .icon-arrow-down, .no-fontface .errorlist:before, .no-fontface .icon-freenode, .no-fontface .icon-alert, .no-fontface .icon-versions, .no-fontface .icon-twitter, .no-fontface .icon-thumbs-up, .no-fontface .icon-thumbs-down, .no-fontface .icon-text-resize, .no-fontface .icon-success-stories, .no-fontface .icon-statistics, .no-fontface .icon-stack-overflow, .no-svg .icon-megaphone, .no-svg .icon-python-alt, .no-svg .icon-pypi, .no-svg .icon-news, .no-svg .icon-moderate, .no-svg .icon-mercurial, .no-svg .icon-jobs, .no-svg .icon-help, .no-svg .icon-download, .no-svg .icon-documentation, .no-svg .icon-community, .no-svg .icon-code, .no-svg .icon-close, .no-svg .icon-calendar, .no-svg .icon-beginner, .no-svg .icon-advanced, .no-svg .icon-sitemap, .no-svg .icon-search, .no-svg .icon-search-alt, .no-svg .icon-python, .no-svg .icon-github, .no-svg .icon-get-started, .no-svg .icon-feed, .no-svg .icon-facebook, .no-svg .icon-email, .no-svg .icon-arrow-up, .no-svg .icon-arrow-right, .no-svg .icon-arrow-left, .no-svg .icon-arrow-down, .no-svg .errorlist:before, .no-svg .icon-freenode, .no-svg .icon-alert, .no-svg .icon-versions, .no-svg .icon-twitter, .no-svg .icon-thumbs-up, .no-svg .icon-thumbs-down, .no-svg .icon-text-resize, .no-svg .icon-success-stories, .no-svg .icon-statistics, .no-svg .icon-stack-overflow, .no-generatedcontent .icon-megaphone, .no-generatedcontent .icon-python-alt, .no-generatedcontent .icon-pypi, .no-generatedcontent .icon-news, .no-generatedcontent .icon-moderate, .no-generatedcontent .icon-mercurial, .no-generatedcontent .icon-jobs, .no-generatedcontent .icon-help, .no-generatedcontent .icon-download, .no-generatedcontent .icon-documentation, .no-generatedcontent .icon-community, .no-generatedcontent .icon-code, .no-generatedcontent .icon-close, .no-generatedcontent .icon-calendar, .no-generatedcontent .icon-beginner, .no-generatedcontent .icon-advanced, .no-generatedcontent .icon-sitemap, .no-generatedcontent .icon-search, .no-generatedcontent .icon-search-alt, .no-generatedcontent .icon-python, .no-generatedcontent .icon-github, .no-generatedcontent .icon-get-started, .no-generatedcontent .icon-feed, .no-generatedcontent .icon-facebook, .no-generatedcontent .icon-email, .no-generatedcontent .icon-arrow-up, .no-generatedcontent .icon-arrow-right, .no-generatedcontent .icon-arrow-left, .no-generatedcontent .icon-arrow-down, .no-generatedcontent .errorlist:before, .no-generatedcontent .icon-freenode, .no-generatedcontent .icon-alert, .no-generatedcontent .icon-versions, .no-generatedcontent .icon-twitter, .no-generatedcontent .icon-thumbs-up, .no-generatedcontent .icon-thumbs-down, .no-generatedcontent .icon-text-resize, .no-generatedcontent .icon-success-stories, .no-generatedcontent .icon-statistics, .no-generatedcontent .icon-stack-overflow { +.no-fontface .icon-megaphone, .no-fontface .icon-python-alt, .no-fontface .icon-pypi, .no-fontface .icon-news, .no-fontface .icon-moderate, .no-fontface .icon-mercurial, .no-fontface .icon-jobs, .no-fontface .icon-help, .no-fontface .icon-download, .no-fontface .icon-documentation, .no-fontface .icon-community, .no-fontface .icon-code, .no-fontface .icon-close, .no-fontface .icon-calendar, .no-fontface .icon-beginner, .no-fontface .icon-advanced, .no-fontface .icon-sitemap, .no-fontface .icon-search, .no-fontface .icon-search-alt, .no-fontface .icon-python, .no-fontface .icon-github, .no-fontface .icon-get-started, .no-fontface .icon-feed, .no-fontface .icon-facebook, .no-fontface .icon-email, .no-fontface .icon-arrow-up, .no-fontface .icon-arrow-right, .no-fontface .icon-arrow-left, .no-fontface .icon-arrow-down, .no-fontface .errorlist:before, .no-fontface .icon-freenode, .no-fontface .icon-alert, .no-fontface .icon-versions, .no-fontface .icon-twitter, .no-fontface .icon-thumbs-up, .no-fontface .icon-thumbs-down, .no-fontface .icon-text-resize, .no-fontface .icon-success-stories, .no-fontface .icon-statistics, .no-fontface .icon-stack-overflow, .no-fontface .icon-mastodon, .no-svg .icon-megaphone, .no-svg .icon-python-alt, .no-svg .icon-pypi, .no-svg .icon-news, .no-svg .icon-moderate, .no-svg .icon-mercurial, .no-svg .icon-jobs, .no-svg .icon-help, .no-svg .icon-download, .no-svg .icon-documentation, .no-svg .icon-community, .no-svg .icon-code, .no-svg .icon-close, .no-svg .icon-calendar, .no-svg .icon-beginner, .no-svg .icon-advanced, .no-svg .icon-sitemap, .no-svg .icon-search, .no-svg .icon-search-alt, .no-svg .icon-python, .no-svg .icon-github, .no-svg .icon-get-started, .no-svg .icon-feed, .no-svg .icon-facebook, .no-svg .icon-email, .no-svg .icon-arrow-up, .no-svg .icon-arrow-right, .no-svg .icon-arrow-left, .no-svg .icon-arrow-down, .no-svg .errorlist:before, .no-svg .icon-freenode, .no-svg .icon-alert, .no-svg .icon-versions, .no-svg .icon-twitter, .no-svg .icon-thumbs-up, .no-svg .icon-thumbs-down, .no-svg .icon-text-resize, .no-svg .icon-success-stories, .no-svg .icon-statistics, .no-svg .icon-stack-overflow, .no-svg .icon-mastodon, .no-generatedcontent .icon-megaphone, .no-generatedcontent .icon-python-alt, .no-generatedcontent .icon-pypi, .no-generatedcontent .icon-news, .no-generatedcontent .icon-moderate, .no-generatedcontent .icon-mercurial, .no-generatedcontent .icon-jobs, .no-generatedcontent .icon-help, .no-generatedcontent .icon-download, .no-generatedcontent .icon-documentation, .no-generatedcontent .icon-community, .no-generatedcontent .icon-code, .no-generatedcontent .icon-close, .no-generatedcontent .icon-calendar, .no-generatedcontent .icon-beginner, .no-generatedcontent .icon-advanced, .no-generatedcontent .icon-sitemap, .no-generatedcontent .icon-search, .no-generatedcontent .icon-search-alt, .no-generatedcontent .icon-python, .no-generatedcontent .icon-github, .no-generatedcontent .icon-get-started, .no-generatedcontent .icon-feed, .no-generatedcontent .icon-facebook, .no-generatedcontent .icon-email, .no-generatedcontent .icon-arrow-up, .no-generatedcontent .icon-arrow-right, .no-generatedcontent .icon-arrow-left, .no-generatedcontent .icon-arrow-down, .no-generatedcontent .errorlist:before, .no-generatedcontent .icon-freenode, .no-generatedcontent .icon-alert, .no-generatedcontent .icon-versions, .no-generatedcontent .icon-twitter, .no-generatedcontent .icon-thumbs-up, .no-generatedcontent .icon-thumbs-down, .no-generatedcontent .icon-text-resize, .no-generatedcontent .icon-success-stories, .no-generatedcontent .icon-statistics, .no-generatedcontent .icon-stack-overflow, .no-generatedcontent .icon-mastodon { /* Show a unicode character back up if it exists */ } - .no-fontface .icon-megaphone:before, .no-fontface .icon-python-alt:before, .no-fontface .icon-pypi:before, .no-fontface .icon-news:before, .no-fontface .icon-moderate:before, .no-fontface .icon-mercurial:before, .no-fontface .icon-jobs:before, .no-fontface .icon-help:before, .no-fontface .icon-download:before, .no-fontface .icon-documentation:before, .no-fontface .icon-community:before, .no-fontface .icon-code:before, .no-fontface .icon-close:before, .no-fontface .icon-calendar:before, .no-fontface .icon-beginner:before, .no-fontface .icon-advanced:before, .no-fontface .icon-sitemap:before, .no-fontface .icon-search:before, .no-fontface .icon-search-alt:before, .no-fontface .icon-python:before, .no-fontface .icon-github:before, .no-fontface .icon-get-started:before, .no-fontface .icon-feed:before, .no-fontface .icon-facebook:before, .no-fontface .icon-email:before, .no-fontface .icon-arrow-up:before, .no-fontface .icon-arrow-right:before, .no-fontface .icon-arrow-left:before, .no-fontface .icon-arrow-down:before, .no-fontface .errorlist:before, .no-fontface .icon-freenode:before, .no-fontface .icon-alert:before, .no-fontface .icon-versions:before, .no-fontface .icon-twitter:before, .no-fontface .icon-thumbs-up:before, .no-fontface .icon-thumbs-down:before, .no-fontface .icon-text-resize:before, .no-fontface .icon-success-stories:before, .no-fontface .icon-statistics:before, .no-fontface .icon-stack-overflow:before, .no-svg .icon-megaphone:before, .no-svg .icon-python-alt:before, .no-svg .icon-pypi:before, .no-svg .icon-news:before, .no-svg .icon-moderate:before, .no-svg .icon-mercurial:before, .no-svg .icon-jobs:before, .no-svg .icon-help:before, .no-svg .icon-download:before, .no-svg .icon-documentation:before, .no-svg .icon-community:before, .no-svg .icon-code:before, .no-svg .icon-close:before, .no-svg .icon-calendar:before, .no-svg .icon-beginner:before, .no-svg .icon-advanced:before, .no-svg .icon-sitemap:before, .no-svg .icon-search:before, .no-svg .icon-search-alt:before, .no-svg .icon-python:before, .no-svg .icon-github:before, .no-svg .icon-get-started:before, .no-svg .icon-feed:before, .no-svg .icon-facebook:before, .no-svg .icon-email:before, .no-svg .icon-arrow-up:before, .no-svg .icon-arrow-right:before, .no-svg .icon-arrow-left:before, .no-svg .icon-arrow-down:before, .no-svg .errorlist:before, .no-svg .icon-freenode:before, .no-svg .icon-alert:before, .no-svg .icon-versions:before, .no-svg .icon-twitter:before, .no-svg .icon-thumbs-up:before, .no-svg .icon-thumbs-down:before, .no-svg .icon-text-resize:before, .no-svg .icon-success-stories:before, .no-svg .icon-statistics:before, .no-svg .icon-stack-overflow:before, .no-generatedcontent .icon-megaphone:before, .no-generatedcontent .icon-python-alt:before, .no-generatedcontent .icon-pypi:before, .no-generatedcontent .icon-news:before, .no-generatedcontent .icon-moderate:before, .no-generatedcontent .icon-mercurial:before, .no-generatedcontent .icon-jobs:before, .no-generatedcontent .icon-help:before, .no-generatedcontent .icon-download:before, .no-generatedcontent .icon-documentation:before, .no-generatedcontent .icon-community:before, .no-generatedcontent .icon-code:before, .no-generatedcontent .icon-close:before, .no-generatedcontent .icon-calendar:before, .no-generatedcontent .icon-beginner:before, .no-generatedcontent .icon-advanced:before, .no-generatedcontent .icon-sitemap:before, .no-generatedcontent .icon-search:before, .no-generatedcontent .icon-search-alt:before, .no-generatedcontent .icon-python:before, .no-generatedcontent .icon-github:before, .no-generatedcontent .icon-get-started:before, .no-generatedcontent .icon-feed:before, .no-generatedcontent .icon-facebook:before, .no-generatedcontent .icon-email:before, .no-generatedcontent .icon-arrow-up:before, .no-generatedcontent .icon-arrow-right:before, .no-generatedcontent .icon-arrow-left:before, .no-generatedcontent .icon-arrow-down:before, .no-generatedcontent .errorlist:before, .no-generatedcontent .icon-freenode:before, .no-generatedcontent .icon-alert:before, .no-generatedcontent .icon-versions:before, .no-generatedcontent .icon-twitter:before, .no-generatedcontent .icon-thumbs-up:before, .no-generatedcontent .icon-thumbs-down:before, .no-generatedcontent .icon-text-resize:before, .no-generatedcontent .icon-success-stories:before, .no-generatedcontent .icon-statistics:before, .no-generatedcontent .icon-stack-overflow:before { + .no-fontface .icon-megaphone:before, .no-fontface .icon-python-alt:before, .no-fontface .icon-pypi:before, .no-fontface .icon-news:before, .no-fontface .icon-moderate:before, .no-fontface .icon-mercurial:before, .no-fontface .icon-jobs:before, .no-fontface .icon-help:before, .no-fontface .icon-download:before, .no-fontface .icon-documentation:before, .no-fontface .icon-community:before, .no-fontface .icon-code:before, .no-fontface .icon-close:before, .no-fontface .icon-calendar:before, .no-fontface .icon-beginner:before, .no-fontface .icon-advanced:before, .no-fontface .icon-sitemap:before, .no-fontface .icon-search:before, .no-fontface .icon-search-alt:before, .no-fontface .icon-python:before, .no-fontface .icon-github:before, .no-fontface .icon-get-started:before, .no-fontface .icon-feed:before, .no-fontface .icon-facebook:before, .no-fontface .icon-email:before, .no-fontface .icon-arrow-up:before, .no-fontface .icon-arrow-right:before, .no-fontface .icon-arrow-left:before, .no-fontface .icon-arrow-down:before, .no-fontface .errorlist:before, .no-fontface .icon-freenode:before, .no-fontface .icon-alert:before, .no-fontface .icon-versions:before, .no-fontface .icon-twitter:before, .no-fontface .icon-thumbs-up:before, .no-fontface .icon-thumbs-down:before, .no-fontface .icon-text-resize:before, .no-fontface .icon-success-stories:before, .no-fontface .icon-statistics:before, .no-fontface .icon-stack-overflow:before, .no-fontface .icon-mastodon:before, .no-svg .icon-megaphone:before, .no-svg .icon-python-alt:before, .no-svg .icon-pypi:before, .no-svg .icon-news:before, .no-svg .icon-moderate:before, .no-svg .icon-mercurial:before, .no-svg .icon-jobs:before, .no-svg .icon-help:before, .no-svg .icon-download:before, .no-svg .icon-documentation:before, .no-svg .icon-community:before, .no-svg .icon-code:before, .no-svg .icon-close:before, .no-svg .icon-calendar:before, .no-svg .icon-beginner:before, .no-svg .icon-advanced:before, .no-svg .icon-sitemap:before, .no-svg .icon-search:before, .no-svg .icon-search-alt:before, .no-svg .icon-python:before, .no-svg .icon-github:before, .no-svg .icon-get-started:before, .no-svg .icon-feed:before, .no-svg .icon-facebook:before, .no-svg .icon-email:before, .no-svg .icon-arrow-up:before, .no-svg .icon-arrow-right:before, .no-svg .icon-arrow-left:before, .no-svg .icon-arrow-down:before, .no-svg .errorlist:before, .no-svg .icon-freenode:before, .no-svg .icon-alert:before, .no-svg .icon-versions:before, .no-svg .icon-twitter:before, .no-svg .icon-thumbs-up:before, .no-svg .icon-thumbs-down:before, .no-svg .icon-text-resize:before, .no-svg .icon-success-stories:before, .no-svg .icon-statistics:before, .no-svg .icon-stack-overflow:before, .no-svg .icon-mastodon:before, .no-generatedcontent .icon-megaphone:before, .no-generatedcontent .icon-python-alt:before, .no-generatedcontent .icon-pypi:before, .no-generatedcontent .icon-news:before, .no-generatedcontent .icon-moderate:before, .no-generatedcontent .icon-mercurial:before, .no-generatedcontent .icon-jobs:before, .no-generatedcontent .icon-help:before, .no-generatedcontent .icon-download:before, .no-generatedcontent .icon-documentation:before, .no-generatedcontent .icon-community:before, .no-generatedcontent .icon-code:before, .no-generatedcontent .icon-close:before, .no-generatedcontent .icon-calendar:before, .no-generatedcontent .icon-beginner:before, .no-generatedcontent .icon-advanced:before, .no-generatedcontent .icon-sitemap:before, .no-generatedcontent .icon-search:before, .no-generatedcontent .icon-search-alt:before, .no-generatedcontent .icon-python:before, .no-generatedcontent .icon-github:before, .no-generatedcontent .icon-get-started:before, .no-generatedcontent .icon-feed:before, .no-generatedcontent .icon-facebook:before, .no-generatedcontent .icon-email:before, .no-generatedcontent .icon-arrow-up:before, .no-generatedcontent .icon-arrow-right:before, .no-generatedcontent .icon-arrow-left:before, .no-generatedcontent .icon-arrow-down:before, .no-generatedcontent .errorlist:before, .no-generatedcontent .icon-freenode:before, .no-generatedcontent .icon-alert:before, .no-generatedcontent .icon-versions:before, .no-generatedcontent .icon-twitter:before, .no-generatedcontent .icon-thumbs-up:before, .no-generatedcontent .icon-thumbs-down:before, .no-generatedcontent .icon-text-resize:before, .no-generatedcontent .icon-success-stories:before, .no-generatedcontent .icon-statistics:before, .no-generatedcontent .icon-stack-overflow:before, .no-generatedcontent .icon-mastodon:before { display: none; margin-right: 0; } - .no-fontface .icon-megaphone span, .no-fontface .icon-python-alt span, .no-fontface .icon-pypi span, .no-fontface .icon-news span, .no-fontface .icon-moderate span, .no-fontface .icon-mercurial span, .no-fontface .icon-jobs span, .no-fontface .icon-help span, .no-fontface .icon-download span, .no-fontface .icon-documentation span, .no-fontface .icon-community span, .no-fontface .icon-code span, .no-fontface .icon-close span, .no-fontface .icon-calendar span, .no-fontface .icon-beginner span, .no-fontface .icon-advanced span, .no-fontface .icon-sitemap span, .no-fontface .icon-search span, .no-fontface .icon-search-alt span, .no-fontface .icon-python span, .no-fontface .icon-github span, .no-fontface .icon-get-started span, .no-fontface .icon-feed span, .no-fontface .icon-facebook span, .no-fontface .icon-email span, .no-fontface .icon-arrow-up span, .no-fontface .icon-arrow-right span, .no-fontface .icon-arrow-left span, .no-fontface .icon-arrow-down span, .no-fontface .errorlist:before span, .no-fontface .icon-freenode span, .no-fontface .icon-alert span, .no-fontface .icon-versions span, .no-fontface .icon-twitter span, .no-fontface .icon-thumbs-up span, .no-fontface .icon-thumbs-down span, .no-fontface .icon-text-resize span, .no-fontface .icon-success-stories span, .no-fontface .icon-statistics span, .no-fontface .icon-stack-overflow span, .no-svg .icon-megaphone span, .no-svg .icon-python-alt span, .no-svg .icon-pypi span, .no-svg .icon-news span, .no-svg .icon-moderate span, .no-svg .icon-mercurial span, .no-svg .icon-jobs span, .no-svg .icon-help span, .no-svg .icon-download span, .no-svg .icon-documentation span, .no-svg .icon-community span, .no-svg .icon-code span, .no-svg .icon-close span, .no-svg .icon-calendar span, .no-svg .icon-beginner span, .no-svg .icon-advanced span, .no-svg .icon-sitemap span, .no-svg .icon-search span, .no-svg .icon-search-alt span, .no-svg .icon-python span, .no-svg .icon-github span, .no-svg .icon-get-started span, .no-svg .icon-feed span, .no-svg .icon-facebook span, .no-svg .icon-email span, .no-svg .icon-arrow-up span, .no-svg .icon-arrow-right span, .no-svg .icon-arrow-left span, .no-svg .icon-arrow-down span, .no-svg .errorlist:before span, .no-svg .icon-freenode span, .no-svg .icon-alert span, .no-svg .icon-versions span, .no-svg .icon-twitter span, .no-svg .icon-thumbs-up span, .no-svg .icon-thumbs-down span, .no-svg .icon-text-resize span, .no-svg .icon-success-stories span, .no-svg .icon-statistics span, .no-svg .icon-stack-overflow span, .no-generatedcontent .icon-megaphone span, .no-generatedcontent .icon-python-alt span, .no-generatedcontent .icon-pypi span, .no-generatedcontent .icon-news span, .no-generatedcontent .icon-moderate span, .no-generatedcontent .icon-mercurial span, .no-generatedcontent .icon-jobs span, .no-generatedcontent .icon-help span, .no-generatedcontent .icon-download span, .no-generatedcontent .icon-documentation span, .no-generatedcontent .icon-community span, .no-generatedcontent .icon-code span, .no-generatedcontent .icon-close span, .no-generatedcontent .icon-calendar span, .no-generatedcontent .icon-beginner span, .no-generatedcontent .icon-advanced span, .no-generatedcontent .icon-sitemap span, .no-generatedcontent .icon-search span, .no-generatedcontent .icon-search-alt span, .no-generatedcontent .icon-python span, .no-generatedcontent .icon-github span, .no-generatedcontent .icon-get-started span, .no-generatedcontent .icon-feed span, .no-generatedcontent .icon-facebook span, .no-generatedcontent .icon-email span, .no-generatedcontent .icon-arrow-up span, .no-generatedcontent .icon-arrow-right span, .no-generatedcontent .icon-arrow-left span, .no-generatedcontent .icon-arrow-down span, .no-generatedcontent .errorlist:before span, .no-generatedcontent .icon-freenode span, .no-generatedcontent .icon-alert span, .no-generatedcontent .icon-versions span, .no-generatedcontent .icon-twitter span, .no-generatedcontent .icon-thumbs-up span, .no-generatedcontent .icon-thumbs-down span, .no-generatedcontent .icon-text-resize span, .no-generatedcontent .icon-success-stories span, .no-generatedcontent .icon-statistics span, .no-generatedcontent .icon-stack-overflow span { + .no-fontface .icon-megaphone span, .no-fontface .icon-python-alt span, .no-fontface .icon-pypi span, .no-fontface .icon-news span, .no-fontface .icon-moderate span, .no-fontface .icon-mercurial span, .no-fontface .icon-jobs span, .no-fontface .icon-help span, .no-fontface .icon-download span, .no-fontface .icon-documentation span, .no-fontface .icon-community span, .no-fontface .icon-code span, .no-fontface .icon-close span, .no-fontface .icon-calendar span, .no-fontface .icon-beginner span, .no-fontface .icon-advanced span, .no-fontface .icon-sitemap span, .no-fontface .icon-search span, .no-fontface .icon-search-alt span, .no-fontface .icon-python span, .no-fontface .icon-github span, .no-fontface .icon-get-started span, .no-fontface .icon-feed span, .no-fontface .icon-facebook span, .no-fontface .icon-email span, .no-fontface .icon-arrow-up span, .no-fontface .icon-arrow-right span, .no-fontface .icon-arrow-left span, .no-fontface .icon-arrow-down span, .no-fontface .errorlist:before span, .no-fontface .icon-freenode span, .no-fontface .icon-alert span, .no-fontface .icon-versions span, .no-fontface .icon-twitter span, .no-fontface .icon-thumbs-up span, .no-fontface .icon-thumbs-down span, .no-fontface .icon-text-resize span, .no-fontface .icon-success-stories span, .no-fontface .icon-statistics span, .no-fontface .icon-stack-overflow span, .no-fontface .icon-mastodon span, .no-svg .icon-megaphone span, .no-svg .icon-python-alt span, .no-svg .icon-pypi span, .no-svg .icon-news span, .no-svg .icon-moderate span, .no-svg .icon-mercurial span, .no-svg .icon-jobs span, .no-svg .icon-help span, .no-svg .icon-download span, .no-svg .icon-documentation span, .no-svg .icon-community span, .no-svg .icon-code span, .no-svg .icon-close span, .no-svg .icon-calendar span, .no-svg .icon-beginner span, .no-svg .icon-advanced span, .no-svg .icon-sitemap span, .no-svg .icon-search span, .no-svg .icon-search-alt span, .no-svg .icon-python span, .no-svg .icon-github span, .no-svg .icon-get-started span, .no-svg .icon-feed span, .no-svg .icon-facebook span, .no-svg .icon-email span, .no-svg .icon-arrow-up span, .no-svg .icon-arrow-right span, .no-svg .icon-arrow-left span, .no-svg .icon-arrow-down span, .no-svg .errorlist:before span, .no-svg .icon-freenode span, .no-svg .icon-alert span, .no-svg .icon-versions span, .no-svg .icon-twitter span, .no-svg .icon-thumbs-up span, .no-svg .icon-thumbs-down span, .no-svg .icon-text-resize span, .no-svg .icon-success-stories span, .no-svg .icon-statistics span, .no-svg .icon-stack-overflow span, .no-svg .icon-mastodon span, .no-generatedcontent .icon-megaphone span, .no-generatedcontent .icon-python-alt span, .no-generatedcontent .icon-pypi span, .no-generatedcontent .icon-news span, .no-generatedcontent .icon-moderate span, .no-generatedcontent .icon-mercurial span, .no-generatedcontent .icon-jobs span, .no-generatedcontent .icon-help span, .no-generatedcontent .icon-download span, .no-generatedcontent .icon-documentation span, .no-generatedcontent .icon-community span, .no-generatedcontent .icon-code span, .no-generatedcontent .icon-close span, .no-generatedcontent .icon-calendar span, .no-generatedcontent .icon-beginner span, .no-generatedcontent .icon-advanced span, .no-generatedcontent .icon-sitemap span, .no-generatedcontent .icon-search span, .no-generatedcontent .icon-search-alt span, .no-generatedcontent .icon-python span, .no-generatedcontent .icon-github span, .no-generatedcontent .icon-get-started span, .no-generatedcontent .icon-feed span, .no-generatedcontent .icon-facebook span, .no-generatedcontent .icon-email span, .no-generatedcontent .icon-arrow-up span, .no-generatedcontent .icon-arrow-right span, .no-generatedcontent .icon-arrow-left span, .no-generatedcontent .icon-arrow-down span, .no-generatedcontent .errorlist:before span, .no-generatedcontent .icon-freenode span, .no-generatedcontent .icon-alert span, .no-generatedcontent .icon-versions span, .no-generatedcontent .icon-twitter span, .no-generatedcontent .icon-thumbs-up span, .no-generatedcontent .icon-thumbs-down span, .no-generatedcontent .icon-text-resize span, .no-generatedcontent .icon-success-stories span, .no-generatedcontent .icon-statistics span, .no-generatedcontent .icon-stack-overflow span, .no-generatedcontent .icon-mastodon span { display: inline; } /* Show in IE8: supports FontFace (eot) but not SVG. */ -.ie8 .icon-megaphone:before, .ie8 .icon-python-alt:before, .ie8 .icon-pypi:before, .ie8 .icon-news:before, .ie8 .icon-moderate:before, .ie8 .icon-mercurial:before, .ie8 .icon-jobs:before, .ie8 .icon-help:before, .ie8 .icon-download:before, .ie8 .icon-documentation:before, .ie8 .icon-community:before, .ie8 .icon-code:before, .ie8 .icon-close:before, .ie8 .icon-calendar:before, .ie8 .icon-beginner:before, .ie8 .icon-advanced:before, .ie8 .icon-sitemap:before, .ie8 .icon-search:before, .ie8 .icon-search-alt:before, .ie8 .icon-python:before, .ie8 .icon-github:before, .ie8 .icon-get-started:before, .ie8 .icon-feed:before, .ie8 .icon-facebook:before, .ie8 .icon-email:before, .ie8 .icon-arrow-up:before, .ie8 .icon-arrow-right:before, .ie8 .icon-arrow-left:before, .ie8 .icon-arrow-down:before, .ie8 .errorlist:before, .ie8 .icon-freenode:before, .ie8 .icon-alert:before, .ie8 .icon-versions:before, .ie8 .icon-twitter:before, .ie8 .icon-thumbs-up:before, .ie8 .icon-thumbs-down:before, .ie8 .icon-text-resize:before, .ie8 .icon-success-stories:before, .ie8 .icon-statistics:before, .ie8 .icon-stack-overflow:before { +.ie8 .icon-megaphone:before, .ie8 .icon-python-alt:before, .ie8 .icon-pypi:before, .ie8 .icon-news:before, .ie8 .icon-moderate:before, .ie8 .icon-mercurial:before, .ie8 .icon-jobs:before, .ie8 .icon-help:before, .ie8 .icon-download:before, .ie8 .icon-documentation:before, .ie8 .icon-community:before, .ie8 .icon-code:before, .ie8 .icon-close:before, .ie8 .icon-calendar:before, .ie8 .icon-beginner:before, .ie8 .icon-advanced:before, .ie8 .icon-sitemap:before, .ie8 .icon-search:before, .ie8 .icon-search-alt:before, .ie8 .icon-python:before, .ie8 .icon-github:before, .ie8 .icon-get-started:before, .ie8 .icon-feed:before, .ie8 .icon-facebook:before, .ie8 .icon-email:before, .ie8 .icon-arrow-up:before, .ie8 .icon-arrow-right:before, .ie8 .icon-arrow-left:before, .ie8 .icon-arrow-down:before, .ie8 .errorlist:before, .ie8 .icon-freenode:before, .ie8 .icon-alert:before, .ie8 .icon-versions:before, .ie8 .icon-twitter:before, .ie8 .icon-thumbs-up:before, .ie8 .icon-thumbs-down:before, .ie8 .icon-text-resize:before, .ie8 .icon-success-stories:before, .ie8 .icon-statistics:before, .ie8 .icon-stack-overflow:before, .ie8 .icon-mastodon:before { display: inline; } -.ie8 .icon-megaphone span, .ie8 .icon-python-alt span, .ie8 .icon-pypi span, .ie8 .icon-news span, .ie8 .icon-moderate span, .ie8 .icon-mercurial span, .ie8 .icon-jobs span, .ie8 .icon-help span, .ie8 .icon-download span, .ie8 .icon-documentation span, .ie8 .icon-community span, .ie8 .icon-code span, .ie8 .icon-close span, .ie8 .icon-calendar span, .ie8 .icon-beginner span, .ie8 .icon-advanced span, .ie8 .icon-sitemap span, .ie8 .icon-search span, .ie8 .icon-search-alt span, .ie8 .icon-python span, .ie8 .icon-github span, .ie8 .icon-get-started span, .ie8 .icon-feed span, .ie8 .icon-facebook span, .ie8 .icon-email span, .ie8 .icon-arrow-up span, .ie8 .icon-arrow-right span, .ie8 .icon-arrow-left span, .ie8 .icon-arrow-down span, .ie8 .errorlist:before span, .ie8 .icon-freenode span, .ie8 .icon-alert span, .ie8 .icon-versions span, .ie8 .icon-twitter span, .ie8 .icon-thumbs-up span, .ie8 .icon-thumbs-down span, .ie8 .icon-text-resize span, .ie8 .icon-success-stories span, .ie8 .icon-statistics span, .ie8 .icon-stack-overflow span { +.ie8 .icon-megaphone span, .ie8 .icon-python-alt span, .ie8 .icon-pypi span, .ie8 .icon-news span, .ie8 .icon-moderate span, .ie8 .icon-mercurial span, .ie8 .icon-jobs span, .ie8 .icon-help span, .ie8 .icon-download span, .ie8 .icon-documentation span, .ie8 .icon-community span, .ie8 .icon-code span, .ie8 .icon-close span, .ie8 .icon-calendar span, .ie8 .icon-beginner span, .ie8 .icon-advanced span, .ie8 .icon-sitemap span, .ie8 .icon-search span, .ie8 .icon-search-alt span, .ie8 .icon-python span, .ie8 .icon-github span, .ie8 .icon-get-started span, .ie8 .icon-feed span, .ie8 .icon-facebook span, .ie8 .icon-email span, .ie8 .icon-arrow-up span, .ie8 .icon-arrow-right span, .ie8 .icon-arrow-left span, .ie8 .icon-arrow-down span, .ie8 .errorlist:before span, .ie8 .icon-freenode span, .ie8 .icon-alert span, .ie8 .icon-versions span, .ie8 .icon-twitter span, .ie8 .icon-thumbs-up span, .ie8 .icon-thumbs-down span, .ie8 .icon-text-resize span, .ie8 .icon-success-stories span, .ie8 .icon-statistics span, .ie8 .icon-stack-overflow span, .ie8 .icon-mastodon span { display: none; } /* @license diff --git a/static/sass/style.scss b/static/sass/style.scss index aeecbc72b..45998bbc1 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -2410,7 +2410,7 @@ span.highlighted { /* ! ===== ICONS ===== */ /* Look inside _fonts.scss for most of the code. We declare this here so we can adjust as needed for specific elements. */ -.icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow { +.icon-megaphone, .icon-python-alt, .icon-pypi, .icon-news, .icon-moderate, .icon-mercurial, .icon-jobs, .icon-help, .icon-download, .icon-documentation, .icon-community, .icon-code, .icon-close, .icon-calendar, .icon-beginner, .icon-advanced, .icon-sitemap, .icon-search, .icon-search-alt, .icon-python, .icon-github, .icon-get-started, .icon-feed, .icon-facebook, .icon-email, .icon-arrow-up, .icon-arrow-right, .icon-arrow-left, .icon-arrow-down, .icon-freenode, .icon-alert, .icon-versions, .icon-twitter, .icon-thumbs-up, .icon-thumbs-down, .icon-text-resize, .icon-success-stories, .icon-statistics, .icon-stack-overflow, .icon-mastodon { font-family: 'Pythonicon'; speak: none; font-style: normal; diff --git a/templates/base.html b/templates/base.html index cf4c65cb0..ffa517a91 100644 --- a/templates/base.html +++ b/templates/base.html @@ -236,8 +236,9 @@

    Socialize From f274b4f340dfb943ba846af5da81c9603ae55e6e Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Wed, 15 Nov 2023 09:51:17 -0500 Subject: [PATCH 022/235] upgrade elasticsearch client --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index b19aacc93..998625e1d 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -22,7 +22,7 @@ chardet==4.0.0 # TODO: We may drop 'django-imagekit' completely. django-imagekit==4.0.2 django-haystack==3.0 -elasticsearch>=5,<6 +elasticsearch>=7,<8 # TODO: 0.14.0 only supports Django 1.8 and 1.11. django-tastypie==0.14.3 From ac85091d1c3937fba565c8f1597366ff1b34b495 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Wed, 15 Nov 2023 09:54:54 -0500 Subject: [PATCH 023/235] upgrade django-haystack --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 998625e1d..9ddabf236 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -21,7 +21,7 @@ icalendar==4.0.7 chardet==4.0.0 # TODO: We may drop 'django-imagekit' completely. django-imagekit==4.0.2 -django-haystack==3.0 +django-haystack==3.2.1 elasticsearch>=7,<8 # TODO: 0.14.0 only supports Django 1.8 and 1.11. django-tastypie==0.14.3 From 82682b072d615ad7563aa64232c247ee54354142 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Wed, 15 Nov 2023 09:58:28 -0500 Subject: [PATCH 024/235] use new backend --- pydotorg/settings/heroku.py | 2 +- pydotorg/settings/local.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pydotorg/settings/heroku.py b/pydotorg/settings/heroku.py index ab9646936..c32c9c67b 100644 --- a/pydotorg/settings/heroku.py +++ b/pydotorg/settings/heroku.py @@ -26,7 +26,7 @@ HAYSTACK_CONNECTIONS = { 'default': { - 'ENGINE': 'haystack.backends.elasticsearch5_backend.Elasticsearch5SearchEngine', + 'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine', 'URL': HAYSTACK_SEARCHBOX_SSL_URL, 'INDEX_NAME': 'haystack-prod', }, diff --git a/pydotorg/settings/local.py b/pydotorg/settings/local.py index 4ecbe35aa..6525d9837 100644 --- a/pydotorg/settings/local.py +++ b/pydotorg/settings/local.py @@ -26,7 +26,7 @@ HAYSTACK_CONNECTIONS = { 'default': { - 'ENGINE': 'haystack.backends.elasticsearch5_backend.Elasticsearch5SearchEngine', + 'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine', 'URL': HAYSTACK_SEARCHBOX_SSL_URL, 'INDEX_NAME': 'haystack', }, From e4ee9ce52bd7ad43032296eede85f7c26ea51b56 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Wed, 15 Nov 2023 10:40:58 -0500 Subject: [PATCH 025/235] make index name configurable --- pydotorg/settings/heroku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydotorg/settings/heroku.py b/pydotorg/settings/heroku.py index c32c9c67b..83e975cb1 100644 --- a/pydotorg/settings/heroku.py +++ b/pydotorg/settings/heroku.py @@ -28,7 +28,7 @@ 'default': { 'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine', 'URL': HAYSTACK_SEARCHBOX_SSL_URL, - 'INDEX_NAME': 'haystack-prod', + 'INDEX_NAME': config('HAYSTACK_INDEX', default='haystack-prod'), }, } From 67207962a817b4dc345843f7524fd2da8f4f2252 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Wed, 15 Nov 2023 10:51:14 -0500 Subject: [PATCH 026/235] this is just a 1/2/3 differentiator, disregard in search --- downloads/search_indexes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/downloads/search_indexes.py b/downloads/search_indexes.py index 307841283..7d476fb33 100644 --- a/downloads/search_indexes.py +++ b/downloads/search_indexes.py @@ -13,7 +13,6 @@ class ReleaseIndex(indexes.SearchIndex, indexes.Indexable): name = indexes.CharField(model_attr='name') description = indexes.CharField() path = indexes.CharField() - version = indexes.CharField(model_attr='version') release_notes_url = indexes.CharField(model_attr='release_notes_url') release_date = indexes.DateTimeField(model_attr='release_date') From c94985579635ad1791246493f7ec024ebe9abbac Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 21 Nov 2023 10:18:59 +0200 Subject: [PATCH 027/235] Add config file for Read the Docs (#2328) * Add config file for Read the Docs * Remove comment --- .gitignore | 1 + .readthedocs.yaml | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.gitignore b/.gitignore index 954ff2401..a9eca9d19 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # $ git config --global core.excludesfile ~/.gitignore_global .sass-cache/ +docs/build media/* static-root/ static/stylesheets/mq.css diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..ec9dc1ce9 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details +# Project page: https://readthedocs.org/projects/pythondotorg/ + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3" + + commands: + - python -m pip install -r docs-requirements.txt + - make -C docs html JOBS=$(nproc) BUILDDIR=_readthedocs + - mv docs/_readthedocs _readthedocs From f04b96f59147015676cf2b283684b381aef27a55 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 21 Nov 2023 10:22:56 +0200 Subject: [PATCH 028/235] Remove broken Twitter widget (#2329) * Remove broken Twitter widget * Remove broken Twitter widget --- static/sass/style.css | 4 --- static/sass/style.scss | 3 -- templates/components/tweets-from-psf.html | 4 --- templates/pages/default.html | 2 -- templates/pages/pep-page.html | 2 -- templates/psf/default.html | 2 -- templates/python/inner.html | 33 +--------------------- templates/successstories/base.html | 2 -- templates/waitforit.html | 34 +---------------------- 9 files changed, 2 insertions(+), 84 deletions(-) delete mode 100644 templates/components/tweets-from-psf.html diff --git a/static/sass/style.css b/static/sass/style.css index ad49c77b4..c3d2bb5f9 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -2771,10 +2771,6 @@ p.quote-by-organization { /* {% endblock left_sidebar %} diff --git a/templates/python/inner.html b/templates/python/inner.html index 06b1ad99e..542e6cb64 100644 --- a/templates/python/inner.html +++ b/templates/python/inner.html @@ -623,40 +623,9 @@

    Form Example

    {% block left_sidebar %} {% endblock left_sidebar %} diff --git a/templates/waitforit.html b/templates/waitforit.html index a7bc8f532..a27a9e274 100644 --- a/templates/waitforit.html +++ b/templates/waitforit.html @@ -22,37 +22,5 @@

    Wait for it…

    {% block left_sidebar %} -{% endblock left_sidebar %} \ No newline at end of file +{% endblock left_sidebar %} From f3eebba0937c408aaa51012a82d4b0a4a315fc36 Mon Sep 17 00:00:00 2001 From: Marc-Andre Lemburg Date: Tue, 21 Nov 2023 11:35:31 +0100 Subject: [PATCH 029/235] Merge main into release (#2330) * Add config file for Read the Docs (#2328) * Add config file for Read the Docs * Remove comment * Remove broken Twitter widget (#2329) * Remove broken Twitter widget * Remove broken Twitter widget --------- Co-authored-by: Hugo van Kemenade --- .gitignore | 1 + .readthedocs.yaml | 15 ++++++++++ static/sass/style.css | 4 --- static/sass/style.scss | 3 -- templates/components/tweets-from-psf.html | 4 --- templates/pages/default.html | 2 -- templates/pages/pep-page.html | 2 -- templates/psf/default.html | 2 -- templates/python/inner.html | 33 +--------------------- templates/successstories/base.html | 2 -- templates/waitforit.html | 34 +---------------------- 11 files changed, 18 insertions(+), 84 deletions(-) create mode 100644 .readthedocs.yaml delete mode 100644 templates/components/tweets-from-psf.html diff --git a/.gitignore b/.gitignore index 954ff2401..a9eca9d19 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # $ git config --global core.excludesfile ~/.gitignore_global .sass-cache/ +docs/build media/* static-root/ static/stylesheets/mq.css diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..ec9dc1ce9 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details +# Project page: https://readthedocs.org/projects/pythondotorg/ + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3" + + commands: + - python -m pip install -r docs-requirements.txt + - make -C docs html JOBS=$(nproc) BUILDDIR=_readthedocs + - mv docs/_readthedocs _readthedocs diff --git a/static/sass/style.css b/static/sass/style.css index ad49c77b4..c3d2bb5f9 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -2771,10 +2771,6 @@ p.quote-by-organization { /* {% endblock left_sidebar %} diff --git a/templates/python/inner.html b/templates/python/inner.html index 06b1ad99e..542e6cb64 100644 --- a/templates/python/inner.html +++ b/templates/python/inner.html @@ -623,40 +623,9 @@

    Form Example

    {% block left_sidebar %} {% endblock left_sidebar %} diff --git a/templates/waitforit.html b/templates/waitforit.html index a7bc8f532..a27a9e274 100644 --- a/templates/waitforit.html +++ b/templates/waitforit.html @@ -22,37 +22,5 @@

    Wait for it…

    {% block left_sidebar %} -{% endblock left_sidebar %} \ No newline at end of file +{% endblock left_sidebar %} From 0f881058596384d2ff167ade73d732edac58068c Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Sat, 9 Dec 2023 10:10:41 -0500 Subject: [PATCH 030/235] fix misleading link in site-tree fixture --- fixtures/sitetree_menus.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fixtures/sitetree_menus.json b/fixtures/sitetree_menus.json index 85fb6b6b0..70ad3fc7c 100644 --- a/fixtures/sitetree_menus.json +++ b/fixtures/sitetree_menus.json @@ -2557,7 +2557,7 @@ "fields": { "title": "PSF Sponsors", "hint": "", - "url": "/psf/sponsorship/sponsors/", + "url": "/psf/sponsors/", "urlaspattern": false, "tree": 1, "hidden": false, From e6118a4540060d53ad807a846979b34952fb208c Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 14 Dec 2023 14:14:27 -0500 Subject: [PATCH 031/235] Update sponsor_new_application.txt --- templates/sponsors/email/sponsor_new_application.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/templates/sponsors/email/sponsor_new_application.txt b/templates/sponsors/email/sponsor_new_application.txt index 486e4ef34..e859386bf 100644 --- a/templates/sponsors/email/sponsor_new_application.txt +++ b/templates/sponsors/email/sponsor_new_application.txt @@ -1,9 +1,11 @@ {% load sponsors %} Dear {{ sponsorship.sponsor.name }} {% if sponsorship.for_modified_package %} -Thank you for submitting your sponsorship application. We will contact you to discuss finalizing the customized sponsorship package within 2 business days. +Thank you for submitting your sponsorship application. +We will contact you to discuss finalizing the customized sponsorship package within 5 business days. {% else %} -Thank you for submitting your sponsorship application. We will be sending a Contract reflecting the sponsorship contract details. +Thank you for submitting your sponsorship application. +We will be sending a Contract reflecting the sponsorship contract details within 5 business days. {% endif %} You can review your full application and a list of benefits you will receive below. From 91fc8ccdf64d16618f49824c3b014f8751aa82b1 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 14 Dec 2023 14:21:50 -0500 Subject: [PATCH 032/235] update sponsor contract with new info, fix sponsorship year --- .../sponsors/admin/contract-template.docx | Bin 15061 -> 15199 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/templates/sponsors/admin/contract-template.docx b/templates/sponsors/admin/contract-template.docx index 6316a3eb18f1d361e5e2894ec8074796df09e312..5bdc44525a4d15367bcaad989f5d63ba6c278233 100644 GIT binary patch delta 10927 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 From 1296660a17266a94e788b0dbc940404d1066bbc9 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 14 Dec 2023 14:33:36 -0500 Subject: [PATCH 033/235] fix notice in post-roll on sponsor application --- templates/sponsors/sponsorship_application_finished.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/sponsors/sponsorship_application_finished.html b/templates/sponsors/sponsorship_application_finished.html index b7bb92953..15fd823c7 100644 --- a/templates/sponsors/sponsorship_application_finished.html +++ b/templates/sponsors/sponsorship_application_finished.html @@ -13,7 +13,7 @@

    Application submitted!


    Thank you for submitting your application to sponsor the PSF ecosystem.

    -

    Our team has been notified and will contact you within 2 business days to discuss next steps.

    +

    Our team has been notified and will contact you within 5 business days to discuss next steps.

    A confirmation has been emailed to {% for item in notified %}{% if forloop.first %}{% else %}{% if forloop.last %} and {% else %}, {% endif %}{% endif %}{{item}}{% endfor %}.

    If you have any questions please respond to the confirmation email or contact sponsors@python.org

    - The Python Software Foundation Sponsorship Team

    From fad5f2b7e4d5e2f08fc7d2e11c2c380bdc60efe0 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 14 Dec 2023 14:46:07 -0500 Subject: [PATCH 034/235] filtering by current_year where necessary --- sponsors/admin.py | 2 +- sponsors/forms.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sponsors/admin.py b/sponsors/admin.py index aa3d5408e..ac05a00b8 100644 --- a/sponsors/admin.py +++ b/sponsors/admin.py @@ -258,7 +258,7 @@ class TargetableEmailBenefitsFilter(admin.SimpleListFilter): @cached_property def benefits(self): qs = EmailTargetableConfiguration.objects.all().values_list("benefit_id", flat=True) - benefits = SponsorshipBenefit.objects.filter(id__in=Subquery(qs)) + benefits = SponsorshipBenefit.objects.filter(id__in=Subquery(qs), year=SponsorshipCurrentYear.get_year()) return {str(b.id): b for b in benefits} def lookups(self, request, model_admin): diff --git a/sponsors/forms.py b/sponsors/forms.py index 01d3de4f2..f4c72726a 100644 --- a/sponsors/forms.py +++ b/sponsors/forms.py @@ -127,6 +127,7 @@ def get_package(self): if not pkg_benefits and standalone: # standalone only pkg, _ = SponsorshipPackage.objects.get_or_create( slug="standalone-only", + year=SponsorshipCurrentYear.get_year(), defaults={"name": "Standalone Only", "sponsorship_amount": 0}, ) From 7b14c6c28bd7f8e23a5721e2a9f6a9e2912c2faf Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 14 Dec 2023 15:32:35 -0500 Subject: [PATCH 035/235] fix deletion of BenefitFeatures --- sponsors/models/benefits.py | 5 ++++- sponsors/models/managers.py | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sponsors/models/benefits.py b/sponsors/models/benefits.py index 51ec1870e..635b3f6b9 100644 --- a/sponsors/models/benefits.py +++ b/sponsors/models/benefits.py @@ -16,7 +16,7 @@ ######################################## # Benefit features abstract classes -from sponsors.models.managers import BenefitFeatureQuerySet +from sponsors.models.managers import BenefitFeatureQuerySet, BenefitFeatureConfigurationQuerySet ######################################## @@ -307,11 +307,14 @@ class BenefitFeatureConfiguration(PolymorphicModel): Base class for sponsorship benefits configuration. """ + objects = BenefitFeatureQuerySet.as_manager() benefit = models.ForeignKey("sponsors.SponsorshipBenefit", on_delete=models.CASCADE) + non_polymorphic = models.Manager() class Meta: verbose_name = "Benefit Feature Configuration" verbose_name_plural = "Benefit Feature Configurations" + base_manager_name = 'non_polymorphic' @property def benefit_feature_class(self): diff --git a/sponsors/models/managers.py b/sponsors/models/managers.py index 4681532f5..5cb241fc9 100644 --- a/sponsors/models/managers.py +++ b/sponsors/models/managers.py @@ -146,6 +146,15 @@ def provided_assets(self): return self.instance_of(*provided_assets_classes).select_related("sponsor_benefit__sponsorship") +class BenefitFeatureConfigurationQuerySet(PolymorphicQuerySet): + + def delete(self): + if not self.polymorphic_disabled: + return self.non_polymorphic().delete() + else: + return super().delete() + + class GenericAssetQuerySet(PolymorphicQuerySet): def all_assets(self): From 82016f407e8a0faf0936e3667786b687c8aa46b5 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 14 Dec 2023 15:35:27 -0500 Subject: [PATCH 036/235] missing migration --- .../migrations/0095_auto_20231214_2025.py | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 sponsors/migrations/0095_auto_20231214_2025.py diff --git a/sponsors/migrations/0095_auto_20231214_2025.py b/sponsors/migrations/0095_auto_20231214_2025.py new file mode 100644 index 000000000..e656bf05c --- /dev/null +++ b/sponsors/migrations/0095_auto_20231214_2025.py @@ -0,0 +1,83 @@ +# Generated by Django 2.2.24 on 2023-12-14 20:25 + +from django.db import migrations +import django.db.models.manager + + +class Migration(migrations.Migration): + dependencies = [ + ("sponsors", "0094_sponsorship_locked"), + ] + + operations = [ + migrations.AlterModelOptions( + name="benefitfeatureconfiguration", + options={ + "base_manager_name": "non_polymorphic", + "verbose_name": "Benefit Feature Configuration", + "verbose_name_plural": "Benefit Feature Configurations", + }, + ), + migrations.AlterModelManagers( + name="benefitfeatureconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="emailtargetableconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="logoplacementconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="providedfileassetconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="providedtextassetconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="requiredimgassetconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="requiredresponseassetconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="requiredtextassetconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name="tieredbenefitconfiguration", + managers=[ + ("non_polymorphic", django.db.models.manager.Manager()), + ("objects", django.db.models.manager.Manager()), + ], + ), + ] From 7ba7d3620d7e16dbfc564cd0cc4cdf5449852b37 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 14 Dec 2023 16:08:35 -0500 Subject: [PATCH 037/235] missing migration --- .../migrations/0096_auto_20231214_2108.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 sponsors/migrations/0096_auto_20231214_2108.py diff --git a/sponsors/migrations/0096_auto_20231214_2108.py b/sponsors/migrations/0096_auto_20231214_2108.py new file mode 100644 index 000000000..11c6dde5b --- /dev/null +++ b/sponsors/migrations/0096_auto_20231214_2108.py @@ -0,0 +1,61 @@ +# Generated by Django 2.2.24 on 2023-12-14 21:08 + +from django.db import migrations +import django.db.models.manager + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0095_auto_20231214_2025'), + ] + + operations = [ + migrations.AlterModelManagers( + name='benefitfeatureconfiguration', + managers=[ + ('objects', django.db.models.manager.Manager()), + ('non_polymorphic', django.db.models.manager.Manager()), + ], + ), + migrations.AlterModelManagers( + name='emailtargetableconfiguration', + managers=[ + ], + ), + migrations.AlterModelManagers( + name='logoplacementconfiguration', + managers=[ + ], + ), + migrations.AlterModelManagers( + name='providedfileassetconfiguration', + managers=[ + ], + ), + migrations.AlterModelManagers( + name='providedtextassetconfiguration', + managers=[ + ], + ), + migrations.AlterModelManagers( + name='requiredimgassetconfiguration', + managers=[ + ], + ), + migrations.AlterModelManagers( + name='requiredresponseassetconfiguration', + managers=[ + ], + ), + migrations.AlterModelManagers( + name='requiredtextassetconfiguration', + managers=[ + ], + ), + migrations.AlterModelManagers( + name='tieredbenefitconfiguration', + managers=[ + ], + ), + ] From 4ef43887cf19fd394ae7dd2ec5d1c0cf5d4d7f84 Mon Sep 17 00:00:00 2001 From: Jessie <70440141+jessiebelle@users.noreply.github.com> Date: Tue, 19 Dec 2023 21:20:39 +0200 Subject: [PATCH 038/235] Sponsorship - adding renewal option for contract generation (#2344) * WIP renewal work * test fix * removing venv added files * tidy and fixup * test fixup after logic changes * Sponsorship renewal review (#2345) * add rewnewal to the admin view for sponsorship * use the sponsorship form directly rather than editing template * include previous effective date in context/review form for renewals * update to real renewal contract * missing migration --------- Co-authored-by: Ee Durbin --- sponsors/admin.py | 1 + sponsors/forms.py | 9 ++++- .../migrations/0097_sponsorship_renewal.py | 18 +++++++++ .../migrations/0098_auto_20231219_1910.py | 18 +++++++++ sponsors/models/sponsorship.py | 13 +++++- sponsors/pdf.py | 10 ++++- sponsors/tests/test_pdf.py | 38 ++++++++++++++++++ sponsors/tests/test_use_cases.py | 18 +++++++++ sponsors/use_cases.py | 3 ++ sponsors/views_admin.py | 6 ++- .../sponsors/admin/approve_application.html | 22 +++++++++- .../admin/renewal-contract-template.docx | Bin 0 -> 9245 bytes 12 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 sponsors/migrations/0097_sponsorship_renewal.py create mode 100644 sponsors/migrations/0098_auto_20231219_1910.py create mode 100644 templates/sponsors/admin/renewal-contract-template.docx diff --git a/sponsors/admin.py b/sponsors/admin.py index ac05a00b8..d6601140f 100644 --- a/sponsors/admin.py +++ b/sponsors/admin.py @@ -402,6 +402,7 @@ class SponsorshipAdmin(ImportExportActionModelAdmin, admin.ModelAdmin): "end_date", "get_contract", "level_name", + "renewal", "overlapped_by", ), }, diff --git a/sponsors/forms.py b/sponsors/forms.py index f4c72726a..8d262b337 100644 --- a/sponsors/forms.py +++ b/sponsors/forms.py @@ -392,6 +392,10 @@ class SponsorshipReviewAdminForm(forms.ModelForm): start_date = forms.DateField(widget=AdminDateWidget(), required=False) end_date = forms.DateField(widget=AdminDateWidget(), required=False) overlapped_by = forms.ModelChoiceField(queryset=Sponsorship.objects.select_related("sponsor", "package"), required=False) + renewal = forms.BooleanField( + help_text="If true, it means the sponsorship is a renewal of a previous sponsorship and will use the renewal template for contracting.", + required=False, + ) def __init__(self, *args, **kwargs): force_required = kwargs.pop("force_required", False) @@ -403,10 +407,12 @@ def __init__(self, *args, **kwargs): self.fields.pop("overlapped_by") # overlapped should never be displayed on approval for field_name in self.fields: self.fields[field_name].required = True + self.fields["renewal"].required = False + class Meta: model = Sponsorship - fields = ["start_date", "end_date", "package", "sponsorship_fee"] + fields = ["start_date", "end_date", "package", "sponsorship_fee", "renewal"] widgets = { 'year': SPONSORSHIP_YEAR_SELECT, } @@ -415,6 +421,7 @@ def clean(self): cleaned_data = super().clean() start_date = cleaned_data.get("start_date") end_date = cleaned_data.get("end_date") + renewal = cleaned_data.get("renewal") if start_date and end_date and end_date <= start_date: raise forms.ValidationError("End date must be greater than start date") diff --git a/sponsors/migrations/0097_sponsorship_renewal.py b/sponsors/migrations/0097_sponsorship_renewal.py new file mode 100644 index 000000000..fdbc347b3 --- /dev/null +++ b/sponsors/migrations/0097_sponsorship_renewal.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2023-12-18 16:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0096_auto_20231214_2108'), + ] + + operations = [ + migrations.AddField( + model_name='sponsorship', + name='renewal', + field=models.BooleanField(blank=True, null=True), + ), + ] diff --git a/sponsors/migrations/0098_auto_20231219_1910.py b/sponsors/migrations/0098_auto_20231219_1910.py new file mode 100644 index 000000000..3c466bb75 --- /dev/null +++ b/sponsors/migrations/0098_auto_20231219_1910.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2023-12-19 19:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0097_sponsorship_renewal'), + ] + + operations = [ + migrations.AlterField( + model_name='sponsorship', + name='renewal', + field=models.BooleanField(blank=True, help_text='If true, it means the sponsorship is a renewal of a previous sponsorship and will use the renewal template for contracting.', null=True), + ), + ] diff --git a/sponsors/models/sponsorship.py b/sponsors/models/sponsorship.py index 8e1d13a63..7443d4d2c 100644 --- a/sponsors/models/sponsorship.py +++ b/sponsors/models/sponsorship.py @@ -135,7 +135,7 @@ class Meta(OrderedModel.Meta): class Sponsorship(models.Model): """ - Represente a sponsorship application by a sponsor. + Represents a sponsorship application by a sponsor. It's responsible to group the set of selected benefits and link it to sponsor """ @@ -182,6 +182,11 @@ class Sponsorship(models.Model): package = models.ForeignKey(SponsorshipPackage, null=True, on_delete=models.SET_NULL) sponsorship_fee = models.PositiveIntegerField(null=True, blank=True) overlapped_by = models.ForeignKey("self", null=True, on_delete=models.SET_NULL) + renewal = models.BooleanField( + null=True, + blank=True, + help_text="If true, it means the sponsorship is a renewal of a previous sponsorship and will use the renewal template for contracting." + ) assets = GenericRelation(GenericAsset) @@ -378,6 +383,12 @@ def next_status(self): } return states_map[self.status] + @property + def previous_effective_date(self): + if len(self.sponsor.sponsorship_set.all().order_by('-year')) > 1: + return self.sponsor.sponsorship_set.all().order_by('-year')[1].start_date + return None + class SponsorshipBenefit(OrderedModel): """ diff --git a/sponsors/pdf.py b/sponsors/pdf.py index 5188b8290..f1b80d911 100644 --- a/sponsors/pdf.py +++ b/sponsors/pdf.py @@ -32,7 +32,9 @@ def _contract_context(contract, **context): "sponsorship": contract.sponsorship, "benefits": _clean_split(contract.benefits_list.raw), "legal_clauses": _clean_split(contract.legal_clauses.raw), + "renewal": contract.sponsorship.renewal, }) + context["previous_effective"] = contract.sponsorship.previous_effective_date if contract.sponsorship.previous_effective_date else "UNKNOWN" return context @@ -49,9 +51,13 @@ def render_contract_to_pdf_file(contract, **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) + renewal = context["renewal"] + if renewal: + template = os.path.join(settings.TEMPLATES_DIR, "sponsors", "admin", "renewal-contract-template.docx") + else: + template = os.path.join(settings.TEMPLATES_DIR, "sponsors", "admin", "contract-template.docx") + doc = DocxTemplate(template) doc.render(context) doc.save(output) return output diff --git a/sponsors/tests/test_pdf.py b/sponsors/tests/test_pdf.py index ec929d05e..2116b7c21 100644 --- a/sponsors/tests/test_pdf.py +++ b/sponsors/tests/test_pdf.py @@ -28,6 +28,8 @@ def setUp(self): "sponsorship": self.contract.sponsorship, "benefits": [], "legal_clauses": [], + "renewal": None, + "previous_effective": "UNKNOWN", } self.template = "sponsors/admin/preview-contract.html" @@ -71,3 +73,39 @@ def test_render_response_with_docx_attachment(self, MockDocxTemplate): response.get("Content-Type"), "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ) + + @patch("sponsors.pdf.DocxTemplate") + def test_render_response_with_docx_attachment__renewal(self, MockDocxTemplate): + renewal_contract = baker.make_recipe("sponsors.tests.empty_contract", sponsorship__start_date=date.today(), + sponsorship__renewal=True) + text = f"{renewal_contract.benefits_list.raw}\n\n**Legal Clauses**\n{renewal_contract.legal_clauses.raw}" + html = render_md(text) + renewal_context = { + "contract": renewal_contract, + "start_date": renewal_contract.sponsorship.start_date, + "start_day_english_suffix": format(self.contract.sponsorship.start_date, "S"), + "sponsor": renewal_contract.sponsorship.sponsor, + "sponsorship": renewal_contract.sponsorship, + "benefits": [], + "legal_clauses": [], + "renewal": True, + "previous_effective": "UNKNOWN", + } + renewal_template = "sponsors/admin/preview-contract.html" + + template = Path(settings.TEMPLATES_DIR) / "sponsors" / "admin" / "renewal-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, renewal_contract) + + MockDocxTemplate.assert_called_once_with(str(template.resolve())) + mocked_doc.render.assert_called_once_with(renewal_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/tests/test_use_cases.py b/sponsors/tests/test_use_cases.py index 433d4950e..3e5e5ad04 100644 --- a/sponsors/tests/test_use_cases.py +++ b/sponsors/tests/test_use_cases.py @@ -118,6 +118,24 @@ def test_update_sponsorship_as_approved_and_create_contract(self): self.assertEqual(self.sponsorship.sponsorship_fee, 100) self.assertEqual(self.sponsorship.package, self.package) self.assertEqual(self.sponsorship.level_name, self.package.name) + self.assertFalse(self.sponsorship.renewal) + + + def test_update_renewal_sponsorship_as_approved_and_create_contract(self): + self.data.update({"renewal": True}) + self.use_case.execute(self.sponsorship, **self.data) + self.sponsorship.refresh_from_db() + + today = timezone.now().date() + self.assertEqual(self.sponsorship.approved_on, today) + self.assertEqual(self.sponsorship.status, Sponsorship.APPROVED) + self.assertTrue(self.sponsorship.contract.pk) + self.assertTrue(self.sponsorship.start_date) + self.assertTrue(self.sponsorship.end_date) + self.assertEqual(self.sponsorship.sponsorship_fee, 100) + self.assertEqual(self.sponsorship.package, self.package) + self.assertEqual(self.sponsorship.level_name, self.package.name) + self.assertEqual(self.sponsorship.renewal, True) def test_send_notifications_using_sponsorship(self): self.use_case.execute(self.sponsorship, **self.data) diff --git a/sponsors/use_cases.py b/sponsors/use_cases.py index 95b2d267e..bbb6f2483 100644 --- a/sponsors/use_cases.py +++ b/sponsors/use_cases.py @@ -55,11 +55,14 @@ def execute(self, sponsorship, start_date, end_date, **kwargs): sponsorship.approve(start_date, end_date) package = kwargs.get("package") fee = kwargs.get("sponsorship_fee") + renewal = kwargs.get("renewal", False) if package: sponsorship.package = package sponsorship.level_name = package.name if fee: sponsorship.sponsorship_fee = fee + if renewal: + sponsorship.renewal = True sponsorship.save() contract = Contract.new(sponsorship) diff --git a/sponsors/views_admin.py b/sponsors/views_admin.py index 8968da1b7..e9a808ccc 100644 --- a/sponsors/views_admin.py +++ b/sponsors/views_admin.py @@ -85,7 +85,11 @@ def approve_sponsorship_view(ModelAdmin, request, pk): ) return redirect(redirect_url) - context = {"sponsorship": sponsorship, "form": form} + context = { + "sponsorship": sponsorship, + "form": form, + "previous_effective": sponsorship.previous_effective_date if sponsorship.previous_effective_date else "UNKNOWN", + } return render(request, "sponsors/admin/approve_application.html", context=context) diff --git a/templates/sponsors/admin/approve_application.html b/templates/sponsors/admin/approve_application.html index 37ce49cdc..42a5f7382 100644 --- a/templates/sponsors/admin/approve_application.html +++ b/templates/sponsors/admin/approve_application.html @@ -2,7 +2,18 @@ {% extends 'admin/change_form.html' %} {% load i18n static sponsors %} -{% block extrastyle %}{{ block.super }}{% endblock %} +{% block extrastyle %} + {{ block.super }} + + +{% endblock %} {% block title %}Accept {{ sponsorship }} | python.org{% endblock %} @@ -33,8 +44,15 @@

    Generate Contract for Signing

    {{ form.media }} {{ form.as_p }} - +

    + + {{ previous_effective }} + The last known contract effective date for this sponsor. This will only impact renewals. If UNKNOWN, you MUST update the resulting docx with the correct effective date. +

    +
    diff --git a/templates/sponsors/admin/renewal-contract-template.docx b/templates/sponsors/admin/renewal-contract-template.docx new file mode 100644 index 0000000000000000000000000000000000000000..97b8d1cc673cb9df49be633c2b7e3e1d114f829e GIT binary patch literal 9245 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 V2m9>85D>`EkFIAoktKgQ`!AfFXAA%U literal 0 HcmV?d00001 From c00f46eee7d64f3a4d4a443bb6754c5047a02d4b Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Tue, 19 Dec 2023 14:49:42 -0500 Subject: [PATCH 039/235] formatting tweaks to the renewal contract --- sponsors/pdf.py | 4 +++- sponsors/tests/test_pdf.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sponsors/pdf.py b/sponsors/pdf.py index f1b80d911..9855beee3 100644 --- a/sponsors/pdf.py +++ b/sponsors/pdf.py @@ -34,7 +34,9 @@ def _contract_context(contract, **context): "legal_clauses": _clean_split(contract.legal_clauses.raw), "renewal": contract.sponsorship.renewal, }) - context["previous_effective"] = contract.sponsorship.previous_effective_date if contract.sponsorship.previous_effective_date else "UNKNOWN" + previous_effective = contract.sponsorship.previous_effective_date + context["previous_effective"] = previous_effective if previous_effective else "UNKNOWN" + context["previous_effective_english_suffix"] = format(previous_effective, "S") if previous_effective else None return context diff --git a/sponsors/tests/test_pdf.py b/sponsors/tests/test_pdf.py index 2116b7c21..e4d140cf2 100644 --- a/sponsors/tests/test_pdf.py +++ b/sponsors/tests/test_pdf.py @@ -30,6 +30,7 @@ def setUp(self): "legal_clauses": [], "renewal": None, "previous_effective": "UNKNOWN", + "previous_effective_english_suffix": None, } self.template = "sponsors/admin/preview-contract.html" @@ -90,6 +91,7 @@ def test_render_response_with_docx_attachment__renewal(self, MockDocxTemplate): "legal_clauses": [], "renewal": True, "previous_effective": "UNKNOWN", + "previous_effective_english_suffix": None, } renewal_template = "sponsors/admin/preview-contract.html" From e8a5c8291368b711894859edf2bd3616cab50cdf Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Tue, 19 Dec 2023 15:02:10 -0500 Subject: [PATCH 040/235] actually add template change --- .../admin/renewal-contract-template.docx | Bin 9245 -> 9323 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/templates/sponsors/admin/renewal-contract-template.docx b/templates/sponsors/admin/renewal-contract-template.docx index 97b8d1cc673cb9df49be633c2b7e3e1d114f829e..3e36801a316f85a4a0484c7b4ed1a227a9fb4285 100644 GIT binary patch delta 6918 zcmZ9R1yCGax3vfNKyY_=x53?+5Zpq7PjL4^f)6@)aEIXTF2RBY2@pKE1REqk{^a}b zt^2;;sp_geU42fUT5GTBs%Ph@9IIf1)RB-00qE%HfRUVfY&rzQksKHg0uy9HYmgVO z>xwApJbI@X+y~ad0BP%1ex=6~v2=bdzirs^>%l*}2?K@Q2?*Tzmd-LSZ-xTo)fZ-0 zW{i0Sh!K&i1t#1*KquCW{fM!YB7#a>I%|=QOyR>|&9)@AB3i~a zlIEOmBYcVZW6aYMyeA>Zv}>e*|*I0{P*bLrhs{?!C~c*Y3Ik>=`rC10_k=PEP2 zyN3P)H3R9T50W4Ik^s-);0`zXY;x%VlqdxCu z8i7T7(#pL6G1Wc8mg}%?`wfssCVYBAi@$i~z5ZlJd+#sf&^Bqm1djHeiihl9kV-*D zRh2V+D+Ogswe8pnzp$EykQ|5JH?j>iN5QKtr|>7FHsF*XfChNTE?V;I=X4%t4*;Z& zhVE-AVC;+l0Bj%v0RQp@_8pNCBI^|P$B#S^Kz{8P_#=0@+=u#XGa}@ zg=~ve7~xlX7V&)0Ch_fe)?)ITeSy`>!fYBQChSUEVpds*H5=FQgcE?=HolkPvRHS+ z)#iKpOl!?tU5|CXV4p0$Lc%$;RvI1|*doeVCvqs-rW}CK%DVqHO-VGwdZgF%kf0P7GIG#f&WWAb&% zv{~!GA}qVg&d1<;>7C;!O}O)gvEP^9@uLd2c4LuErI28JZH4ziU*MZ-w7-gjg}c~5 ze-u~zqxe6A05bsmV-Wngw}Sa25B|wUqYTOz;@^y5p)*6Y7{uU#y#p~VOfwO9c3EdO zs7hq$^Cxfsz5Pvm6TVxeX>{wS6XVs?L>u}W=c=ZwuHW@}b8i~J+KqXx=T=yjZx?q5PH0sb;jDe7Lqe+p<%|w8vpt zxAfEU>II}ET|t8sQ4+nI!CO5VAGmT{7j@Je<*x=N%Mj950`jA`jm{J!O>4ZMA-8rM5E$a^Wmjk?zzl}=TE zjH>x*yf=(u_1IBLiS7Crcf`dEecI*PUWJ};tUxHp+$a-~Ze5m(dgiQOD53PJ7)-+v zpB!~r9^QM{O-6J#+a8~iFu_ERxh|aqR--DlRiPZjNJ=IWyQR)7QpjM-_rm4OOD923 zaVL3k2HwXO0_U`sUhyk(>?@cd$pHM&d4?HFdtCHNrYEVO5%@+$0}akRF4^I!hkcug zIAo**OZ~V-_|{k7+*47!lv;yGO`dz%D70v1=(CP-gNa{zj{Z|wdh<7@8If%xy!eA1`hS}M}K#vT!YKB@ELi-sGIx|@JfFf-tc&%=52 zL`X|Jo`S_Tℜ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 CTDs2w delta 6788 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 From cbc6c143922933a082ad600207ddb75703757fe3 Mon Sep 17 00:00:00 2001 From: Varun Chauhan <43171263+varunhc@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:18:04 -0800 Subject: [PATCH 041/235] updated python issue tracker and pep links (#2318) * updated python issue tracker and pep links * Update templates/base.html Co-authored-by: Hugo van Kemenade --------- Co-authored-by: Hugo van Kemenade --- fixtures/boxes.json | 4 ++-- fixtures/sitetree_menus.json | 2 +- templates/base.html | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fixtures/boxes.json b/fixtures/boxes.json index f7dbeb15e..b0e965011 100644 --- a/fixtures/boxes.json +++ b/fixtures/boxes.json @@ -654,9 +654,9 @@ "created": "2014-11-13T21:49:22.048Z", "updated": "2021-07-29T21:40:21.030Z", "label": "download-dev", - "content": "

    Information about specific ports, and developer info

    \r\n\r\n", + "content": "

    Information about specific ports, and developer info

    \r\n\r\n", "content_markup_type": "html", - "_content_rendered": "

    Information about specific ports, and developer info

    \r\n\r\n" + "_content_rendered": "

    Information about specific ports, and developer info

    \r\n\r\n" } }, { diff --git a/fixtures/sitetree_menus.json b/fixtures/sitetree_menus.json index 70ad3fc7c..f394233ee 100644 --- a/fixtures/sitetree_menus.json +++ b/fixtures/sitetree_menus.json @@ -685,7 +685,7 @@ "fields": { "title": "PEP Index", "hint": "", - "url": "http://python.org/dev/peps/", + "url": "https://peps.python.org", "urlaspattern": false, "tree": 1, "hidden": false, diff --git a/templates/base.html b/templates/base.html index ffa517a91..27daceb50 100644 --- a/templates/base.html +++ b/templates/base.html @@ -86,7 +86,7 @@ + href="https://peps.python.org/peps.rss"> Date: Tue, 2 Jan 2024 15:47:57 +0200 Subject: [PATCH 042/235] Fix for SVG upload in sponsorship application (#2352) * changing imagefield to file field on sponsorupdateform and sponsorshipapplicationform. adding django file validator to these two and the sponsor model * allow png upload * adding test to assert that svg can be uploaded * fix migration --- sponsors/forms.py | 7 +++++-- .../migrations/0099_auto_20231224_1854.py | 19 +++++++++++++++++++ sponsors/models/sponsors.py | 2 ++ sponsors/tests/test_forms.py | 18 ++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 sponsors/migrations/0099_auto_20231224_1854.py diff --git a/sponsors/forms.py b/sponsors/forms.py index 8d262b337..5a31605af 100644 --- a/sponsors/forms.py +++ b/sponsors/forms.py @@ -3,6 +3,7 @@ from django import forms from django.conf import settings from django.contrib.admin.widgets import AdminDateWidget +from django.core.validators import FileExtensionValidator from django.db.models import Q from django.utils import timezone from django.utils.functional import cached_property @@ -225,10 +226,11 @@ class SponsorshipApplicationForm(forms.Form): help_text="For display on our sponsor webpage. High resolution PNG or JPG, smallest dimension no less than 256px", required=False, ) - print_logo = forms.ImageField( + print_logo = forms.FileField( label="Sponsor print logo", help_text="For printed materials, signage, and projection. SVG or EPS", required=False, + validators=[FileExtensionValidator(['eps', 'epsf' 'epsi', 'svg', 'png'])], ) primary_phone = forms.CharField( @@ -557,10 +559,11 @@ class SponsorUpdateForm(forms.ModelForm): help_text="For display on our sponsor webpage. High resolution PNG or JPG, smallest dimension no less than 256px", required=False, ) - print_logo = forms.ImageField( + print_logo = forms.FileField( widget=forms.widgets.FileInput, help_text="For printed materials, signage, and projection. SVG or EPS", required=False, + validators=[FileExtensionValidator(['eps', 'epsf' 'epsi', 'svg', 'png'])], ) def __init__(self, *args, **kwargs): diff --git a/sponsors/migrations/0099_auto_20231224_1854.py b/sponsors/migrations/0099_auto_20231224_1854.py new file mode 100644 index 000000000..d8aaa436c --- /dev/null +++ b/sponsors/migrations/0099_auto_20231224_1854.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.24 on 2023-12-24 18:54 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0098_auto_20231219_1910'), + ] + + operations = [ + migrations.AlterField( + model_name='sponsor', + name='print_logo', + field=models.FileField(blank=True, help_text='For printed materials, signage, and projection. SVG or EPS', null=True, upload_to='sponsor_print_logos', validators=[django.core.validators.FileExtensionValidator(['eps', 'epsfepsi', 'svg', 'png'])], verbose_name='Print logo'), + ), + ] diff --git a/sponsors/models/sponsors.py b/sponsors/models/sponsors.py index 9b4d8fe86..eee7f585e 100644 --- a/sponsors/models/sponsors.py +++ b/sponsors/models/sponsors.py @@ -3,6 +3,7 @@ """ from allauth.account.models import EmailAddress from django.conf import settings +from django.core.validators import FileExtensionValidator from django.db import models from django.core.exceptions import ObjectDoesNotExist from django.template.defaultfilters import slugify @@ -51,6 +52,7 @@ class Sponsor(ContentManageable): ) print_logo = models.FileField( upload_to="sponsor_print_logos", + validators=[FileExtensionValidator(['eps', 'epsf' 'epsi', 'svg', 'png'])], blank=True, null=True, verbose_name="Print logo", diff --git a/sponsors/tests/test_forms.py b/sponsors/tests/test_forms.py index 058e21625..123dc1729 100644 --- a/sponsors/tests/test_forms.py +++ b/sponsors/tests/test_forms.py @@ -1,3 +1,6 @@ +from pathlib import Path + +from django.core.files.uploadedfile import SimpleUploadedFile from model_bakery import baker from django.conf import settings @@ -438,6 +441,21 @@ def test_create_sponsor_with_valid_data_for_non_required_inputs( self.assertEqual(sponsor.landing_page_url, "https://companyx.com") self.assertEqual(sponsor.twitter_handle, "@companyx") + def test_create_sponsor_with_svg_for_print_logo( + self, + ): + tick_svg = Path(settings.STATICFILES_DIRS[0]) / "img"/"sponsors"/"tick.svg" + with tick_svg.open("rb") as fd: + uploaded_svg = SimpleUploadedFile("tick.svg", fd.read()) + self.files["print_logo"] = uploaded_svg + + form = SponsorshipApplicationForm(self.data, self.files) + self.assertTrue(form.is_valid(), form.errors) + + sponsor = form.save() + + self.assertTrue(sponsor.print_logo) + def test_use_previous_user_sponsor(self): contact = baker.make(SponsorContact, user__email="foo@foo.com") self.data = {"sponsor": contact.sponsor.id} From db9d241e2d1f721785dc8df57268e612e09cb146 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Fri, 5 Jan 2024 08:41:41 -0500 Subject: [PATCH 043/235] update sponsor voucher fulfillment for 2024 --- .../create_pycon_vouchers_for_sponsors.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py b/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py index f8b99855a..3e3b4973d 100644 --- a/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py +++ b/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py @@ -20,22 +20,26 @@ ) BENEFITS = { - 121: { - "internal_name": "full_conference_passes_2023_code", + 183: { + "internal_name": "full_conference_passes_code_2024", "voucher_type": "SPNS_COMP_", }, - 139: { - "internal_name": "expo_hall_only_passes_2023_code", + 201: { + "internal_name": "expo_hall_only_passes_code_2024", "voucher_type": "SPNS_EXPO_COMP_", }, - 148: { - "internal_name": "additional_full_conference_passes_2023_code", + 208: { + "internal_name": "additional_full_conference_passes_code_2024", "voucher_type": "SPNS_ADDL_DISC_REG_", }, - 166: { - "internal_name": "online_only_conference_passes_2023_code", + 225: { + "internal_name": "online_only_conference_passes_2024", "voucher_type": "SPNS_ONLINE_COMP_", }, + 237: { + "internal_name": "additional_expo_hall_only_passes_2024", + "voucher_type": "SPNS_EXPO_DISC_", + }, } From 9b4deddbd43cf6e5518a72ddcbc4c94c7b6d487f Mon Sep 17 00:00:00 2001 From: Jessie <70440141+jessiebelle@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:16:58 +0200 Subject: [PATCH 044/235] add new incorporation fields to form and sponsor model (#2351) * adding new fields to form and sponsor model * adding new optional fields to update sponsor application form * fix migrations * modifying existing tests to assert new fields are correctly saved * Re-structure and re-order sponsor information form * update and refactor of new_sponsorship_application_form to be usable for editing * remove migration * new migration file added * merge * add migration * fix tests to reflect update in template --------- Co-authored-by: Ee Durbin --- sponsors/forms.py | 11 +- .../migrations/0100_auto_20240107_1054.py | 29 ++++ sponsors/models/sponsors.py | 9 +- sponsors/tests/test_forms.py | 8 +- .../new_sponsorship_application_form.html | 126 +++++++++++++----- templates/users/sponsor_info_update.html | 55 +++++++- users/tests/test_views.py | 2 +- users/views.py | 2 +- 8 files changed, 199 insertions(+), 43 deletions(-) create mode 100644 sponsors/migrations/0100_auto_20240107_1054.py diff --git a/sponsors/forms.py b/sponsors/forms.py index 5a31605af..21258f3b2 100644 --- a/sponsors/forms.py +++ b/sponsors/forms.py @@ -253,10 +253,17 @@ class SponsorshipApplicationForm(forms.Form): state = forms.CharField( label="State/Province/Region", max_length=64, required=False ) + state_of_incorporation = forms.CharField( + label="State of incorporation", help_text="US only, If different than mailing address", max_length=64, required=False + ) postal_code = forms.CharField( label="Zip/Postal Code", max_length=64, required=False ) - country = CountryField().formfield(required=False) + country = CountryField().formfield(required=False, help_text="For mailing/contact purposes") + + country_of_incorporation = CountryField().formfield( + label="Country of incorporation", help_text="For contractual purposes", required=False + ) def __init__(self, *args, **kwargs): self.user = kwargs.pop("user", None) @@ -373,6 +380,8 @@ def save(self): landing_page_url=self.cleaned_data.get("landing_page_url", ""), twitter_handle=self.cleaned_data["twitter_handle"], print_logo=self.cleaned_data.get("print_logo"), + country_of_incorporation=self.cleaned_data.get("country_of_incorporation", ""), + state_of_incorporation=self.cleaned_data.get("state_of_incorporation", ""), ) contacts = [f.save(commit=False) for f in self.contacts_formset.forms] for contact in contacts: diff --git a/sponsors/migrations/0100_auto_20240107_1054.py b/sponsors/migrations/0100_auto_20240107_1054.py new file mode 100644 index 000000000..8bad2bc92 --- /dev/null +++ b/sponsors/migrations/0100_auto_20240107_1054.py @@ -0,0 +1,29 @@ +# Generated by Django 2.2.24 on 2024-01-07 10:54 + +from django.db import migrations, models +import django_countries.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0099_auto_20231224_1854'), + ] + + operations = [ + migrations.AddField( + model_name='sponsor', + name='country_of_incorporation', + field=django_countries.fields.CountryField(blank=True, help_text='For contractual purposes', max_length=2, null=True, verbose_name='Country of incorporation (If different)'), + ), + migrations.AddField( + model_name='sponsor', + name='state_of_incorporation', + field=models.CharField(blank=True, default='', max_length=64, null=True, verbose_name='US only: State of incorporation (If different)'), + ), + migrations.AlterField( + model_name='sponsor', + name='country', + field=django_countries.fields.CountryField(default='', help_text='For mailing/contact purposes', max_length=2), + ), + ] diff --git a/sponsors/models/sponsors.py b/sponsors/models/sponsors.py index eee7f585e..ba0cff83d 100644 --- a/sponsors/models/sponsors.py +++ b/sponsors/models/sponsors.py @@ -73,8 +73,15 @@ class Sponsor(ContentManageable): postal_code = models.CharField( verbose_name="Zip/Postal Code", max_length=64, default="" ) - country = CountryField(default="") + country = CountryField(default="", help_text="For mailing/contact purposes") assets = GenericRelation(GenericAsset) + country_of_incorporation = CountryField( + verbose_name="Country of incorporation (If different)", help_text="For contractual purposes", blank=True, null=True + ) + state_of_incorporation = models.CharField( + verbose_name="US only: State of incorporation (If different)", + max_length=64, blank=True, null=True, default="" + ) class Meta: verbose_name = "sponsor" diff --git a/sponsors/tests/test_forms.py b/sponsors/tests/test_forms.py index 123dc1729..49b0515cd 100644 --- a/sponsors/tests/test_forms.py +++ b/sponsors/tests/test_forms.py @@ -423,14 +423,18 @@ def test_create_sponsor_with_valid_data(self): def test_create_sponsor_with_valid_data_for_non_required_inputs( self, ): + user = baker.make(settings.AUTH_USER_MODEL) + self.data["description"] = "Important company" self.data["landing_page_url"] = "https://companyx.com" self.data["twitter_handle"] = "@companyx" + self.data["country_of_incorporation"] = "US" + self.data["state_of_incorporation"] = "NY" self.files["print_logo"] = get_static_image_file_as_upload( "psf-logo_print.png", "logo_print.png" ) - form = SponsorshipApplicationForm(self.data, self.files) + form = SponsorshipApplicationForm(self.data, self.files, user=user) self.assertTrue(form.is_valid(), form.errors) sponsor = form.save() @@ -440,6 +444,8 @@ def test_create_sponsor_with_valid_data_for_non_required_inputs( self.assertFalse(form.user_with_previous_sponsors) self.assertEqual(sponsor.landing_page_url, "https://companyx.com") self.assertEqual(sponsor.twitter_handle, "@companyx") + self.assertEqual(sponsor.country_of_incorporation, "US") + self.assertEqual(sponsor.state_of_incorporation, "NY") def test_create_sponsor_with_svg_for_print_logo( self, diff --git a/templates/sponsors/new_sponsorship_application_form.html b/templates/sponsors/new_sponsorship_application_form.html index 9f7597650..1610807e8 100644 --- a/templates/sponsors/new_sponsorship_application_form.html +++ b/templates/sponsors/new_sponsorship_application_form.html @@ -2,15 +2,19 @@ {% load boxes widget_tweaks %} {% load humanize %} {% load sponsors %} +{% block page_title %}Sponsorship Information{% endblock %} -{% block page_title %}Submit Sponsorship Information{% endblock %} {% block content %}
    -

    Submit Sponsorship Information

    -
    +{% if sponsor %} +
    +

    Edit {{sponsor}}

    +
    +{% else %} +
    {% if sponsorship_package %}

    You selected the {{ sponsorship_package.name }} package {% if sponsorship_price %}costing ${{ sponsorship_price|intcomma }} USD {% endif %}and the following benefits: @@ -34,6 +38,10 @@

    Submit Sponsorship Information

    | Back to select benefits
    +

    Submit Sponsorship Information

    +{% endif %} + + {% if form.errors %} The form has one or more errors {{ form.non_field_errors }} @@ -53,6 +61,8 @@

    Submit Sponsorship Information

    +

    Basics

    +

    {% render_field form.name %} @@ -62,6 +72,33 @@

    Submit Sponsorship Information

    {% endif %}

    + +
    +
    +

    + + {% render_field form.country_of_incorporation %} + {% if form.country_of_incorporation.help_text %} +
    + {{ form.country_of_incorporation.help_text }} + {% endif %} +

    +
    + +
    +

    + + {% render_field form.state %} + {% if form.state_of_incorporation.help_text %} +
    + {{ form.state_of_incorporation.help_text }} + {% endif %} +

    +
    +
    +

    {% render_field form.description %} @@ -95,14 +132,39 @@

    Submit Sponsorship Information

    -

    - - {% render_field form.country %} - {% if form.country.help_text %} -
    - {{ form.country.help_text }} - {% endif %} -

    +
    +
    +

    + + {% render_field form.web_logo %} + {% if sponsor.web_logo %} +

    Currently: {{ sponsor.web_logo.name }}

    + {% endif %} + {% if form.web_logo.help_text %} +
    + {{ form.web_logo.help_text }} + {% endif %} +

    +
    + +
    +

    + + {% render_field form.print_logo %} + {% if sponsor.print_logo %} +

    Currently: {{ sponsor.print_logo.name }}

    + {% endif %} + {% if form.print_logo.help_text %} +
    + {{ form.print_logo.help_text }} + {% endif %} +

    +
    +
    + +
    + +

    Mailing and Contact

    @@ -167,11 +229,11 @@

    Submit Sponsorship Information

    - - {% render_field form.primary_phone %} - {% if form.primary_phone.help_text %} + + {% render_field form.country %} + {% if form.country.help_text %}
    - {{ form.primary_phone.help_text }} + {{ form.country.help_text }} {% endif %}

    @@ -179,25 +241,14 @@

    Submit Sponsorship Information

    -

    - - {% render_field form.web_logo %} - {% if form.web_logo.help_text %} -
    - {{ form.web_logo.help_text }} - {% endif %} -

    -
    - -
    -

    - - {% render_field form.print_logo %} - {% if form.print_logo.help_text %} -
    - {{ form.print_logo.help_text }} - {% endif %} -

    +

    + + {% render_field form.primary_phone %} + {% if form.primary_phone.help_text %} +
    + {{ form.primary_phone.help_text }} + {% endif %} +

    @@ -216,11 +267,16 @@

    Contacts

    - +{% if sponsor %} +
    + +
    + {% else %}
    + {% endif %}
    {% endblock content %} diff --git a/templates/users/sponsor_info_update.html b/templates/users/sponsor_info_update.html index 3ae2e720c..e1984a28c 100644 --- a/templates/users/sponsor_info_update.html +++ b/templates/users/sponsor_info_update.html @@ -17,6 +17,7 @@ {% block user_content %}

    Edit {{ sponsor }}

    +

    Basics

    {% if form.errors %} The form has one or more errors @@ -36,7 +37,31 @@

    Sponsor Information

    {% endif %} {% render_field form.name %}

    +
    +
    +

    + + {% render_field form.country_of_incorporation %} + {% if form.country_of_incorporation.help_text %} +
    + {{ form.country_of_incorporation.help_text }} + {% endif %} +

    +
    +
    +

    + + {% render_field form.state %} + {% if form.state_of_incorporation.help_text %} +
    + {{ form.state_of_incorporation.help_text }} + {% endif %} +

    +
    +

    @@ -69,16 +94,29 @@

    Sponsor Information

    - +
    +

    {% render_field form.country %} {% if form.country.help_text %} -
    {{ form.country.help_text }} {% endif %}

    +
    +
    +

    + + {% render_field form.country_of_incorporation %} + {% if form.country_of_incorporation.help_text %} +
    + {{ form.country_of_incorporation.help_text }} + {% endif %} +

    +
    +
    @@ -131,8 +169,19 @@

    Sponsor Information

    {{ form.state.help_text }} {% endif %}

    +
    +
    +

    + + {% render_field form.state %} + {% if form.state_of_incorporation.help_text %} +
    + {{ form.state_of_incorporation.help_text }} + {% endif %} +

    +
    -
    diff --git a/users/tests/test_views.py b/users/tests/test_views.py index 952425c98..13c226e5f 100644 --- a/users/tests/test_views.py +++ b/users/tests/test_views.py @@ -489,7 +489,7 @@ def test_display_template_with_sponsor_info(self): response = self.client.get(self.url) context = response.context - self.assertTemplateUsed(response, "users/sponsor_info_update.html") + self.assertTemplateUsed(response, "sponsors/new_sponsorship_application_form.html") self.assertEqual(context["sponsor"], self.sponsor) self.assertIsInstance(context["form"], SponsorUpdateForm) diff --git a/users/views.py b/users/views.py index 517c1419a..c56dbace4 100644 --- a/users/views.py +++ b/users/views.py @@ -264,7 +264,7 @@ def get_context_data(self, *args, **kwargs): @method_decorator(login_required(login_url=settings.LOGIN_URL), name="dispatch") class UpdateSponsorInfoView(UpdateView): object_name = "sponsor" - template_name = 'users/sponsor_info_update.html' + template_name = 'sponsors/new_sponsorship_application_form.html' form_class = SponsorUpdateForm def get_queryset(self): From 04751c86869f9653b65230a7e0028e7d3abd6009 Mon Sep 17 00:00:00 2001 From: Jessie <70440141+jessiebelle@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:24:47 +0200 Subject: [PATCH 045/235] 2342 display only benefits associated with the year of the sponsorship package being edited (#2356) * WIP * WIP * WIP * we finally got there with the qs filter * removing redundant tests * removing unused imports * missed one --- sponsors/admin.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sponsors/admin.py b/sponsors/admin.py index d6601140f..88aff8c57 100644 --- a/sponsors/admin.py +++ b/sponsors/admin.py @@ -246,9 +246,13 @@ def has_delete_permission(self, request, obj=None): return True return obj.open_for_editing - def get_queryset(self, *args, **kwargs): - qs = super().get_queryset(*args, **kwargs) - return qs.select_related("sponsorship_benefit__program", "program") + def get_queryset(self, request): + #filters the available benefits by the benefits for the year of the sponsorship + match = request.resolver_match + sponsorship = self.parent_model.objects.get(pk=match.kwargs["object_id"]) + year = sponsorship.year + + return super().get_queryset(request).filter(sponsorship_benefit__year=year) class TargetableEmailBenefitsFilter(admin.SimpleListFilter): From 0d5432a04dbfb78b582c808856f912b412b1201b Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Wed, 17 Jan 2024 13:18:02 -0600 Subject: [PATCH 046/235] Add support for hosting SPDX-2 SBOMs alongside release artifacts (#2359) --- downloads/api.py | 2 +- .../0010_releasefile_sbom_spdx2_file.py | 18 ++++++++++++++++++ downloads/models.py | 3 +++ downloads/serializers.py | 1 + downloads/templatetags/download_tags.py | 5 +++++ templates/downloads/release_detail.html | 7 +++++++ 6 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 downloads/migrations/0010_releasefile_sbom_spdx2_file.py diff --git a/downloads/api.py b/downloads/api.py index e58023dbf..73eb9b7bf 100644 --- a/downloads/api.py +++ b/downloads/api.py @@ -69,7 +69,7 @@ class Meta(GenericResource.Meta): 'creator', 'last_modified_by', 'os', 'release', 'description', 'is_source', 'url', 'gpg_signature_file', 'md5_sum', 'filesize', 'download_button', 'sigstore_signature_file', - 'sigstore_cert_file', 'sigstore_bundle_file', + 'sigstore_cert_file', 'sigstore_bundle_file', 'sbom_spdx2_file', ] filtering = { 'name': ('exact',), diff --git a/downloads/migrations/0010_releasefile_sbom_spdx2_file.py b/downloads/migrations/0010_releasefile_sbom_spdx2_file.py new file mode 100644 index 000000000..f3a4784e9 --- /dev/null +++ b/downloads/migrations/0010_releasefile_sbom_spdx2_file.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2024-01-12 21:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('downloads', '0009_releasefile_sigstore_bundle_file'), + ] + + operations = [ + migrations.AddField( + model_name='releasefile', + name='sbom_spdx2_file', + field=models.URLField(blank=True, help_text='SPDX-2 SBOM URL', verbose_name='SPDX-2 SBOM URL'), + ), + ] diff --git a/downloads/models.py b/downloads/models.py index 6d91534ac..4a9c5781c 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -332,6 +332,9 @@ class ReleaseFile(ContentManageable, NameSlugModel): sigstore_bundle_file = models.URLField( "Sigstore Bundle URL", blank=True, help_text="Sigstore Bundle URL" ) + sbom_spdx2_file = models.URLField( + "SPDX-2 SBOM URL", blank=True, help_text="SPDX-2 SBOM URL" + ) md5_sum = models.CharField('MD5 Sum', max_length=200, blank=True) filesize = models.IntegerField(default=0) download_button = models.BooleanField(default=False, help_text="Use for the supernav download button for this OS") diff --git a/downloads/serializers.py b/downloads/serializers.py index 67bde5b5c..1ff57049f 100644 --- a/downloads/serializers.py +++ b/downloads/serializers.py @@ -49,4 +49,5 @@ class Meta: 'sigstore_signature_file', 'sigstore_cert_file', 'sigstore_bundle_file', + 'sbom_spdx2_file', ) diff --git a/downloads/templatetags/download_tags.py b/downloads/templatetags/download_tags.py index fb3496787..57004ccb4 100644 --- a/downloads/templatetags/download_tags.py +++ b/downloads/templatetags/download_tags.py @@ -14,3 +14,8 @@ def has_sigstore_materials(files): f.sigstore_bundle_file or f.sigstore_cert_file or f.sigstore_signature_file for f in files ) + + +@register.filter +def has_sbom(files): + return any(f.sbom_spdx2_file for f in files) diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index b68b69a66..730b9b273 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -2,6 +2,7 @@ {% load boxes %} {% load sitetree %} {% load has_sigstore_materials from download_tags %} +{% load has_sbom from download_tags %} {% block body_attributes %}class="python downloads"{% endblock %} @@ -53,6 +54,9 @@

    Files

    {% if release_files|has_sigstore_materials %} Sigstore {% endif %} + {% if release_files|has_sbom %} + SBOM + {% endif %} @@ -72,6 +76,9 @@

    Files

    {% if f.sigstore_signature_file %}SIG{% endif %} {% endif %} {% endif %} + {% if release_files|has_sbom %} + {% if f.sbom_spdx2_file %}SPDX{% endif %} + {% endif %} {% endfor %} From cde08ed7a689d77ce2f723abd9b3681f1b2b3080 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Wed, 7 Feb 2024 09:22:42 -0600 Subject: [PATCH 047/235] Link to SBOM user documentation from release detail page (#2363) --- templates/downloads/release_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 730b9b273..47ef47ce8 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -55,7 +55,7 @@

    Files

    Sigstore {% endif %} {% if release_files|has_sbom %} - SBOM + SBOM {% endif %} From 096ac337e1ccef8b2659699885a60b9c71d7fbd7 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Fri, 9 Feb 2024 08:42:26 -0500 Subject: [PATCH 048/235] LinkedIn stuff (#2367) * Adds linkedin to socialize * Adds linkedin to sponsor profile Closes #2365 --- sponsors/forms.py | 6 ++++++ .../0101_sponsor_linked_in_page_url.py | 18 ++++++++++++++++++ sponsors/models/sponsors.py | 6 ++++++ static/sass/style.css | 17 +++++++++++++++++ static/sass/style.scss | 18 ++++++++++++++++++ templates/base.html | 7 ++++--- .../new_sponsorship_application_form.html | 11 +++++++++++ templates/users/sponsor_info_update.html | 12 ++++++++++++ 8 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 sponsors/migrations/0101_sponsor_linked_in_page_url.py diff --git a/sponsors/forms.py b/sponsors/forms.py index 21258f3b2..4ced017c9 100644 --- a/sponsors/forms.py +++ b/sponsors/forms.py @@ -221,6 +221,11 @@ class SponsorshipApplicationForm(forms.Form): help_text="For promotion of your sponsorship on social media.", required=False, ) + linked_in_page_url = forms.URLField( + label="LinkedIn page URL", + help_text="URL for your LinkedIn page.", + required=False, + ) web_logo = forms.ImageField( label="Sponsor web logo", help_text="For display on our sponsor webpage. High resolution PNG or JPG, smallest dimension no less than 256px", @@ -379,6 +384,7 @@ def save(self): description=self.cleaned_data.get("description", ""), landing_page_url=self.cleaned_data.get("landing_page_url", ""), twitter_handle=self.cleaned_data["twitter_handle"], + linked_in_page_url=self.cleaned_data["linked_in_page_url"], print_logo=self.cleaned_data.get("print_logo"), country_of_incorporation=self.cleaned_data.get("country_of_incorporation", ""), state_of_incorporation=self.cleaned_data.get("state_of_incorporation", ""), diff --git a/sponsors/migrations/0101_sponsor_linked_in_page_url.py b/sponsors/migrations/0101_sponsor_linked_in_page_url.py new file mode 100644 index 000000000..61041a08e --- /dev/null +++ b/sponsors/migrations/0101_sponsor_linked_in_page_url.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.24 on 2024-02-09 13:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0100_auto_20240107_1054'), + ] + + operations = [ + migrations.AddField( + model_name='sponsor', + name='linked_in_page_url', + field=models.URLField(blank=True, help_text='URL for your LinkedIn page.', null=True, verbose_name='LinkedIn page URL'), + ), + ] diff --git a/sponsors/models/sponsors.py b/sponsors/models/sponsors.py index ba0cff83d..78d5d6e32 100644 --- a/sponsors/models/sponsors.py +++ b/sponsors/models/sponsors.py @@ -44,6 +44,12 @@ class Sponsor(ContentManageable): null=True, verbose_name="Twitter handle", ) + linked_in_page_url = models.URLField( + blank=True, + null=True, + verbose_name="LinkedIn page URL", + help_text="URL for your LinkedIn page." + ) web_logo = models.ImageField( upload_to="sponsor_web_logos", verbose_name="Web logo", diff --git a/static/sass/style.css b/static/sass/style.css index c3d2bb5f9..a58863817 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -3405,6 +3405,23 @@ span.highlighted { .icon-megaphone span, .icon-python-alt span, .icon-pypi span, .icon-news span, .icon-moderate span, .icon-mercurial span, .icon-jobs span, .icon-help span, .icon-download span, .icon-documentation span, .icon-community span, .icon-code span, .icon-close span, .icon-calendar span, .icon-beginner span, .icon-advanced span, .icon-sitemap span, .icon-search span, .icon-search-alt span, .icon-python span, .icon-github span, .icon-get-started span, .icon-feed span, .icon-facebook span, .icon-email span, .icon-arrow-up span, .icon-arrow-right span, .icon-arrow-left span, .icon-arrow-down span, .errorlist:before span, .icon-freenode span, .icon-alert span, .icon-versions span, .icon-twitter span, .icon-thumbs-up span, .icon-thumbs-down span, .icon-text-resize span, .icon-success-stories span, .icon-statistics span, .icon-stack-overflow span, .icon-mastodon span { display: none; } +.fa { + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + margin-right: .5em; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + /* Hide a unicode fallback character when we supply it by default. + * In fonts.scss, we hide the icon and show the fallback when other conditions are not met + */ } + .fa { + display: none; } + /* Keep this at the bottom since it will create a huge set of data */ /* * Would have liked to use Compass' built-in font-face mixin with the inline-font-files() helper, but it seems to be BROKEN in older versions! diff --git a/static/sass/style.scss b/static/sass/style.scss index 2e0ea8981..4fd9a3efd 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -2426,6 +2426,24 @@ span.highlighted { */ span { display: none; } } +.fa { + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + margin-right: .5em; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Hide a unicode fallback character when we supply it by default. + * In fonts.scss, we hide the icon and show the fallback when other conditions are not met + */ + span { display: none; } +} /* Keep this at the bottom since it will create a huge set of data */ @import "fonts"; diff --git a/templates/base.html b/templates/base.html index 27daceb50..cfa0f34ce 100644 --- a/templates/base.html +++ b/templates/base.html @@ -41,6 +41,7 @@ {% stylesheet 'style' %} {% stylesheet 'mq' %} + {% stylesheet 'font-awesome' %} {% comment %} {# equivalent to: #} @@ -235,10 +236,10 @@

  • Socialize
  • diff --git a/templates/sponsors/new_sponsorship_application_form.html b/templates/sponsors/new_sponsorship_application_form.html index 1610807e8..c95bdf4ea 100644 --- a/templates/sponsors/new_sponsorship_application_form.html +++ b/templates/sponsors/new_sponsorship_application_form.html @@ -130,6 +130,17 @@

    Basics

    {% endif %}

    + +
    +

    + + {% render_field form.linked_in_page_url%} + {% if form.linked_in_page_url.help_text %} +
    + {{ form.linked_in_page_url.help_text }} + {% endif %} +

    +
    diff --git a/templates/users/sponsor_info_update.html b/templates/users/sponsor_info_update.html index e1984a28c..1312fb782 100644 --- a/templates/users/sponsor_info_update.html +++ b/templates/users/sponsor_info_update.html @@ -93,6 +93,18 @@

    Sponsor Information

    {% endif %}

    + +
    +

    + + {% render_field form.linked_in_page_url%} + {% if form.linked_in_page_url.help_text %} +
    + {{ form.linked_in_page_url.help_text }} + {% endif %} +

    +
    From 8f37034ec1399af8d42a2291c4053e81ea82c39a Mon Sep 17 00:00:00 2001 From: Jon Clements Date: Wed, 14 Feb 2024 11:22:33 +0000 Subject: [PATCH 049/235] Update job_detail.html (#2298) Explicity escape the job description for the meta og:description where the description contains html which can throw off the rendering of the page... See https://www.python.org/jobs/7314/ for example. --- templates/jobs/job_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/jobs/job_detail.html b/templates/jobs/job_detail.html index 82ddd3f58..be073e551 100644 --- a/templates/jobs/job_detail.html +++ b/templates/jobs/job_detail.html @@ -8,7 +8,7 @@ {% block content_attributes %}with-right-sidebar{% endblock %} {% block og_title %}Job: {{ object.job_title }} at {{ object.company_name }}{% endblock %} -{% block og-descript %}{{ object.description|truncatechars:200 }}{% endblock %} +{% block og-descript %}{{ object.description|escape|truncatechars:200 }}{% endblock %} {% block content %} {% load companies %} From bd3f080dbe3f4b53c0f5464b269917ec34754beb Mon Sep 17 00:00:00 2001 From: cfsok <33849525+cfsok@users.noreply.github.com> Date: Wed, 21 Feb 2024 22:53:37 +0900 Subject: [PATCH 050/235] Add DearPyGui to home page (#2362) --- fixtures/boxes.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fixtures/boxes.json b/fixtures/boxes.json index b0e965011..bc3816cc7 100644 --- a/fixtures/boxes.json +++ b/fixtures/boxes.json @@ -174,9 +174,9 @@ "created": "2013-10-28T19:27:20.963Z", "updated": "2022-01-05T15:42:59.645Z", "label": "widget-use-python-for", - "content": "

    Use Python for…

    \r\n

    More

    \r\n\r\n", + "content": "

    Use Python for…

    \r\n

    More

    \r\n\r\n", "content_markup_type": "html", - "_content_rendered": "

    Use Python for…

    \r\n

    More

    \r\n\r\n" + "_content_rendered": "

    Use Python for…

    \r\n

    More

    \r\n\r\n" } }, { From c1b800bc490b770f7cf2ec50d7820c96607dbb8e Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Wed, 21 Feb 2024 08:54:30 -0500 Subject: [PATCH 051/235] `download:download_release_detail` view: Display file sizes with human-readable units (#2354) Make the release file sizes more readable by passing them through the [filesizeformat filter][1]. [1]: https://docs.djangoproject.com/en/2.2/ref/templates/builtins/#filesizeformat --- downloads/tests/base.py | 1 + downloads/tests/test_views.py | 3 +++ templates/downloads/release_detail.html | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/downloads/tests/base.py b/downloads/tests/base.py index e19ffe03a..bcb7905c4 100644 --- a/downloads/tests/base.py +++ b/downloads/tests/base.py @@ -64,6 +64,7 @@ def setUp(self): is_source=True, description='Gzipped source', url='ftp/python/2.7.5/Python-2.7.5.tgz', + filesize=12345678, ) self.draft_release = Release.objects.create( diff --git a/downloads/tests/test_views.py b/downloads/tests/test_views.py index 75fe76693..50270c556 100644 --- a/downloads/tests/test_views.py +++ b/downloads/tests/test_views.py @@ -40,6 +40,9 @@ def test_download_release_detail(self): response = self.client.get(url) self.assertEqual(response.status_code, 200) + with self.subTest("Release file sizes should be human-readable"): + self.assertInHTML("11.8 MB", response.content.decode()) + url = reverse('download:download_release_detail', kwargs={'release_slug': 'fake_slug'}) response = self.client.get(url) self.assertEqual(response.status_code, 404) diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 47ef47ce8..59ffe2d7a 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -66,7 +66,7 @@

    Files

    {{ f.os.name }} {{ f.description }} {{ f.md5_sum }} - {{ f.filesize }} + {{ f.filesize|filesizeformat }} {% if f.gpg_signature_file %}SIG{% endif %} {% if release_files|has_sigstore_materials %} {% if f.sigstore_bundle_file %} From a4990b711ccd6e34e87d8d4b97169846fba5414f Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Wed, 21 Feb 2024 08:55:08 -0500 Subject: [PATCH 052/235] Move to pandoc for rendering sponsorship contracts (#2343) * Move to pandoc for rendering sponsorship contracts * use renewal template if applicable * consistency * formatting tweaks * bit cleaner names for files * grinding out formatting --- .github/workflows/ci.yml | 12 + Aptfile | 0 Dockerfile | 42 ++- base-requirements.txt | 7 +- pydotorg/settings/base.py | 1 - sponsors/contracts.py | 89 ++++++ sponsors/pandoc_filters/__init__.py | 0 sponsors/pandoc_filters/pagebreak.py | 90 ++++++ sponsors/pdf.py | 78 ----- sponsors/reference.docx | Bin 0 -> 12636 bytes sponsors/tests/test_contracts.py | 39 +++ sponsors/tests/test_pdf.py | 113 ------- sponsors/use_cases.py | 2 +- sponsors/views_admin.py | 2 +- .../sponsors/admin/contract-template.docx | Bin 15199 -> 0 bytes .../admin/contracts/renewal-agreement.md | 119 ++++++++ .../admin/contracts/sponsorship-agreement.md | 209 +++++++++++++ .../sponsors/admin/preview-contract.html | 283 ------------------ .../admin/renewal-contract-template.docx | Bin 9323 -> 0 bytes texlive.packages | 2 + 20 files changed, 605 insertions(+), 483 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/reference.docx 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/renewal-agreement.md create mode 100644 templates/sponsors/admin/contracts/sponsorship-agreement.md delete mode 100644 templates/sponsors/admin/preview-contract.html delete mode 100644 templates/sponsors/admin/renewal-contract-template.docx create mode 100644 texlive.packages diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97298ffca..28bfcc5ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,18 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v2 + - name: Install platform dependencies + run: | + sudo apt -y update + sudo apt -y install --no-install-recommends \ + texlive-latex-base \ + texlive-latex-recommended \ + texlive-plain-generic \ + lmodern + - name: Install pandoc + run: | + wget https://github.com/jgm/pandoc/releases/download/2.17.1.1/pandoc-2.17.1.1-1-amd64.deb + sudo dpkg -i pandoc-2.17.1.1-1-amd64.deb - uses: actions/setup-python@v2 with: python-version: 3.9.16 diff --git a/Aptfile b/Aptfile new file mode 100644 index 000000000..e69de29bb diff --git a/Dockerfile b/Dockerfile index 4d1046a98..f8aca13a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,47 @@ -FROM python:3.9-bullseye +FROM python:3.9-bookworm 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 \ + texlive-plain-generic \ + lmodern + +RUN case $(uname -m) in \ + "x86_64") ARCH=amd64 ;; \ + "aarch64") ARCH=arm64 ;; \ + esac \ + && wget --quiet https://github.com/jgm/pandoc/releases/download/2.17.1.1/pandoc-2.17.1.1-1-${ARCH}.deb \ + && dpkg -i pandoc-2.17.1.1-1-${ARCH}.deb + 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..2495153db 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==2.3.0 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..7e72cde39 --- /dev/null +++ b/sponsors/contracts.py @@ -0,0 +1,89 @@ +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") +REFERENCE_DOCX = os.path.join(dirname, "reference.docx") + + +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), + } + ) + previous_effective = contract.sponsorship.previous_effective_date + context["previous_effective"] = previous_effective if previous_effective else "UNKNOWN" + context["previous_effective_english_suffix"] = format(previous_effective, "S") if previous_effective else "UNKNOWN" + return context + + +def render_markdown_from_template(contract, **context): + template = "sponsors/admin/contracts/sponsorship-agreement.md" + if contract.sponsorship.renewal: + template = "sponsors/admin/contracts/renewal-agreement.md" + context = _contract_context(contract, **context) + return render_to_string(template, 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: + markdown = render_markdown_from_template(contract, **context) + pdf = pypandoc.convert_text( + markdown, "pdf", outputfile=pdf_file.name, format="md" + ) + 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-renewal' if contract.sponsorship.renewal else 'sponsorship-contract'}-{contract.sponsorship.sponsor.name.replace(' ', '-').replace('.', '')}.docx" + return response + + +def render_contract_to_docx_file(contract, **context): + markdown = render_markdown_from_template(contract, **context) + with tempfile.NamedTemporaryFile() as docx_file: + docx = pypandoc.convert_text( + markdown, + "docx", + outputfile=docx_file.name, + format="md", + filters=[DOCXPAGEBREAK_FILTER], + extra_args=[f"--reference-doc", REFERENCE_DOCX], + ) + 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 9855beee3..000000000 --- a/sponsors/pdf.py +++ /dev/null @@ -1,78 +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), - "renewal": contract.sponsorship.renewal, - }) - previous_effective = contract.sponsorship.previous_effective_date - context["previous_effective"] = previous_effective if previous_effective else "UNKNOWN" - context["previous_effective_english_suffix"] = format(previous_effective, "S") if previous_effective else None - 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): - context = _contract_context(contract, **context) - renewal = context["renewal"] - if renewal: - template = os.path.join(settings.TEMPLATES_DIR, "sponsors", "admin", "renewal-contract-template.docx") - else: - template = os.path.join(settings.TEMPLATES_DIR, "sponsors", "admin", "contract-template.docx") - doc = DocxTemplate(template) - 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/reference.docx b/sponsors/reference.docx new file mode 100644 index 0000000000000000000000000000000000000000..bf094ca4f3f29b535da99c765b735eaee71420d1 GIT binary patch literal 12636 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%0D(b%B@_FB(DPPG z&0-g(r3Rwn9F|ya1EjZf5p!cs^V5e5ZrET>?rO&LZgV<8>y|PaqQ=B8^hbNN#5@lG z0asUMKV77q?P6^*ryGXhe|7wL{4^-TYsU*g{?my6?{RnDL<%&%Rsewdqhdk#28DJ-dJc@MXwm#QOhEI1QdJ= zw+08&iV{+vYD)Ju&N{VUf0P7KmtpWi7ursN&SVQ)f$~RDk1=CqiBf_jvQG~b*O=CK zV3KAQLC4&IfxT~*kvnG%bXdDXpTFaQ-8)tQLGU>*qRLSx*I9R^xi-j4EM;a@4fV_M z=;yL$-Whpw-}3U2q)2lT2nm~`#`MbwIa^}|*lDs`in=xFY-z+XKz5-;T8E>9rKX#g z>-^fmKz7f25wC!%-DGwc6lQ)iXrmfORRo5Eedxs1pSC5{%MOX=wWp!}ubewA;a7+K zx@V-P>}F@;sPoecw@6#F=%S?N!;BwtzIKqtH5W3uX-;nT zlewkvbhrB8XW({gOBU!eI)sOecHd@EhQfxQ&jpbg?wV{`kxqv7J#0Tsi zhakfr$2j}4mb2PWz>AYFt;4HLx36?bs(bBRS4YEs(Ep8C4^55|`XO7b1`U=B- zMjiO^A(Kjq%7+I}B!-|f6P_}{B((Rd0>$Rn5#KY0O*l4aU7y1YX(UsB%r)M08I|3M z`dB?YzXhVZON#HBu7PLuMGVnIKU_AV>8XR-@@=~p^3WTA{0}L0m_50C<_`=PKSVZV zTWzKh2qZ=`^sPMGQD6qlt_e??PMEAqxP`lEo_9UY3Fka{ynMv%8SFvWM^j^U!T-l#<8{R#hl jTK;_ySJ8lg{2wf=ycFc?@B#rre*HCrzeXZ-Kd=55B-B^E literal 0 HcmV?d00001 diff --git a/sponsors/tests/test_contracts.py b/sponsors/tests/test_contracts.py new file mode 100644 index 000000000..c330c13a8 --- /dev/null +++ b/sponsors/tests/test_contracts.py @@ -0,0 +1,39 @@ +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()) + + # DOCX unit test + def test_render_response_with_docx_attachment(self): + request = Mock(HttpRequest) + self.contract.sponsorship.renewal = False + 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" + ) + + + # DOCX unit test + def test_render_renewal_response_with_docx_attachment(self): + request = Mock(HttpRequest) + self.contract.sponsorship.renewal = True + response = render_contract_to_docx_response(request, self.contract) + + self.assertEqual(response.get("Content-Disposition"), "attachment; filename=sponsorship-renewal-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 e4d140cf2..000000000 --- a/sponsors/tests/test_pdf.py +++ /dev/null @@ -1,113 +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": [], - "renewal": None, - "previous_effective": "UNKNOWN", - "previous_effective_english_suffix": None, - } - 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" - ) - - @patch("sponsors.pdf.DocxTemplate") - def test_render_response_with_docx_attachment__renewal(self, MockDocxTemplate): - renewal_contract = baker.make_recipe("sponsors.tests.empty_contract", sponsorship__start_date=date.today(), - sponsorship__renewal=True) - text = f"{renewal_contract.benefits_list.raw}\n\n**Legal Clauses**\n{renewal_contract.legal_clauses.raw}" - html = render_md(text) - renewal_context = { - "contract": renewal_contract, - "start_date": renewal_contract.sponsorship.start_date, - "start_day_english_suffix": format(self.contract.sponsorship.start_date, "S"), - "sponsor": renewal_contract.sponsorship.sponsor, - "sponsorship": renewal_contract.sponsorship, - "benefits": [], - "legal_clauses": [], - "renewal": True, - "previous_effective": "UNKNOWN", - "previous_effective_english_suffix": None, - } - renewal_template = "sponsors/admin/preview-contract.html" - - template = Path(settings.TEMPLATES_DIR) / "sponsors" / "admin" / "renewal-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, renewal_contract) - - MockDocxTemplate.assert_called_once_with(str(template.resolve())) - mocked_doc.render.assert_called_once_with(renewal_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 bbb6f2483..91271ff64 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 e9a808ccc..fd8631d3f 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/renewal-agreement.md b/templates/sponsors/admin/contracts/renewal-agreement.md new file mode 100644 index 000000000..3a401c9d7 --- /dev/null +++ b/templates/sponsors/admin/contracts/renewal-agreement.md @@ -0,0 +1,119 @@ +--- +title: SPONSORSHIP AGREEMENT RENEWAL +geometry: +- margin=1.25in +font-size: 12pt +pagestyle: empty +header-includes: +- \pagenumbering{gobble} +--- + +**THIS SPONSORSHIP AGREEMENT RENEWAL** (the **"Agreement"**) +is entered into and made effective as of the +{{start_date|date:"j"}}{{start_day_english_suffix}} of {{start_date|date:"F Y"}} +(the **"Effective Date"**), +by and between the **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 and the PSF previously entered into a Sponsorship Agreement +with the effective date of the +{{ previous_effective|date:"j" }}{{ previous_effective_english_suffix }} of {{ previous_effective|date:"F Y" }} +and a term of one year (the “Sponsorship Agreementâ€). + +**WHEREAS**, Sponsor wishes to renew its 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 to extend and amend the Sponsorship Agreement as follows: + +1. [**Replacement of the Exhibit**]{.underline} Exhibit A to the Sponsorship Agreement is replaced with Exhibit A below. + +1. [**Renewal**]{.underline} Approval and incorporation of this new exhibit with the previous Sponsor Benefits shall be considered written notice by Sponsor to the PSF that you wish to continue the terms of the Sponsorship Agreement for an additional year and to contribute the new Sponsorship Payment specified in Exhibit A, beginning on the Effective Date, as contemplated by Section 6 of the Sponsorship Agreement. + +  + + +### \[Signature Page Follows\] + +::: {.page-break} +\newpage +::: + +## SPONSORSHIP AGREEMENT RENEWAL + +**IN WITNESS WHEREOF**, the Parties hereto have duly executed this **Sponsorship Agreement Renewal** 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 RENEWAL + +### 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/contracts/sponsorship-agreement.md b/templates/sponsors/admin/contracts/sponsorship-agreement.md new file mode 100644 index 000000000..ee0d91ce3 --- /dev/null +++ b/templates/sponsors/admin/contracts/sponsorship-agreement.md @@ -0,0 +1,209 @@ +--- +title: SPONSORSHIP AGREEMENT +geometry: +- margin=1.25in +font-size: 12pt +pagestyle: empty +header-includes: +- \pagenumbering{gobble} +--- + +**THIS SPONSORSHIP AGREEMENT** (the **"Agreement"**) +is entered into and made effective as of the +{{start_date|date:"j"}}{{start_day_english_suffix}} of {{start_date|date:"F Y"}} +(the **"Effective Date"**), +by and between the **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**]{.underline}. Each of the above Recitals is incorporated into and is made a part of this Agreement. + +1. [**Exhibits Incorporated by Reference**]{.underline}. 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. + +1. [**Sponsorship Payment**]{.underline} 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. + +1. [**Acknowledgement of Sponsor**]{.underline} In return for the Sponsorship Payment, Sponsor will be entitled to receive the sponsorship package described in Exhibit A attached hereto (the "Sponsor Benefits"). + +1. [**Intellectual Property**]{.underline} 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. + + (a) [Grant of License by the PSF]{.underline} 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. + + (a) [Grant of License by Sponsor]{.underline} 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. + +1. [**Term**]{.underline} The Term of this Agreement will begin on the Effective Date 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. + +1. [**Termination**]{.underline} 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. + +1. [**Code of Conduct**]{.underline} 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/conduct) and/or the PyCon Code of Conduct (https://pycon.us/code-of-conduct), as applicable. The PSF reserves the right to eject from any event any Sponsor or representative violating those standards. + +1. [**Deadlines**]{.underline} 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. + +1. [**Assignment of Space**]{.underline} 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). + +1. [**Job Postings**]{.underline} 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. + +1. [**Representations and Warranties**]{.underline} 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. + +1. [**Successors and Assigns**]{.underline} 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. + +1. [**No Third-Party Beneficiaries**]{.underline} 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. + +1. [**Severability**]{.underline} 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. + +1. [**Confidential Information**]{.underline} 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. + +1. [**Independent Contractors**]{.underline} 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. + +1. [**Indemnification**]{.underline} 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. + +1. [**Notices**]{.underline} 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 %} + > {{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. + +  + + +### \[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: + + (a) [**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. + + (a) 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 %} diff --git a/templates/sponsors/admin/renewal-contract-template.docx b/templates/sponsors/admin/renewal-contract-template.docx deleted file mode 100644 index 3e36801a316f85a4a0484c7b4ed1a227a9fb4285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9323 zcma)C1yozxwhiuu;_hDD-QC@3X>kg{f;$us?iBY@+@-j?OM&99#hre*|Gj^E@Bi

    E*dJc2N$B6)ouG z9`pTi^LMS+F(X$}pO!fCS%)GHDHfE_P zwo<{g1{v?72%Hcn)>l~Kj9?t8hEbv#4;H(Maj}Ht@t0N;^&6Lc$WeLQ)K8pG*f@u9 zgmjfR=j4@pYYtlzr%>wz>w2J-<$MzQ6id_$tl7*FbVYP15c5C>(H7a5=utC~F;Hwx z`Ypxb(jNCYq$`INWBLk>)jl!LJtE@}1^QEPM}49jd2MJI+fQ62@oOkVDU~~wX z@jZ!VO56~JpGAv{UYasY6%fWPR?H?n_Epz49P%I;y~GN0a~B?4G5j;aTs$`{cEN;E z8Z?0`g(=+}?*dODU2mdomKoO>;?{tZvDLN!2h}XtrwZK;z0cSnz}TNRNWV)3HFDRQ z?#Ad#eZf95bf1bS%Al?Sxqn;jD+QZ!q1|L8Q^p^vU7D84ul55H0_@sWr0;9u?w%05 z(}fwERmHz7XxfYPY%alX!6rk!c7<}MpJQj<>)Nmi3ZqntWf|?H)Q;H%ulUw{zFX|eVxA; z-kGPI;0;NPxYK3*WHx%h@**W*#IjiQJ538<30%?pnh1}#+}WY4Ma^b6BuR0!v3hq6g25C=-dfJ`$ ziBdc%+V;ez0*JZa%E-#`d#9i`z?_8IvI}S&BTcZjeVXI62x2Zkls3Ze6%@E(2>3`< zaZOwthTYH+RBpf&v!x~^%);}uECklqF6lPHm>Z*%9d2wkpJkYot8>kYIXNQBzqstS zd%e4Wdx;$@u5WZI&umEkBO4gMvtjJy2(q>LgOJfm#7-8>z_lNR@ZT3T;9@3g!g=^L zuA`UhARKM`6~nzeDEyBjgGq#xrUW0wOVGZ*wrXU4LkD0)c}2r$`i0m5 zTXIj{+tYo{NBLJKDT`|^YNc^0{Zi(F18LP%s?lb z52g;5K=YSj{m@yoS`s z{1S&xPqt2zCd>j^^O9pSt?`hTqNEZCB!Rwm)*vV_@$a#uZu*sh-$hZGEL=4O3pT#0C8lIkE2PTaIM&Bm>Ic&eky+zib~l*aZ6-6P4$`5M(< zv30c@V(p+&wl2!#pN4fAWufV{>--$li3oj6Ln^m-sSmnsLTlXsu(BW^romB{Fy1&P zZ=`FJ7@H zfX@}`uSgJ70v_6k~Jm=MiNCwadqPa0lIH+{WYF$unwZPNA0 z`&|F4hX3X5YpEvL>8DgX*UY@n*V0Y8_a8ggerfTwRVKDJR7?4^RLkA;sog1N6iAl` zQUEguJE^G0>3!7igU-tJb%NV#4>I_m%M5Xb$n1`q5MKFxoSU(MH)uZA6JK3$;>CxY zD_b1?HE`+q7!5p%F3jx5=a&(OUXjemmmDjUEVO(Y2%hS(eQ{--8r78W=kWB#`X^U@ zDQ|zc@^g)IvM~jMUOf4TXiZ!sa-jQrBJq~`qFugc8HcU3#{nh8kRjg%Z%@Tipbw+@FJj@pQ;^%fpilG+bfy&}^^T01-puNHt;m7&K)BGd}1zbo$_!bHm z`A~HJg@cNa{n`)@IV-$mPGu>6Hu#3V$tbl2v7pX#-9 zhH(L)lFJb*ClABQXnbF77uS;N<)#(64XOC>Z=WOf z8L7dKn~dv=;KMfy1b7aF(NNcR^SP~)rmv)6+GVuIt{@+6G-&QVf-HuET58P?j&P{r zcn%oPfb5GQ#mchaH`q{8`U0B;wlqS}R>mK>im2xfy&oeEGb6NJ4vg4ONY9)j7sTin z5dC5S=>Ag_*#<`FK^g?U#)x-Cy1 z9~)#x_xmoRYOi&s8tz_=Q#rH}I2>2+3LXzF3jqpEcAJ#fbs%txI@sC{`iQ8{Cctv@ z;39t#M%ZESdwzpRfJ(x3M!R2^o$N7ikm+kM$~AhuBnBXo z?Xd~O5Xa}BfFU%R$ak#d1=g>1jJg5LAsw&@#pD*<-f)HiUpiLl-iMZ8y59OR;R7Et z$!(Ciao`ENM2f)CQi0Q7<_13D+ri1x?^&Vc6}^I&U@DQ4s{!MN(V;+2?ie1^a3J4H zRQl3kex~K%MAo%7$n>8-5@uDjH|r zf&5Gv8Nig6S8qYVsfU3V}Pso{i@m3 zBa3oZ;F%3th!HRy0OG5?$z`XQoVW^F4(;oui^}!xknwK33fe?Nyuqy*lEgHJ0XiJm z38X=~?2?Ve??G#JDQR`sY{l3ipO@|Fr$$oF#-Sx=ld4Qym$%p^jDCRmt*RGX!<4OT zdXifd$2Z#1D^JJ$!k4v7yp^4|jxEkPCsN<>$Gyg)P$y(;*^uafg()#DX@B}*3KLr* zBGYj!j+bPYG58X!JfDhWno4eMnh zq8=i^&9fn~onIF^6KB{b3nLe9zb)wA5t?VWSB!0BkYc%HpaqN@kNNhLJ)@Eb+Jezo9?$JDr%QiH0K0!~C0Q2} zWd26RDuq|TFxn2KbC{{^B$6cPNDp~aeoHnasb`08s`8tzMRA=f4h-oUoLLB}}6FcO}t>E*LJ*6BlfX65XH7W z7{?#@Q28}#Y<%6F%H%G=8do91l{&k+3xcQ!v+LyUT!&66Y_-w#l1vV9iC36WBO|UJ zzN$gSH9s@__WEdbE&1mlTA5Q@*VLE+K27>1k1Y`22xJ(YlobpSIJj%_r^X18uF#<$ z!t$3HTgqA)OO>bLb&bvt6VtLnqsTTXu2rfs!tn>a;bg!0zCV=i+uTq+Z&kX03&L~^diWTv{@_Vw=ZN8E@21(DI$JG1jTD_@(cUH5j&4Lft#v$w|yJ2l$g zA6xl(sUzaLw)+-z(+M*?d4!5Mqm&|tU}CjruS6|?a$PZz!~@rMrwycI`q~k z#KSG{A5^LITC@nJ?wCL1hRiDMvo6x5F43;*37T*f@cQXw#OKp`l~dnAq^=gcYn1xQ zM0KpTJ}SK~v~=aBq;})6QBLbYn{2X3A8LuywwU5??pgwIb&mvHIg;2swCB^3AVd&sD^KRq`BpX~ zE@KlTQzMFla?^9WpomQ)Xr`c7NxL*Uu&wvq)NZ*V487mq1+2O<=J~yaSBx}3Y>H0n zKyw|zn{5c6%UwipL9rwZUaIc!W6AfS;s9~SNv~2=>O%<*eZP4OZPU|P_jz=0&YCOQ z_Gr);x~}^H%QZ!o)4p*G`-^)wNTNnqiI%ZP7wsx^Y~0GCveMevwNY4WQdxjd%5()G z2M*&MMhAMXk#O_ZyJN=JUdXiY7{Vv}2T493{WmqJv#p2N_9|HnjPcoJK74pJ|3gIy zM(AqkO}}reZvXnLZ6^PS*$;?eEHQ8&ElFv={fyF&6t#TADnWyb%U{XBL@z26*Hta1 z9qL7gP2B0k>Xx6&vfy0YqAd^Fgsl#=X*r1mW<*>VYy3Gp(ttC8iRF`5%?+2 zt#|8jQ^ohTQD>}jmjkw^RqMkmUCl%W8+%>7sq7VC^QjkSuZjVw5Nu%={_y2-KgRqU z0)2hS7AXOm$C$G1KJLavs}tV?o;)tmPLF6Ntk`3!zNm+bJ=%BTWSbYGEd*xKD z1++?%6y#>$aHPqDOZv(Y4Dg8#sF5fu8F3gVUx+nsE65HZ(vU;1+f(Vs=eQsRrV&=M zNtH?i?O~9-(EwZbHMWVrfRY9{G+uRlr`xY9!m{oTUlEH_9RSe_MHd|`o>X~VbO<^B zlZO4RDb@}948U#33YvDtMkw5V-lm^KBqSVZc)5k20*-2~FQ&Q69sNzF^$k%ge{8Wg zmsv4$J8fFf!YH=nc>GM|8MWk=ngj##cja@Zb2?Mvh(f-02-~$M&N1+M=6pQdQ>}8@ zHdE=3Kz>EpzWrG6TgEot;2p1%xPUO;K$zK}wQ`KkxP36PjopFC=JCe({7 zkRh1>K~f;XWWCB=A!2V-Y_iXg->^WBRCY{ya1^T7o7?r64>uY$0;=k4CsYa}0WLrj zuA|1jk=lFxL6|V0w~@`O>a40s&U0bRShN?4DT^Bi-L{$o4+ksC9cH^wLHx{e`;sj5 zXNtpH_VfXnluxa-AZ^#x8kDcEIg&Y@bZ4EhaJr?X3AW*$3LNQ(ws);FA5PjfXL^UQ zTJ@YAcmn9(t(Qn6H@Vc2yehBmfEo`zylCZJjm2Wrov0CEPC`LhnNXEcikF?Ho!AYs zl3a==g=p&E4ar67S1XZlSH#qpTicp#o0&!Rg*)&+x*l%0qQZ5fwWkbW10CoZm7;KW zE?rhYG}#LXtlRaHX80sywaAqe;zvD}vN0}IwI|L(;rGUl6SrpPaGp^7c+N_Xt;$h( zq)#R~rX;X~0Fe1Ei7a6vxFvF9H5~mG{V{g8T(iY-LWO0&E%uhqEOJ?DGMHWqt?%&g z+LZgNZ5{TO|7CCQVg!wMhkLGAkaVV7)xzQGq_Se-DNdT_;~88w<9Ac}`nBps<|Jkn zB1_)4fnlz9nr*lSZ-dl&>j&EginusO=zs{*Y-kEqzvkLvdWFPJATnK<`B~Z_4%9>! zHBKi>&3Lz?Y8q;KGLr{S&VZwJ#Kz-3$0bK3i$svkAM2;rK1%n+y@BQbWQZxdZ4jrq z!E9p8QWQNjgqeGjN}F}>15fI5^90GonMFMQ0BMKi?~aqZq*@5-f)Wd%t~WfDk(}QvO|4=V%>!45-F*v36kSRd z{7%Z3tu?C=+tf_!^^9U}C&|@Moy|AR`B~|nD!rQMj!-E!-q(r@zUN#mk&@c$0u^mg zTJfm_z&Bl|^f}&jb=|8|jbLu#CdVS7)|*4owG^2R30~!2hp#tK8Cpb*L8gA9UYsag za%I^$DuzK?xmdCj*xK4YIO3**t*$kYZhvfjgnXnfiaU8EdFd;>wjJcfd+xJ7#{W}a z0rlT~1xJvZwW;GvSD{Bs)pmge&3mOhER4kta~f24dgSGhHnI$ww1I{-G|8%ABr=l@&ZoL zt#0FyfZA?s-Ql`E97%FhU)rr$NgN_-rNX=d@e~6&fkh-BRtBlt6&2Z!-%6BGHUucI zJrVJ{-s~xgoa2ekt!t$UGG+BH<12}?sX71~x$$_|*~uDb(hyH%9X4UU*+@G3_<|u-lKe;6~^NxkS7u4K9)88uX_aOLMQl9aCzJt7tj1&%j`POB6(W^g-9i zJ4}_3RYD~?b|iQ9J)Ae%YkpI8h!eq~V7hEj3bv$*kbwv9hN5N#%%DG68h`Q407^Yt z1SKEkya!Vz0XiPNpMlsXPyjYiN}LhqhTrG{@>+jPk-M900Mc2m6tms{DDN2Hg2|<1 zY=YzRxn%tddI8;ogTMBuMfv_T^b?{b${^Pbp=%4p>d+C4!%1LOi{lc6Q@vqzNN20i z)U?ROvzTP1A5*c!;V13+D<@}WIp`cY8vF*S&M@~o`6zR-VvYy#w?+yT%PWpgoz;>T z5ZA?2^w-7&TlYGAoHG!LX#)7)6R*Tq>)~6!sZ=VrH_@aBI=Ddk z1T0;@i7(HDa=d5((Z8j@>!|XZUAP;o;Dho1H7h{EQ6gM&nm96MP6Xcnw4r22z!EH+ z`Rc02PmUArD1z+kMR%$blG?~xR$1!)B%)p(Rt=PXYs!J}OF%w3u*GRW0RUbo{}hmf z{|?Ci*86^M_x(%z8+vZaqe)(SOFsWw{z^`+_#5eI9-CKWY{K(+G7m1%aMB`hTP>Q0$RE_80tpR%OV(P-Z*VA@CnN1d2gm%$r)b7 z1|ub%9u++6dB}CGTwvrk-y!l^-%*O|VCIK|6|Q7_ParU4NuiWCEU#D3SsJ;WiV7Td z84ndwcWXp5XgIhTt(*V8!bwwb9w3yOQ1(EM*fUKz{3>^s*U9t{X15~PKAPyTUQCvb z23PM~M{tYW0tZ1vYHHHuuks7V-Xi0QC9 zA$7r9xdfekkCUINgG&lHmpzkDmzXo_K{?+#X3htj;n8&7&UY;xc@+i;?=QM&ue{7- zpDs2p!n5X+^L+e2v=K8~AV}l=2kSos(~)?2;InrHT?p5vw(p~@p z*vS$fLIhqh)tAePXiy=AsqBqjfq&g@zgITP)T1H*QI-yTw@9vnj;ILaI7sticn257 zK!#cXFh$w64(~RbYL@Mn`zSzl+LX<(S#s7o%0r`?4U4~kuUL~XYx&duU{*j!dwLX+ zGHhS()IL?n4rQ{U1Fe~MW zR)8gu1WcsePBlbAH3#)Fk^j$K>|ICfJUZ*F4hv6Vvu~O(j5AkueYGD-vlHKH1fQeu zAiN3W$2d_@ipJJ&sVYv|+^@{Yk@qP=iY*`wWrB8#djqn`jfLUUty9Q)5YR*A6ZYu2 zZ;&orieTO-dE4l);@6=vfPsJhn6jQ?J2p* zC}*HU`YG1A!x+IZp3~t-)+&UgDt+=vaHAkh1uHcXJ8@vRWoJ|(cQY=bIF5>kIfAKQ zlZza|0{CfKQ}nI5@*ZOfnECAcg1>Tw_PsxYScOZxdn=&F(~QBQB)*pp`{#t_G}}`L zeb!v=1j?2a+&CG^L;(04j#gJac+)07Da9YjNf5q&L%3Q1-F170asVl_7OJF=cf76#ZLQEFcegd+)(t7#EXnNpg zc3b48(B6MvYNTV0H+?wL8Gd_JaN!HzK?$5Vh}e8=ToW_Soh2Cc0RQ1uy{0wb=4!B& zc|(|~ES*rSy~Kz0e%6geEOZ?2^ITiQT{d$1C0Dnk61NZd^bdithgO!#>X|Ad*cYlG zATa@d?#%doL&D3>jKA7%`!xOz{9PM=$zy*S#q&@7uiXoOhyO0-z6j`l+Qf6p{2%zg zsnaQ_AWa}E1<@b9(drNaJc2L%5D|A%_}_bdILUH>`?B%*)c#&4DB@9^JK uz+Wd(o%mnyza-?p3o*ymGZjwy)a`s>Q`g|M! diff --git a/texlive.packages b/texlive.packages new file mode 100644 index 000000000..fc8668ea0 --- /dev/null +++ b/texlive.packages @@ -0,0 +1,2 @@ +xcolor +etoolbox From f3fa1fc16a5202fa3af019240d0285001475f0f9 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:56:08 +0200 Subject: [PATCH 053/235] Prioritise 64-bit downloads over 32-bit (#2311) Co-authored-by: Hugo van Kemenade --- downloads/templatetags/download_tags.py | 34 +++++++++++++++++++++++++ templates/downloads/os_list.html | 5 ++-- templates/downloads/release_detail.html | 3 ++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/downloads/templatetags/download_tags.py b/downloads/templatetags/download_tags.py index 57004ccb4..c72f6d58c 100644 --- a/downloads/templatetags/download_tags.py +++ b/downloads/templatetags/download_tags.py @@ -19,3 +19,37 @@ def has_sigstore_materials(files): @register.filter def has_sbom(files): return any(f.sbom_spdx2_file for f in files) + + +@register.filter +def sort_windows(files): + if not files: + return files + + # Put Windows files in preferred order + files = list(files) + windows_files = [] + other_files = [] + for preferred in ( + 'Windows installer (64-bit)', + 'Windows installer (32-bit)', + 'Windows installer (ARM64)', + 'Windows help file', + 'Windows embeddable package (64-bit)', + 'Windows embeddable package (32-bit)', + 'Windows embeddable package (ARM64)', + ): + for file in files: + if file.name == preferred: + windows_files.append(file) + files.remove(file) + break + + # Then append any remaining Windows files + for file in files: + if file.name.startswith('Windows'): + windows_files.append(file) + else: + other_files.append(file) + + return other_files + windows_files diff --git a/templates/downloads/os_list.html b/templates/downloads/os_list.html index 67db5233f..1e0177dca 100644 --- a/templates/downloads/os_list.html +++ b/templates/downloads/os_list.html @@ -1,6 +1,7 @@ {% extends "downloads/base.html" %} {% load boxes %} {% load sitetree %} +{% load sort_windows from download_tags %} {% block body_attributes %}class="python download"{% endblock %} @@ -45,7 +46,7 @@

    Stable Releases

    {% endif %} {% endif %}
      - {% for f in r.files.all %} + {% for f in r.files.all|sort_windows %}
    • Download {{ f.name }}
    • {% empty %}
    • No files for this release.
    • @@ -63,7 +64,7 @@

      Pre-releases

    • {{ r.name }} - {{ r.release_date|date }}
        - {% for f in r.files.all %} + {% for f in r.files.all|sort_windows %}
      • Download {{ f.name }}
      • {% empty %}
      • No files for this release.
      • diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 59ffe2d7a..720887074 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -3,6 +3,7 @@ {% load sitetree %} {% load has_sigstore_materials from download_tags %} {% load has_sbom from download_tags %} +{% load sort_windows from download_tags %} {% block body_attributes %}class="python downloads"{% endblock %} @@ -60,7 +61,7 @@

        Files

        - {% for f in release_files %} + {% for f in release_files|sort_windows %} {{ f.name }} {{ f.os.name }} From f88599b49d6514168f45920a531823e22d7570d6 Mon Sep 17 00:00:00 2001 From: Dorian Adams <104034366+dorian-adams@users.noreply.github.com> Date: Wed, 21 Feb 2024 08:56:58 -0500 Subject: [PATCH 054/235] Redirect legacy community page (#2319) Use regular expression to redirect all legacy 'community-landing/' paths, including any children. --- pydotorg/urls.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pydotorg/urls.py b/pydotorg/urls.py index 5fc6b3f12..d1496dc03 100644 --- a/pydotorg/urls.py +++ b/pydotorg/urls.py @@ -54,6 +54,7 @@ name='account_change_password'), path('accounts/', include('allauth.urls')), path('box/', include('boxes.urls')), + re_path(r'^community-landing(/.*)?$', RedirectView.as_view(url='/community/', permanent=True)), path('community/', include('community.urls', namespace='community')), path('community/microbit/', TemplateView.as_view(template_name="community/microbit.html"), name='microbit'), path('events/', include('events.urls', namespace='events')), From 94e53dabe52df1195b72ec0ef6d1b84a544176ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:57:38 +0100 Subject: [PATCH 055/235] Bump beautifulsoup4 from 4.9.3 to 4.11.2 (#2239) Bumps [beautifulsoup4](https://www.crummy.com/software/BeautifulSoup/bs4/) from 4.9.3 to 4.11.2. --- updated-dependencies: - dependency-name: beautifulsoup4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 2495153db..71e52b024 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -16,7 +16,7 @@ python-decouple==3.4 lxml==4.6.3 cssselect==1.1.0 feedparser==6.0.8 -beautifulsoup4==4.9.3 +beautifulsoup4==4.11.2 icalendar==4.0.7 chardet==4.0.0 # TODO: We may drop 'django-imagekit' completely. From af64f12c30a405ed561506d71ad158894f898564 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:00:41 +0100 Subject: [PATCH 056/235] Bump lxml from 4.6.3 to 4.9.2 (#2212) Bumps [lxml](https://github.com/lxml/lxml) from 4.6.3 to 4.9.2. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-4.6.3...lxml-4.9.2) --- updated-dependencies: - dependency-name: lxml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 71e52b024..06e1990e4 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -13,7 +13,7 @@ psycopg2-binary==2.8.6 python3-openid==3.2.0 python-decouple==3.4 # lxml used by BeautifulSoup. -lxml==4.6.3 +lxml==4.9.2 cssselect==1.1.0 feedparser==6.0.8 beautifulsoup4==4.11.2 From 8209dff476fa67cd2b129c4d9d9f7c82f5177c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Wed, 21 Feb 2024 15:33:18 +0100 Subject: [PATCH 057/235] Revert "Move to pandoc for rendering sponsorship contracts (#2343)" (#2374) This reverts commit a4990b711ccd6e34e87d8d4b97169846fba5414f. --- .github/workflows/ci.yml | 12 - Aptfile | 0 Dockerfile | 42 +-- base-requirements.txt | 7 +- pydotorg/settings/base.py | 1 + sponsors/contracts.py | 89 ------ sponsors/pandoc_filters/__init__.py | 0 sponsors/pandoc_filters/pagebreak.py | 90 ------ sponsors/pdf.py | 78 +++++ sponsors/reference.docx | Bin 12636 -> 0 bytes sponsors/tests/test_contracts.py | 39 --- sponsors/tests/test_pdf.py | 113 +++++++ sponsors/use_cases.py | 2 +- sponsors/views_admin.py | 2 +- .../sponsors/admin/contract-template.docx | Bin 0 -> 15199 bytes .../admin/contracts/renewal-agreement.md | 119 -------- .../admin/contracts/sponsorship-agreement.md | 209 ------------- .../sponsors/admin/preview-contract.html | 283 ++++++++++++++++++ .../admin/renewal-contract-template.docx | Bin 0 -> 9323 bytes texlive.packages | 2 - 20 files changed, 483 insertions(+), 605 deletions(-) delete mode 100644 Aptfile delete mode 100644 sponsors/contracts.py delete mode 100644 sponsors/pandoc_filters/__init__.py delete mode 100644 sponsors/pandoc_filters/pagebreak.py create mode 100644 sponsors/pdf.py delete mode 100644 sponsors/reference.docx delete mode 100644 sponsors/tests/test_contracts.py create mode 100644 sponsors/tests/test_pdf.py create mode 100644 templates/sponsors/admin/contract-template.docx delete mode 100644 templates/sponsors/admin/contracts/renewal-agreement.md delete mode 100644 templates/sponsors/admin/contracts/sponsorship-agreement.md create mode 100644 templates/sponsors/admin/preview-contract.html create mode 100644 templates/sponsors/admin/renewal-contract-template.docx delete mode 100644 texlive.packages diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28bfcc5ee..97298ffca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,18 +17,6 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v2 - - name: Install platform dependencies - run: | - sudo apt -y update - sudo apt -y install --no-install-recommends \ - texlive-latex-base \ - texlive-latex-recommended \ - texlive-plain-generic \ - lmodern - - name: Install pandoc - run: | - wget https://github.com/jgm/pandoc/releases/download/2.17.1.1/pandoc-2.17.1.1-1-amd64.deb - sudo dpkg -i pandoc-2.17.1.1-1-amd64.deb - uses: actions/setup-python@v2 with: python-version: 3.9.16 diff --git a/Aptfile b/Aptfile deleted file mode 100644 index e69de29bb..000000000 diff --git a/Dockerfile b/Dockerfile index f8aca13a2..4d1046a98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,47 +1,9 @@ -FROM python:3.9-bookworm +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 \ - texlive-plain-generic \ - lmodern - -RUN case $(uname -m) in \ - "x86_64") ARCH=amd64 ;; \ - "aarch64") ARCH=arm64 ;; \ - esac \ - && wget --quiet https://github.com/jgm/pandoc/releases/download/2.17.1.1/pandoc-2.17.1.1-1-${ARCH}.deb \ - && dpkg -i pandoc-2.17.1.1-1-${ARCH}.deb - RUN mkdir /code WORKDIR /code - COPY dev-requirements.txt /code/ COPY base-requirements.txt /code/ - -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 - +RUN pip install -r dev-requirements.txt COPY . /code/ diff --git a/base-requirements.txt b/base-requirements.txt index 06e1990e4..0badc58eb 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -44,11 +44,12 @@ 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==2.3.0 diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index ccbf3acab..25874dd5d 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -173,6 +173,7 @@ 'ordered_model', 'widget_tweaks', 'django_countries', + 'easy_pdf', 'sorl.thumbnail', 'banners', diff --git a/sponsors/contracts.py b/sponsors/contracts.py deleted file mode 100644 index 7e72cde39..000000000 --- a/sponsors/contracts.py +++ /dev/null @@ -1,89 +0,0 @@ -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") -REFERENCE_DOCX = os.path.join(dirname, "reference.docx") - - -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), - } - ) - previous_effective = contract.sponsorship.previous_effective_date - context["previous_effective"] = previous_effective if previous_effective else "UNKNOWN" - context["previous_effective_english_suffix"] = format(previous_effective, "S") if previous_effective else "UNKNOWN" - return context - - -def render_markdown_from_template(contract, **context): - template = "sponsors/admin/contracts/sponsorship-agreement.md" - if contract.sponsorship.renewal: - template = "sponsors/admin/contracts/renewal-agreement.md" - context = _contract_context(contract, **context) - return render_to_string(template, 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: - markdown = render_markdown_from_template(contract, **context) - pdf = pypandoc.convert_text( - markdown, "pdf", outputfile=pdf_file.name, format="md" - ) - 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-renewal' if contract.sponsorship.renewal else 'sponsorship-contract'}-{contract.sponsorship.sponsor.name.replace(' ', '-').replace('.', '')}.docx" - return response - - -def render_contract_to_docx_file(contract, **context): - markdown = render_markdown_from_template(contract, **context) - with tempfile.NamedTemporaryFile() as docx_file: - docx = pypandoc.convert_text( - markdown, - "docx", - outputfile=docx_file.name, - format="md", - filters=[DOCXPAGEBREAK_FILTER], - extra_args=[f"--reference-doc", REFERENCE_DOCX], - ) - return docx_file.read() diff --git a/sponsors/pandoc_filters/__init__.py b/sponsors/pandoc_filters/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/sponsors/pandoc_filters/pagebreak.py b/sponsors/pandoc_filters/pagebreak.py deleted file mode 100644 index 525b89c57..000000000 --- a/sponsors/pandoc_filters/pagebreak.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/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 new file mode 100644 index 000000000..9855beee3 --- /dev/null +++ b/sponsors/pdf.py @@ -0,0 +1,78 @@ +""" +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), + "renewal": contract.sponsorship.renewal, + }) + previous_effective = contract.sponsorship.previous_effective_date + context["previous_effective"] = previous_effective if previous_effective else "UNKNOWN" + context["previous_effective_english_suffix"] = format(previous_effective, "S") if previous_effective else None + 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): + context = _contract_context(contract, **context) + renewal = context["renewal"] + if renewal: + template = os.path.join(settings.TEMPLATES_DIR, "sponsors", "admin", "renewal-contract-template.docx") + else: + template = os.path.join(settings.TEMPLATES_DIR, "sponsors", "admin", "contract-template.docx") + doc = DocxTemplate(template) + 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/reference.docx b/sponsors/reference.docx deleted file mode 100644 index bf094ca4f3f29b535da99c765b735eaee71420d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12636 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%0D(b%B@_FB(DPPG z&0-g(r3Rwn9F|ya1EjZf5p!cs^V5e5ZrET>?rO&LZgV<8>y|PaqQ=B8^hbNN#5@lG z0asUMKV77q?P6^*ryGXhe|7wL{4^-TYsU*g{?my6?{RnDL<%&%Rsewdqhdk#28DJ-dJc@MXwm#QOhEI1QdJ= zw+08&iV{+vYD)Ju&N{VUf0P7KmtpWi7ursN&SVQ)f$~RDk1=CqiBf_jvQG~b*O=CK zV3KAQLC4&IfxT~*kvnG%bXdDXpTFaQ-8)tQLGU>*qRLSx*I9R^xi-j4EM;a@4fV_M z=;yL$-Whpw-}3U2q)2lT2nm~`#`MbwIa^}|*lDs`in=xFY-z+XKz5-;T8E>9rKX#g z>-^fmKz7f25wC!%-DGwc6lQ)iXrmfORRo5Eedxs1pSC5{%MOX=wWp!}ubewA;a7+K zx@V-P>}F@;sPoecw@6#F=%S?N!;BwtzIKqtH5W3uX-;nT zlewkvbhrB8XW({gOBU!eI)sOecHd@EhQfxQ&jpbg?wV{`kxqv7J#0Tsi zhakfr$2j}4mb2PWz>AYFt;4HLx36?bs(bBRS4YEs(Ep8C4^55|`XO7b1`U=B- zMjiO^A(Kjq%7+I}B!-|f6P_}{B((Rd0>$Rn5#KY0O*l4aU7y1YX(UsB%r)M08I|3M z`dB?YzXhVZON#HBu7PLuMGVnIKU_AV>8XR-@@=~p^3WTA{0}L0m_50C<_`=PKSVZV zTWzKh2qZ=`^sPMGQD6qlt_e??PMEAqxP`lEo_9UY3Fka{ynMv%8SFvWM^j^U!T-l#<8{R#hl jTK;_ySJ8lg{2wf=ycFc?@B#rre*HCrzeXZ-Kd=55B-B^E diff --git a/sponsors/tests/test_contracts.py b/sponsors/tests/test_contracts.py deleted file mode 100644 index c330c13a8..000000000 --- a/sponsors/tests/test_contracts.py +++ /dev/null @@ -1,39 +0,0 @@ -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()) - - # DOCX unit test - def test_render_response_with_docx_attachment(self): - request = Mock(HttpRequest) - self.contract.sponsorship.renewal = False - 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" - ) - - - # DOCX unit test - def test_render_renewal_response_with_docx_attachment(self): - request = Mock(HttpRequest) - self.contract.sponsorship.renewal = True - response = render_contract_to_docx_response(request, self.contract) - - self.assertEqual(response.get("Content-Disposition"), "attachment; filename=sponsorship-renewal-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 new file mode 100644 index 000000000..e4d140cf2 --- /dev/null +++ b/sponsors/tests/test_pdf.py @@ -0,0 +1,113 @@ +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": [], + "renewal": None, + "previous_effective": "UNKNOWN", + "previous_effective_english_suffix": None, + } + 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" + ) + + @patch("sponsors.pdf.DocxTemplate") + def test_render_response_with_docx_attachment__renewal(self, MockDocxTemplate): + renewal_contract = baker.make_recipe("sponsors.tests.empty_contract", sponsorship__start_date=date.today(), + sponsorship__renewal=True) + text = f"{renewal_contract.benefits_list.raw}\n\n**Legal Clauses**\n{renewal_contract.legal_clauses.raw}" + html = render_md(text) + renewal_context = { + "contract": renewal_contract, + "start_date": renewal_contract.sponsorship.start_date, + "start_day_english_suffix": format(self.contract.sponsorship.start_date, "S"), + "sponsor": renewal_contract.sponsorship.sponsor, + "sponsorship": renewal_contract.sponsorship, + "benefits": [], + "legal_clauses": [], + "renewal": True, + "previous_effective": "UNKNOWN", + "previous_effective_english_suffix": None, + } + renewal_template = "sponsors/admin/preview-contract.html" + + template = Path(settings.TEMPLATES_DIR) / "sponsors" / "admin" / "renewal-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, renewal_contract) + + MockDocxTemplate.assert_called_once_with(str(template.resolve())) + mocked_doc.render.assert_called_once_with(renewal_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 91271ff64..bbb6f2483 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.contracts import render_contract_to_pdf_file, render_contract_to_docx_file +from sponsors.pdf 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 fd8631d3f..e9a808ccc 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.contracts import render_contract_to_pdf_response, render_contract_to_docx_response +from sponsors.pdf 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 new file mode 100644 index 0000000000000000000000000000000000000000..5bdc44525a4d15367bcaad989f5d63ba6c278233 GIT binary patch literal 15199 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 literal 0 HcmV?d00001 diff --git a/templates/sponsors/admin/contracts/renewal-agreement.md b/templates/sponsors/admin/contracts/renewal-agreement.md deleted file mode 100644 index 3a401c9d7..000000000 --- a/templates/sponsors/admin/contracts/renewal-agreement.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: SPONSORSHIP AGREEMENT RENEWAL -geometry: -- margin=1.25in -font-size: 12pt -pagestyle: empty -header-includes: -- \pagenumbering{gobble} ---- - -**THIS SPONSORSHIP AGREEMENT RENEWAL** (the **"Agreement"**) -is entered into and made effective as of the -{{start_date|date:"j"}}{{start_day_english_suffix}} of {{start_date|date:"F Y"}} -(the **"Effective Date"**), -by and between the **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 and the PSF previously entered into a Sponsorship Agreement -with the effective date of the -{{ previous_effective|date:"j" }}{{ previous_effective_english_suffix }} of {{ previous_effective|date:"F Y" }} -and a term of one year (the “Sponsorship Agreementâ€). - -**WHEREAS**, Sponsor wishes to renew its 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 to extend and amend the Sponsorship Agreement as follows: - -1. [**Replacement of the Exhibit**]{.underline} Exhibit A to the Sponsorship Agreement is replaced with Exhibit A below. - -1. [**Renewal**]{.underline} Approval and incorporation of this new exhibit with the previous Sponsor Benefits shall be considered written notice by Sponsor to the PSF that you wish to continue the terms of the Sponsorship Agreement for an additional year and to contribute the new Sponsorship Payment specified in Exhibit A, beginning on the Effective Date, as contemplated by Section 6 of the Sponsorship Agreement. - -  - - -### \[Signature Page Follows\] - -::: {.page-break} -\newpage -::: - -## SPONSORSHIP AGREEMENT RENEWAL - -**IN WITNESS WHEREOF**, the Parties hereto have duly executed this **Sponsorship Agreement Renewal** 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 RENEWAL - -### 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/contracts/sponsorship-agreement.md b/templates/sponsors/admin/contracts/sponsorship-agreement.md deleted file mode 100644 index ee0d91ce3..000000000 --- a/templates/sponsors/admin/contracts/sponsorship-agreement.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: SPONSORSHIP AGREEMENT -geometry: -- margin=1.25in -font-size: 12pt -pagestyle: empty -header-includes: -- \pagenumbering{gobble} ---- - -**THIS SPONSORSHIP AGREEMENT** (the **"Agreement"**) -is entered into and made effective as of the -{{start_date|date:"j"}}{{start_day_english_suffix}} of {{start_date|date:"F Y"}} -(the **"Effective Date"**), -by and between the **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**]{.underline}. Each of the above Recitals is incorporated into and is made a part of this Agreement. - -1. [**Exhibits Incorporated by Reference**]{.underline}. 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. - -1. [**Sponsorship Payment**]{.underline} 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. - -1. [**Acknowledgement of Sponsor**]{.underline} In return for the Sponsorship Payment, Sponsor will be entitled to receive the sponsorship package described in Exhibit A attached hereto (the "Sponsor Benefits"). - -1. [**Intellectual Property**]{.underline} 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. - - (a) [Grant of License by the PSF]{.underline} 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. - - (a) [Grant of License by Sponsor]{.underline} 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. - -1. [**Term**]{.underline} The Term of this Agreement will begin on the Effective Date 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. - -1. [**Termination**]{.underline} 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. - -1. [**Code of Conduct**]{.underline} 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/conduct) and/or the PyCon Code of Conduct (https://pycon.us/code-of-conduct), as applicable. The PSF reserves the right to eject from any event any Sponsor or representative violating those standards. - -1. [**Deadlines**]{.underline} 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. - -1. [**Assignment of Space**]{.underline} 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). - -1. [**Job Postings**]{.underline} 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. - -1. [**Representations and Warranties**]{.underline} 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. - -1. [**Successors and Assigns**]{.underline} 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. - -1. [**No Third-Party Beneficiaries**]{.underline} 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. - -1. [**Severability**]{.underline} 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. - -1. [**Confidential Information**]{.underline} 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. - -1. [**Independent Contractors**]{.underline} 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. - -1. [**Indemnification**]{.underline} 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. - -1. [**Notices**]{.underline} 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 %} - > {{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. - -  - - -### \[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: - - (a) [**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. - - (a) 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 new file mode 100644 index 000000000..f89fd02b0 --- /dev/null +++ b/templates/sponsors/admin/preview-contract.html @@ -0,0 +1,283 @@ +{% 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 %} diff --git a/templates/sponsors/admin/renewal-contract-template.docx b/templates/sponsors/admin/renewal-contract-template.docx new file mode 100644 index 0000000000000000000000000000000000000000..3e36801a316f85a4a0484c7b4ed1a227a9fb4285 GIT binary patch literal 9323 zcma)C1yozxwhiuu;_hDD-QC@3X>kg{f;$us?iBY@+@-j?OM&99#hre*|Gj^E@Bi

        E*dJc2N$B6)ouG z9`pTi^LMS+F(X$}pO!fCS%)GHDHfE_P zwo<{g1{v?72%Hcn)>l~Kj9?t8hEbv#4;H(Maj}Ht@t0N;^&6Lc$WeLQ)K8pG*f@u9 zgmjfR=j4@pYYtlzr%>wz>w2J-<$MzQ6id_$tl7*FbVYP15c5C>(H7a5=utC~F;Hwx z`Ypxb(jNCYq$`INWBLk>)jl!LJtE@}1^QEPM}49jd2MJI+fQ62@oOkVDU~~wX z@jZ!VO56~JpGAv{UYasY6%fWPR?H?n_Epz49P%I;y~GN0a~B?4G5j;aTs$`{cEN;E z8Z?0`g(=+}?*dODU2mdomKoO>;?{tZvDLN!2h}XtrwZK;z0cSnz}TNRNWV)3HFDRQ z?#Ad#eZf95bf1bS%Al?Sxqn;jD+QZ!q1|L8Q^p^vU7D84ul55H0_@sWr0;9u?w%05 z(}fwERmHz7XxfYPY%alX!6rk!c7<}MpJQj<>)Nmi3ZqntWf|?H)Q;H%ulUw{zFX|eVxA; z-kGPI;0;NPxYK3*WHx%h@**W*#IjiQJ538<30%?pnh1}#+}WY4Ma^b6BuR0!v3hq6g25C=-dfJ`$ ziBdc%+V;ez0*JZa%E-#`d#9i`z?_8IvI}S&BTcZjeVXI62x2Zkls3Ze6%@E(2>3`< zaZOwthTYH+RBpf&v!x~^%);}uECklqF6lPHm>Z*%9d2wkpJkYot8>kYIXNQBzqstS zd%e4Wdx;$@u5WZI&umEkBO4gMvtjJy2(q>LgOJfm#7-8>z_lNR@ZT3T;9@3g!g=^L zuA`UhARKM`6~nzeDEyBjgGq#xrUW0wOVGZ*wrXU4LkD0)c}2r$`i0m5 zTXIj{+tYo{NBLJKDT`|^YNc^0{Zi(F18LP%s?lb z52g;5K=YSj{m@yoS`s z{1S&xPqt2zCd>j^^O9pSt?`hTqNEZCB!Rwm)*vV_@$a#uZu*sh-$hZGEL=4O3pT#0C8lIkE2PTaIM&Bm>Ic&eky+zib~l*aZ6-6P4$`5M(< zv30c@V(p+&wl2!#pN4fAWufV{>--$li3oj6Ln^m-sSmnsLTlXsu(BW^romB{Fy1&P zZ=`FJ7@H zfX@}`uSgJ70v_6k~Jm=MiNCwadqPa0lIH+{WYF$unwZPNA0 z`&|F4hX3X5YpEvL>8DgX*UY@n*V0Y8_a8ggerfTwRVKDJR7?4^RLkA;sog1N6iAl` zQUEguJE^G0>3!7igU-tJb%NV#4>I_m%M5Xb$n1`q5MKFxoSU(MH)uZA6JK3$;>CxY zD_b1?HE`+q7!5p%F3jx5=a&(OUXjemmmDjUEVO(Y2%hS(eQ{--8r78W=kWB#`X^U@ zDQ|zc@^g)IvM~jMUOf4TXiZ!sa-jQrBJq~`qFugc8HcU3#{nh8kRjg%Z%@Tipbw+@FJj@pQ;^%fpilG+bfy&}^^T01-puNHt;m7&K)BGd}1zbo$_!bHm z`A~HJg@cNa{n`)@IV-$mPGu>6Hu#3V$tbl2v7pX#-9 zhH(L)lFJb*ClABQXnbF77uS;N<)#(64XOC>Z=WOf z8L7dKn~dv=;KMfy1b7aF(NNcR^SP~)rmv)6+GVuIt{@+6G-&QVf-HuET58P?j&P{r zcn%oPfb5GQ#mchaH`q{8`U0B;wlqS}R>mK>im2xfy&oeEGb6NJ4vg4ONY9)j7sTin z5dC5S=>Ag_*#<`FK^g?U#)x-Cy1 z9~)#x_xmoRYOi&s8tz_=Q#rH}I2>2+3LXzF3jqpEcAJ#fbs%txI@sC{`iQ8{Cctv@ z;39t#M%ZESdwzpRfJ(x3M!R2^o$N7ikm+kM$~AhuBnBXo z?Xd~O5Xa}BfFU%R$ak#d1=g>1jJg5LAsw&@#pD*<-f)HiUpiLl-iMZ8y59OR;R7Et z$!(Ciao`ENM2f)CQi0Q7<_13D+ri1x?^&Vc6}^I&U@DQ4s{!MN(V;+2?ie1^a3J4H zRQl3kex~K%MAo%7$n>8-5@uDjH|r zf&5Gv8Nig6S8qYVsfU3V}Pso{i@m3 zBa3oZ;F%3th!HRy0OG5?$z`XQoVW^F4(;oui^}!xknwK33fe?Nyuqy*lEgHJ0XiJm z38X=~?2?Ve??G#JDQR`sY{l3ipO@|Fr$$oF#-Sx=ld4Qym$%p^jDCRmt*RGX!<4OT zdXifd$2Z#1D^JJ$!k4v7yp^4|jxEkPCsN<>$Gyg)P$y(;*^uafg()#DX@B}*3KLr* zBGYj!j+bPYG58X!JfDhWno4eMnh zq8=i^&9fn~onIF^6KB{b3nLe9zb)wA5t?VWSB!0BkYc%HpaqN@kNNhLJ)@Eb+Jezo9?$JDr%QiH0K0!~C0Q2} zWd26RDuq|TFxn2KbC{{^B$6cPNDp~aeoHnasb`08s`8tzMRA=f4h-oUoLLB}}6FcO}t>E*LJ*6BlfX65XH7W z7{?#@Q28}#Y<%6F%H%G=8do91l{&k+3xcQ!v+LyUT!&66Y_-w#l1vV9iC36WBO|UJ zzN$gSH9s@__WEdbE&1mlTA5Q@*VLE+K27>1k1Y`22xJ(YlobpSIJj%_r^X18uF#<$ z!t$3HTgqA)OO>bLb&bvt6VtLnqsTTXu2rfs!tn>a;bg!0zCV=i+uTq+Z&kX03&L~^diWTv{@_Vw=ZN8E@21(DI$JG1jTD_@(cUH5j&4Lft#v$w|yJ2l$g zA6xl(sUzaLw)+-z(+M*?d4!5Mqm&|tU}CjruS6|?a$PZz!~@rMrwycI`q~k z#KSG{A5^LITC@nJ?wCL1hRiDMvo6x5F43;*37T*f@cQXw#OKp`l~dnAq^=gcYn1xQ zM0KpTJ}SK~v~=aBq;})6QBLbYn{2X3A8LuywwU5??pgwIb&mvHIg;2swCB^3AVd&sD^KRq`BpX~ zE@KlTQzMFla?^9WpomQ)Xr`c7NxL*Uu&wvq)NZ*V487mq1+2O<=J~yaSBx}3Y>H0n zKyw|zn{5c6%UwipL9rwZUaIc!W6AfS;s9~SNv~2=>O%<*eZP4OZPU|P_jz=0&YCOQ z_Gr);x~}^H%QZ!o)4p*G`-^)wNTNnqiI%ZP7wsx^Y~0GCveMevwNY4WQdxjd%5()G z2M*&MMhAMXk#O_ZyJN=JUdXiY7{Vv}2T493{WmqJv#p2N_9|HnjPcoJK74pJ|3gIy zM(AqkO}}reZvXnLZ6^PS*$;?eEHQ8&ElFv={fyF&6t#TADnWyb%U{XBL@z26*Hta1 z9qL7gP2B0k>Xx6&vfy0YqAd^Fgsl#=X*r1mW<*>VYy3Gp(ttC8iRF`5%?+2 zt#|8jQ^ohTQD>}jmjkw^RqMkmUCl%W8+%>7sq7VC^QjkSuZjVw5Nu%={_y2-KgRqU z0)2hS7AXOm$C$G1KJLavs}tV?o;)tmPLF6Ntk`3!zNm+bJ=%BTWSbYGEd*xKD z1++?%6y#>$aHPqDOZv(Y4Dg8#sF5fu8F3gVUx+nsE65HZ(vU;1+f(Vs=eQsRrV&=M zNtH?i?O~9-(EwZbHMWVrfRY9{G+uRlr`xY9!m{oTUlEH_9RSe_MHd|`o>X~VbO<^B zlZO4RDb@}948U#33YvDtMkw5V-lm^KBqSVZc)5k20*-2~FQ&Q69sNzF^$k%ge{8Wg zmsv4$J8fFf!YH=nc>GM|8MWk=ngj##cja@Zb2?Mvh(f-02-~$M&N1+M=6pQdQ>}8@ zHdE=3Kz>EpzWrG6TgEot;2p1%xPUO;K$zK}wQ`KkxP36PjopFC=JCe({7 zkRh1>K~f;XWWCB=A!2V-Y_iXg->^WBRCY{ya1^T7o7?r64>uY$0;=k4CsYa}0WLrj zuA|1jk=lFxL6|V0w~@`O>a40s&U0bRShN?4DT^Bi-L{$o4+ksC9cH^wLHx{e`;sj5 zXNtpH_VfXnluxa-AZ^#x8kDcEIg&Y@bZ4EhaJr?X3AW*$3LNQ(ws);FA5PjfXL^UQ zTJ@YAcmn9(t(Qn6H@Vc2yehBmfEo`zylCZJjm2Wrov0CEPC`LhnNXEcikF?Ho!AYs zl3a==g=p&E4ar67S1XZlSH#qpTicp#o0&!Rg*)&+x*l%0qQZ5fwWkbW10CoZm7;KW zE?rhYG}#LXtlRaHX80sywaAqe;zvD}vN0}IwI|L(;rGUl6SrpPaGp^7c+N_Xt;$h( zq)#R~rX;X~0Fe1Ei7a6vxFvF9H5~mG{V{g8T(iY-LWO0&E%uhqEOJ?DGMHWqt?%&g z+LZgNZ5{TO|7CCQVg!wMhkLGAkaVV7)xzQGq_Se-DNdT_;~88w<9Ac}`nBps<|Jkn zB1_)4fnlz9nr*lSZ-dl&>j&EginusO=zs{*Y-kEqzvkLvdWFPJATnK<`B~Z_4%9>! zHBKi>&3Lz?Y8q;KGLr{S&VZwJ#Kz-3$0bK3i$svkAM2;rK1%n+y@BQbWQZxdZ4jrq z!E9p8QWQNjgqeGjN}F}>15fI5^90GonMFMQ0BMKi?~aqZq*@5-f)Wd%t~WfDk(}QvO|4=V%>!45-F*v36kSRd z{7%Z3tu?C=+tf_!^^9U}C&|@Moy|AR`B~|nD!rQMj!-E!-q(r@zUN#mk&@c$0u^mg zTJfm_z&Bl|^f}&jb=|8|jbLu#CdVS7)|*4owG^2R30~!2hp#tK8Cpb*L8gA9UYsag za%I^$DuzK?xmdCj*xK4YIO3**t*$kYZhvfjgnXnfiaU8EdFd;>wjJcfd+xJ7#{W}a z0rlT~1xJvZwW;GvSD{Bs)pmge&3mOhER4kta~f24dgSGhHnI$ww1I{-G|8%ABr=l@&ZoL zt#0FyfZA?s-Ql`E97%FhU)rr$NgN_-rNX=d@e~6&fkh-BRtBlt6&2Z!-%6BGHUucI zJrVJ{-s~xgoa2ekt!t$UGG+BH<12}?sX71~x$$_|*~uDb(hyH%9X4UU*+@G3_<|u-lKe;6~^NxkS7u4K9)88uX_aOLMQl9aCzJt7tj1&%j`POB6(W^g-9i zJ4}_3RYD~?b|iQ9J)Ae%YkpI8h!eq~V7hEj3bv$*kbwv9hN5N#%%DG68h`Q407^Yt z1SKEkya!Vz0XiPNpMlsXPyjYiN}LhqhTrG{@>+jPk-M900Mc2m6tms{DDN2Hg2|<1 zY=YzRxn%tddI8;ogTMBuMfv_T^b?{b${^Pbp=%4p>d+C4!%1LOi{lc6Q@vqzNN20i z)U?ROvzTP1A5*c!;V13+D<@}WIp`cY8vF*S&M@~o`6zR-VvYy#w?+yT%PWpgoz;>T z5ZA?2^w-7&TlYGAoHG!LX#)7)6R*Tq>)~6!sZ=VrH_@aBI=Ddk z1T0;@i7(HDa=d5((Z8j@>!|XZUAP;o;Dho1H7h{EQ6gM&nm96MP6Xcnw4r22z!EH+ z`Rc02PmUArD1z+kMR%$blG?~xR$1!)B%)p(Rt=PXYs!J}OF%w3u*GRW0RUbo{}hmf z{|?Ci*86^M_x(%z8+vZaqe)(SOFsWw{z^`+_#5eI9-CKWY{K(+G7m1%aMB`hTP>Q0$RE_80tpR%OV(P-Z*VA@CnN1d2gm%$r)b7 z1|ub%9u++6dB}CGTwvrk-y!l^-%*O|VCIK|6|Q7_ParU4NuiWCEU#D3SsJ;WiV7Td z84ndwcWXp5XgIhTt(*V8!bwwb9w3yOQ1(EM*fUKz{3>^s*U9t{X15~PKAPyTUQCvb z23PM~M{tYW0tZ1vYHHHuuks7V-Xi0QC9 zA$7r9xdfekkCUINgG&lHmpzkDmzXo_K{?+#X3htj;n8&7&UY;xc@+i;?=QM&ue{7- zpDs2p!n5X+^L+e2v=K8~AV}l=2kSos(~)?2;InrHT?p5vw(p~@p z*vS$fLIhqh)tAePXiy=AsqBqjfq&g@zgITP)T1H*QI-yTw@9vnj;ILaI7sticn257 zK!#cXFh$w64(~RbYL@Mn`zSzl+LX<(S#s7o%0r`?4U4~kuUL~XYx&duU{*j!dwLX+ zGHhS()IL?n4rQ{U1Fe~MW zR)8gu1WcsePBlbAH3#)Fk^j$K>|ICfJUZ*F4hv6Vvu~O(j5AkueYGD-vlHKH1fQeu zAiN3W$2d_@ipJJ&sVYv|+^@{Yk@qP=iY*`wWrB8#djqn`jfLUUty9Q)5YR*A6ZYu2 zZ;&orieTO-dE4l);@6=vfPsJhn6jQ?J2p* zC}*HU`YG1A!x+IZp3~t-)+&UgDt+=vaHAkh1uHcXJ8@vRWoJ|(cQY=bIF5>kIfAKQ zlZza|0{CfKQ}nI5@*ZOfnECAcg1>Tw_PsxYScOZxdn=&F(~QBQB)*pp`{#t_G}}`L zeb!v=1j?2a+&CG^L;(04j#gJac+)07Da9YjNf5q&L%3Q1-F170asVl_7OJF=cf76#ZLQEFcegd+)(t7#EXnNpg zc3b48(B6MvYNTV0H+?wL8Gd_JaN!HzK?$5Vh}e8=ToW_Soh2Cc0RQ1uy{0wb=4!B& zc|(|~ES*rSy~Kz0e%6geEOZ?2^ITiQT{d$1C0Dnk61NZd^bdithgO!#>X|Ad*cYlG zATa@d?#%doL&D3>jKA7%`!xOz{9PM=$zy*S#q&@7uiXoOhyO0-z6j`l+Qf6p{2%zg zsnaQ_AWa}E1<@b9(drNaJc2L%5D|A%_}_bdILUH>`?B%*)c#&4DB@9^JK uz+Wd(o%mnyza-?p3o*ymGZjwy)a`s>Q`g|M! literal 0 HcmV?d00001 diff --git a/texlive.packages b/texlive.packages deleted file mode 100644 index fc8668ea0..000000000 --- a/texlive.packages +++ /dev/null @@ -1,2 +0,0 @@ -xcolor -etoolbox From a7f830a4ffd02988c99a9ef80773c1c9c91b6800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Wed, 21 Feb 2024 15:52:07 +0100 Subject: [PATCH 058/235] Remove stranded from templates/base.html (#2377) This was introduced in #2367. --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index cfa0f34ce..424df06f6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -236,7 +236,7 @@

      • Socialize
      • " html += "

      " return mark_safe(html) - other_years.short_description = "Other configured years" def clone_application_config(self, request): return views_admin.clone_application_config(self, request) @@ -828,10 +866,12 @@ def get_queryset(self, *args, **kwargs): qs = super().get_queryset(*args, **kwargs) return qs.select_related("sponsorship__sponsor") + @admin.display( + description="Revision" + ) def get_revision(self, obj): return obj.revision if obj.is_draft else "Final" - get_revision.short_description = "Revision" fieldsets = [ ( @@ -899,6 +939,9 @@ def get_readonly_fields(self, request, obj): return readonly_fields + @admin.display( + description="Contract document" + ) def document_link(self, obj): html, url, msg = "---", "", "" @@ -916,8 +959,10 @@ def document_link(self, obj): html = f'{msg}' return mark_safe(html) - document_link.short_description = "Contract document" + @admin.display( + description="Sponsorship" + ) def get_sponsorship_url(self, obj): if not obj.sponsorship: return "---" @@ -925,7 +970,6 @@ def get_sponsorship_url(self, obj): html = f"{obj.sponsorship}" return mark_safe(html) - get_sponsorship_url.short_description = "Sponsorship" def get_urls(self): urls = super().get_urls() @@ -1090,14 +1134,19 @@ def all_sponsorships(self): qs = Sponsorship.objects.all().select_related("package", "sponsor") return {sp.id: sp for sp in qs} + @admin.display( + description="Value" + ) def get_value(self, obj): html = obj.value if obj.value and getattr(obj.value, "url", None): html = f"{obj.value}" return mark_safe(html) - get_value.short_description = "Value" + @admin.display( + description="Associated with" + ) def get_related_object(self, obj): """ Returns the content_object as an URL and performs better because @@ -1115,11 +1164,12 @@ def get_related_object(self, obj): html = f"{content_object}" return mark_safe(html) - get_related_object.short_description = "Associated with" + @admin.action( + description="Export selected" + ) def export_assets_as_zipfile(self, request, queryset): return views_admin.export_assets_as_zipfile(self, request, queryset) - export_assets_as_zipfile.short_description = "Export selected" class GenericAssetChildModelAdmin(PolymorphicChildModelAdmin): diff --git a/sponsors/migrations/0103_alter_benefitfeature_polymorphic_ctype_and_more.py b/sponsors/migrations/0103_alter_benefitfeature_polymorphic_ctype_and_more.py new file mode 100644 index 000000000..e9eb9e3a2 --- /dev/null +++ b/sponsors/migrations/0103_alter_benefitfeature_polymorphic_ctype_and_more.py @@ -0,0 +1,47 @@ +# Generated by Django 4.2.11 on 2024-09-05 17:10 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('sponsors', '0102_auto_20240509_2037'), + ] + + operations = [ + migrations.AlterField( + model_name='benefitfeature', + name='polymorphic_ctype', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'), + ), + migrations.AlterField( + model_name='benefitfeatureconfiguration', + name='polymorphic_ctype', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'), + ), + migrations.AlterField( + model_name='genericasset', + name='polymorphic_ctype', + field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'), + ), + migrations.AlterField( + model_name='sponsor', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_creator', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='sponsor', + name='last_modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_modified', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='sponsorshipbenefit', + name='conflicts', + field=models.ManyToManyField(blank=True, help_text='For benefits that conflict with one another,', to='sponsors.sponsorshipbenefit', verbose_name='Conflicts'), + ), + ] diff --git a/sponsors/tests/test_api.py b/sponsors/tests/test_api.py index caabd6aa1..3575e59e6 100644 --- a/sponsors/tests/test_api.py +++ b/sponsors/tests/test_api.py @@ -41,7 +41,7 @@ def tearDown(self): sponsor.print_logo.delete() def test_list_logo_placement_as_expected(self): - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(200, response.status_code) @@ -71,7 +71,7 @@ def test_list_logo_placement_as_expected(self): def test_invalid_token(self): Token.objects.all().delete() - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(401, response.status_code) def test_superuser_user_have_permission_by_default(self): @@ -79,19 +79,19 @@ def test_superuser_user_have_permission_by_default(self): self.user.is_superuser = True self.user.is_staff = True self.user.save() - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(200, response.status_code) def test_staff_have_permission_by_default(self): self.user.user_permissions.remove(self.permission) self.user.is_staff = True self.user.save() - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(200, response.status_code) def test_user_must_have_required_permission(self): self.user.user_permissions.remove(self.permission) - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(403, response.status_code) def test_filter_sponsorship_by_publisher(self): @@ -99,7 +99,7 @@ def test_filter_sponsorship_by_publisher(self): "publisher": PublisherChoices.PYPI.value, }) url = f"{self.url}?{querystring}" - response = self.client.get(url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(200, response.status_code) @@ -111,7 +111,7 @@ def test_filter_sponsorship_by_flight(self): "flight": LogoPlacementChoices.SIDEBAR.value, }) url = f"{self.url}?{querystring}" - response = self.client.get(url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(200, response.status_code) @@ -125,7 +125,7 @@ def test_bad_request_for_invalid_filters(self): "publisher": "invalid-publisher" }) url = f"{self.url}?{querystring}" - response = self.client.get(url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(400, response.status_code) @@ -162,7 +162,7 @@ def tearDown(self): def test_invalid_token(self): Token.objects.all().delete() - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(401, response.status_code) def test_superuser_user_have_permission_by_default(self): @@ -170,30 +170,30 @@ def test_superuser_user_have_permission_by_default(self): self.user.is_superuser = True self.user.is_staff = True self.user.save() - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(200, response.status_code) def test_staff_have_permission_by_default(self): self.user.user_permissions.remove(self.permission) self.user.is_staff = True self.user.save() - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(200, response.status_code) def test_user_must_have_required_permission(self): self.user.user_permissions.remove(self.permission) - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) self.assertEqual(403, response.status_code) def test_bad_request_if_no_internal_name(self): url = reverse_lazy("assets_list") - response = self.client.get(url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(url, headers={"authorization": self.authorization}) self.assertEqual(400, response.status_code) self.assertIn("internal_name", response.json()) def test_list_assets_by_internal_name(self): # by default exclude assets with no value - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(200, response.status_code) self.assertEqual(0, len(data)) @@ -202,7 +202,7 @@ def test_list_assets_by_internal_name(self): self.txt_asset.value = "Text Content" self.txt_asset.save() - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(1, len(data)) @@ -216,7 +216,7 @@ def test_list_assets_by_internal_name(self): def test_enable_to_filter_by_assets_with_no_value_via_querystring(self): self.url += "&list_empty=true" - response = self.client.get(self.url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(self.url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(1, len(data)) @@ -230,7 +230,7 @@ def test_serialize_img_value_as_url_to_image(self): self.img_asset.save() url = reverse_lazy("assets_list") + f"?internal_name={self.img_asset.internal_name}" - response = self.client.get(url, HTTP_AUTHORIZATION=self.authorization) + response = self.client.get(url, headers={"authorization": self.authorization}) data = response.json() self.assertEqual(1, len(data)) diff --git a/successstories/__init__.py b/successstories/__init__.py index e2c2c1446..e69de29bb 100644 --- a/successstories/__init__.py +++ b/successstories/__init__.py @@ -1 +0,0 @@ -default_app_config = 'successstories.apps.SuccessstoriesAppConfig' diff --git a/successstories/admin.py b/successstories/admin.py index fdde8878c..bc15d2d11 100644 --- a/successstories/admin.py +++ b/successstories/admin.py @@ -24,6 +24,8 @@ def get_list_display(self, request): fields = list(super().get_list_display(request)) return fields + ['show_link', 'is_published', 'featured'] + @admin.display( + description='View on site' + ) def show_link(self, obj): return format_html(f'\U0001F517') - show_link.short_description = 'View on site' diff --git a/successstories/migrations/0012_alter_story_creator_alter_story_last_modified_by.py b/successstories/migrations/0012_alter_story_creator_alter_story_last_modified_by.py new file mode 100644 index 000000000..dee246421 --- /dev/null +++ b/successstories/migrations/0012_alter_story_creator_alter_story_last_modified_by.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.11 on 2024-09-05 17:10 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('successstories', '0011_auto_20220127_1923'), + ] + + operations = [ + migrations.AlterField( + model_name='story', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_creator', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='story', + name='last_modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_modified', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/successstories/tests/test_models.py b/successstories/tests/test_models.py index de5c0d577..418d27062 100644 --- a/successstories/tests/test_models.py +++ b/successstories/tests/test_models.py @@ -15,12 +15,13 @@ def test_published(self): self.assertEqual(len(Story.objects.published()), 2) def test_draft(self): - self.assertQuerysetEqual(Story.objects.draft(), - [f'']) + draft_stories = Story.objects.draft() + self.assertTrue(all(story.name == 'Fraft Story' for story in draft_stories)) def test_featured(self): - self.assertQuerysetEqual(Story.objects.featured(), - [f'']) + featured_stories = Story.objects.featured() + expected_repr = [f''] + self.assertQuerysetEqual(featured_stories, expected_repr, transform=repr) def test_get_admin_url(self): self.assertEqual(self.story1.get_admin_url(), diff --git a/users/__init__.py b/users/__init__.py index 1bf67ae9c..e69de29bb 100644 --- a/users/__init__.py +++ b/users/__init__.py @@ -1 +0,0 @@ -default_app_config = 'users.apps.UsersAppConfig' diff --git a/users/admin.py b/users/admin.py index 1c003655c..36d7e30f3 100644 --- a/users/admin.py +++ b/users/admin.py @@ -26,7 +26,7 @@ class ApiKeyInline(TastypieApiKeyInline): @admin.register(User) class UserAdmin(BaseUserAdmin): - inlines = BaseUserAdmin.inlines + [ApiKeyInline, MembershipInline] + inlines = BaseUserAdmin.inlines + (ApiKeyInline, MembershipInline,) fieldsets = ( (None, {'fields': ('username', 'password')}), (_('Personal info'), {'fields': ( @@ -44,9 +44,11 @@ class UserAdmin(BaseUserAdmin): def has_add_permission(self, request): return False + @admin.display( + description='Name' + ) def full_name(self, obj): return obj.get_full_name() - full_name.short_description = 'Name' @admin.register(Membership) diff --git a/users/migrations/0015_alter_user_first_name.py b/users/migrations/0015_alter_user_first_name.py new file mode 100644 index 000000000..ac7715204 --- /dev/null +++ b/users/migrations/0015_alter_user_first_name.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.11 on 2024-09-05 17:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0014_auto_20210801_2332'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='first_name', + field=models.CharField(blank=True, max_length=150, verbose_name='first name'), + ), + ] diff --git a/users/tests/test_forms.py b/users/tests/test_forms.py index 10ab95e32..897f41d6c 100644 --- a/users/tests/test_forms.py +++ b/users/tests/test_forms.py @@ -2,6 +2,7 @@ from django.test import TestCase from allauth.account.forms import SignupForm +from allauth.account.models import EmailAddress from users.forms import UserProfileForm, MembershipForm @@ -50,14 +51,16 @@ def test_duplicate_username(self): self.assertIn('username', form.errors) def test_duplicate_email(self): - User.objects.create_user('test1', 'test@example.com', 'testpass') + user = User.objects.create_user('test1', 'test@example.com', 'testpass') + EmailAddress.objects.create(user=user, email="test@example.com") - form = SignupForm({ + form = SignupForm(data={ 'username': 'username2', 'email': 'test@example.com', 'password1': 'password', - 'password2': 'password' + 'password2': 'password', }) + self.assertFalse(form.is_valid()) self.assertIn('email', form.errors) @@ -92,13 +95,8 @@ def test_non_ascii_username(self): 'password2': 'password', }) self.assertFalse(form.is_valid()) - self.assertEqual( - form.errors['username'], - [ - 'Enter a valid username. This value may contain only ' - 'English letters, numbers, and @/./+/-/_ characters.' - ] - ) + expected_error = 'Enter a valid username. This value may contain only unaccented lowercase a-z and uppercase A-Z letters, numbers, and @/./+/-/_ characters.' + self.assertIn(expected_error, form.errors['username']) def test_user_membership(self): form = MembershipForm({ diff --git a/users/tests/test_views.py b/users/tests/test_views.py index 13c226e5f..83b8330f9 100644 --- a/users/tests/test_views.py +++ b/users/tests/test_views.py @@ -2,7 +2,7 @@ from django.conf import settings from django.contrib.auth import get_user_model from django.urls import reverse -from django.test import TestCase +from django.test import TestCase, override_settings from sponsors.forms import SponsorUpdateForm, SponsorRequiredAssetsForm from sponsors.models import Sponsorship, RequiredTextAssetConfiguration, SponsorBenefit @@ -11,8 +11,6 @@ from users.factories import UserFactory from users.models import Membership -from ..factories import MembershipFactory - User = get_user_model() @@ -245,7 +243,7 @@ def test_user_duplicate_username_email(self): response, 'A user with that username already exists.' ) self.assertContains( - response, 'A user is already registered with this e-mail address.' + response, 'A user is already registered with this email address.' ) def test_usernames(self): diff --git a/work_groups/__init__.py b/work_groups/__init__.py index ef2fbcce9..e69de29bb 100644 --- a/work_groups/__init__.py +++ b/work_groups/__init__.py @@ -1 +0,0 @@ -default_app_config = 'work_groups.apps.WorkGroupsAppConfig' diff --git a/work_groups/migrations/0005_alter_workgroup_creator_and_more.py b/work_groups/migrations/0005_alter_workgroup_creator_and_more.py new file mode 100644 index 000000000..a316aa482 --- /dev/null +++ b/work_groups/migrations/0005_alter_workgroup_creator_and_more.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.11 on 2024-09-05 17:10 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('work_groups', '0004_auto_20180705_0352'), + ] + + operations = [ + migrations.AlterField( + model_name='workgroup', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_creator', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='workgroup', + name='last_modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(app_label)s_%(class)s_modified', to=settings.AUTH_USER_MODEL), + ), + ] From f31053a5604b0d919a2abd66e6b3b5dda018ee21 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Thu, 12 Sep 2024 14:50:47 -0500 Subject: [PATCH 088/235] fix: update `django-storages` version (#2533) --- prod-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prod-requirements.txt b/prod-requirements.txt index a7c4022f1..cdc543952 100644 --- a/prod-requirements.txt +++ b/prod-requirements.txt @@ -4,5 +4,5 @@ raven==6.10.0 # Heroku Whitenoise==6.6.0 # 6.4.0 is first version that supports Django 4.2 -django-storages==1.42.2 # 1.42.2 is first version that supports Django 4.2 +django-storages==1.14.4 # 1.14.4 is first version that supports Django 4.2 boto3==1.26.165 From e89f46d04867e514d2702894b1bd8dcddbebc9e1 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Thu, 12 Sep 2024 16:53:51 -0400 Subject: [PATCH 089/235] Fix static (#2534) * re-encode plugins as utf-8 * upgrade to 4.2.x code for HashedFilesMixin and reapply patches --- custom_storages/storages.py | 84 +++++++++++++++++++++++++------------ static/js/plugins/IE7.js | 3 +- static/js/plugins/IE9.js | 2 +- 3 files changed, 60 insertions(+), 29 deletions(-) mode change 100755 => 100644 static/js/plugins/IE7.js mode change 100755 => 100644 static/js/plugins/IE9.js diff --git a/custom_storages/storages.py b/custom_storages/storages.py index c735fd530..567685603 100644 --- a/custom_storages/storages.py +++ b/custom_storages/storages.py @@ -23,6 +23,21 @@ class PipelineManifestStorage(PipelineMixin, ManifestFilesMixin, StaticFilesStor imports in comments. Ref: https://code.djangoproject.com/ticket/21080 """ + # Skip map files + # https://code.djangoproject.com/ticket/33353#comment:13 + patterns = ( + ( + "*.css", + ( + "(?Purl\\(['\"]{0,1}\\s*(?P.*?)[\"']{0,1}\\))", + ( + "(?P@import\\s*[\"']\\s*(?P.*?)[\"'])", + '@import url("%(url)s")', + ), + ), + ), + ) + def get_comment_blocks(self, content): """ Return a list of (start, end) tuples for each comment block. @@ -32,73 +47,85 @@ def get_comment_blocks(self, content): for match in re.finditer(r'\/\*.*?\*\/', content, flags=re.DOTALL) ] - def url_converter(self, name, hashed_files, template=None, comment_blocks=None): + + def is_in_comment(self, pos, comments): + for start, end in comments: + if start < pos and pos < end: + return True + if pos < start: + return False + return False + + + def url_converter(self, name, hashed_files, template=None, comment_blocks=[]): """ Return the custom URL converter for the given file name. """ - if comment_blocks is None: - comment_blocks = [] - if template is None: template = self.default_template def converter(matchobj): """ Convert the matched URL to a normalized and hashed URL. + This requires figuring out which files the matched URL resolves to and calling the url() method of the storage. """ - matched, url = matchobj.groups() + matches = matchobj.groupdict() + matched = matches["matched"] + url = matches["url"] # Ignore URLs in comments. if self.is_in_comment(matchobj.start(), comment_blocks): return matched # Ignore absolute/protocol-relative and data-uri URLs. - if re.match(r'^[a-z]+:', url): + if re.match(r"^[a-z]+:", url): return matched # Ignore absolute URLs that don't point to a static file (dynamic # CSS / JS?). Note that STATIC_URL cannot be empty. - if url.startswith('/') and not url.startswith(settings.STATIC_URL): + if url.startswith("/") and not url.startswith(settings.STATIC_URL): return matched # Strip off the fragment so a path-like fragment won't interfere. url_path, fragment = urldefrag(url) - if url_path.startswith('/'): + # Ignore URLs without a path + if not url_path: + return matched + + if url_path.startswith("/"): # Otherwise the condition above would have returned prematurely. assert url_path.startswith(settings.STATIC_URL) - target_name = url_path[len(settings.STATIC_URL):] + target_name = url_path[len(settings.STATIC_URL) :] else: # We're using the posixpath module to mix paths and URLs conveniently. - source_name = name if os.sep == '/' else name.replace(os.sep, '/') + source_name = name if os.sep == "/" else name.replace(os.sep, "/") target_name = posixpath.join(posixpath.dirname(source_name), url_path) # Determine the hashed name of the target file with the storage backend. hashed_url = self._url( - self._stored_name, unquote(target_name), - force=True, hashed_files=hashed_files, + self._stored_name, + unquote(target_name), + force=True, + hashed_files=hashed_files, ) - transformed_url = '/'.join(url_path.split('/')[:-1] + hashed_url.split('/')[-1:]) + transformed_url = "/".join( + url_path.split("/")[:-1] + hashed_url.split("/")[-1:] + ) # Restore the fragment that was stripped off earlier. if fragment: - transformed_url += ('?#' if '?#' in url else '#') + fragment + transformed_url += ("?#" if "?#" in url else "#") + fragment # Return the hashed version to the file - return template % unquote(transformed_url) + matches["url"] = unquote(transformed_url) + return template % matches return converter - def is_in_comment(self, pos, comments): - for start, end in comments: - if start < pos and pos < end: - return True - if pos < start: - return False - return False def _post_process(self, paths, adjustable_paths, hashed_files): # Sort the files by directory level @@ -122,7 +149,7 @@ def path_level(name): hashed_name = hashed_files[hash_key] # then get the original's file content.. - if hasattr(original_file, 'seek'): + if hasattr(original_file, "seek"): original_file.seek(0) hashed_file_exists = self.exists(hashed_name) @@ -131,12 +158,14 @@ def path_level(name): # ..to apply each replacement pattern to the content if name in adjustable_paths: old_hashed_name = hashed_name - content = original_file.read().decode(settings.FILE_CHARSET) + content = original_file.read().decode("utf-8") for extension, patterns in self._patterns.items(): if matches_patterns(path, (extension,)): comment_blocks = self.get_comment_blocks(content) for pattern, template in patterns: - converter = self.url_converter(name, hashed_files, template, comment_blocks) + converter = self.url_converter( + name, hashed_files, template, comment_blocks + ) try: content = pattern.sub(converter, content) except ValueError as exc: @@ -145,8 +174,9 @@ def path_level(name): self.delete(hashed_name) # then save the processed result content_file = ContentFile(content.encode()) - # Save intermediate file for reference - saved_name = self._save(hashed_name, content_file) + if self.keep_intermediate_files: + # Save intermediate file for reference + self._save(hashed_name, content_file) hashed_name = self.hashed_name(name, content_file) if self.exists(hashed_name): diff --git a/static/js/plugins/IE7.js b/static/js/plugins/IE7.js old mode 100755 new mode 100644 index ba86e3ae0..2884c7d6b --- a/static/js/plugins/IE7.js +++ b/static/js/plugins/IE7.js @@ -12,7 +12,7 @@ Unknown W Brackets, Benjamin Westfarer, Rob Eberhardt, Bill Edney, Kevin Newman, James Crompton, Matthew Mastracci, Doug Wright, Richard York, Kenneth Kolano, MegaZone, - Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Åhlfors, + Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Ã…hlfors, David Zulaica, Ken Kolano, Kevin Newman, Sjoerd Visscher, Ingo Chao */ @@ -2406,3 +2406,4 @@ IE7.loaded = true; })(); })(this, document); + diff --git a/static/js/plugins/IE9.js b/static/js/plugins/IE9.js old mode 100755 new mode 100644 index 4d99fd69e..9a50014ed --- a/static/js/plugins/IE9.js +++ b/static/js/plugins/IE9.js @@ -14,7 +14,7 @@ Unknown W Brackets, Benjamin Westfarer, Rob Eberhardt, Bill Edney, Kevin Newman, James Crompton, Matthew Mastracci, Doug Wright, Richard York, Kenneth Kolano, MegaZone, - Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Åhlfors, + Thomas Verelst, Mark 'Tarquin' Wilton-Jones, Rainer Ã…hlfors, David Zulaica, Ken Kolano, Kevin Newman, Sjoerd Visscher, Ingo Chao */ From d38d0f5b07cc9f0ccdffd3b934b734ddf093c998 Mon Sep 17 00:00:00 2001 From: partev Date: Thu, 12 Sep 2024 19:30:10 -0400 Subject: [PATCH 090/235] docs: fix the URL for RTD (#2192) Co-authored-by: Jacob Coffee --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fc59b7cdf..5bf04cbc6 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ https://github.com/python/cpython/issues/. * Source code: https://github.com/python/pythondotorg * Issue tracker: https://github.com/python/pythondotorg/issues -* Documentation: https://pythondotorg.readthedocs.org/ +* Documentation: https://pythondotorg.readthedocs.io/ * Mailing list: [pydotorg-www](https://mail.python.org/mailman/listinfo/pydotorg-www) * IRC: `#pydotorg` on Freenode * Staging site: https://staging.python.org/ (`main` branch) From 1037cbb409567c667eb1d6684f22698c65eb5d5f Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Fri, 13 Sep 2024 07:23:39 -0400 Subject: [PATCH 091/235] Upgrade to Python 3.12.6 (#2535) * upgrade to Python 3.12 * update deps * fix syntax in tests --- .github/workflows/ci.yml | 2 +- .python-version | 2 +- Dockerfile | 2 +- Dockerfile.cabotage | 2 +- base-requirements.txt | 8 ++++---- downloads/tests/test_models.py | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bd57ab9c..42f8472ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: sudo dpkg -i pandoc-2.17.1.1-1-amd64.deb - uses: actions/setup-python@v5 with: - python-version: 3.9.16 + python-version: 3.12.6 - name: Cache Python dependencies uses: actions/cache@v4 env: diff --git a/.python-version b/.python-version index 9f3d4c178..35f236d6e 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.9.16 +3.12.6 diff --git a/Dockerfile b/Dockerfile index a3c351f5e..b124c73ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-bookworm +FROM python:3.12-bookworm ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/Dockerfile.cabotage b/Dockerfile.cabotage index d96e002a7..854e3179e 100644 --- a/Dockerfile.cabotage +++ b/Dockerfile.cabotage @@ -1,4 +1,4 @@ -FROM python:3.9-bullseye +FROM python:3.12-bookworm COPY --from=ewdurbin/nginx-static:1.25.x /usr/bin/nginx /usr/bin/nginx ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/base-requirements.txt b/base-requirements.txt index a86bf74ae..d63743f4b 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -5,11 +5,11 @@ django-apptemplates==1.5 django-admin-interface==0.24.2 django-translation-aliases==0.1.0 Django==4.2.16 -docutils==0.12 -Markdown==3.3.4 +docutils==0.21.2 +Markdown==3.7 cmarkgfm==0.6.0 -Pillow==9.4.0 -psycopg2-binary==2.8.6 +Pillow==10.4.0 +psycopg2-binary==2.9.9 python3-openid==3.2.0 python-decouple==3.4 # lxml used by BeautifulSoup. diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index f27e9517d..d31afae5c 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -82,8 +82,8 @@ def test_is_version_at_least(self): release_38 = Release.objects.create(name='Python 3.8.0') self.assertFalse(release_38.is_version_at_least_3_9) - self.assert_(release_38.is_version_at_least_3_5) + self.assertTrue(release_38.is_version_at_least_3_5) release_310 = Release.objects.create(name='Python 3.10.0') - self.assert_(release_310.is_version_at_least_3_9) - self.assert_(release_310.is_version_at_least_3_5) + self.assertTrue(release_310.is_version_at_least_3_9) + self.assertTrue(release_310.is_version_at_least_3_5) From 81e263493683c1457aecb73bdefbf3fab63cd82c Mon Sep 17 00:00:00 2001 From: code-review-doctor <72647856+code-review-doctor@users.noreply.github.com> Date: Fri, 13 Sep 2024 14:24:53 +0300 Subject: [PATCH 092/235] Fix issue avoid-misusing-assert-true found at https://codereview.doctor (#1987) Co-authored-by: Jacob Coffee --- jobs/tests/test_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jobs/tests/test_models.py b/jobs/tests/test_models.py index 310659165..5a9c5eb8d 100644 --- a/jobs/tests/test_models.py +++ b/jobs/tests/test_models.py @@ -76,7 +76,7 @@ def test_visible_manager(self): j3 = factories.ApprovedJobFactory(expires=past) visible = Job.objects.visible() - self.assertTrue(len(visible), 1) + self.assertEqual(len(visible), 1) self.assertIn(j1, visible) self.assertNotIn(j2, visible) self.assertNotIn(j3, visible) From 55bf06b928bf642e6a320dc21ba4d9dfdff30c0c Mon Sep 17 00:00:00 2001 From: Nwokolo Godwin Chidera Date: Fri, 13 Sep 2024 12:58:24 +0100 Subject: [PATCH 093/235] Update administration.rst (#1712) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update administration.rst Correct Grammatical Error Concerning Purge From Fastly.com Upon Save * Update administration.rst Correct grammatical error as it relates to the 'Jobs' section of the documentation. --------- Co-authored-by: Åukasz Langa Co-authored-by: Jacob Coffee --- docs/source/administration.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/administration.rst b/docs/source/administration.rst index 872222055..6ba820fd8 100644 --- a/docs/source/administration.rst +++ b/docs/source/administration.rst @@ -46,7 +46,7 @@ Pages are individual entire pages of markup content. They are require ``Title`` :Is Published: Controls whether or not the page is visible on the site. :Template Name: By default Pages use the template ``templates/pages/default.html`` to use a different template enter the template path here. -.. note:: Pages are automatically purge from Fastly.com upon save. +.. note:: Pages are automatically purged from Fastly.com upon save. .. _boxes: @@ -82,7 +82,7 @@ Release Files have a checkbox named 'Download button' that determines which bina Jobs ---- -The jobs application is using to display Python jobs on the site. The data items should be fairly self explanatory. There are a couple of things to keep in mind. Logged in users of the site can submit jobs for review. +The jobs application is used to display Python jobs on the site. The data items should be fairly self explanatory. There are a couple of things to keep in mind. Logged in users of the site can submit jobs for review. :Status: Jobs enter the system in 'review' status after the submitter has entered them. Only jobs in the 'approved' state are displayed on the site. :Featured: Featured jobs are displayed more prominently on the landing page. From 3627bc89603350d24ec01841a05e59926096a9a5 Mon Sep 17 00:00:00 2001 From: Levi Zim Date: Fri, 13 Sep 2024 20:00:14 +0800 Subject: [PATCH 094/235] refactor: use grep -E instead of egrep (#2141) Co-authored-by: Jacob Coffee --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dc296feb4..50585463a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ default: @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null\ | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}'\ | sort\ - | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' + | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$' @echo @exit 1 From 019c0629fd98c7ed4005387eb4ece5182995b14f Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Fri, 13 Sep 2024 09:13:25 -0400 Subject: [PATCH 095/235] upgrade allauth (#2555) bypass the migration issue around socialaccount... since we do not use that feature! --- base-requirements.txt | 2 +- pydotorg/settings/base.py | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/base-requirements.txt b/base-requirements.txt index d63743f4b..2ace94a1d 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -36,7 +36,7 @@ requests[security]>=2.26.0 django-honeypot==1.0.4 # 1.0.4 is first version that supports Django 4.2 django-markupfield==2.0.1 -django-allauth==0.57.2 # 0.55.0 is first version that supports Django 4.2 +django-allauth==64.2.1 django-waffle==2.2.1 diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 9697a6ea8..30dc8de4a 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -230,11 +230,6 @@ 'allauth', 'allauth.account', - 'allauth.socialaccount', - #'allauth.socialaccount.providers.facebook', - #'allauth.socialaccount.providers.github', - #'allauth.socialaccount.providers.openid', - #'allauth.socialaccount.providers.twitter', # Tastypie needs the `users` app to be already loaded. 'tastypie', From 68fa4c10105d3bebb3b8b11a9f4d3e1a92e99091 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Fri, 13 Sep 2024 08:24:07 -0500 Subject: [PATCH 096/235] infra: add pr template, codeowners (#2537) --- .github/CODEOWNERS | 2 ++ .github/PULL_REQUEST_TEMPLATE.md | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..de60a5f44 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# Notify @EWDurbin for all opened Issues and Pull Requests +* @EWDurbin @JacobCoffee diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..fa82b4297 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,19 @@ + +#### Description + +- + + +#### Closes + +- + From 38d9d55bbf1662780de15591eab0ba663bca376c Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Fri, 13 Sep 2024 09:41:19 -0400 Subject: [PATCH 097/235] Check collectstatic (#2554) * add a github action check to ensure collectstatic runs * install prod reqs * fallback to .python-version * explicitly set python-version-file --------- Co-authored-by: Jacob Coffee --- .github/workflows/ci.yml | 2 +- .github/workflows/static.yml | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/static.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42f8472ea..ed08f4b7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: sudo dpkg -i pandoc-2.17.1.1-1-amd64.deb - uses: actions/setup-python@v5 with: - python-version: 3.12.6 + python-version-file: '.python-version' - name: Cache Python dependencies uses: actions/cache@v4 env: diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 000000000..3207b964e --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,29 @@ +name: Check collectstatic +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version-file: '.python-version' + - name: Cache Python dependencies + uses: actions/cache@v4 + env: + cache-name: pythondotorg-cache-pip + with: + path: ~/.cache/pip + key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('requirements.txt', '*-requirements.txt') }} + restore-keys: | + ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}- + ${{ runner.os }}-${{ github.job }}- + ${{ runner.os }}- + - name: Install Python dependencies + run: | + pip install -U pip setuptools wheel + pip install -r requirements.txt -r prod-requirements.txt + - name: Run Tests + run: | + DJANGO_SETTINGS_MODULE=pydotorg.settings.static python manage.py collectstatic --noinput From e2188a104f4a6607137fd1be0e93affda45427b4 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Fri, 13 Sep 2024 10:14:43 -0400 Subject: [PATCH 098/235] pin to minor release in Dockerfiles (#2553) * pin to minor release in Dockerfiles * remove runtime.txt file this was just for Heroku... --- Dockerfile | 2 +- Dockerfile.cabotage | 2 +- runtime.txt | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 runtime.txt diff --git a/Dockerfile b/Dockerfile index b124c73ce..c701cd76c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.12-bookworm +FROM python:3.12.6-bookworm ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/Dockerfile.cabotage b/Dockerfile.cabotage index 854e3179e..9bc9d27ad 100644 --- a/Dockerfile.cabotage +++ b/Dockerfile.cabotage @@ -1,4 +1,4 @@ -FROM python:3.12-bookworm +FROM python:3.12.6-bookworm COPY --from=ewdurbin/nginx-static:1.25.x /usr/bin/nginx /usr/bin/nginx ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/runtime.txt b/runtime.txt deleted file mode 100644 index c9cbcea6f..000000000 --- a/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.9.16 From ee0a7da80a7e031e65027177faa228ed5cd85ed8 Mon Sep 17 00:00:00 2001 From: arunkumarkota Date: Fri, 13 Sep 2024 20:03:22 +0530 Subject: [PATCH 099/235] Update issue tracker link in boxes.json fixture (#2222) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Åukasz Langa Co-authored-by: Jacob Coffee --- fixtures/boxes.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fixtures/boxes.json b/fixtures/boxes.json index bc3816cc7..df66827b5 100644 --- a/fixtures/boxes.json +++ b/fixtures/boxes.json @@ -318,9 +318,9 @@ "created": "2014-02-13T17:37:50.862Z", "updated": "2014-02-16T23:01:04.762Z", "label": "widget-weneedyou", - "content": "

      >>> Python Needs You

      \r\n

      Open source software is made better when users can easily contribute code and documentation to fix bugs and add features. Python strongly encourages community involvement in improving the software. Learn more about how to make Python better for everyone.

      \r\n

      \r\n Contribute to Python\r\n Bug Tracker\r\n

      ", + "content": "

      >>> Python Needs You

      \r\n

      Open source software is made better when users can easily contribute code and documentation to fix bugs and add features. Python strongly encourages community involvement in improving the software. Learn more about how to make Python better for everyone.

      \r\n

      \r\n Contribute to Python\r\n Bug Tracker\r\n

      ", "content_markup_type": "html", - "_content_rendered": "

      >>> Python Needs You

      \r\n

      Open source software is made better when users can easily contribute code and documentation to fix bugs and add features. Python strongly encourages community involvement in improving the software. Learn more about how to make Python better for everyone.

      \r\n

      \r\n Contribute to Python\r\n Bug Tracker\r\n

      " + "_content_rendered": "

      >>> Python Needs You

      \r\n

      Open source software is made better when users can easily contribute code and documentation to fix bugs and add features. Python strongly encourages community involvement in improving the software. Learn more about how to make Python better for everyone.

      \r\n

      \r\n Contribute to Python\r\n Bug Tracker\r\n

      " } }, { From 74e659c33077839657bd702a9eb1ddd678ebc5c4 Mon Sep 17 00:00:00 2001 From: Marc-Andre Lemburg Date: Fri, 13 Sep 2024 18:10:35 +0200 Subject: [PATCH 100/235] Deal with cases where DTEND is not given in the event dict (#2024) Fixes #2021. Co-authored-by: Jacob Coffee --- events/importer.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/events/importer.py b/events/importer.py index e47775060..fe04d35f5 100644 --- a/events/importer.py +++ b/events/importer.py @@ -22,7 +22,13 @@ def import_occurrence(self, event, event_data): # but won't add any timezone information. We will convert them to # aware datetime objects manually. dt_start = extract_date_or_datetime(event_data['DTSTART'].dt) - dt_end = extract_date_or_datetime(event_data['DTEND'].dt) + if 'DTEND' in event_data: + # DTEND is not always set on events, in particular it seems that + # events which have the same start and end time, don't provide + # DTEND. See #2021. + dt_end = extract_date_or_datetime(event_data['DTEND'].dt) + else: + dt_end = dt_start # Let's mark those occurrences as 'all-day'. all_day = ( From 24ce5393c4ee5a7be238926204216bb92f0be7ec Mon Sep 17 00:00:00 2001 From: daniel carvalho <42525687+ddevdan@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:11:48 -0300 Subject: [PATCH 101/235] Fix issue #1988 - This image not being found as "/static/metro-icon-144x144-precomposed.png" (#2216) --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index b9f3df9c6..578dc1204 100644 --- a/templates/base.html +++ b/templates/base.html @@ -66,7 +66,7 @@ {# Tile icon for Win8 (144x144 + tile color) #} - + From 30f3cb43a843346c22c820ce4f87dea09d852df1 Mon Sep 17 00:00:00 2001 From: Maksudul Haque Date: Fri, 13 Sep 2024 22:24:48 +0600 Subject: [PATCH 102/235] fix: `RecurringRule` and `OccurringRule` model `__str__` method (#2166) * Fix `RecurringRule` and `OccurringRule` model `__str__` method * Update events/models.py * Update events/models.py --------- Co-authored-by: Jacob Coffee --- events/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/events/models.py b/events/models.py index 3334ca326..b41d92b22 100644 --- a/events/models.py +++ b/events/models.py @@ -237,7 +237,7 @@ class OccurringRule(RuleMixin, models.Model): def __str__(self): strftime = settings.SHORT_DATETIME_FORMAT - return f'{self.event.title} {date(self.dt_start.strftime, strftime)} - {date(self.dt_end.strftime, strftime)}' + return f'{self.event.title} {date(self.dt_start, strftime)} - {date(self.dt_end, strftime)}' @property def begin(self): @@ -283,8 +283,8 @@ class RecurringRule(RuleMixin, models.Model): all_day = models.BooleanField(default=False) def __str__(self): - strftime = settings.SHORT_DATETIME_FORMAT - return f'{self.event.title} every {timedelta_nice_repr(self.interval)} since {date(self.dt_start.strftime, strftime)}' + return (f'{self.event.title} every {timedelta_nice_repr(self.freq_interval_as_timedelta)} since ' + f'{date(self.dt_start, settings.SHORT_DATETIME_FORMAT)}') def to_rrule(self): return rrule( From 681cf0ed16c4b9fca5be1efd8ef97fc0c97d96cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:57:26 -0500 Subject: [PATCH 103/235] Bump feedparser from 6.0.8 to 6.0.11 (#2543) Bumps [feedparser](https://github.com/kurtmckee/feedparser) from 6.0.8 to 6.0.11. - [Changelog](https://github.com/kurtmckee/feedparser/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/kurtmckee/feedparser/compare/6.0.8...6.0.11) --- updated-dependencies: - dependency-name: feedparser dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jacob Coffee --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 2ace94a1d..be3e772eb 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -15,7 +15,7 @@ python-decouple==3.4 # lxml used by BeautifulSoup. lxml==5.2.2 cssselect==1.1.0 -feedparser==6.0.8 +feedparser==6.0.11 beautifulsoup4==4.11.2 icalendar==4.0.7 chardet==4.0.0 From d55e71b5cae28f7c08825875703163376e5a28c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 11:58:29 -0500 Subject: [PATCH 104/235] Bump django-widget-tweaks from 1.4.8 to 1.5.0 (#2542) Bumps [django-widget-tweaks](https://github.com/jazzband/django-widget-tweaks) from 1.4.8 to 1.5.0. - [Release notes](https://github.com/jazzband/django-widget-tweaks/releases) - [Changelog](https://github.com/jazzband/django-widget-tweaks/blob/master/CHANGES.rst) - [Commits](https://github.com/jazzband/django-widget-tweaks/compare/1.4.8...1.5.0) --- updated-dependencies: - dependency-name: django-widget-tweaks dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index be3e772eb..67736daed 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -43,7 +43,7 @@ django-waffle==2.2.1 djangorestframework==3.14.0 # 3.14.0 is first version that supports Django 4.1, 4.2 support hasnt been "released" django-filter==2.4.0 django-ordered-model==3.4.3 -django-widget-tweaks==1.4.8 +django-widget-tweaks==1.5.0 django-countries==7.2.1 num2words==0.5.10 django-polymorphic==3.1.0 # 3.1.0 is first version that supports Django 4.0, unsure if it fully supports 4.2 From 241b3b8ef188b626a4f52e56fad4cc0ab3105e05 Mon Sep 17 00:00:00 2001 From: Anuraag-CH <48093039+Anuraag-CH@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:29:47 +0530 Subject: [PATCH 105/235] Remove unused imports in downloads/tests/test_views.py (#2272) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * remove unused import * Remove another unused import in the same file --------- Co-authored-by: Åukasz Langa Co-authored-by: Jacob Coffee --- downloads/tests/test_views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/downloads/tests/test_views.py b/downloads/tests/test_views.py index e495b9e93..c585fe05c 100644 --- a/downloads/tests/test_views.py +++ b/downloads/tests/test_views.py @@ -5,11 +5,10 @@ from django.urls import reverse from django.test import TestCase, override_settings -from rest_framework.authtoken.models import Token from rest_framework.test import APITestCase from .base import BaseDownloadTests, DownloadMixin -from ..models import OS, Release +from ..models import Release from pages.factories import PageFactory from pydotorg.drf import BaseAPITestCase from users.factories import UserFactory From 3bf4a22a0cdccda65b7527838b5c76e55e23f147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:05:04 -0500 Subject: [PATCH 106/235] Bump beautifulsoup4 from 4.11.2 to 4.12.3 (#2551) Bumps [beautifulsoup4](https://www.crummy.com/software/BeautifulSoup/bs4/) from 4.11.2 to 4.12.3. --- updated-dependencies: - dependency-name: beautifulsoup4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 67736daed..4f9c0aa39 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -16,7 +16,7 @@ python-decouple==3.4 lxml==5.2.2 cssselect==1.1.0 feedparser==6.0.11 -beautifulsoup4==4.11.2 +beautifulsoup4==4.12.3 icalendar==4.0.7 chardet==4.0.0 celery[redis]==5.3.6 From 591a1ddcfa201e351fa7b112a4d5dff65ba4dcfe Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Fri, 13 Sep 2024 13:29:28 -0500 Subject: [PATCH 107/235] docs(#2480): update readme (#2559) --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5bf04cbc6..caa261e07 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,14 @@ ### General information -This is the repository and issue tracker for [python.org](https://www.python.org). -The repository for CPython itself is at https://github.com/python/cpython, and the -issue tracker is at https://github.com/python/cpython/issues/. +This is the repository and issue tracker for [python.org](https://www.python.org). -Issues related to [Python's documentation](https://docs.python.org) can be filed in -https://github.com/python/cpython/issues/. +> [!NOTE] +> The repository for CPython itself is at https://github.com/python/cpython, and the +> issue tracker is at https://github.com/python/cpython/issues/. +> +> Similarly, issues related to [Python's documentation](https://docs.python.org) can be filed in +> https://github.com/python/cpython/issues/. ### Contributing @@ -19,5 +21,4 @@ https://github.com/python/cpython/issues/. * Documentation: https://pythondotorg.readthedocs.io/ * Mailing list: [pydotorg-www](https://mail.python.org/mailman/listinfo/pydotorg-www) * IRC: `#pydotorg` on Freenode -* Staging site: https://staging.python.org/ (`main` branch) * License: Apache License From af33d311fc5d58658f8c99084f3b19371c25e919 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Mon, 16 Sep 2024 09:02:04 -0400 Subject: [PATCH 108/235] Remove peps app. (#2552) all peps were moved to peps.python.org, so this machinery is no longer necessary --- peps/__init__.py | 0 peps/apps.py | 6 - peps/converters.py | 262 ----- peps/management/__init__.py | 0 peps/management/commands/__init__.py | 0 peps/management/commands/dump_pep_pages.py | 21 - .../management/commands/generate_pep_pages.py | 143 --- peps/models.py | 1 - peps/templatetags/__init__.py | 0 peps/templatetags/peps.py | 16 - peps/tests/__init__.py | 6 - peps/tests/peps.tar.gz | Bin 46010 -> 0 bytes peps/tests/peps/pep-0000.html | 1030 ----------------- peps/tests/peps/pep-0012.html | 53 - peps/tests/peps/pep-0012.rst | 33 - peps/tests/peps/pep-0525.html | 595 ---------- peps/tests/peps/pep-3001-1.png | Bin 14117 -> 0 bytes peps/tests/peps/pep-3001.html | 140 --- peps/tests/test_commands.py | 56 - peps/tests/test_converters.py | 64 - pydotorg/settings/base.py | 5 - templates/components/pep-widget.html | 19 - templates/python/documentation.html | 3 - templates/python/index.html | 2 - 24 files changed, 2455 deletions(-) delete mode 100644 peps/__init__.py delete mode 100644 peps/apps.py delete mode 100644 peps/converters.py delete mode 100644 peps/management/__init__.py delete mode 100644 peps/management/commands/__init__.py delete mode 100644 peps/management/commands/dump_pep_pages.py delete mode 100644 peps/management/commands/generate_pep_pages.py delete mode 100644 peps/models.py delete mode 100644 peps/templatetags/__init__.py delete mode 100644 peps/templatetags/peps.py delete mode 100644 peps/tests/__init__.py delete mode 100644 peps/tests/peps.tar.gz delete mode 100644 peps/tests/peps/pep-0000.html delete mode 100644 peps/tests/peps/pep-0012.html delete mode 100644 peps/tests/peps/pep-0012.rst delete mode 100644 peps/tests/peps/pep-0525.html delete mode 100644 peps/tests/peps/pep-3001-1.png delete mode 100644 peps/tests/peps/pep-3001.html delete mode 100644 peps/tests/test_commands.py delete mode 100644 peps/tests/test_converters.py delete mode 100644 templates/components/pep-widget.html diff --git a/peps/__init__.py b/peps/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/peps/apps.py b/peps/apps.py deleted file mode 100644 index a59996f2a..000000000 --- a/peps/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class PepsAppConfig(AppConfig): - - name = 'peps' diff --git a/peps/converters.py b/peps/converters.py deleted file mode 100644 index 1d63d7438..000000000 --- a/peps/converters.py +++ /dev/null @@ -1,262 +0,0 @@ -import functools -import datetime -import re -import os - -from bs4 import BeautifulSoup - -from django.conf import settings -from django.core.exceptions import ImproperlyConfigured -from django.core.files import File -from django.db.models import Max - -from pages.models import Page, Image - -PEP_TEMPLATE = 'pages/pep-page.html' -pep_url = lambda num: f'dev/peps/pep-{num}/' - - -def get_peps_last_updated(): - last_update = Page.objects.filter( - path__startswith='dev/peps', - ).aggregate(Max('updated')).get('updated__max') - if last_update is None: - return datetime.datetime( - 1970, 1, 1, tzinfo=datetime.timezone( - datetime.timedelta(0) - ) - ) - return last_update - - -def convert_pep0(artifact_path): - """ - Take existing generated pep-0000.html and convert to something suitable - for a Python.org Page returns the core body HTML necessary only - """ - pep0_path = os.path.join(artifact_path, 'pep-0000.html') - pep0_content = open(pep0_path).read() - data = convert_pep_page(0, pep0_content) - if data is None: - return - return data['content'] - - -def get_pep0_page(artifact_path, commit=True): - """ - Using convert_pep0 above, create a CMS ready pep0 page and return it - - pep0 is used as the directory index, but it's also an actual pep, so we - return both Page objects. - """ - pep0_content = convert_pep0(artifact_path) - if pep0_content is None: - return None, None - pep0_page, _ = Page.objects.get_or_create(path='dev/peps/') - pep0000_page, _ = Page.objects.get_or_create(path='dev/peps/pep-0000/') - for page in [pep0_page, pep0000_page]: - page.content = pep0_content - page.content_markup_type = 'html' - page.title = "PEP 0 -- Index of Python Enhancement Proposals (PEPs)" - page.template_name = PEP_TEMPLATE - - if commit: - page.save() - - return pep0_page, pep0000_page - - -def fix_headers(soup, data): - """ Remove empty or unwanted headers and find our title """ - header_rows = soup.find_all('th') - for t in header_rows: - if 'Version:' in t.text: - if t.next_sibling.text == '$Revision$': - t.parent.extract() - if t.next_sibling.text == '': - t.parent.extract() - if 'Last-Modified:' in t.text: - if '$Date$'in t.next_sibling.text: - t.parent.extract() - if t.next_sibling.text == '': - t.parent.extract() - if t.text == 'Title:': - data['title'] = t.next_sibling.text - if t.text == 'Content-Type:': - t.parent.extract() - if 'Version:' in t.text and 'N/A' in t.next_sibling.text: - t.parent.extract() - - return soup, data - - -def convert_pep_page(pep_number, content): - """ - Handle different formats that pep2html.py outputs - """ - data = { - 'title': None, - } - # Remove leading zeros from PEP number for display purposes - pep_number_humanize = re.sub(r'^0+', '', str(pep_number)) - - if '' in content: - soup = BeautifulSoup(content, 'lxml') - data['title'] = soup.title.text - - if not re.search(r'PEP \d+', data['title']): - data['title'] = 'PEP {} -- {}'.format( - pep_number_humanize, - soup.title.text, - ) - - header = soup.body.find('div', class_="header") - header, data = fix_headers(header, data) - data['header'] = str(header) - - main_content = soup.body.find('div', class_="content") - - data['main_content'] = str(main_content) - data['content'] = ''.join([ - data['header'], - data['main_content'] - ]) - - else: - soup = BeautifulSoup(content, 'lxml') - - soup, data = fix_headers(soup, data) - if not data['title']: - data['title'] = f"PEP {pep_number_humanize} -- " - else: - if not re.search(r'PEP \d+', data['title']): - data['title'] = "PEP {} -- {}".format( - pep_number_humanize, - data['title'], - ) - - data['content'] = str(soup) - - # Fix PEP links - pep_content = BeautifulSoup(data['content'], 'lxml') - body_links = pep_content.find_all("a") - - pep_href_re = re.compile(r'pep-(\d+)\.html') - - for b in body_links: - m = pep_href_re.search(b.attrs['href']) - - # Skip anything not matching 'pep-XXXX.html' - if not m: - continue - - b.attrs['href'] = f'/dev/peps/pep-{m.group(1)}/' - - # Return early if 'html' or 'body' return None. - if pep_content.html is None or pep_content.body is None: - return - - # Strip and tags. - pep_content.html.unwrap() - pep_content.body.unwrap() - - data['content'] = str(pep_content) - return data - - -def get_pep_page(artifact_path, pep_number, commit=True): - """ - Given a pep_number retrieve original PEP source text, rst, or html. - Get or create the associated Page and return it - """ - pep_path = os.path.join(artifact_path, f'pep-{pep_number}.html') - if not os.path.exists(pep_path): - print(f"PEP Path '{pep_path}' does not exist, skipping") - return - - pep_content = convert_pep_page(pep_number, open(pep_path).read()) - if pep_content is None: - return None - pep_rst_source = os.path.join( - artifact_path, f'pep-{pep_number}.rst', - ) - pep_ext = '.rst' if os.path.exists(pep_rst_source) else '.txt' - source_link = 'https://github.com/python/peps/blob/master/pep-{}{}'.format( - pep_number, pep_ext) - pep_content['content'] += """Source: {0}""".format(source_link) - - pep_page, _ = Page.objects.get_or_create(path=pep_url(pep_number)) - - pep_page.title = pep_content['title'] - - pep_page.content = pep_content['content'] - pep_page.content_markup_type = 'html' - pep_page.template_name = PEP_TEMPLATE - - if commit: - pep_page.save() - - return pep_page - - -def add_pep_image(artifact_path, pep_number, path): - image_path = os.path.join(artifact_path, path) - if not os.path.exists(image_path): - print(f"Image Path '{image_path}' does not exist, skipping") - return - - try: - page = Page.objects.get(path=pep_url(pep_number)) - except Page.DoesNotExist: - print(f"Could not find backing PEP {pep_number}") - return - - # Find existing images, we have to loop here as we can't use the ORM - # to query against image__path - existing_images = Image.objects.filter(page=page) - - FOUND = False - for image in existing_images: - if image.image.name.endswith(path): - FOUND = True - break - - if not FOUND: - image = Image(page=page) - - with open(image_path, 'rb') as image_obj: - image.image.save(path, File(image_obj)) - image.save() - - # Old images used to live alongside html, but now they're in different - # places, so update the page accordingly. - soup = BeautifulSoup(page.content.raw, 'lxml') - for img_tag in soup.findAll('img'): - if img_tag['src'] == path: - img_tag['src'] = image.image.url - - page.content.raw = str(soup) - page.save() - - return image - - -def get_peps_rss(artifact_path): - rss_feed = os.path.join(artifact_path, 'peps.rss') - if not os.path.exists(rss_feed): - return - - page, _ = Page.objects.get_or_create( - path="dev/peps/peps.rss", - template_name="pages/raw.html", - ) - - with open(rss_feed) as rss_content: - content = rss_content.read() - - page.content = content - page.is_published = True - page.content_type = "application/rss+xml" - page.save() - - return page diff --git a/peps/management/__init__.py b/peps/management/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/peps/management/commands/__init__.py b/peps/management/commands/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/peps/management/commands/dump_pep_pages.py b/peps/management/commands/dump_pep_pages.py deleted file mode 100644 index 549b8faa4..000000000 --- a/peps/management/commands/dump_pep_pages.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.core import serializers -from django.core.management import BaseCommand - -from pages.models import Page - - -class Command(BaseCommand): - """ - Dump PEP related Pages as indented JSON - """ - help = "Dump PEP related Pages as indented JSON" - - def handle(self, **options): - qs = Page.objects.filter(path__startswith='dev/peps/') - - serializers.serialize( - format='json', - queryset=qs, - indent=4, - stream=self.stdout, - ) diff --git a/peps/management/commands/generate_pep_pages.py b/peps/management/commands/generate_pep_pages.py deleted file mode 100644 index 9f9010584..000000000 --- a/peps/management/commands/generate_pep_pages.py +++ /dev/null @@ -1,143 +0,0 @@ -import re -import os - -from contextlib import ExitStack -from tarfile import TarFile -from tempfile import TemporaryDirectory, TemporaryFile - -import requests - -from django.core.management import BaseCommand -from django.conf import settings - -from dateutil.parser import parse as parsedate - -from peps.converters import ( - get_pep0_page, get_pep_page, add_pep_image, get_peps_rss, get_peps_last_updated -) - -pep_number_re = re.compile(r'pep-(\d+)') - - -class Command(BaseCommand): - """ - Generate CMS Pages from flat file PEP data. - - Run this command AFTER normal RST -> HTML PEP transformation from the PEP - repository has happened. This works on the HTML files created during that - process. - - For verbose output run this with: - - ./manage.py generate_pep_pages --verbosity=2 - """ - help = "Generate PEP Page objects from rendered HTML" - - def is_pep_page(self, path): - return path.startswith('pep-') and path.endswith('.html') - - def is_image(self, path): - # All images are pngs - return path.endswith('.png') - - def handle(self, **options): - verbosity = int(options['verbosity']) - - def verbose(msg): - """ Output wrapper """ - if verbosity > 1: - print(msg) - - verbose("== Starting PEP page generation") - - with ExitStack() as stack: - if settings.PEP_REPO_PATH is not None: - artifacts_path = settings.PEP_REPO_PATH - else: - verbose(f"== Fetching PEP artifact from {settings.PEP_ARTIFACT_URL}") - temp_file = self.get_artifact_tarball(stack) - if not temp_file: - verbose("== No update to artifacts, we're done here!") - return - temp_dir = stack.enter_context(TemporaryDirectory()) - tar_ball = stack.enter_context(TarFile.open(fileobj=temp_file, mode='r:gz')) - tar_ball.extractall(path=temp_dir, numeric_owner=False) - - artifacts_path = os.path.join(temp_dir, 'peps') - - verbose("Generating RSS Feed") - peps_rss = get_peps_rss(artifacts_path) - if not peps_rss: - verbose("Could not find generated RSS feed. Skipping.") - - verbose("Generating PEP0 index page") - pep0_page, _ = get_pep0_page(artifacts_path) - if pep0_page is None: - verbose("HTML version of PEP 0 cannot be generated.") - return - - image_paths = set() - - # Find pep pages - for f in os.listdir(artifacts_path): - - if self.is_image(f): - verbose(f"- Deferring import of image '{f}'") - image_paths.add(f) - continue - - # Skip files we aren't looking for - if not self.is_pep_page(f): - verbose(f"- Skipping non-PEP file '{f}'") - continue - - if 'pep-0000.html' in f: - verbose("- Skipping duplicate PEP0 index") - continue - - verbose(f"Generating PEP Page from '{f}'") - pep_match = pep_number_re.match(f) - if pep_match: - pep_number = pep_match.groups(1)[0] - p = get_pep_page(artifacts_path, pep_number) - if p is None: - verbose( - "- HTML version PEP {!r} cannot be generated.".format( - pep_number - ) - ) - verbose(f"====== Title: '{p.title}'") - else: - verbose(f"- Skipping invalid '{f}'") - - # Find pep images. This needs to happen afterwards, because we need - for img in image_paths: - pep_match = pep_number_re.match(img) - if pep_match: - pep_number = pep_match.groups(1)[0] - verbose("Generating image for PEP {} at '{}'".format( - pep_number, img)) - add_pep_image(artifacts_path, pep_number, img) - else: - verbose(f"- Skipping non-PEP related image '{img}'") - - verbose("== Finished") - - def get_artifact_tarball(self, stack): - artifact_url = settings.PEP_ARTIFACT_URL - if not artifact_url.startswith(('http://', 'https://')): - return stack.enter_context(open(artifact_url, 'rb')) - - peps_last_updated = get_peps_last_updated() - with requests.get(artifact_url, stream=True) as r: - artifact_last_modified = parsedate(r.headers['last-modified']) - if peps_last_updated > artifact_last_modified: - return - - temp_file = stack.enter_context(TemporaryFile()) - for chunk in r.iter_content(chunk_size=8192): - if chunk: - temp_file.write(chunk) - - temp_file.seek(0) - return temp_file diff --git a/peps/models.py b/peps/models.py deleted file mode 100644 index e45cd9cd1..000000000 --- a/peps/models.py +++ /dev/null @@ -1 +0,0 @@ -# Intentially left blank diff --git a/peps/templatetags/__init__.py b/peps/templatetags/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/peps/templatetags/peps.py b/peps/templatetags/peps.py deleted file mode 100644 index 9d90afe24..000000000 --- a/peps/templatetags/peps.py +++ /dev/null @@ -1,16 +0,0 @@ -from django import template - -from pages.models import Page - -register = template.Library() - - -@register.simple_tag -def get_newest_pep_pages(limit=5): - """ Retrieve the most recently added PEPs """ - latest_peps = Page.objects.filter( - path__startswith='dev/peps/', - is_published=True, - ).order_by('-created')[:limit] - - return latest_peps diff --git a/peps/tests/__init__.py b/peps/tests/__init__.py deleted file mode 100644 index 944cc90aa..000000000 --- a/peps/tests/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -import os - -from django.conf import settings - -FAKE_PEP_REPO = os.path.join(settings.BASE, 'peps/tests/peps/') -FAKE_PEP_ARTIFACT = os.path.join(settings.BASE, 'peps/tests/peps.tar.gz') diff --git a/peps/tests/peps.tar.gz b/peps/tests/peps.tar.gz deleted file mode 100644 index edaa86b79a67945ecf960d06657e6453f6657916..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46010 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 K3_LUdSONgDYY=k) diff --git a/peps/tests/peps/pep-0000.html b/peps/tests/peps/pep-0000.html deleted file mode 100644 index c11c027c9..000000000 --- a/peps/tests/peps/pep-0000.html +++ /dev/null @@ -1,1030 +0,0 @@ - - - - - PEP 0 -- Index of Python Enhancement Proposals (PEPs) - - - - - - -
      - - - - - - - - - -
      PEP: 0
      Title: Index of Python Enhancement Proposals (PEPs)
      Version: N/A
      Last-Modified: 2014-09-26
      Author: David Goodger <goodger at python.org>, Barry Warsaw <barry at python.org>
      Status: Active
      Type: Informational
      Created: 13-Jul-2000
      -
      -
      -
      -

      Introduction

      -
      -    This PEP contains the index of all Python Enhancement Proposals,
      -    known as PEPs.  PEP numbers are assigned by the PEP editors, and
      -    once assigned are never changed[1].  The Mercurial history[2] of
      -    the PEP texts represent their historical record.
      -
      -
      -
      -

      Index by Category

      -
      -     num  title                                                   owner
      -     ---  -----                                                   -----
      -
      - Meta-PEPs (PEPs about PEPs or Processes)
      -
      - P     1  PEP Purpose and Guidelines                              Warsaw, Hylton, Goodger, Coghlan
      - P     4  Deprecation of Standard Modules                         von Löwis
      - P     5  Guidelines for Language Evolution                       Prescod
      - P     6  Bug Fix Releases                                        Aahz, Baxter
      - P     7  Style Guide for C Code                                  GvR
      - P     8  Style Guide for Python Code                             GvR, Warsaw, Coghlan
      - P     9  Sample Plaintext PEP Template                           Warsaw
      - P    10  Voting Guidelines                                       Warsaw
      - P    11  Removing support for little used platforms              von Löwis
      - P    12  Sample reStructuredText PEP Template                    Goodger, Warsaw
      -
      - Other Informational PEPs
      -
      - I    20  The Zen of Python                                       Peters
      - I   101  Doing Python Releases 101                               Warsaw, GvR
      - IF  247  API for Cryptographic Hash Functions                    Kuchling
      - IF  248  Python Database API Specification v1.0                  Lemburg
      - IF  249  Python Database API Specification v2.0                  Lemburg
      - I   257  Docstring Conventions                                   Goodger, GvR
      - IF  272  API for Block Encryption Algorithms v1.0                Kuchling
      - I   287  reStructuredText Docstring Format                       Goodger
      - I   290  Code Migration and Modernization                        Hettinger
      - IF  291  Backward Compatibility for the Python 2 Standard ...    Norwitz
      - IF  333  Python Web Server Gateway Interface v1.0                Eby
      - I   373  Python 2.7 Release Schedule                             Peterson
      - I   392  Python 3.2 Release Schedule                             Brandl
      - I   394  The "python" Command on Unix-Like Systems               Staley, Coghlan
      - I   398  Python 3.3 Release Schedule                             Brandl
      - IF  399  Pure Python/C Accelerator Module Compatibility ...      Cannon
      - IF  404  Python 2.8 Un-release Schedule                          Warsaw
      - IA  411  Provisional packages in the Python standard library     Coghlan, Bendersky
      - I   429  Python 3.4 Release Schedule                             Hastings
      - IF  430  Migrating to Python 3 as the default online ...         Coghlan
      - I   434  IDLE Enhancement Exception for All Branches             Rovito, Reedy
      - IA  440  Version Identification and Dependency Specification     Coghlan, Stufft
      - I   478  Python 3.5 Release Schedule                             Hastings
      - IF 3333  Python Web Server Gateway Interface v1.0.1              Eby
      -
      - Accepted PEPs (accepted; may not be implemented yet)
      -
      - SA  345  Metadata for Python Software Packages 1.2               Jones
      - SA  376  Database of Installed Python Distributions              Ziadé
      - SA  425  Compatibility Tags for Built Distributions              Holth
      - SA  427  The Wheel Binary Package Format 1.0                     Holth
      - SA  461  Adding % formatting to bytes and bytearray              Furman
      - SA  471  os.scandir() function -- a better and faster ...        Hoyt
      - SA  477  Backport ensurepip (PEP 453) to Python 2.7              Stufft, Coghlan
      - SA 3121  Extension Module Initialization and Finalization        von Löwis
      -
      - Open PEPs (under consideration)
      -
      - S   381  Mirroring infrastructure for PyPI                       Ziadé, v. Löwis
      - P   387  Backwards Compatibility Policy                          Peterson
      - S   426  Metadata for Python Software Packages 2.0               Coghlan, Holth, Stufft
      - S   431  Time zone support improvements                          Regebro
      - S   432  Simplifying the CPython startup sequence                Coghlan
      - S   436  The Argument Clinic DSL                                 Hastings
      - S   441  Improving Python ZIP Application Support                Holth
      - S   447  Add __getdescriptor__ method to metaclass               Oussoren
      - S   448  Additional Unpacking Generalizations                    Landau
      - I   452  API for Cryptographic Hash Functions v2.0               Kuchling, Heimes
      - S   455  Adding a key-transforming dictionary to collections     Pitrou
      - I   457  Syntax For Positional-Only Parameters                   Hastings
      - S   458  Surviving a Compromise of PyPI                          Kuppusamy, Stufft, Cappos
      - S   459  Standard Metadata Extensions for Python Software ...    Coghlan
      - S   463  Exception-catching expressions                          Angelico
      - S   467  Minor API improvements for binary sequences             Coghlan
      - S   468  Preserving the order of \*\*kwargs in a function.       Snow
      - P   470  Using Multi Index Support for External to PyPI ...      Stufft
      - S   472  Support for indexing with keyword arguments             Borini, Martinot-Lagarde
      - S   473  Adding structured data to built-in exceptions           Kreft
      - S   475  Retry system calls failing with EINTR                   Natali, Stinner
      - S   476  Enabling certificate verification by default for ...    Gaynor
      -
      - Finished PEPs (done, implemented in code repository)
      -
      - SF  100  Python Unicode Integration                              Lemburg
      - SF  201  Lockstep Iteration                                      Warsaw
      - SF  202  List Comprehensions                                     Warsaw
      - SF  203  Augmented Assignments                                   Wouters
      - SF  205  Weak References                                         Drake
      - SF  207  Rich Comparisons                                        GvR, Ascher
      - SF  208  Reworking the Coercion Model                            Schemenauer, Lemburg
      - SF  214  Extended Print Statement                                Warsaw
      - SF  217  Display Hook for Interactive Use                        Zadka
      - SF  218  Adding a Built-In Set Object Type                       Wilson, Hettinger
      - SF  221  Import As                                               Wouters
      - SF  223  Change the Meaning of \x Escapes                        Peters
      - SF  227  Statically Nested Scopes                                Hylton
      - SF  229  Using Distutils to Build Python                         Kuchling
      - SF  230  Warning Framework                                       GvR
      - SF  232  Function Attributes                                     Warsaw
      - SF  234  Iterators                                               Yee, GvR
      - SF  235  Import on Case-Insensitive Platforms                    Peters
      - SF  236  Back to the __future__                                  Peters
      - SF  237  Unifying Long Integers and Integers                     Zadka, GvR
      - SF  238  Changing the Division Operator                          Zadka, GvR
      - SF  241  Metadata for Python Software Packages                   Kuchling
      - SF  250  Using site-packages on Windows                          Moore
      - SF  252  Making Types Look More Like Classes                     GvR
      - SF  253  Subtyping Built-in Types                                GvR
      - SF  255  Simple Generators                                       Schemenauer, Peters, Hetland
      - SF  260  Simplify xrange()                                       GvR
      - SF  261  Support for "wide" Unicode characters                   Prescod
      - SF  263  Defining Python Source Code Encodings                   Lemburg, von Löwis
      - SF  264  Future statements in simulated shells                   Hudson
      - SF  273  Import Modules from Zip Archives                        Ahlstrom
      - SF  274  Dict Comprehensions                                     Warsaw
      - SF  277  Unicode file name support for Windows NT                Hodgson
      - SF  278  Universal Newline Support                               Jansen
      - SF  279  The enumerate() built-in function                       Hettinger
      - SF  282  A Logging System                                        Sajip, Mick
      - SF  285  Adding a bool type                                      GvR
      - SF  289  Generator Expressions                                   Hettinger
      - SF  292  Simpler String Substitutions                            Warsaw
      - SF  293  Codec Error Handling Callbacks                          Dörwald
      - SF  301  Package Index and Metadata for Distutils                Jones
      - SF  302  New Import Hooks                                        JvR, Moore
      - SF  305  CSV File API                                            Altis, Cole, McNamara, Montanaro, Wells
      - SF  307  Extensions to the pickle protocol                       GvR, Peters
      - SF  308  Conditional Expressions                                 GvR, Hettinger
      - SF  309  Partial Function Application                            Harris
      - SF  311  Simplified Global Interpreter Lock Acquisition for ...  Hammond
      - SF  314  Metadata for Python Software Packages v1.1              Kuchling, Jones
      - SF  318  Decorators for Functions and Methods                    Smith
      - SF  322  Reverse Iteration                                       Hettinger
      - SF  324  subprocess - New process module                         Astrand
      - SF  327  Decimal Data Type                                       Batista
      - SF  328  Imports: Multi-Line and Absolute/Relative               Aahz
      - SF  331  Locale-Independent Float/String Conversions             Reis
      - SF  338  Executing modules as scripts                            Coghlan
      - SF  341  Unifying try-except and try-finally                     Brandl
      - SF  342  Coroutines via Enhanced Generators                      GvR, Eby
      - SF  343  The "with" Statement                                    GvR, Coghlan
      - SF  352  Required Superclass for Exceptions                      Cannon, GvR
      - SF  353  Using ssize_t as the index type                         von Löwis
      - SF  357  Allowing Any Object to be Used for Slicing              Oliphant
      - SF  358  The "bytes" Object                                      Schemenauer, GvR
      - SF  362  Function Signature Object                               Cannon, Seo, Selivanov, Hastings
      - SF  366  Main module explicit relative imports                   Coghlan
      - SF  370  Per user site-packages directory                        Heimes
      - SF  371  Addition of the multiprocessing package to the ...      Noller, Oudkerk
      - SF  372  Adding an ordered dictionary to collections             Ronacher, Hettinger
      - SF  378  Format Specifier for Thousands Separator                Hettinger
      - SF  380  Syntax for Delegating to a Subgenerator                 Ewing
      - SF  383  Non-decodable Bytes in System Character Interfaces      v. Löwis
      - SF  384  Defining a Stable ABI                                   v. Löwis
      - SF  389  argparse - New Command Line Parsing Module              Bethard
      - SF  391  Dictionary-Based Configuration For Logging              Sajip
      - SF  393  Flexible String Representation                          v. Löwis
      - SF  397  Python launcher for Windows                             Hammond, v. Löwis
      - SF  405  Python Virtual Environments                             Meyer
      - SF  409  Suppressing exception context                           Furman
      - SF  412  Key-Sharing Dictionary                                  Shannon
      - SF  414  Explicit Unicode Literal for Python 3.3                 Ronacher, Coghlan
      - SF  415  Implement context suppression with exception attributes Peterson
      - SF  417  Including mock in the Standard Library                  Foord
      - SF  418  Add monotonic time, performance counter, and ...        Simpson, Jewett, Turnbull, Stinner
      - SF  420  Implicit Namespace Packages                             Smith
      - SF  421  Adding sys.implementation                               Snow
      - SF  424  A method for exposing a length hint                     Gaynor
      - SF  428  The pathlib module -- object-oriented filesystem paths  Pitrou
      - SF  435  Adding an Enum type to the Python standard library      Warsaw, Bendersky, Furman
      - SF  442  Safe object finalization                                Pitrou
      - SF  443  Single-dispatch generic functions                       Langa
      - SF  445  Add new APIs to customize Python memory allocators      Stinner
      - SF  446  Make newly created file descriptors non-inheritable     Stinner
      - SF  450  Adding A Statistics Module To The Standard Library      D'Aprano
      - SF  451  A ModuleSpec Type for the Import System                 Snow
      - SF  453  Explicit bootstrapping of pip in Python installations   Stufft, Coghlan
      - SF  454  Add a new tracemalloc module to trace Python memory ... Stinner
      - SF  456  Secure and interchangeable hash algorithm               Heimes
      - SF  465  A dedicated infix operator for matrix multiplication    Smith
      - SF  466  Network Security Enhancements for Python 2.7.x          Coghlan
      - SF 3101  Advanced String Formatting                              Talin
      - SF 3102  Keyword-Only Arguments                                  Talin
      - SF 3104  Access to Names in Outer Scopes                         Yee
      - SF 3105  Make print a function                                   Brandl
      - SF 3106  Revamping dict.keys(), .values() and .items()           GvR
      - SF 3107  Function Annotations                                    Winter, Lownds
      - SF 3108  Standard Library Reorganization                         Cannon
      - SF 3109  Raising Exceptions in Python 3000                       Winter
      - SF 3110  Catching Exceptions in Python 3000                      Winter
      - SF 3111  Simple input built-in in Python 3000                    Roberge
      - SF 3112  Bytes literals in Python 3000                           Orendorff
      - SF 3113  Removal of Tuple Parameter Unpacking                    Cannon
      - SF 3114  Renaming iterator.next() to iterator.__next__()         Yee
      - SF 3115  Metaclasses in Python 3000                              Talin
      - SF 3116  New I/O                                                 Stutzbach, GvR, Verdone
      - SF 3118  Revising the buffer protocol                            Oliphant, Banks
      - SF 3119  Introducing Abstract Base Classes                       GvR, Talin
      - SF 3120  Using UTF-8 as the default source encoding              von Löwis
      - SF 3123  Making PyObject_HEAD conform to standard C              von Löwis
      - SF 3127  Integer Literal Support and Syntax                      Maupin
      - SF 3129  Class Decorators                                        Winter
      - SF 3131  Supporting Non-ASCII Identifiers                        von Löwis
      - SF 3132  Extended Iterable Unpacking                             Brandl
      - SF 3134  Exception Chaining and Embedded Tracebacks              Yee
      - SF 3135  New Super                                               Spealman, Delaney, Ryan
      - SF 3137  Immutable Bytes and Mutable Buffer                      GvR
      - SF 3138  String representation in Python 3000                    Ishimoto
      - SF 3141  A Type Hierarchy for Numbers                            Yasskin
      - SF 3144  IP Address Manipulation Library for the Python ...      Moody
      - SF 3147  PYC Repository Directories                              Warsaw
      - SF 3148  futures - execute computations asynchronously           Quinlan
      - SF 3149  ABI version tagged .so files                            Warsaw
      - SF 3151  Reworking the OS and IO exception hierarchy             Pitrou
      - SF 3154  Pickle protocol version 4                               Pitrou
      - SF 3155  Qualified name for classes and functions                Pitrou
      - SF 3156  Asynchronous IO Support Rebooted: the "asyncio" Module  GvR
      -
      - Historical Meta-PEPs and Informational PEPs
      -
      - PF    2  Procedure for Adding New Modules                        Faassen
      - PF   42  Feature Requests                                        Hylton
      - IF  160  Python 1.6 Release Schedule                             Drake
      - IF  200  Python 2.0 Release Schedule                             Hylton
      - IF  226  Python 2.1 Release Schedule                             Hylton
      - IF  251  Python 2.2 Release Schedule                             Warsaw, GvR
      - IF  283  Python 2.3 Release Schedule                             GvR
      - IF  320  Python 2.4 Release Schedule                             Warsaw, Hettinger, Baxter
      - PF  347  Migrating the Python CVS to Subversion                  von Löwis
      - IF  356  Python 2.5 Release Schedule                             Norwitz, GvR, Baxter
      - PF  360  Externally Maintained Packages                          Cannon
      - IF  361  Python 2.6 and 3.0 Release Schedule                     Norwitz, Warsaw
      - PF  374  Choosing a distributed VCS for the Python project       Cannon, Turnbull, Vassalotti, Warsaw, Ochtman
      - IF  375  Python 3.1 Release Schedule                             Peterson
      - PF  385  Migrating from Subversion to Mercurial                  Ochtman, Pitrou, Brandl
      - PA  438  Transitioning to release-file hosting on PyPI           Krekel, Meyer
      - PA  449  Removal of the PyPI Mirror Auto Discovery and ...       Stufft
      - PA  464  Removal of the PyPI Mirror Authenticity API             Stufft
      - PF 3000  Python 3000                                             GvR
      - PF 3002  Procedure for Backwards-Incompatible Changes            Bethard
      - PF 3003  Python Language Moratorium                              Cannon, Noller, GvR
      - PF 3099  Things that will Not Change in Python 3000              Brandl
      - PF 3100  Miscellaneous Python 3.0 Plans                          Cannon
      -
      - Deferred PEPs
      -
      - SD  211  Adding A New Outer Product Operator                     Wilson
      - SD  212  Loop Counter Iteration                                  Schneider-Kamp
      - SD  213  Attribute Access Handlers                               Prescod
      - SD  219  Stackless Python                                        McMillan
      - SD  222  Web Library Enhancements                                Kuchling
      - SD  225  Elementwise/Objectwise Operators                        Zhu, Lielens
      - SD  233  Python Online Help                                      Prescod
      - SD  262  A Database of Installed Python Packages                 Kuchling
      - SD  267  Optimized Access to Module Namespaces                   Hylton
      - SD  269  Pgen Module for Python                                  Riehl
      - SD  280  Optimizing access to globals                            GvR
      - SD  286  Enhanced Argument Tuples                                von Löwis
      - SD  312  Simple Implicit Lambda                                  Suzi, Martelli
      - SD  316  Programming by Contract for Python                      Way
      - SD  323  Copyable Iterators                                      Martelli
      - SD  337  Logging Usage in the Standard Library                   Dubner
      - SD  349  Allow str() to return unicode strings                   Schemenauer
      - SD  368  Standard image protocol and class                       Mastrodomenico
      - ID  396  Module Version Numbers                                  Warsaw
      - SD  400  Deprecate codecs.StreamReader and codecs.StreamWriter   Stinner
      - SD  403  General purpose decorator clause (aka "@in" clause)     Coghlan
      - PD  407  New release cycle and introducing long-term support ... Pitrou, Brandl, Warsaw
      - SD  419  Protecting cleanup statements from interruptions        Colomiets
      - SD  422  Simpler customisation of class creation                 Coghlan, Urban
      - ID  423  Naming conventions and recipes related to packaging     Bryon
      - ID  444  Python Web3 Interface                                   McDonough, Ronacher
      - PD  462  Core development workflow automation for CPython        Coghlan
      - PD  474  Creating forge.python.org                               Coghlan
      - SD  628  Add ``math.tau``                                        Coghlan
      - SD 3124  Overloading, Generic Functions, Interfaces, and ...     Eby
      - SD 3143  Standard daemon process library                         Finney
      - SD 3150  Statement local namespaces (aka "given" clause)         Coghlan
      - SD 3152  Cofunctions                                             Ewing
      -
      - Abandoned, Withdrawn, and Rejected PEPs
      -
      - PW    3  Guidelines for Handling Bug Reports                     Hylton
      - IS  102  Doing Python Micro Releases                             Baxter, Warsaw, GvR
      - SR  204  Range Literals                                          Wouters
      - IW  206  Python Advanced Library                                 Kuchling
      - SW  209  Multi-dimensional Arrays                                Barrett, Oliphant
      - SR  210  Decoupling the Interpreter Loop                         Ascher
      - SS  215  String Interpolation                                    Yee
      - IR  216  Docstring Format                                        Zadka
      - IR  220  Coroutines, Generators, Continuations                   McMillan
      - SR  224  Attribute Docstrings                                    Lemburg
      - SW  228  Reworking Python's Numeric Model                        Zadka, GvR
      - SR  231  __findattr__()                                          Warsaw
      - SR  239  Adding a Rational Type to Python                        Craig, Zadka
      - SR  240  Adding a Rational Literal to Python                     Craig, Zadka
      - SR  242  Numeric Kinds                                           Dubois
      - SW  243  Module Repository Upload Mechanism                      Reifschneider
      - SR  244  The `directive' statement                               von Löwis
      - SR  245  Python Interface Syntax                                 Pelletier
      - SR  246  Object Adaptation                                       Martelli, Evans
      - SR  254  Making Classes Look More Like Types                     GvR
      - SR  256  Docstring Processing System Framework                   Goodger
      - SR  258  Docutils Design Specification                           Goodger
      - SR  259  Omit printing newline after newline                     GvR
      - SR  265  Sorting Dictionaries by Value                           Griffin
      - SW  266  Optimizing Global Variable/Attribute Access             Montanaro
      - SR  268  Extended HTTP functionality and WebDAV                  Stein
      - SR  270  uniq method for list objects                            Petrone
      - SR  271  Prefixing sys.path by command line option               Giacometti
      - SR  275  Switching on Multiple Values                            Lemburg
      - SR  276  Simple Iterator for ints                                Althoff
      - SR  281  Loop Counter Iteration with range and xrange            Hetland
      - SR  284  Integer for-loops                                       Eppstein, Ewing
      - SW  288  Generators Attributes and Exceptions                    Hettinger
      - SR  294  Type Names in the types Module                          Tirosh
      - SR  295  Interpretation of multiline string constants            Koltsov
      - SW  296  Adding a bytes Object Type                              Gilbert
      - SR  297  Support for System Upgrades                             Lemburg
      - SW  298  The Locked Buffer Interface                             Heller
      - SR  299  Special __main__() function in modules                  Epler
      - SR  303  Extend divmod() for Multiple Divisors                   Bellman
      - SW  304  Controlling Generation of Bytecode Files                Montanaro
      - IW  306  How to Change Python's Grammar                          Hudson, Diederich, Coghlan, Peterson
      - SR  310  Reliable Acquisition/Release Pairs                      Hudson, Moore
      - SR  313  Adding Roman Numeral Literals to Python                 Meyer
      - SR  315  Enhanced While Loop                                     Hettinger, Carroll
      - SR  317  Eliminate Implicit Exception Instantiation              Taschuk
      - SR  319  Python Synchronize/Asynchronize Block                   Pelletier
      - SW  321  Date/Time Parsing and Formatting                        Kuchling
      - SR  325  Resource-Release Support for Generators                 Pedroni
      - SR  326  A Case for Top and Bottom Values                        Carlson, Reedy
      - SR  329  Treating Builtins as Constants in the Standard Library  Hettinger
      - SR  330  Python Bytecode Verification                            Pelletier
      - SR  332  Byte vectors and String/Unicode Unification             Montanaro
      - SW  334  Simple Coroutines via SuspendIteration                  Evans
      - SR  335  Overloadable Boolean Operators                          Ewing
      - SR  336  Make None Callable                                      McClelland
      - IW  339  Design of the CPython Compiler                          Cannon
      - SR  340  Anonymous Block Statements                              GvR
      - SS  344  Exception Chaining and Embedded Tracebacks              Yee
      - SW  346  User Defined ("``with``") Statements                    Coghlan
      - SR  348  Exception Reorganization for Python 3.0                 Cannon
      - IR  350  Codetags                                                Elliott
      - SR  351  The freeze protocol                                     Warsaw
      - SS  354  Enumerations in Python                                  Finney
      - SR  355  Path - Object oriented filesystem paths                 Lindqvist
      - SW  359  The "make" Statement                                    Bethard
      - SR  363  Syntax For Dynamic Attribute Access                     North
      - SW  364  Transitioning to the Py3K Standard Library              Warsaw
      - SR  365  Adding the pkg_resources module                         Eby
      - SS  367  New Super                                               Spealman, Delaney
      - SW  369  Post import hooks                                       Heimes
      - SR  377  Allow __enter__() methods to skip the statement body    Coghlan
      - SW  379  Adding an Assignment Expression                         Whitley
      - SR  382  Namespace Packages                                      v. Löwis
      - SS  386  Changing the version comparison module in Distutils     Ziadé
      - SR  390  Static metadata for Distutils                           Ziadé
      - SW  395  Qualified Names for Modules                             Coghlan
      - PR  401  BDFL Retirement                                         Warsaw, Cannon
      - SR  402  Simplified Package Layout and Partitioning              Eby
      - SW  406  Improved Encapsulation of Import State                  Coghlan, Slodkowicz
      - SR  408  Standard library __preview__ package                    Coghlan, Bendersky
      - SR  410  Use decimal.Decimal type for timestamps                 Stinner
      - PW  413  Faster evolution of the Python Standard Library         Coghlan
      - SR  416  Add a frozendict builtin type                           Stinner
      - SS  433  Easier suppression of file descriptor inheritance       Stinner
      - SR  437  A DSL for specifying signatures, annotations and ...    Krah
      - SR  439  Inclusion of implicit pip bootstrap in Python ...       Jones
      - SW  460  Add binary interpolation and formatting                 Pitrou
      - SW  469  Migration of dict iteration code to Python 3            Coghlan
      - SR  666  Reject Foolish Indentation                              Creighton
      - SR  754  IEEE 754 Floating Point Special Values                  Warnes
      - PW 3001  Procedure for reviewing and improving standard ...      Brandl
      - SR 3103  A Switch/Case Statement                                 GvR
      - SR 3117  Postfix type declarations                               Brandl
      - SR 3122  Delineation of the main module                          Cannon
      - SR 3125  Remove Backslash Continuation                           Jewett
      - SR 3126  Remove Implicit String Concatenation                    Jewett, Hettinger
      - SR 3128  BList: A Faster List-like Type                          Stutzbach
      - SR 3130  Access to Current Module/Class/Function                 Jewett
      - SR 3133  Introducing Roles                                       Winter
      - SR 3136  Labeled break and continue                              Chisholm
      - SR 3139  Cleaning out sys and the "interpreter" module           Peterson
      - SR 3140  str(container) should call str(item), not repr(item)    Broytmann, Jewett
      - SR 3142  Add a "while" clause to generator expressions           Britton
      - SW 3145  Asynchronous I/O For subprocess.Popen                   Pruitt, McCreary, Carlson
      - SW 3146  Merging Unladen Swallow into CPython                    Winter, Yasskin, Kleckner
      - SS 3153  Asynchronous IO support                                 Houtven
      -
      -
      -
      -

      Numerical Index

      -
      -     num  title                                                   owner
      -     ---  -----                                                   -----
      - P     1  PEP Purpose and Guidelines                              Warsaw, Hylton, Goodger, Coghlan
      - PF    2  Procedure for Adding New Modules                        Faassen
      - PW    3  Guidelines for Handling Bug Reports                     Hylton
      - P     4  Deprecation of Standard Modules                         von Löwis
      - P     5  Guidelines for Language Evolution                       Prescod
      - P     6  Bug Fix Releases                                        Aahz, Baxter
      - P     7  Style Guide for C Code                                  GvR
      - P     8  Style Guide for Python Code                             GvR, Warsaw, Coghlan
      - P     9  Sample Plaintext PEP Template                           Warsaw
      - P    10  Voting Guidelines                                       Warsaw
      - P    11  Removing support for little used platforms              von Löwis
      - P    12  Sample reStructuredText PEP Template                    Goodger, Warsaw
      -
      - I    20  The Zen of Python                                       Peters
      -
      - PF   42  Feature Requests                                        Hylton
      -
      - SF  100  Python Unicode Integration                              Lemburg
      - I   101  Doing Python Releases 101                               Warsaw, GvR
      - IS  102  Doing Python Micro Releases                             Baxter, Warsaw, GvR
      -
      - IF  160  Python 1.6 Release Schedule                             Drake
      -
      - IF  200  Python 2.0 Release Schedule                             Hylton
      - SF  201  Lockstep Iteration                                      Warsaw
      - SF  202  List Comprehensions                                     Warsaw
      - SF  203  Augmented Assignments                                   Wouters
      - SR  204  Range Literals                                          Wouters
      - SF  205  Weak References                                         Drake
      - IW  206  Python Advanced Library                                 Kuchling
      - SF  207  Rich Comparisons                                        GvR, Ascher
      - SF  208  Reworking the Coercion Model                            Schemenauer, Lemburg
      - SW  209  Multi-dimensional Arrays                                Barrett, Oliphant
      - SR  210  Decoupling the Interpreter Loop                         Ascher
      - SD  211  Adding A New Outer Product Operator                     Wilson
      - SD  212  Loop Counter Iteration                                  Schneider-Kamp
      - SD  213  Attribute Access Handlers                               Prescod
      - SF  214  Extended Print Statement                                Warsaw
      - SS  215  String Interpolation                                    Yee
      - IR  216  Docstring Format                                        Zadka
      - SF  217  Display Hook for Interactive Use                        Zadka
      - SF  218  Adding a Built-In Set Object Type                       Wilson, Hettinger
      - SD  219  Stackless Python                                        McMillan
      - IR  220  Coroutines, Generators, Continuations                   McMillan
      - SF  221  Import As                                               Wouters
      - SD  222  Web Library Enhancements                                Kuchling
      - SF  223  Change the Meaning of \x Escapes                        Peters
      - SR  224  Attribute Docstrings                                    Lemburg
      - SD  225  Elementwise/Objectwise Operators                        Zhu, Lielens
      - IF  226  Python 2.1 Release Schedule                             Hylton
      - SF  227  Statically Nested Scopes                                Hylton
      - SW  228  Reworking Python's Numeric Model                        Zadka, GvR
      - SF  229  Using Distutils to Build Python                         Kuchling
      - SF  230  Warning Framework                                       GvR
      - SR  231  __findattr__()                                          Warsaw
      - SF  232  Function Attributes                                     Warsaw
      - SD  233  Python Online Help                                      Prescod
      - SF  234  Iterators                                               Yee, GvR
      - SF  235  Import on Case-Insensitive Platforms                    Peters
      - SF  236  Back to the __future__                                  Peters
      - SF  237  Unifying Long Integers and Integers                     Zadka, GvR
      - SF  238  Changing the Division Operator                          Zadka, GvR
      - SR  239  Adding a Rational Type to Python                        Craig, Zadka
      - SR  240  Adding a Rational Literal to Python                     Craig, Zadka
      - SF  241  Metadata for Python Software Packages                   Kuchling
      - SR  242  Numeric Kinds                                           Dubois
      - SW  243  Module Repository Upload Mechanism                      Reifschneider
      - SR  244  The `directive' statement                               von Löwis
      - SR  245  Python Interface Syntax                                 Pelletier
      - SR  246  Object Adaptation                                       Martelli, Evans
      - IF  247  API for Cryptographic Hash Functions                    Kuchling
      - IF  248  Python Database API Specification v1.0                  Lemburg
      - IF  249  Python Database API Specification v2.0                  Lemburg
      - SF  250  Using site-packages on Windows                          Moore
      - IF  251  Python 2.2 Release Schedule                             Warsaw, GvR
      - SF  252  Making Types Look More Like Classes                     GvR
      - SF  253  Subtyping Built-in Types                                GvR
      - SR  254  Making Classes Look More Like Types                     GvR
      - SF  255  Simple Generators                                       Schemenauer, Peters, Hetland
      - SR  256  Docstring Processing System Framework                   Goodger
      - I   257  Docstring Conventions                                   Goodger, GvR
      - SR  258  Docutils Design Specification                           Goodger
      - SR  259  Omit printing newline after newline                     GvR
      - SF  260  Simplify xrange()                                       GvR
      - SF  261  Support for "wide" Unicode characters                   Prescod
      - SD  262  A Database of Installed Python Packages                 Kuchling
      - SF  263  Defining Python Source Code Encodings                   Lemburg, von Löwis
      - SF  264  Future statements in simulated shells                   Hudson
      - SR  265  Sorting Dictionaries by Value                           Griffin
      - SW  266  Optimizing Global Variable/Attribute Access             Montanaro
      - SD  267  Optimized Access to Module Namespaces                   Hylton
      - SR  268  Extended HTTP functionality and WebDAV                  Stein
      - SD  269  Pgen Module for Python                                  Riehl
      - SR  270  uniq method for list objects                            Petrone
      - SR  271  Prefixing sys.path by command line option               Giacometti
      - IF  272  API for Block Encryption Algorithms v1.0                Kuchling
      - SF  273  Import Modules from Zip Archives                        Ahlstrom
      - SF  274  Dict Comprehensions                                     Warsaw
      - SR  275  Switching on Multiple Values                            Lemburg
      - SR  276  Simple Iterator for ints                                Althoff
      - SF  277  Unicode file name support for Windows NT                Hodgson
      - SF  278  Universal Newline Support                               Jansen
      - SF  279  The enumerate() built-in function                       Hettinger
      - SD  280  Optimizing access to globals                            GvR
      - SR  281  Loop Counter Iteration with range and xrange            Hetland
      - SF  282  A Logging System                                        Sajip, Mick
      - IF  283  Python 2.3 Release Schedule                             GvR
      - SR  284  Integer for-loops                                       Eppstein, Ewing
      - SF  285  Adding a bool type                                      GvR
      - SD  286  Enhanced Argument Tuples                                von Löwis
      - I   287  reStructuredText Docstring Format                       Goodger
      - SW  288  Generators Attributes and Exceptions                    Hettinger
      - SF  289  Generator Expressions                                   Hettinger
      - I   290  Code Migration and Modernization                        Hettinger
      - IF  291  Backward Compatibility for the Python 2 Standard ...    Norwitz
      - SF  292  Simpler String Substitutions                            Warsaw
      - SF  293  Codec Error Handling Callbacks                          Dörwald
      - SR  294  Type Names in the types Module                          Tirosh
      - SR  295  Interpretation of multiline string constants            Koltsov
      - SW  296  Adding a bytes Object Type                              Gilbert
      - SR  297  Support for System Upgrades                             Lemburg
      - SW  298  The Locked Buffer Interface                             Heller
      - SR  299  Special __main__() function in modules                  Epler
      -
      - SF  301  Package Index and Metadata for Distutils                Jones
      - SF  302  New Import Hooks                                        JvR, Moore
      - SR  303  Extend divmod() for Multiple Divisors                   Bellman
      - SW  304  Controlling Generation of Bytecode Files                Montanaro
      - SF  305  CSV File API                                            Altis, Cole, McNamara, Montanaro, Wells
      - IW  306  How to Change Python's Grammar                          Hudson, Diederich, Coghlan, Peterson
      - SF  307  Extensions to the pickle protocol                       GvR, Peters
      - SF  308  Conditional Expressions                                 GvR, Hettinger
      - SF  309  Partial Function Application                            Harris
      - SR  310  Reliable Acquisition/Release Pairs                      Hudson, Moore
      - SF  311  Simplified Global Interpreter Lock Acquisition for ...  Hammond
      - SD  312  Simple Implicit Lambda                                  Suzi, Martelli
      - SR  313  Adding Roman Numeral Literals to Python                 Meyer
      - SF  314  Metadata for Python Software Packages v1.1              Kuchling, Jones
      - SR  315  Enhanced While Loop                                     Hettinger, Carroll
      - SD  316  Programming by Contract for Python                      Way
      - SR  317  Eliminate Implicit Exception Instantiation              Taschuk
      - SF  318  Decorators for Functions and Methods                    Smith
      - SR  319  Python Synchronize/Asynchronize Block                   Pelletier
      - IF  320  Python 2.4 Release Schedule                             Warsaw, Hettinger, Baxter
      - SW  321  Date/Time Parsing and Formatting                        Kuchling
      - SF  322  Reverse Iteration                                       Hettinger
      - SD  323  Copyable Iterators                                      Martelli
      - SF  324  subprocess - New process module                         Astrand
      - SR  325  Resource-Release Support for Generators                 Pedroni
      - SR  326  A Case for Top and Bottom Values                        Carlson, Reedy
      - SF  327  Decimal Data Type                                       Batista
      - SF  328  Imports: Multi-Line and Absolute/Relative               Aahz
      - SR  329  Treating Builtins as Constants in the Standard Library  Hettinger
      - SR  330  Python Bytecode Verification                            Pelletier
      - SF  331  Locale-Independent Float/String Conversions             Reis
      - SR  332  Byte vectors and String/Unicode Unification             Montanaro
      - IF  333  Python Web Server Gateway Interface v1.0                Eby
      - SW  334  Simple Coroutines via SuspendIteration                  Evans
      - SR  335  Overloadable Boolean Operators                          Ewing
      - SR  336  Make None Callable                                      McClelland
      - SD  337  Logging Usage in the Standard Library                   Dubner
      - SF  338  Executing modules as scripts                            Coghlan
      - IW  339  Design of the CPython Compiler                          Cannon
      - SR  340  Anonymous Block Statements                              GvR
      - SF  341  Unifying try-except and try-finally                     Brandl
      - SF  342  Coroutines via Enhanced Generators                      GvR, Eby
      - SF  343  The "with" Statement                                    GvR, Coghlan
      - SS  344  Exception Chaining and Embedded Tracebacks              Yee
      - SA  345  Metadata for Python Software Packages 1.2               Jones
      - SW  346  User Defined ("``with``") Statements                    Coghlan
      - PF  347  Migrating the Python CVS to Subversion                  von Löwis
      - SR  348  Exception Reorganization for Python 3.0                 Cannon
      - SD  349  Allow str() to return unicode strings                   Schemenauer
      - IR  350  Codetags                                                Elliott
      - SR  351  The freeze protocol                                     Warsaw
      - SF  352  Required Superclass for Exceptions                      Cannon, GvR
      - SF  353  Using ssize_t as the index type                         von Löwis
      - SS  354  Enumerations in Python                                  Finney
      - SR  355  Path - Object oriented filesystem paths                 Lindqvist
      - IF  356  Python 2.5 Release Schedule                             Norwitz, GvR, Baxter
      - SF  357  Allowing Any Object to be Used for Slicing              Oliphant
      - SF  358  The "bytes" Object                                      Schemenauer, GvR
      - SW  359  The "make" Statement                                    Bethard
      - PF  360  Externally Maintained Packages                          Cannon
      - IF  361  Python 2.6 and 3.0 Release Schedule                     Norwitz, Warsaw
      - SF  362  Function Signature Object                               Cannon, Seo, Selivanov, Hastings
      - SR  363  Syntax For Dynamic Attribute Access                     North
      - SW  364  Transitioning to the Py3K Standard Library              Warsaw
      - SR  365  Adding the pkg_resources module                         Eby
      - SF  366  Main module explicit relative imports                   Coghlan
      - SS  367  New Super                                               Spealman, Delaney
      - SD  368  Standard image protocol and class                       Mastrodomenico
      - SW  369  Post import hooks                                       Heimes
      - SF  370  Per user site-packages directory                        Heimes
      - SF  371  Addition of the multiprocessing package to the ...      Noller, Oudkerk
      - SF  372  Adding an ordered dictionary to collections             Ronacher, Hettinger
      - I   373  Python 2.7 Release Schedule                             Peterson
      - PF  374  Choosing a distributed VCS for the Python project       Cannon, Turnbull, Vassalotti, Warsaw, Ochtman
      - IF  375  Python 3.1 Release Schedule                             Peterson
      - SA  376  Database of Installed Python Distributions              Ziadé
      - SR  377  Allow __enter__() methods to skip the statement body    Coghlan
      - SF  378  Format Specifier for Thousands Separator                Hettinger
      - SW  379  Adding an Assignment Expression                         Whitley
      - SF  380  Syntax for Delegating to a Subgenerator                 Ewing
      - S   381  Mirroring infrastructure for PyPI                       Ziadé, v. Löwis
      - SR  382  Namespace Packages                                      v. Löwis
      - SF  383  Non-decodable Bytes in System Character Interfaces      v. Löwis
      - SF  384  Defining a Stable ABI                                   v. Löwis
      - PF  385  Migrating from Subversion to Mercurial                  Ochtman, Pitrou, Brandl
      - SS  386  Changing the version comparison module in Distutils     Ziadé
      - P   387  Backwards Compatibility Policy                          Peterson
      -
      - SF  389  argparse - New Command Line Parsing Module              Bethard
      - SR  390  Static metadata for Distutils                           Ziadé
      - SF  391  Dictionary-Based Configuration For Logging              Sajip
      - I   392  Python 3.2 Release Schedule                             Brandl
      - SF  393  Flexible String Representation                          v. Löwis
      - I   394  The "python" Command on Unix-Like Systems               Staley, Coghlan
      - SW  395  Qualified Names for Modules                             Coghlan
      - ID  396  Module Version Numbers                                  Warsaw
      - SF  397  Python launcher for Windows                             Hammond, v. Löwis
      - I   398  Python 3.3 Release Schedule                             Brandl
      - IF  399  Pure Python/C Accelerator Module Compatibility ...      Cannon
      - SD  400  Deprecate codecs.StreamReader and codecs.StreamWriter   Stinner
      - PR  401  BDFL Retirement                                         Warsaw, Cannon
      - SR  402  Simplified Package Layout and Partitioning              Eby
      - SD  403  General purpose decorator clause (aka "@in" clause)     Coghlan
      - IF  404  Python 2.8 Un-release Schedule                          Warsaw
      - SF  405  Python Virtual Environments                             Meyer
      - SW  406  Improved Encapsulation of Import State                  Coghlan, Slodkowicz
      - PD  407  New release cycle and introducing long-term support ... Pitrou, Brandl, Warsaw
      - SR  408  Standard library __preview__ package                    Coghlan, Bendersky
      - SF  409  Suppressing exception context                           Furman
      - SR  410  Use decimal.Decimal type for timestamps                 Stinner
      - IA  411  Provisional packages in the Python standard library     Coghlan, Bendersky
      - SF  412  Key-Sharing Dictionary                                  Shannon
      - PW  413  Faster evolution of the Python Standard Library         Coghlan
      - SF  414  Explicit Unicode Literal for Python 3.3                 Ronacher, Coghlan
      - SF  415  Implement context suppression with exception attributes Peterson
      - SR  416  Add a frozendict builtin type                           Stinner
      - SF  417  Including mock in the Standard Library                  Foord
      - SF  418  Add monotonic time, performance counter, and ...        Simpson, Jewett, Turnbull, Stinner
      - SD  419  Protecting cleanup statements from interruptions        Colomiets
      - SF  420  Implicit Namespace Packages                             Smith
      - SF  421  Adding sys.implementation                               Snow
      - SD  422  Simpler customisation of class creation                 Coghlan, Urban
      - ID  423  Naming conventions and recipes related to packaging     Bryon
      - SF  424  A method for exposing a length hint                     Gaynor
      - SA  425  Compatibility Tags for Built Distributions              Holth
      - S   426  Metadata for Python Software Packages 2.0               Coghlan, Holth, Stufft
      - SA  427  The Wheel Binary Package Format 1.0                     Holth
      - SF  428  The pathlib module -- object-oriented filesystem paths  Pitrou
      - I   429  Python 3.4 Release Schedule                             Hastings
      - IF  430  Migrating to Python 3 as the default online ...         Coghlan
      - S   431  Time zone support improvements                          Regebro
      - S   432  Simplifying the CPython startup sequence                Coghlan
      - SS  433  Easier suppression of file descriptor inheritance       Stinner
      - I   434  IDLE Enhancement Exception for All Branches             Rovito, Reedy
      - SF  435  Adding an Enum type to the Python standard library      Warsaw, Bendersky, Furman
      - S   436  The Argument Clinic DSL                                 Hastings
      - SR  437  A DSL for specifying signatures, annotations and ...    Krah
      - PA  438  Transitioning to release-file hosting on PyPI           Krekel, Meyer
      - SR  439  Inclusion of implicit pip bootstrap in Python ...       Jones
      - IA  440  Version Identification and Dependency Specification     Coghlan, Stufft
      - S   441  Improving Python ZIP Application Support                Holth
      - SF  442  Safe object finalization                                Pitrou
      - SF  443  Single-dispatch generic functions                       Langa
      - ID  444  Python Web3 Interface                                   McDonough, Ronacher
      - SF  445  Add new APIs to customize Python memory allocators      Stinner
      - SF  446  Make newly created file descriptors non-inheritable     Stinner
      - S   447  Add __getdescriptor__ method to metaclass               Oussoren
      - S   448  Additional Unpacking Generalizations                    Landau
      - PA  449  Removal of the PyPI Mirror Auto Discovery and ...       Stufft
      - SF  450  Adding A Statistics Module To The Standard Library      D'Aprano
      - SF  451  A ModuleSpec Type for the Import System                 Snow
      - I   452  API for Cryptographic Hash Functions v2.0               Kuchling, Heimes
      - SF  453  Explicit bootstrapping of pip in Python installations   Stufft, Coghlan
      - SF  454  Add a new tracemalloc module to trace Python memory ... Stinner
      - S   455  Adding a key-transforming dictionary to collections     Pitrou
      - SF  456  Secure and interchangeable hash algorithm               Heimes
      - I   457  Syntax For Positional-Only Parameters                   Hastings
      - S   458  Surviving a Compromise of PyPI                          Kuppusamy, Stufft, Cappos
      - S   459  Standard Metadata Extensions for Python Software ...    Coghlan
      - SW  460  Add binary interpolation and formatting                 Pitrou
      - SA  461  Adding % formatting to bytes and bytearray              Furman
      - PD  462  Core development workflow automation for CPython        Coghlan
      - S   463  Exception-catching expressions                          Angelico
      - PA  464  Removal of the PyPI Mirror Authenticity API             Stufft
      - SF  465  A dedicated infix operator for matrix multiplication    Smith
      - SF  466  Network Security Enhancements for Python 2.7.x          Coghlan
      - S   467  Minor API improvements for binary sequences             Coghlan
      - S   468  Preserving the order of \*\*kwargs in a function.       Snow
      - SW  469  Migration of dict iteration code to Python 3            Coghlan
      - P   470  Using Multi Index Support for External to PyPI ...      Stufft
      - SA  471  os.scandir() function -- a better and faster ...        Hoyt
      - S   472  Support for indexing with keyword arguments             Borini, Martinot-Lagarde
      - S   473  Adding structured data to built-in exceptions           Kreft
      - PD  474  Creating forge.python.org                               Coghlan
      - S   475  Retry system calls failing with EINTR                   Natali, Stinner
      - S   476  Enabling certificate verification by default for ...    Gaynor
      - SA  477  Backport ensurepip (PEP 453) to Python 2.7              Stufft, Coghlan
      - I   478  Python 3.5 Release Schedule                             Hastings
      -
      - SD  628  Add ``math.tau``                                        Coghlan
      -
      - SR  666  Reject Foolish Indentation                              Creighton
      -
      - SR  754  IEEE 754 Floating Point Special Values                  Warnes
      -
      - PF 3000  Python 3000                                             GvR
      - PW 3001  Procedure for reviewing and improving standard ...      Brandl
      - PF 3002  Procedure for Backwards-Incompatible Changes            Bethard
      - PF 3003  Python Language Moratorium                              Cannon, Noller, GvR
      -
      - PF 3099  Things that will Not Change in Python 3000              Brandl
      - PF 3100  Miscellaneous Python 3.0 Plans                          Cannon
      - SF 3101  Advanced String Formatting                              Talin
      - SF 3102  Keyword-Only Arguments                                  Talin
      - SR 3103  A Switch/Case Statement                                 GvR
      - SF 3104  Access to Names in Outer Scopes                         Yee
      - SF 3105  Make print a function                                   Brandl
      - SF 3106  Revamping dict.keys(), .values() and .items()           GvR
      - SF 3107  Function Annotations                                    Winter, Lownds
      - SF 3108  Standard Library Reorganization                         Cannon
      - SF 3109  Raising Exceptions in Python 3000                       Winter
      - SF 3110  Catching Exceptions in Python 3000                      Winter
      - SF 3111  Simple input built-in in Python 3000                    Roberge
      - SF 3112  Bytes literals in Python 3000                           Orendorff
      - SF 3113  Removal of Tuple Parameter Unpacking                    Cannon
      - SF 3114  Renaming iterator.next() to iterator.__next__()         Yee
      - SF 3115  Metaclasses in Python 3000                              Talin
      - SF 3116  New I/O                                                 Stutzbach, GvR, Verdone
      - SR 3117  Postfix type declarations                               Brandl
      - SF 3118  Revising the buffer protocol                            Oliphant, Banks
      - SF 3119  Introducing Abstract Base Classes                       GvR, Talin
      - SF 3120  Using UTF-8 as the default source encoding              von Löwis
      - SA 3121  Extension Module Initialization and Finalization        von Löwis
      - SR 3122  Delineation of the main module                          Cannon
      - SF 3123  Making PyObject_HEAD conform to standard C              von Löwis
      - SD 3124  Overloading, Generic Functions, Interfaces, and ...     Eby
      - SR 3125  Remove Backslash Continuation                           Jewett
      - SR 3126  Remove Implicit String Concatenation                    Jewett, Hettinger
      - SF 3127  Integer Literal Support and Syntax                      Maupin
      - SR 3128  BList: A Faster List-like Type                          Stutzbach
      - SF 3129  Class Decorators                                        Winter
      - SR 3130  Access to Current Module/Class/Function                 Jewett
      - SF 3131  Supporting Non-ASCII Identifiers                        von Löwis
      - SF 3132  Extended Iterable Unpacking                             Brandl
      - SR 3133  Introducing Roles                                       Winter
      - SF 3134  Exception Chaining and Embedded Tracebacks              Yee
      - SF 3135  New Super                                               Spealman, Delaney, Ryan
      - SR 3136  Labeled break and continue                              Chisholm
      - SF 3137  Immutable Bytes and Mutable Buffer                      GvR
      - SF 3138  String representation in Python 3000                    Ishimoto
      - SR 3139  Cleaning out sys and the "interpreter" module           Peterson
      - SR 3140  str(container) should call str(item), not repr(item)    Broytmann, Jewett
      - SF 3141  A Type Hierarchy for Numbers                            Yasskin
      - SR 3142  Add a "while" clause to generator expressions           Britton
      - SD 3143  Standard daemon process library                         Finney
      - SF 3144  IP Address Manipulation Library for the Python ...      Moody
      - SW 3145  Asynchronous I/O For subprocess.Popen                   Pruitt, McCreary, Carlson
      - SW 3146  Merging Unladen Swallow into CPython                    Winter, Yasskin, Kleckner
      - SF 3147  PYC Repository Directories                              Warsaw
      - SF 3148  futures - execute computations asynchronously           Quinlan
      - SF 3149  ABI version tagged .so files                            Warsaw
      - SD 3150  Statement local namespaces (aka "given" clause)         Coghlan
      - SF 3151  Reworking the OS and IO exception hierarchy             Pitrou
      - SD 3152  Cofunctions                                             Ewing
      - SS 3153  Asynchronous IO support                                 Houtven
      - SF 3154  Pickle protocol version 4                               Pitrou
      - SF 3155  Qualified name for classes and functions                Pitrou
      - SF 3156  Asynchronous IO Support Rebooted: the "asyncio" Module  GvR
      -
      - IF 3333  Python Web Server Gateway Interface v1.0.1              Eby
      -
      -
      -
      -

      Reserved PEP Numbers

      -
      -     num  title                                                   owner
      -     ---  -----                                                   -----
      -     801  RESERVED                                                Warsaw
      -
      -
      -
      -

      Key

      -
      -    S - Standards Track PEP
      -    I - Informational PEP
      -    P - Process PEP
      -
      -    A - Accepted proposal
      -    R - Rejected proposal
      -    W - Withdrawn proposal
      -    D - Deferred proposal
      -    F - Final proposal
      -    A - Active proposal
      -    D - Draft proposal
      -    S - Superseded proposal
      -
      -
      -
      -

      Owners

      -
      -    name                         email address
      -    ----                         -------------
      -    Aahz                         aahz at pythoncraft.com
      -    Ahlstrom, James C.           jim at interet.com
      -    Althoff, Jim                 james_althoff at i2.com
      -    Altis, Kevin                 altis at semi-retired.com
      -    Angelico, Chris              rosuav at gmail.com
      -    Ascher, David                davida at activestate.com
      -    Astrand, Peter               astrand at lysator.liu.se
      -    Banks, Carl                  pythondev at aerojockey.com
      -    Barrett, Paul                barrett at stsci.edu
      -    Batista, Facundo             facundo at taniquetil.com.ar
      -    Baxter, Anthony              anthony at interlink.com.au
      -    Bellman, Thomas              bellman+pep-divmod@lysator.liu.se
      -    Bendersky, Eli               eliben at gmail.com
      -    Bethard, Steven              steven.bethard at gmail.com
      -    Borini, Stefano              
      -    Brandl, Georg                georg at python.org
      -    Britton, Gerald              gerald.britton at gmail.com
      -    Broytmann, Oleg              phd at phd.pp.ru
      -    Bryon, Benoit                benoit at marmelune.net
      -    Cannon, Brett                brett at python.org
      -    Cappos, Justin               jcappos at poly.edu
      -    Carlson, Josiah              jcarlson at uci.edu
      -    Carroll,         W Isaac     icarroll at pobox.com
      -    Chisholm, Matt               matt-python at theory.org
      -    Coghlan, Nick                ncoghlan at gmail.com
      -    Cole, Dave                   djc at object-craft.com.au
      -    Colomiets, Paul              paul at colomiets.name
      -    Craig, Christopher A.        python-pep at ccraig.org
      -    Creighton, Laura             lac at strakt.com
      -    D'Aprano, Steven             steve at pearwood.info
      -    Delaney, Tim                 timothy.c.delaney at gmail.com
      -    Diederich, Jack              jackdied at gmail.com
      -    Dörwald, Walter              walter at livinglogic.de
      -    Drake, Fred L., Jr.          fdrake at acm.org
      -    Dubner, Michael P.           dubnerm at mindless.com
      -    Dubois, Paul F.              paul at pfdubois.com
      -    Eby, P.J.                    pje at telecommunity.com
      -    Eby, Phillip J.              pje at telecommunity.com
      -    Elliott, Micah               mde at tracos.org
      -    Epler, Jeff                  jepler at unpythonic.net
      -    Eppstein, David              eppstein at ics.uci.edu
      -    Evans, Clark C.              cce at clarkevans.com
      -    Ewing, Gregory               greg.ewing at canterbury.ac.nz
      -    Ewing, Greg                  greg.ewing at canterbury.ac.nz
      -    Faassen, Martijn             faassen at infrae.com
      -    Finney, Ben                  ben+python@benfinney.id.au
      -    Foord, Michael               michael at python.org
      -    Furman, Ethan                ethan at stoneleaf.us
      -    Gaynor, Alex                 alex.gaynor at gmail.com
      -    Giacometti, Frédéric B.      fred at arakne.com
      -    Gilbert, Scott               xscottg at yahoo.com
      -    Goodger, David               goodger at python.org
      -    Griffin, Grant               g2 at iowegian.com
      -    Hammond, Mark                mhammond at skippinet.com.au
      -    Harris, Peter                scav at blueyonder.co.uk
      -    Hastings, Larry              larry at hastings.org
      -    Heimes, Christian            christian at python.org
      -    Heller, Thomas               theller at python.net
      -    Hetland, Magnus Lie          magnus at hetland.org
      -    Hettinger, Raymond           python at rcn.com
      -    Hodgson, Neil                neilh at scintilla.org
      -    Holth, Daniel                dholth at gmail.com
      -    Houtven, Laurens Van         _ at lvh.cc
      -    Hoyt, Ben                    benhoyt at gmail.com
      -    Hudson, Michael              mwh at python.net
      -    Hylton, Jeremy               jeremy at alum.mit.edu
      -    Ishimoto, Atsuo              ishimoto--at--gembook.org
      -    Jansen, Jack                 jack at cwi.nl
      -    Jewett, Jim J.               jimjjewett at gmail.com
      -    Jewett, Jim                  jimjjewett at gmail.com
      -    Jones, Richard               richard at python.org
      -    Kleckner, Reid               rnk at mit.edu
      -    Koltsov, Stepan              yozh at mx1.ru
      -    Krah, Stefan                 skrah at bytereef.org
      -    Kreft, Sebastian             skreft at deezer.com
      -    Krekel, Holger               holger at merlinux.eu
      -    Kuchling, A.M.               amk at amk.ca
      -    Kuppusamy, Trishank Karthik  tk47 at students.poly.edu
      -    Landau, Joshua               joshua at landau.ws
      -    Langa, Åukasz                lukasz at langa.pl
      -    Lemburg, Marc-André          mal at lemburg.com
      -    Lielens, Gregory             gregory.lielens at fft.be
      -    Lindqvist, Björn             bjourne at gmail.com
      -    von Löwis, Martin            martin at v.loewis.de
      -    v. Löwis, Martin             martin at v.loewis.de
      -    Lownds, Tony                 tony at lownds.com
      -    Martelli, Alex               aleaxit at gmail.com
      -    Martinot-Lagarde, Joseph     
      -    Mastrodomenico, Lino         l.mastrodomenico at gmail.com
      -    Maupin, Patrick              pmaupin at gmail.com
      -    McClelland, Andrew           eternalsquire at comcast.net
      -    McCreary, Charles R.         
      -    McDonough, Chris             chrism at plope.com
      -    McMillan, Gordon             gmcm at hypernet.com
      -    McNamara, Andrew             andrewm at object-craft.com.au
      -    Meyer, Mike                  mwm at mired.org
      -    Meyer, Carl                  carl at oddbird.net
      -    Mick, Trent                  trentm at activestate.com
      -    Montanaro, Skip              skip at pobox.com
      -    Moody, Peter                 pmoody at google.com
      -    Moore, Paul                  gustav at morpheus.demon.co.uk
      -    Natali, Charles-François     cf.natali at gmail.com
      -    Noller, Jesse                jnoller at gmail.com
      -    North, Ben                   ben at redfrontdoor.org
      -    Norwitz, Neal                nnorwitz at gmail.com
      -    Ochtman, Dirkjan             dirkjan at ochtman.nl
      -    Oliphant, Travis             oliphant at ee.byu.edu
      -    Orendorff, Jason             jason.orendorff at gmail.com
      -    Oudkerk, Richard             r.m.oudkerk at googlemail.com
      -    Oussoren, Ronald             ronaldoussoren at mac.com
      -    Pedroni, Samuele             pedronis at python.org
      -    Pelletier, Michel            michel at users.sourceforge.net
      -    Peters, Tim                  tim at zope.com
      -    Peterson, Benjamin           benjamin at python.org
      -    Petrone, Jason               jp at demonseed.net
      -    Pitrou, Antoine              solipsis at pitrou.net
      -    Prescod, Paul                paul at prescod.net
      -    Pruitt, (James) Eric         
      -    Quinlan, Brian               brian at sweetapp.com
      -    Reedy, Terry                 tjreedy at udel.edu
      -    Regebro, Lennart             regebro at gmail.com
      -    Reifschneider, Sean          jafo-pep at tummy.com
      -    Reis, Christian R.           kiko at async.com.br
      -    Riehl, Jonathan              jriehl at spaceship.com
      -    Roberge, Andre               andre.roberge at gmail.com 
      -    Ronacher, Armin              armin.ronacher at active-4.com
      -    van Rossum, Guido (GvR)      guido at python.org
      -    van Rossum, Just (JvR)       just at letterror.com
      -    Rovito, Todd                 rovitotv at gmail.com
      -    Ryan, Lie                    lie.1296 at gmail.com
      -    Sajip, Vinay                 vinay_sajip at red-dove.com
      -    Schemenauer, Neil            nas at arctrix.com
      -    Schneider-Kamp, Peter        nowonder at nowonder.de
      -    Selivanov, Yury              yselivanov at sprymix.com
      -    Seo, Jiwon                   seojiwon at gmail.com
      -    Shannon, Mark                mark at hotpy.org
      -    Simpson, Cameron             cs at zip.com.au
      -    Slodkowicz, Greg             jergosh at gmail.com
      -    Smith, Nathaniel J.          njs at pobox.com
      -    Smith, Kevin D.              kevin.smith at themorgue.org
      -    Smith, Eric V.               eric at trueblade.com
      -    Snow, Eric                   ericsnowcurrently at gmail.com
      -    Spealman, Calvin             ironfroggy at gmail.com
      -    Staley, Kerrick              mail at kerrickstaley.com
      -    Stein, Greg                  gstein at lyra.org
      -    Stinner, Victor              victor.stinner at gmail.com
      -    Stufft, Donald               donald at stufft.io
      -    Stutzbach, Daniel            daniel at stutzbachenterprises.com
      -    Suzi, Roman                  rnd at onego.ru
      -    Talin                        talin at acm.org
      -    Taschuk, Steven              staschuk at telusplanet.net
      -    Tirosh, Oren                 oren at hishome.net
      -    Turnbull, Stephen J.         stephen at xemacs.org
      -    Urban, Daniel                urban.dani+py@gmail.com
      -    Vassalotti, Alexandre        alexandre at peadrop.com
      -    Verdone, Mike                mike.verdone at gmail.com
      -    Warnes, Gregory R.           gregory_r_warnes at groton.pfizer.com
      -    Warsaw, Barry                barry at python.org
      -    Way, Terence                 terry at wayforward.net
      -    Wells, Cliff                 logiplexsoftware at earthlink.net
      -    Whitley, Jervis              jervisau at gmail.com
      -    Wilson, Greg                 gvwilson at ddj.com
      -    Winter, Collin               collinwinter at google.com
      -    Wouters, Thomas              thomas at python.org
      -    Yasskin, Jeffrey             jyasskin at google.com
      -    Yee, Ka-Ping                 ping at zesty.ca
      -    Zadka, Moshe                 moshez at zadka.site.co.il
      -    Zhu, Huaiyu                  hzhu at users.sourceforge.net
      -    Ziadé, Tarek                 tarek at ziade.org
      -
      -
      -
      -

      References

      -
      -    [1] PEP 1: PEP Purpose and Guidelines
      -    [2] View PEP history online
      -        http://hg.python.org/peps/
      -
      -
      -
      - - diff --git a/peps/tests/peps/pep-0012.html b/peps/tests/peps/pep-0012.html deleted file mode 100644 index e341e82f5..000000000 --- a/peps/tests/peps/pep-0012.html +++ /dev/null @@ -1,53 +0,0 @@ - - --- - - - - - - - - - - - - - - - - - -
      PEP:12
      Title:Sample reStructuredText PEP Template
      Author:David Goodger <goodger at python.org>, -Barry Warsaw <barry at python.org>
      Status:Active
      Type:Process
      Content-Type:text/x-rst
      Created:05-Aug-2002
      Post-History:30-Aug-2002
      -
      -
      -

      Contents

      - -
      -
      -

      Abstract

      -

      This PEP provides a boilerplate or sample template for creating your -own reStructuredText PEPs.

      -
      - - diff --git a/peps/tests/peps/pep-0012.rst b/peps/tests/peps/pep-0012.rst deleted file mode 100644 index 92a90835e..000000000 --- a/peps/tests/peps/pep-0012.rst +++ /dev/null @@ -1,33 +0,0 @@ -PEP: 12 -Title: Sample reStructuredText PEP Template -Author: David Goodger , - Barry Warsaw -Status: Active -Type: Process -Content-Type: text/x-rst -Created: 05-Aug-2002 -Post-History: 30-Aug-2002 - - -Abstract -======== - -This PEP provides a boilerplate or sample template for creating your -own reStructuredText PEPs. - - -Copyright -========= - -This document has been placed in the public domain. - - - -.. - Local Variables: - mode: indented-text - indent-tabs-mode: nil - sentence-end-double-space: t - fill-column: 70 - coding: utf-8 - End: diff --git a/peps/tests/peps/pep-0525.html b/peps/tests/peps/pep-0525.html deleted file mode 100644 index 55a756e0d..000000000 --- a/peps/tests/peps/pep-0525.html +++ /dev/null @@ -1,595 +0,0 @@ - - --- - - - - - - - - - - - - - - - - - - - - - - - - - -
      PEP:525
      Title:Asynchronous Generators
      Version:$Revision$
      Last-Modified:$Date$
      Author:Yury Selivanov <yury at magic.io>
      Discussions-To:<python-dev at python.org>
      Status:Draft
      Type:Standards Track
      Content-Type:text/x-rst
      Created:28-Jul-2016
      Python-Version:3.6
      Post-History:02-Aug-2016
      -
      - -
      -

      Abstract

      -

      PEP 492 introduced support for native coroutines and async/await -syntax to Python 3.5. It is proposed here to extend Python's -asynchronous capabilities by adding support for -asynchronous generators.

      -
      -
      -

      Rationale and Goals

      -

      Regular generators (introduced in PEP 255) enabled an elegant way of -writing complex data producers and have them behave like an iterator.

      -

      However, currently there is no equivalent concept for the asynchronous -iteration protocol (async for). This makes writing asynchronous -data producers unnecessarily complex, as one must define a class that -implements __aiter__ and __anext__ to be able to use it in -an async for statement.

      -

      Essentially, the goals and rationale for PEP 255, applied to the -asynchronous execution case, hold true for this proposal as well.

      -

      Performance is an additional point for this proposal: in our testing of -the reference implementation, asynchronous generators are 2x faster -than an equivalent implemented as an asynchronous iterator.

      -

      As an illustration of the code quality improvement, consider the -following class that prints numbers with a given delay once iterated:

      -
      -class Ticker:
      -    """Yield numbers from 0 to `to` every `delay` seconds."""
      -
      -    def __init__(self, delay, to):
      -        self.delay = delay
      -        self.i = 0
      -        self.to = to
      -
      -    def __aiter__(self):
      -        return self
      -
      -    async def __anext__(self):
      -        i = self.i
      -        if i >= self.to:
      -            raise StopAsyncIteration
      -        self.i += 1
      -        if i:
      -            await asyncio.sleep(self.delay)
      -        return i
      -
      -

      The same can be implemented as a much simpler asynchronous generator:

      -
      -async def ticker(delay, to):
      -    """Yield numbers from 0 to `to` every `delay` seconds."""
      -    for i in range(to):
      -        yield i
      -        await asyncio.sleep(delay)
      -
      -
      -
      -

      Specification

      -

      This proposal introduces the concept of asynchronous generators to -Python.

      -

      This specification presumes knowledge of the implementation of -generators and coroutines in Python (PEP 342, PEP 380 and PEP 492).

      -
      -

      Asynchronous Generators

      -

      A Python generator is any function containing one or more yield -expressions:

      -
      -def func():            # a function
      -    return
      -
      -def genfunc():         # a generator function
      -    yield
      -
      -

      We propose to use the same approach to define -asynchronous generators:

      -
      -async def coro():      # a coroutine function
      -    await smth()
      -
      -async def asyncgen():  # an asynchronous generator function
      -    await smth()
      -    yield 42
      -
      -

      The result of calling an asynchronous generator function is -an asynchronous generator object, which implements the asynchronous -iteration protocol defined in PEP 492.

      -

      It is a SyntaxError to have a non-empty return statement in an -asynchronous generator.

      -
      -
      -

      Support for Asynchronous Iteration Protocol

      -

      The protocol requires two special methods to be implemented:

      -
        -
      1. An __aiter__ method returning an asynchronous iterator.
      2. -
      3. An __anext__ method returning an awaitable object, which uses -StopIteration exception to "yield" values, and -StopAsyncIteration exception to signal the end of the iteration.
      4. -
      -

      Asynchronous generators define both of these methods. Let's manually -iterate over a simple asynchronous generator:

      -
      -async def genfunc():
      -    yield 1
      -    yield 2
      -
      -gen = genfunc()
      -
      -assert gen.__aiter__() is gen
      -
      -assert await gen.__anext__() == 1
      -assert await gen.__anext__() == 2
      -
      -await gen.__anext__()  # This line will raise StopAsyncIteration.
      -
      -
      -
      -

      Finalization

      -

      PEP 492 requires an event loop or a scheduler to run coroutines. -Because asynchronous generators are meant to be used from coroutines, -they also require an event loop to run and finalize them.

      -

      Asynchronous generators can have try..finally blocks, as well as -async with. It is important to provide a guarantee that, even -when partially iterated, and then garbage collected, generators can -be safely finalized. For example:

      -
      -async def square_series(con, to):
      -    async with con.transaction():
      -        cursor = con.cursor(
      -            'SELECT generate_series(0, $1) AS i', to)
      -        async for row in cursor:
      -            yield row['i'] ** 2
      -
      -async for i in square_series(con, 1000):
      -    if i == 100:
      -        break
      -
      -

      The above code defines an asynchronous generator that uses -async with to iterate over a database cursor in a transaction. -The generator is then iterated over with async for, which interrupts -the iteration at some point.

      -

      The square_series() generator will then be garbage collected, -and without a mechanism to asynchronously close the generator, Python -interpreter would not be able to do anything.

      -

      To solve this problem we propose to do the following:

      -
        -
      1. Implement an aclose method on asynchronous generators -returning a special awaitable. When awaited it -throws a GeneratorExit into the suspended generator and -iterates over it until either a GeneratorExit or -a StopAsyncIteration occur.

        -

        This is very similar to what the close() method does to regular -Python generators, except that an event loop is required to execute -aclose().

        -
      2. -
      3. Raise a RuntimeError, when an asynchronous generator executes -a yield expression in its finally block (using await -is fine, though):

        -
        -async def gen():
        -    try:
        -        yield
        -    finally:
        -        await asyncio.sleep(1)   # Can use 'await'.
        -
        -        yield                    # Cannot use 'yield',
        -                                 # this line will trigger a
        -                                 # RuntimeError.
        -
        -
      4. -
      5. Add two new methods to the sys module: -set_asyncgen_finalizer() and get_asyncgen_finalizer().

        -
      6. -
      -

      The idea behind sys.set_asyncgen_finalizer() is to allow event -loops to handle generators finalization, so that the end user -does not need to care about the finalization problem, and it just -works.

      -

      When an asynchronous generator is iterated for the first time, -it stores a reference to the current finalizer. If there is none, -a RuntimeError is raised. This provides a strong guarantee that -every asynchronous generator object will always have a finalizer -installed by the correct event loop.

      -

      When an asynchronous generator is about to be garbage collected, -it calls its cached finalizer. The assumption is that the finalizer -will schedule an aclose() call with the loop that was active -when the iteration started.

      -

      For instance, here is how asyncio is modified to allow safe -finalization of asynchronous generators:

      -
      -# asyncio/base_events.py
      -
      -class BaseEventLoop:
      -
      -    def run_forever(self):
      -        ...
      -        old_finalizer = sys.get_asyncgen_finalizer()
      -        sys.set_asyncgen_finalizer(self._finalize_asyncgen)
      -        try:
      -            ...
      -        finally:
      -            sys.set_asyncgen_finalizer(old_finalizer)
      -            ...
      -
      -    def _finalize_asyncgen(self, gen):
      -        self.create_task(gen.aclose())
      -
      -

      sys.set_asyncgen_finalizer() is thread-specific, so several event -loops running in parallel threads can use it safely.

      -
      -
      -

      Asynchronous Generator Object

      -

      The object is modeled after the standard Python generator object. -Essentially, the behaviour of asynchronous generators is designed -to replicate the behaviour of synchronous generators, with the only -difference in that the API is asynchronous.

      -

      The following methods and properties are defined:

      -
        -
      1. agen.__aiter__(): Returns agen.

        -
      2. -
      3. agen.__anext__(): Returns an awaitable, that performs one -asynchronous generator iteration when awaited.

        -
      4. -
      5. agen.asend(val): Returns an awaitable, that pushes the -val object in the agen generator. When the agen has -not yet been iterated, val must be None.

        -

        Example:

        -
        -async def gen():
        -    await asyncio.sleep(0.1)
        -    v = yield 42
        -    print(v)
        -    await asyncio.sleep(0.2)
        -
        -g = gen()
        -
        -await g.asend(None)      # Will return 42 after sleeping
        -                         # for 0.1 seconds.
        -
        -await g.asend('hello')   # Will print 'hello' and
        -                         # raise StopAsyncIteration
        -                         # (after sleeping for 0.2 seconds.)
        -
        -
      6. -
      7. agen.athrow(typ, [val, [tb]]): Returns an awaitable, that -throws an exception into the agen generator.

        -

        Example:

        -
        -async def gen():
        -    try:
        -        await asyncio.sleep(0.1)
        -        yield 'hello'
        -    except ZeroDivisionError:
        -        await asyncio.sleep(0.2)
        -        yield 'world'
        -
        -g = gen()
        -v = await g.asend(None)
        -print(v)                # Will print 'hello' after
        -                        # sleeping for 0.1 seconds.
        -
        -v = await g.athrow(ZeroDivisionError)
        -print(v)                # Will print 'world' after
        -                        $ sleeping 0.2 seconds.
        -
        -
      8. -
      9. agen.aclose(): Returns an awaitable, that throws a -GeneratorExit exception into the generator. The awaitable can -either return a yielded value, if agen handled the exception, -or agen will be closed and the exception will propagate back -to the caller.

        -
      10. -
      11. agen.__name__ and agen.__qualname__: readable and writable -name and qualified name attributes.

        -
      12. -
      13. agen.ag_await: The object that agen is currently awaiting -on, or None. This is similar to the currently available -gi_yieldfrom for generators and cr_await for coroutines.

        -
      14. -
      15. agen.ag_frame, agen.ag_running, and agen.ag_code: -defined in the same way as similar attributes of standard generators.

        -
      16. -
      -

      StopIteration and StopAsyncIteration are not propagated out of -asynchronous generators, and are replaced with a RuntimeError.

      -
      -
      -

      Implementation Details

      -

      Asynchronous generator object (PyAsyncGenObject) shares the -struct layout with PyGenObject. In addition to that, the -reference implementation introduces three new objects:

      -
        -
      1. PyAsyncGenASend: the awaitable object that implements -__anext__ and asend() methods.
      2. -
      3. PyAsyncGenAThrow: the awaitable object that implements -athrow() and aclose() methods.
      4. -
      5. _PyAsyncGenWrappedValue: every directly yielded object from an -asynchronous generator is implicitly boxed into this structure. This -is how the generator implementation can separate objects that are -yielded using regular iteration protocol from objects that are -yielded using asynchronous iteration protocol.
      6. -
      -

      PyAsyncGenASend and PyAsyncGenAThrow are awaitables (they have -__await__ methods returning self) and are coroutine-like objects -(implementing __iter__, __next__, send() and throw() -methods). Essentially, they control how asynchronous generators are -iterated:

      -pep-0525-1.png -
      -

      PyAsyncGenASend and PyAsyncGenAThrow

      -

      PyAsyncGenASend is a coroutine-like object that drives __anext__ -and asend() methods and implements the asynchronous iteration -protocol.

      -

      agen.asend(val) and agen.__anext__() return instances of -PyAsyncGenASend (which hold references back to the parent -agen object.)

      -

      The data flow is defined as follows:

      -
        -
      1. When PyAsyncGenASend.send(val) is called for the first time, -val is pushed to the parent agen object (using existing -facilities of PyGenObject.)

        -

        Subsequent iterations over the PyAsyncGenASend objects, push -None to agen.

        -

        When a _PyAsyncGenWrappedValue object is yielded, it -is unboxed, and a StopIteration exception is raised with the -unwrapped value as an argument.

        -
      2. -
      3. When PyAsyncGenASend.throw(*exc) is called for the first time, -*exc is throwed into the parent agen object.

        -

        Subsequent iterations over the PyAsyncGenASend objects, push -None to agen.

        -

        When a _PyAsyncGenWrappedValue object is yielded, it -is unboxed, and a StopIteration exception is raised with the -unwrapped value as an argument.

        -
      4. -
      5. return statements in asynchronous generators raise -StopAsyncIteration exception, which is propagated through -PyAsyncGenASend.send() and PyAsyncGenASend.throw() methods.

        -
      6. -
      -

      PyAsyncGenAThrow is very similar to PyAsyncGenASend. The only -difference is that PyAsyncGenAThrow.send(), when called first time, -throws an exception into the parent agen object (instead of pushing -a value into it.)

      -
      -
      -
      -

      New Standard Library Functions and Types

      -
        -
      1. types.AsyncGeneratorType -- type of asynchronous generator -object.
      2. -
      3. sys.set_asyncgen_finalizer() and sys.get_asyncgen_finalizer() -methods to set up asynchronous generators finalizers in event loops.
      4. -
      5. inspect.isasyncgen() and inspect.isasyncgenfunction() -introspection functions.
      6. -
      -
      -
      -

      Backwards Compatibility

      -

      The proposal is fully backwards compatible.

      -

      In Python 3.5 it is a SyntaxError to define an async def -function with a yield expression inside, therefore it's safe to -introduce asynchronous generators in 3.6.

      -
      -
      -
      -

      Performance

      -
      -

      Regular Generators

      -

      There is no performance degradation for regular generators. -The following micro benchmark runs at the same speed on CPython with -and without asynchronous generators:

      -
      -def gen():
      -    i = 0
      -    while i < 100000000:
      -        yield i
      -        i += 1
      -
      -list(gen())
      -
      -
      -
      -

      Improvements over asynchronous iterators

      -

      The following micro-benchmark shows that asynchronous generators -are about 2.3x faster than asynchronous iterators implemented in -pure Python:

      -
      -N = 10 ** 7
      -
      -async def agen():
      -    for i in range(N):
      -        yield i
      -
      -class AIter:
      -    def __init__(self):
      -        self.i = 0
      -
      -    def __aiter__(self):
      -        return self
      -
      -    async def __anext__(self):
      -        i = self.i
      -        if i >= N:
      -            raise StopAsyncIteration
      -        self.i += 1
      -        return i
      -
      -
      -
      -
      -

      Design Considerations

      -
      -

      aiter() and anext() builtins

      -

      Originally, PEP 492 defined __aiter__ as a method that should -return an awaitable object, resulting in an asynchronous iterator.

      -

      However, in CPython 3.5.2, __aiter__ was redefined to return -asynchronous iterators directly. To avoid breaking backwards -compatibility, it was decided that Python 3.6 will support both -ways: __aiter__ can still return an awaitable with -a DeprecationWarning being issued.

      -

      Because of this dual nature of __aiter__ in Python 3.6, we cannot -add a synchronous implementation of aiter() built-in. Therefore, -it is proposed to wait until Python 3.7.

      -
      -
      -

      Asynchronous list/dict/set comprehensions

      -

      Syntax for asynchronous comprehensions is unrelated to the asynchronous -generators machinery, and should be considered in a separate PEP.

      -
      -
      -

      Asynchronous yield from

      -

      While it is theoretically possible to implement yield from support -for asynchronous generators, it would require a serious redesign of the -generators implementation.

      -

      yield from is also less critical for asynchronous generators, since -there is no need provide a mechanism of implementing another coroutines -protocol on top of coroutines. And to compose asynchronous generators a -simple async for loop can be used:

      -
      -async def g1():
      -    yield 1
      -    yield 2
      -
      -async def g2():
      -    async for v in g1():
      -        yield v
      -
      -
      -
      -

      Why the asend() and athrow() methods are necessary

      -

      They make it possible to implement concepts similar to -contextlib.contextmanager using asynchronous generators. -For instance, with the proposed design, it is possible to implement -the following pattern:

      -
      -@async_context_manager
      -async def ctx():
      -    await open()
      -    try:
      -        yield
      -    finally:
      -        await close()
      -
      -async with ctx():
      -    await ...
      -
      -

      Another reason is that it is possible to push data and throw exceptions -into asynchronous generators using the object returned from -__anext__ object, but it is hard to do that correctly. Adding -explicit asend() and athrow() will pave a safe way to -accomplish that.

      -

      In terms of implementation, asend() is a slightly more generic -version of __anext__, and athrow() is very similar to -aclose(). Therefore having these methods defined for asynchronous -generators does not add any extra complexity.

      -
      -
      -
      -

      Example

      -

      A working example with the current reference implementation (will -print numbers from 0 to 9 with one second delay):

      -
      -async def ticker(delay, to):
      -    for i in range(to):
      -        yield i
      -        await asyncio.sleep(delay)
      -
      -
      -async def run():
      -    async for i in ticker(1, 10):
      -        print(i)
      -
      -
      -import asyncio
      -loop = asyncio.get_event_loop()
      -try:
      -    loop.run_until_complete(run())
      -finally:
      -    loop.close()
      -
      -
      -
      -

      Implementation

      -

      The complete reference implementation is available at [1].

      -
      - - - diff --git a/peps/tests/peps/pep-3001-1.png b/peps/tests/peps/pep-3001-1.png deleted file mode 100644 index 7f63aea5041e88f26907237a7131f989a0c975e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14117 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 ngzX&X`Tj - --- - - - - - - - - - - - - - - - - - - - - - -
      PEP:3001
      Title:Procedure for reviewing and improving standard library modules
      Version:$Revision$
      Last-Modified:$Date$
      Author:Georg Brandl <georg at python.org>
      Status:Withdrawn
      Type:Process
      Content-Type:text/x-rst
      Created:05-Apr-2006
      Post-History:
      -
      - -
      -

      Abstract

      -

      This PEP describes a procedure for reviewing and improving standard -library modules, especially those written in Python, making them ready -for Python 3000. There can be different steps of refurbishing, each -of which is described in a section below. Of course, not every step -has to be performed for every module.

      -
      -
      -

      Removal of obsolete modules

      -

      All modules marked as deprecated in 2.x versions should be removed for -Python 3000. The same applies to modules which are seen as obsolete today, -but are too widely used to be deprecated or removed. Python 3000 is the -big occasion to get rid of them. pep-3001-1.png

      -

      There will have to be a document listing all removed modules, together -with information on possible substitutes or alternatives. This infor- -mation will also have to be provided by the python3warn.py porting -helper script mentioned in PEP XXX.

      -
      -
      -

      Renaming modules

      -

      There are proposals for a "great stdlib renaming" introducing a hierarchic -library namespace or a top-level package from which to import standard -modules. That possibility aside, some modules' names are known to have -been chosen unwisely, a mistake which could never be corrected in the 2.x -series. Examples are names like "StringIO" or "Cookie". For Python 3000, -there will be the possibility to give those modules less confusing and -more conforming names.

      -

      Of course, each rename will have to be stated in the documentation of -the respective module and perhaps in the global document of Step 1. -Additionally, the python3warn.py script will recognize the old module -names and notify the user accordingly.

      -

      If the name change is made in time for another release of the Python 2.x -series, it is worth considering to introduce the new name in the 2.x -branch to ease transition.

      -
      -
      -

      Code cleanup

      -

      As most library modules written in Python have not been touched except -for bug fixes, following the policy of never changing a running system, -many of them may contain code that is not up to the newest language -features and could be rewritten in a more concise, modern Python.

      -

      PyChecker should run cleanly over the library. With a carefully tuned -configuration file, PyLint should also emit as few warnings as possible.

      -

      As long as these changes don't change the module's interface and behavior, -no documentation updates are necessary.

      -
      -
      -

      Enhancement of test and documentation coverage

      -

      Code coverage by unit tests varies greatly between modules. Each test -suite should be checked for completeness, and the remaining classic tests -should be converted to PyUnit (or whatever new shiny testing framework -comes with Python 3000, perhaps py.test?).

      -

      It should also be verified that each publicly visible function has a -meaningful docstring which ideally contains several doctests.

      -

      No documentation changes are necessary for enhancing test coverage.

      -
      -
      -

      Unification of module metadata

      -

      This is a small and probably not very important step. There have been -various attempts at providing author, version and similar metadata in -modules (such as a "__version__" global). Those could be standardized -and used throughout the library.

      -

      No documentation changes are necessary for this step, too.

      -
      -
      -

      Backwards incompatible bug fixes

      -

      Over the years, many bug reports have been filed which complained about -bugs in standard library modules, but have subsequently been closed as -"Won't fix" since a fix would have introduced a major incompatibility -which was not acceptable in the Python 2.x series. In Python 3000, the -fix can be applied if the interface per se is still acceptable.

      -

      Each slight behavioral change caused by such fixes must be mentioned in -the documentation, perhaps in a "Changed in Version 3.0" paragraph.

      -
      -
      -

      Interface changes

      -

      The last and most disruptive change is the overhaul of a module's public -interface. If a module's interface is to be changed, a justification -should be made beforehand, or a PEP should be written.

      -

      The change must be fully documented as "New in Version 3.0", and the -python3warn.py script must know about it.

      -
      -
      -

      References

      -

      None yet.

      -
      - - diff --git a/peps/tests/test_commands.py b/peps/tests/test_commands.py deleted file mode 100644 index 2579a5f99..000000000 --- a/peps/tests/test_commands.py +++ /dev/null @@ -1,56 +0,0 @@ -import io - -from bs4 import BeautifulSoup - -from django.test import TestCase, override_settings -from django.conf import settings -from django.core import serializers -from django.core.management import call_command - -import responses - -from pages.models import Image - -from . import FAKE_PEP_ARTIFACT - - -PEP_ARTIFACT_URL = 'https://example.net/fake-peps.tar.gz' - - -@override_settings(PEP_ARTIFACT_URL=PEP_ARTIFACT_URL) -class PEPManagementCommandTests(TestCase): - - def setUp(self): - responses.add( - responses.GET, - PEP_ARTIFACT_URL, - headers={'Last-Modified': 'Sun, 24 Feb 2019 18:01:42 GMT'}, - stream=True, - content_type='application/x-tar', - status=200, - body=open(FAKE_PEP_ARTIFACT, 'rb'), - ) - - @responses.activate - def test_generate_pep_pages_real_with_remote_artifact(self): - call_command('generate_pep_pages') - - @override_settings(PEP_ARTIFACT_URL=FAKE_PEP_ARTIFACT) - def test_generate_pep_pages_real_with_local_artifact(self): - call_command('generate_pep_pages') - - @responses.activate - def test_image_generated(self): - call_command('generate_pep_pages') - img = Image.objects.get(page__path='dev/peps/pep-3001/') - soup = BeautifulSoup(img.page.content.raw, 'lxml') - self.assertIn(settings.MEDIA_URL, soup.find('img')['src']) - - @responses.activate - def test_dump_pep_pages(self): - call_command('generate_pep_pages') - stdout = io.StringIO() - call_command('dump_pep_pages', stdout=stdout) - output = stdout.getvalue() - result = list(serializers.deserialize('json', output)) - self.assertGreater(len(result), 0) diff --git a/peps/tests/test_converters.py b/peps/tests/test_converters.py deleted file mode 100644 index 833bf7c0e..000000000 --- a/peps/tests/test_converters.py +++ /dev/null @@ -1,64 +0,0 @@ -from django.test import TestCase, override_settings -from django.core.exceptions import ImproperlyConfigured -from django.test.utils import captured_stdout - -from peps.converters import get_pep0_page, get_pep_page, add_pep_image - -from . import FAKE_PEP_REPO - - -class PEPConverterTests(TestCase): - - def test_source_link(self): - pep = get_pep_page(FAKE_PEP_REPO, '0525') - self.assertEqual(pep.title, 'PEP 525 -- Asynchronous Generators') - self.assertIn( - 'Source: https://github.com/python/peps/blob/master/pep-0525.txt', - pep.content.rendered - ) - - def test_source_link_rst(self): - pep = get_pep_page(FAKE_PEP_REPO, '0012') - self.assertEqual(pep.title, 'PEP 12 -- Sample reStructuredText PEP Template') - self.assertIn( - 'Source: https://github.com/python/peps/blob/master/pep-0012.rst', - pep.content.rendered - ) - - def test_invalid_pep_number(self): - with captured_stdout() as stdout: - get_pep_page(FAKE_PEP_REPO, '9999999') - self.assertRegex( - stdout.getvalue(), - r"PEP Path '(.*)9999999(.*)' does not exist, skipping" - ) - - def test_add_image_not_found(self): - with captured_stdout() as stdout: - add_pep_image(FAKE_PEP_REPO, '0525', '/path/that/does/not/exist') - self.assertRegex( - stdout.getvalue(), - r"Image Path '(.*)/path/that/does/not/exist(.*)' does not exist, skipping" - ) - - def test_html_do_not_prettify(self): - pep = get_pep_page(FAKE_PEP_REPO, '3001') - self.assertEqual( - pep.title, - 'PEP 3001 -- Procedure for reviewing and improving standard library modules' - ) - self.assertIn( - 'Title:' - 'Procedure for reviewing and improving ' - 'standard library modules\n', - pep.content.rendered - ) - - def test_strip_html_and_body_tags(self): - pep = get_pep_page(FAKE_PEP_REPO, '0525') - self.assertNotIn('', pep.content.rendered) - self.assertNotIn('', pep.content.rendered) - self.assertNotIn('', pep.content.rendered) - self.assertNotIn('', pep.content.rendered) diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 30dc8de4a..2c392b355 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -222,7 +222,6 @@ 'minutes', 'nominations', 'pages', - 'peps', 'sponsors', 'successstories', 'users', @@ -285,10 +284,6 @@ ### Registration mailing lists MAILING_LIST_PSF_MEMBERS = "psf-members-announce-request@python.org" -### PEP Repo Location -PEP_REPO_PATH = None -PEP_ARTIFACT_URL = 'https://pythondotorg-assets-staging.s3.amazonaws.com/fake-peps.tar.gz' - ### Fastly ### FASTLY_API_KEY = False # Set to Fastly API key in production to allow pages to # be purged on save diff --git a/templates/components/pep-widget.html b/templates/components/pep-widget.html deleted file mode 100644 index bba29ea2d..000000000 --- a/templates/components/pep-widget.html +++ /dev/null @@ -1,19 +0,0 @@ -{% load peps %} -
      - -

      - >>> Python Enhancement Proposals (PEPs): The future of Python is discussed here. - -

      - - - {# This isn't that awesome, commenting out for now #} - {% comment %} - {% get_newest_pep_pages as peps %} - - {% endcomment %} -
      \ No newline at end of file diff --git a/templates/python/documentation.html b/templates/python/documentation.html index 7db3662d2..e301b0010 100644 --- a/templates/python/documentation.html +++ b/templates/python/documentation.html @@ -106,7 +106,4 @@

      P

    - - {% include 'components/pep-widget.html' %} - {% endblock content %} diff --git a/templates/python/index.html b/templates/python/index.html index ac8b191df..753a53407 100644 --- a/templates/python/index.html +++ b/templates/python/index.html @@ -85,8 +85,6 @@
    - {% include 'components/pep-widget.html' %} - {% include 'components/psf-widget.html' %} {% endblock content %} From 552229a495fc79990cc311d85080efdecfd652c1 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Mon, 16 Sep 2024 08:05:48 -0500 Subject: [PATCH 109/235] feat(#639): update wording for job tech -> type (#2557) --- ...pe_options_alter_job_job_types_and_more.py | 27 +++++++++++++++++++ jobs/models.py | 8 +++--- 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 jobs/migrations/0022_alter_jobtype_options_alter_job_job_types_and_more.py diff --git a/jobs/migrations/0022_alter_jobtype_options_alter_job_job_types_and_more.py b/jobs/migrations/0022_alter_jobtype_options_alter_job_job_types_and_more.py new file mode 100644 index 000000000..4013f2376 --- /dev/null +++ b/jobs/migrations/0022_alter_jobtype_options_alter_job_job_types_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.16 on 2024-09-13 17:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('jobs', '0021_alter_job_creator_alter_job_last_modified_by_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='jobtype', + options={'ordering': ('name',), 'verbose_name': 'job types', 'verbose_name_plural': 'job types'}, + ), + migrations.AlterField( + model_name='job', + name='job_types', + field=models.ManyToManyField(blank=True, limit_choices_to={'active': True}, related_name='jobs', to='jobs.jobtype', verbose_name='Job types'), + ), + migrations.AlterField( + model_name='job', + name='other_job_type', + field=models.CharField(blank=True, max_length=100, verbose_name='Other job types'), + ), + ] diff --git a/jobs/models.py b/jobs/models.py index 54722873d..8b232fb93 100644 --- a/jobs/models.py +++ b/jobs/models.py @@ -30,8 +30,8 @@ class JobType(NameSlugModel): objects = JobTypeQuerySet.as_manager() class Meta: - verbose_name = 'job technologies' - verbose_name_plural = 'job technologies' + verbose_name = 'job types' + verbose_name_plural = 'job types' ordering = ('name', ) @@ -59,11 +59,11 @@ class Job(ContentManageable): JobType, related_name='jobs', blank=True, - verbose_name='Job technologies', + verbose_name='Job types', limit_choices_to={'active': True}, ) other_job_type = models.CharField( - verbose_name='Other job technologies', + verbose_name='Other job types', max_length=100, blank=True, ) From 7eac3351ee0827dc7f4a311d1164e56b141f3e2a Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Mon, 16 Sep 2024 08:06:55 -0500 Subject: [PATCH 110/235] feat(#2492): use newest compose command (#2558) --- Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 50585463a..bd4291bbe 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ default: .state/docker-build-web: Dockerfile dev-requirements.txt base-requirements.txt # Build web container for this project - docker-compose build --force-rm web + docker compose build --force-rm web # Mark the state so we don't rebuild this needlessly. mkdir -p .state && touch .state/docker-build-web @@ -24,35 +24,35 @@ default: .state/db-initialized: .state/docker-build-web .state/db-migrated # Load all fixtures - docker-compose run --rm web ./manage.py loaddata fixtures/*.json + docker compose run --rm web ./manage.py loaddata fixtures/*.json # Mark the state so we don't rebuild this needlessly. mkdir -p .state && touch .state/db-initialized serve: .state/db-initialized - docker-compose up --remove-orphans + docker compose up --remove-orphans migrations: .state/db-initialized # Run Django makemigrations - docker-compose run --rm web ./manage.py makemigrations + docker compose run --rm web ./manage.py makemigrations migrate: .state/docker-build-web # Run Django migrate - docker-compose run --rm web ./manage.py migrate + docker compose run --rm web ./manage.py migrate manage: .state/db-initialized # Run Django manage to accept arbitrary arguments - docker-compose run --rm web ./manage.py $(filter-out $@,$(MAKECMDGOALS)) + docker compose run --rm web ./manage.py $(filter-out $@,$(MAKECMDGOALS)) shell: .state/db-initialized - docker-compose run --rm web ./manage.py shell + docker compose run --rm web ./manage.py shell clean: - docker-compose down -v + docker compose down -v rm -f .state/docker-build-web .state/db-initialized .state/db-migrated test: .state/db-initialized - docker-compose run --rm web ./manage.py test + docker compose run --rm web ./manage.py test docker_shell: .state/db-initialized - docker-compose run --rm web /bin/bash + docker compose run --rm web /bin/bash From 4aa0d26fc41ab98642f30722b4b94677f494ca2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:44:14 -0500 Subject: [PATCH 111/235] Bump panflute from 2.3.0 to 2.3.1 (#2563) Bumps [panflute](https://github.com/sergiocorreia/panflute) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/sergiocorreia/panflute/releases) - [Commits](https://github.com/sergiocorreia/panflute/commits) --- updated-dependencies: - dependency-name: panflute dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 4f9c0aa39..680685cfc 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -52,5 +52,5 @@ django-extensions==3.1.4 django-import-export==2.7.1 pypandoc==1.12 -panflute==2.3.0 +panflute==2.3.1 Unidecode==1.3.8 From 0969d7213ee012331fa05b12ca35c87fa60a4eb2 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Mon, 16 Sep 2024 11:45:02 -0400 Subject: [PATCH 112/235] Pages: Also purge trailing slash (#2565) Fastly purge requests are sensitive to trailing slash, so to ensure we get the result we want we should also purge that. --- pages/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/models.py b/pages/models.py index 9b67997e1..c3973ce68 100644 --- a/pages/models.py +++ b/pages/models.py @@ -137,6 +137,8 @@ def purge_fastly_cache(sender, instance, **kwargs): Requires settings.FASTLY_API_KEY being set """ purge_url(f'/{instance.path}') + if not instance.path.endswith('/'): + purge_url(f'/{instance.path}/') def page_image_path(instance, filename): From 1795b1f27dba8b40c27c82675411a8ba4978563b Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Mon, 16 Sep 2024 11:00:00 -0500 Subject: [PATCH 113/235] feat: add ngwaf (#2527) * feat: add ngwaf with successful tfplan * docs: update to latest var name * chore: apply formatting * feat: make ngwaf bits enabled via var * fix: use var fvor activation * fix: fix invalid syntax * fix: fix invalid syntax again * chore: use service account * chore: cleanup cruft * fix: apply patch for dynamic dynamic things * Update infra/cdn/README.md * Update infra/cdn/README.md --- infra/.terraform.lock.hcl | 22 +++++++++++++ infra/cdn/README.md | 28 ++++++++++++++-- infra/cdn/main.tf | 69 +++++++++++++++++++++++++++++++++++++++ infra/cdn/ngwaf.tf | 49 +++++++++++++++++++++++++++ infra/cdn/providers.tf | 8 +++++ infra/cdn/variables.tf | 36 +++++++++++++++++++- infra/cdn/versions.tf | 4 +++ infra/main.tf | 18 +++++++--- infra/variables.tf | 7 +++- 9 files changed, 233 insertions(+), 8 deletions(-) create mode 100644 infra/cdn/ngwaf.tf diff --git a/infra/.terraform.lock.hcl b/infra/.terraform.lock.hcl index 165cd9357..5844f52bd 100644 --- a/infra/.terraform.lock.hcl +++ b/infra/.terraform.lock.hcl @@ -22,3 +22,25 @@ provider "registry.terraform.io/fastly/fastly" { "zh:ec8d899cafd925d3492f00c6523c90599aebc43c1373ad4bd6c55f12d2376230", ] } + +provider "registry.terraform.io/signalsciences/sigsci" { + version = "3.3.0" + constraints = "3.3.0" + hashes = [ + "h1:DIoFVzfofY8lQSxFTw9wmQQC28PPMq+5l3xbPNw9gLc=", + "zh:07c25e1cca9c13314429a8430c2e999ad94c7d5e2f2a11501ee2608182387e61", + "zh:07daf79b672f3e0bec7b48e3ac8dcdeec02af06b10d653bd8158a74236b0746b", + "zh:1e24a050c3d3571ec3224c4bb5c82635caf636e707b5993a1cc97c9a1f19fa8f", + "zh:24293ae24b3de13bda8512c47967f01814724805396a1bfbfbfc56f5627615cc", + "zh:2cc6ba7a38d9854146d1d05f4b7a2f8e18a33c1267b768506cbe37168dad01dc", + "zh:42065bfee0cfde04096d6140c65379253359bed49b481a97aff70aa65bf568b3", + "zh:6f7f4d96967dfd92f098b57647d396679b70d92548db6d100c4dc8723569d175", + "zh:a2e4431f045cef16ed152c0d1f8a377b6468351b775ad1ca7ce3fe74fb874be2", + "zh:b0ed1cb03d6f191fe211f10bb59ef8daed6f89e3d99136e7bb5d38f2ac72fa45", + "zh:b61ea18442a65d27b97dd1cd43bdd8d0a56c2b4b8db6355480e89f8507c6782a", + "zh:c31bb2f50ac2a636758f93afec0b9d173be6d7d7476f9e250b4554e70c6d8d82", + "zh:cb7337f7b4678ad7ece28741069c07ce5601d2a103a9667db568cf10ed0ee5a2", + "zh:d521a7dac51733aebb0905e25b8f7c1279d83c06136e87826e010c667528fd3e", + "zh:ef791688acee3b8b1191b3c6dc54dabf69612dbfb666720280b492ce348a3a06", + ] +} diff --git a/infra/cdn/README.md b/infra/cdn/README.md index 6ebe5a637..a667f63db 100644 --- a/infra/cdn/README.md +++ b/infra/cdn/README.md @@ -29,5 +29,29 @@ N/A ## Requirements Tested on -- Tested on Terraform 1.8.5 -- Fastly provider 5.13.0 \ No newline at end of file +- Tested on Terraform 1.9.5 +- Fastly provider 5.13.0 + +# Fastly's NGWAF + +This module also conditionally can set up the Fastly Next-Gen Web Application Firewall (NGWAF) +for our Fastly services related to python.org / test.python.org. + +## Usage + +```hcl +module "fastly_production" { + source = "./cdn" + + ... + activate_ngwaf_service = true + ... +} +``` + +## Requirements + +Tested on +- Terraform 1.9.5 +- Fastly provider 5.13.0 +- SigSci provider 3.3.0 \ No newline at end of file diff --git a/infra/cdn/main.tf b/infra/cdn/main.tf index 12d1fbba4..eb6c6858c 100644 --- a/infra/cdn/main.tf +++ b/infra/cdn/main.tf @@ -342,4 +342,73 @@ resource "fastly_service_vcl" "python_org" { response = "Forbidden" status = 403 } + + dynamic "dictionary" { + for_each = var.activate_ngwaf_service ? [1] : [] + content { + name = var.edge_security_dictionary + } + } + + dynamic "dynamicsnippet" { + for_each = var.activate_ngwaf_service ? [1] : [] + content { + name = "ngwaf_config_init" + type = "init" + priority = 0 + } + } + + dynamic "dynamicsnippet" { + for_each = var.activate_ngwaf_service ? [1] : [] + content { + name = "ngwaf_config_miss" + type = "miss" + priority = 9000 + } + } + + dynamic "dynamicsnippet" { + for_each = var.activate_ngwaf_service ? [1] : [] + content { + name = "ngwaf_config_pass" + type = "pass" + priority = 9000 + } + } + + dynamic "dynamicsnippet" { + for_each = var.activate_ngwaf_service ? [1] : [] + content { + name = "ngwaf_config_deliver" + type = "deliver" + priority = 9000 + } + } + + lifecycle { + ignore_changes = [ + product_enablement, + ] + } +} + +output "service_id" { + value = fastly_service_vcl.python_org.id + description = "The ID of the Fastly service" +} + +output "backend_address" { + value = var.backend_address + description = "The backend address for the service." +} + +output "service_name" { + value = var.name + description = "The name of the Fastly service" +} + +output "domain" { + value = var.domain + description = "The domain of the Fastly service" } diff --git a/infra/cdn/ngwaf.tf b/infra/cdn/ngwaf.tf new file mode 100644 index 000000000..8ca3a61f6 --- /dev/null +++ b/infra/cdn/ngwaf.tf @@ -0,0 +1,49 @@ +resource "fastly_service_dictionary_items" "edge_security_dictionary_items" { + count = var.activate_ngwaf_service ? 1 : 0 + service_id = fastly_service_vcl.python_org.id + dictionary_id = one([for d in fastly_service_vcl.python_org.dictionary : d.dictionary_id if d.name == var.edge_security_dictionary]) + items = { + Enabled : "100" + } +} + +resource "fastly_service_dynamic_snippet_content" "ngwaf_config_snippets" { + for_each = var.activate_ngwaf_service ? toset(["init", "miss", "pass", "deliver"]) : [] + service_id = fastly_service_vcl.python_org.id + snippet_id = one([for d in fastly_service_vcl.python_org.dynamicsnippet : d.snippet_id if d.name == "ngwaf_config_${each.key}"]) + content = "### Terraform managed ngwaf_config_${each.key}" + manage_snippets = false +} + +# NGWAF Edge Deployment on SignalSciences.net +resource "sigsci_edge_deployment" "ngwaf_edge_site_service" { + count = var.activate_ngwaf_service ? 1 : 0 + provider = sigsci.firewall + site_short_name = var.ngwaf_site_name +} + +resource "sigsci_edge_deployment_service" "ngwaf_edge_service_link" { + count = var.activate_ngwaf_service ? 1 : 0 + provider = sigsci.firewall + site_short_name = var.ngwaf_site_name + fastly_sid = fastly_service_vcl.python_org.id + activate_version = var.activate_ngwaf_service + percent_enabled = 100 + depends_on = [ + sigsci_edge_deployment.ngwaf_edge_site_service, + fastly_service_vcl.python_org, + fastly_service_dictionary_items.edge_security_dictionary_items, + fastly_service_dynamic_snippet_content.ngwaf_config_snippets, + ] +} + +resource "sigsci_edge_deployment_service_backend" "ngwaf_edge_service_backend_sync" { + count = var.activate_ngwaf_service ? 1 : 0 + provider = sigsci.firewall + site_short_name = var.ngwaf_site_name + fastly_sid = fastly_service_vcl.python_org.id + fastly_service_vcl_active_version = fastly_service_vcl.python_org.active_version + depends_on = [ + sigsci_edge_deployment_service.ngwaf_edge_service_link, + ] +} diff --git a/infra/cdn/providers.tf b/infra/cdn/providers.tf index 201f5de4a..bdee7a807 100644 --- a/infra/cdn/providers.tf +++ b/infra/cdn/providers.tf @@ -2,3 +2,11 @@ provider "fastly" { alias = "cdn" api_key = var.fastly_key } + +provider "sigsci" { + alias = "firewall" + corp = var.ngwaf_corp_name + email = var.ngwaf_email + auth_token = var.ngwaf_token + fastly_api_key = var.fastly_key +} diff --git a/infra/cdn/variables.tf b/infra/cdn/variables.tf index 4cbf6db6e..5c1be4562 100644 --- a/infra/cdn/variables.tf +++ b/infra/cdn/variables.tf @@ -40,4 +40,38 @@ variable "backend_address" { variable "default_ttl" { type = number description = "The default TTL for the service." -} \ No newline at end of file +} + +## NGWAF +variable "activate_ngwaf_service" { + type = bool + description = "Whether to activate the NGWAF service." +} +variable "edge_security_dictionary" { + type = string + description = "The dictionary name for the Edge Security product." + default = "" +} +variable "ngwaf_corp_name" { + type = string + description = "Corp name for NGWAF" + default = "python" +} +variable "ngwaf_site_name" { + type = string + description = "Site SHORT name for NGWAF" + + validation { + condition = can(regex("^(test|stage|prod)$", var.ngwaf_site_name)) + error_message = "'ngwaf_site_name' must be one of the following: test, stage, or prod" + } +} +variable "ngwaf_email" { + type = string + description = "Email address associated with the token for the NGWAF API." +} +variable "ngwaf_token" { + type = string + description = "Secret token for the NGWAF API." + sensitive = true +} diff --git a/infra/cdn/versions.tf b/infra/cdn/versions.tf index da9c01f79..f8c137ba6 100644 --- a/infra/cdn/versions.tf +++ b/infra/cdn/versions.tf @@ -4,5 +4,9 @@ terraform { source = "fastly/fastly" version = "5.13.0" } + sigsci = { + source = "signalsciences/sigsci" + version = "3.3.0" + } } } diff --git a/infra/main.tf b/infra/main.tf index b3ec26a77..90c2ba9c5 100644 --- a/infra/main.tf +++ b/infra/main.tf @@ -12,15 +12,20 @@ module "fastly_production" { fastly_key = var.FASTLY_API_KEY fastly_header_token = var.FASTLY_HEADER_TOKEN s3_logging_keys = var.fastly_s3_logging + + ngwaf_site_name = "prod" + ngwaf_email = "infrastructure-staff@python.org" + ngwaf_token = var.ngwaf_token + activate_ngwaf_service = false } module "fastly_staging" { source = "./cdn" - name = "test.python.org" - domain = "test.python.org" - subdomain = "www.test.python.org" - extra_domains = ["www.test.python.org"] + name = "test.python.org" + domain = "test.python.org" + subdomain = "www.test.python.org" + extra_domains = ["www.test.python.org"] # TODO: adjust to test-pythondotorg when done testing NGWAF backend_address = "pythondotorg.ingress.us-east-2.psfhosted.computer" default_ttl = 3600 @@ -29,4 +34,9 @@ module "fastly_staging" { fastly_key = var.FASTLY_API_KEY fastly_header_token = var.FASTLY_HEADER_TOKEN s3_logging_keys = var.fastly_s3_logging + + ngwaf_site_name = "test" + ngwaf_email = "infrastructure-staff@python.org" + ngwaf_token = var.ngwaf_token + activate_ngwaf_service = true } diff --git a/infra/variables.tf b/infra/variables.tf index ec23b23ec..33fc1dda5 100644 --- a/infra/variables.tf +++ b/infra/variables.tf @@ -17,4 +17,9 @@ variable "fastly_s3_logging" { type = map(string) description = "S3 bucket keys for Fastly logging" sensitive = true -} \ No newline at end of file +} +variable "ngwaf_token" { + type = string + description = "Secret token for the NGWAF API." + sensitive = true +} From 097df08265800240d092645328f271dfad3582a5 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Mon, 16 Sep 2024 12:13:12 -0500 Subject: [PATCH 114/235] fix: recreate dictionary each run (#2568) * fix: recreate dictionary each run * Update infra/cdn/main.tf --- infra/cdn/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/infra/cdn/main.tf b/infra/cdn/main.tf index eb6c6858c..c50888e3f 100644 --- a/infra/cdn/main.tf +++ b/infra/cdn/main.tf @@ -347,6 +347,7 @@ resource "fastly_service_vcl" "python_org" { for_each = var.activate_ngwaf_service ? [1] : [] content { name = var.edge_security_dictionary + force_destroy = true } } From edee24abe775f9ac7133134a9fe16b8adbe11254 Mon Sep 17 00:00:00 2001 From: Ee Durbin Date: Tue, 17 Sep 2024 11:38:35 -0400 Subject: [PATCH 115/235] add a name for the ngwaf edge dictionary (#2579) --- infra/cdn/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/cdn/variables.tf b/infra/cdn/variables.tf index 5c1be4562..ec0a11a83 100644 --- a/infra/cdn/variables.tf +++ b/infra/cdn/variables.tf @@ -50,7 +50,7 @@ variable "activate_ngwaf_service" { variable "edge_security_dictionary" { type = string description = "The dictionary name for the Edge Security product." - default = "" + default = "Edge_Security" } variable "ngwaf_corp_name" { type = string From 2856d9cc906b1f5f35debe00f19b0e9887947b0f Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Tue, 17 Sep 2024 11:03:47 -0500 Subject: [PATCH 116/235] infra: activate by default (#2580) * infra: activate by default * Update infra/cdn/main.tf --- infra/cdn/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/cdn/main.tf b/infra/cdn/main.tf index c50888e3f..e7aa77108 100644 --- a/infra/cdn/main.tf +++ b/infra/cdn/main.tf @@ -4,7 +4,7 @@ resource "fastly_service_vcl" "python_org" { http3 = false stale_if_error = false stale_if_error_ttl = 43200 - activate = false + activate = true domain { name = var.domain From 6b4c6815f06313ba84b7f5bb1d787faa14c4ff6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:49:59 -0500 Subject: [PATCH 117/235] Bump django-ordered-model from 3.4.3 to 3.7.4 (#2544) Bumps [django-ordered-model](https://github.com/django-ordered-model/django-ordered-model) from 3.4.3 to 3.7.4. - [Release notes](https://github.com/django-ordered-model/django-ordered-model/releases) - [Changelog](https://github.com/django-ordered-model/django-ordered-model/blob/master/CHANGES.md) - [Commits](https://github.com/django-ordered-model/django-ordered-model/compare/3.4.3...3.7.4) --- updated-dependencies: - dependency-name: django-ordered-model dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jacob Coffee --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 680685cfc..f616b8cb6 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -42,7 +42,7 @@ django-waffle==2.2.1 djangorestframework==3.14.0 # 3.14.0 is first version that supports Django 4.1, 4.2 support hasnt been "released" django-filter==2.4.0 -django-ordered-model==3.4.3 +django-ordered-model==3.7.4 django-widget-tweaks==1.5.0 django-countries==7.2.1 num2words==0.5.10 From 306a73df3c120664031670a47b04c3d8cc56c8c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 15:08:46 -0500 Subject: [PATCH 118/235] Bump num2words from 0.5.10 to 0.5.13 (#2574) Bumps [num2words](https://github.com/savoirfairelinux/num2words) from 0.5.10 to 0.5.13. - [Release notes](https://github.com/savoirfairelinux/num2words/releases) - [Changelog](https://github.com/savoirfairelinux/num2words/blob/master/CHANGES.rst) - [Commits](https://github.com/savoirfairelinux/num2words/compare/v0.5.10...v0.5.13) --- updated-dependencies: - dependency-name: num2words dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index f616b8cb6..d8b1295c9 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -45,7 +45,7 @@ django-filter==2.4.0 django-ordered-model==3.7.4 django-widget-tweaks==1.5.0 django-countries==7.2.1 -num2words==0.5.10 +num2words==0.5.13 django-polymorphic==3.1.0 # 3.1.0 is first version that supports Django 4.0, unsure if it fully supports 4.2 sorl-thumbnail==12.7.0 django-extensions==3.1.4 From e4883ee2b48b7ba8e9dd72166b1006ffbeb8917e Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Wed, 18 Sep 2024 13:22:40 -0500 Subject: [PATCH 119/235] feat(#1612): add rss feed for latest downloads (#2569) * feat: add rss feed for latest downloads * Update downloads/views.py * fix: query DB for releas * fix: query DB for releas * chore: add missing types * fix: update naive datetime, remove staticmethod * fix: remove staticmethod chore: apply formatting and ruuuuuff * chore: no logging needed after working * tests: add them * chore: address code reviews * chore: remove unused imports * chore: remove unused code * chore: remove unused code * fix: purge cdn cache * revert: put the code back, john --- downloads/models.py | 1 + downloads/tests/test_views.py | 42 ++++++++++++++++++++++++++++++ downloads/urls.py | 1 + downloads/views.py | 49 +++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/downloads/models.py b/downloads/models.py index 4a9c5781c..4576afb2f 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -272,6 +272,7 @@ def purge_fastly_download_pages(sender, instance, **kwargs): if instance.is_published: # Purge our common pages purge_url('/downloads/') + purge_url('/downloads/feed.rss') purge_url('/downloads/latest/python2/') purge_url('/downloads/latest/python3/') purge_url('/downloads/macos/') diff --git a/downloads/tests/test_views.py b/downloads/tests/test_views.py index c585fe05c..b559a2adc 100644 --- a/downloads/tests/test_views.py +++ b/downloads/tests/test_views.py @@ -554,3 +554,45 @@ def test_filter_release_file_delete_by_release(self): headers={"authorization": self.Authorization} ) self.assertEqual(response.status_code, 405) + +class ReleaseFeedTests(BaseDownloadTests): + """Tests for the downloads/feed.rss endpoint. + + Content is ensured via setUp in BaseDownloadTests. + """ + + url = reverse("downloads:feed") + + + def test_endpoint_reachable(self) -> None: + response = self.client.get(self.url) + self.assertEqual(response.status_code, 200) + + def test_feed_content(self) -> None: + """Ensure feed content is as expected. + + Some things we want to check: + - Feed title, description, pubdate + - Feed items (releases) are in the correct order + - We get the expected number of releases (10) + """ + response = self.client.get(self.url) + content = response.content.decode() + + self.assertIn("Python 2.7.5", content) + self.assertIn("Python 3.10", content) + # Published but hidden show up in the API and thus the feed + self.assertIn("Python 0.0.0", content) + + # No unpublished releases + self.assertNotIn("Python 9.7.2", content) + + # Pre-releases are shown + self.assertIn("Python 3.9.90", content) + + def test_feed_item_count(self) -> None: + response = self.client.get(self.url) + content = response.content.decode() + + # In BaseDownloadTests, we create 5 releases, 4 of which are published, 1 of those published are hidden.. + self.assertEqual(content.count(""), 4) diff --git a/downloads/urls.py b/downloads/urls.py index d64f0a1ad..f553caeaa 100644 --- a/downloads/urls.py +++ b/downloads/urls.py @@ -9,4 +9,5 @@ path('release//', views.DownloadReleaseDetail.as_view(), name='download_release_detail'), path('/', views.DownloadOSList.as_view(), name='download_os_list'), path('', views.DownloadHome.as_view(), name='download'), + path("feed.rss", views.ReleaseFeed(), name="feed"), ] diff --git a/downloads/views.py b/downloads/views.py index 746845402..92e851545 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -1,7 +1,14 @@ +from typing import Any + +from datetime import datetime + from django.db.models import Prefetch from django.urls import reverse +from django.utils import timezone from django.views.generic import DetailView, TemplateView, ListView, RedirectView from django.http import Http404 +from django.contrib.syndication.views import Feed +from django.utils.feedgenerator import Rss201rev2Feed from .models import OS, Release, ReleaseFile @@ -147,3 +154,45 @@ def get_context_data(self, **kwargs): ) return context + + +class ReleaseFeed(Feed): + """Generate an RSS feed of the latest Python releases. + + .. note:: It may seem like these are unused methods, but the superclass uses them + using Django's Syndication framework. + Docs: https://docs.djangoproject.com/en/4.2/ref/contrib/syndication/ + """ + + feed_type = Rss201rev2Feed + title = "Python Releases" + description = "Latest Python releases from Python.org" + + @staticmethod + def link() -> str: + """Return the URL to the main downloads page.""" + return reverse("downloads:download") + + def items(self) -> list[dict[str, Any]]: + """Return the latest Python releases.""" + return Release.objects.filter(is_published=True).order_by("-release_date")[:10] + + def item_title(self, item: Release) -> str: + """Return the release name as the item title.""" + return item.name + + def item_description(self, item: Release) -> str: + """Return the release version and release date as the item description.""" + return f"Version: {item.version}, Release Date: {item.release_date}" + + def item_pubdate(self, item: Release) -> datetime | None: + """Return the release date as the item publication date.""" + if item.release_date: + if timezone.is_naive(item.release_date): + return timezone.make_aware(item.release_date) + return item.release_date + return None + + def item_guid(self, item: Release) -> str: + """Return a unique ID for the item based on DB record.""" + return str(item.pk) From 993d52deed99ae6a808ff3f70ebdbcb78dd000f3 Mon Sep 17 00:00:00 2001 From: Jacob Coffee Date: Wed, 18 Sep 2024 13:25:12 -0500 Subject: [PATCH 120/235] infra: update templates to new form style, add config links (#2571) * infra: update templates to new form style, add config links * fix: update links * chore: casing * chore: no caps! --- .github/ISSUE_TEMPLATE/BUG.yml | 119 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/DOCS.yml | 23 +++++ .github/ISSUE_TEMPLATE/REQUEST.yml | 66 ++++++++++++ .github/ISSUE_TEMPLATE/bug_report.md | 45 -------- .github/ISSUE_TEMPLATE/config.yml | 14 +++ .github/ISSUE_TEMPLATE/feature_request.md | 27 ----- 6 files changed, 222 insertions(+), 72 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/BUG.yml create mode 100644 .github/ISSUE_TEMPLATE/DOCS.yml create mode 100644 .github/ISSUE_TEMPLATE/REQUEST.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/BUG.yml b/.github/ISSUE_TEMPLATE/BUG.yml new file mode 100644 index 000000000..9adc2b03a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG.yml @@ -0,0 +1,119 @@ +name: "Bug Report" +description: Report a bug with pyton.org website to help us improve +title: "Bug: " +labels: ["bug", "Triage Required"] + +body: + - type: markdown + attributes: + value: | + This is the repository and issue tracker for the https://www.pyton.org website. + + If you're looking to file an issue with CPython itself, please click here: [CPython Issues](https://github.com/python/cpython/issues/new/choose). + + Issues related to [Python's documentation](https://docs.python.org) can also be filed [here](https://github.com/python/cpython/issues/new?assignees=&labels=docs&template=documentation.md). + + - type: textarea + id: description + attributes: + label: "Describe the bug" + description: A clear and concise description of what the bug is. + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: "To Reproduce" + description: Steps to reproduce the behavior + placeholder: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + + - type: textarea + id: expected + attributes: + label: "Expected behavior" + description: A clear and concise description of what you expected to happen. + validations: + required: true + + - type: input + id: reprod-url + attributes: + label: "URL to the issue" + description: Please enter the URL to provide a reproduction of the issue, if applicable + placeholder: ex. https://python.org/my-issue/here + validations: + required: false + + - type: textarea + id: screenshot + attributes: + label: "Screenshots" + description: If applicable, add screenshots to help explain your problem. + value: | + "![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)" + render: bash + validations: + required: false + + - type: dropdown + id: browsers + attributes: + label: "Browsers" + description: What browsers are you seeing the problem on? + multiple: true + options: + - Firefox + - Chrome + - Safari + - Microsoft Edge + - Other + validations: + required: true + + - type: dropdown + id: os + attributes: + label: "Operating System" + description: What operating system are you using? + options: + - Windows + - macOS + - Linux + - iOS + - Android + - Other + validations: + required: true + + - type: input + id: version + attributes: + label: "Browser Version" + description: What version of the browser are you using? + placeholder: "e.g. 22" + validations: + required: false + + - type: textarea + id: logs + attributes: + label: "Relevant log output" + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell + validations: + required: false + + - type: textarea + id: additional + attributes: + label: "Additional context" + description: Add any other context about the problem here. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/DOCS.yml b/.github/ISSUE_TEMPLATE/DOCS.yml new file mode 100644 index 000000000..df7a2c231 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/DOCS.yml @@ -0,0 +1,23 @@ +name: "Documentation Update" +description: Create an issue for documentation changes +title: "Docs: <title>" +labels: ["documentation"] + +body: + - type: markdown + attributes: + value: | + This is the repository and issue tracker for the https://www.pyton.org website. + + If you're looking to file an issue with CPython itself, please click here: [CPython Issues](https://github.com/python/cpython/issues/new/choose). + + Issues related to [Python's documentation](https://docs.python.org) can also be filed [here](https://github.com/python/cpython/issues/new?assignees=&labels=docs&template=documentation.md). + + - type: textarea + id: summary + attributes: + label: "Summary" + description: Provide a brief summary of your request + placeholder: We need to update the documentation to include information about... + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/REQUEST.yml b/.github/ISSUE_TEMPLATE/REQUEST.yml new file mode 100644 index 000000000..144ad75c1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/REQUEST.yml @@ -0,0 +1,66 @@ +name: "Feature Request" +description: Suggest an idea for www.pyton.org +title: "Enhancement: <title>" +labels: ["enhancement"] + +body: + - type: markdown + attributes: + value: | + This is the repository and issue tracker for the https://www.pyton.org website. + + If you're looking to file an issue with CPython itself, please click here: [CPython Issues](https://github.com/python/cpython/issues/new/choose). + + Issues related to [Python's documentation](https://docs.python.org) can also be filed [here](https://github.com/python/cpython/issues/new?assignees=&labels=docs&template=documentation.md). + + - type: textarea + id: problem + attributes: + label: "Is your feature request related to a problem? Please describe." + description: A clear and concise description of what the problem is. + placeholder: Ex. I'm always frustrated when [...] + validations: + required: true + + - type: textarea + id: solution + attributes: + label: "Describe the solution you'd like" + description: A clear and concise description of what you want to happen. + placeholder: Ex. It would be great if [...] + validations: + required: true + + - type: textarea + id: basic_example + attributes: + label: "Basic Example" + description: Provide some basic examples of your feature request. + placeholder: Describe how your feature would work with a simple example. + validations: + required: false + + - type: textarea + id: alternatives + attributes: + label: "Describe alternatives you've considered" + description: A clear and concise description of any alternative solutions or features you've considered. + validations: + required: false + + - type: textarea + id: drawbacks + attributes: + label: "Drawbacks and Impact" + description: What are the drawbacks or impacts of your feature request? + placeholder: Describe any potential drawbacks or impacts of implementing this feature. + validations: + required: false + + - type: textarea + id: additional_context + attributes: + label: "Additional context" + description: Add any other context or screenshots about the feature request here. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index c958c11a4..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -name: Bug report -about: Report a bug with Python.org website to help us improve ---- - -<!-- -This is the repository and issue tracker for https://www.python.org -website. - -If you're looking to file an issue with CPython itself, please go to -https://github.com/python/cpython/issues/new/choose - -Issues related to Python's documentation (https://docs.python.org) can -also be filed at https://github.com/python/cpython/issues/new?assignees=&labels=docs&template=documentation.md. ---> - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..cd8c31d2a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false +contact_links: + - name: CPython Documentation + url: https://docs.python.org/ + about: Official CPython documentation - please check here before opening an issue. + - name: Python Website + url: https://python.org/ + about: For all things Python + - name: PyPI Issues / Support + url: https://github.com/pypi/support + about: For issues with PyPI itself, PyPI accounts, or with packages hosted on PyPI. + - name: CPython Issues + url: https://github.com/python/cpython/issues + about: For issues with the CPython interpreter itself. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 514274e5f..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for www.python.org ---- - -<!-- -This is the repository and issue tracker for https://www.python.org -website. - -If you're looking to file an issue with CPython itself, please go to -https://github.com/python/cpython/issues/new/choose - -Issues related to Python's documentation (https://docs.python.org) can -also be filed at https://github.com/python/cpython/issues/new?assignees=&labels=docs&template=documentation.md. ---> - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. Ex. It would be great if [...] - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. From bbaa2a1e8161481a50de57163ef88e9ced2ec7ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:38:37 -0500 Subject: [PATCH 121/235] Bump celery[redis] from 5.3.6 to 5.4.0 (#2550) Bumps [celery[redis]](https://github.com/celery/celery) from 5.3.6 to 5.4.0. - [Release notes](https://github.com/celery/celery/releases) - [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst) - [Commits](https://github.com/celery/celery/compare/v5.3.6...v5.4.0) --- updated-dependencies: - dependency-name: celery[redis] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index d8b1295c9..fc018561c 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -19,7 +19,7 @@ feedparser==6.0.11 beautifulsoup4==4.12.3 icalendar==4.0.7 chardet==4.0.0 -celery[redis]==5.3.6 +celery[redis]==5.4.0 django-celery-beat==2.5.0 # TODO: We may drop 'django-imagekit' completely. django-imagekit==5.0 # 5.0 is first version that supports Django 4.2 From 7e414b5e0a7b10d8db7f7ee1b9e57c3db9939d03 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Wed, 18 Sep 2024 15:40:31 -0500 Subject: [PATCH 122/235] feat: add new download feed to base head (#2587) --- templates/base.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/base.html b/templates/base.html index 578dc1204..a1cfba788 100644 --- a/templates/base.html +++ b/templates/base.html @@ -96,6 +96,8 @@ href="https://feeds.feedburner.com/PythonSoftwareFoundationNews"> <link rel="alternate" type="application/rss+xml" title="Python Insider" href="https://feeds.feedburner.com/PythonInsider"> + <link rel="alternate" type="application/rss+xml" title="Python Releases" + href="https://www.python.org/downloads/feed.rss"> {% comment %} No support for these yet... From dc57cd2963c43e6c007c7ce5be9f68b67d6a05bb Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Wed, 18 Sep 2024 15:50:00 -0500 Subject: [PATCH 123/235] fix: guid must be a full URL, use item link url (#2588) --- downloads/views.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/downloads/views.py b/downloads/views.py index 92e851545..6a7f9d95e 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -192,7 +192,3 @@ def item_pubdate(self, item: Release) -> datetime | None: return timezone.make_aware(item.release_date) return item.release_date return None - - def item_guid(self, item: Release) -> str: - """Return a unique ID for the item based on DB record.""" - return str(item.pk) From 51c5b5de88c607d8fdaf0c1c463a36c234489bf4 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Thu, 19 Sep 2024 16:04:40 -0500 Subject: [PATCH 124/235] fix: display active events, fix time not displaying for some events (#2556) * fix: display active events, fix time not displaying for some events * test: passing events view tests * style: different icon * Update views.py Co-authored-by: Ee Durbin <ewdurbin@gmail.com> --------- Co-authored-by: Ee Durbin <ewdurbin@gmail.com> --- events/models.py | 11 ++- events/tests/test_views.py | 61 +++++++++++++-- events/views.py | 23 ++++-- templates/events/event_list.html | 123 ++++++++++++++++++++----------- 4 files changed, 161 insertions(+), 57 deletions(-) diff --git a/events/models.py b/events/models.py index b41d92b22..1f2ab2cb0 100644 --- a/events/models.py +++ b/events/models.py @@ -211,8 +211,15 @@ def previous_time(self): return None @property - def next_or_previous_time(self): - return self.next_time or self.previous_time + def next_or_previous_time(self) -> models.Model: + """Return the next or previous time of the event OR the occurring rule.""" + if next_time := self.next_time: + return next_time + + if previous_time := self.previous_time: + return previous_time + + return self.occurring_rule if hasattr(self, "occurring_rule") else None @property def is_past(self): diff --git a/events/tests/test_views.py b/events/tests/test_views.py index 691817036..1291252a5 100644 --- a/events/tests/test_views.py +++ b/events/tests/test_views.py @@ -35,11 +35,50 @@ def setUpTestData(cls): finish=cls.now - datetime.timedelta(days=1), ) + # Future event + cls.future_event = Event.objects.create(title='Future Event', creator=cls.user, calendar=cls.calendar, featured=True) + RecurringRule.objects.create( + event=cls.future_event, + begin=cls.now + datetime.timedelta(days=1), + finish=cls.now + datetime.timedelta(days=2), + ) + + # Happening now event + cls.current_event = Event.objects.create(title='Current Event', creator=cls.user, calendar=cls.calendar) + RecurringRule.objects.create( + event=cls.current_event, + begin=cls.now - datetime.timedelta(hours=1), + finish=cls.now + datetime.timedelta(hours=1), + ) + + # Just missed event + cls.just_missed_event = Event.objects.create(title='Just Missed Event', creator=cls.user, calendar=cls.calendar) + RecurringRule.objects.create( + event=cls.just_missed_event, + begin=cls.now - datetime.timedelta(hours=3), + finish=cls.now - datetime.timedelta(hours=1), + ) + + # Past event + cls.past_event = Event.objects.create(title='Past Event', creator=cls.user, calendar=cls.calendar) + RecurringRule.objects.create( + event=cls.past_event, + begin=cls.now - datetime.timedelta(days=2), + finish=cls.now - datetime.timedelta(days=1), + ) + def test_events_homepage(self): url = reverse('events:events') response = self.client.get(url) + events = response.context['object_list'] + event_titles = [event.title for event in events] + self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.context['object_list']), 1) + self.assertEqual(len(events), 6) + + self.assertIn('Future Event', event_titles) + self.assertIn('Current Event', event_titles) + self.assertIn('Past Event', event_titles) def test_calendar_list(self): calendars_count = Calendar.objects.count() @@ -54,7 +93,7 @@ def test_event_list(self): response = self.client.get(url) self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.context['object_list']), 1) + self.assertEqual(len(response.context['object_list']), 3) url = reverse('events:event_list_past', kwargs={"calendar_slug": 'unexisting'}) response = self.client.get(url) @@ -66,7 +105,7 @@ def test_event_list_past(self): response = self.client.get(url) self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.context['object_list']), 1) + self.assertEqual(len(response.context['object_list']), 4) def test_event_list_category(self): category = EventCategory.objects.create( @@ -114,7 +153,7 @@ def test_event_list_date(self): response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(response.context['object'], dt.date()) - self.assertEqual(len(response.context['object_list']), 2) + self.assertEqual(len(response.context['object_list']), 6) def test_eventlocation_list(self): venue = EventLocation.objects.create( @@ -150,12 +189,20 @@ def test_event_detail(self): self.assertEqual(self.event, response.context['object']) def test_upcoming_tag(self): - self.assertEqual(len(get_events_upcoming()), 1) - self.assertEqual(len(get_events_upcoming(only_featured=True)), 0) + self.assertEqual(len(get_events_upcoming()), 3) + self.assertEqual(len(get_events_upcoming(only_featured=True)), 1) self.rule.begin = self.now - datetime.timedelta(days=3) self.rule.finish = self.now - datetime.timedelta(days=2) self.rule.save() - self.assertEqual(len(get_events_upcoming()), 0) + self.assertEqual(len(get_events_upcoming()), 2) + + def test_context_data(self): + url = reverse("events:events") + response = self.client.get(url) + + self.assertIn("events_just_missed", response.context) + self.assertIn("upcoming_events", response.context) + self.assertIn("events_now", response.context) class EventSubmitTests(TestCase): diff --git a/events/views.py b/events/views.py index 2490626e3..56df88dcb 100644 --- a/events/views.py +++ b/events/views.py @@ -40,10 +40,21 @@ def get_context_data(self, **kwargs): class EventHomepage(ListView): """ Main Event Landing Page """ - template_name = 'events/event_list.html' + template_name = "events/event_list.html" - def get_queryset(self): - return Event.objects.for_datetime(timezone.now()).order_by('occurring_rule__dt_start') + def get_queryset(self) -> Event: + """Queryset to return all events, ordered by START date.""" + return Event.objects.all().order_by("-occurring_rule__dt_start") + + def get_context_data(self, **kwargs: dict) -> dict: + """Add more ctx, specifically events that are happening now, just missed, and upcoming.""" + context = super().get_context_data(**kwargs) + context["events_just_missed"] = Event.objects.until_datetime(timezone.now())[:2] + context["upcoming_events"] = Event.objects.for_datetime(timezone.now()) + context["events_now"] = Event.objects.filter( + occurring_rule__dt_start__lte=timezone.now(), + occurring_rule__dt_end__gte=timezone.now())[:2] + return context class EventDetail(DetailView): @@ -68,11 +79,13 @@ def get_context_data(self, **kwargs): class EventList(EventListBase): def get_queryset(self): - return Event.objects.for_datetime(timezone.now()).filter(calendar__slug=self.kwargs['calendar_slug']).order_by('occurring_rule__dt_start') + return Event.objects.for_datetime(timezone.now()).filter(calendar__slug=self.kwargs['calendar_slug']).order_by( + 'occurring_rule__dt_start') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['events_today'] = Event.objects.until_datetime(timezone.now()).filter(calendar__slug=self.kwargs['calendar_slug'])[:2] + context['events_today'] = Event.objects.until_datetime(timezone.now()).filter( + calendar__slug=self.kwargs['calendar_slug'])[:2] context['calendar'] = get_object_or_404(Calendar, slug=self.kwargs['calendar_slug']) return context diff --git a/templates/events/event_list.html b/templates/events/event_list.html index bbfb764d2..8d7b0d60f 100644 --- a/templates/events/event_list.html +++ b/templates/events/event_list.html @@ -8,73 +8,110 @@ {% block header_content %} {% if featured %} - <div class="featured-event"> + <div class="featured-event"> - <h2 class="welcome-message">Featured Python Event</h2> + <h2 class="welcome-message">Featured Python Event</h2> - <h1 class="call-to-action">{{ featured.title|striptags }}</h1> + <h1 class="call-to-action">{{ featured.title|striptags }}</h1> - <p class="event-date"><time datetime="{{ featured.next_datetime.dt_start|date:'c' }}"> - {{ featured.next_datetime.dt_start|date:"l, F d, Y" }} - </time></p> - <p class="excerpt">{{ featured.description.rendered|striptags|truncatewords:"60" }} <a class="readmore" href="{{ featured.get_absolute_url }}">Read more</a></p> - </div> + <p class="event-date"> + <time datetime="{{ featured.next_datetime.dt_start|date:'c' }}"> + {{ featured.next_datetime.dt_start|date:"l, F d, Y" }} + </time> + </p> + <p class="excerpt">{{ featured.description.rendered|striptags|truncatewords:"60" }} <a class="readmore" + href="{{ featured.get_absolute_url }}">Read + more</a></p> + </div> {% endif %} {% endblock header_content %} - -{# Based on python/events.html #} - {% block content %} - {% if calendar %} + {% if calendar %} <header class="article-header"> <h3>from the {{ calendar.name }}</h3> </header> - {% endif %} + {% endif %} - <div class="most-recent-events"> + <div class="most-recent-events"> + {% if events_now %} <div class="shrubbery"> - <h2 class="widget-title"><span aria-hidden="true" class="icon-calendar"></span>Upcoming Events</h2> - {% if page_obj.has_next %} - <p class="give-me-more"><a href="?page={{ page_obj.next_page_number }}" title="More Events">More</a></p> - {% endif %} + <h2 class="widget-title"><span aria-hidden="true" class="icon-alert"></span>Happening Now</h2> <ul class="list-recent-events menu"> - {% for object in object_list %} + {% for object in events_now %} + <li> + <h3 class="event-title"><a + href="{{ object.get_absolute_url }}">{{ object.title|striptags }}</a></h3> + <p> + {% with object.occurring_rule as next_time %} + {% include "events/includes/time_tag.html" %} + {% endwith %} + + {% if object.venue %} + <span class="event-location">{% if object.venue.url %} + <a href="{{ object.venue.url }}">{% endif %}{{ object.venue.name }} + {% if object.venue.url %}</a>{% endif %}{% if object.venue.address %}, + {{ object.venue.address }}{% endif %}</span> + {% endif %} + </p> + </li> + {% endfor %} + </ul> + </div> + {% endif %} + + <div class="shrubbery"> + <h2 class="widget-title"><span aria-hidden="true" class="icon-calendar"></span>Upcoming Events</h2> + {% if page_obj.has_next %} + <p class="give-me-more"><a href="?page={{ page_obj.next_page_number }}" title="More Events">More</a></p> + {% endif %} + <ul class="list-recent-events menu"> + {% for object in upcoming_events %} <li> - <h3 class="event-title"><a href="{{ object.get_absolute_url }}">{{ object.title|striptags }}</a></h3> + <h3 class="event-title"><a href="{{ object.get_absolute_url }}">{{ object.title|striptags }}</a> + </h3> <p> {% with object.next_time as next_time %} - {% include "events/includes/time_tag.html" %} + {% include "events/includes/time_tag.html" %} {% endwith %} {% if object.venue %} - <span class="event-location">{% if object.venue.url %}<a href="{{ object.venue.url }}">{% endif %}{{ object.venue.name }}{% if object.venue.url %}</a>{% endif %}{% if object.venue.address %}, {{ object.venue.address }}{% endif %}</span> + <span class="event-location">{% if object.venue.url %} + <a href="{{ object.venue.url }}">{% endif %}{{ object.venue.name }} + {% if object.venue.url %}</a>{% endif %}{% if object.venue.address %}, + {{ object.venue.address }}{% endif %}</span> {% endif %} </p> </li> {% endfor %} - </ul> - </div> - - {% if events_today %} - <h3 class="widget-title just-missed">You just missed...</h3> - <ul class="list-recent-events menu"> - {% for object in events_today %} - <li> - <h3 class="event-title"><a href="{{ object.get_absolute_url }}">{{ object.title|striptags }}</a></h3> - <p> - {% with object.previous_time as next_time %} - {% include "events/includes/time_tag.html" %} - {% endwith %} - - {% if object.venue %} - <span class="event-location">{% if object.venue.url %}<a href="{{ object.venue.url }}">{% endif %}{{ object.venue.name }}{% if object.venue.url %}</a>{% endif %}{% if object.venue.address %}, {{ object.venue.address }}{% endif %}</span> - {% endif %} - </p> - </li> - {% endfor %} </ul> - {% endif %} </div> + + {% if events_just_missed %} + <div class="shrubbery"> + <h3 class="widget-title just-missed">You just missed...</h3> + <ul class="list-recent-events menu"> + {% for object in events_just_missed %} + <li> + <h3 class="event-title"><a + href="{{ object.get_absolute_url }}">{{ object.title|striptags }}</a></h3> + <p> + {% with object.previous_time as next_time %} + {% include "events/includes/time_tag.html" %} + {% endwith %} + + {% if object.venue %} + <span class="event-location">{% if object.venue.url %} + <a href="{{ object.venue.url }}">{% endif %}{{ object.venue.name }} + {% if object.venue.url %}</a>{% endif %}{% if object.venue.address %}, + {{ object.venue.address }}{% endif %}</span> + {% endif %} + </p> + </li> + {% endfor %} + </ul> + </div> + {% endif %} + </div> {% endblock content %} From 5fdcbb2ec277c52109f184f09569958e2e33c91c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 21:28:19 +0000 Subject: [PATCH 125/235] Bump django-admin-interface from 0.24.2 to 0.28.9 (#2589) Bumps [django-admin-interface](https://github.com/fabiocaccamo/django-admin-interface) from 0.24.2 to 0.28.9. - [Release notes](https://github.com/fabiocaccamo/django-admin-interface/releases) - [Changelog](https://github.com/fabiocaccamo/django-admin-interface/blob/main/CHANGELOG.md) - [Commits](https://github.com/fabiocaccamo/django-admin-interface/compare/0.24.2...0.28.9) --- updated-dependencies: - dependency-name: django-admin-interface dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jacob Coffee <jacob@z7x.org> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index fc018561c..2b777de51 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -2,7 +2,7 @@ dj-database-url==0.5.0 django-pipeline==3.0.0 # 3.0.0 is first version that supports Django 4.2 django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4.2 django-apptemplates==1.5 -django-admin-interface==0.24.2 +django-admin-interface==0.28.9 django-translation-aliases==0.1.0 Django==4.2.16 docutils==0.21.2 From a13d00adabac7f817164455af11d26dbaffd5e7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:38:17 -0500 Subject: [PATCH 126/235] Bump django-pipeline from 3.0.0 to 3.1.0 (#2549) Bumps [django-pipeline](https://github.com/jazzband/django-pipeline) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/jazzband/django-pipeline/releases) - [Changelog](https://github.com/jazzband/django-pipeline/blob/master/HISTORY.rst) - [Commits](https://github.com/jazzband/django-pipeline/compare/3.0.0...3.1.0) --- updated-dependencies: - dependency-name: django-pipeline dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 2b777de51..fc681bce5 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -1,5 +1,5 @@ dj-database-url==0.5.0 -django-pipeline==3.0.0 # 3.0.0 is first version that supports Django 4.2 +django-pipeline==3.1.0 # 3.0.0 is first version that supports Django 4.2 django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4.2 django-apptemplates==1.5 django-admin-interface==0.28.9 From fa18e78c393babc44f911e6c67516f6011f6463e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:05:36 -0500 Subject: [PATCH 127/235] Bump factory-boy from 3.2.1 to 3.3.1 (#2548) Bumps [factory-boy](https://github.com/FactoryBoy/factory_boy) from 3.2.1 to 3.3.1. - [Changelog](https://github.com/FactoryBoy/factory_boy/blob/master/docs/changelog.rst) - [Commits](https://github.com/FactoryBoy/factory_boy/compare/3.2.1...3.3.1) --- updated-dependencies: - dependency-name: factory-boy dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index 8d61d0f9d..1ee11a333 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,7 +2,7 @@ # Required for running tests -factory-boy==3.2.1 +factory-boy==3.3.1 Faker==0.8.1 tblib==1.7.0 responses==0.13.3 From 3fa351b168942274c48158cb370e2371e843c1a8 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Fri, 20 Sep 2024 10:02:09 -0500 Subject: [PATCH 128/235] fix(frontend): add help text to story form (#2594) * fix(frontend): add help text to story form Closes #2364 * chore: source migration * fix: use meta class overrides instead * feat: linkify --- successstories/forms.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/successstories/forms.py b/successstories/forms.py index f623001b0..45ec1dfd3 100644 --- a/successstories/forms.py +++ b/successstories/forms.py @@ -24,6 +24,10 @@ class Meta: labels = { 'name': 'Story name', } + help_texts = { + "content": "Note: Submissions in <a href='https://www.markdownguide.org/basic-syntax/'>Markdown</a> " + "are strongly preferred and can be processed faster.", + } def clean_name(self): name = self.cleaned_data.get('name') From f2e763cc62cb894c26b4bc39b328ac70752db96b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:49:37 -0500 Subject: [PATCH 129/235] Bump python-decouple from 3.4 to 3.8 (#2596) Bumps [python-decouple](https://github.com/henriquebastos/python-decouple) from 3.4 to 3.8. - [Release notes](https://github.com/henriquebastos/python-decouple/releases) - [Changelog](https://github.com/HBNetwork/python-decouple/blob/master/CHANGELOG.md) - [Commits](https://github.com/henriquebastos/python-decouple/compare/v3.4...v3.8) --- updated-dependencies: - dependency-name: python-decouple dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jacob Coffee <jacob@z7x.org> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index fc681bce5..ed65c1acf 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -11,7 +11,7 @@ cmarkgfm==0.6.0 Pillow==10.4.0 psycopg2-binary==2.9.9 python3-openid==3.2.0 -python-decouple==3.4 +python-decouple==3.8 # lxml used by BeautifulSoup. lxml==5.2.2 cssselect==1.1.0 From ccbc9e42488f2bf6c12831c5e12d31f5eec4c2a7 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Mon, 23 Sep 2024 07:14:45 -0500 Subject: [PATCH 130/235] deps: no mo boto (#2598) --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 427010ca9..dbe4b843c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -16,6 +16,10 @@ updates: - 0.13.0 - 0.13.1 - 0.13.2 + - dependency-name: "boto3" + - dependency-name: "boto3-stubs" + - dependency-name: "botocore" + - dependency-name: "botocore-stubs" - dependency-name: lxml versions: - 4.6.2 From c8a87b747fb257fb16725c66641dcd694a116eac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:10:46 -0500 Subject: [PATCH 131/235] Bump django-tastypie from 0.14.6 to 0.14.7 (#2602) Bumps [django-tastypie](https://github.com/django-tastypie/django-tastypie) from 0.14.6 to 0.14.7. - [Release notes](https://github.com/django-tastypie/django-tastypie/releases) - [Commits](https://github.com/django-tastypie/django-tastypie/compare/v0.14.6...v0.14.7) --- updated-dependencies: - dependency-name: django-tastypie dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index ed65c1acf..d3400104f 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -26,7 +26,7 @@ django-imagekit==5.0 # 5.0 is first version that supports Django 4.2 django-haystack==3.2.1 elasticsearch>=7,<8 # TODO: 0.14.0 only supports Django 1.8 and 1.11. -django-tastypie==0.14.6 # 0.14.6 is first version that supports Django 4.2 +django-tastypie==0.14.7 # 0.14.6 is first version that supports Django 4.2 pytz==2021.1 python-dateutil==2.8.2 From a84a53a7fee93bd74f9db51179935c1d3e59103c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:20:01 -0500 Subject: [PATCH 132/235] Bump cssselect from 1.1.0 to 1.2.0 (#2606) Bumps [cssselect](https://github.com/scrapy/cssselect) from 1.1.0 to 1.2.0. - [Changelog](https://github.com/scrapy/cssselect/blob/master/CHANGES) - [Commits](https://github.com/scrapy/cssselect/compare/v1.1.0...v1.2.0) --- updated-dependencies: - dependency-name: cssselect dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index d3400104f..4877f78c3 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -14,7 +14,7 @@ python3-openid==3.2.0 python-decouple==3.8 # lxml used by BeautifulSoup. lxml==5.2.2 -cssselect==1.1.0 +cssselect==1.2.0 feedparser==6.0.11 beautifulsoup4==4.12.3 icalendar==4.0.7 From 70a7ef6b363f7621082d03901fc16951561a07f2 Mon Sep 17 00:00:00 2001 From: Mike Fiedler <miketheman@gmail.com> Date: Tue, 24 Sep 2024 10:32:57 -0400 Subject: [PATCH 133/235] chores & docs: clean up some inaccuracies in getting started (#2600) * chore: remove obsolete version entry from compose Currently raises a warning: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion Signed-off-by: Mike Fiedler <miketheman@gmail.com> * docs: staging site does not exist Signed-off-by: Mike Fiedler <miketheman@gmail.com> * docs: format the link to be clickable Signed-off-by: Mike Fiedler <miketheman@gmail.com> * docs: use what's currently in docker-compose.yml Signed-off-by: Mike Fiedler <miketheman@gmail.com> * docs: remove version specificity Signed-off-by: Mike Fiedler <miketheman@gmail.com> --------- Signed-off-by: Mike Fiedler <miketheman@gmail.com> --- docker-compose.yml | 2 -- docs/source/index.rst | 1 - docs/source/install.md | 6 +++--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4406c0ff5..1f5ea36b4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.9" - services: postgres: image: postgres:15.3-bullseye diff --git a/docs/source/index.rst b/docs/source/index.rst index 76a201828..cfde87586 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,7 +10,6 @@ General information :Issue tracker: https://github.com/python/pythondotorg/issues :Mailing list: pydotorg-www_ :IRC: ``#pydotorg`` on Freenode -:Staging site: https://staging.python.org/ (``main`` branch) :Production configuration: https://github.com/python/psf-salt :GitHub Actions: .. image:: https://github.com/python/pythondotorg/actions/workflows/ci.yml/badge.svg diff --git a/docs/source/install.md b/docs/source/install.md index d6c29d295..c91d1bd59 100644 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -55,7 +55,7 @@ web_1 | Starting development server at http://0.0.0.0:8000/ web_1 | Quit the server with CONTROL-C. ``` -You can view these results in your local web browser at: `http://localhost:8000` +You can view these results in your local web browser at: <http://localhost:8000> To reset your local environment, run: @@ -88,7 +88,7 @@ This is a simple wrapper around running `python manage.py` in the container, all Manual setup ------------ -First, install [PostgreSQL](https://www.postgresql.org/download/) on your machine and run it. *pythondotorg* currently uses Postgres 10.21. +First, install [PostgreSQL](https://www.postgresql.org/download/) on your machine and run it. *pythondotorg* currently uses Postgres 15.x. Then clone the repository: @@ -99,7 +99,7 @@ $ git clone git://github.com/python/pythondotorg.git Then create a virtual environment: ``` -$ python3.9 -m venv venv +$ python3 -m venv venv ``` And then you'll need to install dependencies. You don't need to use `pip3` inside a Python 3 virtual environment: From c33a664718193fb8216bbfe121f038c6acb011af Mon Sep 17 00:00:00 2001 From: Nwokolo Godwin Chidera <nwokolo.godwin.chidera@gmail.com> Date: Thu, 26 Sep 2024 22:55:03 +0100 Subject: [PATCH 134/235] fix(#1701): Events page displays year for events scheduled to start or end at a future year (#2500) * Add Methods To Check If Event Starts And Ends This Year * Set Up Templates For Querying Start And End Years Passed variables to the time_tag template [time_tag.html] that checks if an event was scheduled to start or end with the current year. * Insert New Test Data And Update test_views.py More events are created to test particular scenarios of events especially events set to start or end at a future year. * Time Tag Now Shows Year For Events With Details Not Within The Current Year The time tag now displays the year when an event will occur. This is only for events that have been scheduled to start or end in at a future year. The accompanying functional tests have also been included. * Move All Test Data To Functional Test All test data concerning the provision of data to serve the functional tests have been moved to the functional test. As it improves readability. All other test data at test_views.py was reset to accommodate for the reduction in number of test data instances. * Functional Test For Displaying Year Of Event For Future Events Now Implemented With Unit Tests * Remove Functional Test For Displaying Year Of Future Event Since the current CI at the main branch does not support selenium [web driver] operations, the functional test which depends on selenium to run has been removed. * Handle Case When Call To Next Event Returns None * Fix Erroneous Addition To Dev Requirements This error was introduced in 115af08e7ce529e2e9298d93a98aacf77bb007af * Refactor Tests For Relevant Year String Rendering At Events Page - Updated the test methods `test_scheduled_to_start_this_year_method` and `test_scheduled_to_end_this_year_method` to better reflect event scheduling edge cases. - Added assertions to verify when events are not scheduled to start or end within the current year. - Utilize `unittest.mock` to clamp down datetime-sensitive tests. --------- Co-authored-by: Jacob Coffee <jacob@z7x.org> --- events/models.py | 14 ++++++ events/tests/test_models.py | 61 ++++++++++++++++++++++++- events/tests/test_views.py | 60 +++++++++++++++++++++--- templates/events/event_list.html | 12 ++++- templates/events/includes/time_tag.html | 31 ++++++++++++- 5 files changed, 167 insertions(+), 11 deletions(-) diff --git a/events/models.py b/events/models.py index 1f2ab2cb0..017b919f3 100644 --- a/events/models.py +++ b/events/models.py @@ -181,6 +181,20 @@ def next_time(self): except IndexError: return None + def is_scheduled_to_start_this_year(self) -> bool: + if self.next_time: + current_year: int = timezone.now().year + if self.next_time.dt_start.year == current_year: + return True + return False + + def is_scheduled_to_end_this_year(self) -> bool: + if self.next_time: + current_year: int = timezone.now().year + if self.next_time.dt_end.year == current_year: + return True + return False + @property def previous_time(self): now = timezone.now() diff --git a/events/tests/test_models.py b/events/tests/test_models.py index 0f3bafe76..3d0938280 100644 --- a/events/tests/test_models.py +++ b/events/tests/test_models.py @@ -1,4 +1,6 @@ import datetime +from types import SimpleNamespace +from unittest.mock import patch from django.contrib.auth import get_user_model from django.test import TestCase @@ -62,7 +64,6 @@ def test_recurring_event(self): self.assertEqual(self.event.next_time.dt_start, recurring_time_dtstart) self.assertTrue(rt.valid_dt_end()) - rt.begin = now - datetime.timedelta(days=5) rt.finish = now - datetime.timedelta(days=3) rt.save() @@ -186,3 +187,61 @@ def test_event_previous_event(self): # 'Event.previous_event' can return None if there is no # OccurringRule or RecurringRule found. self.assertIsNone(self.event.previous_event) + + def test_scheduled_to_start_this_year_method(self): + test_datetime = SimpleNamespace( + now=lambda: timezone.datetime(timezone.now().year, + 6, 1, tzinfo=timezone.now().tzinfo) + ) + + with patch("django.utils.timezone", new=test_datetime) as mock_timezone: + with patch("events.models.timezone", new=test_datetime): + now = seconds_resolution(mock_timezone.now()) + + occurring_time_dtstart = now + datetime.timedelta(days=1) + OccurringRule.objects.create( + event=self.event, + dt_start=occurring_time_dtstart, + dt_end=occurring_time_dtstart + datetime.timedelta(days=3) + ) + self.assertTrue(self.event.is_scheduled_to_start_this_year()) + + OccurringRule.objects.get(event=self.event).delete() + + event_not_scheduled_to_start_this_year_occurring_time_dtstart = now + datetime.timedelta(days=365) + OccurringRule.objects.create( + event=self.event, + dt_start=event_not_scheduled_to_start_this_year_occurring_time_dtstart, + dt_end=event_not_scheduled_to_start_this_year_occurring_time_dtstart + datetime.timedelta(days=3) + ) + + self.assertFalse(self.event.is_scheduled_to_start_this_year()) + + def test_scheduled_to_end_this_year_method(self): + test_datetime = SimpleNamespace( + now=lambda: timezone.datetime(timezone.now().year, + 6, 1, tzinfo=timezone.now().tzinfo) + ) + + with patch("django.utils.timezone", new=test_datetime) as mock_timezone: + with patch("events.models.timezone", new=test_datetime): + now = seconds_resolution(mock_timezone.now()) + occurring_time_dtstart = now + datetime.timedelta(days=1) + + OccurringRule.objects.create( + event=self.event, + dt_start=occurring_time_dtstart, + dt_end=occurring_time_dtstart + ) + + self.assertTrue(self.event.is_scheduled_to_end_this_year()) + + OccurringRule.objects.get(event=self.event).delete() + + OccurringRule.objects.create( + event=self.event, + dt_start=now, + dt_end=now + datetime.timedelta(days=365) + ) + + self.assertFalse(self.event.is_scheduled_to_end_this_year()) diff --git a/events/tests/test_views.py b/events/tests/test_views.py index 1291252a5..34ca27831 100644 --- a/events/tests/test_views.py +++ b/events/tests/test_views.py @@ -6,7 +6,7 @@ from django.test import TestCase from django.utils import timezone -from ..models import Calendar, Event, EventCategory, EventLocation, RecurringRule +from ..models import Calendar, Event, EventCategory, EventLocation, RecurringRule, OccurringRule from ..templatetags.events import get_events_upcoming from users.factories import UserFactory @@ -18,6 +18,11 @@ def setUpTestData(cls): cls.calendar = Calendar.objects.create(creator=cls.user, slug="test-calendar") cls.event = Event.objects.create(creator=cls.user, calendar=cls.calendar) cls.event_past = Event.objects.create(title='Past Event', creator=cls.user, calendar=cls.calendar) + cls.event_single_day = Event.objects.create(title="Single Day Event", creator=cls.user, calendar=cls.calendar) + cls.event_starts_at_future_year = Event.objects.create(title='Event Starting Following Year', + creator=cls.user, calendar=cls.calendar) + cls.event_ends_at_future_year = Event.objects.create(title='Event Ending Following Year', + creator=cls.user, calendar=cls.calendar) cls.now = timezone.now() @@ -34,7 +39,6 @@ def setUpTestData(cls): begin=cls.now - datetime.timedelta(days=2), finish=cls.now - datetime.timedelta(days=1), ) - # Future event cls.future_event = Event.objects.create(title='Future Event', creator=cls.user, calendar=cls.calendar, featured=True) RecurringRule.objects.create( @@ -67,6 +71,22 @@ def setUpTestData(cls): finish=cls.now - datetime.timedelta(days=1), ) + cls.rule_single_day = OccurringRule.objects.create( + event=cls.event_single_day, + dt_start=recurring_time_dtstart, + dt_end=recurring_time_dtstart + ) + cls.rule_future_start_year = OccurringRule.objects.create( + event=cls.event_starts_at_future_year, + dt_start=recurring_time_dtstart + datetime.timedelta(weeks=52), + dt_end=recurring_time_dtstart + datetime.timedelta(weeks=53), + ) + cls.rule_future_end_year = OccurringRule.objects.create( + event=cls.event_ends_at_future_year, + dt_start=recurring_time_dtstart, + dt_end=recurring_time_dtend + datetime.timedelta(weeks=52) + ) + def test_events_homepage(self): url = reverse('events:events') response = self.client.get(url) @@ -74,11 +94,13 @@ def test_events_homepage(self): event_titles = [event.title for event in events] self.assertEqual(response.status_code, 200) - self.assertEqual(len(events), 6) + self.assertEqual(len(events), 9) self.assertIn('Future Event', event_titles) self.assertIn('Current Event', event_titles) self.assertIn('Past Event', event_titles) + self.assertIn('Event Starting Following Year', event_titles) + self.assertIn('Event Ending Following Year', event_titles) def test_calendar_list(self): calendars_count = Calendar.objects.count() @@ -93,7 +115,7 @@ def test_event_list(self): response = self.client.get(url) self.assertEqual(response.status_code, 200) - self.assertEqual(len(response.context['object_list']), 3) + self.assertEqual(len(response.context['object_list']), 6) url = reverse('events:event_list_past', kwargs={"calendar_slug": 'unexisting'}) response = self.client.get(url) @@ -189,12 +211,21 @@ def test_event_detail(self): self.assertEqual(self.event, response.context['object']) def test_upcoming_tag(self): - self.assertEqual(len(get_events_upcoming()), 3) + self.assertEqual(len(get_events_upcoming()), 5) self.assertEqual(len(get_events_upcoming(only_featured=True)), 1) self.rule.begin = self.now - datetime.timedelta(days=3) self.rule.finish = self.now - datetime.timedelta(days=2) self.rule.save() - self.assertEqual(len(get_events_upcoming()), 2) + self.assertEqual(len(get_events_upcoming()), 5) + + def test_event_starting_future_year_displays_relevant_year(self): + event = self.event_starts_at_future_year + url = reverse('events:events') + response = self.client.get(url) + self.assertIn( + f'<span id="start-{event.id}">', + response.content.decode() + ) def test_context_data(self): url = reverse("events:events") @@ -204,6 +235,23 @@ def test_context_data(self): self.assertIn("upcoming_events", response.context) self.assertIn("events_now", response.context) + def test_event_ending_future_year_displays_relevant_year(self): + event = self.event_ends_at_future_year + url = reverse('events:events') + response = self.client.get(url) + self.assertIn( + f'<span id="end-{event.id}">', + response.content.decode() + ) + + def test_events_scheduled_current_year_does_not_display_current_year(self): + event = self.event_single_day + url = reverse('events:events') + response = self.client.get(url) + self.assertIn( # start date + f'<span id="start-{event.id}" class="say-no-more">', + response.content.decode() + ) class EventSubmitTests(TestCase): event_submit_url = reverse_lazy('events:event_submit') diff --git a/templates/events/event_list.html b/templates/events/event_list.html index 8d7b0d60f..c4d14321e 100644 --- a/templates/events/event_list.html +++ b/templates/events/event_list.html @@ -73,7 +73,11 @@ <h3 class="event-title"><a href="{{ object.get_absolute_url }}">{{ object.title| </h3> <p> {% with object.next_time as next_time %} - {% include "events/includes/time_tag.html" %} + {% with object.is_scheduled_to_start_this_year as scheduled_start_this_year %} + {% with object.is_scheduled_to_end_this_year as scheduled_end_this_year %} + {% include "events/includes/time_tag.html" %} + {% endwith %} + {% endwith %} {% endwith %} {% if object.venue %} @@ -98,7 +102,11 @@ <h3 class="event-title"><a href="{{ object.get_absolute_url }}">{{ object.title|striptags }}</a></h3> <p> {% with object.previous_time as next_time %} - {% include "events/includes/time_tag.html" %} + {% with object.is_scheduled_to_start_this_year as scheduled_start_this_year %} + {% with object.is_scheduled_to_end_this_year as scheduled_end_this_year %} + {% include "events/includes/time_tag.html" %} + {% endwith %} + {% endwith %} {% endwith %} {% if object.venue %} diff --git a/templates/events/includes/time_tag.html b/templates/events/includes/time_tag.html index 078fcf1dc..90bc4491b 100644 --- a/templates/events/includes/time_tag.html +++ b/templates/events/includes/time_tag.html @@ -1,5 +1,32 @@ {% if next_time.single_day %} -<time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }}<span class="say-no-more"> {{ next_time.dt_start|date:"Y" }}</span>{% if not next_time.all_day %} {{ next_time.dt_start|date:"fA"|lower }} {{ next_time.dt_start|date:"e" }}{% if next_time.valid_dt_end %} – {{ next_time.dt_end|date:"fA"|lower }} {{ next_time.dt_end|date:"e" }}{% endif %}{% endif %}</time> + <time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }} + <span id="start-{{ object.id }}"{% if scheduled_start_this_year %} class="say-no-more"{% endif %}> + {{ next_time.dt_start|date:"Y" }} + </span> + + <span id="start-{{ object.id }}"{% if scheduled_end_this_year %} class="say-no-more"{% endif %}> + {{ next_time.dt_start|date:"Y" }} + </span> + + {% if not next_time.all_day %} + {{ next_time.dt_start|date:"fA"|lower }} {{ next_time.dt_start|date:"e" }} + {% if next_time.valid_dt_end %} – {{ next_time.dt_end|date:"fA"|lower }} + {{ next_time.dt_end|date:"e" }} + {% endif %} + {% endif %} + </time> {% else %} -<time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }}{% if next_time.valid_dt_end %} – {{ next_time.dt_end|date:"d N" }}{% endif %} <span class="say-no-more"> {{ next_time.dt_end|date:"Y" }}</span></time> + <time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }} + <span id="start-{{ object.id }}"{% if scheduled_start_this_year %} class="say-no-more"{% endif %}> + {{ next_time.dt_start|date:"Y" }} + </span> + + {% if next_time.valid_dt_end %} – + {{ next_time.dt_end|date:"d N" }} + {% endif %} + + <span id="end-{{ object.id }}"{% if scheduled_end_this_year %} class="say-no-more"{% endif %}> + {{ next_time.dt_end|date:"Y" }} + </span> + </time> {% endif %} \ No newline at end of file From 9e4d888b4dc58cf9e4f35ea33c4f50c7ba9e91c6 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Fri, 27 Sep 2024 09:28:38 -0500 Subject: [PATCH 135/235] infra: enable the waf (#2613) --- infra/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/main.tf b/infra/main.tf index 90c2ba9c5..d5865970f 100644 --- a/infra/main.tf +++ b/infra/main.tf @@ -16,7 +16,7 @@ module "fastly_production" { ngwaf_site_name = "prod" ngwaf_email = "infrastructure-staff@python.org" ngwaf_token = var.ngwaf_token - activate_ngwaf_service = false + activate_ngwaf_service = true } module "fastly_staging" { From 2ad65677a9bb6c87f049a7541014175e2851adca Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Fri, 27 Sep 2024 09:42:11 -0500 Subject: [PATCH 136/235] fix(infra): use new site names (#2614) --- infra/cdn/variables.tf | 4 ++-- infra/main.tf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/infra/cdn/variables.tf b/infra/cdn/variables.tf index ec0a11a83..969d51e77 100644 --- a/infra/cdn/variables.tf +++ b/infra/cdn/variables.tf @@ -62,8 +62,8 @@ variable "ngwaf_site_name" { description = "Site SHORT name for NGWAF" validation { - condition = can(regex("^(test|stage|prod)$", var.ngwaf_site_name)) - error_message = "'ngwaf_site_name' must be one of the following: test, stage, or prod" + condition = can(regex("^(pythondotorg-test|pythondotorg-prod)$", var.ngwaf_site_name)) + error_message = "'ngwaf_site_name' must be one of the following: pythondotorg-test, or pythondotorg-prod" } } variable "ngwaf_email" { diff --git a/infra/main.tf b/infra/main.tf index d5865970f..58159f6cf 100644 --- a/infra/main.tf +++ b/infra/main.tf @@ -13,7 +13,7 @@ module "fastly_production" { fastly_header_token = var.FASTLY_HEADER_TOKEN s3_logging_keys = var.fastly_s3_logging - ngwaf_site_name = "prod" + ngwaf_site_name = "pythondotorg-prod" ngwaf_email = "infrastructure-staff@python.org" ngwaf_token = var.ngwaf_token activate_ngwaf_service = true @@ -35,7 +35,7 @@ module "fastly_staging" { fastly_header_token = var.FASTLY_HEADER_TOKEN s3_logging_keys = var.fastly_s3_logging - ngwaf_site_name = "test" + ngwaf_site_name = "pythondotorg-test" ngwaf_email = "infrastructure-staff@python.org" ngwaf_token = var.ngwaf_token activate_ngwaf_service = true From 89ae28c589583b48a7b2f227721aec6cbe7ca942 Mon Sep 17 00:00:00 2001 From: Mike Fiedler <miketheman@gmail.com> Date: Fri, 27 Sep 2024 11:11:57 -0400 Subject: [PATCH 137/235] chore: avoid running Actions twice on PR (#2615) * chore: avoid running Actions twice on PR Refs: https://github.com/orgs/community/discussions/57827#discussioncomment-6579237 * chore: run once --- .github/workflows/ci.yml | 2 ++ .github/workflows/static.yml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed08f4b7f..4328adf50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,8 @@ name: CI on: [push, pull_request] jobs: test: + # Avoid running CI more than once on pushes to main repo open PRs + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: ubuntu-latest services: postgres: diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 3207b964e..d29c620ee 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -1,7 +1,9 @@ name: Check collectstatic on: [push, pull_request] jobs: - test: + collectstatic: + # Avoid running CI more than once on pushes to main repo open PRs + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: ubuntu-latest steps: - name: Check out repository From a9fab67cb08fde08a160ed8f164beaa5d0d8b12c Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Mon, 30 Sep 2024 14:17:37 -0400 Subject: [PATCH 138/235] add a static container for handling local frontend dev (#2619) * add a static container for handling local frontend dev * resulting css files --- Dockerfile.static | 10 + Gemfile | 6 +- Gemfile.lock | 19 +- bin/static | 3 + docker-compose.yml | 7 + static/sass/mq.css | 362 +++++++++++----------- static/sass/no-mq.css | 323 +++++++++----------- static/sass/style.css | 677 ++++++++++++++++++++---------------------- 8 files changed, 679 insertions(+), 728 deletions(-) create mode 100644 Dockerfile.static create mode 100755 bin/static diff --git a/Dockerfile.static b/Dockerfile.static new file mode 100644 index 000000000..94d806cb8 --- /dev/null +++ b/Dockerfile.static @@ -0,0 +1,10 @@ +FROM ruby:2.7.8-bullseye AS static + +RUN mkdir /code +WORKDIR /code + +COPY Gemfile Gemfile.lock /code/ + +RUN bundle install + +COPY . /code diff --git a/Gemfile b/Gemfile index 1b175cfc6..c96d2b85e 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,9 @@ source "https://rubygems.org" group :media do - gem "compass", "~>0.12.2" - gem "sass", "~>3.2.5" - gem "susy", "~>1.0.5" + gem "compass", "~>0.12.7" + gem "sass", "~>3.2.19" + gem "susy", "~>1.0.9" end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index a7bcf92d3..040bac565 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,16 +1,16 @@ GEM remote: https://rubygems.org/ specs: - chunky_png (1.2.7) - compass (0.12.2) + chunky_png (1.4.0) + compass (0.12.7) chunky_png (~> 1.2) fssm (>= 0.2.7) - sass (~> 3.1) + sass (~> 3.2.19) foreman (0.61.0) thor (>= 0.13.6) fssm (0.2.10) - sass (3.2.6) - susy (1.0.5) + sass (3.2.19) + susy (1.0.9) compass (>= 0.12.2) sass (>= 3.2.0) thor (0.17.0) @@ -19,7 +19,10 @@ PLATFORMS ruby DEPENDENCIES - compass (~> 0.12.2) + compass (~> 0.12.7) foreman (~> 0.61.0) - sass (~> 3.2.5) - susy (~> 1.0.5) + sass (~> 3.2.19) + susy (~> 1.0.9) + +BUNDLED WITH + 2.1.4 diff --git a/bin/static b/bin/static new file mode 100755 index 000000000..0aea623f8 --- /dev/null +++ b/bin/static @@ -0,0 +1,3 @@ +#!/bin/bash +cd static +bundle exec sass --compass --scss -I $(dirname $(dirname $(gem which susy))) --trace --watch sass:sass diff --git a/docker-compose.yml b/docker-compose.yml index 1f5ea36b4..0d5bd0bfd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,6 +20,13 @@ services: test: ["CMD", "redis-cli","ping"] interval: 1s + static: + command: bin/static + build: + dockerfile: Dockerfile.static + volumes: + - .:/code + web: build: . image: pythondotorg:docker-compose diff --git a/static/sass/mq.css b/static/sass/mq.css index d08ec4338..38c68317a 100644 --- a/static/sass/mq.css +++ b/static/sass/mq.css @@ -177,7 +177,7 @@ .slides, .flex-control-nav, .flex-direction-nav {margin: 0; padding: 0; list-style: none;} */ -/* FlexSlider Necessary Styles + /* FlexSlider Necessary Styles .flexslider {margin: 0; padding: 0;} .flexslider .slides > li {display: none; -webkit-backface-visibility: hidden;} /* Hide the slides before the JS is loaded. Avoids image jumping .flexslider .slides img {width: 100%; display: block;} @@ -554,20 +554,20 @@ html[xmlns] .slides { display: block; } .no-touch .main-navigation .subnav { min-width: 100%; display: none; + -webkit-transition: all 0s ease; -moz-transition: all 0s ease; -o-transition: all 0s ease; - -webkit-transition: all 0s ease; transition: all 0s ease; } .touch .main-navigation .subnav { top: 120%; display: none; opacity: 0; + -webkit-transition: opacity 0.25s ease-in-out; -moz-transition: opacity 0.25s ease-in-out; -o-transition: opacity 0.25s ease-in-out; - -webkit-transition: opacity 0.25s ease-in-out; transition: opacity 0.25s ease-in-out; - -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); } .touch .main-navigation .subnav:before { position: absolute; @@ -582,16 +582,16 @@ html[xmlns] .slides { display: block; } .no-touch .main-navigation .element-1:hover .subnav, .no-touch .main-navigation .element-1:focus .subnav, .no-touch .main-navigation .element-2:hover .subnav, .no-touch .main-navigation .element-2:focus .subnav, .no-touch .main-navigation .element-3:hover .subnav, .no-touch .main-navigation .element-3:focus .subnav, .no-touch .main-navigation .element-4:hover .subnav, .no-touch .main-navigation .element-4:focus .subnav { left: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .no-touch .main-navigation .element-5:hover .subnav, .no-touch .main-navigation .element-5:focus .subnav, .no-touch .main-navigation .element-6:hover .subnav, .no-touch .main-navigation .element-6:focus .subnav, .no-touch .main-navigation .element-7:hover .subnav, .no-touch .main-navigation .element-7:focus .subnav, .no-touch .main-navigation .element-8:hover .subnav, .no-touch .main-navigation .element-8:focus .subnav, .no-touch .main-navigation .last:hover .subnav, .no-touch .main-navigation .last:focus .subnav { right: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .touch .main-navigation .element-1, .touch .main-navigation .element-2, .touch .main-navigation .element-3, .touch .main-navigation .element-4 { /* Position the pointer element */ } @@ -620,11 +620,13 @@ html[xmlns] .slides { display: block; } display: block; clear: both; text-align: center; + -webkit-border-radius: 8px 8px 0 0; -moz-border-radius: 8px 8px 0 0; - -webkit-border-radius: 8px; + -ms-border-radius: 8px 8px 0 0; + -o-border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0; - -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } .no-touch .main-navigation .tier-1 { float: left; @@ -657,8 +659,8 @@ html[xmlns] .slides { display: block; } .no-touch .main-navigation .tier-2 > a { border-right: 1px solid rgba(255, 255, 255, 0.8); } .no-touch .main-navigation .subnav { - -moz-box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); } /* Shorten the amount of blue space under the nav on inner pages */ @@ -717,25 +719,27 @@ html[xmlns] .slides { display: block; } display: block; opacity: 1; border-top: 0; - -moz-box-shadow: none; -webkit-box-shadow: none; + -moz-box-shadow: none; box-shadow: none; } /* TO DO: With Javascript, look for a left-right swipe action and also trigger the menu to open */ .touch #touchnav-wrapper { + -webkit-transition: -webkit-transform 300ms ease; -moz-transition: -moz-transform 300ms ease; -o-transition: -o-transform 300ms ease; - -webkit-transition: -webkit-transform 300ms ease; transition: transform 300ms ease; + -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); - -webkit-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); -webkit-backface-visibility: hidden; } .touch .show-sidemenu #touchnav-wrapper { + -webkit-transform: translate3d(260px, 0, 0); -moz-transform: translate3d(260px, 0, 0); -ms-transform: translate3d(260px, 0, 0); - -webkit-transform: translate3d(260px, 0, 0); + -o-transform: translate3d(260px, 0, 0); transform: translate3d(260px, 0, 0); } /* Simple Column Structure */ @@ -784,9 +788,9 @@ html[xmlns] .slides { display: block; } border-color: transparent; } .search-field { + -webkit-transition: width 0.3s ease-in-out; -moz-transition: width 0.3s ease-in-out; -o-transition: width 0.3s ease-in-out; - -webkit-transition: width 0.3s ease-in-out; transition: width 0.3s ease-in-out; } .search-field:focus { @@ -841,11 +845,10 @@ html[xmlns] .slides { display: block; } background-color: #2d618c; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF3776AB', endColorstr='#FF2D618C'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiMzNzc2YWIiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #3776ab), color-stop(95%, #2d618c)); - background-image: -moz-linear-gradient(#3776ab 30%, #2d618c 95%); background-image: -webkit-linear-gradient(#3776ab 30%, #2d618c 95%); + background-image: -moz-linear-gradient(#3776ab 30%, #2d618c 95%); + background-image: -o-linear-gradient(#3776ab 30%, #2d618c 95%); background-image: linear-gradient(#3776ab 30%, #2d618c 95%); border-top: 1px solid #629ccd; border-bottom: 1px solid #18334b; @@ -862,15 +865,14 @@ html[xmlns] .slides { display: block; } border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .python-navigation .tier-1 > a:hover, .python-navigation .tier-1 > a:focus, .python-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #2d618c; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF326B9C', endColorstr='#FF2D618C'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMjZiOWMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #326b9c), color-stop(90%, #2d618c)); - background-image: -moz-linear-gradient(#326b9c 10%, #2d618c 90%); background-image: -webkit-linear-gradient(#326b9c 10%, #2d618c 90%); + background-image: -moz-linear-gradient(#326b9c 10%, #2d618c 90%); + background-image: -o-linear-gradient(#326b9c 10%, #2d618c 90%); background-image: linear-gradient(#326b9c 10%, #2d618c 90%); border-top: 1px solid #3776ab; border-bottom: 1px solid #2d618c; } @@ -879,14 +881,13 @@ html[xmlns] .slides { display: block; } background-color: #d6e5f2; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFBBD4E9', endColorstr='#FFD6E5F2'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNiYmQ0ZTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #bbd4e9), color-stop(90%, #d6e5f2)); - background-image: -moz-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); background-image: -webkit-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); + background-image: -moz-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); + background-image: -o-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); background-image: linear-gradient(#bbd4e9 10%, #d6e5f2 90%); - -moz-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); /*modernizr*/ } .touch .python-navigation .subnav:before { @@ -901,27 +902,25 @@ html[xmlns] .slides { display: block; } .python-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(55, 118, 171, 0.25); } .python-navigation .current_item { - color: #fff; + color: white; background-color: #244e71; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF2B5B84', endColorstr='#FF244E71'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyYjViODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzI0NGU3MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #2b5b84), color-stop(90%, #244e71)); - background-image: -moz-linear-gradient(#2b5b84 10%, #244e71 90%); background-image: -webkit-linear-gradient(#2b5b84 10%, #244e71 90%); + background-image: -moz-linear-gradient(#2b5b84 10%, #244e71 90%); + background-image: -o-linear-gradient(#2b5b84 10%, #244e71 90%); background-image: linear-gradient(#2b5b84 10%, #244e71 90%); } .python-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #89b4d9; background-color: #d6e5f2; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFCFDFE', endColorstr='#FFD6E5F2'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmY2ZkZmUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #fcfdfe), color-stop(90%, #d6e5f2)); - background-image: -moz-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); background-image: -webkit-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); + background-image: -moz-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); + background-image: -o-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); background-image: linear-gradient(#fcfdfe 10%, #d6e5f2 90%); } .python-navigation .super-navigation a:not(.button) { color: #3776ab; } @@ -932,18 +931,17 @@ html[xmlns] .slides { display: block; } background-color: #646565; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF78797A', endColorstr='#FF646565'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM3ODc5N2EiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #78797a), color-stop(95%, #646565)); - background-image: -moz-linear-gradient(#78797a 30%, #646565 95%); background-image: -webkit-linear-gradient(#78797a 30%, #646565 95%); + background-image: -moz-linear-gradient(#78797a 30%, #646565 95%); + background-image: -o-linear-gradient(#78797a 30%, #646565 95%); background-image: linear-gradient(#78797a 30%, #646565 95%); border-top: 1px solid #9e9fa0; border-bottom: 1px solid #39393a; /*a*/ } .psf-navigation .tier-1 { border-top: 1px solid #929393; - border-right: 1px solid #5f6060; + border-right: 1px solid #5f5f60; border-bottom: 1px solid #454647; border-left: 1px solid #929393; } .psf-navigation .tier-1 > a { @@ -953,15 +951,14 @@ html[xmlns] .slides { display: block; } border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .psf-navigation .tier-1 > a:hover, .psf-navigation .tier-1 > a:focus, .psf-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #646565; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF6E6F70', endColorstr='#FF646565'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2ZTZmNzAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #6e6f70), color-stop(90%, #646565)); - background-image: -moz-linear-gradient(#6e6f70 10%, #646565 90%); background-image: -webkit-linear-gradient(#6e6f70 10%, #646565 90%); + background-image: -moz-linear-gradient(#6e6f70 10%, #646565 90%); + background-image: -o-linear-gradient(#6e6f70 10%, #646565 90%); background-image: linear-gradient(#6e6f70 10%, #646565 90%); border-top: 1px solid #78797a; border-bottom: 1px solid #646565; } @@ -970,14 +967,13 @@ html[xmlns] .slides { display: block; } background-color: #ececec; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFDADADA', endColorstr='#FFECECEC'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkYWRhZGEiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #dadada), color-stop(90%, #ececec)); - background-image: -moz-linear-gradient(#dadada 10%, #ececec 90%); background-image: -webkit-linear-gradient(#dadada 10%, #ececec 90%); + background-image: -moz-linear-gradient(#dadada 10%, #ececec 90%); + background-image: -o-linear-gradient(#dadada 10%, #ececec 90%); background-image: linear-gradient(#dadada 10%, #ececec 90%); - -moz-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); /*modernizr*/ } .touch .psf-navigation .subnav:before { @@ -992,27 +988,25 @@ html[xmlns] .slides { display: block; } .psf-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(120, 121, 122, 0.25); } .psf-navigation .current_item { - color: #fff; + color: white; background-color: #525353; *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF5F6060', endColorstr='#FF525353'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM1ZjYwNjAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzUyNTM1MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #5f6060), color-stop(90%, #525353)); - background-image: -moz-linear-gradient(#5f6060 10%, #525353 90%); - background-image: -webkit-linear-gradient(#5f6060 10%, #525353 90%); - background-image: linear-gradient(#5f6060 10%, #525353 90%); } + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF5F5F60', endColorstr='#FF525353'); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #5f5f60), color-stop(90%, #525353)); + background-image: -webkit-linear-gradient(#5f5f60 10%, #525353 90%); + background-image: -moz-linear-gradient(#5f5f60 10%, #525353 90%); + background-image: -o-linear-gradient(#5f5f60 10%, #525353 90%); + background-image: linear-gradient(#5f5f60 10%, #525353 90%); } .psf-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #b8b9b9; background-color: #ececec; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFECECEC'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #ececec)); - background-image: -moz-linear-gradient(#ffffff 10%, #ececec 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #ececec 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #ececec 90%); + background-image: -o-linear-gradient(#ffffff 10%, #ececec 90%); background-image: linear-gradient(#ffffff 10%, #ececec 90%); } .psf-navigation .super-navigation a:not(.button) { color: #78797a; } @@ -1023,13 +1017,12 @@ html[xmlns] .slides { display: block; } background-color: #ffc91a; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFD343', endColorstr='#FFFFC91A'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNmZmQzNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #ffd343), color-stop(95%, #ffc91a)); - background-image: -moz-linear-gradient(#ffd343 30%, #ffc91a 95%); background-image: -webkit-linear-gradient(#ffd343 30%, #ffc91a 95%); + background-image: -moz-linear-gradient(#ffd343 30%, #ffc91a 95%); + background-image: -o-linear-gradient(#ffd343 30%, #ffc91a 95%); background-image: linear-gradient(#ffd343 30%, #ffc91a 95%); - border-top: 1px solid #ffe590; + border-top: 1px solid #ffe58f; border-bottom: 1px solid #c39500; /*a*/ } .docs-navigation .tier-1 { @@ -1038,21 +1031,20 @@ html[xmlns] .slides { display: block; } border-bottom: 1px solid #dca900; border-left: 1px solid #ffdf76; } .docs-navigation .tier-1 > a { - color: #333; + color: #333333; background-color: transparent; border-top: 1px solid transparent; border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .docs-navigation .tier-1 > a:hover, .docs-navigation .tier-1 > a:focus, .docs-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #ffc91a; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFCE2F', endColorstr='#FFFFC91A'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmNlMmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffce2f), color-stop(90%, #ffc91a)); - background-image: -moz-linear-gradient(#ffce2f 10%, #ffc91a 90%); background-image: -webkit-linear-gradient(#ffce2f 10%, #ffc91a 90%); + background-image: -moz-linear-gradient(#ffce2f 10%, #ffc91a 90%); + background-image: -o-linear-gradient(#ffce2f 10%, #ffc91a 90%); background-image: linear-gradient(#ffce2f 10%, #ffc91a 90%); border-top: 1px solid #ffd343; border-bottom: 1px solid #ffc91a; } @@ -1061,14 +1053,13 @@ html[xmlns] .slides { display: block; } background-color: white; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFFFFFF'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #ffffff)); - background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -o-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: linear-gradient(#ffffff 10%, #ffffff 90%); - -moz-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); /*modernizr*/ } .touch .docs-navigation .subnav:before { @@ -1083,42 +1074,39 @@ html[xmlns] .slides { display: block; } .docs-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(255, 211, 67, 0.25); } .docs-navigation .current_item { - color: #fff; - background-color: #f6bc00; + color: white; + background-color: #f5bc00; *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFC710', endColorstr='#FFF6BC00'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmM3MTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y2YmMwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffc710), color-stop(90%, #f6bc00)); - background-image: -moz-linear-gradient(#ffc710 10%, #f6bc00 90%); - background-image: -webkit-linear-gradient(#ffc710 10%, #f6bc00 90%); - background-image: linear-gradient(#ffc710 10%, #f6bc00 90%); } + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFC710', endColorstr='#FFF5BC00'); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffc710), color-stop(90%, #f5bc00)); + background-image: -webkit-linear-gradient(#ffc710 10%, #f5bc00 90%); + background-image: -moz-linear-gradient(#ffc710 10%, #f5bc00 90%); + background-image: -o-linear-gradient(#ffc710 10%, #f5bc00 90%); + background-image: linear-gradient(#ffc710 10%, #f5bc00 90%); } .docs-navigation .super-navigation { - color: #666; - border: 1px solid #fff1c3; + color: #666666; + border: 1px solid #fff1c2; background-color: white; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFFFFFF'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #ffffff)); - background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -o-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: linear-gradient(#ffffff 10%, #ffffff 90%); } .docs-navigation .super-navigation a:not(.button) { color: #ffd343; } .docs-navigation .super-navigation h4 { - color: #ffcd2a; } + color: #ffcd29; } .pypl-navigation { background-color: #6c9238; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF82B043', endColorstr='#FF6C9238'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM4MmIwNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #82b043), color-stop(95%, #6c9238)); - background-image: -moz-linear-gradient(#82b043 30%, #6c9238 95%); background-image: -webkit-linear-gradient(#82b043 30%, #6c9238 95%); + background-image: -moz-linear-gradient(#82b043 30%, #6c9238 95%); + background-image: -o-linear-gradient(#82b043 30%, #6c9238 95%); background-image: linear-gradient(#82b043 30%, #6c9238 95%); border-top: 1px solid #a6ca75; border-bottom: 1px solid #3e5420; @@ -1135,15 +1123,14 @@ html[xmlns] .slides { display: block; } border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .pypl-navigation .tier-1 > a:hover, .pypl-navigation .tier-1 > a:focus, .pypl-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #6c9238; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF77A13D', endColorstr='#FF6C9238'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM3N2ExM2QiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #77a13d), color-stop(90%, #6c9238)); - background-image: -moz-linear-gradient(#77a13d 10%, #6c9238 90%); background-image: -webkit-linear-gradient(#77a13d 10%, #6c9238 90%); + background-image: -moz-linear-gradient(#77a13d 10%, #6c9238 90%); + background-image: -o-linear-gradient(#77a13d 10%, #6c9238 90%); background-image: linear-gradient(#77a13d 10%, #6c9238 90%); border-top: 1px solid #82b043; border-bottom: 1px solid #6c9238; } @@ -1152,14 +1139,13 @@ html[xmlns] .slides { display: block; } background-color: #eef5e4; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFDDEBCA', endColorstr='#FFEEF5E4'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkZGViY2EiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ddebca), color-stop(90%, #eef5e4)); - background-image: -moz-linear-gradient(#ddebca 10%, #eef5e4 90%); background-image: -webkit-linear-gradient(#ddebca 10%, #eef5e4 90%); + background-image: -moz-linear-gradient(#ddebca 10%, #eef5e4 90%); + background-image: -o-linear-gradient(#ddebca 10%, #eef5e4 90%); background-image: linear-gradient(#ddebca 10%, #eef5e4 90%); - -moz-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); /*modernizr*/ } .touch .pypl-navigation .subnav:before { @@ -1174,27 +1160,25 @@ html[xmlns] .slides { display: block; } .pypl-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(130, 176, 67, 0.25); } .pypl-navigation .current_item { - color: #fff; + color: white; background-color: #59792e; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF678B35', endColorstr='#FF59792E'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2NzhiMzUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzU5NzkyZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #678b35), color-stop(90%, #59792e)); - background-image: -moz-linear-gradient(#678b35 10%, #59792e 90%); background-image: -webkit-linear-gradient(#678b35 10%, #59792e 90%); + background-image: -moz-linear-gradient(#678b35 10%, #59792e 90%); + background-image: -o-linear-gradient(#678b35 10%, #59792e 90%); background-image: linear-gradient(#678b35 10%, #59792e 90%); } .pypl-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #bed99a; background-color: #eef5e4; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFEEF5E4'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #eef5e4)); - background-image: -moz-linear-gradient(#ffffff 10%, #eef5e4 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #eef5e4 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #eef5e4 90%); + background-image: -o-linear-gradient(#ffffff 10%, #eef5e4 90%); background-image: linear-gradient(#ffffff 10%, #eef5e4 90%); } .pypl-navigation .super-navigation a:not(.button) { color: #82b043; } @@ -1205,11 +1189,10 @@ html[xmlns] .slides { display: block; } background-color: #8b5792; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFA06BA7', endColorstr='#FF8B5792'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNhMDZiYTciLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #a06ba7), color-stop(95%, #8b5792)); - background-image: -moz-linear-gradient(#a06ba7 30%, #8b5792 95%); background-image: -webkit-linear-gradient(#a06ba7 30%, #8b5792 95%); + background-image: -moz-linear-gradient(#a06ba7 30%, #8b5792 95%); + background-image: -o-linear-gradient(#a06ba7 30%, #8b5792 95%); background-image: linear-gradient(#a06ba7 30%, #8b5792 95%); border-top: 1px solid #bf9bc4; border-bottom: 1px solid #58375c; @@ -1226,15 +1209,14 @@ html[xmlns] .slides { display: block; } border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .jobs-navigation .tier-1 > a:hover, .jobs-navigation .tier-1 > a:focus, .jobs-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #8b5792; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF985F9F', endColorstr='#FF8B5792'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5ODVmOWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #985f9f), color-stop(90%, #8b5792)); - background-image: -moz-linear-gradient(#985f9f 10%, #8b5792 90%); background-image: -webkit-linear-gradient(#985f9f 10%, #8b5792 90%); + background-image: -moz-linear-gradient(#985f9f 10%, #8b5792 90%); + background-image: -o-linear-gradient(#985f9f 10%, #8b5792 90%); background-image: linear-gradient(#985f9f 10%, #8b5792 90%); border-top: 1px solid #a06ba7; border-bottom: 1px solid #8b5792; } @@ -1243,14 +1225,13 @@ html[xmlns] .slides { display: block; } background-color: #fcfbfd; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFEEE5EF', endColorstr='#FFFCFBFD'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlZWU1ZWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #eee5ef), color-stop(90%, #fcfbfd)); - background-image: -moz-linear-gradient(#eee5ef 10%, #fcfbfd 90%); background-image: -webkit-linear-gradient(#eee5ef 10%, #fcfbfd 90%); + background-image: -moz-linear-gradient(#eee5ef 10%, #fcfbfd 90%); + background-image: -o-linear-gradient(#eee5ef 10%, #fcfbfd 90%); background-image: linear-gradient(#eee5ef 10%, #fcfbfd 90%); - -moz-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); /*modernizr*/ } .touch .jobs-navigation .subnav:before { @@ -1265,27 +1246,25 @@ html[xmlns] .slides { display: block; } .jobs-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(160, 107, 167, 0.25); } .jobs-navigation .current_item { - color: #fff; + color: white; background-color: #764a7c; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF85538C', endColorstr='#FF764A7C'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM4NTUzOGMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzc2NGE3YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #85538c), color-stop(90%, #764a7c)); - background-image: -moz-linear-gradient(#85538c 10%, #764a7c 90%); background-image: -webkit-linear-gradient(#85538c 10%, #764a7c 90%); + background-image: -moz-linear-gradient(#85538c 10%, #764a7c 90%); + background-image: -o-linear-gradient(#85538c 10%, #764a7c 90%); background-image: linear-gradient(#85538c 10%, #764a7c 90%); } .jobs-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #d3bbd7; background-color: #fcfbfd; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFCFBFD'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #fcfbfd)); - background-image: -moz-linear-gradient(#ffffff 10%, #fcfbfd 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #fcfbfd 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #fcfbfd 90%); + background-image: -o-linear-gradient(#ffffff 10%, #fcfbfd 90%); background-image: linear-gradient(#ffffff 10%, #fcfbfd 90%); } .jobs-navigation .super-navigation a:not(.button) { color: #a06ba7; } @@ -1296,11 +1275,10 @@ html[xmlns] .slides { display: block; } background-color: #9e4650; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFB55863', endColorstr='#FF9E4650'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNiNTU4NjMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #b55863), color-stop(95%, #9e4650)); - background-image: -moz-linear-gradient(#b55863 30%, #9e4650 95%); background-image: -webkit-linear-gradient(#b55863 30%, #9e4650 95%); + background-image: -moz-linear-gradient(#b55863 30%, #9e4650 95%); + background-image: -o-linear-gradient(#b55863 30%, #9e4650 95%); background-image: linear-gradient(#b55863 30%, #9e4650 95%); border-top: 1px solid #cc8d95; border-bottom: 1px solid #622b32; @@ -1317,15 +1295,14 @@ html[xmlns] .slides { display: block; } border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .shop-navigation .tier-1 > a:hover, .shop-navigation .tier-1 > a:focus, .shop-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #9e4650; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFAC4C58', endColorstr='#FF9E4650'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNhYzRjNTgiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ac4c58), color-stop(90%, #9e4650)); - background-image: -moz-linear-gradient(#ac4c58 10%, #9e4650 90%); background-image: -webkit-linear-gradient(#ac4c58 10%, #9e4650 90%); + background-image: -moz-linear-gradient(#ac4c58 10%, #9e4650 90%); + background-image: -o-linear-gradient(#ac4c58 10%, #9e4650 90%); background-image: linear-gradient(#ac4c58 10%, #9e4650 90%); border-top: 1px solid #b55863; border-bottom: 1px solid #9e4650; } @@ -1334,14 +1311,13 @@ html[xmlns] .slides { display: block; } background-color: #fbf7f8; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFF1DEE0', endColorstr='#FFFBF7F8'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmMWRlZTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #f1dee0), color-stop(90%, #fbf7f8)); - background-image: -moz-linear-gradient(#f1dee0 10%, #fbf7f8 90%); background-image: -webkit-linear-gradient(#f1dee0 10%, #fbf7f8 90%); + background-image: -moz-linear-gradient(#f1dee0 10%, #fbf7f8 90%); + background-image: -o-linear-gradient(#f1dee0 10%, #fbf7f8 90%); background-image: linear-gradient(#f1dee0 10%, #fbf7f8 90%); - -moz-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); /*modernizr*/ } .touch .shop-navigation .subnav:before { @@ -1356,27 +1332,25 @@ html[xmlns] .slides { display: block; } .shop-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(181, 88, 99, 0.25); } .shop-navigation .current_item { - color: #fff; + color: white; background-color: #853b44; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF97434D', endColorstr='#FF853B44'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5NzQzNGQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzg1M2I0NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #97434d), color-stop(90%, #853b44)); - background-image: -moz-linear-gradient(#97434d 10%, #853b44 90%); background-image: -webkit-linear-gradient(#97434d 10%, #853b44 90%); + background-image: -moz-linear-gradient(#97434d 10%, #853b44 90%); + background-image: -o-linear-gradient(#97434d 10%, #853b44 90%); background-image: linear-gradient(#97434d 10%, #853b44 90%); } .shop-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #dcb0b6; background-color: #fbf7f8; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFBF7F8'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #fbf7f8)); - background-image: -moz-linear-gradient(#ffffff 10%, #fbf7f8 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #fbf7f8 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #fbf7f8 90%); + background-image: -o-linear-gradient(#ffffff 10%, #fbf7f8 90%); background-image: linear-gradient(#ffffff 10%, #fbf7f8 90%); } .shop-navigation .super-navigation a:not(.button) { color: #b55863; } @@ -1394,7 +1368,7 @@ html[xmlns] .slides { display: block; } width: 65.95745%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .main-content.with-right-sidebar { width: 65.95745%; float: left; @@ -1415,13 +1389,13 @@ html[xmlns] .slides { display: block; } width: 31.91489%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .left-sidebar .small-widget, .left-sidebar .medium-widget, .left-sidebar .triple-widget, .right-sidebar .small-widget, .right-sidebar .medium-widget, .right-sidebar .triple-widget { float: none; width: auto; margin-right: auto; - #margin-left: auto; } + *margin-left: auto; } /* Widgets in main content */ .row { @@ -1495,15 +1469,15 @@ html[xmlns] .slides { display: block; } .listing-company-category:before { content: "Category: "; - color: #666; } + color: #666666; } .listing-job-title:before { content: "Title: "; - color: #666; } + color: #666666; } .listing-job-type:before { content: "Looking for: "; - color: #666; } + color: #666666; } .release-number, .release-date, @@ -1556,8 +1530,8 @@ html[xmlns] .slides { display: block; } overflow: hidden; *zoom: 1; } .previous-next a { - -moz-box-sizing: border-box; -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; } .previous-next .prev-button { width: 48.93617%; @@ -1567,7 +1541,7 @@ html[xmlns] .slides { display: block; } width: 48.93617%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } /* Footer */ .main-footer .jump-link { @@ -1613,7 +1587,7 @@ html[xmlns] .slides { display: block; } margin: 0.875em 0; } .search-field { - background: #fff; + background: white; padding: .4em .5em .3em; margin-right: .5em; width: 11em; } @@ -1659,37 +1633,38 @@ html[xmlns] .slides { display: block; } right: 2.6em; white-space: nowrap; padding: .4em .75em .35em; - color: #999; + color: #999999; background-color: #1f1f1f; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF333333', endColorstr='#FF1F1F1F'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMzMzMzMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzFmMWYxZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #333333), color-stop(90%, #1f1f1f)); - background-image: -moz-linear-gradient(#333333 10%, #1f1f1f 90%); background-image: -webkit-linear-gradient(#333333 10%, #1f1f1f 90%); + background-image: -moz-linear-gradient(#333333 10%, #1f1f1f 90%); + background-image: -o-linear-gradient(#333333 10%, #1f1f1f 90%); background-image: linear-gradient(#333333 10%, #1f1f1f 90%); - border-top: 1px solid #444; - border-right: 1px solid #444; - border-bottom: 1px solid #444; - border-left: 1px solid #444; - -moz-border-radius: 6px; + border-top: 1px solid #444444; + border-right: 1px solid #444444; + border-bottom: 1px solid #444444; + border-left: 1px solid #444444; -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; - -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); - -moz-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; - -o-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; -webkit-transition-delay: 0s, 0.25s; + -moz-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; + -o-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; } .flexslide .launch-shell .button:hover .message { opacity: 1; top: 0; + -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; -moz-transition: opacity 0.25s ease-in-out, top 0s linear; -o-transition: opacity 0.25s ease-in-out, top 0s linear; - -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; transition: opacity 0.25s ease-in-out, top 0s linear; } .introduction { @@ -1718,24 +1693,24 @@ html[xmlns] .slides { display: block; } padding-top: 1em; } .about-banner { - background: 120% 0 no-repeat url('../img/landing-about.png?1576869008') transparent; + background: 120% 0 no-repeat url('../img/landing-about.png?1646853871') transparent; min-height: 345px; padding-bottom: 3.5em; margin-bottom: -2.5em; } .download-for-current-os { - background: 130% 0 no-repeat url('../img/landing-downloads.png?1576869008') transparent; + background: 130% 0 no-repeat url('../img/landing-downloads.png?1646853871') transparent; min-height: 345px; padding-bottom: 4em; margin-bottom: -3em; } .documentation-banner { - background: 130% 0 no-repeat url('../img/landing-docs.png?1576869008') transparent; + background: 130% 0 no-repeat url('../img/landing-docs.png?1646853871') transparent; padding-bottom: 1em; } .community-banner { text-align: left; - background: 110% 0 no-repeat url('../img/landing-community.png?1576869008') transparent; + background: 110% 0 no-repeat url('../img/landing-community.png?1646853871') transparent; min-height: 345px; padding-bottom: 2em; margin-bottom: -1.25em; } @@ -1789,7 +1764,7 @@ html[xmlns] .slides { display: block; } width: 74.46809%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .main-content.with-right-sidebar { width: 74.46809%; float: left; @@ -1806,7 +1781,7 @@ html[xmlns] .slides { display: block; } width: 23.40426%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .featured-success-story { /*blockquote*/ } @@ -1839,7 +1814,7 @@ html[xmlns] .slides { display: block; } right: 1em; width: 210px; height: 210px; - background: top left no-repeat url('../img/python-logo-large.png?1576869008') transparent; } + background: top left no-repeat url('../img/python-logo-large.png?1646853871') transparent; } .psf-widget .widget-title, .psf-widget p, .python-needs-you-widget .widget-title, .python-needs-you-widget p { margin-right: 34.04255%; } @@ -1871,7 +1846,7 @@ html[xmlns] .slides { display: block; } width: 48.93617%; float: right; margin-right: 0; - #margin-left: -20px; + *margin-left: -20px; text-align: right; clear: none; } .list-recent-jobs .listing-actions { @@ -1887,14 +1862,14 @@ html[xmlns] .slides { display: block; } float: left; margin-right: 2.12766%; } .listing-company .listing-company-name a:hover:after, .listing-company .listing-company-name a:focus:after { - color: #666; + color: #666666; content: " View Details"; font-size: .75em; } .listing-company .listing-location { width: 40.42553%; float: right; margin-right: 0; - #margin-left: -20px; + *margin-left: -20px; text-align: right; } .job-meta { @@ -1907,7 +1882,7 @@ html[xmlns] .slides { display: block; } width: 48.93617%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } /* Forms that are wide enough to have labels and input fields side by side */ .wide-form ul { @@ -2030,20 +2005,20 @@ html[xmlns] .slides { display: block; } .no-touch .main-navigation .subnav { min-width: 100%; display: none; + -webkit-transition: all 0s ease; -moz-transition: all 0s ease; -o-transition: all 0s ease; - -webkit-transition: all 0s ease; transition: all 0s ease; } .touch .main-navigation .subnav { top: 120%; display: none; opacity: 0; + -webkit-transition: opacity 0.25s ease-in-out; -moz-transition: opacity 0.25s ease-in-out; -o-transition: opacity 0.25s ease-in-out; - -webkit-transition: opacity 0.25s ease-in-out; transition: opacity 0.25s ease-in-out; - -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); } .touch .main-navigation .subnav:before { position: absolute; @@ -2058,16 +2033,16 @@ html[xmlns] .slides { display: block; } .no-touch .main-navigation .element-1:hover .subnav, .no-touch .main-navigation .element-1:focus .subnav, .no-touch .main-navigation .element-2:hover .subnav, .no-touch .main-navigation .element-2:focus .subnav, .no-touch .main-navigation .element-3:hover .subnav, .no-touch .main-navigation .element-3:focus .subnav, .no-touch .main-navigation .element-4:hover .subnav, .no-touch .main-navigation .element-4:focus .subnav { left: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .no-touch .main-navigation .element-5:hover .subnav, .no-touch .main-navigation .element-5:focus .subnav, .no-touch .main-navigation .element-6:hover .subnav, .no-touch .main-navigation .element-6:focus .subnav, .no-touch .main-navigation .element-7:hover .subnav, .no-touch .main-navigation .element-7:focus .subnav, .no-touch .main-navigation .element-8:hover .subnav, .no-touch .main-navigation .element-8:focus .subnav, .no-touch .main-navigation .last:hover .subnav, .no-touch .main-navigation .last:focus .subnav { right: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .touch .main-navigation .element-1, .touch .main-navigation .element-2, .touch .main-navigation .element-3, .touch .main-navigation .element-4 { /* Position the pointer element */ } @@ -2096,11 +2071,13 @@ html[xmlns] .slides { display: block; } display: block; text-align: center; font-size: 1.125em; - -moz-border-radius: 8px; -webkit-border-radius: 8px; + -moz-border-radius: 8px; + -ms-border-radius: 8px; + -o-border-radius: 8px; border-radius: 8px; - -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } .no-touch .main-navigation .menu { text-align: center; } @@ -2188,7 +2165,7 @@ html[xmlns] .slides { display: block; } /*.subnav li*/ .super-navigation { - color: #666; + color: #666666; position: absolute; /* relative to the containing LI */ top: 0; @@ -2215,7 +2192,7 @@ html[xmlns] .slides { display: block; } line-height: 1.25em; margin-bottom: 0; } .super-navigation p.date-posted { - color: #666; + color: #666666; font-size: 0.625em !important; font-style: italic; } .super-navigation p.excert { @@ -2287,7 +2264,7 @@ html[xmlns] .slides { display: block; } .text { /* Make the intro/first paragraphs slightly larger? */ } .text > p:first-of-type { - color: #666; + color: #666666; font-size: 1.125em; line-height: 1.6875; margin-bottom: 1.25em; } @@ -2417,7 +2394,7 @@ html[xmlns] .slides { display: block; } .home-slideshow .flex-direction-nav .flex-prev, .home-slideshow .flex-direction-nav .flex-next { top: 40%; font-size: 1.5em; - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); opacity: 1; } .home-slideshow .flex-direction-nav .flex-prev { left: -.75em; } @@ -2471,25 +2448,27 @@ html[xmlns] .slides { display: block; } display: block; opacity: 1; border-top: 0; - -moz-box-shadow: none; -webkit-box-shadow: none; + -moz-box-shadow: none; box-shadow: none; } /* TO DO: With Javascript, look for a left-right swipe action and also trigger the menu to open */ .touch #touchnav-wrapper { + -webkit-transition: -webkit-transform 300ms ease; -moz-transition: -moz-transform 300ms ease; -o-transition: -o-transform 300ms ease; - -webkit-transition: -webkit-transform 300ms ease; transition: transform 300ms ease; + -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); - -webkit-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); -webkit-backface-visibility: hidden; } .touch .show-sidemenu #touchnav-wrapper { + -webkit-transform: translate3d(260px, 0, 0); -moz-transform: translate3d(260px, 0, 0); -ms-transform: translate3d(260px, 0, 0); - -webkit-transform: translate3d(260px, 0, 0); + -o-transform: translate3d(260px, 0, 0); transform: translate3d(260px, 0, 0); } } /* - - - Larger than 1024px - - - */ @media (min-width: 64em) { @@ -2585,7 +2564,6 @@ html[xmlns] .slides { display: block; } */ @-ms-viewport { width: device-width; } + @viewport { width: device-width; } - -/*# sourceMappingURL=mq.css.map */ diff --git a/static/sass/no-mq.css b/static/sass/no-mq.css index 283fffa7b..0565a60dd 100644 --- a/static/sass/no-mq.css +++ b/static/sass/no-mq.css @@ -177,7 +177,7 @@ .slides, .flex-control-nav, .flex-direction-nav {margin: 0; padding: 0; list-style: none;} */ -/* FlexSlider Necessary Styles + /* FlexSlider Necessary Styles .flexslider {margin: 0; padding: 0;} .flexslider .slides > li {display: none; -webkit-backface-visibility: hidden;} /* Hide the slides before the JS is loaded. Avoids image jumping .flexslider .slides img {width: 100%; display: block;} @@ -505,9 +505,9 @@ a.button { border-color: transparent; } .search-field { + -webkit-transition: width 0.3s ease-in-out; -moz-transition: width 0.3s ease-in-out; -o-transition: width 0.3s ease-in-out; - -webkit-transition: width 0.3s ease-in-out; transition: width 0.3s ease-in-out; } .search-field:focus { @@ -562,11 +562,10 @@ a.button { background-color: #2d618c; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF3776AB', endColorstr='#FF2D618C'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiMzNzc2YWIiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #3776ab), color-stop(95%, #2d618c)); - background-image: -moz-linear-gradient(#3776ab 30%, #2d618c 95%); background-image: -webkit-linear-gradient(#3776ab 30%, #2d618c 95%); + background-image: -moz-linear-gradient(#3776ab 30%, #2d618c 95%); + background-image: -o-linear-gradient(#3776ab 30%, #2d618c 95%); background-image: linear-gradient(#3776ab 30%, #2d618c 95%); border-top: 1px solid #629ccd; border-bottom: 1px solid #18334b; @@ -583,15 +582,14 @@ a.button { border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .python-navigation .tier-1 > a:hover, .python-navigation .tier-1 > a:focus, .python-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #2d618c; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF326B9C', endColorstr='#FF2D618C'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMjZiOWMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #326b9c), color-stop(90%, #2d618c)); - background-image: -moz-linear-gradient(#326b9c 10%, #2d618c 90%); background-image: -webkit-linear-gradient(#326b9c 10%, #2d618c 90%); + background-image: -moz-linear-gradient(#326b9c 10%, #2d618c 90%); + background-image: -o-linear-gradient(#326b9c 10%, #2d618c 90%); background-image: linear-gradient(#326b9c 10%, #2d618c 90%); border-top: 1px solid #3776ab; border-bottom: 1px solid #2d618c; } @@ -600,14 +598,13 @@ a.button { background-color: #d6e5f2; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFBBD4E9', endColorstr='#FFD6E5F2'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNiYmQ0ZTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #bbd4e9), color-stop(90%, #d6e5f2)); - background-image: -moz-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); background-image: -webkit-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); + background-image: -moz-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); + background-image: -o-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); background-image: linear-gradient(#bbd4e9 10%, #d6e5f2 90%); - -moz-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); /*modernizr*/ } .touch .python-navigation .subnav:before { @@ -622,27 +619,25 @@ a.button { .python-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(55, 118, 171, 0.25); } .python-navigation .current_item { - color: #fff; + color: white; background-color: #244e71; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF2B5B84', endColorstr='#FF244E71'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyYjViODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzI0NGU3MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #2b5b84), color-stop(90%, #244e71)); - background-image: -moz-linear-gradient(#2b5b84 10%, #244e71 90%); background-image: -webkit-linear-gradient(#2b5b84 10%, #244e71 90%); + background-image: -moz-linear-gradient(#2b5b84 10%, #244e71 90%); + background-image: -o-linear-gradient(#2b5b84 10%, #244e71 90%); background-image: linear-gradient(#2b5b84 10%, #244e71 90%); } .python-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #89b4d9; background-color: #d6e5f2; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFCFDFE', endColorstr='#FFD6E5F2'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmY2ZkZmUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #fcfdfe), color-stop(90%, #d6e5f2)); - background-image: -moz-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); background-image: -webkit-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); + background-image: -moz-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); + background-image: -o-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); background-image: linear-gradient(#fcfdfe 10%, #d6e5f2 90%); } .python-navigation .super-navigation a:not(.button) { color: #3776ab; } @@ -653,18 +648,17 @@ a.button { background-color: #646565; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF78797A', endColorstr='#FF646565'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM3ODc5N2EiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #78797a), color-stop(95%, #646565)); - background-image: -moz-linear-gradient(#78797a 30%, #646565 95%); background-image: -webkit-linear-gradient(#78797a 30%, #646565 95%); + background-image: -moz-linear-gradient(#78797a 30%, #646565 95%); + background-image: -o-linear-gradient(#78797a 30%, #646565 95%); background-image: linear-gradient(#78797a 30%, #646565 95%); border-top: 1px solid #9e9fa0; border-bottom: 1px solid #39393a; /*a*/ } .psf-navigation .tier-1 { border-top: 1px solid #929393; - border-right: 1px solid #5f6060; + border-right: 1px solid #5f5f60; border-bottom: 1px solid #454647; border-left: 1px solid #929393; } .psf-navigation .tier-1 > a { @@ -674,15 +668,14 @@ a.button { border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .psf-navigation .tier-1 > a:hover, .psf-navigation .tier-1 > a:focus, .psf-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #646565; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF6E6F70', endColorstr='#FF646565'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2ZTZmNzAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #6e6f70), color-stop(90%, #646565)); - background-image: -moz-linear-gradient(#6e6f70 10%, #646565 90%); background-image: -webkit-linear-gradient(#6e6f70 10%, #646565 90%); + background-image: -moz-linear-gradient(#6e6f70 10%, #646565 90%); + background-image: -o-linear-gradient(#6e6f70 10%, #646565 90%); background-image: linear-gradient(#6e6f70 10%, #646565 90%); border-top: 1px solid #78797a; border-bottom: 1px solid #646565; } @@ -691,14 +684,13 @@ a.button { background-color: #ececec; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFDADADA', endColorstr='#FFECECEC'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkYWRhZGEiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #dadada), color-stop(90%, #ececec)); - background-image: -moz-linear-gradient(#dadada 10%, #ececec 90%); background-image: -webkit-linear-gradient(#dadada 10%, #ececec 90%); + background-image: -moz-linear-gradient(#dadada 10%, #ececec 90%); + background-image: -o-linear-gradient(#dadada 10%, #ececec 90%); background-image: linear-gradient(#dadada 10%, #ececec 90%); - -moz-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); /*modernizr*/ } .touch .psf-navigation .subnav:before { @@ -713,27 +705,25 @@ a.button { .psf-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(120, 121, 122, 0.25); } .psf-navigation .current_item { - color: #fff; + color: white; background-color: #525353; *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF5F6060', endColorstr='#FF525353'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM1ZjYwNjAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzUyNTM1MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #5f6060), color-stop(90%, #525353)); - background-image: -moz-linear-gradient(#5f6060 10%, #525353 90%); - background-image: -webkit-linear-gradient(#5f6060 10%, #525353 90%); - background-image: linear-gradient(#5f6060 10%, #525353 90%); } + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF5F5F60', endColorstr='#FF525353'); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #5f5f60), color-stop(90%, #525353)); + background-image: -webkit-linear-gradient(#5f5f60 10%, #525353 90%); + background-image: -moz-linear-gradient(#5f5f60 10%, #525353 90%); + background-image: -o-linear-gradient(#5f5f60 10%, #525353 90%); + background-image: linear-gradient(#5f5f60 10%, #525353 90%); } .psf-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #b8b9b9; background-color: #ececec; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFECECEC'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #ececec)); - background-image: -moz-linear-gradient(#ffffff 10%, #ececec 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #ececec 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #ececec 90%); + background-image: -o-linear-gradient(#ffffff 10%, #ececec 90%); background-image: linear-gradient(#ffffff 10%, #ececec 90%); } .psf-navigation .super-navigation a:not(.button) { color: #78797a; } @@ -744,13 +734,12 @@ a.button { background-color: #ffc91a; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFD343', endColorstr='#FFFFC91A'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNmZmQzNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #ffd343), color-stop(95%, #ffc91a)); - background-image: -moz-linear-gradient(#ffd343 30%, #ffc91a 95%); background-image: -webkit-linear-gradient(#ffd343 30%, #ffc91a 95%); + background-image: -moz-linear-gradient(#ffd343 30%, #ffc91a 95%); + background-image: -o-linear-gradient(#ffd343 30%, #ffc91a 95%); background-image: linear-gradient(#ffd343 30%, #ffc91a 95%); - border-top: 1px solid #ffe590; + border-top: 1px solid #ffe58f; border-bottom: 1px solid #c39500; /*a*/ } .docs-navigation .tier-1 { @@ -759,21 +748,20 @@ a.button { border-bottom: 1px solid #dca900; border-left: 1px solid #ffdf76; } .docs-navigation .tier-1 > a { - color: #333; + color: #333333; background-color: transparent; border-top: 1px solid transparent; border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .docs-navigation .tier-1 > a:hover, .docs-navigation .tier-1 > a:focus, .docs-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #ffc91a; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFCE2F', endColorstr='#FFFFC91A'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmNlMmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffce2f), color-stop(90%, #ffc91a)); - background-image: -moz-linear-gradient(#ffce2f 10%, #ffc91a 90%); background-image: -webkit-linear-gradient(#ffce2f 10%, #ffc91a 90%); + background-image: -moz-linear-gradient(#ffce2f 10%, #ffc91a 90%); + background-image: -o-linear-gradient(#ffce2f 10%, #ffc91a 90%); background-image: linear-gradient(#ffce2f 10%, #ffc91a 90%); border-top: 1px solid #ffd343; border-bottom: 1px solid #ffc91a; } @@ -782,14 +770,13 @@ a.button { background-color: white; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFFFFFF'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #ffffff)); - background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -o-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: linear-gradient(#ffffff 10%, #ffffff 90%); - -moz-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); /*modernizr*/ } .touch .docs-navigation .subnav:before { @@ -804,42 +791,39 @@ a.button { .docs-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(255, 211, 67, 0.25); } .docs-navigation .current_item { - color: #fff; - background-color: #f6bc00; + color: white; + background-color: #f5bc00; *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFC710', endColorstr='#FFF6BC00'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmM3MTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y2YmMwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffc710), color-stop(90%, #f6bc00)); - background-image: -moz-linear-gradient(#ffc710 10%, #f6bc00 90%); - background-image: -webkit-linear-gradient(#ffc710 10%, #f6bc00 90%); - background-image: linear-gradient(#ffc710 10%, #f6bc00 90%); } + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFC710', endColorstr='#FFF5BC00'); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffc710), color-stop(90%, #f5bc00)); + background-image: -webkit-linear-gradient(#ffc710 10%, #f5bc00 90%); + background-image: -moz-linear-gradient(#ffc710 10%, #f5bc00 90%); + background-image: -o-linear-gradient(#ffc710 10%, #f5bc00 90%); + background-image: linear-gradient(#ffc710 10%, #f5bc00 90%); } .docs-navigation .super-navigation { - color: #666; - border: 1px solid #fff1c3; + color: #666666; + border: 1px solid #fff1c2; background-color: white; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFFFFFF'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #ffffff)); - background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #ffffff 90%); + background-image: -o-linear-gradient(#ffffff 10%, #ffffff 90%); background-image: linear-gradient(#ffffff 10%, #ffffff 90%); } .docs-navigation .super-navigation a:not(.button) { color: #ffd343; } .docs-navigation .super-navigation h4 { - color: #ffcd2a; } + color: #ffcd29; } .pypl-navigation { background-color: #6c9238; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF82B043', endColorstr='#FF6C9238'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM4MmIwNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #82b043), color-stop(95%, #6c9238)); - background-image: -moz-linear-gradient(#82b043 30%, #6c9238 95%); background-image: -webkit-linear-gradient(#82b043 30%, #6c9238 95%); + background-image: -moz-linear-gradient(#82b043 30%, #6c9238 95%); + background-image: -o-linear-gradient(#82b043 30%, #6c9238 95%); background-image: linear-gradient(#82b043 30%, #6c9238 95%); border-top: 1px solid #a6ca75; border-bottom: 1px solid #3e5420; @@ -856,15 +840,14 @@ a.button { border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .pypl-navigation .tier-1 > a:hover, .pypl-navigation .tier-1 > a:focus, .pypl-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #6c9238; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF77A13D', endColorstr='#FF6C9238'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM3N2ExM2QiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #77a13d), color-stop(90%, #6c9238)); - background-image: -moz-linear-gradient(#77a13d 10%, #6c9238 90%); background-image: -webkit-linear-gradient(#77a13d 10%, #6c9238 90%); + background-image: -moz-linear-gradient(#77a13d 10%, #6c9238 90%); + background-image: -o-linear-gradient(#77a13d 10%, #6c9238 90%); background-image: linear-gradient(#77a13d 10%, #6c9238 90%); border-top: 1px solid #82b043; border-bottom: 1px solid #6c9238; } @@ -873,14 +856,13 @@ a.button { background-color: #eef5e4; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFDDEBCA', endColorstr='#FFEEF5E4'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkZGViY2EiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ddebca), color-stop(90%, #eef5e4)); - background-image: -moz-linear-gradient(#ddebca 10%, #eef5e4 90%); background-image: -webkit-linear-gradient(#ddebca 10%, #eef5e4 90%); + background-image: -moz-linear-gradient(#ddebca 10%, #eef5e4 90%); + background-image: -o-linear-gradient(#ddebca 10%, #eef5e4 90%); background-image: linear-gradient(#ddebca 10%, #eef5e4 90%); - -moz-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); /*modernizr*/ } .touch .pypl-navigation .subnav:before { @@ -895,27 +877,25 @@ a.button { .pypl-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(130, 176, 67, 0.25); } .pypl-navigation .current_item { - color: #fff; + color: white; background-color: #59792e; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF678B35', endColorstr='#FF59792E'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2NzhiMzUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzU5NzkyZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #678b35), color-stop(90%, #59792e)); - background-image: -moz-linear-gradient(#678b35 10%, #59792e 90%); background-image: -webkit-linear-gradient(#678b35 10%, #59792e 90%); + background-image: -moz-linear-gradient(#678b35 10%, #59792e 90%); + background-image: -o-linear-gradient(#678b35 10%, #59792e 90%); background-image: linear-gradient(#678b35 10%, #59792e 90%); } .pypl-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #bed99a; background-color: #eef5e4; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFEEF5E4'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #eef5e4)); - background-image: -moz-linear-gradient(#ffffff 10%, #eef5e4 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #eef5e4 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #eef5e4 90%); + background-image: -o-linear-gradient(#ffffff 10%, #eef5e4 90%); background-image: linear-gradient(#ffffff 10%, #eef5e4 90%); } .pypl-navigation .super-navigation a:not(.button) { color: #82b043; } @@ -926,11 +906,10 @@ a.button { background-color: #8b5792; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFA06BA7', endColorstr='#FF8B5792'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNhMDZiYTciLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #a06ba7), color-stop(95%, #8b5792)); - background-image: -moz-linear-gradient(#a06ba7 30%, #8b5792 95%); background-image: -webkit-linear-gradient(#a06ba7 30%, #8b5792 95%); + background-image: -moz-linear-gradient(#a06ba7 30%, #8b5792 95%); + background-image: -o-linear-gradient(#a06ba7 30%, #8b5792 95%); background-image: linear-gradient(#a06ba7 30%, #8b5792 95%); border-top: 1px solid #bf9bc4; border-bottom: 1px solid #58375c; @@ -947,15 +926,14 @@ a.button { border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .jobs-navigation .tier-1 > a:hover, .jobs-navigation .tier-1 > a:focus, .jobs-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #8b5792; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF985F9F', endColorstr='#FF8B5792'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5ODVmOWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #985f9f), color-stop(90%, #8b5792)); - background-image: -moz-linear-gradient(#985f9f 10%, #8b5792 90%); background-image: -webkit-linear-gradient(#985f9f 10%, #8b5792 90%); + background-image: -moz-linear-gradient(#985f9f 10%, #8b5792 90%); + background-image: -o-linear-gradient(#985f9f 10%, #8b5792 90%); background-image: linear-gradient(#985f9f 10%, #8b5792 90%); border-top: 1px solid #a06ba7; border-bottom: 1px solid #8b5792; } @@ -964,14 +942,13 @@ a.button { background-color: #fcfbfd; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFEEE5EF', endColorstr='#FFFCFBFD'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlZWU1ZWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #eee5ef), color-stop(90%, #fcfbfd)); - background-image: -moz-linear-gradient(#eee5ef 10%, #fcfbfd 90%); background-image: -webkit-linear-gradient(#eee5ef 10%, #fcfbfd 90%); + background-image: -moz-linear-gradient(#eee5ef 10%, #fcfbfd 90%); + background-image: -o-linear-gradient(#eee5ef 10%, #fcfbfd 90%); background-image: linear-gradient(#eee5ef 10%, #fcfbfd 90%); - -moz-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); /*modernizr*/ } .touch .jobs-navigation .subnav:before { @@ -986,27 +963,25 @@ a.button { .jobs-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(160, 107, 167, 0.25); } .jobs-navigation .current_item { - color: #fff; + color: white; background-color: #764a7c; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF85538C', endColorstr='#FF764A7C'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM4NTUzOGMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzc2NGE3YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #85538c), color-stop(90%, #764a7c)); - background-image: -moz-linear-gradient(#85538c 10%, #764a7c 90%); background-image: -webkit-linear-gradient(#85538c 10%, #764a7c 90%); + background-image: -moz-linear-gradient(#85538c 10%, #764a7c 90%); + background-image: -o-linear-gradient(#85538c 10%, #764a7c 90%); background-image: linear-gradient(#85538c 10%, #764a7c 90%); } .jobs-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #d3bbd7; background-color: #fcfbfd; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFCFBFD'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #fcfbfd)); - background-image: -moz-linear-gradient(#ffffff 10%, #fcfbfd 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #fcfbfd 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #fcfbfd 90%); + background-image: -o-linear-gradient(#ffffff 10%, #fcfbfd 90%); background-image: linear-gradient(#ffffff 10%, #fcfbfd 90%); } .jobs-navigation .super-navigation a:not(.button) { color: #a06ba7; } @@ -1017,11 +992,10 @@ a.button { background-color: #9e4650; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFB55863', endColorstr='#FF9E4650'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNiNTU4NjMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(30%, #b55863), color-stop(95%, #9e4650)); - background-image: -moz-linear-gradient(#b55863 30%, #9e4650 95%); background-image: -webkit-linear-gradient(#b55863 30%, #9e4650 95%); + background-image: -moz-linear-gradient(#b55863 30%, #9e4650 95%); + background-image: -o-linear-gradient(#b55863 30%, #9e4650 95%); background-image: linear-gradient(#b55863 30%, #9e4650 95%); border-top: 1px solid #cc8d95; border-bottom: 1px solid #622b32; @@ -1038,15 +1012,14 @@ a.button { border-bottom: 1px solid transparent; letter-spacing: 0.01em; } .shop-navigation .tier-1 > a:hover, .shop-navigation .tier-1 > a:focus, .shop-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; + color: white; background-color: #9e4650; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFAC4C58', endColorstr='#FF9E4650'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNhYzRjNTgiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ac4c58), color-stop(90%, #9e4650)); - background-image: -moz-linear-gradient(#ac4c58 10%, #9e4650 90%); background-image: -webkit-linear-gradient(#ac4c58 10%, #9e4650 90%); + background-image: -moz-linear-gradient(#ac4c58 10%, #9e4650 90%); + background-image: -o-linear-gradient(#ac4c58 10%, #9e4650 90%); background-image: linear-gradient(#ac4c58 10%, #9e4650 90%); border-top: 1px solid #b55863; border-bottom: 1px solid #9e4650; } @@ -1055,14 +1028,13 @@ a.button { background-color: #fbf7f8; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFF1DEE0', endColorstr='#FFFBF7F8'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmMWRlZTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #f1dee0), color-stop(90%, #fbf7f8)); - background-image: -moz-linear-gradient(#f1dee0 10%, #fbf7f8 90%); background-image: -webkit-linear-gradient(#f1dee0 10%, #fbf7f8 90%); + background-image: -moz-linear-gradient(#f1dee0 10%, #fbf7f8 90%); + background-image: -o-linear-gradient(#f1dee0 10%, #fbf7f8 90%); background-image: linear-gradient(#f1dee0 10%, #fbf7f8 90%); - -moz-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); -webkit-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); + -moz-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); /*modernizr*/ } .touch .shop-navigation .subnav:before { @@ -1077,27 +1049,25 @@ a.button { .shop-navigation .tier-2:last-child > a { border-bottom: 1px solid rgba(181, 88, 99, 0.25); } .shop-navigation .current_item { - color: #fff; + color: white; background-color: #853b44; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF97434D', endColorstr='#FF853B44'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5NzQzNGQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzg1M2I0NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #97434d), color-stop(90%, #853b44)); - background-image: -moz-linear-gradient(#97434d 10%, #853b44 90%); background-image: -webkit-linear-gradient(#97434d 10%, #853b44 90%); + background-image: -moz-linear-gradient(#97434d 10%, #853b44 90%); + background-image: -o-linear-gradient(#97434d 10%, #853b44 90%); background-image: linear-gradient(#97434d 10%, #853b44 90%); } .shop-navigation .super-navigation { - color: #666; + color: #666666; border: 1px solid #dcb0b6; background-color: #fbf7f8; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FFFBF7F8'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffffff), color-stop(90%, #fbf7f8)); - background-image: -moz-linear-gradient(#ffffff 10%, #fbf7f8 90%); background-image: -webkit-linear-gradient(#ffffff 10%, #fbf7f8 90%); + background-image: -moz-linear-gradient(#ffffff 10%, #fbf7f8 90%); + background-image: -o-linear-gradient(#ffffff 10%, #fbf7f8 90%); background-image: linear-gradient(#ffffff 10%, #fbf7f8 90%); } .shop-navigation .super-navigation a:not(.button) { color: #b55863; } @@ -1115,7 +1085,7 @@ a.button { width: 65.95745%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .main-content.with-right-sidebar { width: 65.95745%; float: left; @@ -1136,13 +1106,13 @@ a.button { width: 31.91489%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .left-sidebar .small-widget, .left-sidebar .medium-widget, .left-sidebar .triple-widget, .right-sidebar .small-widget, .right-sidebar .medium-widget, .right-sidebar .triple-widget { float: none; width: auto; margin-right: auto; - #margin-left: auto; } + *margin-left: auto; } /* Widgets in main content */ .row { @@ -1216,15 +1186,15 @@ a.button { .listing-company-category:before { content: "Category: "; - color: #666; } + color: #666666; } .listing-job-title:before { content: "Title: "; - color: #666; } + color: #666666; } .listing-job-type:before { content: "Looking for: "; - color: #666; } + color: #666666; } .release-number, .release-date, @@ -1277,8 +1247,8 @@ a.button { overflow: hidden; *zoom: 1; } .previous-next a { - -moz-box-sizing: border-box; -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; } .previous-next .prev-button { width: 48.93617%; @@ -1288,7 +1258,7 @@ a.button { width: 48.93617%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } /* Footer */ .main-footer .jump-link { @@ -1328,7 +1298,7 @@ a.button { margin: 0.875em 0; } .search-field { - background: #fff; + background: white; padding: .4em .5em .3em; margin-right: .5em; width: 11em; } @@ -1374,37 +1344,38 @@ a.button { right: 2.6em; white-space: nowrap; padding: .4em .75em .35em; - color: #999; + color: #999999; background-color: #1f1f1f; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF333333', endColorstr='#FF1F1F1F'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMzMzMzMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzFmMWYxZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #333333), color-stop(90%, #1f1f1f)); - background-image: -moz-linear-gradient(#333333 10%, #1f1f1f 90%); background-image: -webkit-linear-gradient(#333333 10%, #1f1f1f 90%); + background-image: -moz-linear-gradient(#333333 10%, #1f1f1f 90%); + background-image: -o-linear-gradient(#333333 10%, #1f1f1f 90%); background-image: linear-gradient(#333333 10%, #1f1f1f 90%); - border-top: 1px solid #444; - border-right: 1px solid #444; - border-bottom: 1px solid #444; - border-left: 1px solid #444; - -moz-border-radius: 6px; + border-top: 1px solid #444444; + border-right: 1px solid #444444; + border-bottom: 1px solid #444444; + border-left: 1px solid #444444; -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; - -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); - -moz-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; - -o-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; -webkit-transition-delay: 0s, 0.25s; + -moz-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; + -o-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; } .flexslide .launch-shell .button:hover .message { opacity: 1; top: 0; + -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; -moz-transition: opacity 0.25s ease-in-out, top 0s linear; -o-transition: opacity 0.25s ease-in-out, top 0s linear; - -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; transition: opacity 0.25s ease-in-out, top 0s linear; } .introduction { @@ -1433,24 +1404,24 @@ a.button { padding-top: 1em; } .about-banner { - background: 120% 0 no-repeat url('../img/landing-about.png?1576869008') transparent; + background: 120% 0 no-repeat url('../img/landing-about.png?1646853871') transparent; min-height: 345px; padding-bottom: 3.5em; margin-bottom: -2.5em; } .download-for-current-os { - background: 130% 0 no-repeat url('../img/landing-downloads.png?1576869008') transparent; + background: 130% 0 no-repeat url('../img/landing-downloads.png?1646853871') transparent; min-height: 345px; padding-bottom: 4em; margin-bottom: -3em; } .documentation-banner { - background: 130% 0 no-repeat url('../img/landing-docs.png?1576869008') transparent; + background: 130% 0 no-repeat url('../img/landing-docs.png?1646853871') transparent; padding-bottom: 1em; } .community-banner { text-align: left; - background: 110% 0 no-repeat url('../img/landing-community.png?1576869008') transparent; + background: 110% 0 no-repeat url('../img/landing-community.png?1646853871') transparent; min-height: 345px; padding-bottom: 2em; margin-bottom: -1.25em; } @@ -1504,7 +1475,7 @@ a.button { width: 74.46809%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .main-content.with-right-sidebar { width: 74.46809%; float: left; @@ -1521,7 +1492,7 @@ a.button { width: 23.40426%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } .featured-success-story { /*blockquote*/ } @@ -1554,7 +1525,7 @@ a.button { right: 1em; width: 210px; height: 210px; - background: top left no-repeat url('../img/python-logo-large.png?1576869008') transparent; } + background: top left no-repeat url('../img/python-logo-large.png?1646853871') transparent; } .psf-widget .widget-title, .psf-widget p, .python-needs-you-widget .widget-title, .python-needs-you-widget p { margin-right: 34.04255%; } @@ -1586,7 +1557,7 @@ a.button { width: 48.93617%; float: right; margin-right: 0; - #margin-left: -20px; + *margin-left: -20px; text-align: right; clear: none; } .list-recent-jobs .listing-actions { @@ -1602,14 +1573,14 @@ a.button { float: left; margin-right: 2.12766%; } .listing-company .listing-company-name a:hover:after, .listing-company .listing-company-name a:focus:after { - color: #666; + color: #666666; content: " View Details"; font-size: .75em; } .listing-company .listing-location { width: 40.42553%; float: right; margin-right: 0; - #margin-left: -20px; + *margin-left: -20px; text-align: right; } .job-meta { @@ -1622,7 +1593,7 @@ a.button { width: 48.93617%; float: right; margin-right: 0; - #margin-left: -20px; } + *margin-left: -20px; } /* Forms that are wide enough to have labels and input fields side by side */ .wide-form ul { @@ -1725,20 +1696,20 @@ a.button { .no-touch .main-navigation .subnav { min-width: 100%; display: none; + -webkit-transition: all 0s ease; -moz-transition: all 0s ease; -o-transition: all 0s ease; - -webkit-transition: all 0s ease; transition: all 0s ease; } .touch .main-navigation .subnav { top: 120%; display: none; opacity: 0; + -webkit-transition: opacity 0.25s ease-in-out; -moz-transition: opacity 0.25s ease-in-out; -o-transition: opacity 0.25s ease-in-out; - -webkit-transition: opacity 0.25s ease-in-out; transition: opacity 0.25s ease-in-out; - -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); } .touch .main-navigation .subnav:before { position: absolute; @@ -1753,16 +1724,16 @@ a.button { .no-touch .main-navigation .element-1:hover .subnav, .no-touch .main-navigation .element-1:focus .subnav, .no-touch .main-navigation .element-2:hover .subnav, .no-touch .main-navigation .element-2:focus .subnav, .no-touch .main-navigation .element-3:hover .subnav, .no-touch .main-navigation .element-3:focus .subnav, .no-touch .main-navigation .element-4:hover .subnav, .no-touch .main-navigation .element-4:focus .subnav { left: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .no-touch .main-navigation .element-5:hover .subnav, .no-touch .main-navigation .element-5:focus .subnav, .no-touch .main-navigation .element-6:hover .subnav, .no-touch .main-navigation .element-6:focus .subnav, .no-touch .main-navigation .element-7:hover .subnav, .no-touch .main-navigation .element-7:focus .subnav, .no-touch .main-navigation .element-8:hover .subnav, .no-touch .main-navigation .element-8:focus .subnav, .no-touch .main-navigation .last:hover .subnav, .no-touch .main-navigation .last:focus .subnav { right: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .touch .main-navigation .element-1, .touch .main-navigation .element-2, .touch .main-navigation .element-3, .touch .main-navigation .element-4 { /* Position the pointer element */ } @@ -1791,11 +1762,13 @@ a.button { display: block; text-align: center; font-size: 1.125em; - -moz-border-radius: 8px; -webkit-border-radius: 8px; + -moz-border-radius: 8px; + -ms-border-radius: 8px; + -o-border-radius: 8px; border-radius: 8px; - -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); } .no-touch .main-navigation .menu { text-align: center; } @@ -1883,7 +1856,7 @@ a.button { /*.subnav li*/ .super-navigation { - color: #666; + color: #666666; position: absolute; /* relative to the containing LI */ top: 0; @@ -1910,7 +1883,7 @@ a.button { line-height: 1.25em; margin-bottom: 0; } .super-navigation p.date-posted { - color: #666; + color: #666666; font-size: 0.625em !important; font-style: italic; } .super-navigation p.excert { @@ -1982,7 +1955,7 @@ a.button { .text { /* Make the intro/first paragraphs slightly larger? */ } .text > p:first-of-type { - color: #666; + color: #666666; font-size: 1.125em; line-height: 1.6875; margin-bottom: 1.25em; } @@ -2112,7 +2085,7 @@ a.button { .home-slideshow .flex-direction-nav .flex-prev, .home-slideshow .flex-direction-nav .flex-next { top: 40%; font-size: 1.5em; - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); opacity: 1; } .home-slideshow .flex-direction-nav .flex-prev { left: -.75em; } @@ -2131,5 +2104,3 @@ a.button { .site-headline a, .site-headline a .python-logo { width: 290px; height: 82px; } - -/*# sourceMappingURL=no-mq.css.map */ diff --git a/static/sass/style.css b/static/sass/style.css index a58863817..c3af6444f 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -115,14 +115,13 @@ background-color: #2b5b84; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF1E415E', endColorstr='#FF2B5B84'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMxZTQxNWUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJiNWI4NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #1e415e), color-stop(90%, #2b5b84)); - background-image: -moz-linear-gradient(#1e415e 10%, #2b5b84 90%); background-image: -webkit-linear-gradient(#1e415e 10%, #2b5b84 90%); + background-image: -moz-linear-gradient(#1e415e 10%, #2b5b84 90%); + background-image: -o-linear-gradient(#1e415e 10%, #2b5b84 90%); background-image: linear-gradient(#1e415e 10%, #2b5b84 90%); - -moz-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), inset 0 0 20px rgba(0, 0, 0, 0.03); -webkit-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), inset 0 0 20px rgba(0, 0, 0, 0.03); + -moz-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), inset 0 0 20px rgba(0, 0, 0, 0.03); box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), inset 0 0 20px rgba(0, 0, 0, 0.03); } .psf-widget, .python-needs-you-widget { @@ -138,14 +137,13 @@ background-color: #d8dbde; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFE6E8EA', endColorstr='#FFD8DBDE'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlNmU4ZWEiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q4ZGJkZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #e6e8ea), color-stop(90%, #d8dbde)); - background-image: -moz-linear-gradient(#e6e8ea 10%, #d8dbde 90%); background-image: -webkit-linear-gradient(#e6e8ea 10%, #d8dbde 90%); + background-image: -moz-linear-gradient(#e6e8ea 10%, #d8dbde 90%); + background-image: -o-linear-gradient(#e6e8ea 10%, #d8dbde 90%); background-image: linear-gradient(#e6e8ea 10%, #d8dbde 90%); - -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); + -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); } .pep-widget, .most-recent-events .more-by-location, .user-profile-controls div.section-links ul li { @@ -162,14 +160,13 @@ background-color: #ffdd6c; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFE89F', endColorstr='#FFFFDD6C'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmU4OWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZGQ2YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffe89f), color-stop(90%, #ffdd6c)); - background-image: -moz-linear-gradient(#ffe89f 10%, #ffdd6c 90%); background-image: -webkit-linear-gradient(#ffe89f 10%, #ffdd6c 90%); + background-image: -moz-linear-gradient(#ffe89f 10%, #ffdd6c 90%); + background-image: -o-linear-gradient(#ffe89f 10%, #ffdd6c 90%); background-image: linear-gradient(#ffe89f 10%, #ffdd6c 90%); - -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); } .single-event-date { @@ -185,7 +182,7 @@ /* Buttons */ .psf-widget .button, .python-needs-you-widget .button, .donate-button, .header-banner .button, .header-banner a.button, .user-profile-controls div.section span, a.delete, form.deletion-form button[type="submit"], button[type=submit], .search-button, #dive-into-python .flex-control-paging a, .text form button, .text form input[type=submit], .sidebar-widget form button, -.sidebar-widget form input[type=submit], input[type=submit], input[type=reset], button, a.button, .button { +.sidebar-widget form input[type=submit], #update-sponsorship-assets .btn, input[type=submit], input[type=reset], button, a.button, .button { cursor: pointer; color: #4d4d4d !important; font-weight: normal; @@ -197,130 +194,124 @@ background-color: #cccccc; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFD9D9D9', endColorstr='#FFCCCCCC'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkOWQ5ZDkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2NjY2NjYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #d9d9d9), color-stop(90%, #cccccc)); - background-image: -moz-linear-gradient(#d9d9d9 10%, #cccccc 90%); background-image: -webkit-linear-gradient(#d9d9d9 10%, #cccccc 90%); + background-image: -moz-linear-gradient(#d9d9d9 10%, #cccccc 90%); + background-image: -o-linear-gradient(#d9d9d9 10%, #cccccc 90%); background-image: linear-gradient(#d9d9d9 10%, #cccccc 90%); border-top: 1px solid #caccce; border-right: 1px solid #caccce; - border-bottom: 1px solid #999; + border-bottom: 1px solid #999999; border-left: 1px solid #caccce; - -moz-border-radius: 6px; -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; - -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), inset 0 0 5px rgba(255, 255, 255, 0.5); -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), inset 0 0 5px rgba(255, 255, 255, 0.5); + -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), inset 0 0 5px rgba(255, 255, 255, 0.5); box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), inset 0 0 5px rgba(255, 255, 255, 0.5); } - .donate-button:hover, .header-banner .button:hover, .header-banner a.button:hover, .user-profile-controls div.section span:hover, a.delete:hover, form.deletion-form button[type="submit"]:hover, .search-button:hover, #dive-into-python .flex-control-paging a:hover, .text form button:hover, .text form input[type=submit]:hover, + .donate-button:hover, .user-profile-controls div.section span:hover, a.delete:hover, form.deletion-form button[type="submit"]:hover, .search-button:hover, #dive-into-python .flex-control-paging a:hover, .text form button:hover, .text form input[type=submit]:hover, .sidebar-widget form button:hover, - .sidebar-widget form input[type=submit]:hover, input[type=submit]:hover, input[type=reset]:hover, button:hover, .button:hover, .donate-button:focus, .header-banner .button:focus, .header-banner a.button:focus, .user-profile-controls div.section span:focus, a.delete:focus, form.deletion-form button[type="submit"]:focus, .search-button:focus, #dive-into-python .flex-control-paging a:focus, .text form button:focus, .text form input[type=submit]:focus, + .sidebar-widget form input[type=submit]:hover, #update-sponsorship-assets .btn:hover, input[type=submit]:hover, input[type=reset]:hover, button:hover, .button:hover, .donate-button:focus, .user-profile-controls div.section span:focus, a.delete:focus, form.deletion-form button[type="submit"]:focus, .search-button:focus, #dive-into-python .flex-control-paging a:focus, .text form button:focus, .text form input[type=submit]:focus, .sidebar-widget form button:focus, - .sidebar-widget form input[type=submit]:focus, input[type=submit]:focus, input[type=reset]:focus, button:focus, .button:focus, .donate-button:active, .header-banner .button:active, .header-banner a.button:active, .user-profile-controls div.section span:active, a.delete:active, form.deletion-form button[type="submit"]:active, .search-button:active, #dive-into-python .flex-control-paging a:active, .text form button:active, .text form input[type=submit]:active, + .sidebar-widget form input[type=submit]:focus, #update-sponsorship-assets .btn:focus, input[type=submit]:focus, input[type=reset]:focus, button:focus, .button:focus, .donate-button:active, .user-profile-controls div.section span:active, a.delete:active, form.deletion-form button[type="submit"]:active, .search-button:active, #dive-into-python .flex-control-paging a:active, .text form button:active, .text form input[type=submit]:active, .sidebar-widget form button:active, - .sidebar-widget form input[type=submit]:active, input[type=submit]:active, input[type=reset]:active, button:active, .button:active { + .sidebar-widget form input[type=submit]:active, #update-sponsorship-assets .btn:active, input[type=submit]:active, input[type=reset]:active, button:active, .button:active { color: #1a1a1a !important; background-color: #d9d9d9; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFE6E6E6', endColorstr='#FFD9D9D9'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlNmU2ZTYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q5ZDlkOSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #e6e6e6), color-stop(90%, #d9d9d9)); - background-image: -moz-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); background-image: -webkit-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); + background-image: -moz-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); + background-image: -o-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); background-image: linear-gradient(#e6e6e6 10%, #d9d9d9 90%); } .psf-widget .button, .python-needs-you-widget .button, .donate-button, .header-banner .button, .header-banner a.button, .user-profile-controls div.section span { background-color: #ffd343; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFDF76', endColorstr='#FFFFD343'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmRmNzYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZDM0MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffdf76), color-stop(90%, #ffd343)); - background-image: -moz-linear-gradient(#ffdf76 10%, #ffd343 90%); background-image: -webkit-linear-gradient(#ffdf76 10%, #ffd343 90%); + background-image: -moz-linear-gradient(#ffdf76 10%, #ffd343 90%); + background-image: -o-linear-gradient(#ffdf76 10%, #ffd343 90%); background-image: linear-gradient(#ffdf76 10%, #ffd343 90%); border-top: 1px solid #dca900; border-right: 1px solid #dca900; border-bottom: 1px solid #dca900; border-left: 1px solid #dca900; } - .psf-widget .button:hover, .python-needs-you-widget .button:hover, .donate-button:hover, .header-banner .button:hover, .header-banner a.button:hover, .user-profile-controls div.section span:hover, .psf-widget .button:active, .python-needs-you-widget .button:active, .donate-button:active, .header-banner .button:active, .header-banner a.button:active, .user-profile-controls div.section span:active { + .psf-widget .button:hover, .python-needs-you-widget .button:hover, .donate-button:hover, .header-banner .button:hover, .user-profile-controls div.section span:hover, .psf-widget .button:active, .python-needs-you-widget .button:active, .donate-button:active, .header-banner .button:active, .user-profile-controls div.section span:active { background-color: inherit; background-color: #ffd343; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFEBA9', endColorstr='#FFFFD343'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmViYTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZDM0MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffeba9), color-stop(90%, #ffd343)); - background-image: -moz-linear-gradient(#ffeba9 10%, #ffd343 90%); background-image: -webkit-linear-gradient(#ffeba9 10%, #ffd343 90%); + background-image: -moz-linear-gradient(#ffeba9 10%, #ffd343 90%); + background-image: -o-linear-gradient(#ffeba9 10%, #ffd343 90%); background-image: linear-gradient(#ffeba9 10%, #ffd343 90%); } a.delete, form.deletion-form button[type="submit"] { background-color: #b55863; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFC57B84', endColorstr='#FFB55863'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNjNTdiODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2I1NTg2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #c57b84), color-stop(90%, #b55863)); - background-image: -moz-linear-gradient(#c57b84 10%, #b55863 90%); background-image: -webkit-linear-gradient(#c57b84 10%, #b55863 90%); + background-image: -moz-linear-gradient(#c57b84 10%, #b55863 90%); + background-image: -o-linear-gradient(#c57b84 10%, #b55863 90%); background-image: linear-gradient(#c57b84 10%, #b55863 90%); border-top: 1px solid #74333b; border-right: 1px solid #74333b; border-bottom: 1px solid #74333b; border-left: 1px solid #74333b; - color: #fff !important; } + color: white !important; } a.delete:hover, form.deletion-form button[type="submit"]:hover, a.delete:active, form.deletion-form button[type="submit"]:active { background-color: inherit; - color: #fff !important; + color: white !important; background-color: #b55863; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFD49FA5', endColorstr='#FFB55863'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkNDlmYTUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2I1NTg2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #d49fa5), color-stop(90%, #b55863)); - background-image: -moz-linear-gradient(#d49fa5 10%, #b55863 90%); background-image: -webkit-linear-gradient(#d49fa5 10%, #b55863 90%); + background-image: -moz-linear-gradient(#d49fa5 10%, #b55863 90%); + background-image: -o-linear-gradient(#d49fa5 10%, #b55863 90%); background-image: linear-gradient(#d49fa5 10%, #b55863 90%); } button[type=submit], .search-button, #dive-into-python .flex-control-paging a, .text form button, .text form input[type=submit], .sidebar-widget form button, -.sidebar-widget form input[type=submit] { +.sidebar-widget form input[type=submit], #update-sponsorship-assets .btn { color: #e6e8ea !important; text-shadow: none; background-color: #2b5b84; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF3776AB', endColorstr='#FF2B5B84'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzNzc2YWIiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJiNWI4NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #3776ab), color-stop(90%, #2b5b84)); - background-image: -moz-linear-gradient(#3776ab 10%, #2b5b84 90%); background-image: -webkit-linear-gradient(#3776ab 10%, #2b5b84 90%); + background-image: -moz-linear-gradient(#3776ab 10%, #2b5b84 90%); + background-image: -o-linear-gradient(#3776ab 10%, #2b5b84 90%); background-image: linear-gradient(#3776ab 10%, #2b5b84 90%); border-top: 1px solid #3d83be; border-right: 1px solid #3776ab; border-bottom: 1px solid #3776ab; border-left: 1px solid #3d83be; - -moz-box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); -webkit-box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); + -moz-box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); } button[type=submit]:hover, .search-button:hover, #dive-into-python .flex-control-paging a:hover, .text form button:hover, .text form input[type=submit]:hover, .sidebar-widget form button:hover, - .sidebar-widget form input[type=submit]:hover, button[type=submit]:active, .search-button:active, #dive-into-python .flex-control-paging a:active, .text form button:active, .text form input[type=submit]:active, + .sidebar-widget form input[type=submit]:hover, #update-sponsorship-assets .btn:hover, button[type=submit]:active, .search-button:active, #dive-into-python .flex-control-paging a:active, .text form button:active, .text form input[type=submit]:active, .sidebar-widget form button:active, - .sidebar-widget form input[type=submit]:active { + .sidebar-widget form input[type=submit]:active, #update-sponsorship-assets .btn:active { background: inherit; color: #f2f4f6 !important; background-color: #244e71; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF316998', endColorstr='#FF244E71'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMTY5OTgiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzI0NGU3MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #316998), color-stop(90%, #244e71)); - background-image: -moz-linear-gradient(#316998 10%, #244e71 90%); background-image: -webkit-linear-gradient(#316998 10%, #244e71 90%); + background-image: -moz-linear-gradient(#316998 10%, #244e71 90%); + background-image: -o-linear-gradient(#316998 10%, #244e71 90%); background-image: linear-gradient(#316998 10%, #244e71 90%); } .header-banner a:not(.button), .header-banner a:not(.readmore), .text a:not(.button), @@ -348,7 +339,7 @@ button[type=submit], .search-button, #dive-into-python .flex-control-paging a, . .pagination a { /* Used in the pagination UL anchors, and in the Previous Next pattern */ display: block; - color: #999; + color: #999999; padding: .5em .75em .4em; border: 1px solid #caccce; background-color: transparent; } @@ -405,7 +396,7 @@ form, .header-banner, .success-stories-widget .quote-from { .slides, .flex-control-nav, .flex-direction-nav {margin: 0; padding: 0; list-style: none;} */ -/* FlexSlider Necessary Styles + /* FlexSlider Necessary Styles .flexslider {margin: 0; padding: 0;} .flexslider .slides > li {display: none; -webkit-backface-visibility: hidden;} /* Hide the slides before the JS is loaded. Avoids image jumping .flexslider .slides img {width: 100%; display: block;} @@ -491,8 +482,8 @@ q q:after { content: "’"; } ins { - background-color: #ddd; - color: #222; + background-color: #dddddd; + color: #222222; text-decoration: none; } mark { @@ -529,7 +520,7 @@ hr { input, button, select { display: inline-block; vertical-align: middle; - cursor: pointer; } + cursor: text; } html { font-size: 100%; @@ -674,6 +665,7 @@ abbr.truncation { /* Stupid IE: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/ */ @-ms-viewport { width: device-width; } + canvas { -ms-touch-action: double-tap-zoom; } @@ -712,20 +704,20 @@ html { font: normal 100%/1.625 SourceSansProRegular, Arial, sans-serif; } body { - color: #444; - background-color: #fff; + color: #444444; + background-color: white; /* Label the body with our media query parameters. Then check with JS to coordinate @media changes */ } body:after { content: 'small'; display: none; } body, input, textarea, select, button { - color: #444; + color: #444444; font: normal 100%/1.625 SourceSansProRegular, Arial, sans-serif; } * { - -moz-box-sizing: border-box; -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; } a, a:active, a:visited, a:hover, a:visited:hover { @@ -737,7 +729,7 @@ a:hover, a:focus { /*modernizr*/ .touch a[href^="tel:"] { - border-bottom: 1px dotted #444; } + border-bottom: 1px dotted #444444; } a img { display: block; @@ -789,34 +781,34 @@ h1, .alpha { margin-bottom: 0.4375em; } h2, .beta { - color: #999; + color: #999999; font-family: SourceSansProRegular, Arial, sans-serif; font-size: 1.5em; margin-top: 1.3125em; margin-bottom: 0.32813em; } h3, .chi { - color: #222; + color: #222222; font-size: 1.3125em; margin-top: 1.75em; margin-bottom: 0.4375em; } h4, .delta { - color: #222; + color: #222222; font-family: SourceSansProBold, Arial, sans-serif; font-size: 1.125em; margin-top: 1.3125em; margin-bottom: 0.4375em; } h5, .epsilon { - color: #222; + color: #222222; font-family: SourceSansProBold, Arial, sans-serif; text-transform: uppercase; letter-spacing: 0.0625em; margin-top: 1.75em; } h6, .gamma { - color: #222; + color: #222222; font-family: SourceSansProBold, Arial, sans-serif; margin-top: 1.75em; } @@ -867,7 +859,7 @@ dl { label { display: block; - color: #999; + color: #999999; font-weight: bold; margin-top: 0.875em; margin-top: 0.21875em; } @@ -878,8 +870,10 @@ input, textarea { width: 100%; padding: .65em; border: 1px solid #caccce; - -moz-border-radius: 6px; -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; } input, textarea, select { @@ -896,22 +890,22 @@ input[type=radio] { input { /*modernizr*/ } .no-touch input:focus { - -moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); } input[required=required] { border-color: #b55863; } input[required=required]:focus { - -moz-box-shadow: 0px 0px 10px rgba(255, 0, 0, 0.5); -webkit-box-shadow: 0px 0px 10px rgba(255, 0, 0, 0.5); + -moz-box-shadow: 0px 0px 10px rgba(255, 0, 0, 0.5); box-shadow: 0px 0px 10px rgba(255, 0, 0, 0.5); } ::-webkit-input-placeholder { - color: #999; + color: #999999; font-style: italic; } input:-moz-placeholder { - color: #999; + color: #999999; font-style: italic; } /* Not a mistake... I repeat a.button and .button so I do not need to add !important to the color declaration */ @@ -919,29 +913,27 @@ input[type=submit], input[type=reset], button, a.button, .button { display: block; } input[type=reset], button.secondaryAction[type=submit] { - background-color: #999; + background-color: #999999; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFB3B3B3', endColorstr='#FF999999'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNiM2IzYjMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzk5OTk5OSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #b3b3b3), color-stop(90%, #999999)); - background-image: -moz-linear-gradient(#b3b3b3 10%, #999999 90%); background-image: -webkit-linear-gradient(#b3b3b3 10%, #999999 90%); + background-image: -moz-linear-gradient(#b3b3b3 10%, #999999 90%); + background-image: -o-linear-gradient(#b3b3b3 10%, #999999 90%); background-image: linear-gradient(#b3b3b3 10%, #999999 90%); border-top: 1px solid #caccce; - border-right: 1px solid #999; + border-right: 1px solid #999999; border-bottom: 1px solid gray; - border-left: 1px solid #999; } + border-left: 1px solid #999999; } input[type=reset]:hover, input[type=reset]:focus, input[type=reset]:active, button.secondaryAction[type=submit]:hover, button.secondaryAction[type=submit]:focus, button.secondaryAction[type=submit]:active { - color: #fff; + color: white; background-color: #b3b3b3; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF999999', endColorstr='#FFB3B3B3'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5OTk5OTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2IzYjNiMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #999999), color-stop(90%, #b3b3b3)); - background-image: -moz-linear-gradient(#999999 10%, #b3b3b3 90%); background-image: -webkit-linear-gradient(#999999 10%, #b3b3b3 90%); + background-image: -moz-linear-gradient(#999999 10%, #b3b3b3 90%); + background-image: -o-linear-gradient(#999999 10%, #b3b3b3 90%); background-image: linear-gradient(#999999 10%, #b3b3b3 90%); } /* Reset for a special case */ @@ -1010,15 +1002,14 @@ h2.not-column { /* ! ===== MAJOR PAGE ELEMENTS ===== */ .top-bar a:hover, .top-bar a:focus, .python .top-bar .python-meta a, .psf .top-bar .psf-meta a, .docs .top-bar .docs-meta a, .pypi .top-bar .pypi-meta a, .jobs .top-bar .jobs-meta a, .shop .top-bar .shop-meta a { - color: #fff; + color: white; background-color: #1f2a32; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF13191E', endColorstr='#FF1F2A32'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMxMzE5MWUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzFmMmEzMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #13191e), color-stop(90%, #1f2a32)); - background-image: -moz-linear-gradient(#13191e 10%, #1f2a32 90%); background-image: -webkit-linear-gradient(#13191e 10%, #1f2a32 90%); + background-image: -moz-linear-gradient(#13191e 10%, #1f2a32 90%); + background-image: -o-linear-gradient(#13191e 10%, #1f2a32 90%); background-image: linear-gradient(#13191e 10%, #1f2a32 90%); } .top-bar a:hover:before, .top-bar a:focus:before, .python .top-bar .python-meta a:before, .psf .top-bar .psf-meta a:before, .docs .top-bar .docs-meta a:before, .pypi .top-bar .pypi-meta a:before, .jobs .top-bar .jobs-meta a:before, .shop .top-bar .shop-meta a:before { left: 50%; } @@ -1030,7 +1021,7 @@ h2.not-column { .top-bar a { position: relative; display: block; - color: #999; + color: #999999; background: transparent; text-align: center; padding: .5em .75em .4em; @@ -1089,7 +1080,7 @@ h2.not-column { /*h1*/ .site-headline { - color: #fff; + color: white; margin: 0.15em auto 0.2em; } .site-headline a { display: block; @@ -1113,14 +1104,16 @@ h2.not-column { .options-bar { width: 100%; - color: #bbb; + color: #bbbbbb; margin-bottom: 1.3125em; border-top: 1px solid #2d3e4d; border-bottom: 1px solid #070a0c; background-color: #1e2933; line-height: 1em; - -moz-border-radius: 6px; -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; } .options-bar form { padding: 0.35em 0.2em 0.3em; } @@ -1172,9 +1165,9 @@ input#s, border-right: 1px solid #070a0c; } #site-map-link { - color: #bbb; } + color: #bbbbbb; } #site-map-link:hover, #site-map-link:focus { - color: #fff; } + color: white; } .no-touch #site-map-link { display: none; } @@ -1197,28 +1190,30 @@ input#s, .search-field { width: 4.5em; margin-bottom: 0; - color: #bbb; + color: #bbbbbb; background-color: transparent; border: none; margin: .125em 0; padding: .4em 0 .3em; - -moz-border-radius: 0px; -webkit-border-radius: 0px; + -moz-border-radius: 0px; + -ms-border-radius: 0px; + -o-border-radius: 0px; border-radius: 0px; } .search-field::-webkit-input-placeholder { - color: #bbb; + color: #bbbbbb; font-style: normal; } .search-field:-moz-placeholder { - color: #bbb; + color: #bbbbbb; font-style: normal; } .search-field:focus { - background-color: #fff; - color: #444; + background-color: white; + color: #444444; padding: .4em .5em .3em; /* removed this line because it was making the height fluctuate on focus: @include pe-border( $color-top: darken( $darkerblue, 12% ), $color-bottom: lighten( $darkerblue, 8% ) ); */ } .search-field:blur { - color: #bbb; } + color: #bbbbbb; } .search-button { margin-right: 0.2em; @@ -1312,25 +1307,15 @@ input#s, .account-signin .sidebar-widget form label + ul, .sidebar-widget form .account-signin label + ul { *zoom: 1; } - .adjust-font-size .menu:after, .adjust-font-size form ul:after, form .adjust-font-size ul:after, .adjust-font-size .errorlist:after, .adjust-font-size .text form label + ul:after, .text form .adjust-font-size label + ul:after, - .adjust-font-size .sidebar-widget form label + ul:after, - .sidebar-widget form .adjust-font-size label + ul:after, + .adjust-font-size .menu:after, .adjust-font-size form ul:after, form .adjust-font-size ul:after, .adjust-font-size .errorlist:after, .winkwink-nudgenudge .menu:after, .winkwink-nudgenudge form ul:after, form .winkwink-nudgenudge ul:after, .winkwink-nudgenudge .errorlist:after, - .winkwink-nudgenudge .text form label + ul:after, - .text form .winkwink-nudgenudge label + ul:after, - .winkwink-nudgenudge .sidebar-widget form label + ul:after, - .sidebar-widget form .winkwink-nudgenudge label + ul:after, .account-signin .menu:after, .account-signin form ul:after, form .account-signin ul:after, - .account-signin .errorlist:after, - .account-signin .text form label + ul:after, - .text form .account-signin label + ul:after, - .account-signin .sidebar-widget form label + ul:after, - .sidebar-widget form .account-signin label + ul:after { + .account-signin .errorlist:after { content: ""; display: table; clear: both; } @@ -1351,9 +1336,9 @@ input#s, .account-signin .subnav { min-width: 100%; display: none; + -webkit-transition: all 0s ease; -moz-transition: all 0s ease; -o-transition: all 0s ease; - -webkit-transition: all 0s ease; transition: all 0s ease; } .touch .adjust-font-size .subnav, .touch .winkwink-nudgenudge .subnav, .touch @@ -1361,12 +1346,12 @@ input#s, top: 120%; display: none; opacity: 0; + -webkit-transition: opacity 0.25s ease-in-out; -moz-transition: opacity 0.25s ease-in-out; -o-transition: opacity 0.25s ease-in-out; - -webkit-transition: opacity 0.25s ease-in-out; transition: opacity 0.25s ease-in-out; - -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); } .touch .adjust-font-size .subnav:before, .touch .winkwink-nudgenudge .subnav:before, .touch @@ -1399,9 +1384,9 @@ input#s, .account-signin .element-4:focus .subnav { left: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .no-touch .adjust-font-size .element-5:hover .subnav, .no-touch .adjust-font-size .element-5:focus .subnav, .no-touch .adjust-font-size .element-6:hover .subnav, .no-touch .adjust-font-size .element-6:focus .subnav, .no-touch .adjust-font-size .element-7:hover .subnav, .no-touch .adjust-font-size .element-7:focus .subnav, .no-touch .adjust-font-size .element-8:hover .subnav, .no-touch .adjust-font-size .element-8:focus .subnav, .no-touch .adjust-font-size .last:hover .subnav, .no-touch .adjust-font-size .last:focus .subnav, .no-touch .winkwink-nudgenudge .element-5:hover .subnav, .no-touch @@ -1426,9 +1411,9 @@ input#s, .account-signin .last:focus .subnav { right: 0; display: initial; + -webkit-transition-delay: 0.25s; -moz-transition-delay: 0.25s; -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; transition-delay: 0.25s; } .touch .adjust-font-size .element-1, .touch .adjust-font-size .element-2, .touch .adjust-font-size .element-3, .touch .adjust-font-size .element-4, .touch .winkwink-nudgenudge .element-1, .touch @@ -1531,7 +1516,7 @@ input#s, .adjust-font-size a, .winkwink-nudgenudge a, .account-signin a { - color: #bbb; + color: #bbbbbb; background-color: transparent; } .adjust-font-size .tier-1, .winkwink-nudgenudge .tier-1, @@ -1557,7 +1542,7 @@ input#s, .account-signin .subnav a:hover, .account-signin .subnav a:focus { color: #e6e8ea; - background-color: #999; } + background-color: #999999; } .touch .adjust-font-size .subnav a .tier-2, .touch .winkwink-nudgenudge .subnav a .tier-2, .touch .account-signin .subnav a .tier-2 { @@ -1571,12 +1556,12 @@ input#s, .winkwink-nudgenudge .subnav, .touch .account-signin .subnav { top: 135%; - border: 3px solid #666; } + border: 3px solid #666666; } .touch .adjust-font-size .subnav:before, .touch .winkwink-nudgenudge .subnav:before, .touch .account-signin .subnav:before { top: -1.6em; - border-color: transparent transparent #666 transparent; } + border-color: transparent transparent #666666 transparent; } .adjust-font-size :hover .subnav, .winkwink-nudgenudge :hover .subnav, .account-signin :hover .subnav { @@ -1622,8 +1607,8 @@ input#s, margin: 0 auto; max-width: 61.25em; background: #1e2933; - -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); } .slide-code, @@ -1637,9 +1622,9 @@ input#s, display: inline-block; color: #11a611; } .slide-code code .comment { - color: #666; } + color: #666666; } .slide-code code .output { - color: #ddd; } + color: #dddddd; } .js .launch-shell, .no-js .launch-shell { display: none; } @@ -1665,11 +1650,11 @@ input#s, filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70); opacity: 0.7; } #dive-into-python .flex-control-paging a:hover, #dive-into-python .flex-control-paging a:focus { - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); opacity: 1; } #dive-into-python .flex-control-paging .flex-active { color: #ffd343 !important; - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); opacity: 1; } .introduction { @@ -1686,7 +1671,7 @@ input#s, color: #ffd343; text-decoration: underline; } .introduction a:hover, .introduction a:focus, .introduction a:link:hover, .introduction a:link:focus, .introduction a:visited:hover, .introduction a:visited:focus { - color: #fff; } + color: white; } .introduction .breaker { display: none; } @@ -1717,11 +1702,10 @@ input#s, background-color: #f9f9f9; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFCFCFC', endColorstr='#FFF9F9F9'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmY2ZjZmMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #fcfcfc), color-stop(90%, #f9f9f9)); - background-image: -moz-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); background-image: -webkit-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); + background-image: -moz-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); + background-image: -o-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); background-image: linear-gradient(#fcfcfc 10%, #f9f9f9 90%); } .content-wrapper .container { padding: 0.25em; } @@ -1734,7 +1718,7 @@ input#s, padding-bottom: 1.75em; } .page-title { - color: #666; + color: #666666; word-spacing: .15em; font-size: 2em; } .fontface .page-title { @@ -1874,23 +1858,14 @@ input#s, color: $grey-light; margin-right: .5em; } */ } - .text nav a, .text .menu a, .text form ul a, form .text ul a, .text .errorlist a, .text form label + ul a, - .text .sidebar-widget form label + ul a, - .sidebar-widget form .text label + ul a, .text input[type=submit], .text input[type=reset], .text input[type=button], .text button, .text .prompt, .text .readmore:before, .text .give-me-more a:before, .give-me-more .text a:before, - .text nav a:hover, .text .menu a:hover, .text form ul a:hover, form .text ul a:hover, .text .errorlist a:hover, .text form label + ul a:hover, - .text .sidebar-widget form label + ul a:hover, - .sidebar-widget form .text label + ul a:hover, .text input[type=submit]:hover, .text input[type=reset]:hover, .text input[type=button]:hover, .text .prompt:hover, .text .readmore:hover:before, .text .give-me-more a:hover:before, .give-me-more .text a:hover:before, - .text nav a:focus, .text .menu a:focus, .text form ul a:focus, form .text ul a:focus, .text .errorlist a:focus, .text form label + ul a:focus, - .text .sidebar-widget form label + ul a:focus, - .sidebar-widget form .text label + ul a:focus, .text input[type=submit]:focus, .text input[type=reset]:focus, .text input[type=button]:focus, .text .prompt:focus, .text .readmore:focus:before, .text .give-me-more a:focus:before, .give-me-more .text a:focus:before, + .text nav a, .text .menu a, .text form ul a, form .text ul a, .text .errorlist a, .text input[type=submit], .text input[type=reset], .text input[type=button], .text button, .text .prompt, .text .readmore:before, .text .give-me-more a:before, .give-me-more .text a:before, + .text nav a:hover, .text .menu a:hover, .text form ul a:hover, form .text ul a:hover, .text .errorlist a:hover, .text input[type=submit]:hover, .text input[type=reset]:hover, .text input[type=button]:hover, .text .prompt:hover, .text .readmore:hover:before, .text .give-me-more a:hover:before, .give-me-more .text a:hover:before, + .text nav a:focus, .text .menu a:focus, .text form ul a:focus, form .text ul a:focus, .text .errorlist a:focus, .text input[type=submit]:focus, .text input[type=reset]:focus, .text input[type=button]:focus, .text .prompt:focus, .text .readmore:focus:before, .text .give-me-more a:focus:before, .give-me-more .text a:focus:before, .sidebar-widget nav a, .sidebar-widget .menu a, .sidebar-widget form ul a, form .sidebar-widget ul a, .sidebar-widget .errorlist a, - .sidebar-widget .text form label + ul a, - .text form .sidebar-widget label + ul a, - .sidebar-widget form label + ul a, .sidebar-widget input[type=submit], .sidebar-widget input[type=reset], .sidebar-widget input[type=button], @@ -1904,9 +1879,6 @@ input#s, .sidebar-widget form ul a:hover, form .sidebar-widget ul a:hover, .sidebar-widget .errorlist a:hover, - .sidebar-widget .text form label + ul a:hover, - .text form .sidebar-widget label + ul a:hover, - .sidebar-widget form label + ul a:hover, .sidebar-widget input[type=submit]:hover, .sidebar-widget input[type=reset]:hover, .sidebar-widget input[type=button]:hover, @@ -1919,9 +1891,6 @@ input#s, .sidebar-widget form ul a:focus, form .sidebar-widget ul a:focus, .sidebar-widget .errorlist a:focus, - .sidebar-widget .text form label + ul a:focus, - .text form .sidebar-widget label + ul a:focus, - .sidebar-widget form label + ul a:focus, .sidebar-widget input[type=submit]:focus, .sidebar-widget input[type=reset]:focus, .sidebar-widget input[type=button]:focus, @@ -1946,7 +1915,7 @@ input#s, letter-spacing: 0.125em; } .text var, .sidebar-widget var { - color: #222; + color: #222222; font-size: 104%; font-weight: 700; } .text code, .text kbd, .text samp, @@ -1971,46 +1940,50 @@ input#s, margin: 0 -.0625em; background: #e6e8ea; background: rgba(230, 232, 234, 0.5); - -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; -webkit-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; + -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; - -moz-border-radius: 6px; -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; } .text pre, .sidebar-widget pre { padding: .5em; border-left: 5px solid #11a611; background: #e6e8ea; - -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; -webkit-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; + -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; } .text pre code, .sidebar-widget pre code { display: block; padding: 0; margin: 0; - -moz-box-shadow: 0; -webkit-box-shadow: 0; + -moz-box-shadow: 0; box-shadow: 0; - -moz-border-radius: 0; -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; border-radius: 0; } .text s, .text strike, .text del, .sidebar-widget s, .sidebar-widget strike, .sidebar-widget del { - color: #999; } + color: #999999; } /* Prettier tables if authors use the correct elements */ table caption { caption-side: top; - color: #444; + color: #444444; font-size: 1.125em; text-align: left; margin-bottom: 1.75em; } table thead, table tfoot { - border-bottom: 1px solid #ddd; } + border-bottom: 1px solid #dddddd; } table tr { background-color: #f6f6f6; } table tr th { @@ -2019,11 +1992,11 @@ table tr:nth-of-type(even), table tr.even { background-color: #f0f0f0; } table th, table td { padding: .25em .5em .2em; - border-left: 2px solid #fff; } + border-left: 2px solid white; } table th:first-child, table td:first-child { border-left: none; } table tfoot { - border-top: 1px solid #ddd; } + border-top: 1px solid #dddddd; } .row-title { border-top: 5px solid #d4dbe1; @@ -2060,7 +2033,7 @@ table tfoot { .widget-title, .listing-company { - color: #444; + color: #444444; line-height: 1.25em; margin: 0 0 0.1em; font-family: Flux-Regular, SourceSansProRegular, Arial, sans-serif; @@ -2083,7 +2056,7 @@ table tfoot { margin-right: .25em; } .widget-title > span:before, .listing-company > span:before { - color: #999; } + color: #999999; } /* ! ===== Section Specific Widget Colorways ===== */ .python .small-widget, .python .download-list-widget, .python .active-release-list-widget, .python .most-recent-events, .python .triple-widget, .python .most-recent-posts, .python @@ -2152,23 +2125,24 @@ table tfoot { letter-spacing: 0.01em; } .success-stories-widget blockquote { - color: #666; - background-color: #ffe590; + color: #666666; + background-color: #ffe58f; padding: 0.7em 1em 0.875em; margin-bottom: 0.4375em; font-size: 1em; line-height: 1.75em; background-color: #ffdf76; *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFE590', endColorstr='#FFFFDF76'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmU1OTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZGY3NiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; - background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffe590), color-stop(90%, #ffdf76)); - background-image: -moz-linear-gradient(#ffe590 10%, #ffdf76 90%); - background-image: -webkit-linear-gradient(#ffe590 10%, #ffdf76 90%); - background-image: linear-gradient(#ffe590 10%, #ffdf76 90%); - -moz-border-radius: 6px; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFE58F', endColorstr='#FFFFDF76'); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffe58f), color-stop(90%, #ffdf76)); + background-image: -webkit-linear-gradient(#ffe58f 10%, #ffdf76 90%); + background-image: -moz-linear-gradient(#ffe58f 10%, #ffdf76 90%); + background-image: -o-linear-gradient(#ffe58f 10%, #ffdf76 90%); + background-image: linear-gradient(#ffe58f 10%, #ffdf76 90%); -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; } .success-stories-widget blockquote:after { position: absolute; @@ -2182,7 +2156,7 @@ table tfoot { bottom: -2.875em; border-top-color: #ffdf76; } .success-stories-widget blockquote a { - color: #666; } + color: #666666; } .success-stories-widget blockquote a:hover, .success-stories-widget blockquote a:focus, .success-stories-widget blockquote a:active { color: #3776ab; } .success-stories-widget .quote-from td { @@ -2237,9 +2211,9 @@ table tfoot { top: .25em; right: .25em; } .shrubbery .give-me-more a { - color: #999; } + color: #999999; } .shrubbery .give-me-more a:hover, .shrubbery .give-me-more a:active { - color: #666; } + color: #666666; } /* ! ===== PSF Board Meeting Minutes ===== */ .draft-preview { @@ -2262,7 +2236,7 @@ table tfoot { .pep-widget .widget-title a:hover, .pep-widget .widget-title a:active { color: #1f3b47; } .pep-widget .pep-number { - color: #666; + color: #666666; font-family: SourceSansProBold, Arial, sans-serif; display: inline-block; width: 3em; } @@ -2281,7 +2255,7 @@ table tfoot { border-bottom: 1px solid #e6eaee; padding: .6em .75em .5em; } .pep-list li a:hover, .pep-list li a:focus, .pep-list li a:active { - color: #222; + color: #222222; background-color: #fefefe; } .rss-link { @@ -2321,7 +2295,7 @@ table tfoot { display: inline-block; color: #3776ab; } .pep-index-list a:hover, .pep-index-list a:focus, .pep-index-list a:active { - color: #222; } + color: #222222; } .pep-type, .pep-num, .pep-title, .pep-owner { padding: .5em .5em .4em; @@ -2376,7 +2350,7 @@ table tfoot { /* ! ===== Success Stories landing page ===== */ .featured-success-story { padding: 1.3125em 0; - background: center -230px no-repeat url('../img/success-glow2.png?1576869008') transparent; + background: center -230px no-repeat url('../img/success-glow2.png?1646853871') transparent; /*blockquote*/ } .featured-success-story img { padding: 10px 30px; } @@ -2458,7 +2432,7 @@ p.quote-by-organization { .latest-blog-post .readmore, .featured-event .readmore { color: #ffd343; } .latest-blog-post .readmore:hover, .latest-blog-post .readmore:focus, .featured-event .readmore:hover, .featured-event .readmore:focus { - color: #fff; } + color: white; } .most-recent-posts li time { position: relative; } @@ -2470,10 +2444,10 @@ p.quote-by-organization { margin-top: 1.3125em; } .list-recent-events, .list-recent-posts { - border-top: 1px solid #ddd; } + border-top: 1px solid #dddddd; } .list-recent-events li, .list-recent-posts li { position: relative; - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #dddddd; padding: 0 0 0.75em; } .list-recent-events li .date-start, .list-recent-events li .date-end, @@ -2509,15 +2483,17 @@ p.quote-by-organization { /* ! ===== Community landing page ===== */ .community-success-stories blockquote { padding: 0; - color: #666; + color: #666666; line-height: 1.5; } .community-success-stories blockquote:before { content: ''; } .python-weekly { background-color: #f2f4f6; + -webkit-border-radius: 0 0 8px 8px; -moz-border-radius: 0 0 8px 8px; - -webkit-border-radius: 0; + -ms-border-radius: 0 0 8px 8px; + -o-border-radius: 0 0 8px 8px; border-radius: 0 0 8px 8px; padding: .75em 1em; } @@ -2547,7 +2523,7 @@ p.quote-by-organization { /*a*/ } .tag-wrapper .tag { white-space: nowrap; - color: #666; + color: #666666; font-size: 0.875em; vertical-align: baseline; padding: .2em .4em .1em; @@ -2555,7 +2531,7 @@ p.quote-by-organization { border-top: 1px solid #f2f4f6; border-bottom: 1px solid #caccce; } .tag-wrapper .tag:hover, .tag-wrapper .tag:focus { - color: #444; + color: #444444; background-color: #d0d4d7; border-top: 1px solid #dae0e5; border-bottom: 1px solid #b5b8ba; } @@ -2609,7 +2585,7 @@ p.quote-by-organization { zoom: 1; display: inline; } .pagination a:hover, .pagination a:focus { - color: #333; + color: #333333; background-color: #ffd343; } .pagination a.active { color: #e6e8ea; @@ -2649,7 +2625,7 @@ p.quote-by-organization { .previous-next .prev-button:not(.disabled):hover, .previous-next .prev-button:not(.disabled):focus, .previous-next .next-button:not(.disabled):hover, .previous-next .next-button:not(.disabled):focus { - color: #333; + color: #333333; background-color: #ffd343; } .previous-next .prev-button-text, .previous-next .next-button-text { @@ -2713,7 +2689,7 @@ p.quote-by-organization { .main-content .psf-widget a:not(.button), .main-content .python-needs-you-widget a:not(.button) { color: #ffd343; } .main-content .psf-widget a:not(.button):hover, .main-content .psf-widget a:not(.button):focus, .main-content .python-needs-you-widget a:not(.button):hover, .main-content .python-needs-you-widget a:not(.button):focus { - color: #fff1c3; } + color: #fff1c2; } .psf-widget .widget-title, .psf-widget .readmore, .psf-widget .readmore:before, .python-needs-you-widget .widget-title, .python-needs-you-widget .readmore, .python-needs-you-widget .readmore:before { color: #ffd343; } .psf-widget .widget-title:hover, .psf-widget .widget-title:focus, .psf-widget .readmore:hover, .psf-widget .readmore:focus, .psf-widget .readmore:before:hover, .psf-widget .readmore:before:focus, .python-needs-you-widget .widget-title:hover, .python-needs-you-widget .widget-title:focus, .python-needs-you-widget .readmore:hover, .python-needs-you-widget .readmore:focus, .python-needs-you-widget .readmore:before:hover, .python-needs-you-widget .readmore:before:focus { @@ -2730,15 +2706,17 @@ p.quote-by-organization { .user-feedback { padding: .75em 1em .65em; margin-bottom: 1.3125em; - -moz-border-radius: 6px; -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; border-radius: 6px; } .user-feedback p { margin-bottom: 0; } .user-feedback a { text-decoration: underline; } .user-feedback a:hover, .user-feedback a:focus { - color: #222; } + color: #222222; } /* A helpful tip */ .level-general { @@ -2784,7 +2762,7 @@ p.quote-by-organization { /*h2*/ .listing-company .listing-new { display: inline-block; - color: #fff; + color: white; background-color: #b55863; font-size: 0.58333em; text-transform: uppercase; @@ -2793,15 +2771,15 @@ p.quote-by-organization { margin-right: .25em; } .listing-company .listing-removed { display: inline-block; - color: #fff; - background-color: #666; + color: white; + background-color: #666666; font-size: 0.58333em; text-transform: uppercase; letter-spacing: .0625em; padding: .45em .5em 0; margin-right: .25em; } .listing-company .listing-location a { - color: #999; } + color: #999999; } .listing-company .listing-location a:hover, .listing-company .listing-location a:focus { color: #3776ab; } @@ -2863,11 +2841,10 @@ p.quote-by-organization { background-color: #3776ab; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FF2B5B84', endColorstr='#FF3776AB'); - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyYjViODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzM3NzZhYiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); - background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #2b5b84), color-stop(90%, #3776ab)); - background-image: -moz-linear-gradient(#2b5b84 10%, #3776ab 90%); background-image: -webkit-linear-gradient(#2b5b84 10%, #3776ab 90%); + background-image: -moz-linear-gradient(#2b5b84 10%, #3776ab 90%); + background-image: -o-linear-gradient(#2b5b84 10%, #3776ab 90%); background-image: linear-gradient(#2b5b84 10%, #3776ab 90%); } .psf-sidebar-widget .widget-title { color: #ffd343; @@ -2875,7 +2852,7 @@ p.quote-by-organization { .psf-sidebar-widget .widget-title a { color: #ffd343; } .psf-sidebar-widget .widget-title a:hover, .psf-sidebar-widget .widget-title a:focus { - color: #fff; } + color: white; } /* ! ===== User profile pages and sign up forms ===== */ .user-profile-controls { @@ -2926,15 +2903,15 @@ p.quote-by-organization { width: 25%; } .profile-label { - color: #999; } + color: #999999; } .psf-codeofconduct { font-size: 0.875em; padding: .5em 1em; margin-bottom: 1em; - background-color: #fff; - -moz-box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); + background-color: white; -webkit-box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); } /*p*/ @@ -2961,15 +2938,15 @@ p.quote-by-organization { .main-footer { clear: both; - color: #666; + color: #666666; background-color: #e6e8ea; border-top: 1px solid #d8dbde; } .main-footer .container { padding: 0 .75em .75em; } .main-footer a { - color: #666; } + color: #666666; } .main-footer a:hover, .main-footer a:focus { - color: #444; } + color: #444444; } .main-footer .jump-link { background-color: #e0e3e5; } .main-footer a.jump-link { @@ -2993,7 +2970,7 @@ p.quote-by-organization { margin-top: 0.875em; margin-bottom: 0em; } .sitemap .tier-1 > a:hover, .sitemap .tier-1 > a:focus { - color: #222; } + color: #222222; } .sitemap .subnav { font-size: 1em; margin-bottom: 0; @@ -3034,7 +3011,7 @@ p.quote-by-organization { border-bottom: 1px dotted #4f90c6; color: #75a8d3; } .copyright a:hover, .copyright a:focus { - color: #fff; + color: white; text-decoration: none; } #python-status-indicator { @@ -3174,14 +3151,14 @@ span.highlighted { color: #888; margin-left: .5em; } .flex-control-nav a:hover, .flex-control-nav a:focus { - color: #444; + color: #444444; background-color: #ccc; border-color: #bbb; } .text .flex-control-nav a { text-decoration: none; } .flex-control-nav .flex-active { - color: #666; - background-color: #fff; } + color: #666666; + background-color: white; } .touch .flex-control-nav a { /* Larger touch target */ padding: .5em .75em; } @@ -3204,9 +3181,9 @@ span.highlighted { font-size: 1.25em; font-weight: bold; line-height: 1em; - color: #999; } + color: #999999; } .flex-direction-nav .flex-prev:hover, .flex-direction-nav .flex-prev:focus, .flex-direction-nav .flex-next:hover, .flex-direction-nav .flex-next:focus { - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); opacity: 1; } .text .flex-direction-nav .flex-prev, .text .flex-direction-nav .flex-next { text-decoration: none; } @@ -3220,7 +3197,7 @@ span.highlighted { filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70); opacity: 0.7; } .home-slideshow .flex-direction-nav .flex-prev:hover, .home-slideshow .flex-direction-nav .flex-prev:focus, .home-slideshow .flex-direction-nav .flex-next:hover, .home-slideshow .flex-direction-nav .flex-next:focus { - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); opacity: 1; } .home-slideshow .flex-direction-nav .flex-prev { left: .75em; } @@ -3344,6 +3321,7 @@ span.highlighted { @page { margin: 0.5cm; } + p, h2, h3 { orphans: 3; widows: 3; } @@ -3376,11 +3354,11 @@ span.highlighted { .python .site-headline a:before { width: 290px; height: 82px; - content: url('../img/python-logo_print.png?1576869008'); } + content: url('../img/python-logo_print.png?1646853871'); } .psf .site-headline a:before { width: 334px; height: 82px; - content: url('../img/psf-logo_print.png?1576869008'); } } + content: url('../img/psf-logo_print.png?1646853871'); } } /* * When we want to review the markup for W3 and similar errors, turn some of these on * Uses :not selectors a bunch, so only modern browsers will support them @@ -3419,7 +3397,7 @@ span.highlighted { /* Hide a unicode fallback character when we supply it by default. * In fonts.scss, we hide the icon and show the fallback when other conditions are not met */ } - .fa { + .fa span { display: none; } /* Keep this at the bottom since it will create a huge set of data */ @@ -3428,138 +3406,135 @@ span.highlighted { * Be sure to upgrade to at least 0.12.1 to have this work properly. * in Terminal, gem install compass --version '= 0.12.1' */ - @font-face { - font-family: 'Pythonicon'; - src:url('../fonts/Pythonicon.eot'); -} @font-face { - font-family: 'Pythonicon'; - src: url(data:application/x-font-woff;charset=utf-8;base64,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) format('woff'), - url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype'); - font-weight: normal; - font-style: normal; -} + font-family: 'Pythonicon'; + src: url("../fonts/Pythonicon.eot"); } + +@font-face { + font-family: 'Pythonicon'; + src: url(data:application/x-font-woff;charset=utf-8;base64,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) format("woff"), url(data:application/x-font-ttf;charset=utf-8;base64,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) format("truetype"); + font-weight: normal; + font-style: normal; } + +.icon-bullhorn:before { + content: "\e600"; } + +.icon-python-alt:before { + content: "\e601"; } + +.icon-pypi:before { + content: "\e602"; } + +.icon-news:before { + content: "\e603"; } - .icon-bullhorn:before { - content: "\e600"; - } - .icon-python-alt:before { - content: "\e601"; - } - .icon-pypi:before { - content: "\e602"; - } - .icon-news:before { - content: "\e603"; - } - .icon-moderate:before { - content: "\e604"; - } - .icon-mercurial:before { - content: "\e605"; - } - .icon-jobs:before { - content: "\e606"; - } - .icon-help:before { - content: "\3f"; - } - .icon-download:before { - content: "\e609"; - } - .icon-documentation:before { - content: "\e60a"; - } - .icon-community:before { - content: "\e60b"; - } - .icon-code:before { - content: "\e60c"; - } - .icon-close:before { - content: "\58"; - } - .icon-calendar:before { - content: "\e60e"; - } - .icon-beginner:before { - content: "\e60f"; - } - .icon-advanced:before { - content: "\e610"; - } - .icon-sitemap:before { - content: "\e611"; - } - .icon-search-alt:before { - content: "\e612"; - } - .icon-search:before { - content: "\e613"; - } - .icon-python:before { - content: "\e614"; - } - .icon-github:before { - content: "\e615"; - } - .icon-get-started:before { - content: "\e616"; - } - .icon-feed:before { - content: "\e617"; - } - .icon-facebook:before { - content: "\e618"; - } - .icon-email:before { - content: "\e619"; - } - .icon-arrow-up:before { - content: "\e61a"; - } - .icon-arrow-right:before { - content: "\e61b"; - } - .icon-arrow-left:before { - content: "\e61c"; - } - .icon-arrow-down:before, .errorlist:before { - content: "\e61d"; - } - .icon-freenode:before { - content: "\e61e"; - } - .icon-alert:before { - content: "\e61f"; - } - .icon-versions:before { - content: "\e620"; - } - .icon-twitter:before { - content: "\e621"; - } - .icon-thumbs-up:before { - content: "\e622"; - } - .icon-thumbs-down:before { - content: "\e623"; - } - .icon-text-resize:before { - content: "\e624"; - } - .icon-success-stories:before { - content: "\e625"; - } - .icon-statistics:before { - content: "\e626"; - } - .icon-stack-overflow:before { - content: "\e627"; - } - .icon-mastodon:before { - content: "\e900"; - } +.icon-moderate:before { + content: "\e604"; } + +.icon-mercurial:before { + content: "\e605"; } + +.icon-jobs:before { + content: "\e606"; } + +.icon-help:before { + content: "\3f"; } + +.icon-download:before { + content: "\e609"; } + +.icon-documentation:before { + content: "\e60a"; } + +.icon-community:before { + content: "\e60b"; } + +.icon-code:before { + content: "\e60c"; } + +.icon-close:before { + content: "\58"; } + +.icon-calendar:before { + content: "\e60e"; } + +.icon-beginner:before { + content: "\e60f"; } + +.icon-advanced:before { + content: "\e610"; } + +.icon-sitemap:before { + content: "\e611"; } + +.icon-search-alt:before { + content: "\e612"; } + +.icon-search:before { + content: "\e613"; } + +.icon-python:before { + content: "\e614"; } + +.icon-github:before { + content: "\e615"; } + +.icon-get-started:before { + content: "\e616"; } + +.icon-feed:before { + content: "\e617"; } + +.icon-facebook:before { + content: "\e618"; } + +.icon-email:before { + content: "\e619"; } + +.icon-arrow-up:before { + content: "\e61a"; } + +.icon-arrow-right:before { + content: "\e61b"; } + +.icon-arrow-left:before { + content: "\e61c"; } + +.icon-arrow-down:before, .errorlist:before { + content: "\e61d"; } + +.icon-freenode:before { + content: "\e61e"; } + +.icon-alert:before { + content: "\e61f"; } + +.icon-versions:before { + content: "\e620"; } + +.icon-twitter:before { + content: "\e621"; } + +.icon-thumbs-up:before { + content: "\e622"; } + +.icon-thumbs-down:before { + content: "\e623"; } + +.icon-text-resize:before { + content: "\e624"; } + +.icon-success-stories:before { + content: "\e625"; } + +.icon-statistics:before { + content: "\e626"; } + +.icon-stack-overflow:before { + content: "\e627"; } + +.icon-mastodon:before { + content: "\e900"; } /* * Hide from anything that does not support FontFace (Opera Mini, Blackberry) @@ -3613,6 +3588,7 @@ span.highlighted { src: url("../fonts/FluxRegular.eot?#iefix") format("embedded-opentype"), url("../fonts/FluxRegular.woff") format("woff"), url('data:font/truetype;base64,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AN8AjwBwAG8AcQBzAHIAdACcAHUAdwB2AHgAeQB7AHoAfAB9ANwAfgCAAH8AgQCDAIIAsACdAIUAhACGAIcACQDgALIAzwDYANIA0wDUANcA0ADWAK4ArwC7AKwArQC8AIgAuQCNAO4ABwDxAPAAAAABAAAC3/73AHQEJf+I/8ED/QABAAAAAAAAAAAAAAAAAAAA9wEoAAAAAAAAASgAAAEoAAACIQAjAbQAHwEFAGQCDgApAf4AWwHlAD8A8gBGAWUARgJSADEBzgASAsYAFwJDADEA5wBQATQAPAE0AAYBZQAZAccALwDeADwBNwA8AN4AOwFPAAABzQAoAQoAHgG0ACgBpgAoAckAFAGvADIB4QAmAY8ADwHCAB4B1wAcAPYASQD8AEwBVAAsApkAMQFUACwBygAoAwQAMgIXAAoB/wA8AhgAHAIcADwBwwA8AaQAPAIhAB0CNwA8ANYARgFWAAoB9gA8AYIAPALHADwCVAA8AlsAHgHUADwCWwAeAdcAPAHiAB4B0wAKAjUANwIAAAoC/QAKAkYAKAHQAAoCQAAoAQsAPAFQAAABCwAfAowAUgH0AAQBUgBCAaMAHgHVADwBjwAeAdkAHgGjAB4BGwAeAdsAKAHSADwA1wA8AN7/iAGnADwA3wA8Ap4AMgHFADIBzQAeAdYAPAHgACMBSwA8AYoAKAETAB4BzAAyAbIADwJrAA8BswAeAdMAMgGqAB4BUQAeAOkAUAFQAAwBmQAwAhcACgIXAAoCLAAmAcMAPAJUADwCWwAeAj8APAGtACgBrQAoAbYAKAGtACgBrQAoAa0AKAGPAB4BowAeAaMAHgGkAB4BowAeANsAEgDf//QA3//LAN//2QHFADIBzQAeAc0AHgHNAB4BzQAeAc0AHgHMADIBzAAyAcwAMgHMADICFgAtASEAMgGZAB4CMwAoAc0AMgGfADwB7gAeAiwAFAM4ADIDNwAyAjUAHgFbADwBpAA7ApoAPAMbAAoCWgAeAlcAHgHMADIBnwAoAZ8AKAK+ACgBzQAeAcsAJwDyAEYBrAAKAhwAFAHxADIB8QAyAp4AOwIXAAoCFwAKAlsAHgMUABwC9QAoAoMAPAM3ADwBdQA7AXQAOwDeADsA3gA7AuMAFAMYABQB5wA8AeQAFAHO/+wBQwAyAUMAMgHiABQCFgAUAgwAKADeADsA3gA7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/90AhwB3/90AiAB4/90AiQB5/90AigB6/9wAiwB6/9wAjAB7/9wAjQB8/9wAjgB9/9sAjwB+/9sAkAB//9sAkQCA/9sAkgCB/9oAkwCB/9oAlACC/9oAlQCD/9oAlgCE/9kAlwCF/9kAmACG/9kAmQCH/9kAmgCI/9gAmwCI/9gAnACJ/9gAnQCK/9gAngCL/9cAnwCM/9cAoACN/9cAoQCO/9cAogCP/9YAowCP/9YApACQ/9YApQCR/9YApgCS/9UApwCT/9UAqACU/9UAqQCV/9UAqgCW/9QAqwCW/9QArACX/9QArQCY/9QArgCZ/9MArwCa/9MAsACb/9MAsQCc/9MAsgCd/9IAswCd/9IAtACe/9IAtQCf/9IAtgCg/9EAtwCh/9EAuACi/9EAuQCj/9EAugCk/9AAuwCk/9AAvACl/9AAvQCm/88AvgCn/88AvwCo/88AwACp/88AwQCq/84AwgCr/84AwwCs/84AxACs/84AxQCt/80AxgCu/80AxwCv/80AyACw/80AyQCx/8wAygCy/8wAywCz/8wAzACz/8wAzQC0/8sAzgC1/8sAzwC2/8sA0AC3/8sA0QC4/8oA0gC5/8oA0wC6/8oA1AC6/8oA1QC7/8kA1gC8/8kA1wC9/8kA2AC+/8kA2QC//8gA2gDA/8gA2wDB/8gA3ADB/8gA3QDC/8cA3gDD/8cA3wDE/8cA4ADF/8cA4QDG/8YA4gDH/8YA4wDI/8YA5ADI/8YA5QDJ/8UA5gDK/8UA5wDL/8UA6ADM/8UA6QDN/8QA6gDO/8QA6wDP/8QA7ADP/8QA7QDQ/8MA7gDR/8MA7wDS/8MA8ADT/8MA8QDU/8IA8gDV/8IA8wDW/8IA9ADW/8IA9QDX/8EA9gDY/8EA9wDZ/8EA+ADa/8EA+QDb/8AA+gDc/8AA+wDd/8AA/ADe/78A/QDe/78A/gDf/78A/wDg/78AFAA1AC4ASQBlAAAACgFwABACEQAMAkkABgAAuAAALEu4AAlQWLEBAY5ZuAH/hbgARB25AAkAA19eLbgAASwgIEVpRLABYC24AAIsuAABKiEtuAADLCBGsAMlRlJYI1kgiiCKSWSKIEYgaGFksAQlRiBoYWRSWCNlilkvILAAU1hpILAAVFghsEBZG2kgsABUWCGwQGVZWTotuAAELCBGsAQlRlJYI4pZIEYgamFksAQlRiBqYWRSWCOKWS/9LbgABSxLILADJlBYUViwgEQbsEBEWRshISBFsMBQWLDARBshWVktuAAGLCAgRWlEsAFgICBFfWkYRLABYC24AAcsuAAGKi24AAgsSyCwAyZTWLBAG7AAWYqKILADJlNYIyGwgIqKG4ojWSCwAyZTWCMhuADAioobiiNZILADJlNYIyG4AQCKihuKI1kgsAMmU1gjIbgBQIqKG4ojWSC4AAMmU1iwAyVFuAGAUFgjIbgBgCMhG7ADJUUjISMhWRshWUQtuAAJLEtTWEVEGyEhWS0AuAAAKwC6AAEAAgACKwG6AAMAAgACKwG/AAMATAA+ADAAIwASAAAACCu/AAQANwAtACMAGQASAAAACCsAvwABAGgAXABIADQAHwAAAAgrvwACAHgAXABIADQAHwAAAAgrALoABQAEAAcruAAAIEV9aRhEAAAAAAD3AQEBAUwBAQEBMwEBAUQ7OwEBOwEBAQEBAUwBAUxMTEwBTEwBAQEBAQEBATsBTAEBREwBOwEBHDs7TDtMOwFMAQEBAQEBATMBAQEzMwFMOwFMMwEBAQEvN0wvOwFMAUwBAQE3AQEBAQEzAQEBOy9MNzdMRDdEOzs7TEwBAQEBN0xMTExMTExMTAE7AQFMAUxMMzdMATcBATsBTExMTEwBAQEBAQFMAQE7AUQBAQEBAQFETERMAQEBOyIBAQEBRAEBATcBAQFMATs7RDtMTEwBAQEBAQE7AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAURMAQAAAQAAAAoAHgAsAAFsYXRuAAgABAAAAAD//wABAAAAAWtlcm4ACAAAAAEAAAABAAQAAgAAAAEACAABCo4ABAAAAEsAoACqALQAwgD8AR4BSAHKAdAB1gHcAe4B+AIGAgwCFgIgAlICbAKKArQCygM8A1IDWANmA2wDvgP4A/4EBARCBKQEzgTwBSIFsAXaBmAGygdoB/YIcAh6CJwIqgi0CLoIyAkSCSAJLgk0CToJQAlGCVwJZgl4CYoJlAmaCawJtgnMCdYJ7An2CgQKDgowCkIKVApqCoAAAgAq/9gASv/oAAIAKv/QAEH/7AADABIAKgBP//AAUwBYAA4ALP/sAC3/7AAw/+wAOP/sADr/7AA9/84AP//sAED/7ABC/84AS//wAFD/8ABY//YAX//iAGD/7AAIAB3/2AAq/+gAPf/YAD//6ABB/9AAQv/IAEP/2ABh/+gACgAr/+wALP/iADD/7AA4/+wAPf/OAD//7ABA/+wAQv/YAF//4ABg/+gAIAAZ/9gAGv/gABv/yAAc/9AAHf+IAB7/4AAf/+gAIv/YACr/sAA4/+wAPP/sAD0AHgA/ABQAQAAUAEIAHgBK/9AATP/QAE3/2ABO/9gAUP/IAFb/0ABX/+AAWP/YAFn/0ABa/9AAW//QAFz/2ABe/+AAX//oAGD/4ABh/9AAYv/oAAEARf/QAAEARf/oAAEARf/QAAQAFv/gABgAEAAg//AARf/AAAIAGAAgAEX/2AADABb/8AAYABgARf/IAAEARf/wAAIAGP/wAB3/sAACABgAEABF/9gADAAL/9gAEP/YABb/6AA4/+wAPf/EAD7/7AA//84AQP/sAEL/zgBF/8gAX//oAGD/6AAGAAv/7AA9/84AQf/OAEL/zgBD/+wARf/gAAcALP/xADj/7AA9//YAQP/sAEH/4gBC/+wAQ//sAAoAFf/sABf/4gAz/+IAPf/iAD7/9gA//+wAQf/OAEL/2ABD/+IARf/oAAUAOv/2AD8AFABAABQAQgAUAEUAIAAcABX/4gAX/9gAMP/sADP/4gA4/+wAOv/sAD8AFABAABQAQf/iAEIAFABFACgASv/QAEz/4ABN/+gATv/oAFD/6ABW/+gAV//oAFj/6ABZ/+AAWv/gAFv/6ABc/+gAXv/wAF//+ABh//AAYv/oAGP/8AAFAD3/7AA///YAQf/iAEL/9gBD//YAAQBB/+wAAwA4//YAQf/sAEr/8AABACr/7AAUABb/4AAs/+wAMP/YADj/4AA6/+gAPP/4AD7/8ABK/+gATP/gAE3/6ABO//AAUP/YAFX/8ABX//gAWP/oAFr/4ABb//gAXv/yAF//5QBg/+UADgAL/+wALf/2ADD/7AA4/+gAOv/wAD3/2AA+/+gAP//YAED/8ABC/+gAUP/4AFj/8ABf//AAYP/wAAEAQf/oAAEAQf/oAA8AFf/sABf/7AAY/+wAKv/sAC7/9gAz/9gAPf/oAD//7ABA/+wAQf/EAEL/7ABD/84ARf/oAEr/8ABh//AAGAAV/+IAFv/oABf/4gAY/9gAKv/EAC3/9gAz/9AAOf/4ADr/+AA8//gAPf/4AEH/yABD/9gASv/QAEz/6ABN/+gATv/gAFD/4ABW/+gAV//4AFj/4ABZ//gAW//oAFz/8AAKABX/7AAz/+AAPf/gAD//8ABB/8AAQv/oAEP/2ABK//AAXP/4AGH/8AAIAD7/+ABB/9gAQv/wAEr/8ABM//AATv/wAFD/8ABY//AADAAL/+wAEP/sADP/8AA9/+gAP//wAEH/2ABC//AAQ//gAF//8ABg//AAYf/wAGP/+AAjABX/4gAW/9gAF//YABj/2AAq/8QALP/2ADD/7AAz/+IAOP/xADr/8AA8//gAPwAYAEAAGABB/+gAQgAYAEUAKABK/6gATP+4AE3/wABO/7AAUP+4AFb/sABX/7AAWP+oAFn/qABa/7AAW/+4AFz/uABd//AAXv+2AF//uABg/8gAYf/AAGL/wABj/7gACgAY/+wAKv/sAC7/7AAv//YAM//sADn/+AA6//gAPf/oAEH/2ABD/9gAIQAV/+wAFv/gABf/7AAY/84AKv/OADD/7AAz/8QAOP/sADr/8AA9ABAAPwAUAEAAFABB/+IAQgAUAEP/4gBFABAASv/IAEz/0ABN/9gATv/YAFD/0ABW/9gAV//YAFj/yABZ/8gAWv/QAFv/2ABc/9gAXv/wAF//+ABh/+gAYv/YAGP/4AAaABX/7AAX/+wAGP/YACr/7AAz/9gAOP/sAD0AEAA/ABQAQAAUAEH/7ABCABQARQAQAEr/0ABM/+gATf/YAE7/4ABQ/9gAVv/wAFf/4ABY/+AAW//YAFz/4ABe/+gAYf/oAGL/6ABj/+AAJwAQ/+wAFv/QACv/zgAs/84ALf/iAC7/7AAv/+IAMP/EADH/7AAy/+wANf/4ADb/+AA3/+gAOP/EADn/6AA6/8AAO//oADz/2AA9/+AAPv/YAD//4gBA/+wAQf/YAEL/7ABD/+IASv/QAEv/6ABM/9gATf/iAE7/4gBQ/+IAWP/dAFn/7ABa/+IAXf/iAF7/4gBf/+IAYP/iAGL/5QAjABX/2AAW/9AAF//iABj/2AAq/84ALP/sADD/7AAz/9gAOP/sADr/6AA8//gAPQAQAD8AFABAABQAQf/sAEP/7ABFABgASv/AAEz/uABN/8gATv/QAFD/wABW/8gAV//YAFj/wABZ/8AAWv/AAFv/yABc/8AAXv/QAF//4ABg/9gAYf/YAGL/2ABj/+AAHgAW/+AALP/iAC3/4gAu/+wAL//2ADD/xAAx//YAOP/OADr/2AA7//gAPP/4AD3/4AA+/9gAP//iAED/7ABB/+IAQv/sAEP/7ABL//AATP/oAE3/6ABO//AAT//wAFD/8ABR//AAWP/oAFn/+ABa//AAX//gAGD/6AACAEYABwBTAEAACAA4//AAPf/IAD7/6AA//8gAQP/IAEL/yABQ//gAX//gAAMAC//gAEL/wABF/9gAAgBC/9AARf/oAAEARf/YAAMAPf/QAEL/yABF/9gAEgALAEAAEAAUABIAUAAV/+gAF//oAC8AHQAxABgANAAIADUAMAA9ACgAPgAeAD8AOABAADgAQwAYAEUAaABGADgASv/2AGYAMAADAAv/8ABC/9AARf/oAAMAC//wAEL/0ABF/+gAAQBTACgAAQBC/+gAAQBF/9gAAQBF/+gABQAV//YAQ//gAEX/4ABh/+wAY//lAAIAQ//gAEX/4AAEAEP/4ABTAE8AXv/zAGH/8wAEABX/7AAX//AAQ//gAE8ADwACABb/8ABD/+AAAQBD/+AABAAV/+wAF//oABj/8ABD/+AAAgAV/+wAF//oAAUAFv/oAEz/5QBY/+wAWf/zAFr/5QACAEX/8ABTABoABQAQ//AARf/gAE3/5QBY/+UAWf/lAAIAT//oAGYAJAADAHsAPAB8ADIAfQBJAAIAfAA+AH0ANQAIAHoAPQB7AC0AfAB8AH0AcgDDABIAxAASAMUAEgDGABIABAB6ACoAewA6AHwAZwB9AFwABAB8AA4AxAA8AMUATwDGAEsABQB8AA0AwwAxAMQAfQDFAGkAxgArAAUAfAANAMMAJgDEAHIAxQBeAMYASQADAHwADQDEAD8AxQArAAIADAALAAsAAAAQABEAAQAVACAAAwAiACIADwAqAEUAEABKAEwALABOAFEALwBTAFQAMwBWAFwANQBeAGQAPAB6AH0AQwDDAMYARwAA') format('truetype'); font-weight: normal; font-style: normal; } + /*@font-face { font-family: 'Flux-BoldItalic'; src: url('../fonts/FluxBoldItalic.eot'); @@ -3634,6 +3610,7 @@ span.highlighted { src: url("../fonts/FluxBold.eot?#iefix") format("embedded-opentype"), url("../fonts/FluxBold.woff") format("woff"), url('data:font/truetype;base64,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AN8AjwBwAG8AcQBzAHIAdACcAHUAdwB2AHgAeQB7AHoAfAB9ANwAfgCAAH8AgQCDAIIAsACdAIUAhACGAIcACQDgALIAzwDYANIA0wDUANcA0ADWAK4ArwC7AKwArQC8AIgAuQCNAO4ABwDxAPAAAAABAAAC4/77AIIEMv+I/8EECgABAAAAAAAAAAAAAAAAAAAA9wEoAAAAAAAAASgAAAEoAAACIQAUAbQAEAEFAF0CDgAiAf4AUAHlADgBBgBGAXQARgJiADIB8wAeAtwAHgJlAC0A9wBQAUsAPAFLAAoBhQAeAdsAMgDxADwBRQA8APIAPAFjAAAB2gAoARwAHgHEACgBtgAoAeAAFAG9ADIB7gAmAagADwHQAB4B5gAcAQYARgEHAEYBbAAoAqIAMgFsADIB1QAoAxMAMgIuAAoCDQA8AikAHAIqADwB2AA8AcMAPAIxABwCRQA8AOoARgFnAAoCDgA8AZYAPALVADwCYgA8AmkAHgHhADwCaQAeAe0APAHzAB4B6AAKAkMANwIUAAoDEQAKAmYAKAHoAAoCVgAoAR4APAFiAAABHwAfAngAPAIrABQBZQAtAaoAHgHjADwBoAAeAd0AHgGqAB0BLAAeAeoAKAHWADwA8gA8AOj/iAG+ADwA9wA8AqIAMgHJADIB2wAeAeQAPAHvACMBXgA8AZIAKAEhAB4B1QAyAcYADwJ/AA8B1AAeAeIAMgHAAB4BdQAeAPgAUAF2AB4BtQAyAi4ACgIuAAoCPQAmAdgAPAJiADwCaQAeAk0APAG+ACgBvgAoAcoAKAG+ACgBvgAoAb4AKAGgAB4BtQAeAbUAHgG2AB4BtQAeAPMAEgD3//QA9//LAO7/2QHTADIB2wAeAdsAHgHbAB4B2wAeAdsAHgHaADIB2gAyAdoAMgHaADICKwAtAS8AMgGqAB4CRgAoAd8AMgGuADwB/QAeAjkAFANGADIDRgAyAkkAHgFzADwBsQA8ArYAPAM5AAoCaQAeAnMAHgHaADIBtAAoAbQAKALQACgB2wAeAdUAKAEGAEYBwgAKAi0AFAIGADICBgAyAq4AOwIuAAoCLgAKAmkAHgMpABwC/QAeApkAPANNADwBgwA7AYIAPADsADsA7AA8AvEAFAMnABQB9gA8AfwAFAHl/+wBWAAyAVgAMgHxABQCJgAUAiEAKADsADwA7AA8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AE3/6QBYAE7/6QBZAE//6QBaAE//6QBbAFD/6ABcAFH/6ABdAFL/6ABeAFP/6ABfAFT/5wBgAFX/5wBhAFb/5wBiAFb/5wBjAFf/5gBkAFj/5gBlAFn/5gBmAFr/5gBnAFv/5QBoAFz/5QBpAF3/5QBqAF3/5QBrAF7/5ABsAF//5ABtAGD/5ABuAGH/5ABvAGL/4wBwAGP/4wBxAGT/4wByAGT/4wBzAGX/4gB0AGb/4gB1AGf/4gB2AGj/4gB3AGn/4QB4AGr/4QB5AGv/4QB6AGv/4QB7AGz/4AB8AG3/4AB9AG7/4AB+AG//3wB/AHD/3wCAAHH/3wCBAHL/3wCCAHP/3gCDAHP/3gCEAHT/3gCFAHX/3gCGAHb/3QCHAHf/3QCIAHj/3QCJAHn/3QCKAHr/3ACLAHr/3ACMAHv/3ACNAHz/3ACOAH3/2wCPAH7/2wCQAH//2wCRAID/2wCSAIH/2gCTAIH/2gCUAIL/2gCVAIP/2gCWAIT/2QCXAIX/2QCYAIb/2QCZAIf/2QCaAIj/2ACbAIj/2ACcAIn/2ACdAIr/2ACeAIv/1wCfAIz/1wCgAI3/1wChAI7/1wCiAI//1gCjAI//1gCkAJD/1gClAJH/1gCmAJL/1QCnAJP/1QCoAJT/1QCpAJX/1QCqAJb/1ACrAJb/1ACsAJf/1ACtAJj/1ACuAJn/0wCvAJr/0wCwAJv/0wCxAJz/0wCyAJ3/0gCzAJ3/0gC0AJ7/0gC1AJ//0gC2AKD/0QC3AKH/0QC4AKL/0QC5AKP/0QC6AKT/0AC7AKT/0AC8AKX/0AC9AKb/zwC+AKf/zwC/AKj/zwDAAKn/zwDBAKr/zgDCAKv/zgDDAKz/zgDEAKz/zgDFAK3/zQDGAK7/zQDHAK//zQDIALD/zQDJALH/zADKALL/zADLALP/zADMALP/zADNALT/ywDOALX/ywDPALb/ywDQALf/ywDRALj/ygDSALn/ygDTALr/ygDUALr/ygDVALv/yQDWALz/yQDXAL3/yQDYAL7/yQDZAL//yADaAMD/yADbAMH/yADcAMH/yADdAML/xwDeAMP/xwDfAMT/xwDgAMX/xwDhAMb/xgDiAMf/xgDjAMj/xgDkAMj/xgDlAMn/xQDmAMr/xQDnAMv/xQDoAMz/xQDpAM3/xADqAM7/xADrAM//xADsAM//xADt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/+wASv/wAAEAKv/sABQAFv/gACz/7AAw/9gAOP/gADr/6AA8//gAPv/wAEr/6ABM/+AATf/oAE7/8ABQ/9gAVf/wAFf/+ABY/+gAWv/gAFv/+ABe//IAX//lAGD/5QAOAAv/7AAt//YAMP/sADj/6AA6//AAPf/YAD7/6AA//9gAQP/wAEL/6ABQ//gAWP/wAF//8ABg//AAAQBB/+gAAQBB/+gADwAV/+wAF//sABj/7AAq/+wALv/2ADP/2AA9/+gAP//sAED/7ABB/8QAQv/sAEP/zgBF/+gASv/wAGH/8AAYABX/4gAW/+gAF//iABj/2AAq/8QALf/2ADP/0AA5//gAOv/4ADz/+AA9//gAQf/IAEP/2ABK/9AATP/oAE3/6ABO/+AAUP/gAFb/6ABX//gAWP/gAFn/+ABb/+gAXP/wAAoAFf/sADP/4AA9/+AAP//wAEH/wABC/+gAQ//YAEr/8ABc//gAYf/wAAgAPv/4AEH/2ABC//AASv/wAEz/8ABO//AAUP/wAFj/8AAMAAv/7AAQ/+wAM//wAD3/6AA///AAQf/YAEL/8ABD/+AAX//wAGD/8ABh//AAY//4ACMAFf/iABb/2AAX/9gAGP/YACr/xAAs//YAMP/sADP/4gA4//EAOv/wADz/+AA/ABgAQAAYAEH/6ABCABgARQAoAEr/qABM/7gATf/AAE7/sABQ/7gAVv+wAFf/sABY/6gAWf+oAFr/sABb/7gAXP+4AF3/8ABe/7YAX/+4AGD/yABh/8AAYv/AAGP/uAAKABj/7AAq/+wALv/sAC//9gAz/+wAOf/4ADr/+AA9/+gAQf/YAEP/2AAhABX/7AAW/+AAF//sABj/zgAq/84AMP/sADP/xAA4/+wAOv/wAD0AEAA/ABQAQAAUAEH/4gBCABQAQ//iAEUAEABK/8gATP/QAE3/2ABO/9gAUP/QAFb/2ABX/9gAWP/IAFn/yABa/9AAW//YAFz/2ABe//AAX//4AGH/6ABi/9gAY//gABoAFf/sABf/7AAY/9gAKv/sADP/2AA4/+wAPQAQAD8AFABAABQAQf/sAEIAFABFABAASv/QAEz/6ABN/9gATv/gAFD/2ABW//AAV//gAFj/4ABb/9gAXP/gAF7/6ABh/+gAYv/oAGP/4AAnABD/7AAW/9AAK//OACz/zgAt/+IALv/sAC//4gAw/8QAMf/sADL/7AA1//gANv/4ADf/6AA4/8QAOf/oADr/wAA7/+gAPP/YAD3/4AA+/9gAP//iAED/7ABB/9gAQv/sAEP/4gBK/9AAS//oAEz/2ABN/+IATv/iAFD/4gBY/90AWf/sAFr/4gBd/+IAXv/iAF//4gBg/+IAYv/lACMAFf/YABb/0AAX/+IAGP/YACr/zgAs/+wAMP/sADP/2AA4/+wAOv/oADz/+AA9ABAAPwAUAEAAFABB/+wAQ//sAEUAGABK/8AATP+4AE3/yABO/9AAUP/AAFb/yABX/9gAWP/AAFn/wABa/8AAW//IAFz/wABe/9AAX//gAGD/2ABh/9gAYv/YAGP/4AAeABb/4AAs/+IALf/iAC7/7AAv//YAMP/EADH/9gA4/84AOv/YADv/+AA8//gAPf/gAD7/2AA//+IAQP/sAEH/4gBC/+wAQ//sAEv/8ABM/+gATf/oAE7/8ABP//AAUP/wAFH/8ABY/+gAWf/4AFr/8ABf/+AAYP/oAAIARgAHAFMAQAAIADj/8AA9/8gAPv/oAD//yABA/8gAQv/IAFD/+ABf/+AAAwAL/+AAQv/AAEX/2AACAEL/0ABF/+gAAQBF/9gAAwA9/9AAQv/IAEX/2AASAAsAQAAQABQAEgBQABX/6AAX/+gALwAdADEAGAA0AAgANQAwAD0AKAA+AB4APwA4AEAAOABDABgARQBoAEYAOABK//IAZgAwAAMAC//wAEL/0ABF/+gAAwAL//AAQv/QAEX/6AABAFMAKAABAEL/6AABAEX/2AABAEX/6AAFABX/9gBD/+AARf/gAGH/7ABj/+UAAgBD/+AARf/gAAQAQ//gAFMATwBe//MAYf/zAAQAFf/sABf/8ABD/+AATwAOAAIAFv/wAEP/4AABAEP/4AAEABX/7AAX/+gAGP/wAEP/4AACABX/7AAX/+gABQAW/+gATP/lAFj/7ABZ//MAWv/lAAIARf/wAFMAGgAFABD/8ABF/+AATf/lAFj/5QBZ/+UAAgBP/+gAZgAkAAMAewA8AHwAMgB9AEkAAgB8AD4AfQA1AAgAegA9AHsALQB8AHwAfQByAMMAEgDEABIAxQASAMYAEgAEAHoAKgB7ADoAfABnAH0AXAAEAHwADgDEADwAxQBPAMYASwAFAHwADQDDADEAxAB9AMUAaQDGACsABQB8AA0AwwAmAMQAcgDFAF4AxgBJAAMAfAANAMQAPwDFACsAAgAMAAsACwAAABAAEQABABUAIAADACIAIgAPACoARQAQAEoATAAsAE4AUQAvAFMAVAAzAFYAXAA1AF4AZAA8AHoAfQBDAMMAxgBHAAA=') format('truetype'); font-weight: bold; font-style: normal; } + /* * Generated by Font Squirrel (http://www.fontsquirrel.com) on July 2, 2013 10:19:24 AM America/New_York * Adobe Source Pro Sans, Open Source License: http://store1.adobe.com/cfusion/store/html/index.cfm?event=displayFontPackage&code=1959 @@ -3644,12 +3621,14 @@ span.highlighted { src: url("../fonts/SourceSansPro-Regular-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/SourceSansPro-Regular-webfont.woff") format("woff"), url("../fonts/SourceSansPro-Regular-webfont.ttf") format("truetype"), url("../fonts/SourceSansPro-Regular-webfont.svg#source_sans_proregular") format("svg"); font-weight: normal; font-style: normal; } + @font-face { font-family: 'SourceSansProBold'; src: url("../fonts/SourceSansPro-Bold-webfont.eot"); src: url("../fonts/SourceSansPro-Bold-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/SourceSansPro-Bold-webfont.woff") format("woff"), url("../fonts/SourceSansPro-Bold-webfont.ttf") format("truetype"), url("../fonts/SourceSansPro-Bold-webfont.svg#source_sans_probold") format("svg"); font-weight: bold; font-style: normal; } + @font-face { font-family: 'SourceSansProItalic'; src: url("../fonts/SourceSansPro-It-webfont.eot"); @@ -3809,7 +3788,7 @@ span.highlighted { #select_sponsorship_benefits_container .benefit-title { margin-top: 0; } #select_sponsorship_benefits_container .benefit-program { - font-weight: bold; } + font-size: bold; } #select_sponsorship_benefits_container #benefitsTable { width: 90vw; position: relative; @@ -3822,7 +3801,7 @@ span.highlighted { font-size: 16px; line-height: 18px; } #select_sponsorship_benefits_container #benefitsTable .row { - border-bottom: 1px solid #e6e8ea; } + border-bottom: 1px solid #E6E8EA; } #select_sponsorship_benefits_container #benefitsTable .row .col:not(first-child) { width: 10%; text-align: center; @@ -3838,7 +3817,7 @@ span.highlighted { width: 70%; } } #select_sponsorship_benefits_container #benefitsTable .separator { flex-shrink: 0; - border-bottom: 3px solid #ffd343; + border-bottom: 3px solid #FFD343; display: block; } #select_sponsorship_benefits_container #benefitsTable .separator h4 { font-size: 23px; @@ -4008,7 +3987,7 @@ span.highlighted { #sponsorship-detail-container .card { flex: 1 0 48%; } #sponsorship-detail-container .card-info { - margin: 0.5em 0.5em; + margin: .5em .5em; padding: 1em 1em; border: 1px solid #caccce; -webkit-border-radius: 6px; From 18e1d74eb1fe435d617b78b91fc7a5457d262a9d Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Mon, 30 Sep 2024 14:17:55 -0400 Subject: [PATCH 139/235] Improve static deploy (#2609) * Add a utility for purging Fastly by Surrogate-Key * add a postdeploy step to purge surroage-keys for static files --- Procfile | 1 + fastly/utils.py | 20 ++++++++++++++++++++ pydotorg/management/__init__.py | 0 pydotorg/management/commands/__init__.py | 0 pydotorg/management/commands/postdeploy.py | 14 ++++++++++++++ pydotorg/settings/base.py | 10 ++++++++-- pydotorg/settings/cabotage.py | 8 +++++++- 7 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 pydotorg/management/__init__.py create mode 100644 pydotorg/management/commands/__init__.py create mode 100644 pydotorg/management/commands/postdeploy.py diff --git a/Procfile b/Procfile index 16deb5f5b..cce927ff8 100644 --- a/Procfile +++ b/Procfile @@ -2,3 +2,4 @@ release: python manage.py migrate --noinput web: bin/start-nginx gunicorn -c gunicorn.conf pydotorg.wsgi worker: celery -A pydotorg worker -l INFO worker-beat: celery -A pydotorg beat -l INFO --scheduler django_celery_beat.schedulers:DatabaseScheduler +postdeploy: python manage.py postdeploy diff --git a/fastly/utils.py b/fastly/utils.py index 42637aeb2..8bc9a8b80 100644 --- a/fastly/utils.py +++ b/fastly/utils.py @@ -20,3 +20,23 @@ def purge_url(path): return response return None + + +def purge_surrogate_key(key): + """ + Purge a Fastly.com Surrogate-Key given a key. + """ + if settings.DEBUG: + return + + api_key = getattr(settings, 'FASTLY_API_KEY', None) + service_id = getattr(settings, 'FASTLY_SERVICE_ID', None) + if api_key and service_id: + response = requests.request( + "POST", + f'https://api.fastly.com/service/{service_id}/purge/{key}', + headers={'Fastly-Key': api_key}, + ) + return response + + return None diff --git a/pydotorg/management/__init__.py b/pydotorg/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pydotorg/management/commands/__init__.py b/pydotorg/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pydotorg/management/commands/postdeploy.py b/pydotorg/management/commands/postdeploy.py new file mode 100644 index 000000000..17c518e31 --- /dev/null +++ b/pydotorg/management/commands/postdeploy.py @@ -0,0 +1,14 @@ +from django.core.management.base import BaseCommand +from django.conf import settings + +from fastly.utils import purge_surrogate_key + + +class Command(BaseCommand): + """ Do things after deployment is complete """ + + def handle(self, *args, **kwargs): + # If we have a STATIC_SURROGATE_KEY set, purge static files to ensure + # that anything cached mid-deploy is ignored (like 404s). + if settings.STATIC_SURROGATE_KEY: + purge_surrogate_key(settings.STATIC_SURROGATE_KEY) diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 2c392b355..70ec472f9 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -285,8 +285,10 @@ MAILING_LIST_PSF_MEMBERS = "psf-members-announce-request@python.org" ### Fastly ### -FASTLY_API_KEY = False # Set to Fastly API key in production to allow pages to - # be purged on save +FASTLY_SERVICE_ID = False # Set to a Fastly Service ID in production to allow + # purges by Surrogate-Key +FASTLY_API_KEY = False # Set to Fastly API key in production to allow + # pages to be purged on save # Jobs JOB_THRESHOLD_DAYS = 90 @@ -349,6 +351,10 @@ GLOBAL_SURROGATE_KEY = 'pydotorg-app' +### pydotorg.settings.cabotage.add_surrogate_keys_to_static + +STATIC_SURROGATE_KEY = 'pydotorg-static' + ### PyCon Integration for Sponsor Voucher Codes PYCON_API_KEY = config("PYCON_API_KEY", default="deadbeef-dead-beef-dead-beefdeadbeef") PYCON_API_SECRET = config("PYCON_API_SECRET", default="deadbeef-dead-beef-dead-beefdeadbeef") diff --git a/pydotorg/settings/cabotage.py b/pydotorg/settings/cabotage.py index 4661fbf66..2effbacf7 100644 --- a/pydotorg/settings/cabotage.py +++ b/pydotorg/settings/cabotage.py @@ -53,6 +53,11 @@ }, } +def add_surrogate_keys_to_static(headers, path, url): + headers['Surrogate-Key'] = STATIC_SURROGATE_KEY + +WHITENOISE_ADD_HEADERS_FUNCTION = add_surrogate_keys_to_static + EMAIL_HOST = config('EMAIL_HOST') EMAIL_HOST_USER = config('EMAIL_HOST_USER') EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD') @@ -63,7 +68,8 @@ PEP_REPO_PATH = None PEP_ARTIFACT_URL = config('PEP_ARTIFACT_URL') -# Fastly API Key +# Fastly +FASTLY_SERVICE_ID = config('FASTLY_SERVICE_ID') FASTLY_API_KEY = config('FASTLY_API_KEY') SECURE_SSL_REDIRECT = True From 00b4302f26d7c1db29a3b12b69d7a1df10171399 Mon Sep 17 00:00:00 2001 From: Mike Fiedler <miketheman@gmail.com> Date: Mon, 30 Sep 2024 14:26:16 -0400 Subject: [PATCH 140/235] refactor: update `all_day` detection logic (#2601) Instead of using a particular resolution on an object, which differs between `datetime.date` and `datetime.datetime` objects, operate on parent class of `datetime` and convert all `dt` to timezone-aware `datetime` values. This is also in accordance to the model field being a `DateTimeField`, so we should always be passing the correctly-created object, instead of a `datetime.date()`, raising `received a naive datetime` warnings. Removes unused constants. Signed-off-by: Mike Fiedler <miketheman@gmail.com> Co-authored-by: Ee Durbin <ewdurbin@gmail.com> --- events/importer.py | 8 +------- events/utils.py | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/events/importer.py b/events/importer.py index fe04d35f5..12bf2efce 100644 --- a/events/importer.py +++ b/events/importer.py @@ -7,9 +7,6 @@ from .models import EventLocation, Event, OccurringRule from .utils import extract_date_or_datetime -DATE_RESOLUTION = timedelta(1) -TIME_RESOLUTION = timedelta(0, 0, 1) - logger = logging.getLogger(__name__) @@ -31,10 +28,7 @@ def import_occurrence(self, event, event_data): dt_end = dt_start # Let's mark those occurrences as 'all-day'. - all_day = ( - dt_start.resolution == DATE_RESOLUTION or - dt_end.resolution == DATE_RESOLUTION - ) + all_day = dt_end - dt_start >= timedelta(days=1) defaults = { 'dt_start': dt_start, diff --git a/events/utils.py b/events/utils.py index a3801d4a6..1ddadcc79 100644 --- a/events/utils.py +++ b/events/utils.py @@ -21,7 +21,7 @@ def date_to_datetime(date, tzinfo=None): def extract_date_or_datetime(dt): - if isinstance(dt, datetime.datetime): + if isinstance(dt, datetime.date): return convert_dt_to_aware(dt) return dt From 4c44d8045c5c6e9a6cd2a15bbc9cfef52739edc3 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Mon, 30 Sep 2024 15:06:45 -0400 Subject: [PATCH 141/235] Revert "Improve static deploy" (#2621) Revert "Improve static deploy (#2609)" This reverts commit 18e1d74eb1fe435d617b78b91fc7a5457d262a9d. --- Procfile | 1 - fastly/utils.py | 20 -------------------- pydotorg/management/__init__.py | 0 pydotorg/management/commands/__init__.py | 0 pydotorg/management/commands/postdeploy.py | 14 -------------- pydotorg/settings/base.py | 10 ++-------- pydotorg/settings/cabotage.py | 8 +------- 7 files changed, 3 insertions(+), 50 deletions(-) delete mode 100644 pydotorg/management/__init__.py delete mode 100644 pydotorg/management/commands/__init__.py delete mode 100644 pydotorg/management/commands/postdeploy.py diff --git a/Procfile b/Procfile index cce927ff8..16deb5f5b 100644 --- a/Procfile +++ b/Procfile @@ -2,4 +2,3 @@ release: python manage.py migrate --noinput web: bin/start-nginx gunicorn -c gunicorn.conf pydotorg.wsgi worker: celery -A pydotorg worker -l INFO worker-beat: celery -A pydotorg beat -l INFO --scheduler django_celery_beat.schedulers:DatabaseScheduler -postdeploy: python manage.py postdeploy diff --git a/fastly/utils.py b/fastly/utils.py index 8bc9a8b80..42637aeb2 100644 --- a/fastly/utils.py +++ b/fastly/utils.py @@ -20,23 +20,3 @@ def purge_url(path): return response return None - - -def purge_surrogate_key(key): - """ - Purge a Fastly.com Surrogate-Key given a key. - """ - if settings.DEBUG: - return - - api_key = getattr(settings, 'FASTLY_API_KEY', None) - service_id = getattr(settings, 'FASTLY_SERVICE_ID', None) - if api_key and service_id: - response = requests.request( - "POST", - f'https://api.fastly.com/service/{service_id}/purge/{key}', - headers={'Fastly-Key': api_key}, - ) - return response - - return None diff --git a/pydotorg/management/__init__.py b/pydotorg/management/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/pydotorg/management/commands/__init__.py b/pydotorg/management/commands/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/pydotorg/management/commands/postdeploy.py b/pydotorg/management/commands/postdeploy.py deleted file mode 100644 index 17c518e31..000000000 --- a/pydotorg/management/commands/postdeploy.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.core.management.base import BaseCommand -from django.conf import settings - -from fastly.utils import purge_surrogate_key - - -class Command(BaseCommand): - """ Do things after deployment is complete """ - - def handle(self, *args, **kwargs): - # If we have a STATIC_SURROGATE_KEY set, purge static files to ensure - # that anything cached mid-deploy is ignored (like 404s). - if settings.STATIC_SURROGATE_KEY: - purge_surrogate_key(settings.STATIC_SURROGATE_KEY) diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 70ec472f9..2c392b355 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -285,10 +285,8 @@ MAILING_LIST_PSF_MEMBERS = "psf-members-announce-request@python.org" ### Fastly ### -FASTLY_SERVICE_ID = False # Set to a Fastly Service ID in production to allow - # purges by Surrogate-Key -FASTLY_API_KEY = False # Set to Fastly API key in production to allow - # pages to be purged on save +FASTLY_API_KEY = False # Set to Fastly API key in production to allow pages to + # be purged on save # Jobs JOB_THRESHOLD_DAYS = 90 @@ -351,10 +349,6 @@ GLOBAL_SURROGATE_KEY = 'pydotorg-app' -### pydotorg.settings.cabotage.add_surrogate_keys_to_static - -STATIC_SURROGATE_KEY = 'pydotorg-static' - ### PyCon Integration for Sponsor Voucher Codes PYCON_API_KEY = config("PYCON_API_KEY", default="deadbeef-dead-beef-dead-beefdeadbeef") PYCON_API_SECRET = config("PYCON_API_SECRET", default="deadbeef-dead-beef-dead-beefdeadbeef") diff --git a/pydotorg/settings/cabotage.py b/pydotorg/settings/cabotage.py index 2effbacf7..4661fbf66 100644 --- a/pydotorg/settings/cabotage.py +++ b/pydotorg/settings/cabotage.py @@ -53,11 +53,6 @@ }, } -def add_surrogate_keys_to_static(headers, path, url): - headers['Surrogate-Key'] = STATIC_SURROGATE_KEY - -WHITENOISE_ADD_HEADERS_FUNCTION = add_surrogate_keys_to_static - EMAIL_HOST = config('EMAIL_HOST') EMAIL_HOST_USER = config('EMAIL_HOST_USER') EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD') @@ -68,8 +63,7 @@ def add_surrogate_keys_to_static(headers, path, url): PEP_REPO_PATH = None PEP_ARTIFACT_URL = config('PEP_ARTIFACT_URL') -# Fastly -FASTLY_SERVICE_ID = config('FASTLY_SERVICE_ID') +# Fastly API Key FASTLY_API_KEY = config('FASTLY_API_KEY') SECURE_SSL_REDIRECT = True From 354631bd2525a12dea8c51b337ee028309e7cb7c Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Mon, 30 Sep 2024 14:21:05 -0500 Subject: [PATCH 142/235] feat(infra): do not cache static 404s (#2622) * feat(infra): do not cache static 404s * feat(infra): apply condition --- infra/cdn/main.tf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/infra/cdn/main.tf b/infra/cdn/main.tf index e7aa77108..059fd8977 100644 --- a/infra/cdn/main.tf +++ b/infra/cdn/main.tf @@ -68,6 +68,14 @@ resource "fastly_service_vcl" "python_org" { ttl = 0 } + cache_setting { + action = "pass" + cache_condition = "Don't cache 404s for /static" + name = "No caching for /static 404s" + stale_ttl = 0 + ttl = 0 + } + condition { name = "Force Pass No-Cache No-Store" priority = 10 @@ -129,6 +137,13 @@ resource "fastly_service_vcl" "python_org" { type = "REQUEST" } + condition { + name = "Don't cache 404s for /static" + priority = 10 + statement = "req.url ~ \"^/static/\" && beresp.status == 404" + type = "CACHE" + } + gzip { name = "Default rules" content_types = [ From 2154a90fe7ac3fbda1ff4f8045179f0e33c28e5d Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Mon, 30 Sep 2024 15:24:38 -0500 Subject: [PATCH 143/235] docs: add details to CSS generation (#2623) * docs: add details to CSS generation * docs: no NBSP * docs: note automatic compiles --- docs/source/install.md | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/docs/source/install.md b/docs/source/install.md index c91d1bd59..55cf483fb 100644 --- a/docs/source/install.md +++ b/docs/source/install.md @@ -88,7 +88,7 @@ This is a simple wrapper around running `python manage.py` in the container, all Manual setup ------------ -First, install [PostgreSQL](https://www.postgresql.org/download/) on your machine and run it. *pythondotorg* currently uses Postgres 15.x. +First, install [PostgreSQL](https://www.postgresql.org/download/) on your machine and run it. *pythondotorg* currently uses Postgres 15.x. Then clone the repository: @@ -102,13 +102,13 @@ Then create a virtual environment: $ python3 -m venv venv ``` -And then you'll need to install dependencies. You don't need to use `pip3` inside a Python 3 virtual environment: +And then you'll need to install dependencies. You don't need to use `pip3` inside a Python 3 virtual environment: ``` $ pip install -r dev-requirements.txt ``` -*pythondotorg* will look for a PostgreSQL database named `pythondotorg` by default. Run the following command to create a new database: +*pythondotorg* will look for a PostgreSQL database named `pythondotorg` by default. Run the following command to create a new database: ``` $ createdb pythondotorg -E utf-8 -l en_US.UTF-8 @@ -121,7 +121,7 @@ If the above command fails to create a database and you see an error message sim createdb: database creation failed: ERROR: permission denied to create database ``` -Use the following command to create a database with *postgres* user as the owner: +Use the following command to create a database with *postgres* user as the owner: ``` $ sudo -u postgres createdb pythondotorg -E utf-8 -l en_US.UTF-8 @@ -135,10 +135,10 @@ If you get an error like this: createdb: database creation failed: ERROR: new collation (en_US.UTF-8) is incompatible with the collation of the template database (en_GB.UTF-8) ``` -Then you will have to change the value of the `-l` option to what your database was set up with initially. +Then you will have to change the value of the `-l` option to what your database was set up with initially. ```` -To change database configuration, you can add the following setting to `pydotorg/settings/local.py` (or you can use the `DATABASE_URL` environment variable): +To change database configuration, you can add the following setting to `pydotorg/settings/local.py` (or you can use the `DATABASE_URL` environment variable): ``` DATABASES = { @@ -146,14 +146,14 @@ DATABASES = { } ``` -If you prefer to use a simpler setup for your database you can use SQLite. Set the `DATABASE_URL` environment variable for the current terminal session: +If you prefer to use a simpler setup for your database you can use SQLite. Set the `DATABASE_URL` environment variable for the current terminal session: ``` $ export DATABASE_URL="sqlite:///pythondotorg.db" ``` ```{note} -If you prefer to set this variable in a more permanent way add the above line in your `.bashrc` file. Then it will be set for all terminal sessions in your system. +If you prefer to set this variable in a more permanent way add the above line in your `.bashrc` file. Then it will be set for all terminal sessions in your system. ``` Whichever database type you chose, now it's time to run migrations: @@ -162,7 +162,7 @@ Whichever database type you chose, now it's time to run migrations: $ ./manage.py migrate ``` -To compile and compress static media, you will need *compass* and *yui-compressor*: +To compile and compress static media, you will need *compass* and *yui-compressor*: ``` $ gem install bundler @@ -170,7 +170,7 @@ $ bundle install ``` ```{note} -To install *yui-compressor*, use your OS's package manager or download it directly then add the executable to your `PATH`. +To install *yui-compressor*, use your OS's package manager or download it directly then add the executable to your `PATH`. ``` To create initial data for the most used applications, run: @@ -179,7 +179,7 @@ To create initial data for the most used applications, run: $ ./manage.py create_initial_data ``` -See [create_initial_data](https://pythondotorg.readthedocs.io/commands.html#command-create-initial-data) for the command options to specify while creating initial data. +See `pythondotorg`[create_initial_data](https://pythondotorg.readthedocs.io/commands.html#command-create-initial-data) for the command options to specify while creating initial data. Finally, start the development server: @@ -190,19 +190,24 @@ $ ./manage.py runserver Optional: Install Elasticsearch ------------------------------- -The search feature in Python.org uses Elasticsearch engine. If you want to test out this feature, you will need to install [Elasticsearch](https://www.elastic.co/downloads/elasticsearch). +The search feature in Python.org uses Elasticsearch engine. If you want to test out this feature, you will need to install [Elasticsearch](https://www.elastic.co/downloads/elasticsearch). -Once you have it installed, update the URL value of `HAYSTACK_CONNECTIONS` settings in `pydotorg/settings/local.py` to your local ElasticSearch server. +Once you have it installed, update the URL value of `HAYSTACK_CONNECTIONS` settings in `pydotorg/settings/local.py` to your local ElasticSearch server. Generating CSS files automatically ---------------------------------- -Due to performance issues of [django-pipeline](https://github.com/jazzband/django-pipeline/issues/313), we are using a dummy compiler `pydotorg.compilers.DummySASSCompiler` in development mode. To generate CSS files, use `sass` itself in a separate terminal window: +```{warning} +When editing frontend styles, ensure you ONLY edit the `.scss` files. +These will then be compiled into `.css` files automatically. ``` -$ cd static -$ sass --compass --scss -I $(dirname $(dirname $(gem which susy))) --trace --watch sass/style.scss:sass/style.css -``` + +Static files are automatically compiled inside the [Docker Compose `static` container](../../docker-compose.yml) +when running `make serve`. + +When your pull request has stylesheet changes, commit the `.scss` files and the compiled `.css` files. +Otherwise, ignore committing and pushing the `.css` files. Running tests ------------- @@ -220,7 +225,7 @@ $ coverage run manage.py test $ coverage report ``` -Generate an HTML report with `coverage html` if you like. +Generate an HTML report with `coverage html` if you like. Useful commands --------------- From 020753a5fd194307a1f3aed1213d1690ab7909ae Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Mon, 30 Sep 2024 16:47:36 -0500 Subject: [PATCH 144/235] ci: add reminder to deploy TF cloud changes (#2625) * ci: add reminder to deploy TF cloud changes * ci: update checkout version * ci: fastly --- .github/workflows/deployminder.yml | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/deployminder.yml diff --git a/.github/workflows/deployminder.yml b/.github/workflows/deployminder.yml new file mode 100644 index 000000000..04774f04f --- /dev/null +++ b/.github/workflows/deployminder.yml @@ -0,0 +1,37 @@ +name: Deploy Reminder + +on: + pull_request: + types: + - closed + branches: + - main + +jobs: + remind: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for changes in infra/ + id: check_changes + run: | + git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | grep -q '^infra/' + echo "has_infra_changes=$?" >> $GITHUB_OUTPUT + + - name: Comment on PR + if: steps.check_changes.outputs.has_infra_changes == '0' + uses: actions/github-script@v7 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Changes detected in the `infra/` directory. Don\'t forget to apply these changes in Terraform Cloud and/or Fastly!' + }) From 672864d1b8c934ebf3f567d491ff2a25386ae296 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:50:50 -0500 Subject: [PATCH 145/235] chore(deps): bump sorl-thumbnail from 12.7.0 to 12.11.0 (#2608) Bumps [sorl-thumbnail](https://github.com/jazzband/sorl-thumbnail) from 12.7.0 to 12.11.0. - [Release notes](https://github.com/jazzband/sorl-thumbnail/releases) - [Changelog](https://github.com/jazzband/sorl-thumbnail/blob/master/CHANGES.rst) - [Commits](https://github.com/jazzband/sorl-thumbnail/compare/12.7.0...12.11.0) --- updated-dependencies: - dependency-name: sorl-thumbnail dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 4877f78c3..200f620b7 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -47,7 +47,7 @@ django-widget-tweaks==1.5.0 django-countries==7.2.1 num2words==0.5.13 django-polymorphic==3.1.0 # 3.1.0 is first version that supports Django 4.0, unsure if it fully supports 4.2 -sorl-thumbnail==12.7.0 +sorl-thumbnail==12.11.0 django-extensions==3.1.4 django-import-export==2.7.1 From 1bfeace44973dff8310f695ca15b40c277047cc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:01:36 -0500 Subject: [PATCH 146/235] Bump django-extensions from 3.1.4 to 3.2.3 (#2564) Bumps [django-extensions](https://github.com/django-extensions/django-extensions) from 3.1.4 to 3.2.3. - [Release notes](https://github.com/django-extensions/django-extensions/releases) - [Changelog](https://github.com/django-extensions/django-extensions/blob/main/CHANGELOG.md) - [Commits](https://github.com/django-extensions/django-extensions/compare/3.1.4...3.2.3) --- updated-dependencies: - dependency-name: django-extensions dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 200f620b7..35b62e126 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -48,7 +48,7 @@ django-countries==7.2.1 num2words==0.5.13 django-polymorphic==3.1.0 # 3.1.0 is first version that supports Django 4.0, unsure if it fully supports 4.2 sorl-thumbnail==12.11.0 -django-extensions==3.1.4 +django-extensions==3.2.3 django-import-export==2.7.1 pypandoc==1.12 From 46fbea644ebf73fc0aa38028690698a4a48a75a0 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:01:05 +0300 Subject: [PATCH 147/235] fix(downloads): remove major version from /downloads/feed.rss (#2630) --- downloads/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/downloads/views.py b/downloads/views.py index 6a7f9d95e..2e48cb2f3 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -182,8 +182,8 @@ def item_title(self, item: Release) -> str: return item.name def item_description(self, item: Release) -> str: - """Return the release version and release date as the item description.""" - return f"Version: {item.version}, Release Date: {item.release_date}" + """Return the release date as the item description.""" + return f"Release date: {item.release_date}" def item_pubdate(self, item: Release) -> datetime | None: """Return the release date as the item publication date.""" From ae76ce1104685aff13136cd99289195434ead7ab Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Fri, 4 Oct 2024 12:30:30 -0400 Subject: [PATCH 148/235] update link to new privacy notice (#2633) --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index a1cfba788..0091c41b0 100644 --- a/templates/base.html +++ b/templates/base.html @@ -335,7 +335,7 @@ <h1 class="site-headline"> <span class="pre">Copyright ©2001-{% now 'Y' %}.</span>  <span class="pre"><a href="/psf-landing/">Python Software Foundation</a></span>  <span class="pre"><a href="/about/legal/">Legal Statements</a></span> -  <span class="pre"><a href="/privacy/">Privacy Policy</a></span> +  <span class="pre"><a href="https://policies.python.org/python.org/Privacy-Notice/">Privacy Notice</a></span> <!-- <span class="pre"><a href="/psf/community-infrastructure">Powered by PSF Community Infrastructure</a></span>--> </small></p> </div> From ab7779fb41ef5783922687c4cee808c96f985251 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Mon, 7 Oct 2024 14:21:05 -0500 Subject: [PATCH 149/235] feat: add shorthand link for downloads/latest/ (#2570) --- downloads/urls.py | 1 + 1 file changed, 1 insertion(+) diff --git a/downloads/urls.py b/downloads/urls.py index f553caeaa..eddef7a10 100644 --- a/downloads/urls.py +++ b/downloads/urls.py @@ -5,6 +5,7 @@ urlpatterns = [ re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'), re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), + re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'), path('release/<slug:release_slug>/', views.DownloadReleaseDetail.as_view(), name='download_release_detail'), path('<slug:slug>/', views.DownloadOSList.as_view(), name='download_os_list'), From 64b737ed539cde0e1eef713cc9d5bf8cb5159b53 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Mon, 7 Oct 2024 15:24:07 -0400 Subject: [PATCH 150/235] fix: Ensure that Box content is rendered after update (#2638) This resolves the underlying problem from #2631. When updated via Django's [`update_or_create`](https://docs.djangoproject.com/en/4.2/ref/models/querysets/#update-or-create), the new `content` for a `Box` is not rendered by django-markupfield's [`pre_save`](https://github.com/jamesturk/django-markupfield/blob/2.0.1/markupfield/fields.py#L163-L179) method unless `save()` is called. This is due to the fact that [`update`](https://docs.djangoproject.com/en/4.2/ref/models/querysets/#django.db.models.query.QuerySet.update) bypasses calls to `save`, `pre_save`, and `post_save`, from the docs: > Finally, realize that update() does an update at the SQL level and, thus, does not call any save() methods on your models, nor does it emit the pre_save or post_save signals (which are a consequence of calling Model.save()) --- blogs/parser.py | 4 +++- downloads/models.py | 12 +++++++++--- successstories/models.py | 4 +++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/blogs/parser.py b/blogs/parser.py index fd5e4b54d..55cf693b8 100644 --- a/blogs/parser.py +++ b/blogs/parser.py @@ -48,10 +48,12 @@ def update_blog_supernav(): pass else: rendered_box = _render_blog_supernav(latest_entry) - box, _ = Box.objects.update_or_create( + box, created = Box.objects.update_or_create( label='supernav-python-blog', defaults={ 'content': rendered_box, 'content_markup_type': 'html', } ) + if not created: + box.save() diff --git a/downloads/models.py b/downloads/models.py index 4576afb2f..415804b6e 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -179,13 +179,15 @@ def update_supernav(): 'last_updated': timezone.now(), }) - box, _ = Box.objects.update_or_create( + box, created = Box.objects.update_or_create( label='supernav-python-downloads', defaults={ 'content': content, 'content_markup_type': 'html', } ) + if not created: + box.save() def update_download_landing_sources_box(): @@ -208,13 +210,15 @@ def update_download_landing_sources_box(): return source_content = render_to_string('downloads/download-sources-box.html', context) - source_box, _ = Box.objects.update_or_create( + source_box, created = Box.objects.update_or_create( label='download-sources', defaults={ 'content': source_content, 'content_markup_type': 'html', } ) + if not created: + source_box.save() def update_homepage_download_box(): @@ -234,13 +238,15 @@ def update_homepage_download_box(): content = render_to_string('downloads/homepage-downloads-box.html', context) - box, _ = Box.objects.update_or_create( + box, created = Box.objects.update_or_create( label='homepage-downloads', defaults={ 'content': content, 'content_markup_type': 'html', } ) + if not created: + box.save() @receiver(post_save, sender=Release) diff --git a/successstories/models.py b/successstories/models.py index e5345b435..cb3fd7418 100644 --- a/successstories/models.py +++ b/successstories/models.py @@ -102,13 +102,15 @@ def update_successstories_supernav(sender, instance, created, **kwargs): 'story': instance, }) - box, _ = Box.objects.update_or_create( + box, created = Box.objects.update_or_create( label='supernav-python-success-stories', defaults={ 'content': content, 'content_markup_type': 'html', } ) + if not created: + box.save() # Purge Fastly cache purge_url('/box/supernav-python-success-stories/') From 102fee612fd1ba57c052cc79810bafa82fbdf400 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:38:14 -0500 Subject: [PATCH 151/235] chore(deps): bump gunicorn from 22.0.0 to 23.0.0 (#2628) Bumps [gunicorn](https://github.com/benoitc/gunicorn) from 22.0.0 to 23.0.0. - [Release notes](https://github.com/benoitc/gunicorn/releases) - [Commits](https://github.com/benoitc/gunicorn/compare/22.0.0...23.0.0) --- updated-dependencies: - dependency-name: gunicorn dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- prod-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prod-requirements.txt b/prod-requirements.txt index cdc543952..72bf30dcd 100644 --- a/prod-requirements.txt +++ b/prod-requirements.txt @@ -1,4 +1,4 @@ -gunicorn==22.0.0 +gunicorn==23.0.0 raven==6.10.0 From 3ad7b968370279f284952ab09de0a12708505afd Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Tue, 8 Oct 2024 15:28:50 -0500 Subject: [PATCH 152/235] fix: links are direct to asset (#2593) * fix: links are direct to assett Closes: #2577 * test: add them * chore: remove unused imports --- static/sass/style.css | 125 ++++++++++--- static/sass/style.scss | 166 +++++++++++++++-- templates/users/base.html | 3 +- templates/users/sponsorship_detail.html | 226 +++++++++++------------- users/tests/test_views.py | 33 +++- users/views.py | 1 + 6 files changed, 393 insertions(+), 161 deletions(-) diff --git a/static/sass/style.css b/static/sass/style.css index c3af6444f..09c849482 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -2350,7 +2350,7 @@ table tfoot { /* ! ===== Success Stories landing page ===== */ .featured-success-story { padding: 1.3125em 0; - background: center -230px no-repeat url('../img/success-glow2.png?1646853871') transparent; + background: center -230px no-repeat url('../img/success-glow2.png?1726783859') transparent; /*blockquote*/ } .featured-success-story img { padding: 10px 30px; } @@ -3354,11 +3354,11 @@ span.highlighted { .python .site-headline a:before { width: 290px; height: 82px; - content: url('../img/python-logo_print.png?1646853871'); } + content: url('../img/python-logo_print.png?1726783859'); } .psf .site-headline a:before { width: 334px; height: 82px; - content: url('../img/psf-logo_print.png?1646853871'); } } + content: url('../img/psf-logo_print.png?1726783859'); } } /* * When we want to review the markup for W3 and similar errors, turn some of these on * Uses :not selectors a bunch, so only modern browsers will support them @@ -3979,25 +3979,106 @@ span.highlighted { .hidden { display: none; } -#sponsorship-detail-container .info-cards { - display: flex; - width: 100%; - align-content: center; - flex-wrap: wrap; } -#sponsorship-detail-container .card { - flex: 1 0 48%; } -#sponsorship-detail-container .card-info { - margin: .5em .5em; - padding: 1em 1em; - border: 1px solid #caccce; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - -ms-border-radius: 6px; - -o-border-radius: 6px; - border-radius: 6px; - background: #e6e8ea; } - #sponsorship-detail-container .card-info h3 { - margin: 0; } +#sponsorship-detail-container { + max-width: 1200px; + margin: 0 auto; + padding: 2rem; } + #sponsorship-detail-container .info-cards { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1.5rem; } + @media (max-width: 768px) { + #sponsorship-detail-container .info-cards { + grid-template-columns: 1fr; } } + #sponsorship-detail-container .card { + background-color: #fff; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + padding: 0.75rem; } + #sponsorship-detail-container .card h3 { + margin-top: 0; + margin-bottom: 1rem; } + #sponsorship-detail-container .card ul li { + margin-bottom: 0.5rem; } + #sponsorship-detail-container .wide-column { + grid-column: 1 / -1; } + #sponsorship-detail-container .assets-list { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1rem; + margin-top: 1rem; } + #sponsorship-detail-container .asset-item { + background-color: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + padding: 1rem; } + #sponsorship-detail-container .asset-item h4 { + margin-top: 0; + margin-bottom: 0.5rem; + font-size: 1rem; } + #sponsorship-detail-container .asset-item p { + margin-bottom: 0.75rem; + font-size: 0.9rem; } + #sponsorship-detail-container .asset-item.incomplete { + border-left: 3px solid #dc3545; } + #sponsorship-detail-container .asset-item.fulfilled { + border-left: 3px solid #28a745; } + #sponsorship-detail-container .due-date { + font-weight: bold; + color: #dc3545; } + #sponsorship-detail-container .btn { + display: inline-block; + padding: 0.375rem 0.75rem; + font-size: 0.9rem; + text-align: center; + text-decoration: none; + border-radius: 4px; + transition: background-color 0.2s ease; } + #sponsorship-detail-container .btn-link { + color: #007bff; } + #sponsorship-detail-container .edit-all-assets { + margin-top: 1.5rem; + text-align: right; } + #sponsorship-detail-container .benefits-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + margin-top: 1rem; } + #sponsorship-detail-container .benefit-item { + display: flex; + flex-direction: column; + background-color: #ffffff; + border: 1px solid #e9ecef; + border-radius: 4px; + padding: 0.75rem; + transition: background-color 0.2s ease; } + #sponsorship-detail-container .benefit-item:hover { + background-color: #f8f9fa; } + #sponsorship-detail-container .benefit-content { + flex-grow: 1; } + #sponsorship-detail-container .benefit-name { + display: block; + font-weight: 500; + font-size: 0.9rem; + line-height: 1.2; + margin-bottom: 0.25rem; } + #sponsorship-detail-container .benefit-description { + color: #6c757d; + cursor: help; + font-size: 0.8rem; } + #sponsorship-detail-container .benefit-category { + display: inline-block; + background-color: #e9ecef; + color: #495057; + font-size: 0.75rem; + padding: 0.25rem 0.5rem; + border-radius: 4px; + margin-top: 0.5rem; } + @media (max-width: 768px) { + #sponsorship-detail-container .info-cards { + grid-template-columns: 1fr; } + #sponsorship-detail-container .assets-list { + grid-template-columns: 1fr; } } #update-sponsorship-assets input { padding: 0.25em; diff --git a/static/sass/style.scss b/static/sass/style.scss index 4fd9a3efd..cb78d9a4d 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -2943,28 +2943,158 @@ $breakpoint-desktop: 1200px; #sponsorship-detail-container { - .info-cards { - display: flex; - width: 100%; - align-content: center; - flex-wrap: wrap; - } + max-width: 1200px; + margin: 0 auto; + padding: 2rem; - .card { - flex: 1 0 48%; - } + .info-cards { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1.5rem; + } - .card-info { - margin: .5em .5em; - padding: 1em 1em; - border: 1px solid $default-border-color; - @include border-radius(); - background: $grey-lightest; + @media (max-width: 768px) { + .info-cards { + grid-template-columns: 1fr; + } + } - h3 { - margin: 0; + + .card { + background-color: #fff; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0,0,0,0.1); + padding: 0.75rem; + } + + .card h3 { + margin-top: 0; + margin-bottom: 1rem; + } + + .card ul li { + margin-bottom: 0.5rem; + } + + .wide-column { + grid-column: 1 / -1; + } + + .assets-list { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1rem; + margin-top: 1rem; + } + + .asset-item { + background-color: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: 6px; + padding: 1rem; + } + + .asset-item h4 { + margin-top: 0; + margin-bottom: 0.5rem; + font-size: 1rem; + } + + .asset-item p { + margin-bottom: 0.75rem; + font-size: 0.9rem; + } + + .asset-item.incomplete { + border-left: 3px solid #dc3545; + } + + .asset-item.fulfilled { + border-left: 3px solid #28a745; + } + + .due-date { + font-weight: bold; + color: #dc3545; + } + + .btn { + display: inline-block; + padding: 0.375rem 0.75rem; + font-size: 0.9rem; + text-align: center; + text-decoration: none; + border-radius: 4px; + transition: background-color 0.2s ease; + } + + .btn-link { + color: #007bff; + } + + .edit-all-assets { + margin-top: 1.5rem; + text-align: right; + } + + .benefits-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + margin-top: 1rem; + } + + .benefit-item { + display: flex; + flex-direction: column; + background-color: #ffffff; + border: 1px solid #e9ecef; + border-radius: 4px; + padding: 0.75rem; + transition: background-color 0.2s ease; + } + + .benefit-item:hover { + background-color: #f8f9fa; + } + + .benefit-content { + flex-grow: 1; + } + + .benefit-name { + display: block; + font-weight: 500; + font-size: 0.9rem; + line-height: 1.2; + margin-bottom: 0.25rem; + } + + .benefit-description { + color: #6c757d; + cursor: help; + font-size: 0.8rem; + } + + .benefit-category { + display: inline-block; + background-color: #e9ecef; + color: #495057; + font-size: 0.75rem; + padding: 0.25rem 0.5rem; + border-radius: 4px; + margin-top: 0.5rem; + } + + @media (max-width: 768px) { + .info-cards { + grid-template-columns: 1fr; + } + + .assets-list { + grid-template-columns: 1fr; + } } - } } #update-sponsorship-assets { diff --git a/templates/users/base.html b/templates/users/base.html index f4e217675..5c11bb471 100644 --- a/templates/users/base.html +++ b/templates/users/base.html @@ -10,7 +10,8 @@ {% endblock %} -{% block content_attributes %}with-right-sidebar{% endblock %} +{# This added an unnecessarily large gap on every user/ page. #} +{#{% block content_attributes %}with-right-sidebar{% endblock %}#} {% block content %} diff --git a/templates/users/sponsorship_detail.html b/templates/users/sponsorship_detail.html index 447b4245c..a2d587d89 100644 --- a/templates/users/sponsorship_detail.html +++ b/templates/users/sponsorship_detail.html @@ -2,11 +2,11 @@ {% load humanize pipeline %} {% block head %} - {% stylesheet 'font-awesome' %} + {% stylesheet 'font-awesome' %} {% endblock %} {% block page_title %} - {{ sponsorship.sponsor.name }} Sponsorship Application | {{ SITE_INFO.site_name }} + {{ sponsorship.sponsor.name }} Sponsorship Application | {{ SITE_INFO.site_name }} {% endblock %} {% block body_attributes %}class="psf signup default-page"{% endblock %} @@ -15,131 +15,119 @@ {% block main-nav_attributes %}psf-navigation{% endblock %} {% block user_content %} - <div id="sponsorship-detail-container"> - <h1>{{ sponsorship.sponsor.name }} Sponsorship Application</h1> + <div id="sponsorship-detail-container"> + <h1>{{ sponsorship.sponsor.name }} Sponsorship Application</h1> - <div class="info-cards"> + <div class="info-cards"> + <div id="sponsor-info" class="card small-column"> + <h3>Sponsor: {{ sponsor.name }}</h3> + <ul> + <li><b>URL:</b> <a href="{{ sponsor.landing_page_url }}" target="_blank">landing page</a></li> + <li><b>Description:</b> {{ sponsor.description }}</li> + <li><b>Twitter:</b> {{ sponsor.twitter_handle }}</li> + <li><b>Phone:</b> {{ sponsor.primary_phone }}</li> + <li><b>Mailing Address:</b> + {{ sponsor.mailing_address_line_1 }}{% if sponsor.mailing_address_line_2 %} - + {{ sponsor.mailing_address_line_2 }}{% endif %}</li> + <li><b>City:</b> {{ sponsor.city }}</li> + <li><b>State:</b> {{ sponsor.state }}</li> + <li><b>Country:</b> {{ sponsor.country }}</li> + </ul> + <small><a href="{% url 'users:edit_sponsor_info' sponsorship.sponsor.pk %}">Edit sponsor information</a></small> + </div> - <div class="card"> - <div id="sponsor-info" class="card-info"> - <h3>Sponsor: {{ sponsor.name }}</h3> - <ul> - <li> - <b>URL:</b> <a href="{{ sponsor.landing_page_url }}" target="_blank">landing page</a> - </li> - <li> - <b>Description:</b> {{ sponsor.description }} - </li> - <li> - <b>Twitter:</b> {{ sponsor.twitter_handle }} - </li> - <li> - <b>Phone:</b> {{ sponsor.primary_phone }} - </li> - <li> - <b>Mailing Address:</b> {{ sponsor.mailing_address_line_1 }}{% if sponsor.mailing_address_line_2 %} - {{ sponsor.mailing_address_line_2 }}{% endif %} - </li> - <li> - <b>City:</b> {{ sponsor.city }} - </li> - <li> - <b>State:</b> {{ sponsor.state }} - </li> - <li> - <b>Country:</b> {{ sponsor.country }} - </li> - </ul> - <br/> - <small><a href="{% url 'users:edit_sponsor_info' sponsorship.sponsor.pk %}">Click here</a> if you want to edit sponsor information.</small> - </div> + <div id="application-info" class="card small-column"> + <h3>Application Data</h3> + <ul> + <li><b>Status:</b> {{ sponsorship.get_status_display }}</li> + <li><b>Application date:</b> {{ sponsorship.applied_on|default_if_none:"---" }}</li> + <li><b>Approval date:</b> {{ sponsorship.approved_on|default_if_none:"---" }}</li> + <li><b>Start date:</b> {{ sponsorship.start_date|default_if_none:"---" }}</li> + <li><b>End date:</b> {{ sponsorship.end_date|default_if_none:"---" }}</li> + {% if sponsorship.finalized_on %} + <li><b>Finalized date:</b> {{ sponsorship.finalized_on }}</li> + {% endif %} + <li><b>Level:</b> {{ sponsorship.level_name }}</li> + <li><b>Agreed sponsorship fee:</b> {% if sponsorship.agreed_fee %}$ + {{ sponsorship.agreed_fee|intcomma }}{% else %}To be determined{% endif %}</li> + </ul> + </div> - <div id="application-info" class="card-info"> - <h3>Application Data</h3> - <ul> - <li> - <b>Status:</b> {{ sponsorship.get_status_display }} - </li> - <li> - <b>Application date:</b> {{ sponsorship.applied_on|default_if_none:"---" }} - </li> - <li> - <b>Approval date:</b> {{ sponsorship.approved_on|default_if_none:"---" }} - </li> - <li> - <b>Start date:</b> {{ sponsorship.start_date|default_if_none:"---" }} - </li> - <li> - <b>End date:</b> {{ sponsorship.end_date|default_if_none:"---" }} - </li> - {% if sponsorship.finalized_on %} - <li> - <b>Finalized date:</b> {{ sponsorship.finalized_on }} - </li> + {% if provided_assets %} + <div id="provided-assets-info" class="card wide-column"> + <h3>Provided Assets</h3> + <p><small>Assets from the PSF related to your sponsorship.</small></p> + <ul> + {% for asset in provided_assets %} + <p><b>{{ asset.sponsor_benefit }}</b> benefit provides you with {{ asset.label }}:</p> + {% if asset.polymorphic_ctype.name == "Provided Text" %} + <pre>{{ asset.value|urlize }}</pre> + {% elif asset.polymorphic_ctype.name == "Provided File" %} + <a href="{{ asset.value.url }}">View File</a> + {% else %} + {{ asset.value }} + {% endif %} + <small>{{ asset.help_text }}</small> + <br><br> + {% endfor %} + </ul> + <small><a href="{% url 'users:view_provided_sponsorship_assets' sponsorship.pk %}">View all + assets</a></small> + </div> {% endif %} - <li> - <b>Level:</b> {{ sponsorship.level_name }} - </li> - <li> - <b>Agreed sponsorship fee:</b> {% if sponsorship.agreed_fee %}${{ sponsorship.agreed_fee|intcomma }}{% else %} - To - be determined{% endif %} - </li> - </ul> - </div> - - </div> - - <div id="sponsorship-info" class="card"> - {% if required_assets or fulfilled_assets %} - <div id="assets-info" class="card-info"> - <h3>Required Assets</h3> - <p><small>You've selected benefits which requires extra assets (logos, slides etc) in order to be fulfilled.</small></p> - <br/> - <ul> - {% for asset in required_assets %} - <li><b>{{ asset.label }}</b><br>Incomplete{% if asset.due_date %} <b>Required by {{ asset.due_date }}</b>{% endif %}: <a href="{{ asset.user_edit_url }}">Add asset</a>.</li> - {% endfor %} - {% for asset in fulfilled_assets %} - <li><b>{{ asset.label }}</b><br>Fulfilled: <a href="{{ asset.user_edit_url }}">Edit asset</a>.</li> - {% endfor %} - </ul> - <br/> - <small>Or you can also <a href="{% url 'users:update_sponsorship_assets' sponsorship.pk %}">click here</a> to edit all the assets under the same page.</small> - </div> - {% endif %} - {% if provided_assets %} - <div id="provided-assets-info" class="card-info"> - <h3>Provided Assets</h3> - <p><small>Assets from the PSF related to your sponsorship.</small></p> - <br/> - <ul> - {% for asset in provided_assets %} - <li><b>{{ asset.label }}</b>: <a href="{{ asset.user_view_url }}">View asset</a>.</li> - {% endfor %} - </ul> - <br/> - <small>Or you can also <a href="{% url 'users:view_provided_sponsorship_assets' sponsorship.pk %}">click here</a> to view all the assets under the same page.</small> - </div> - {% endif %} + {% if required_assets or fulfilled_assets %} + <div id="assets-info" class="card wide-column"> + <h3>Required Assets</h3> + <p><small>You've selected benefits which require extra assets (logos, slides etc) in order to be + fulfilled.</small></p> + <div class="assets-list"> + {% for asset in required_assets %} + <div class="asset-item incomplete"> + <h4>{{ asset.label }}</h4> + <p>Incomplete{% if asset.due_date %} - + <span class="due-date">Required by {{ asset.due_date }}</span>{% endif %}</p> + <a href="{{ asset.user_edit_url }}" class="btn btn-link btn-sm">Add asset</a> + </div> + {% endfor %} + {% for asset in fulfilled_assets %} + <div class="asset-item fulfilled"> + <h4>{{ asset.label }}</h4> + <p>Fulfilled</p> + <a href="{{ asset.user_edit_url }}" class="btn btn-link btn-sm">Edit asset</a> + </div> + {% endfor %} + </div> + <div class="edit-all-assets"> + <a href="{% url 'users:update_sponsorship_assets' sponsorship.pk %}" class="btn btn-link">Edit + all assets</a> + </div> + </div> + {% endif %} - <div class="card-info"> - <h3>Sponsorship Benefits</h3> - <ul style="list-style-type:none; margin-left: 0.5em"> - {% for benefit in sponsorship.benefits.all %} - <li> - {% if benefit.description %}<i class="fa fa-info" title="{{ benefit.description }}"></i> - - {% endif %} {{ benefit.name_for_display }} - </li> - {% endfor %} - </ul> + <div class="card wide-column"> + <h3>Sponsorship Benefits</h3> + <div class="benefits-grid"> + {% for benefit in sponsorship.benefits.all %} + <div class="benefit-item"> + <div class="benefit-content"> + <span class="benefit-name">{{ benefit.name_for_display }}</span> + {% if benefit.description %} + <span class="benefit-description" title="{{ benefit.description }}"> + <i class="fa fa-info-circle"></i> + </span> + {% endif %} + <span class="benefit-category">{{ benefit.program.name }}</span> + </div> + </div> + {% endfor %} + </div> + </div> </div> - </div> </div> - </div> {% endblock %} {% block javascript %} - {{ block.super }} - {% javascript 'sponsors' %} -{% endblock %} + {{ block.super }} + {% javascript 'sponsors' %} +{% endblock %} \ No newline at end of file diff --git a/users/tests/test_views.py b/users/tests/test_views.py index 83b8330f9..28fc649ca 100644 --- a/users/tests/test_views.py +++ b/users/tests/test_views.py @@ -1,8 +1,9 @@ +from django.core.files.uploadedfile import SimpleUploadedFile from model_bakery import baker from django.conf import settings from django.contrib.auth import get_user_model from django.urls import reverse -from django.test import TestCase, override_settings +from django.test import TestCase from sponsors.forms import SponsorUpdateForm, SponsorRequiredAssetsForm from sponsors.models import Sponsorship, RequiredTextAssetConfiguration, SponsorBenefit @@ -448,6 +449,36 @@ def test_fulfilled_assets(self): self.assertEqual(1, len(context["fulfilled_assets"])) self.assertIn(asset, context["fulfilled_assets"]) + def test_asset_links_are_direct(self) -> None: + """Ensure that assets listed under 'Provided Assets' in `/users/sponsorships/#/` are directly accessible.""" + # Create a sponsorship with a provided file asset + cfg = baker.make( + "sponsors.ProvidedFileAssetConfiguration", + internal_name="test_provided_file_asset", + related_to="sponsorship", + ) + benefit = baker.make("sponsors.SponsorBenefit",sponsorship=self.sponsorship) + asset = cfg.create_benefit_feature(benefit) + file_content = b"This is a test file." + test_file = SimpleUploadedFile( + "test_file.pdf", + file_content, + content_type="application/pdf" + ) + asset.value = test_file + asset.save() + + # Then we can read the page + response = self.client.get(self.url) + content = response.content.decode("utf-8") + expected_asset_link = f'href="{asset.value.url}"' + + # and finally check that the asset link is ACTUALLY pointing to the asset and not the list view page + self.assertIn("View File", content, "View file text not found.") + self.assertIn(expected_asset_link, content, "Asset link not found in the page.") + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "users/sponsorship_detail.html") + class UpdateSponsorInfoViewTests(TestCase): diff --git a/users/views.py b/users/views.py index 23140853e..f73172296 100644 --- a/users/views.py +++ b/users/views.py @@ -324,6 +324,7 @@ def form_valid(self, form): @method_decorator(login_required(login_url=settings.LOGIN_URL), name="dispatch") class ProvidedSponsorshipAssetsView(DetailView): + """TODO: Deprecate this view now that everything lives in the SponsorshipDetailView""" object_name = "sponsorship" template_name = 'users/sponsorship_assets_view.html' From 452480d1b3a496e74d594a6614acb88620f85548 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Thu, 7 Nov 2024 12:33:44 -0500 Subject: [PATCH 153/235] disable logging to datadog by default (#2653) * disable logging to datadog by default When the logging_datadog section was added in #2519, there was no logging condition applied leading to all requests being logged to datadog. this adds a "False" condition so that logs are only emitted from the rate limiter * rename response condition for clarity --- infra/cdn/main.tf | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/infra/cdn/main.tf b/infra/cdn/main.tf index 059fd8977..91cac411e 100644 --- a/infra/cdn/main.tf +++ b/infra/cdn/main.tf @@ -136,6 +136,12 @@ resource "fastly_service_vcl" "python_org" { statement = "req.http.host == \"python.org\"" type = "REQUEST" } + condition { + name = "Always False" + priority = 10 + statement = "false" + type = "RESPONSE" + } condition { name = "Don't cache 404s for /static" @@ -262,9 +268,10 @@ resource "fastly_service_vcl" "python_org" { } logging_datadog { - name = "ratelimit-debug" - token = var.datadog_key - region = "US" + name = "ratelimit-debug" + token = var.datadog_key + region = "US" + response_condition = "Always False" } logging_s3 { @@ -361,7 +368,7 @@ resource "fastly_service_vcl" "python_org" { dynamic "dictionary" { for_each = var.activate_ngwaf_service ? [1] : [] content { - name = var.edge_security_dictionary + name = var.edge_security_dictionary force_destroy = true } } From bc51c6003f6e1b2811a782410777cdff64c8c7cf Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:07:58 +0200 Subject: [PATCH 154/235] Hide GPG column if no GPG signatures in release (#2656) --- downloads/templatetags/download_tags.py | 5 +++++ templates/downloads/release_detail.html | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/downloads/templatetags/download_tags.py b/downloads/templatetags/download_tags.py index c72f6d58c..f61f25ada 100644 --- a/downloads/templatetags/download_tags.py +++ b/downloads/templatetags/download_tags.py @@ -8,6 +8,11 @@ def strip_minor_version(version): return '.'.join(version.split('.')[:2]) +@register.filter +def has_gpg(files: list) -> bool: + return any(f.gpg_signature_file for f in files) + + @register.filter def has_sigstore_materials(files): return any( diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 720887074..0ddcde32a 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -1,6 +1,7 @@ {% extends "base.html" %} {% load boxes %} {% load sitetree %} +{% load has_gpg from download_tags %} {% load has_sigstore_materials from download_tags %} {% load has_sbom from download_tags %} {% load sort_windows from download_tags %} @@ -51,7 +52,9 @@ <h1 class="page-title">Files</h1> <th>Description</th> <th>MD5 Sum</th> <th>File Size</th> + {% if release_files|has_gpg %} <th>GPG</th> + {% endif %} {% if release_files|has_sigstore_materials %} <th colspan="2"><a href="https://www.python.org/download/sigstore/">Sigstore</a></th> {% endif %} @@ -68,7 +71,9 @@ <h1 class="page-title">Files</h1> <td>{{ f.description }}</td> <td>{{ f.md5_sum }}</td> <td>{{ f.filesize|filesizeformat }}</td> + {% if release_files|has_gpg %} <td>{% if f.gpg_signature_file %}<a href="{{ f.gpg_signature_file }}">SIG</a>{% endif %}</td> + {% endif %} {% if release_files|has_sigstore_materials %} {% if f.sigstore_bundle_file %} <td colspan="2">{% if f.sigstore_bundle_file %}<a href="{{ f.sigstore_bundle_file}}">.sigstore</a>{% endif %}</td> From f625b90d04f0015c4c908aeee8228f31635f1aac Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Thu, 21 Nov 2024 14:28:43 -0500 Subject: [PATCH 155/235] Update sponsorship-agreement.md (#2660) --- templates/sponsors/admin/contracts/sponsorship-agreement.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/sponsors/admin/contracts/sponsorship-agreement.md b/templates/sponsors/admin/contracts/sponsorship-agreement.md index f1e2f2e9f..73540dbab 100644 --- a/templates/sponsors/admin/contracts/sponsorship-agreement.md +++ b/templates/sponsors/admin/contracts/sponsorship-agreement.md @@ -33,9 +33,9 @@ and international community of Python programmers (the **"Programs"**); and the PSF previously entered into a Sponsorship Agreement with the effective date of the {{ previous_effective|date:"j" }}{{ previous_effective_english_suffix }} of {{ previous_effective|date:"F Y" }} - -**WHEREAS**, Sponsor wishes to renew its support the Programs by making a contribution to the PSF. and a term of one year (the “Sponsorship Agreementâ€). + +**WHEREAS**, Sponsor wishes to renew its support of the Programs by making a contribution to the PSF. {% else %} wishes to support the Programs by making a contribution to the PSF. {% endif %} From c68d9e4a1a8d954ac3b01f79f08a570a4bc1a5b8 Mon Sep 17 00:00:00 2001 From: Nice Zombies <nineteendo19d0@gmail.com> Date: Wed, 27 Nov 2024 13:39:16 +0100 Subject: [PATCH 156/235] Replace `pyton.org` with `python.org` (#2666) --- .github/ISSUE_TEMPLATE/BUG.yml | 4 ++-- .github/ISSUE_TEMPLATE/DOCS.yml | 2 +- .github/ISSUE_TEMPLATE/REQUEST.yml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG.yml b/.github/ISSUE_TEMPLATE/BUG.yml index 9adc2b03a..f75b4a61c 100644 --- a/.github/ISSUE_TEMPLATE/BUG.yml +++ b/.github/ISSUE_TEMPLATE/BUG.yml @@ -1,5 +1,5 @@ name: "Bug Report" -description: Report a bug with pyton.org website to help us improve +description: Report a bug with python.org website to help us improve title: "Bug: <title>" labels: ["bug", "Triage Required"] @@ -7,7 +7,7 @@ body: - type: markdown attributes: value: | - This is the repository and issue tracker for the https://www.pyton.org website. + This is the repository and issue tracker for the https://www.python.org website. If you're looking to file an issue with CPython itself, please click here: [CPython Issues](https://github.com/python/cpython/issues/new/choose). diff --git a/.github/ISSUE_TEMPLATE/DOCS.yml b/.github/ISSUE_TEMPLATE/DOCS.yml index df7a2c231..2f216878a 100644 --- a/.github/ISSUE_TEMPLATE/DOCS.yml +++ b/.github/ISSUE_TEMPLATE/DOCS.yml @@ -7,7 +7,7 @@ body: - type: markdown attributes: value: | - This is the repository and issue tracker for the https://www.pyton.org website. + This is the repository and issue tracker for the https://www.python.org website. If you're looking to file an issue with CPython itself, please click here: [CPython Issues](https://github.com/python/cpython/issues/new/choose). diff --git a/.github/ISSUE_TEMPLATE/REQUEST.yml b/.github/ISSUE_TEMPLATE/REQUEST.yml index 144ad75c1..c0f29e2c0 100644 --- a/.github/ISSUE_TEMPLATE/REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/REQUEST.yml @@ -1,5 +1,5 @@ name: "Feature Request" -description: Suggest an idea for www.pyton.org +description: Suggest an idea for www.python.org title: "Enhancement: <title>" labels: ["enhancement"] @@ -7,7 +7,7 @@ body: - type: markdown attributes: value: | - This is the repository and issue tracker for the https://www.pyton.org website. + This is the repository and issue tracker for the https://www.python.org website. If you're looking to file an issue with CPython itself, please click here: [CPython Issues](https://github.com/python/cpython/issues/new/choose). From 1da2a8a3d5de8f4be8d043625e9fcb0bbef2183a Mon Sep 17 00:00:00 2001 From: Dorian Adams <104034366+dorian-adams@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:14:18 -0500 Subject: [PATCH 157/235] Default primary contact field to True for first contact (#2648) Co-authored-by: Jacob Coffee <jacob@z7x.org> --- sponsors/forms.py | 5 ++++- sponsors/tests/test_forms.py | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sponsors/forms.py b/sponsors/forms.py index 4ced017c9..33b299322 100644 --- a/sponsors/forms.py +++ b/sponsors/forms.py @@ -285,7 +285,10 @@ def __init__(self, *args, **kwargs): if self.data: self.contacts_formset = SponsorContactFormSet(self.data, **formset_kwargs) else: - self.contacts_formset = SponsorContactFormSet(**formset_kwargs) + self.contacts_formset = SponsorContactFormSet( + initial=[{"primary": True}], + **formset_kwargs + ) def clean(self): cleaned_data = super().clean() diff --git a/sponsors/tests/test_forms.py b/sponsors/tests/test_forms.py index 49b0515cd..c375b9a2b 100644 --- a/sponsors/tests/test_forms.py +++ b/sponsors/tests/test_forms.py @@ -534,6 +534,15 @@ def test_invalidate_form_if_no_primary_contact(self): msg = "You have to mark at least one contact as the primary one." self.assertIn(msg, form.errors["__all__"]) + def test_initial_primary_contact(self): + form = SponsorshipApplicationForm() + formset = form.contacts_formset + + self.assertTrue( + formset.forms[0].initial.get("primary"), + "The primary field in the first contact form should be initially set to True." + ) + class SponsorContactFormSetTests(TestCase): def setUp(self): From 4efdd87cce3bde83b06d7aa702f42a2b36a5c8d9 Mon Sep 17 00:00:00 2001 From: Nice Zombies <nineteendo19d0@gmail.com> Date: Mon, 2 Dec 2024 16:18:05 +0100 Subject: [PATCH 158/235] Fix code prompt in Fibonacci example (#2665) --- codesamples/factories.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/codesamples/factories.py b/codesamples/factories.py index 5a52b9738..3fca25177 100644 --- a/codesamples/factories.py +++ b/codesamples/factories.py @@ -122,11 +122,12 @@ def initial_data(): <code> <span class=\"comment\"># Write Fibonacci series up to n</span> >>> def fib(n): - >>> a, b = 0, 1 - >>> while a < n: - >>> print(a, end=' ') - >>> a, b = b, a+b - >>> print() + ... a, b = 0, 1 + ... while a < n: + ... print(a, end=' ') + ... a, b = b, a+b + ... print() + ... >>> fib(1000) <span class=\"output\">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610</span> </code> From a1cb93932ce5cee332e5b0fea8b9492351f77c51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 15:03:22 -0600 Subject: [PATCH 159/235] chore(deps): bump django from 4.2.16 to 4.2.17 (#2673) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 35b62e126..4adad74c4 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.16 +Django==4.2.17 docutils==0.21.2 Markdown==3.7 cmarkgfm==0.6.0 From 1d4331c4c2ce20397282d216975c5f205a453ffe Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Wed, 11 Dec 2024 16:09:31 -0500 Subject: [PATCH 160/235] remove vendored retina.js, retire @2x logos to default (#2675) --- static/img/psf-logo.png | Bin 14117 -> 19844 bytes static/img/psf-logo@2x.png | Bin 19844 -> 0 bytes static/img/python-logo.png | Bin 10102 -> 15770 bytes static/img/python-logo@2x.png | Bin 15770 -> 0 bytes static/js/plugins.js | 24 ------------------------ 5 files changed, 24 deletions(-) delete mode 100644 static/img/psf-logo@2x.png delete mode 100644 static/img/python-logo@2x.png diff --git a/static/img/psf-logo.png b/static/img/psf-logo.png index 7f63aea5041e88f26907237a7131f989a0c975e1..0a7f8e715b18959a0327ba400905b0eaa34ba2a9 100644 GIT binary patch delta 19117 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 VbI!m1AOWbz;5ta{QkYfnzX43<Z5aRn delta 13345 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�_@K910bvPw-SoZmgHO2MgOdu=+6>`yG@}Cpw|Fh+2hzPe zgb?4sqn3z*#4?n2cwoOT@r6nA99H468_?bKrz!};YaAoU$;J8#lwlU&75K&N04?jr z^h=-<slY5e$xmVBkInH_hPzCznwoQy5C->6(E41&Tq~)!q&@MUri5<lj~{zKGkfe8 z%V}Cwx;^vfum1I-B1pdLSWSTF4<KjpIJ@!RfF-=p)nRf_C(hbHKd|wy$nodBy}f|$ zB7ziF+%an}zPXOCwT$;sc_%il6U}9ftKRr$`Y$Th_=mr>N{ijY*QEWWeoN|jC%u2j zuCl-{DJ3uk^1x<~@ns7B2-oztA%^oL&G=`TIYqn>RDRG)Rmk079D)s6xEl&x)SO>c zkP`lS)%rO@TJTa{J<qE+-S;2BUFdMGymhV3IBQDdF-fv$q2#pIX>6rb#pKb2h;Y}e zDFvWz{}4g?0zfQJcO=o!&=C1BBBZynGCjnv?)io)iI+fw1>l8k>84sQrbG`ut!=sY zfN-H?K(-C3M{JdD<0z;Zez7&FW*ufM{H%L)-pAa0CPxhP!EL_BO=;$NlC7qlKtHdv zG^>`4TNf!9Tr%RA2QE|bXiwmTLkQlyd&*WO-BuLijtndmwjj9Ww8vXfg;A|~$>iGa zMt007t;B|MhyPrk3{3pmUcV|Z|4R_VxGShK(e0Z@OH&ri1rDeLh0z&PFZ5JN(Q)3M zMK}mN)BNjN)owLQf5Hvxwd7C56bbg3Rm(S<&3-B+9LB>rZZn^@5Zs)j!R1JthAbZd z^wmO{R%p#Uvz;(*=O{vGi~(K*4OR9r^3D<uJ$*zIoGFag`F&wTgUvKv2y!6uTEVZA zHiTYe7?pg1>>kj;Ip2-70#hcxYd5nkQ;o!PF4RsZV7Z7JULp`i$7=A!H)-YAI7oc) z;C$gBQar}g(TfS&9;%P*%kritq92eDM4nV_j+G;UPmo2kX5~gShk|_bCP69#91Wxs zT8gBzGu(pWc^mnCpHL9TEg)ck-oKlrTU1mehK`2TZ3;T-9W|Pmghg-m(gJb+8pCrl zRW;LuRtZ%9nPn67dNV7^%6*p*dv!y}$a8v8-U=;`wc1D{w0KW0R<E(JMNK%&Waw!E zq3dyMCegeeU-%(JsU}KXe9T(qMoa?;r%Q?X#SFt<;45zz*|Dbe0XO^CM{SIN-7S=h zF@_Y`I1o{RUq>4iGqj)>`nR(N4vI=%qPQX`;JUgOe@;E0*9+R(BfO*!EGywax8X4{ z(ZPHy#!5NX<8_y}Hz`+u@k^V!m*{uso#~0LNy>{a`drK>zlMGDNTW8D@?@QUUre3M z|4y!8hMQWyBho%5|AH75RexP?lbvXuQfk!Ewh5v_(?btYEC7SOD@pcFe<+;3cOGP8 z*=8bxy^S}X=ZmWs(Q?fmFB7do;IY(Vbs0JQdWExO5%}+ZmR})hx$eG=4C9KoHm7O~ z_n!_?WOS?6(A=cZIhh@-Cj)o<3Bt^8gxB~X=r#wXvg?Z%OU@Nu1(JHHO4Thx7JWPf zf2ns6Hm&@muw^Oe`>A}#F@9Ao#rK>UP4ut*Vgrq6;R};TKuo=rZmnAf=XL_4u~v7v zAddwsrts!hsZ${r?xHjCs^C;r-a{MuV^e_)))ng|YEi{iW(!g!O;*&5@VXIcHeBni zHA|IM@N2LCodwF#gE6W3%qM!;hIYlP0T7>WM7Rx?fxRv~lNAR+>;m0By;ekMBpq!~ z?&(75TqOo~+3&JUTlCC|q(p*)jw*kyT@zT=9LhxfXyk`tk|*D($^D+|T0Cp~#Lz}8 z8@_5chSRMQ>$tRS7coZ4x+`Xy>6JvB3<iwbYNyOwk7lia-!+7#?2hqw9eJ9sPau1L zJ~NJ~+iH6BTb7Y&7>DJwLKWb59#&j!J{gHuW;V?G0s-muEnRy&N_USq{~?9An_S0B zIyjx&C%AA!XOeC3P+Qe@5P=bYf--3TsynW5-~R+Q(8Rl$39pT@-=g><XKk^P5QA_f zJDp`w!K(m=Lua)l^NcO!h46;b6?C?1+Jy?NlHL^&BXVt@@St2GUZM?>pf`djNIzFr z^xa?XPJa~R7baSJSpifxN-)Nj1$lWF+1c6EhJ6wQ>_6k^q3pU#8@I27<VsCH$QpbF zM${uT;g8Wr7nw97H=!4vo@m$?3D+dDZrCB^ut%IURWS~ooHoRQB~6^BK%tL2(mvUr zYSRP~k~bZ=&$?AKuq#4Wjw|+3e(BqHSpDLk#8)+Wjaku?`ZZSFS9LMt*do3~_aB;s z(A`xLCMJ8*VA}$lSnOj{U%}xY&()9U2Q_4y_caddN31VLf7sAt$!5>QpmsxU2F?bv znbz+p33qUzJ8+=pSvl%K=1e0cbWvnMqCJh&KLQ9X6$Tvn5LO?leh$PiSz8zs>&^WK zir8;2B}jm$gvThdn$1yKk^L3ARps=wKC2|bTAsd{@ZWX~;eM)6JwHERPGt);z^o*W zPEWHZtd!zW*_LQfw5mv;i(H&A^qq>e9&W%|ZX;mxKVi^^_sD@lPCdUDV~kuC_O8aS z<nW$MUKOdAp0sVthBS~inG`CfOGO`V>|M9kjaYqebZw!_PHT&XQr+OjE2ZTvVksvQ zVZY)F4}@JF0x2cP>{Lo7)S<b~6J$g4rl;PRHKIvpNSxDsPmK$N$Et5=!0&5l{C1ge zMR2Us_pNI4g2DkLHlz~YP;K&pBjGU_y7lK(Z0=0xhrxlGyYL3S?j%a}2!Stt?+Ls% z9O(^z;(0e<YOX#miCRuJ+P;9Hmx9Z!XuV#(ruattPAFny5bE9&`|Oe~CzHDTtSKfs zdL}jSPgbMrD08qg&y=hAym6ELVjE=VclZF~8>q&^)V_lHEA#WqigJWv>btB`OgyO{ z?BqUhfLkTYB5Yiqa3ze2nBc6R7PiUqH>z@lI2>LUH*3qbqO~gFnu(@r7ic68&u9e{ z5pzGGFP$=5EO<;qxQ>Vhx<eE&lR;tzgrY@{T`EwU(i!K1ndI46v{#)pSE%0)PbZFI zmOMlQ6p26shZpLqHDbp+-y>UnxM}@H?}I>jt98~df4A<l?m@-(lI|TddHN#0>9E#K z2?5X@jxve+Bpr=Ex|Yw5OkZ!F4?1JIH5Zk*q1q+B!B4I})k<x22fn(fW7Z4HCom@j zyt-HU*@;ZsyJZ923L!GBRH<u?%2B4_Y%60?+8n6TfZL?Q>yoG;`4lrnOH-3AMQ*hd zBiqw0hHH`-hsP6#1A~G7$6j0JUYK|G$2Sk4ke>l7K}`}gPN)VmIyeI06VKJb&ls$d zXyT1tS3@Q#8x2<N;K=v+nR<=K3Pa>MXjQN$T3Y$F_;6ieoH_K_&5-<~F-ZSyyrj~r zxfFz3P>oh>CZr;4oTbXJKA|kq!^iL{eUy^c(J67OtRrll;qIEu^7CLZ!30nQzE$#z zRSnEZ?6Tdw*Mur%ht)%c>NuUas*Wf9w^H}{RitjbFOU-Vr#D1VE<=3=K4LADPu4F| zwOjlN_XP7*GhqB)r$fyed_q4uJp7e3MhjBRrM#oQD>iS^+I@tJRhc7}&`neAL#OWr zsb()H2{A&~UvH~p_sLV4tVLZs5?K9)ZW?F071--!Nztlp!fKoRF{WzBE@CIL+D^$U zv$McvoGX~G-Rt{4!k&g$szlxS8YkfRjb=Eh5rv+=$qtVMFH8R#O7mc9o!$rjYc)uG zZvAtt-f(hdY~g&{^OCk1x2nrwK?GTOYI?d)P3$TnMAFt;lfpD3KKo0ukG9tvow?z; zY+{w`ZCpmx)2&e?E9twKTzXS!)Z#3(U?ylJ2T{wV^5Z*itI<gXaTW&=Imzy-B{#+o zj0SZUu=HiOid4~2v&uvo*x;I_m_WTus*bFqXcm+>iQUC4H=gX*a!Wqn1wRi6)FmxQ zG)33<V=s`XcZHcWR8?l*h8$s3<uSl-Xo!%jErJ4Q<-4$8N`En2hjX%ng=gKINhBM0 zef!+c2dZ%@dSx(C%+{%ASXlkFyOzrX*n{B3$4SQ5GQaXoAG^5x*_`XL$O26ZgC|^z zX7$tRoTwTEJ`U5&uC!`*t)xb*nsudwNV*$J3etRwanIXm=;?(P7b7vLnKrYBAlASp zZ1V?cAaA(7oYQau`S$WW&|G}Su*sfR)!07D30nDKAQTRTFL{jqcj}vR#)98jB$DMt za<#s_E7IIP!%U|{4x@`d5~x@A>~~o|(C<Z^#Za+lAD&Ey&~wuW$*XT@)$b<l6C(a^ z`|U)HRk)fEZsx<-M34Iouc_(nBB#Th>9N!IT1)7SiX*mk3%g*AMOnp~{i+e5iW2|E z%dB2Jr8PAo+RA61E50kr_1I7}L0p5R*wu*+pPRyD{>y{W<nIt48#KJ~E(8XHD<-oA zz)mL@WWS<(zX`8xwV!_aW6<U2i8t<bs_XEHiFjYS_M3!_v%LJsr;_+q$X4%KhN!yg zYG*bOX(&NXT6%+7Fx)oljl5AoLMBy3Mpqrf|0fQ+n{p}4=g&X=rRltL`=FYheLJC5 zVKx8y=Z5}nC5$M=1}RE0_(W-Skp0U0M>puQFHNY~U+rtEtJ=m>a;WKdkKC;Z+d?rw zn)%{Jl6KDP>drA|s`lb3A_pvb#g&S;6J?{DMa~T=mK$d3{f%5+n8}tHN-~}sIP9*5 zNgjzR-|D^Pd)xtG*g-(Ym0DSQK=kp=BO$kS<=FVRL$Ba>Q1I%7A;f>+;w9diEt13E zo08lU8Tn1oUDq2f>IH|IZhbtJ^GEFcZa#`U;BTL3KtVcx4o>e2*1<JX1@ykZ2LvW4 z!lHHq@Of7uthNcFA@1VB3YWz1^?baXyX411n=H;kM6K)V?Vf+a8=d+agGli`A$$gA zxmI8*GFs3N_oTHO*H0Zkj+V26KE^m|0l315TCUxZ8GoEET+?W?{lbWm{Vnfg?@6{T zqqM?4O3(`8aW2S;3ovzZ{8Q9T{^{td>e|oy3CLw{|Dma0u=!2;fIS0m#F(-z;(D~* z`gP1Wy@lv9ZE8Ldr#TZGW|b;Ws|PLtGf51N;uM1D9r!jfy<apXG8`8Wa##v|!ACVg z5E&@~Al?JR2W$;|ePE?n2vfI#Fmk8eH=d_=wUd;b0UdIE@7>*9{!--(E~xalGZ;kD zr{#@}4H+t*!ku$cib;HmsXz!w@PnEUZakakA(kR*r%s1)c&UJ3;XE5_Yrig8@|7!6 z5F)byN9fx_z-80&)+vNZ{Vrwc5Qa549*DwD%M<Xh#yglzHLIlVG8KD^Veei+zMsXt zb;JN~G}>vAj9BK!Z-u?A0`9TtLg`XG_<ujM@4UAClL$Sc%I=AJb?;_)Wes1uT@i@s z_-(?YvAg!FO`=?=T$InB18rM?YIKkf0`p8RLnCV@sNa)%d-P<%2awN_AiL9QEVs<x z#+6!`AIfBY=t=u3RM~#?^4`v#o}OMad_rV9c3a~+80k@&dcQk0a-%Nw;y<+Jb-nm8 z;P^_HvtKsAwRogcUd8C$Ftw4qnUJlEQ$VgN7yG=V(t!W3YjD|7t8p8^E#+AaLgpB@ z2UvfGxc<YjWFmrj<$S-F7IuA2>DOOSB^XHc=NQbD*vt+-k?Q-rK;$d92klP_vmtv! zVoykREuF`?{-WU&<&<>xO6Ad6Iy+g!v!ma3BE+fuZU^;5TNUxauOF}1Ai${?La$wd zQC0ymsyNuXC+Iz#Tr}Vb9Z(6<f)oL<e$UbBv$9IQ=R^vG19XD-lrpVSWH&drnq4L; z7VeZD;>O|XVKV;<f`ey6UES0s&-0~4YHDhu^vR=g%fLOQgM8tvf@<>hHV>Qbn%hG= z64Aux1+OO}xH{a0UCx9xJo3_MngS+K=r#1am+=&&sr==D-LXQs3oTHLYiMf-&h$3U zxg)ISQ@&w5_6%m^!`#~`gDX{5T9!n!dQ%{9GL1jfcgRkTm@%?jeD#t#h0vw+v;&L9 zgI#^`Rl?sG9PJkUBgoopY_d3q`aSed_30h_-rss`{%aU49D<@!mLvv_AuNGt23z>^ zs9C0L629HL;(E)hCo&L$`n~KoK@n~i78X({OdZ334E(Pf42bs>C(>DTAEv()alh~i zrLh>yeV!{;==jU;4NcmHA$W&quFbvk5#Y8(1x*PJTLM+USAt}xHwaG0I~YYZcQuEc zn%E&aRY@xAoW6<9e8ob5+YT~t+$mKDjJgvZIr+bZ_s8vj<N#2?YxdXCU;s=gFZS2o zkIpp<yhm-+<``<SNd6g>pzorAFUkhp0nhRyV1w+1`1`OOL|<n(->da1qm~bjov-27 zI+%`}rVK_z3zymq=jM_7@k%1A{8sZ27*bzPxDi}Mh9HFq|H6oFjVMJK0B3;}R)oPP z!689_Xo2G4!~_cK#$c0tg6~&_7|1kICosE2U1;;DA-$t>FQ57&?pE@G$ig{@Bw-Lc zD0gxj8YnA6IbcIECGip6Fj5%~{=s(HaD=r_JX0X{Aul7$Zx37>*$SvMZphh*1jw8Z zvUDt);pO4>gE6=$rALmH{O?RX1J(~uJsTdkM7?*m{6LrFxkQ>mB?;zDOE%sTdrn{= z3^eS<qYA9bFVFpIK7u6)#C#MA*u51K1wR%p{pyu$rkOI6&<lMM{5#{dsCnP4l1b$t zkNqnl{s6cX_YwelM-W7nOcQ%KDT@0B|LMhjB#{y(<PvpY(i5t4#T)Tv#^6Kt`nld} zyc_QR6%+wJp7w9jg86DYPY!y!848Ai(G|O2(Avks!fKZwx-Z)`F^*0}Io*J^_QdS9 z<o|v48c!}3ggQqRgU=ohlkd?P3Kcs0=c@}e!6*3pCVs#)gM15au~D+0JKWjgPefE2 z8;Xy^-ly7Fl7(d4bklbJ!|&&l5X)E}%FUdx3WO0sUb`-~xf$W1V&;4Ja}foPWrfdq zqcx;AJ_0(pIas)e$kr$Z%?(#V<d@BtFUEq9CNed3wQZM`+TC(`uy%nXeV}@?GQ;{Z zhFt!o!m)3UpywIM`C>&{yEiS(0f#O3W?7Z0ihEht70ek%-!;8<=Vfa*sorE`NjVFb z0_a(25?#HcXwLi=?f#0MySX2i$2_}rjb0~pdt4iLyJ9bpT+)DR{3$Pg%Qe|?hCH9+ ziF$uP<>!9ck!Mu-U-!PzTgBHc(}I%da*lL`v57WKly>iH)!-a?16+<Nru(c#JRb+1 z`)XVlzKPSPY~r+kXMWyIOC8N3^=Svho1hELf!~WEBmw~(?_D+}q#GB)DB|X#UykAW z;o#2REMkwft<lq=fLf2FQ*HJ<uc@{W>!=ZdBh?Huz_FMQm`={;xUz|WP9{uc`t5-m zFx8F&lu;j-+6jx#45!dFlrZ{_UA*B2b0a`O1t*V~MZ^34gTMWtIU*%QYXtuQK@``w zD6C=!j1cU(Jt$abXe00`F<c;HqeyvluN}FS0wo&93|ULSELnFV#1;4fIS(;am`a~~ z{b5{qlP^+|TgRi$i2nlbm;|&Pr}=Q3Ic56%h(AocW|Sqa29ims1DCMpyNfSSW18Hr z!exZ^Jc-7JumSmqITO+;{Hh@JC8|o@woL!hu+z-4_Y-o;MiDLr+HC{!(rmk1GuUjh zvsy0VA_TM?=#WOGNS}W-mm>eB;Ug8%C~Zo{lFYAeVcya1pYFwVb!D{82?_4UjZfh5 zcn5r=dA9i*uOPi`xJcQ2y0-W3=llWNZ5Yb8Pv*;}?u1Xb?e@A`uW=x@vHl^0Oy7V* z#=5#XV~84Gespvsczbz#oL1=>p-7|Kpo{R&zgK~vrUk#ILA@bjZz-kodoE1u0V-;u zJ6;uG7xsp=%28!~rAddb&gAf<(OJ`_0dx7gl!#9ZEk<Uqh0_s<3-@94zdt~0;!&W) zL$%1;P#c-68|p#iyb|aIRx_K*V=k8h)0njlBN;clO7!8;oD-(tQcpEEH{D4h6DEXI zB4-Xa+JkAtgMlGX9(htmIuXRa%3Q@I5o?f{*r=N>cwFp@ot<pa;Lwwz)ioqg6IyA7 zV?(`myuE`>3F0iHaG_mOj&B8Ws(v@bpWn+~(^iM{B;i6_MNk!!fA(F_4wfqxsp6>& z-8j42gR|B`oWZKGSFBd|+idc(0fX<hFJQ8_BrHtKRxGUvZsA2sy*@h6)kGG2J!TA# zP8M51c^3IRh$~T6Rt8x#h{&`~WEpGaL6+CNx*i%@)lZxr<|Ol_G2~h|r)m3iyCgkG z^)lAbG0LG@pdL1O&QkC|+h_Sb%r8goj1=`Vny3KxY>#f;xsV(tad=C|@Po%%s{%7t zUFK)-1n;2xXhA8#at@TFD>UkZ6jJX`@$iph+}(KjIt5o~b<7d%zlMFM%rOaQLy8rW za5oY(o&76OzPlvc(*g)vLZ1Tb>3%eOhRk*n4=vLJK)~d2D4;LCmnyoq({WrF>;MMV zJtpOgtN+5T2$DiBY~!iqFTgY?b7v_9QcW{s$E9wBrUr$B-kx$%@Y%jFn~<CKlywK~ zeY++Gb7ifK5+2V6_p6iH05p3Ak;aoPQU4&q4&LLc0?yJ4>Et^^FQv0%na81YTrF#% zt!6_($UBINDau|s6x8l>{wd<@Bim}S-8pS#h}u{m?1-wpia5PXrybDq_+UChjMdEK zkmmVbtyukAPPMlCpW@ozQ*fA330h2{zTsra_%%>4n3ufs(@j=G!S|#^1%j=GRvD-_ za8j1zjBvAs?Z?@wymnAKdI)$l?l8R`7-!%>$bPCb=RgOU;KUj}9|m?v-x5+E?T@~` zzAl;J#6I(#<R3q}aV~Qdi<4UnErD)d@Hd*fE`1x}jx1GQrU!%1--=^MwMKtbWs<6< zHXo!X=i*0l&nV69kuVjD8>jR|ow`*E)$siJkuE^H$I2CWBsTm;#|SS+G7-JMpqZ=- z;-cp-M&uILF7pl<SywDD)xVc^Bv%#eWoS-MM~H7N^C;}s&jDY}+`t{<kT#ucq!rN| zRn(v4`-!wkd<}><GQYDuObAWtB;Zld4HpohUeDGeT(}=Y&IWE{Er7$fLI2+OOuPKL zqL^(4OhBqRg1p{Cv4pRSSG<SEI0n%m<kVA`P!q9U_rF>Tov;Y?_38Zz+H7_R$-!Cq zvHVk{Ka)3DYDapd>CC8DBKbHaoUPP@l}h;CRTKLeJ5dvpS11kkv?fB4xPh+7Obrxp z_!5crI>WctNl2Qtdfe>t=6VIu0uq$Vp|C4C`V|!8VsP?FQSPB&^Fe`A)X-v(b2PER z%U`$Hz$`5&Emd5z9A5GeS$l_1s~*nHw-w_X0x3y$%8Vmy8@QG9?@sKt%%_4Ll^K;) zVbXVSTT*5r&Z^Wj#8YlT%~mO;=r%P<f?3npD%mSm5T)%*^zH8-*8eCuP*gOC0AT%T z;~wFA_27r|Ql){G2`hM_EeMqK)?|AYQTI;owtJt2itn?PN6nR7#5B2Myi%?G)kReX zPPd_>tvP8FmvgA5PcRVH<}x#RkeOixkl_zEgnAC(rnL#9aMP2AH;SLtuF^$e%zq8R zvMG&j=u^kYb_`by5-7u$tp-;twJkib$WLUc0tV9UU~iyRT>&K&k024G(C9K5g(6)Z zGUhCC?f37Y11-Pme`cvX;$Kwkav{eash#Vg8|fVNW_%S)HUqyO@(+t{HZr%F5U>Sa zw-K+Gz?xI~4}FoW7DhM|FbPWS%1NXG;uC}sd(ljqehrkca!1pFfa}>pIN$TC7C!*6 zc^AmWMoC#f7`RGM4Kk$KE1|NThlS7dfGFMQ03Msm)rR5A{A4e`JlglSg2!^+=scL- zQ@O~Rtu9u?Up_xu#_98X@G5q6)<TbakaM?xA6U~t&?ueRWR8)sXgp%Bm5vvukzDo! z@H9MGfY3o;DU5}|fA;Wj*BI6L>`z5#IhD_ru;gh?Xx^+XD7x3c{1DDTvdFM_A_UuN z?jNZr8KE7)qKo>sYk6G_nmPub2@_7WVGa_&jxU_w_1hkc9unP<<i|iQQmLHdMj(A@ zVKBBhBEL<o(?MT1_iw6$m-}-XDyqFz|Eo3|j4S9cU#vc??X+*t3#VTN=+$zKTfU6` z5ctn`KAaQ+ee;RQ*ywgGR^Pup<YC}Pq^>HYZi@a5?6Zq65C6vnGZiYyOvq=ky`-^T zz4>?;8<qj3bN3#F1gKL-qOo$EAC0%FjR25Rezd<~mxA$BvND88#kq^993HY<x&>fS z!GqS5nV(?1mZA7_XGWVznArPR_vhy3f}l$TBAtyvl%Yp)v9YlYa`7aqfA<r_oHsjt z!M@M!o+?ZQC!Y*SwJmR$$4BA-DN0Kv*#ZF<Q^BBwgwv&JtDki@NEVxsGPbt-2Z*SN zV?44VHVBGIy60{4^r{EW&(noHX_Xu4L2JvzUMbRER~s2{7N*H`Do0I@tM!u*9g7SW zP*Drwol#0-dxs0Yg)z?-fav&Z5EY{ukWRM^>AbjxRCrsp4!X=IdE=}2Frh{gplfd_ zWcFY6K%Hh)y0fzqq}1Qq22`CY77%#5iJIt79B~Y$53RqXUtI{L`iBsFeN77jfoqug zRZ7uw8g0u9>HcBQ6-Xh}gZ>3oQGG=9f-+K4!u;W0SU8#46Z;D-O9%)pD00@qDZvB$ zYj8@z;CKNSGb{&740-kZ+!Ig3BD>pdc1%o6K7=H?f8sj}kSGVw?0^B!N6CNTjlEy3 zo@gq$!mB0qX{oE_B>q(P6&;;;+JQ%V8^Hg9AIbHwsvF(gao^;-J9SIlD{(*vZX*(! ztbdt?+4`Dl)xoTGkkH2=;J@I7qBvt{q2WwLwjPYu9yEvVkrr7c)3Gm{xDHdy|3pNt zLy|FhT^IZb4uY9Ne`D>ZeEaqD`HtpyNcn${722Rmg=+6Ui~fv1TxR6dDC}p!1h8_M zH*y>w3=8^AaOQ<UeNh4Z_fqbkv+eswMWaGrSoOv?SA`a<X_@R?nNI&Fm!eJJTCc1! z3SU-wF_mBulv{pwal}BP(d^K!waAKW-(FG<X}_n#odU}Ibvq=P!(K+CG82rb9Oz1x zcX~DY-;ah-{mv-Nl8;IF#28Xk!KmP_vz~k^---MiOV?YxOhs-EGL2(!Kq1ew17{+1 z6kWx$TA}q)!)*I)r3s3rrk?+zFznJs71jSc$+ixQy#Ix0I#d4Pn*;2)Y}V=?Hjg2p PAAo|4s&uuadFcNGy(gN% diff --git a/static/img/psf-logo@2x.png b/static/img/psf-logo@2x.png deleted file mode 100644 index 0a7f8e715b18959a0327ba400905b0eaa34ba2a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19844 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 diff --git a/static/img/python-logo.png b/static/img/python-logo.png index e6c63e1f9015e6f8fa17b8c703fb0f0374dd08a6..d18e7c33a08c7de70fea8fba6c95e03b58c445d6 100644 GIT binary patch literal 15770 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 aguMYVB#h{ks|J>>LDJ$1kZMuGp#KBCRVvQ_ literal 10102 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 ;B+y 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 Ug5c}`4$^@XWmRO#U`7G|1C`#K$N&HU diff --git a/static/img/python-logo@2x.png b/static/img/python-logo@2x.png deleted file mode 100644 index d18e7c33a08c7de70fea8fba6c95e03b58c445d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15770 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 aguMYVB#h{ks|J>>LDJ$1kZMuGp#KBCRVvQ_ diff --git a/static/js/plugins.js b/static/js/plugins.js index 61909a7e6..d8a126e5e 100644 --- a/static/js/plugins.js +++ b/static/js/plugins.js @@ -25,30 +25,6 @@ if(!key){result[name]=converted(cookie);}} return result;};config.defaults={};$.removeCookie=function(key,options){if($.cookie(key)!==undefined){$.cookie(key,'',$.extend(options,{expires:-1}));return true;} return false;};})); - -/*! Retina.js - * https://github.com/imulus/retinajs/blob/master/src/retina.js - * Copyright (C) 2012 Ben Atkin - * MIT License. - */ -(function(){var root=(typeof exports=='undefined'?window:exports);var config={check_mime_type:true};root.Retina=Retina;function Retina(){} -Retina.configure=function(options){if(options===null)options={};for(var prop in options)config[prop]=options[prop];};Retina.init=function(context){if(context===null)context=root;var existing_onload=context.onload||new Function;context.onload=function(){var images=document.getElementsByTagName("img"),retinaImages=[],i,image;for(i=0;i<images.length;i++){image=images[i];retinaImages.push(new RetinaImage(image));} -existing_onload();}};Retina.isRetina=function(){var mediaQuery="(-webkit-min-device-pixel-ratio: 1.5),\ - (min--moz-device-pixel-ratio: 1.5),\ - (-o-min-device-pixel-ratio: 3/2),\ - (min-resolution: 1.5dppx)";if(root.devicePixelRatio>1) -return true;if(root.matchMedia&&root.matchMedia(mediaQuery).matches) -return true;return false;};root.RetinaImagePath=RetinaImagePath;function RetinaImagePath(path){this.path=path;this.at_2x_path=path.replace(/\.\w+$/,function(match){return"@2x"+match;});} -RetinaImagePath.confirmed_paths=[];RetinaImagePath.prototype.is_external=function(){return!!(this.path.match(/^https?\:/i)&&!this.path.match('//'+document.domain));} -RetinaImagePath.prototype.check_2x_variant=function(callback){var http,that=this;if(this.is_external()){return callback(false);}else if(this.at_2x_path in RetinaImagePath.confirmed_paths){return callback(true);}else{http=new XMLHttpRequest;http.open('HEAD',this.at_2x_path);http.onreadystatechange=function(){if(http.readyState!=4){return callback(false);} -if(http.status>=200&&http.status<=399){if(config.check_mime_type){var type=http.getResponseHeader('Content-Type');if(type===null||!type.match(/^image/i)){return callback(false);}} -RetinaImagePath.confirmed_paths.push(that.at_2x_path);return callback(true);}else{return callback(false);}} -http.send();}} -function RetinaImage(el){this.el=el;this.path=new RetinaImagePath(this.el.getAttribute('src'));var that=this;this.path.check_2x_variant(function(hasVariant){if(hasVariant)that.swap();});} -root.RetinaImage=RetinaImage;RetinaImage.prototype.swap=function(path){if(typeof path=='undefined')path=this.path.at_2x_path;var that=this;function load(){if(!that.el.complete){setTimeout(load,5);}else{that.el.setAttribute('width',that.el.offsetWidth);that.el.setAttribute('height',that.el.offsetHeight);that.el.setAttribute('src',path);}} -load();} -if(Retina.isRetina()){Retina.init(root);}})(); - /* * jQuery FlexSlider v2.1 * http://www.woothemes.com/flexslider/ From 023121f3efd852679d31814c55c1d56a8a426033 Mon Sep 17 00:00:00 2001 From: Mike Fiedler <miketheman@gmail.com> Date: Mon, 23 Dec 2024 16:36:39 -0500 Subject: [PATCH 161/235] feat(dev): emit descriptions for commands in help (#2678) --- Makefile | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index bd4291bbe..ae0c143dc 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,11 @@ -default: +help: @echo "Call a specific subcommand:" @echo - @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null\ - | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}'\ - | sort\ - | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$' + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \ + | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' @echo - @exit 1 + +default: help .state/docker-build-web: Dockerfile dev-requirements.txt base-requirements.txt # Build web container for this project @@ -29,30 +28,29 @@ default: # Mark the state so we don't rebuild this needlessly. mkdir -p .state && touch .state/db-initialized -serve: .state/db-initialized +serve: .state/db-initialized ## Start the application docker compose up --remove-orphans -migrations: .state/db-initialized - # Run Django makemigrations +migrations: .state/db-initialized ## Generate migrations from models docker compose run --rm web ./manage.py makemigrations -migrate: .state/docker-build-web - # Run Django migrate +migrate: .state/docker-build-web ## Run Django migrate docker compose run --rm web ./manage.py migrate -manage: .state/db-initialized - # Run Django manage to accept arbitrary arguments +manage: .state/db-initialized ## Run Django manage to accept arbitrary arguments docker compose run --rm web ./manage.py $(filter-out $@,$(MAKECMDGOALS)) -shell: .state/db-initialized +shell: .state/db-initialized ## Open Django interactive shell docker compose run --rm web ./manage.py shell -clean: +clean: ## Clean up the environment docker compose down -v rm -f .state/docker-build-web .state/db-initialized .state/db-migrated -test: .state/db-initialized +test: .state/db-initialized ## Run tests docker compose run --rm web ./manage.py test -docker_shell: .state/db-initialized +docker_shell: .state/db-initialized ## Open a bash shell in the web container docker compose run --rm web /bin/bash + +.PHONY: help serve migrations migrate manage shell clean test docker_shell From 9bd3afe155c15f005e40d60a318c82ac731e181d Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Wed, 8 Jan 2025 10:06:16 -0500 Subject: [PATCH 162/235] update pycon sponsorship integration for 2025 (#2682) --- sponsors/api.py | 2 ++ .../create_pycon_vouchers_for_sponsors.py | 24 +++++++++---------- sponsors/serializers.py | 5 ++++ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/sponsors/api.py b/sponsors/api.py index 0d180be6d..c5a8173ab 100644 --- a/sponsors/api.py +++ b/sponsors/api.py @@ -29,6 +29,8 @@ def get(self, request, *args, **kwargs): logo_filters.is_valid(raise_exception=True) sponsorships = Sponsorship.objects.enabled().with_logo_placement() + if logo_filters.by_year: + sponsorships = sponsorships.filter(year=logo_filters.by_year) for sponsorship in sponsorships.select_related("sponsor").iterator(): sponsor = sponsorship.sponsor base_data = { diff --git a/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py b/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py index 3e3b4973d..67f624b0a 100644 --- a/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py +++ b/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py @@ -20,24 +20,24 @@ ) BENEFITS = { - 183: { - "internal_name": "full_conference_passes_code_2024", + 241: { + "internal_name": "full_conference_passes_code_2025", "voucher_type": "SPNS_COMP_", }, - 201: { - "internal_name": "expo_hall_only_passes_code_2024", + 259: { + "internal_name": "pycon_expo_hall_only_passes_code_2025", "voucher_type": "SPNS_EXPO_COMP_", }, - 208: { - "internal_name": "additional_full_conference_passes_code_2024", + 265: { + "internal_name": "pycon_additional_full_conference_passes_code_2025", "voucher_type": "SPNS_ADDL_DISC_REG_", }, - 225: { - "internal_name": "online_only_conference_passes_2024", - "voucher_type": "SPNS_ONLINE_COMP_", - }, - 237: { - "internal_name": "additional_expo_hall_only_passes_2024", + #225: { + # "internal_name": "online_only_conference_passes_2025", + # "voucher_type": "SPNS_ONLINE_COMP_", + #}, + 292: { + "internal_name": "pycon_additional_expo_hall_only_passes_2025", "voucher_type": "SPNS_EXPO_DISC_", }, } diff --git a/sponsors/serializers.py b/sponsors/serializers.py index c0782c12a..e47e28f0b 100644 --- a/sponsors/serializers.py +++ b/sponsors/serializers.py @@ -58,6 +58,7 @@ class FilterLogoPlacementsSerializer(serializers.Serializer): choices=[(c.value, c.name.replace("_", " ").title()) for c in LogoPlacementChoices], required=False, ) + year = serializers.IntegerField(required=False) @property def by_publisher(self): @@ -67,6 +68,10 @@ def by_publisher(self): def by_flight(self): return self.validated_data.get("flight") + @property + def by_year(self): + return self.validated_data.get("year") + def skip_logo(self, logo): if self.by_publisher and self.by_publisher != logo.publisher: return True From 4e2bd048f74878dde67cded083168ce2a17fc839 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 22:39:29 +0000 Subject: [PATCH 163/235] chore(deps): bump django from 4.2.17 to 4.2.18 (#2686) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 4adad74c4..38e1647c6 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.17 +Django==4.2.18 docutils==0.21.2 Markdown==3.7 cmarkgfm==0.6.0 From b7150ce3625edb0ed46a439b85dd6fda0a534ebf Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Thu, 6 Feb 2025 14:30:40 -0500 Subject: [PATCH 164/235] update link to create a new sponsorship application on the sponsors page --- templates/psf/sponsors-list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/psf/sponsors-list.html b/templates/psf/sponsors-list.html index d05befdac..a03b78d83 100644 --- a/templates/psf/sponsors-list.html +++ b/templates/psf/sponsors-list.html @@ -13,7 +13,7 @@ <h3> <a href="/psf/sponsorship/">sponsors</a>. While the PSF thanks these sponsors for their support, we don't necessarily endorse nor promote any specific activity of any of its sponsors. </h3> - <p>Interested in becoming a sponsor? Check out our <a href="{% url 'new_sponsorship_application' %}">sponsor application</a>.</p> + <p>Interested in becoming a sponsor? Check out our <a href="{% url 'select_sponsorship_application_benefits' %}">sponsor application</a>.</p> {% list_sponsors "sponsors" %} From 47e192cd2ed658f39aa15a684823d6034d3841c9 Mon Sep 17 00:00:00 2001 From: Karan Rautela <137271352+karnrautela@users.noreply.github.com> Date: Fri, 7 Feb 2025 20:44:58 +0530 Subject: [PATCH 165/235] Update mq.css (#2692) * Update mq.css Fix footer layout distortion on mobile devices * Update mq.scss * compile from scss rather than hand edit css --------- Co-authored-by: Ee Durbin <ewdurbin@gmail.com> --- static/sass/mq.css | 3 +++ static/sass/mq.scss | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/static/sass/mq.css b/static/sass/mq.css index 38c68317a..4d4dea4ac 100644 --- a/static/sass/mq.css +++ b/static/sass/mq.css @@ -413,6 +413,9 @@ html[xmlns] .slides { display: block; } display: none; speak: none; } + .tier-1 { + position: static !important; } + .slideshow { display: none; } } /* - - - Larger than 400px - - - */ diff --git a/static/sass/mq.scss b/static/sass/mq.scss index 309aec202..26a361717 100644 --- a/static/sass/mq.scss +++ b/static/sass/mq.scss @@ -36,6 +36,9 @@ body:after { @include javascript_tag( 'animatebody' ); } + .tier-1 { + position: static !important; + } @include max_width_480(); } @@ -159,4 +162,4 @@ * for IE10 Snap Mode on Metro */ @-ms-viewport { width: device-width; } -@viewport { width: device-width; } \ No newline at end of file +@viewport { width: device-width; } From 0d728a37c723c6988d35c51d3ab75522b412e659 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Mar 2025 23:11:12 +0000 Subject: [PATCH 166/235] chore(deps): bump django from 4.2.18 to 4.2.20 (#2699) Bumps [django](https://github.com/django/django) from 4.2.18 to 4.2.20. - [Commits](https://github.com/django/django/compare/4.2.18...4.2.20) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 38e1647c6..aa4e0f4e0 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.18 +Django==4.2.20 docutils==0.21.2 Markdown==3.7 cmarkgfm==0.6.0 From 43b22c1a19798835d7b255cf4198b93f88f589d7 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Mon, 7 Apr 2025 17:12:11 -0400 Subject: [PATCH 167/235] add our plausible install to analytics --- templates/base.html | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/base.html b/templates/base.html index 0091c41b0..051605cb9 100644 --- a/templates/base.html +++ b/templates/base.html @@ -15,6 +15,7 @@ </script> <!-- Plausible.io analytics --> <script defer data-domain="python.org" src="https://plausible.io/js/script.js"></script> + <script defer data-domain="python.org" src="https://analytics.python.org/js/script.js"></script> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> From 40c3dbbbcfada83b54bc5e897f343a44817d6d5a Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Wed, 16 Apr 2025 14:36:46 -0400 Subject: [PATCH 168/235] update Basic Membership Form header text (#2710) * update Basic Membership Form header text * update user profile detail page * move repeated text to an include * update nominations history page to make sense for people that have never nominated --- templates/users/_membership_detail.html | 35 +++++++++++++++++++++++++ templates/users/membership_form.html | 16 +---------- templates/users/nominations_view.html | 8 +++--- templates/users/user_detail.html | 15 ++--------- 4 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 templates/users/_membership_detail.html diff --git a/templates/users/_membership_detail.html b/templates/users/_membership_detail.html new file mode 100644 index 000000000..7b97bfaa5 --- /dev/null +++ b/templates/users/_membership_detail.html @@ -0,0 +1,35 @@ + <div class="info"> + + <p> + Your Basic Membership information is managed here. + </p> + + <p> + To manage your Supporting and Contributing Memberships, visit <a href="https://psfmember.org/user-information/">psfmember.org</a>. + </p> + + <p> + Voting in PSF elections requires a Supporting, Contributing, or Fellow Membership. + <b>Basic Membership is not a voting class</b>. + To learn more about PSF Membership classes, and to enroll as a Supporting or Contributing Member, + visit <a href="https://www.python.org/psf/membership/">Our Membership Page</a>. + </p> + + <p> + This site (python.org), will list you as a Basic Member + even if you are a Supporting, Contribution, or Fellowship member + because the voting tiers of membership are managed on the separate, + <a href="https://www.psfmember.org">psfmember.org</a> website. + To affirm your PSF Voting Eligibility you will need to use + <a href="https://psfmember.org/civicrm/votingaffirmation/">psfmember.org</a>. + </p> + + <p> + If you believe you are a Supporting, Contributing, or Fellow Member + but do not have an account on <a href="https://www.psfmember.org">psfmember.org</a>, + please create an account and verify your email, + then email <a href="mailto:psf-donations@python.org">psf-donations@python.org</a> + to have your account linked to your membership. + </p> + + </div> diff --git a/templates/users/membership_form.html b/templates/users/membership_form.html index ecc032467..7c65589b3 100644 --- a/templates/users/membership_form.html +++ b/templates/users/membership_form.html @@ -18,21 +18,7 @@ <h1 class="default-title">Edit your PSF Basic Membership</h1> <h1 class="default-title">Register to become a PSF Basic Member</h1> {% endif %} - <div class="info"> - <p> - Basic membership is <b>not a voting membership class</b>.<br>For more information see Article IV - of the <a href="https://www.python.org/psf/bylaws/">PSF Bylaws</a>. - </p> - <p> - All other membership classes are recorded on <a href="https://psfmember.org">psfmember.org</a>.<br> - Please log in there and review your <a href="https://psfmember.org/user-information/">user profile</a> - to see your membership status.<br> - If you believe you are a member but do not have an account on psfmember.org, please - <a href="https://psfmember.org/wp-login.php?action=register">create an account</a> and verify your - email, then email <a href="mailto:psf-donations@python.org">psf-donations@python.org</a> to get your account linked to your membership. - </p> - <p>For more information and to sign up for other kinds of PSF membership, visit our <a href="https://www.python.org/psf/membership/">Membership Page</a>.</p> - </div> + {% include 'users/_membership_detail.html' %} {% if form.errors %} <div class="user-feedback level-error"> diff --git a/templates/users/nominations_view.html b/templates/users/nominations_view.html index 8c28aa87b..fe0fbbd76 100644 --- a/templates/users/nominations_view.html +++ b/templates/users/nominations_view.html @@ -15,11 +15,13 @@ {% block user_content %} <div> + <h1>Your History of PSF Board Nominations</h1> + {% for election, nominations in elections.items %} - <h1><a href="{% url 'nominations:nominees_list' election=election.slug %}">{{ election.name }} Election</a></h1> + <h2><a href="{% url 'nominations:nominees_list' election=election.slug %}">{{ election.name }} Election</a></h2> {% if nominations.nominations_recieved|length > 0 %} - <h2>Nominations Received</h2> + <h3>Nominations Received</h3> <ul> {% for nomination in nominations.nominations_recieved %} <li> @@ -45,7 +47,7 @@ <h2>Nominations Received</h2> {% endif %} {% if nominations.nominations_made|length > 0 %} - <h2>Nominations Made</h2> + <h3>Nominations Made</h3> <ul> {% for nomination in nominations.nominations_made %} <li> diff --git a/templates/users/user_detail.html b/templates/users/user_detail.html index ce2f5ee90..dcf614855 100644 --- a/templates/users/user_detail.html +++ b/templates/users/user_detail.html @@ -24,20 +24,9 @@ <p><span class="profile-label"><span class="icon-python" aria-hidden="true"></span>PSF Basic Member?</span> {{ object.has_membership|yesno|capfirst }}</p> {% if object.has_membership %} <div style="margin-left: 1em;"> - <p> - Basic membership is <b>not a voting membership class</b>.<br>For more information see Article IV - of the <a href="https://www.python.org/psf/bylaws/">PSF Bylaws</a>. - </p> - <p> - All other membership classes are recorded on <a href="https://psfmember.org">psfmember.org</a>.<br> - Please log in there and review your <a href="https://psfmember.org/user-information/">user profile</a> - to see your membership status.<br> - If you believe you are a member but do not have an account on psfmember.org, please - <a href="https://psfmember.org/wp-login.php?action=register">create an account</a> and verify your - email, then email <a href="mailto:psf-donations@python.org">psf-donations@python.org</a> to get your account linked to your membership. - </p> + {% include 'users/_membership_detail.html' %} </div> - {% endif %} + {% endif %} </div> {% comment %} <div class="user-profile-location"> From ac6463d5ec0ad8150120f7aa20638c4615d7941b Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Wed, 16 Apr 2025 13:52:51 -0500 Subject: [PATCH 169/235] chore: remove flaky deploy reminder ci task (#2711) --- .github/workflows/deployminder.yml | 37 ------------------------------ 1 file changed, 37 deletions(-) delete mode 100644 .github/workflows/deployminder.yml diff --git a/.github/workflows/deployminder.yml b/.github/workflows/deployminder.yml deleted file mode 100644 index 04774f04f..000000000 --- a/.github/workflows/deployminder.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Deploy Reminder - -on: - pull_request: - types: - - closed - branches: - - main - -jobs: - remind: - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Check for changes in infra/ - id: check_changes - run: | - git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | grep -q '^infra/' - echo "has_infra_changes=$?" >> $GITHUB_OUTPUT - - - name: Comment on PR - if: steps.check_changes.outputs.has_infra_changes == '0' - uses: actions/github-script@v7 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'Changes detected in the `infra/` directory. Don\'t forget to apply these changes in Terraform Cloud and/or Fastly!' - }) From 1f9000041bffcdf4e6553b0be879e574d6e2eadb Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Thu, 17 Apr 2025 13:56:36 -0400 Subject: [PATCH 170/235] remove google analytics and plausible.io (#2713) we're going to be migrating to self-hosted plausbile entirely now. drop plausible.io script, and enable outbound links --- templates/base.html | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/templates/base.html b/templates/base.html index 051605cb9..f66f80ca9 100644 --- a/templates/base.html +++ b/templates/base.html @@ -5,17 +5,7 @@ <!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"> <!--<![endif]--> {% load pipeline sitetree %} <head> - <!-- Google tag (gtag.js) --> - <script async src="https://www.googletagmanager.com/gtag/js?id=G-TF35YF9CVH"></script> - <script> - window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', 'G-TF35YF9CVH'); - </script> - <!-- Plausible.io analytics --> - <script defer data-domain="python.org" src="https://plausible.io/js/script.js"></script> - <script defer data-domain="python.org" src="https://analytics.python.org/js/script.js"></script> + <script defer data-domain="python.org" src="https://analytics.python.org/js/script.outbound-links.js"></script> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> From f58149cf45655d7cd5e1b30dc8ea917c2e41c0ae Mon Sep 17 00:00:00 2001 From: Ned Batchelder <ned@nedbatchelder.com> Date: Thu, 24 Apr 2025 11:57:22 -0400 Subject: [PATCH 171/235] add a link to docs.python.org on the search page (#2718) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Jacob Coffee <jacob@z7x.org> --- templates/search/search.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/templates/search/search.html b/templates/search/search.html index 1782fe3ca..dd5579a25 100644 --- a/templates/search/search.html +++ b/templates/search/search.html @@ -17,7 +17,7 @@ <h3>Results</h3> {% include result.include_template %} </li> {% empty %} - <p>No results found.</p> + <li>No results found.</li> {% endfor %} </ul> {% if page.has_previous or page.has_next %} @@ -27,8 +27,13 @@ <h3>Results</h3> {% if page.has_next %}<a href="?q={{ query }}&page={{ page.next_page_number }}">{% endif %}Next »{% if page.has_next %}</a>{% endif %} </div> {% endif %} + + <h3>Python language documentation</h3> + <p>If you didn't find what you need, try your search in the + <a href="https://docs.python.org/3/search.html?q={{ request.GET.q | urlencode }}">Python language documentation</a>. + </p> {% else %} {# Show some example queries to run, maybe query syntax, something else? #} {% endif %} </form> -{% endblock %} \ No newline at end of file +{% endblock %} From 595b55890c481dd4f139a45f72160fcf9ddc7dad Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Fri, 2 May 2025 09:53:07 -0400 Subject: [PATCH 172/235] add sponsorship id to sponsor list api endpoint (#2720) this will be useful to make the sync more reliable to link via id not string --- sponsors/api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sponsors/api.py b/sponsors/api.py index c5a8173ab..e5ef245df 100644 --- a/sponsors/api.py +++ b/sponsors/api.py @@ -34,6 +34,7 @@ def get(self, request, *args, **kwargs): for sponsorship in sponsorships.select_related("sponsor").iterator(): sponsor = sponsorship.sponsor base_data = { + "sponsor_id": sponsor.id, "sponsor": sponsor.name, "sponsor_slug": sponsor.slug, "level_name": sponsorship.level_name, From eaeb1573105a64fc95e514b1ca52244e0d1986c4 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Fri, 2 May 2025 10:27:42 -0400 Subject: [PATCH 173/235] actually add sponsor_id to sponsor api (#2721) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit oh yeah 🙃 --- sponsors/serializers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sponsors/serializers.py b/sponsors/serializers.py index e47e28f0b..e73ee309b 100644 --- a/sponsors/serializers.py +++ b/sponsors/serializers.py @@ -8,6 +8,7 @@ class LogoPlacementSerializer(serializers.Serializer): publisher = serializers.CharField() flight = serializers.CharField() sponsor = serializers.CharField() + sponsor_id = serializers.CharField() sponsor_slug = serializers.CharField() description = serializers.CharField() logo = serializers.URLField() From 1efbb241904a3c92869b0c4b1243d543f9169100 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Fri, 2 May 2025 13:04:57 -0400 Subject: [PATCH 174/235] send sponsor_id when calling pycon create voucher api (#2722) --- .../commands/create_pycon_vouchers_for_sponsors.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py b/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py index 67f624b0a..db095f075 100644 --- a/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py +++ b/sponsors/management/commands/create_pycon_vouchers_for_sponsors.py @@ -66,8 +66,10 @@ def api_call(uri, query): scheme = "http" if settings.DEBUG else "https" url = f"{scheme}://{settings.PYCON_API_HOST}{uri}" try: - return requests.get(url, headers=headers, params=query).json() + r = requests.get(url, headers=headers, params=query) + return r.json() except RequestException: + print(r, r.content) raise @@ -103,6 +105,7 @@ def generate_voucher_codes(year): "voucher_type": code["voucher_type"], "quantity": quantity.quantity, "sponsor_name": sponsorbenefit.sponsorship.sponsor.name, + "sponsor_id": sponsorbenefit.sponsorship.sponsor.id, }, ) if result["code"] == 200: From e2ac65b9797153f9b4a38163354e0b0e6377234a Mon Sep 17 00:00:00 2001 From: Steve Dower <steve.dower@python.org> Date: Wed, 7 May 2025 15:57:12 +0100 Subject: [PATCH 175/235] Update website for Python install manager (#2717) Co-authored-by: Jacob Coffee <jacob@z7x.org> --- downloads/managers.py | 13 ++++++++++++ .../migrations/0012_alter_release_version.py | 18 ++++++++++++++++ downloads/models.py | 6 ++++++ downloads/urls.py | 1 + downloads/views.py | 21 +++++++++++++++++++ templates/downloads/index.html | 9 ++++++++ templates/downloads/os_list.html | 12 ++++++++++- templates/downloads/supernav.html | 6 ++++++ 8 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 downloads/migrations/0012_alter_release_version.py diff --git a/downloads/managers.py b/downloads/managers.py index b529dcdd4..56040d2bb 100644 --- a/downloads/managers.py +++ b/downloads/managers.py @@ -23,12 +23,18 @@ def python2(self): def python3(self): return self.filter(version=3, is_published=True) + def pymanager(self): + return self.filter(version=100, is_published=True) + def latest_python2(self): return self.python2().filter(is_latest=True) def latest_python3(self): return self.python3().filter(is_latest=True) + def latest_pymanager(self): + return self.pymanager().filter(is_latest=True) + def pre_release(self): return self.filter(pre_release=True) @@ -50,3 +56,10 @@ def latest_python3(self): return qs[0] else: return None + + def latest_pymanager(self): + qs = self.get_queryset().latest_pymanager() + if qs: + return qs[0] + else: + return None diff --git a/downloads/migrations/0012_alter_release_version.py b/downloads/migrations/0012_alter_release_version.py new file mode 100644 index 000000000..e6aea4d1f --- /dev/null +++ b/downloads/migrations/0012_alter_release_version.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.20 on 2025-04-24 19:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('downloads', '0011_alter_os_creator_alter_os_last_modified_by_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='release', + name='version', + field=models.IntegerField(choices=[(3, 'Python 3.x.x'), (2, 'Python 2.x.x'), (1, 'Python 1.x.x'), (100, 'Python install manager')], default=3), + ), + ] diff --git a/downloads/models.py b/downloads/models.py index 415804b6e..3c0a74f97 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -45,10 +45,12 @@ class Release(ContentManageable, NameSlugModel): PYTHON1 = 1 PYTHON2 = 2 PYTHON3 = 3 + PYMANAGER = 100 PYTHON_VERSION_CHOICES = ( (PYTHON3, 'Python 3.x.x'), (PYTHON2, 'Python 2.x.x'), (PYTHON1, 'Python 1.x.x'), + (PYMANAGER, 'Python install manager'), ) version = models.IntegerField(default=PYTHON3, choices=PYTHON_VERSION_CHOICES) is_latest = models.BooleanField( @@ -146,6 +148,10 @@ def is_version_at_least_3_5(self): def is_version_at_least_3_9(self): return self.is_version_at_least((3, 9)) + @property + def is_version_at_least_3_14(self): + return self.is_version_at_least((3, 14)) + def update_supernav(): latest_python3 = Release.objects.latest_python3() diff --git a/downloads/urls.py b/downloads/urls.py index eddef7a10..5b6b3fda0 100644 --- a/downloads/urls.py +++ b/downloads/urls.py @@ -5,6 +5,7 @@ urlpatterns = [ re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'), re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), + re_path(r'latest/pymanager/?$', views.DownloadLatestPyManager.as_view(), name='download_latest_pymanager'), re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'), path('release/<slug:release_slug>/', views.DownloadReleaseDetail.as_view(), name='download_release_detail'), diff --git a/downloads/views.py b/downloads/views.py index 2e48cb2f3..21e66cd55 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -45,6 +45,22 @@ def get_redirect_url(self, **kwargs): return reverse('download') +class DownloadLatestPyManager(RedirectView): + """ Redirect to latest Python install manager release """ + permanent = False + + def get_redirect_url(self, **kwargs): + try: + latest_pymanager = Release.objects.latest_pymanager() + except Release.DoesNotExist: + latest_pymanager = None + + if latest_pymanager: + return latest_pymanager.get_absolute_url() + else: + return reverse('downloads') + + class DownloadBase: """ Include latest releases in all views """ def get_context_data(self, **kwargs): @@ -52,6 +68,7 @@ def get_context_data(self, **kwargs): context.update({ 'latest_python2': Release.objects.latest_python2(), 'latest_python3': Release.objects.latest_python3(), + 'latest_pymanager': Release.objects.latest_pymanager(), }) return context @@ -71,6 +88,8 @@ def get_context_data(self, **kwargs): except Release.DoesNotExist: latest_python3 = None + latest_pymanager = context.get('latest_pymanager') + python_files = [] for o in OS.objects.all(): data = { @@ -80,6 +99,8 @@ def get_context_data(self, **kwargs): data['python2'] = latest_python2.download_file_for_os(o.slug) if latest_python3 is not None: data['python3'] = latest_python3.download_file_for_os(o.slug) + if latest_pymanager is not None: + data['pymanager'] = latest_pymanager.download_file_for_os(o.slug) python_files.append(data) context.update({ diff --git a/templates/downloads/index.html b/templates/downloads/index.html index 4cd8155e1..f527be031 100644 --- a/templates/downloads/index.html +++ b/templates/downloads/index.html @@ -17,11 +17,20 @@ <h1 class="call-to-action">Download the latest source release</h1> {% else %} <h1 class="call-to-action">Download the latest version for {{ data.os.name }}</h1> {% endif %} + {% if data.pymanager %} + <p class="download-buttons"> + <a class="button" href="{{ data.pymanager.url }}">Download Python install manager</a> + </p> + {% if data.python3 %} + <p>Or get the standalone installer for <a href="{{ data.python3.url }}">{{ data.python3.release.name }}</a></p> + {% endif %} + {% else %} <p class="download-buttons"> {% if data.python3 %} <a class="button" href="{{ data.python3.url }}">Download {{ data.python3.release.name }}</a> {% endif %} </p> + {% endif %} </div> {% endfor %} <div class="download-unknown"> diff --git a/templates/downloads/os_list.html b/templates/downloads/os_list.html index 1e0177dca..ffd524e5f 100644 --- a/templates/downloads/os_list.html +++ b/templates/downloads/os_list.html @@ -29,6 +29,10 @@ <h1 class="page-title">Python Releases for {{ os.name }}</h1> </header> <ul> + {% if os.slug == 'windows' and latest_pymanager %} + <li><a href="{{ latest_pymanager.get_absolute_url }}">Latest Python install manager - {{ latest_pymanager.name }}</a></li> + {% endif %} + <li><a href="{{ latest_python3.get_absolute_url }}">Latest Python 3 Release - {{ latest_python3.name }}</a></li> </ul> <div class="col-row two-col"> @@ -39,7 +43,13 @@ <h2>Stable Releases</h2> <li> <a href="{{ r.get_absolute_url }}">{{ r.name }} - {{ r.release_date|date }}</a> {% if os.slug == 'windows' %} - {% if r.is_version_at_least_3_9 %} + {% if latest_pymanager and r.is_version_at_least_3_14 %} + {% if latest_pymanager %} + <p>Download using the <a href="{{ latest_pymanager.get_absolute_url }}">Python install manager</a>.</p> + {% else %} + <p>Download using the <a href="https://docs.python.org/using/windows.html">Python install manager</a>.</p> + {% endif %} + {% elif r.is_version_at_least_3_9 %} <p><strong>Note that {{ r.name }} <em>cannot</em> be used on Windows 7 or earlier.</strong></p> {% elif r.is_version_at_least_3_5 %} <p><strong>Note that {{ r.name }} <em>cannot</em> be used on Windows XP or earlier.</strong></p> diff --git a/templates/downloads/supernav.html b/templates/downloads/supernav.html index fb0a1e629..12568eadb 100644 --- a/templates/downloads/supernav.html +++ b/templates/downloads/supernav.html @@ -7,10 +7,16 @@ <h3>Python Source</h3> {% else %} <h4>Download for {{ data.os.name }}</h4> {% endif %} + + {% if data.pymanager %} + <p><a class="button" href="{{ data.pymanager.url }}">Python install manager</a></p> + <p>Or get the standalone installer for <a class="button" href="{{ data.python3.url }}">{{ data.python3.release.name }}</a></p> + {% else %} <p> <a class="button" href="{{ data.python3.url }}">{{ data.python3.release.name }}</a> </p> {% if data.os.slug == 'windows' %}<p><strong>Note that Python 3.9+ <em>cannot</em> be used on Windows 7 or earlier.</strong></p>{% endif %} + {% endif %} <p>Not the OS you are looking for? Python can be used on many operating systems and environments. <a href="{% url 'download:download' %}">View the full list of downloads</a>.</p> </div> {% endfor %} From 1e92dd5c9a9af63c420e93cbf13443c00ff88810 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 11:50:27 -0400 Subject: [PATCH 176/235] chore(deps): bump django from 4.2.20 to 4.2.21 (#2728) Bumps [django](https://github.com/django/django) from 4.2.20 to 4.2.21. - [Commits](https://github.com/django/django/compare/4.2.20...4.2.21) --- updated-dependencies: - dependency-name: django dependency-version: 4.2.21 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index aa4e0f4e0..235bdc7d9 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.20 +Django==4.2.21 docutils==0.21.2 Markdown==3.7 cmarkgfm==0.6.0 From 0ab17f8b0dacc814561554e193bdb768e25f8a77 Mon Sep 17 00:00:00 2001 From: shenxianpeng <xianpeng.shen@gmail.com> Date: Sun, 11 May 2025 06:32:31 +0300 Subject: [PATCH 177/235] Update index.rst to fix not found page (#2715) Co-authored-by: Jacob Coffee <jacob@z7x.org> --- docs/source/index.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index cfde87586..ab7b710ed 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -32,8 +32,6 @@ Indices and tables ================== * :ref:`genindex` -* :ref:`modindex` -* :ref:`search` .. _python.org: https://www.python.org .. _pydotorg-www: https://mail.python.org/mailman/listinfo/pydotorg-www From 142583bd66d5efe4c86b01ffb299b1979c85b91d Mon Sep 17 00:00:00 2001 From: Steve Dower <steve.dower@python.org> Date: Mon, 26 May 2025 23:57:31 +0100 Subject: [PATCH 178/235] Hide releases from Downloads page when they have no files to download (#2736) --- templates/downloads/os_list.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/downloads/os_list.html b/templates/downloads/os_list.html index ffd524e5f..b110e57b1 100644 --- a/templates/downloads/os_list.html +++ b/templates/downloads/os_list.html @@ -40,6 +40,7 @@ <h1 class="page-title">Python Releases for {{ os.name }}</h1> <h2>Stable Releases</h2> <ul> {% for r in releases %} + {% if r.files.all %} <li> <a href="{{ r.get_absolute_url }}">{{ r.name }} - {{ r.release_date|date }}</a> {% if os.slug == 'windows' %} @@ -63,6 +64,7 @@ <h2>Stable Releases</h2> {% endfor %} </ul> </li> + {% endif %} {% endfor %} </ul> </div> @@ -71,6 +73,7 @@ <h2>Stable Releases</h2> <h2>Pre-releases</h2> <ul> {% for r in pre_releases %} + {% if r.files.all %} <li> <a href="{{ r.get_absolute_url }}">{{ r.name }} - {{ r.release_date|date }}</a> <ul> @@ -81,6 +84,7 @@ <h2>Pre-releases</h2> {% endfor %} </ul> </li> + {% endif %} {% endfor %} </ul> </div> From 902fb3989693dd61cc0c5b0faf527492b885cff2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jun 2025 10:05:38 -0500 Subject: [PATCH 179/235] chore(deps): bump django from 4.2.21 to 4.2.22 (#2737) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jacob Coffee <jacob@z7x.org> --- base-requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base-requirements.txt b/base-requirements.txt index 235bdc7d9..cd8474961 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,10 +4,10 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.21 +Django==4.2.22 docutils==0.21.2 Markdown==3.7 -cmarkgfm==0.6.0 +cmarkgfm==2024.11.20 Pillow==10.4.0 psycopg2-binary==2.9.9 python3-openid==3.2.0 From 53c0affbb86ec6f94f6a6bf016eeb9e529e24e80 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Tue, 22 Jul 2025 10:19:41 -0400 Subject: [PATCH 180/235] Do not accept nominations for elections before they open (#2755) Update views.py --- nominations/views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nominations/views.py b/nominations/views.py index 484f7a7c2..570d89c48 100644 --- a/nominations/views.py +++ b/nominations/views.py @@ -89,6 +89,11 @@ def get_form_class(self): self.request, f"Nominations for {election.name} Election are closed" ) raise Http404(f"Nominations for {election.name} Election are closed") + if not election.nominations_open: + messages.error( + self.request, f"Nominations for {election.name} Election are not open" + ) + raise Http404(f"Nominations for {election.name} Election are not open") return NominationCreateForm From 2074f188bfcf68c98c2ddab7861dcf4b9a41a1e1 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Mon, 28 Jul 2025 14:13:30 -0400 Subject: [PATCH 181/235] fix: inject context for events (#2758) --- events/tests/test_views.py | 2 ++ events/views.py | 1 + 2 files changed, 3 insertions(+) diff --git a/events/tests/test_views.py b/events/tests/test_views.py index 34ca27831..613a6ee46 100644 --- a/events/tests/test_views.py +++ b/events/tests/test_views.py @@ -116,6 +116,8 @@ def test_event_list(self): self.assertEqual(response.status_code, 200) self.assertEqual(len(response.context['object_list']), 6) + self.assertIn('upcoming_events', response.context) + self.assertEqual(list(response.context['upcoming_events']), list(response.context['object_list'])) url = reverse('events:event_list_past', kwargs={"calendar_slug": 'unexisting'}) response = self.client.get(url) diff --git a/events/views.py b/events/views.py index 56df88dcb..40e2ee81f 100644 --- a/events/views.py +++ b/events/views.py @@ -87,6 +87,7 @@ def get_context_data(self, **kwargs): context['events_today'] = Event.objects.until_datetime(timezone.now()).filter( calendar__slug=self.kwargs['calendar_slug'])[:2] context['calendar'] = get_object_or_404(Calendar, slug=self.kwargs['calendar_slug']) + context['upcoming_events'] = self.get_queryset() return context From 2a81f76a3b86cd078786ab737bbf3811b8883545 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Tue, 29 Jul 2025 17:40:51 -0400 Subject: [PATCH 182/235] fix: order events properly (#2759) --- events/views.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/events/views.py b/events/views.py index 40e2ee81f..a9d6c8fb3 100644 --- a/events/views.py +++ b/events/views.py @@ -44,16 +44,26 @@ class EventHomepage(ListView): def get_queryset(self) -> Event: """Queryset to return all events, ordered by START date.""" - return Event.objects.all().order_by("-occurring_rule__dt_start") + return Event.objects.all().order_by("occurring_rule__dt_start") def get_context_data(self, **kwargs: dict) -> dict: """Add more ctx, specifically events that are happening now, just missed, and upcoming.""" context = super().get_context_data(**kwargs) - context["events_just_missed"] = Event.objects.until_datetime(timezone.now())[:2] - context["upcoming_events"] = Event.objects.for_datetime(timezone.now()) + + # past events, most recent first + past_events = list(Event.objects.until_datetime(timezone.now())) + past_events.sort(key=lambda e: e.previous_time.dt_start if e.previous_time else timezone.now(), reverse=True) + context["events_just_missed"] = past_events[:2] + + # upcoming events, soonest first + upcoming = list(Event.objects.for_datetime(timezone.now())) + upcoming.sort(key=lambda e: e.next_time.dt_start if e.next_time else timezone.now()) + context["upcoming_events"] = upcoming + + # right now, soonest first context["events_now"] = Event.objects.filter( occurring_rule__dt_start__lte=timezone.now(), - occurring_rule__dt_end__gte=timezone.now())[:2] + occurring_rule__dt_end__gte=timezone.now()).order_by('occurring_rule__dt_start')[:2] return context @@ -79,15 +89,19 @@ def get_context_data(self, **kwargs): class EventList(EventListBase): def get_queryset(self): - return Event.objects.for_datetime(timezone.now()).filter(calendar__slug=self.kwargs['calendar_slug']).order_by( - 'occurring_rule__dt_start') + return Event.objects.for_datetime(timezone.now()).filter(calendar__slug=self.kwargs['calendar_slug']).order_by('occurring_rule__dt_start') def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['events_today'] = Event.objects.until_datetime(timezone.now()).filter( - calendar__slug=self.kwargs['calendar_slug'])[:2] + + # today's events, most recent first + today_events = list(Event.objects.until_datetime(timezone.now()).filter( + calendar__slug=self.kwargs['calendar_slug'])) + today_events.sort(key=lambda e: e.previous_time.dt_start if e.previous_time else timezone.now(), reverse=True) + context['events_today'] = today_events[:2] context['calendar'] = get_object_or_404(Calendar, slug=self.kwargs['calendar_slug']) - context['upcoming_events'] = self.get_queryset() + context['upcoming_events'] = context['object_list'] + return context From 93d17e331870daf269775bff4e2948fc69bd505c Mon Sep 17 00:00:00 2001 From: Malcolm Smith <smith@chaquo.com> Date: Thu, 7 Aug 2025 16:21:29 +0100 Subject: [PATCH 183/235] Add Android release support (#2762) Add Android support --- fixtures/downloads.json | 335 +++++++++++++++++++++++++++++++ fixtures/sitetree_menus.json | 28 ++- templates/downloads/os_list.html | 5 + 3 files changed, 366 insertions(+), 2 deletions(-) diff --git a/fixtures/downloads.json b/fixtures/downloads.json index 0f9f1ce10..f49e18c5e 100644 --- a/fixtures/downloads.json +++ b/fixtures/downloads.json @@ -35,6 +35,18 @@ "slug": "source" } }, +{ + "model": "downloads.os", + "pk": 4, + "fields": { + "created": "2025-08-06T17:02:24.294Z", + "updated": "2025-08-06T17:02:24.296Z", + "creator": 1, + "last_modified_by": null, + "name": "Android", + "slug": "android" + } +}, { "model": "downloads.release", "pk": 1, @@ -7441,6 +7453,29 @@ "_content_rendered": "<p><strong>Note:</strong> The release you are looking at is <strong>Python 3.7.14</strong>, a <strong>security bugfix release</strong> for the legacy <strong>3.7</strong> series which is now in the <strong>security fix</strong> phase of its life cycle. See the <a class=\"reference external\" href=\"/downloads/\">downloads page</a> for currently supported versions of Python and for the most recent source-only <strong>security fix</strong> release for 3.7. The final <strong>bugfix release</strong> with binary installers for 3.7 was <a class=\"reference external\" href=\"/downloads/release/python-379/\">3.7.9</a>.</p>\n<p>Please see the <a class=\"reference external\" href=\"https://docs.python.org/release/3.7.14/whatsnew/changelog.html#changelog\">Full Changelog</a> link for more information about the contents of this release and see <a class=\"reference external\" href=\"https://docs.python.org/release/3.7.14/whatsnew/3.7.html\">What\u2019s New In Python 3.7</a> for more information about 3.7 features.</p>\n<div class=\"section\" id=\"security-content-in-this-release\">\n<h1>Security content in this release</h1>\n<ul class=\"simple\">\n<li><a class=\"reference external\" href=\"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735\">CVE-2020-10735</a>: converting between int and str in bases other than 2 (binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) <a class=\"reference external\" href=\"https://docs.python.org/release/3.7.14/whatsnew/3.7.html#notable-security-feature-in-3-7-14\">now raises a ValueError</a> if the number of digits in string form is above a limit to avoid potential denial of service attacks due to the algorithmic complexity.</li>\n<li>gh-87389: http.server: Fix an open redirection vulnerability in the HTTP server when an URI path starts with //.</li>\n<li>gh-93065: Fix contextvars HAMT implementation to handle iteration over deep trees to avoid a potential crash of the interpreter.</li>\n<li>gh-80254: Raise ProgrammingError instead of segfaulting on recursive usage of cursors in sqlite3 converters.</li>\n</ul>\n</div>\n<div class=\"section\" id=\"more-resources\">\n<h1>More resources</h1>\n<ul class=\"simple\">\n<li><a class=\"reference external\" href=\"https://docs.python.org/release/3.7.14/\">Online Documentation</a></li>\n<li><a class=\"reference external\" href=\"http://www.python.org/dev/peps/pep-0537\">PEP 537</a>, 3.7 Release Schedule</li>\n<li>Report bugs at <a class=\"reference external\" href=\"https://github.com/python/cpython/issues\">https://github.com/python/cpython/issues</a>.</li>\n<li><a class=\"reference external\" href=\"/psf/donations/\">Help fund Python and its community</a>.</li>\n</ul>\n</div>\n" } }, +{ + "model": "downloads.release", + "pk": 729, + "fields": { + "created": "2025-08-06T20:41:07.457Z", + "updated": "2025-08-06T20:44:16.512Z", + "creator": 1, + "last_modified_by": 1, + "name": "Python 3.14.0rc1", + "slug": "python-3140rc1", + "version": 3, + "is_latest": false, + "is_published": true, + "pre_release": true, + "show_on_download_page": true, + "release_date": "2025-08-06T20:39:16Z", + "release_page": null, + "release_notes_url": "https://docs.python.org/3.14/whatsnew/3.14.html", + "content": "[It's](https://www.youtube.com/watch?v=ydyXFUmv6S4) the first 3.14 release candidate!", + "content_markup_type": "markdown", + "_content_rendered": "<p><a href=\"https://www.youtube.com/watch?v=ydyXFUmv6S4\">It's</a> the first 3.14 release candidate!</p>" + } +}, { "model": "downloads.releasefile", "pk": 1, @@ -63032,4 +63067,304 @@ "download_button": false } } +{ + "model": "downloads.releasefile", + "pk": 3880, + "fields": { + "created": "2025-08-06T21:13:43.643Z", + "updated": "2025-08-06T21:13:43.647Z", + "creator": null, + "last_modified_by": null, + "name": "Android embeddable package (aarch64)", + "slug": "3140-rc1-Android-embeddable-package-aarch64", + "os": 4, + "release": 729, + "description": "", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-aarch64-linux-android.tar.gz", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-aarch64-linux-android.tar.gz.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-aarch64-linux-android.tar.gz.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-aarch64-linux-android.tar.gz.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "4a1b2748bf64b54b226b40f845de9e6a", + "filesize": 29099264, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3881, + "fields": { + "created": "2025-08-06T21:13:43.664Z", + "updated": "2025-08-06T21:13:43.667Z", + "creator": null, + "last_modified_by": null, + "name": "Windows installer (64-bit)", + "slug": "3140-rc1-Windows-installer-64-bit", + "os": 1, + "release": 729, + "description": "Recommended", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-amd64.exe", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-amd64.exe.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-amd64.exe.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-amd64.exe.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "b674030fe04f2d5c4c1385237998a10c", + "filesize": 29924384, + "download_button": true + } +}, +{ + "model": "downloads.releasefile", + "pk": 3882, + "fields": { + "created": "2025-08-06T21:13:43.678Z", + "updated": "2025-08-06T21:13:43.681Z", + "creator": null, + "last_modified_by": null, + "name": "Windows embeddable package (64-bit)", + "slug": "3140-rc1-Windows-embeddable-package-64-bit", + "os": 1, + "release": 729, + "description": "", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-amd64.zip", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-amd64.zip.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-amd64.zip.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-amd64.zip.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "58da6dd39544a56d8d387d42c3397460", + "filesize": 11972759, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3883, + "fields": { + "created": "2025-08-06T21:13:43.692Z", + "updated": "2025-08-06T21:13:43.695Z", + "creator": null, + "last_modified_by": null, + "name": "Windows release manifest", + "slug": "3140-rc1-Windows-release-manifest", + "os": 1, + "release": 729, + "description": "Install with 'py install 3.14'", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/windows-3.14.0rc1.json", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/windows-3.14.0rc1.json.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/windows-3.14.0rc1.json.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/windows-3.14.0rc1.json.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "3a140287b276a6d661790687b9fdd081", + "filesize": 15669, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3884, + "fields": { + "created": "2025-08-06T21:13:43.707Z", + "updated": "2025-08-06T21:13:43.709Z", + "creator": null, + "last_modified_by": null, + "name": "Windows installer (32-bit)", + "slug": "3140-rc1-Windows-installer-32-bit", + "os": 1, + "release": 729, + "description": "", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1.exe", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1.exe.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1.exe.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1.exe.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "bad58261535240afd04f6e98510321df", + "filesize": 28481000, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3885, + "fields": { + "created": "2025-08-06T21:13:43.719Z", + "updated": "2025-08-06T21:13:43.722Z", + "creator": null, + "last_modified_by": null, + "name": "macOS 64-bit universal2 installer", + "slug": "3140-rc1-macOS-64-bit-universal2-installer", + "os": 2, + "release": 729, + "description": "for macOS 10.13 and later", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-macos11.pkg", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-macos11.pkg.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-macos11.pkg.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-macos11.pkg.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "88d1bed73bde571e5cae6afaeb636331", + "filesize": 74569591, + "download_button": true + } +}, +{ + "model": "downloads.releasefile", + "pk": 3886, + "fields": { + "created": "2025-08-06T21:13:43.732Z", + "updated": "2025-08-06T21:13:43.734Z", + "creator": null, + "last_modified_by": null, + "name": "Windows installer (ARM64)", + "slug": "3140-rc1-Windows-installer-ARM64", + "os": 1, + "release": 729, + "description": "Experimental", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-arm64.exe", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-arm64.exe.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-arm64.exe.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-arm64.exe.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "19956541e2ccfea8d9c1be2843271fc9", + "filesize": 29132600, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3887, + "fields": { + "created": "2025-08-06T21:13:43.743Z", + "updated": "2025-08-06T21:13:43.746Z", + "creator": null, + "last_modified_by": null, + "name": "Windows embeddable package (32-bit)", + "slug": "3140-rc1-Windows-embeddable-package-32-bit", + "os": 1, + "release": 729, + "description": "", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-win32.zip", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-win32.zip.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-win32.zip.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-win32.zip.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "20c52ba256be93ef49a87f462a324723", + "filesize": 10571221, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3888, + "fields": { + "created": "2025-08-06T21:13:43.754Z", + "updated": "2025-08-06T21:13:43.756Z", + "creator": null, + "last_modified_by": null, + "name": "XZ compressed source tarball", + "slug": "3140-rc1-XZ-compressed-source-tarball", + "os": 3, + "release": 729, + "description": "", + "is_source": true, + "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tar.xz", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tar.xz.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tar.xz.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tar.xz.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "48c4518c06dcb675c24276c56f69b9fd", + "filesize": 23661916, + "download_button": true + } +}, +{ + "model": "downloads.releasefile", + "pk": 3889, + "fields": { + "created": "2025-08-06T21:13:43.766Z", + "updated": "2025-08-06T21:13:43.768Z", + "creator": null, + "last_modified_by": null, + "name": "Windows embeddable package (ARM64)", + "slug": "3140-rc1-Windows-embeddable-package-ARM64", + "os": 1, + "release": 729, + "description": "", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-arm64.zip", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-arm64.zip.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-arm64.zip.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-embed-arm64.zip.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "709fc10a10cf3ad9633222827ca2abf5", + "filesize": 11165022, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3890, + "fields": { + "created": "2025-08-06T21:13:43.776Z", + "updated": "2025-08-06T21:13:43.778Z", + "creator": null, + "last_modified_by": null, + "name": "Gzipped source tarball", + "slug": "3140-rc1-Gzipped-source-tarball", + "os": 3, + "release": 729, + "description": "", + "is_source": true, + "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tgz", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tgz.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tgz.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tgz.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "11fba5eb7576c1889498af3f8555ed2d", + "filesize": 30639704, + "download_button": false + } +}, +{ + "model": "downloads.releasefile", + "pk": 3891, + "fields": { + "created": "2025-08-06T21:13:43.786Z", + "updated": "2025-08-06T21:13:43.788Z", + "creator": null, + "last_modified_by": null, + "name": "Android embeddable package (x86_64)", + "slug": "3140-rc1-Android-embeddable-package-x86_64", + "os": 4, + "release": 729, + "description": "", + "is_source": false, + "url": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-x86_64-linux-android.tar.gz", + "gpg_signature_file": "", + "sigstore_signature_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-x86_64-linux-android.tar.gz.sig", + "sigstore_cert_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-x86_64-linux-android.tar.gz.crt", + "sigstore_bundle_file": "https://www.python.org/ftp/python/3.14.0/python-3.14.0rc1-x86_64-linux-android.tar.gz.sigstore", + "sbom_spdx2_file": "", + "md5_sum": "3eb6b0c0c03a81c8444300c00724cac5", + "filesize": 29272204, + "download_button": false + } +} ] diff --git a/fixtures/sitetree_menus.json b/fixtures/sitetree_menus.json index f394233ee..59f387f91 100644 --- a/fixtures/sitetree_menus.json +++ b/fixtures/sitetree_menus.json @@ -507,7 +507,7 @@ "access_restricted": false, "access_perm_type": 1, "parent": 8, - "sort_order": 23, + "sort_order": 24, "access_permissions": [] } }, @@ -531,7 +531,7 @@ "access_restricted": false, "access_perm_type": 1, "parent": 8, - "sort_order": 24, + "sort_order": 25, "access_permissions": [] } }, @@ -2742,5 +2742,29 @@ "sort_order": 123, "access_permissions": [] } +}, +{ + "model": "sitetree.treeitem", + "pk": 124, + "fields": { + "title": "Android", + "hint": "", + "url": "/downloads/android/", + "urlaspattern": false, + "tree": 1, + "hidden": false, + "alias": null, + "description": "", + "inmenu": true, + "inbreadcrumbs": true, + "insitetree": true, + "access_loggedin": false, + "access_guest": false, + "access_restricted": false, + "access_perm_type": 1, + "parent": 8, + "sort_order": 23, + "access_permissions": [] + } } ] diff --git a/templates/downloads/os_list.html b/templates/downloads/os_list.html index b110e57b1..127b21a7c 100644 --- a/templates/downloads/os_list.html +++ b/templates/downloads/os_list.html @@ -35,6 +35,11 @@ <h1 class="page-title">Python Releases for {{ os.name }}</h1> <li><a href="{{ latest_python3.get_absolute_url }}">Latest Python 3 Release - {{ latest_python3.name }}</a></li> </ul> + + {% if os.slug == 'android' %} + <p>Rather than using these packages directly, in most cases you should use one of the tools recommended in the <a href="https://docs.python.org/3/using/android.html">Python documentation</a>.</p> + {% endif %} + <div class="col-row two-col"> <div class="column"> <h2>Stable Releases</h2> From 805bb677833ad392cb69d64851b36862223b07c9 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Thu, 7 Aug 2025 23:44:26 -0400 Subject: [PATCH 184/235] Apply for floss.fund (#2763) * Fix broken fixture * serve /funding.json --- fixtures/downloads.json | 2 +- pydotorg/urls.py | 1 + pydotorg/views.py | 17 +++- static/funding.json | 205 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 static/funding.json diff --git a/fixtures/downloads.json b/fixtures/downloads.json index f49e18c5e..e0eb0b1f4 100644 --- a/fixtures/downloads.json +++ b/fixtures/downloads.json @@ -63066,7 +63066,7 @@ "filesize": 18121168, "download_button": false } -} +}, { "model": "downloads.releasefile", "pk": 3880, diff --git a/pydotorg/urls.py b/pydotorg/urls.py index f87ab496b..8a70d5790 100644 --- a/pydotorg/urls.py +++ b/pydotorg/urls.py @@ -21,6 +21,7 @@ path('authenticated', views.AuthenticatedView.as_view(), name='authenticated'), re_path(r'^humans.txt$', TemplateView.as_view(template_name='humans.txt', content_type='text/plain')), re_path(r'^robots.txt$', TemplateView.as_view(template_name='robots.txt', content_type='text/plain')), + re_path(r'^funding.json$', views.serve_funding_json, name='funding_json'), path('shell/', TemplateView.as_view(template_name="python/shell.html"), name='shell'), # python section landing pages diff --git a/pydotorg/views.py b/pydotorg/views.py index 9777cf1aa..bbc30ec51 100644 --- a/pydotorg/views.py +++ b/pydotorg/views.py @@ -1,5 +1,7 @@ +import json +import os from django.conf import settings -from django.http import HttpResponse +from django.http import HttpResponse, JsonResponse from django.views.generic.base import RedirectView, TemplateView from codesamples.models import CodeSample @@ -10,6 +12,19 @@ def health(request): return HttpResponse('OK') +def serve_funding_json(request): + """Serve the funding.json file from the static directory.""" + funding_json_path = os.path.join(settings.BASE, 'static', 'funding.json') + try: + with open(funding_json_path, 'r') as f: + data = json.load(f) + return JsonResponse(data) + except FileNotFoundError: + return JsonResponse({'error': 'funding.json not found'}, status=404) + except json.JSONDecodeError: + return JsonResponse({'error': 'Invalid JSON in funding.json'}, status=500) + + class IndexView(TemplateView): template_name = "python/index.html" diff --git a/static/funding.json b/static/funding.json new file mode 100644 index 000000000..e1af9148a --- /dev/null +++ b/static/funding.json @@ -0,0 +1,205 @@ +{ + "version": "v1.0.0", + "entity": { + "type": "organisation", + "role": "owner", + "name": "Python Software Foundation", + "email": "sponsors@python.org", + "description": "The Python Software Foundation is the charitable organization behind the Python programming language. The mission of the Python Software Foundation 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.", + "webpageUrl": { + "url": "https://www.python.org/psf" + } + }, + "projects": [ + { + "guid": "cpython", + "name": "CPython", + "description": "Python is an open-source programming language. By several measures, it is the most widely used programming language in the world. At our last measurement, python.org served over 110 billion downloads for Python releases annually.", + "webpageUrl": { + "url": "https://www.python.org/" + }, + "repositoryUrl": { + "url": "https://github.com/python/cpython", + "wellKnown": "https://github.com/python/cpython/blob/main/.well-known/funding-manifest-urls" + }, + "licenses": [ + "Python Software Foundation License Version 2" + ], + "tags": [ + "python" + ] + }, + { + "guid": "pypi", + "name": "Python Package Index", + "description": "PyPI is a public repository of software that is free to use for distributing and downloading bundles of Python software. PyPI is a free service the Python Software Foundation maintains and provides to the public.", + "webpageUrl": { + "url": "https://pypi.org/", + "wellKnown": "https://pypi.org/.well-known/funding-manifest-urls" + }, + "repositoryUrl": { + "url": "https://github.com/pypi/warehouse", + "wellKnown": "https://github.com/pypi/warehouse/blob/main/warehouse/templates/funding-manifest-urls.txt" + }, + "licenses": [ + "Apache 2.0 License" + ], + "tags": [ + "python", + "packaging" + ] + }, + { + "guid": "pyconus", + "name": "PyCon US", + "description": "PyCon US is the largest annual gathering for the Python community. Each year, the community comes together to network, learn, share ideas, and create new relationships and partnerships.", + "webpageUrl": { + "url": "https://us.pycon.org/", + "wellKnown": "https://us.pycon.org/.well-known/funding-manifest-urls" + }, + "repositoryUrl": { + "url": "https://github.com/psf/pycon-us-mobile", + "wellKnown": "https://github.com/psf/pycon-us-mobile/blob/main/.well-known/funding-manifest-urls" + }, + "licenses": [ + "MIT" + ], + "tags": [ + "python", + "community", + "events" + ] + }, + { + "guid": "community", + "name": "Global Community Support", + "description": "The PSF Grants Program supports a thriving global network of regional Python events, workshops, user groups, communities, and initiatives.", + "webpageUrl": { + "url": "https://www.python.org/psf/grants/" + }, + "repositoryUrl": { + "url": "https://github.com/psf/.github", + "wellKnown": "https://github.com/psf/.github/blob/main/.well-known/funding-manifest-urls" + }, + "licenses": [ + "MIT" + ], + "tags": [ + "python", + "community", + "networking" + ] + } + ], + "funding": { + "channels": [ + { + "guid": "paypal", + "type": "payment-provider", + "address": "https://psfmember.org/civicrm/contribute/transact?reset=1&id=2", + "description": "Donate directly via PayPal" + }, + { + "guid": "paypal-member", + "type": "payment-provider", + "address": "https://psfmember.org/civicrm/contribute/transact/?reset=1&id=1", + "description": "Become a Supporting Member via PayPal" + }, + { + "guid": "github", + "type": "payment-provider", + "address": "https://github.com/sponsors/psf", + "description": "Donate via GitHub Sponsors, and get recognized on your GitHub profile" + }, + { + "guid": "bank", + "type": "bank", + "address": "sponsors@python.org", + "description": "Please email us for ACH payment details." + } + ], + "plans": [ + { + "guid": "supportingmember", + "status": "active", + "name": "Supporting Member - Individual", + "amount": 99, + "currency": "USD", + "frequency": "yearly", + "channels": ["paypal-member"] + }, + { + "guid": "visionary", + "status": "active", + "name": "Visionary Sponsor", + "amount": 155000, + "currency": "USD", + "frequency": "yearly", + "channels": ["bank"] + }, + { + "guid": "sustainability", + "status": "active", + "name": "Sustainability Sponsor", + "amount": 95000, + "currency": "USD", + "frequency": "yearly", + "channels": ["bank"] + }, + { + "guid": "maintaining", + "status": "active", + "name": "Maintaining Sponsor", + "amount": 63000, + "currency": "USD", + "frequency": "yearly", + "channels": ["bank"] + }, + { + "guid": "contributing", + "status": "active", + "name": "Contributing Sponsor", + "amount": 33000, + "currency": "USD", + "frequency": "yearly", + "channels": ["bank"] + }, + { + "guid": "supporting", + "status": "active", + "name": "Supporting Sponsor", + "amount": 16500, + "currency": "USD", + "frequency": "yearly", + "channels": ["bank"] + }, + { + "guid": "partner", + "status": "active", + "name": "Partner Sponsor", + "amount": 11000, + "currency": "USD", + "frequency": "yearly", + "channels": ["bank"] + }, + { + "guid": "participating", + "status": "active", + "name": "Participating Sponsor", + "amount": 4000, + "currency": "USD", + "frequency": "yearly", + "channels": ["paypal", "github", "bank"] + }, + { + "guid": "associate", + "status": "active", + "name": "Associate Sponsor", + "amount": 1500, + "currency": "USD", + "frequency": "yearly", + "channels": ["paypal", "github", "bank"] + } + ] + } +} From b6587be039fe5d3020707c8f2e60591f59178430 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Fri, 8 Aug 2025 06:05:57 -0400 Subject: [PATCH 185/235] Update funding.json --- static/funding.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/funding.json b/static/funding.json index e1af9148a..92fc307cb 100644 --- a/static/funding.json +++ b/static/funding.json @@ -39,7 +39,7 @@ }, "repositoryUrl": { "url": "https://github.com/pypi/warehouse", - "wellKnown": "https://github.com/pypi/warehouse/blob/main/warehouse/templates/funding-manifest-urls.txt" + "wellKnown": "https://github.com/pypi/warehouse/blob/main/warehouse/.well-known/funding-manifest-urls" }, "licenses": [ "Apache 2.0 License" From 4a0648b2e30d9d9cb30b21fabdc2b0680cfae3e9 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Fri, 8 Aug 2025 06:06:30 -0400 Subject: [PATCH 186/235] Update funding.json --- static/funding.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/funding.json b/static/funding.json index 92fc307cb..a7f09a99a 100644 --- a/static/funding.json +++ b/static/funding.json @@ -39,7 +39,7 @@ }, "repositoryUrl": { "url": "https://github.com/pypi/warehouse", - "wellKnown": "https://github.com/pypi/warehouse/blob/main/warehouse/.well-known/funding-manifest-urls" + "wellKnown": "https://github.com/pypi/warehouse/blob/main/.well-known/funding-manifest-urls" }, "licenses": [ "Apache 2.0 License" From f220ee78183beca99835d0200f6312453838ef41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Aug 2025 21:16:25 -0500 Subject: [PATCH 187/235] chore(deps): bump actions/checkout from 4 to 5 in the github-actions group (#2765) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/static.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4328adf50..05ede12f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: Check out repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install platform dependencies run: | sudo apt -y update diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index d29c620ee..9329c2c8a 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - uses: actions/setup-python@v5 with: python-version-file: '.python-version' From 1ba382822b9cd56db03d76eed5a6ddd68a9e32e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 11:05:00 -0500 Subject: [PATCH 188/235] chore(deps): bump actions/setup-python from 5 to 6 in the github-actions group (#2768) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/static.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05ede12f3..23c5ad626 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: run: | wget https://github.com/jgm/pandoc/releases/download/2.17.1.1/pandoc-2.17.1.1-1-amd64.deb sudo dpkg -i pandoc-2.17.1.1-1-amd64.deb - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version-file: '.python-version' - name: Cache Python dependencies diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 9329c2c8a..7941021ca 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -8,7 +8,7 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v5 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version-file: '.python-version' - name: Cache Python dependencies From a7cb7147e5bebbbee8391ef7ed7bec5344be82cb Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:49:02 +0100 Subject: [PATCH 189/235] Link 'GPG' in downloads table to more info (#2772) --- templates/downloads/release_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 0ddcde32a..cb46e126c 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -53,7 +53,7 @@ <h1 class="page-title">Files</h1> <th>MD5 Sum</th> <th>File Size</th> {% if release_files|has_gpg %} - <th>GPG</th> + <th><a href="https://www.python.org/downloads/#gpg">GPG</a></th> {% endif %} {% if release_files|has_sigstore_materials %} <th colspan="2"><a href="https://www.python.org/download/sigstore/">Sigstore</a></th> From ad226ec288d0409ba38d6fb7becfe93ae4d9b88a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 10:47:19 -0500 Subject: [PATCH 190/235] chore(deps): bump whitenoise from 6.6.0 to 6.11.0 (#2778) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- prod-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prod-requirements.txt b/prod-requirements.txt index 72bf30dcd..28b186f6a 100644 --- a/prod-requirements.txt +++ b/prod-requirements.txt @@ -3,6 +3,6 @@ gunicorn==23.0.0 raven==6.10.0 # Heroku -Whitenoise==6.6.0 # 6.4.0 is first version that supports Django 4.2 +Whitenoise==6.11.0 # 6.4.0 is first version that supports Django 4.2 django-storages==1.14.4 # 1.14.4 is first version that supports Django 4.2 boto3==1.26.165 From b569dc86897ec279c7bc34a141aa0e3517d5ee32 Mon Sep 17 00:00:00 2001 From: Sohan Shanbhag <127968647+sohanshanbhag1502@users.noreply.github.com> Date: Tue, 23 Sep 2025 20:39:49 +0530 Subject: [PATCH 191/235] fix(Frontend): Fixed Issue #1433 "Wrong arrow when select Community" (#2777) --- templates/community/post_detail.html | 2 +- templates/community/post_list.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/community/post_detail.html b/templates/community/post_detail.html index ccd29d77c..502b49a43 100644 --- a/templates/community/post_detail.html +++ b/templates/community/post_detail.html @@ -3,7 +3,7 @@ {% block page_title %}{{ object.title }} | {{ SITE_INFO.site_name }}{% endblock %} {% block og_title %}{{ object.title }}{% endblock %} -{% block body_attributes %}class="python community default-page"{% endblock %} +{% block body_attributes %}class="shop community default-page"{% endblock %} {% block main-nav_attributes %}community-navigation{% endblock main-nav_attributes %} diff --git a/templates/community/post_list.html b/templates/community/post_list.html index 627fd2912..b5e10bfe5 100644 --- a/templates/community/post_list.html +++ b/templates/community/post_list.html @@ -5,7 +5,7 @@ {% block page_title %}Our Community | {{ SITE_INFO.site_name }}{% endblock %} {% block og_title %}Our Community{% endblock %} -{% block body_attributes %}class="python community"{% endblock %} +{% block body_attributes %}class="shop"{% endblock %} {% block main-nav_attributes %}python-navigation{% endblock main-nav_attributes %} From 5c61eb5f77f244585e14fcbb3a53047f51d024e1 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 30 Sep 2025 17:38:29 +0300 Subject: [PATCH 192/235] Prioritise Sigstore over GPG in downloads table (#2783) --- templates/downloads/release_detail.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index cb46e126c..db49d974e 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -52,15 +52,15 @@ <h1 class="page-title">Files</h1> <th>Description</th> <th>MD5 Sum</th> <th>File Size</th> - {% if release_files|has_gpg %} - <th><a href="https://www.python.org/downloads/#gpg">GPG</a></th> - {% endif %} {% if release_files|has_sigstore_materials %} <th colspan="2"><a href="https://www.python.org/download/sigstore/">Sigstore</a></th> {% endif %} {% if release_files|has_sbom %} <th><a href="https://www.python.org/download/sbom/">SBOM</a></th> {% endif %} + {% if release_files|has_gpg %} + <th><a href="https://www.python.org/downloads/#gpg">GPG</a></th> + {% endif %} </tr> </thead> <tbody> @@ -71,9 +71,6 @@ <h1 class="page-title">Files</h1> <td>{{ f.description }}</td> <td>{{ f.md5_sum }}</td> <td>{{ f.filesize|filesizeformat }}</td> - {% if release_files|has_gpg %} - <td>{% if f.gpg_signature_file %}<a href="{{ f.gpg_signature_file }}">SIG</a>{% endif %}</td> - {% endif %} {% if release_files|has_sigstore_materials %} {% if f.sigstore_bundle_file %} <td colspan="2">{% if f.sigstore_bundle_file %}<a href="{{ f.sigstore_bundle_file}}">.sigstore</a>{% endif %}</td> @@ -85,6 +82,9 @@ <h1 class="page-title">Files</h1> {% if release_files|has_sbom %} <td>{% if f.sbom_spdx2_file %}<a href="{{ f.sbom_spdx2_file }}">SPDX</a>{% endif %}</td> {% endif %} + {% if release_files|has_gpg %} + <td>{% if f.gpg_signature_file %}<a href="{{ f.gpg_signature_file }}">SIG</a>{% endif %}</td> + {% endif %} </tr> {% endfor %} </tbody> From 700120f742cd1175d164018c0bcef60456787292 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 23:03:35 +0000 Subject: [PATCH 193/235] chore(deps): bump django from 4.2.22 to 4.2.25 (#2784) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index cd8474961..c0515c27f 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.22 +Django==4.2.25 docutils==0.21.2 Markdown==3.7 cmarkgfm==2024.11.20 From dd0a24bd1ba267b878fd9edfe92b3c2b2434603b Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Thu, 2 Oct 2025 18:32:46 +0100 Subject: [PATCH 194/235] Change "Non-English Docs" link to the translation dashboard (#2776) --- fixtures/sitetree_menus.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fixtures/sitetree_menus.json b/fixtures/sitetree_menus.json index 59f387f91..70de29110 100644 --- a/fixtures/sitetree_menus.json +++ b/fixtures/sitetree_menus.json @@ -661,7 +661,7 @@ "fields": { "title": "Non-English Docs", "hint": "", - "url": "http://wiki.python.org/moin/Languages", + "url": "https://python-docs-translations.github.io/dashboard/", "urlaspattern": false, "tree": 1, "hidden": false, From b9f398cb22bbaad62cf64a159a728386610f7e26 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Mon, 6 Oct 2025 13:32:56 -0400 Subject: [PATCH 195/235] remove all feedburner urls, ref #2787 (#2788) --- pydotorg/settings/base.py | 2 +- templates/base.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pydotorg/settings/base.py b/pydotorg/settings/base.py index 2c392b355..0fac91eb1 100644 --- a/pydotorg/settings/base.py +++ b/pydotorg/settings/base.py @@ -278,7 +278,7 @@ HONEYPOT_VALUE = 'write your message' ### Blog Feed URL -PYTHON_BLOG_FEED_URL = "https://feeds.feedburner.com/PythonInsider" +PYTHON_BLOG_FEED_URL = "https://blog.python.org/feeds/posts/default?alt=rss" PYTHON_BLOG_URL = "https://blog.python.org" ### Registration mailing lists diff --git a/templates/base.html b/templates/base.html index f66f80ca9..527baf616 100644 --- a/templates/base.html +++ b/templates/base.html @@ -84,9 +84,9 @@ <link rel="alternate" type="application/rss+xml" title="Python Job Opportunities" href="https://www.python.org/jobs/feed/rss/"> <link rel="alternate" type="application/rss+xml" title="Python Software Foundation News" - href="https://feeds.feedburner.com/PythonSoftwareFoundationNews"> + href="https://pyfound.blogspot.com/feeds/posts/default?alt=rss"> <link rel="alternate" type="application/rss+xml" title="Python Insider" - href="https://feeds.feedburner.com/PythonInsider"> + href="https://blog.python.org/feeds/posts/default?alt=rss"> <link rel="alternate" type="application/rss+xml" title="Python Releases" href="https://www.python.org/downloads/feed.rss"> From 4218afeb0af61a217bab41003981b444a48f4aef Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Wed, 8 Oct 2025 10:34:17 -0400 Subject: [PATCH 196/235] migrate from raven to sentry sdk (#2789) --- prod-requirements.txt | 2 +- pydotorg/settings/cabotage.py | 19 ++++++++++--------- pydotorg/settings/static.py | 1 - 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/prod-requirements.txt b/prod-requirements.txt index 28b186f6a..bf48d2731 100644 --- a/prod-requirements.txt +++ b/prod-requirements.txt @@ -1,6 +1,6 @@ gunicorn==23.0.0 -raven==6.10.0 +sentry-sdk[django]==2.40.0 # Heroku Whitenoise==6.11.0 # 6.4.0 is first version that supports Django 4.2 diff --git a/pydotorg/settings/cabotage.py b/pydotorg/settings/cabotage.py index 4661fbf66..654db889e 100644 --- a/pydotorg/settings/cabotage.py +++ b/pydotorg/settings/cabotage.py @@ -1,7 +1,8 @@ import os import dj_database_url -import raven +import sentry_sdk +from sentry_sdk.integrations.django import DjangoIntegration from decouple import Csv from .base import * @@ -71,14 +72,14 @@ SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True -INSTALLED_APPS += [ - "raven.contrib.django.raven_compat", -] - -RAVEN_CONFIG = { - "dsn": config('SENTRY_DSN'), - "release": config('SOURCE_COMMIT'), -} +sentry_sdk.init( + dsn=config('SENTRY_DSN'), + integrations=[DjangoIntegration()], + release=config('SOURCE_COMMIT'), + send_default_pii=True, + traces_sample_rate=0.1, + profiles_sample_rate=0.1, +) AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY') diff --git a/pydotorg/settings/static.py b/pydotorg/settings/static.py index 5dcbf6f92..49b7c643c 100644 --- a/pydotorg/settings/static.py +++ b/pydotorg/settings/static.py @@ -1,7 +1,6 @@ import os import dj_database_url -import raven from decouple import Csv from .base import * From e8ac397c5b9ab8092c68a98735ee95b9cff88568 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Wed, 8 Oct 2025 15:03:23 -0400 Subject: [PATCH 197/235] fix: handle release objects with 'invalid' names (#2790) --- downloads/models.py | 4 ++-- downloads/tests/test_models.py | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/downloads/models.py b/downloads/models.py index 3c0a74f97..6a810c393 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -125,7 +125,7 @@ def get_version(self): version = re.match(r'Python\s([\d.]+)', self.name) if version is not None: return version.group(1) - return None + return "" def is_version_at_least(self, min_version_tuple): v1 = [] @@ -291,7 +291,7 @@ def purge_fastly_download_pages(sender, instance, **kwargs): purge_url('/downloads/source/') purge_url('/downloads/windows/') purge_url('/ftp/python/') - if instance.get_version() is not None: + if instance.get_version(): purge_url(f'/ftp/python/{instance.get_version()}/') # See issue #584 for details purge_url('/box/supernav-python-downloads/') diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index d31afae5c..e73858d3b 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -74,7 +74,7 @@ def test_get_version_invalid(self): with self.subTest(name=name): release = Release.objects.create(name=name) self.assertEqual(release.name, name) - self.assertIsNone(release.get_version()) + self.assertEqual(release.get_version(), "") def test_is_version_at_least(self): self.assertFalse(self.release_275.is_version_at_least_3_5) @@ -87,3 +87,11 @@ def test_is_version_at_least(self): release_310 = Release.objects.create(name='Python 3.10.0') self.assertTrue(release_310.is_version_at_least_3_9) self.assertTrue(release_310.is_version_at_least_3_5) + + def test_is_version_at_least_with_invalid_name(self): + """Test that is_version_at_least returns False for releases with invalid names""" + invalid_release = Release.objects.create(name='Python install manager') + # Should return False instead of raising AttributeError + self.assertFalse(invalid_release.is_version_at_least_3_5) + self.assertFalse(invalid_release.is_version_at_least_3_9) + self.assertFalse(invalid_release.is_version_at_least_3_14) From 7a8bd53d85a6f10bc76238158c5178da93ecff41 Mon Sep 17 00:00:00 2001 From: Steve Dower <steve.dower@python.org> Date: Fri, 10 Oct 2025 20:09:43 +0100 Subject: [PATCH 198/235] Update downloads supernav page for Python install manager (#2793) --- downloads/models.py | 20 +++++++----- downloads/tests/test_models.py | 53 ++++++++++++++++++++++++++++++- templates/downloads/supernav.html | 4 ++- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/downloads/models.py b/downloads/models.py index 6a810c393..aa929855d 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -158,24 +158,29 @@ def update_supernav(): if not latest_python3: return + try: + latest_pymanager = Release.objects.latest_pymanager() + except Release.DoesNotExist: + latest_pymanager = None + python_files = [] for o in OS.objects.all(): data = { 'os': o, 'python3': None, + 'pymanager': None, } - release_file = latest_python3.download_file_for_os(o.slug) - if not release_file: - continue - data['python3'] = release_file + data['python3'] = latest_python3.download_file_for_os(o.slug) + if latest_pymanager: + data['pymanager'] = latest_pymanager.download_file_for_os(o.slug) python_files.append(data) if not python_files: return - if not all(f['python3'] for f in python_files): + if not all(f['python3'] or f['pymanager'] for f in python_files): # We have a latest Python release, different OSes, but don't have release # files for the release, so return early. return @@ -287,6 +292,7 @@ def purge_fastly_download_pages(sender, instance, **kwargs): purge_url('/downloads/feed.rss') purge_url('/downloads/latest/python2/') purge_url('/downloads/latest/python3/') + purge_url('/downloads/latest/pymanager/') purge_url('/downloads/macos/') purge_url('/downloads/source/') purge_url('/downloads/windows/') @@ -308,9 +314,7 @@ def update_download_supernav_and_boxes(sender, instance, **kwargs): return if instance.is_published: - # Supernav only has download buttons for Python 3. - if instance.version == instance.PYTHON3: - update_supernav() + update_supernav() update_download_landing_sources_box() update_homepage_download_box() diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index e73858d3b..bd26c3b58 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -1,4 +1,4 @@ -from ..models import Release +from ..models import Release, ReleaseFile from .base import BaseDownloadTests @@ -95,3 +95,54 @@ def test_is_version_at_least_with_invalid_name(self): self.assertFalse(invalid_release.is_version_at_least_3_5) self.assertFalse(invalid_release.is_version_at_least_3_9) self.assertFalse(invalid_release.is_version_at_least_3_14) + + def test_update_supernav(self): + from ..models import update_supernav + from boxes.models import Box + + release = Release.objects.create( + name='Python install manager 25.0', + version=Release.PYMANAGER, + is_latest=True, + is_published=True, + ) + + for os, slug in [ + (self.windows, 'python3.10-windows'), + (self.osx, 'python3.10-macos'), + (self.linux, 'python3.10-linux'), + ]: + ReleaseFile.objects.create( + os=os, + release=self.python_3, + slug=slug, + name='Python 3.10', + url='/ftp/python/{}.zip'.format(slug), + download_button=True, + ) + + update_supernav() + + content = Box.objects.get(label='supernav-python-downloads').content.rendered + self.assertIn('class="download-os-windows"', content) + self.assertNotIn('pymanager-25.0.msix', content) + self.assertIn('python3.10-windows.zip', content) + self.assertIn('class="download-os-macos"', content) + self.assertIn('python3.10-macos.zip', content) + self.assertIn('class="download-os-linux"', content) + self.assertIn('python3.10-linux.zip', content) + + ReleaseFile.objects.create( + os=self.windows, + release=release, + name='MSIX', + url='/ftp/python/pymanager/pymanager-25.0.msix', + download_button=True, + ) + + update_supernav() + + content = Box.objects.get(label='supernav-python-downloads').content.rendered + self.assertIn('class="download-os-windows"', content) + self.assertIn('pymanager-25.0.msix', content) + self.assertIn('python3.10-windows.zip', content) diff --git a/templates/downloads/supernav.html b/templates/downloads/supernav.html index 12568eadb..edd23dc82 100644 --- a/templates/downloads/supernav.html +++ b/templates/downloads/supernav.html @@ -10,8 +10,10 @@ <h4>Download for {{ data.os.name }}</h4> {% if data.pymanager %} <p><a class="button" href="{{ data.pymanager.url }}">Python install manager</a></p> + {% if data.python3 %} <p>Or get the standalone installer for <a class="button" href="{{ data.python3.url }}">{{ data.python3.release.name }}</a></p> - {% else %} + {% endif %} + {% elif data.python3 %} <p> <a class="button" href="{{ data.python3.url }}">{{ data.python3.release.name }}</a> </p> From bea5da146a50459d6d7196ba60e580c078d98535 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Thu, 30 Oct 2025 16:01:26 -0400 Subject: [PATCH 199/235] Update sponsorship-agreement.md (#2801) --- templates/sponsors/admin/contracts/sponsorship-agreement.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/sponsors/admin/contracts/sponsorship-agreement.md b/templates/sponsors/admin/contracts/sponsorship-agreement.md index 73540dbab..9e68e4d35 100644 --- a/templates/sponsors/admin/contracts/sponsorship-agreement.md +++ b/templates/sponsors/admin/contracts/sponsorship-agreement.md @@ -112,7 +112,7 @@ wishes to support the Programs by making a contribution to the PSF. >          9450 SW Gemini Dr. ECM # 90772 >          Beaverton, OR 97008 USA >          Facsimile: +1 (858) 712-8966 - >          Email: deb@python.org + >          Email: deb@python.org, with a copy to: legal@python.org   @@ -172,7 +172,7 @@ wishes to support the Programs by making a contribution to the PSF. > By:        ________________________________ > Name:   Loren Crary -> Title:     Director of Resource Development +> Title:     Deputy Executive Director   From 869bc732f99ac5c4ff69b3e4285cb45e5957c738 Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Thu, 30 Oct 2025 16:21:41 -0400 Subject: [PATCH 200/235] Add management command to reset sponsorship benefits (#2802) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new management command `reset_sponsorship_benefits` that performs a complete clean slate reset of sponsorship benefits when sponsors transition from one year's package to another (e.g., 2025 to 2026). This addresses the issue where sponsorships created in 2025 were later assigned to 2026 packages but retained 2025 benefit configurations, templates, and asset references, causing inconsistencies in the admin interface and benefit calculations. Command features: - Deletes ALL GenericAssets linked to the sponsorship (including old year references) - Deletes ALL existing sponsor benefits (cascades to features) - Recreates all benefits fresh from the target year's package template - Updates sponsorship year to match package year (with --update-year flag) - Supports dry-run mode for safe preview (with --dry-run flag) - Uses atomic transactions to ensure data consistency - Handles edge cases: duplicates, renamed benefits, missing templates Usage: python manage.py reset_sponsorship_benefits <id> [<id> ...] --update-year python manage.py reset_sponsorship_benefits <id> --dry-run --update-year Tests added to verify: - Full 2025 to 2026 transition scenario - Duplicate benefit handling - Dry-run mode functionality - Year updates - GenericAsset cleanup - Admin visibility (template year matching) - Feature recreation with updated configurations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com> --- .../commands/reset_sponsorship_benefits.py | 214 +++++++++++ sponsors/tests/test_management_command.py | 338 +++++++++++++++++- 2 files changed, 551 insertions(+), 1 deletion(-) create mode 100644 sponsors/management/commands/reset_sponsorship_benefits.py diff --git a/sponsors/management/commands/reset_sponsorship_benefits.py b/sponsors/management/commands/reset_sponsorship_benefits.py new file mode 100644 index 000000000..16087b894 --- /dev/null +++ b/sponsors/management/commands/reset_sponsorship_benefits.py @@ -0,0 +1,214 @@ +from django.core.management.base import BaseCommand +from django.db import transaction +from sponsors.models import Sponsorship, SponsorshipBenefit + + +class Command(BaseCommand): + help = "Reset benefits for specified sponsorships to match their current package/year templates" + + def add_arguments(self, parser): + parser.add_argument( + "sponsorship_ids", + nargs="+", + type=int, + help="IDs of sponsorships to reset benefits for", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Show what would be reset without actually doing it", + ) + parser.add_argument( + "--update-year", + action="store_true", + help="Update sponsorship year to match the package year", + ) + + def handle(self, *args, **options): + sponsorship_ids = options["sponsorship_ids"] + dry_run = options["dry_run"] + update_year = options["update_year"] + + if dry_run: + self.stdout.write(self.style.WARNING("DRY RUN MODE - No changes will be made")) + + for sid in sponsorship_ids: + try: + sponsorship = Sponsorship.objects.get(id=sid) + except Sponsorship.DoesNotExist: + self.stdout.write( + self.style.ERROR(f"Sponsorship {sid} does not exist - skipping") + ) + continue + + self.stdout.write(f"\n{'='*60}") + self.stdout.write(f"Sponsorship ID: {sid}") + self.stdout.write(f"Sponsor: {sponsorship.sponsor.name}") + self.stdout.write(f"Package: {sponsorship.package.name if sponsorship.package else 'None'}") + self.stdout.write(f"Sponsorship Year: {sponsorship.year}") + if sponsorship.package: + self.stdout.write(f"Package Year: {sponsorship.package.year}") + self.stdout.write(f"Status: {sponsorship.status}") + self.stdout.write(f"{'='*60}") + + if not sponsorship.package: + self.stdout.write( + self.style.WARNING(" No package associated - skipping") + ) + continue + + # Check if year mismatch and update if requested + target_year = sponsorship.year + if sponsorship.package.year != sponsorship.year: + self.stdout.write( + self.style.WARNING( + f"Year mismatch: Sponsorship year ({sponsorship.year}) != " + f"Package year ({sponsorship.package.year})" + ) + ) + if update_year: + target_year = sponsorship.package.year + if not dry_run: + sponsorship.year = target_year + sponsorship.save() + self.stdout.write( + self.style.SUCCESS( + f" ✓ Updated sponsorship year to {target_year}" + ) + ) + else: + self.stdout.write( + self.style.SUCCESS( + f" [DRY RUN] Would update sponsorship year to {target_year}" + ) + ) + else: + self.stdout.write( + self.style.WARNING( + f" Use --update-year to update sponsorship year to {sponsorship.package.year}" + ) + ) + + # Get template benefits for this package and target year + template_benefits = SponsorshipBenefit.objects.filter( + packages=sponsorship.package, + year=target_year + ) + + self.stdout.write( + self.style.SUCCESS( + f"Found {template_benefits.count()} template benefits for year {target_year}" + ) + ) + + if template_benefits.count() == 0: + self.stdout.write( + self.style.ERROR( + f" ERROR: No template benefits found for package " + f"'{sponsorship.package.name}' year {target_year}" + ) + ) + continue + + reset_count = 0 + missing_count = 0 + + # Use transaction to ensure atomicity + with transaction.atomic(): + from sponsors.models import SponsorBenefit, GenericAsset + from django.contrib.contenttypes.models import ContentType + + # Get count of current benefits before deletion + current_count = sponsorship.benefits.count() + expected_count = template_benefits.count() + + self.stdout.write( + f"Current benefits: {current_count}, Expected: {expected_count}" + ) + + # STEP 1: Delete ALL GenericAssets linked to this sponsorship + sponsorship_ct = ContentType.objects.get_for_model(sponsorship) + generic_assets = GenericAsset.objects.filter( + content_type=sponsorship_ct, + object_id=sponsorship.id + ) + asset_count = generic_assets.count() + + if asset_count > 0: + if not dry_run: + # Delete each asset individually to handle polymorphic cascade properly + deleted_count = 0 + for asset in generic_assets: + asset.delete() + deleted_count += 1 + self.stdout.write( + self.style.WARNING(f" 🗑 Deleted {deleted_count} GenericAssets") + ) + else: + self.stdout.write( + self.style.WARNING(f" [DRY RUN] Would delete {asset_count} GenericAssets") + ) + + # STEP 2: Delete ALL existing sponsor benefits (this cascades to features) + if not dry_run: + deleted_count = 0 + for benefit in sponsorship.benefits.all(): + self.stdout.write(f" 🗑 Deleting benefit: {benefit.name}") + benefit.delete() + deleted_count += 1 + self.stdout.write( + self.style.WARNING(f"\nDeleted {deleted_count} existing benefits") + ) + else: + self.stdout.write( + self.style.WARNING(f" [DRY RUN] Would delete all {current_count} existing benefits") + ) + + # STEP 3: Add all benefits from the package template + if not dry_run: + self.stdout.write(f"\nAdding {expected_count} benefits from {target_year} package...") + added_count = 0 + for template in template_benefits: + # Create new benefit with all features from template + new_benefit = SponsorBenefit.new_copy( + template, + sponsorship=sponsorship, + added_by_user=False + ) + self.stdout.write(f" ✓ Added: {template.name}") + added_count += 1 + + self.stdout.write( + self.style.SUCCESS(f"\nAdded {added_count} benefits with all features") + ) + reset_count = added_count + else: + self.stdout.write( + self.style.SUCCESS( + f" [DRY RUN] Would add {expected_count} benefits from {target_year} package" + ) + ) + for template in template_benefits[:5]: # Show first 5 + self.stdout.write(f" - {template.name}") + if expected_count > 5: + self.stdout.write(f" ... and {expected_count - 5} more") + + if dry_run: + # Rollback transaction in dry run + transaction.set_rollback(True) + + self.stdout.write( + self.style.SUCCESS( + f"\nSummary for Sponsorship {sid}: " + f"Removed {current_count}, Added {expected_count}" + ) + ) + + if dry_run: + self.stdout.write( + self.style.WARNING("\nDRY RUN COMPLETE - No changes were made") + ) + else: + self.stdout.write( + self.style.SUCCESS("\nAll sponsorship benefits have been reset!") + ) diff --git a/sponsors/tests/test_management_command.py b/sponsors/tests/test_management_command.py index 100daad2a..e86b14d0e 100644 --- a/sponsors/tests/test_management_command.py +++ b/sponsors/tests/test_management_command.py @@ -1,11 +1,25 @@ from django.test import TestCase +from django.core.management import call_command from model_bakery import baker from unittest import mock +from io import StringIO -from sponsors.models import ProvidedTextAssetConfiguration, ProvidedTextAsset +from sponsors.models import ( + ProvidedTextAssetConfiguration, + ProvidedTextAsset, + Sponsor, + Sponsorship, + SponsorshipBenefit, + SponsorshipPackage, + SponsorshipProgram, + SponsorshipCurrentYear, + GenericAsset, + TieredBenefitConfiguration, +) from sponsors.models.enums import AssetsRelatedTo +from django.contrib.contenttypes.models import ContentType from sponsors.management.commands.create_pycon_vouchers_for_sponsors import ( generate_voucher_codes, @@ -52,3 +66,325 @@ def test_generate_voucher_codes(self, mock_api_call): sponsor_benefit__id=benefit_id, internal_name=code["internal_name"] ) self.assertEqual(asset.value, "test-promo-code") + + +class ResetSponsorshipBenefitsTestCase(TestCase): + """ + Test the reset_sponsorship_benefits management command. + + Scenario: A sponsor applies while 2025 is the current year, the current year + changes to 2026 with new packages, the sponsor is assigned the new package, + then the command is run to reset benefits. + """ + + def setUp(self): + """Set up test data for 2025 and 2026 sponsorships""" + # Create sponsor + self.sponsor = baker.make(Sponsor, name="Test Sponsor Corp") + + # Create program + self.program = baker.make(SponsorshipProgram, name="PSF Sponsorship") + + # Set current year to 2025 + current_year = SponsorshipCurrentYear.objects.first() + if current_year: + current_year.year = 2025 + current_year.save() + else: + SponsorshipCurrentYear.objects.create(year=2025) + + # Create 2025 package and benefits + self.package_2025 = baker.make( + SponsorshipPackage, + name="Gold", + year=2025, + sponsorship_amount=10000, + ) + + # Create 2025 benefits + self.benefit_2025_a = baker.make( + SponsorshipBenefit, + name="Logo on Website", + year=2025, + program=self.program, + internal_value=1000, + ) + self.benefit_2025_b = baker.make( + SponsorshipBenefit, + name="Conference Passes - OLD NAME", + year=2025, + program=self.program, + internal_value=2000, + ) + self.benefit_2025_c = baker.make( + SponsorshipBenefit, + name="Social Media Mention", + year=2025, + program=self.program, + internal_value=500, + ) + + # Add benefits to 2025 package + self.package_2025.benefits.add( + self.benefit_2025_a, + self.benefit_2025_b, + self.benefit_2025_c, + ) + + # Add tiered benefit configuration to 2025 benefit + baker.make( + TieredBenefitConfiguration, + benefit=self.benefit_2025_b, + package=self.package_2025, + quantity=5, + ) + + # Create 2026 package and benefits + self.package_2026 = baker.make( + SponsorshipPackage, + name="Gold", + year=2026, + sponsorship_amount=12000, + ) + + # Create 2026 benefits (some renamed, some new) + self.benefit_2026_a = baker.make( + SponsorshipBenefit, + name="Logo on Website", + year=2026, + program=self.program, + internal_value=1500, + ) + self.benefit_2026_b = baker.make( + SponsorshipBenefit, + name="Conference Passes", # Renamed from "Conference Passes - OLD NAME" + year=2026, + program=self.program, + internal_value=2500, + ) + self.benefit_2026_d = baker.make( + SponsorshipBenefit, + name="Newsletter Feature", # New benefit for 2026 + year=2026, + program=self.program, + internal_value=750, + ) + + # Add benefits to 2026 package (note: Social Media Mention is removed) + self.package_2026.benefits.add( + self.benefit_2026_a, + self.benefit_2026_b, + self.benefit_2026_d, + ) + + # Add tiered benefit configuration to 2026 benefit + baker.make( + TieredBenefitConfiguration, + benefit=self.benefit_2026_b, + package=self.package_2026, + quantity=10, # Increased from 5 + ) + + def test_reset_sponsorship_benefits_from_2025_to_2026(self): + """ + Test that a sponsorship created in 2025 can be reset to 2026 benefits + after being assigned to a 2026 package. + """ + # Step 1: Sponsor applies in 2025 with 2025 package + sponsorship = Sponsorship.new( + self.sponsor, + [self.benefit_2025_a, self.benefit_2025_b, self.benefit_2025_c], + package=self.package_2025, + ) + + # Verify initial state + self.assertEqual(sponsorship.year, 2025) + self.assertEqual(sponsorship.package.year, 2025) + self.assertEqual(sponsorship.benefits.count(), 3) + + # Verify all benefits have 2025 templates + for benefit in sponsorship.benefits.all(): + self.assertEqual(benefit.sponsorship_benefit.year, 2025) + + # Create some GenericAssets with 2025 references + sponsorship_ct = ContentType.objects.get_for_model(sponsorship) + asset_2025 = baker.make( + "sponsors.TextAsset", + content_type=sponsorship_ct, + object_id=sponsorship.id, + internal_name="conference_passes_code_2025", + text="2025-CODE-123", + ) + + # Step 2: Current year changes to 2026 + current_year = SponsorshipCurrentYear.objects.first() + current_year.year = 2026 + current_year.save() + + # Step 3: Sponsor is assigned to 2026 package (simulating admin action) + sponsorship.package = self.package_2026 + sponsorship.save() + + # At this point, sponsorship has: + # - year = 2025 + # - package year = 2026 + # - benefits linked to 2025 templates + # - GenericAssets with 2025 references + self.assertEqual(sponsorship.year, 2025) + self.assertEqual(sponsorship.package.year, 2026) + + # Verify there are GenericAssets with 2025 references + assets_2025 = GenericAsset.objects.filter( + content_type=sponsorship_ct, + object_id=sponsorship.id, + internal_name__contains="2025", + ) + self.assertGreater(assets_2025.count(), 0) + + # Step 4: Run the management command + out = StringIO() + call_command( + "reset_sponsorship_benefits", + str(sponsorship.id), + "--update-year", + stdout=out, + ) + + # Step 5: Verify the reset + sponsorship.refresh_from_db() + + # Verify year was updated + self.assertEqual(sponsorship.year, 2026) + + # Verify benefits were reset to 2026 package + self.assertEqual(sponsorship.benefits.count(), 3) + + # Verify all benefits now point to 2026 templates + for benefit in sponsorship.benefits.all(): + self.assertEqual(benefit.sponsorship_benefit.year, 2026) + + # Verify benefit names match 2026 package + benefit_names = set(sponsorship.benefits.values_list("name", flat=True)) + expected_names = { + "Logo on Website", + "Conference Passes", + "Newsletter Feature", + } + self.assertEqual(benefit_names, expected_names) + + # Verify old benefit was removed + self.assertNotIn("Social Media Mention", benefit_names) + self.assertNotIn("Conference Passes - OLD NAME", benefit_names) + + # Verify new benefit was added + self.assertIn("Newsletter Feature", benefit_names) + + # Verify GenericAssets with 2025 references were deleted + assets_2025_after = GenericAsset.objects.filter( + content_type=sponsorship_ct, + object_id=sponsorship.id, + internal_name__contains="2025", + ) + self.assertEqual(assets_2025_after.count(), 0) + + # Verify benefits are visible in admin (template year matches sponsorship year) + visible_benefits = sponsorship.benefits.filter( + sponsorship_benefit__year=sponsorship.year + ) + self.assertEqual(visible_benefits.count(), sponsorship.benefits.count()) + + # Verify benefit features were recreated with 2026 configurations + conference_passes_benefit = sponsorship.benefits.get(name="Conference Passes") + tiered_features = conference_passes_benefit.features.filter( + polymorphic_ctype__model="tieredbenefit" + ) + self.assertEqual(tiered_features.count(), 1) + + # Verify the quantity was updated from 2025 config (5) to 2026 config (10) + from sponsors.models import TieredBenefit + tiered_benefit = TieredBenefit.objects.get( + sponsor_benefit=conference_passes_benefit + ) + self.assertEqual(tiered_benefit.quantity, 10) + + def test_reset_with_duplicate_benefits(self): + """Test that the reset handles duplicate benefits correctly""" + # Create sponsorship with duplicate benefits + sponsorship = Sponsorship.new( + self.sponsor, + [self.benefit_2025_a], + package=self.package_2025, + ) + + # Manually create a duplicate benefit + from sponsors.models import SponsorBenefit + duplicate = SponsorBenefit.new_copy( + self.benefit_2025_a, + sponsorship=sponsorship, + added_by_user=False, + ) + + # Verify we have a duplicate + self.assertEqual(sponsorship.benefits.count(), 2) + self.assertEqual( + sponsorship.benefits.filter(name="Logo on Website").count(), 2 + ) + + # Update to 2026 package + sponsorship.package = self.package_2026 + sponsorship.save() + + # Run command + out = StringIO() + call_command( + "reset_sponsorship_benefits", + str(sponsorship.id), + "--update-year", + stdout=out, + ) + + # Verify duplicates were handled + sponsorship.refresh_from_db() + self.assertEqual(sponsorship.benefits.count(), 3) # All 2026 benefits + self.assertEqual( + sponsorship.benefits.filter(name="Logo on Website").count(), 1 + ) + + def test_dry_run_mode(self): + """Test that dry run doesn't make any changes""" + # Create sponsorship + sponsorship = Sponsorship.new( + self.sponsor, + [self.benefit_2025_a, self.benefit_2025_b], + package=self.package_2025, + ) + + # Update to 2026 package + sponsorship.package = self.package_2026 + sponsorship.save() + + # Record initial state + initial_year = sponsorship.year + initial_benefit_count = sponsorship.benefits.count() + initial_benefit_ids = set(sponsorship.benefits.values_list("id", flat=True)) + + # Run command in dry-run mode + out = StringIO() + call_command( + "reset_sponsorship_benefits", + str(sponsorship.id), + "--update-year", + "--dry-run", + stdout=out, + ) + + # Verify nothing changed + sponsorship.refresh_from_db() + self.assertEqual(sponsorship.year, initial_year) + self.assertEqual(sponsorship.benefits.count(), initial_benefit_count) + current_benefit_ids = set(sponsorship.benefits.values_list("id", flat=True)) + self.assertEqual(current_benefit_ids, initial_benefit_ids) + + # Verify dry run message was printed + output = out.getvalue() + self.assertIn("DRY RUN", output) From 323a2ba2af7322811672204a5784b6110f533e3e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 4 Nov 2025 19:13:58 +0200 Subject: [PATCH 201/235] Change default for downloads from reStructuredText to Markdown (#2803) --- .../0013_alter_release_content_markup_type.py | 18 ++++++++++++++++++ downloads/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 downloads/migrations/0013_alter_release_content_markup_type.py diff --git a/downloads/migrations/0013_alter_release_content_markup_type.py b/downloads/migrations/0013_alter_release_content_markup_type.py new file mode 100644 index 000000000..1d896c1c4 --- /dev/null +++ b/downloads/migrations/0013_alter_release_content_markup_type.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.25 on 2025-11-01 21:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('downloads', '0012_alter_release_version'), + ] + + operations = [ + migrations.AlterField( + model_name='release', + name='content_markup_type', + field=models.CharField(choices=[('', '--'), ('html', 'HTML'), ('plain', 'Plain'), ('markdown', 'Markdown'), ('restructuredtext', 'Restructured Text')], default='markdown', max_length=30), + ), + ] diff --git a/downloads/models.py b/downloads/models.py index aa929855d..3217dec50 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -19,7 +19,7 @@ from .managers import ReleaseManager -DEFAULT_MARKUP_TYPE = getattr(settings, 'DEFAULT_MARKUP_TYPE', 'restructuredtext') +DEFAULT_MARKUP_TYPE = getattr(settings, 'DEFAULT_MARKUP_TYPE', 'markdown') class OS(ContentManageable, NameSlugModel): From 61f0c9a7eb80542cfbc551f1ddb41de08dfb4db2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Nov 2025 11:27:24 -0600 Subject: [PATCH 202/235] chore(deps): bump django from 4.2.25 to 4.2.26 (#2804) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index c0515c27f..bfd2dece1 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.25 +Django==4.2.26 docutils==0.21.2 Markdown==3.7 cmarkgfm==2024.11.20 From ba1d3fee64c281416543a8703fd2f659b6af309b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:53:37 +0200 Subject: [PATCH 203/235] Add featured downloads (#2805) --- downloads/views.py | 16 ++++++++- static/sass/style.css | 44 +++++++++++++++++++++++++ static/sass/style.scss | 40 ++++++++++++++++++++++ templates/downloads/release_detail.html | 19 ++++++++++- 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/downloads/views.py b/downloads/views.py index 21e66cd55..57196d622 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -2,7 +2,7 @@ from datetime import datetime -from django.db.models import Prefetch +from django.db.models import Case, IntegerField, Prefetch, When from django.urls import reverse from django.utils import timezone from django.views.generic import DetailView, TemplateView, ListView, RedirectView @@ -157,6 +157,20 @@ def get_object(self): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + # Add featured files (files with download_button=True) + # Order: macOS first, Windows second, Source last + context['featured_files'] = self.object.files.filter( + download_button=True + ).annotate( + os_order=Case( + When(os__slug='macos', then=1), + When(os__slug='windows', then=2), + When(os__slug='source', then=3), + default=4, + output_field=IntegerField(), + ) + ).order_by('os_order') + # Manually add release files for better ordering context['release_files'] = [] diff --git a/static/sass/style.css b/static/sass/style.css index 09c849482..b66cc9de4 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -2113,6 +2113,50 @@ table tfoot { .download-widget p:last-child a { white-space: nowrap; } +.featured-downloads-list { + display: flex; + flex-wrap: wrap; + gap: 1.5em; + justify-content: center; + margin-bottom: 2em; } + +.featured-download-box { + background-color: #f2f4f6; + border: 1px solid #caccce; + border-radius: 5px; + display: flex; + flex: 1 1 300px; + flex-direction: column; + min-width: 250px; + max-width: 400px; + padding: 1.25em; } + .featured-download-box h3 { + margin-top: 0; } + .featured-download-box .button { + background-color: #ffd343; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFDF76', endColorstr='#FFFFD343'); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffdf76), color-stop(90%, #ffd343)); + background-image: -webkit-linear-gradient(#ffdf76 10%, #ffd343 90%); + background-image: -moz-linear-gradient(#ffdf76 10%, #ffd343 90%); + background-image: -o-linear-gradient(#ffdf76 10%, #ffd343 90%); + background-image: linear-gradient(#ffdf76 10%, #ffd343 90%); + border: 1px solid #dca900; + white-space: normal; } + .featured-download-box .button:hover, .featured-download-box .button:active { + background-color: inherit; + background-color: #ffd343; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFEBA9', endColorstr='#FFFFD343'); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(10%, #ffeba9), color-stop(90%, #ffd343)); + background-image: -webkit-linear-gradient(#ffeba9 10%, #ffd343 90%); + background-image: -moz-linear-gradient(#ffeba9 10%, #ffd343 90%); + background-image: -o-linear-gradient(#ffeba9 10%, #ffd343 90%); + background-image: linear-gradient(#ffeba9 10%, #ffd343 90%); } + .featured-download-box .download-buttons { + margin-bottom: 0; + text-align: center; } + .time-posted { display: block; font-size: 0.875em; diff --git a/static/sass/style.scss b/static/sass/style.scss index cb78d9a4d..174a73374 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -1098,6 +1098,46 @@ $colors: $blue, $psf, $yellow, $green, $purple, $red; p:last-child a { white-space: nowrap; } } +.featured-downloads-list { + display: flex; + flex-wrap: wrap; + gap: 1.5em; + justify-content: center; + margin-bottom: 2em; +} + +.featured-download-box { + background-color: $grey-lighterest; + border: 1px solid $default-border-color; + border-radius: 5px; + display: flex; + flex: 1 1 300px; + flex-direction: column; + min-width: 250px; + max-width: 400px; + padding: 1.25em; + + h3 { + margin-top: 0; + } + + .button { + @include vertical-gradient( lighten($yellow, 10%), $yellow ); + border: 1px solid darken($yellow, 20%); + white-space: normal; + + &:hover, &:active { + background-color: inherit; + @include vertical-gradient( lighten($yellow, 20%), $yellow ); + } + } + + .download-buttons { + margin-bottom: 0; + text-align: center; + } +} + .documentation-widget { } .jobs-widget { } diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index db49d974e..5959dfe30 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -41,9 +41,26 @@ <h1 class="page-title">{{ release.name }}</h1> {% endif %} <header class="article-header"> - <h1 class="page-title">Files</h1> + <h2 class="page-title">Files</h2> </header> + {% if featured_files %} + <div class="featured-downloads-list"> + {% for f in featured_files %} + <div class="featured-download-box"> + <h3>{{ f.os.name }}</h3> + <p class="download-buttons"> + {% if f.os.slug == 'windows' and latest_pymanager and release.is_version_at_least_3_5 %} + <a class="button" href="https://www.python.org/downloads/latest/pymanager/">Download Python install manager</a> + {% else %} + <a class="button" href="{{ f.url }}">Download {{ f.name }}</a> + {% endif %} + </p> + </div> + {% endfor %} + </div> + {% endif %} + <table> <thead> <tr> From a543b5c4394c286f1e18b8d0438c5a0f36a562cc Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 12 Nov 2025 22:21:25 +0200 Subject: [PATCH 204/235] Point donate button to donate.python.org (#2808) --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index 527baf616..e0b692407 100644 --- a/templates/base.html +++ b/templates/base.html @@ -196,7 +196,7 @@ <h1 class="site-headline"> </h1> <div class="options-bar-container do-not-print"> - <a href="https://psfmember.org/civicrm/contribute/transact?reset=1&id=2" class="donate-button">Donate</a> + <a href="https://donate.python.org/" class="donate-button">Donate</a> <div class="options-bar"> {# Its a little ugly, but no space between elements makes the inline-block style work better #} <a id="site-map-link" class="jump-to-menu" href="#site-map"><span class="menu-icon">≡</span> Menu</a><form class="search-the-site" action="/search/" method="get"> From ea671dbbafcede8720b81b8ff8f2d4a6d2039493 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Sat, 15 Nov 2025 20:53:02 +0000 Subject: [PATCH 205/235] Update URLs in sitetree_menus.json (#2810) --- fixtures/sitetree_menus.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fixtures/sitetree_menus.json b/fixtures/sitetree_menus.json index 70de29110..69b9b34af 100644 --- a/fixtures/sitetree_menus.json +++ b/fixtures/sitetree_menus.json @@ -637,7 +637,7 @@ "fields": { "title": "FAQ", "hint": "", - "url": "https://docs.python.org/faq/", + "url": "https://docs.python.org/3/faq/", "urlaspattern": false, "tree": 1, "hidden": false, @@ -661,7 +661,7 @@ "fields": { "title": "Non-English Docs", "hint": "", - "url": "https://python-docs-translations.github.io/dashboard/", + "url": "https://translations.python.org", "urlaspattern": false, "tree": 1, "hidden": false, From 568f643a29796ab4d4e2e53554fce7f2db8ddde6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 08:11:13 -0600 Subject: [PATCH 206/235] chore(deps): bump actions/checkout from 5 to 6 in the github-actions group (#2815) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/static.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23c5ad626..6988c370e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: Check out repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Install platform dependencies run: | sudo apt -y update diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 7941021ca..9c06ff4a9 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version-file: '.python-version' From c589e2ff490cbf9bb28c68f7d8539a0f112e8edf Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 21 Nov 2025 20:13:53 +0200 Subject: [PATCH 207/235] Redirect `downloads/latest/python3.x` for given 3.x (#2816) --- downloads/managers.py | 29 ++++++++++------------------- downloads/models.py | 6 ++++++ downloads/urls.py | 1 + downloads/views.py | 21 +++++++++++++++++++++ static/sass/_layout.scss | 8 +++++--- static/sass/mq.css | 10 +++++++--- static/sass/no-mq.css | 10 +++++++--- 7 files changed, 57 insertions(+), 28 deletions(-) diff --git a/downloads/managers.py b/downloads/managers.py index 56040d2bb..22da0cdd0 100644 --- a/downloads/managers.py +++ b/downloads/managers.py @@ -29,8 +29,11 @@ def pymanager(self): def latest_python2(self): return self.python2().filter(is_latest=True) - def latest_python3(self): - return self.python3().filter(is_latest=True) + def latest_python3(self, minor_version: int | None = None): + if minor_version is None: + return self.python3().filter(is_latest=True) + pattern = rf"^Python 3\.{minor_version}\." + return self.python3().filter(name__regex=pattern).order_by("-release_date") def latest_pymanager(self): return self.pymanager().filter(is_latest=True) @@ -44,22 +47,10 @@ def released(self): class ReleaseManager(Manager.from_queryset(ReleaseQuerySet)): def latest_python2(self): - qs = self.get_queryset().latest_python2() - if qs: - return qs[0] - else: - return None - - def latest_python3(self): - qs = self.get_queryset().latest_python3() - if qs: - return qs[0] - else: - return None + return self.get_queryset().latest_python2().first() + + def latest_python3(self, minor_version: int | None = None): + return self.get_queryset().latest_python3(minor_version).first() def latest_pymanager(self): - qs = self.get_queryset().latest_pymanager() - if qs: - return qs[0] - else: - return None + return self.get_queryset().latest_pymanager().first() diff --git a/downloads/models.py b/downloads/models.py index 3217dec50..f37a041d0 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -292,6 +292,12 @@ def purge_fastly_download_pages(sender, instance, **kwargs): purge_url('/downloads/feed.rss') purge_url('/downloads/latest/python2/') purge_url('/downloads/latest/python3/') + # Purge minor version specific URLs (like /downloads/latest/python3.14/) + version = instance.get_version() + if instance.version == Release.PYTHON3 and version: + match = re.match(r'^3\.(\d+)', version) + if match: + purge_url(f'/downloads/latest/python3.{match.group(1)}/') purge_url('/downloads/latest/pymanager/') purge_url('/downloads/macos/') purge_url('/downloads/source/') diff --git a/downloads/urls.py b/downloads/urls.py index 5b6b3fda0..4b2d573bf 100644 --- a/downloads/urls.py +++ b/downloads/urls.py @@ -5,6 +5,7 @@ urlpatterns = [ re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'), re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), + re_path(r'latest/python3\.(?P<minor>\d+)/?$', views.DownloadLatestPython3x.as_view(), name='download_latest_python3x'), re_path(r'latest/pymanager/?$', views.DownloadLatestPyManager.as_view(), name='download_latest_pymanager'), re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'), diff --git a/downloads/views.py b/downloads/views.py index 57196d622..d19f0e868 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -45,6 +45,27 @@ def get_redirect_url(self, **kwargs): return reverse('download') +class DownloadLatestPython3x(RedirectView): + """ Redirect to latest Python 3.x release for a specific minor version """ + permanent = False + + def get_redirect_url(self, **kwargs): + minor_version = kwargs.get('minor') + if not minor_version: + return reverse('downloads:download') + + try: + minor_version_int = int(minor_version) + latest_release = Release.objects.latest_python3(minor_version_int) + except (ValueError, Release.DoesNotExist): + latest_release = None + + if latest_release: + return latest_release.get_absolute_url() + else: + return reverse('downloads:download') + + class DownloadLatestPyManager(RedirectView): """ Redirect to latest Python install manager release """ permanent = False diff --git a/static/sass/_layout.scss b/static/sass/_layout.scss index 884a0e9bc..3e256a6ac 100644 --- a/static/sass/_layout.scss +++ b/static/sass/_layout.scss @@ -449,6 +449,7 @@ .release-version, .release-status, + .release-dl, .release-start, .release-end, .release-pep { @@ -458,10 +459,11 @@ vertical-align: middle; } - .release-version { width: 15%; } + .release-version { width: 10%; } .release-status { width: 20%; } - .release-start { width: 25%; } - .release-end { width: 25%; } + .release-dl { width: 15%; } + .release-start { width: 20%; } + .release-end { width: 20%; } .release-pep { width: 15%; } /* Previous Next pattern */ diff --git a/static/sass/mq.css b/static/sass/mq.css index 4d4dea4ac..7c49abf44 100644 --- a/static/sass/mq.css +++ b/static/sass/mq.css @@ -1505,6 +1505,7 @@ html[xmlns] .slides { display: block; } .release-version, .release-status, + .release-dl, .release-start, .release-end, .release-pep { @@ -1514,16 +1515,19 @@ html[xmlns] .slides { display: block; } vertical-align: middle; } .release-version { - width: 15%; } + width: 10%; } .release-status { width: 20%; } + .release-dl { + width: 15%; } + .release-start { - width: 25%; } + width: 20%; } .release-end { - width: 25%; } + width: 20%; } .release-pep { width: 15%; } diff --git a/static/sass/no-mq.css b/static/sass/no-mq.css index 0565a60dd..f50d4140c 100644 --- a/static/sass/no-mq.css +++ b/static/sass/no-mq.css @@ -1219,6 +1219,7 @@ a.button { .release-version, .release-status, +.release-dl, .release-start, .release-end, .release-pep { @@ -1228,16 +1229,19 @@ a.button { vertical-align: middle; } .release-version { - width: 15%; } + width: 10%; } .release-status { width: 20%; } +.release-dl { + width: 15%; } + .release-start { - width: 25%; } + width: 20%; } .release-end { - width: 25%; } + width: 20%; } .release-pep { width: 15%; } From d19b30fe95a11c1fa4049f3f8e213d045ece1110 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 25 Nov 2025 03:48:35 +0200 Subject: [PATCH 208/235] Sort downloads table by version (#2822) --- downloads/tests/base.py | 30 ++++++++++++++++++++++++++---- downloads/tests/test_models.py | 8 ++++---- downloads/tests/test_views.py | 23 +++++++++++++++++++---- downloads/views.py | 11 ++++++++++- templates/downloads/index.html | 4 ++-- 5 files changed, 61 insertions(+), 15 deletions(-) diff --git a/downloads/tests/base.py b/downloads/tests/base.py index bcb7905c4..2b5e2c905 100644 --- a/downloads/tests/base.py +++ b/downloads/tests/base.py @@ -1,4 +1,4 @@ -import datetime +import datetime as dt from django.test import TestCase from django.utils import timezone @@ -32,7 +32,7 @@ def setUp(self): is_latest=True, is_published=True, release_page=self.release_275_page, - release_date=timezone.now() - datetime.timedelta(days=-1) + release_date=dt.datetime.fromisoformat("2013-05-15T00:00Z"), ) self.release_275_windows_32bit = ReleaseFile.objects.create( os=self.windows, @@ -102,9 +102,31 @@ def setUp(self): self.python_3 = Release.objects.create( version=Release.PYTHON3, - name='Python 3.10', + name="Python 3.10.19", is_latest=True, is_published=True, show_on_download_page=True, - release_page=self.release_275_page + release_page=self.release_275_page, + release_date=dt.datetime.fromisoformat("2025-10-09T00:00Z"), + ) + + self.python_3_10_18 = Release.objects.create( + version=Release.PYTHON3, + name="Python 3.10.18", + is_published=True, + release_date=dt.datetime.fromisoformat("2025-06-03T00:00Z"), + ) + + self.python_3_8_20 = Release.objects.create( + version=Release.PYTHON3, + name="Python 3.8.20", + is_published=True, + release_date=dt.datetime.fromisoformat("2024-09-06T00:00Z"), + ) + + self.python_3_8_19 = Release.objects.create( + version=Release.PYTHON3, + name="Python 3.8.19", + is_published=True, + release_date=dt.datetime.fromisoformat("2024-03-19T00:00Z"), ) diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index bd26c3b58..b89b2ecce 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -10,14 +10,14 @@ def test_stringification(self): def test_published(self): published_releases = Release.objects.published() - self.assertEqual(len(published_releases), 4) + self.assertEqual(len(published_releases), 7) self.assertIn(self.release_275, published_releases) self.assertIn(self.hidden_release, published_releases) self.assertNotIn(self.draft_release, published_releases) def test_release(self): released_versions = Release.objects.released() - self.assertEqual(len(released_versions), 3) + self.assertEqual(len(released_versions), 6) self.assertIn(self.release_275, released_versions) self.assertIn(self.hidden_release, released_versions) self.assertNotIn(self.draft_release, released_versions) @@ -37,7 +37,7 @@ def test_draft(self): def test_downloads(self): downloads = Release.objects.downloads() - self.assertEqual(len(downloads), 2) + self.assertEqual(len(downloads), 5) self.assertIn(self.release_275, downloads) self.assertNotIn(self.hidden_release, downloads) self.assertNotIn(self.draft_release, downloads) @@ -50,7 +50,7 @@ def test_python2(self): def test_python3(self): versions = Release.objects.python3() - self.assertEqual(len(versions), 3) + self.assertEqual(len(versions), 6) self.assertNotIn(self.release_275, versions) self.assertNotIn(self.draft_release, versions) self.assertIn(self.hidden_release, versions) diff --git a/downloads/tests/test_views.py b/downloads/tests/test_views.py index b559a2adc..c42572d13 100644 --- a/downloads/tests/test_views.py +++ b/downloads/tests/test_views.py @@ -56,6 +56,21 @@ def test_download(self): response = self.client.get(url) self.assertEqual(response.status_code, 200) + def test_download_releases_ordered_by_version(self): + url = reverse("download:download") + response = self.client.get(url) + releases = response.context["releases"] + self.assertEqual( + releases, + [ + self.python_3, + self.python_3_10_18, + self.python_3_8_20, + self.python_3_8_19, + self.release_275, + ], + ) + def test_latest_redirects(self): latest_python2 = Release.objects.released().python2().latest() url = reverse('download:download_latest_python2') @@ -218,13 +233,13 @@ def test_get_release(self): self.assertEqual(response.status_code, 200) content = self.get_json(response) # 'self.draft_release' won't shown here. - self.assertEqual(len(content), 4) + self.assertEqual(len(content), 7) # Login to get all releases. response = self.client.get(url, headers={"authorization": self.Authorization}) self.assertEqual(response.status_code, 200) content = self.get_json(response) - self.assertEqual(len(content), 5) + self.assertEqual(len(content), 8) self.assertFalse(content[0]['is_latest']) def test_post_release(self): @@ -594,5 +609,5 @@ def test_feed_item_count(self) -> None: response = self.client.get(self.url) content = response.content.decode() - # In BaseDownloadTests, we create 5 releases, 4 of which are published, 1 of those published are hidden.. - self.assertEqual(content.count("<item>"), 4) + # In BaseDownloadTests, we create 8 releases, 7 of which are published, 1 of those published are hidden.. + self.assertEqual(content.count("<item>"), 7) diff --git a/downloads/views.py b/downloads/views.py index d19f0e868..5d8da9461 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -124,8 +124,17 @@ def get_context_data(self, **kwargs): data['pymanager'] = latest_pymanager.download_file_for_os(o.slug) python_files.append(data) + def version_key(release: Release) -> tuple[int, ...]: + try: + return tuple(int(x) for x in release.get_version().split(".")) + except ValueError: + return (0,) + + releases = list(Release.objects.downloads()) + releases.sort(key=version_key, reverse=True) + context.update({ - 'releases': Release.objects.downloads(), + 'releases': releases, 'latest_python2': latest_python2, 'latest_python3': latest_python3, 'python_files': python_files, diff --git a/templates/downloads/index.html b/templates/downloads/index.html index f527be031..303fad87b 100644 --- a/templates/downloads/index.html +++ b/templates/downloads/index.html @@ -50,7 +50,7 @@ <h1 class="call-to-action">Download the latest version of Python</h1> <div class="row active-release-list-widget"> {% render_active_banner %} - <h2 class="widget-title">Active Python Releases</h2> + <h2 class="widget-title">Active Python releases</h2> <p class="success-quote"><a href="https://devguide.python.org/versions/#versions">For more information visit the Python Developer's Guide</a>.</p> {% box 'downloads-active-releases' %} @@ -74,7 +74,7 @@ <h2 class="widget-title">Looking for a specific release?</h2> <span class="release-number"><a href="{{ r.get_absolute_url }}">{{ r.name }}</a></span> <span class="release-date">{{ r.release_date|date }}</span> <span class="release-download"><a href="{{ r.get_absolute_url }}"><span aria-hidden="true" class="icon-download"></span> Download</a></span> - <span class="release-enhancements"><a href="{{ r.release_notes_url }}">Release Notes</a></span> + <span class="release-enhancements"><a href="{{ r.release_notes_url }}">Release notes</a></span> </li> {% endfor %} </ol> From a2b0d2d496350ee170b522f6ac74b8a9bec0e184 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:31:48 +0200 Subject: [PATCH 209/235] Add tests for download redirects and refactor DownloadLatestPython3 (#2821) --- downloads/tests/test_models.py | 18 ++++++++++++++++++ downloads/tests/test_views.py | 13 +++++++++++++ downloads/urls.py | 2 +- downloads/views.py | 25 +++---------------------- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index b89b2ecce..1c8e9ba47 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -1,3 +1,5 @@ +import datetime as dt + from ..models import Release, ReleaseFile from .base import BaseDownloadTests @@ -56,6 +58,22 @@ def test_python3(self): self.assertIn(self.hidden_release, versions) self.assertIn(self.pre_release, versions) + def test_latest_python3(self): + latest_3 = Release.objects.latest_python3() + self.assertEqual(latest_3, self.python_3) + self.assertNotEqual(latest_3, self.python_3_10_18) + + latest_3_10 = Release.objects.latest_python3(minor_version=10) + self.assertEqual(latest_3_10, self.python_3) + self.assertNotEqual(latest_3_10, self.python_3_10_18) + + latest_3_8 = Release.objects.latest_python3(minor_version=8) + self.assertEqual(latest_3_8, self.python_3_8_20) + self.assertNotEqual(latest_3_8, self.python_3_8_19) + + latest_3_99 = Release.objects.latest_python3(minor_version=99) + self.assertIsNone(latest_3_99) + def test_get_version(self): self.assertEqual(self.release_275.name, 'Python 2.7.5') self.assertEqual(self.release_275.get_version(), '2.7.5') diff --git a/downloads/tests/test_views.py b/downloads/tests/test_views.py index c42572d13..1fbb687d0 100644 --- a/downloads/tests/test_views.py +++ b/downloads/tests/test_views.py @@ -82,6 +82,19 @@ def test_latest_redirects(self): response = self.client.get(url) self.assertRedirects(response, latest_python3.get_absolute_url()) + def test_latest_python3x_redirects(self): + url = reverse("download:download_latest_python3x", kwargs={"minor": "10"}) + response = self.client.get(url) + self.assertRedirects(response, self.python_3.get_absolute_url()) + + url = reverse("download:download_latest_python3x", kwargs={"minor": "8"}) + response = self.client.get(url) + self.assertRedirects(response, self.python_3_8_20.get_absolute_url()) + + url = reverse("download:download_latest_python3x", kwargs={"minor": "99"}) + response = self.client.get(url) + self.assertRedirects(response, reverse("download:download")) + def test_redirect_page_object_to_release_detail_page(self): self.release_275.release_page = None self.release_275.save() diff --git a/downloads/urls.py b/downloads/urls.py index 4b2d573bf..75dcef211 100644 --- a/downloads/urls.py +++ b/downloads/urls.py @@ -5,7 +5,7 @@ urlpatterns = [ re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'), re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), - re_path(r'latest/python3\.(?P<minor>\d+)/?$', views.DownloadLatestPython3x.as_view(), name='download_latest_python3x'), + re_path(r'latest/python3\.(?P<minor>\d+)/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3x'), re_path(r'latest/pymanager/?$', views.DownloadLatestPyManager.as_view(), name='download_latest_pymanager'), re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'), diff --git a/downloads/views.py b/downloads/views.py index 5d8da9461..1d69a234c 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -30,40 +30,21 @@ def get_redirect_url(self, **kwargs): class DownloadLatestPython3(RedirectView): - """ Redirect to latest Python 3 release """ - permanent = False - - def get_redirect_url(self, **kwargs): - try: - latest_python3 = Release.objects.latest_python3() - except Release.DoesNotExist: - latest_python3 = None + """Redirect to latest Python 3 release, optionally for a specific minor""" - if latest_python3: - return latest_python3.get_absolute_url() - else: - return reverse('download') - - -class DownloadLatestPython3x(RedirectView): - """ Redirect to latest Python 3.x release for a specific minor version """ permanent = False def get_redirect_url(self, **kwargs): minor_version = kwargs.get('minor') - if not minor_version: - return reverse('downloads:download') - try: - minor_version_int = int(minor_version) + minor_version_int = int(minor_version) if minor_version else None latest_release = Release.objects.latest_python3(minor_version_int) except (ValueError, Release.DoesNotExist): latest_release = None if latest_release: return latest_release.get_absolute_url() - else: - return reverse('downloads:download') + return reverse("downloads:download") class DownloadLatestPyManager(RedirectView): From d846f8299bcc6b846061e90983efd78130a6f1b9 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:37:19 +0200 Subject: [PATCH 210/235] Add 'Python 3.X.YaN' placeholder for release name (#2819) --- downloads/admin.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/downloads/admin.py b/downloads/admin.py index d32f97b71..da5d94ad8 100644 --- a/downloads/admin.py +++ b/downloads/admin.py @@ -25,3 +25,9 @@ class ReleaseAdmin(ContentManageableModelAdmin): list_filter = ['version', 'is_published', 'show_on_download_page'] search_fields = ['name', 'slug'] ordering = ['-release_date'] + + def formfield_for_dbfield(self, db_field, request, **kwargs): + field = super().formfield_for_dbfield(db_field, request, **kwargs) + if db_field.name == "name": + field.widget.attrs["placeholder"] = "Python 3.X.YaN" + return field From e36232d712778ed181d89af83d0ef62bc20bdf4b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:42:35 +0200 Subject: [PATCH 211/235] Remove outdated PEPs code and docs (#2806) Co-authored-by: Jacob Coffee <jacob@z7x.org> --- .gitattributes | 1 - docs/source/commands.rst | 27 ----- docs/source/index.rst | 1 - docs/source/pep_generation.rst | 34 ------ env_sample | 4 - pydotorg/settings/cabotage.py | 3 - pydotorg/settings/local.py | 9 -- static/sass/_layout.scss | 48 --------- static/sass/mq.css | 59 ---------- static/sass/no-mq.css | 59 ---------- static/sass/style.css | 135 +---------------------- static/sass/style.scss | 160 ---------------------------- templates/pages/pep-page.html | 83 --------------- templates/peps/list.html | 106 ------------------ templates/python/documentation.html | 2 +- 15 files changed, 5 insertions(+), 726 deletions(-) delete mode 100644 docs/source/pep_generation.rst delete mode 100644 templates/pages/pep-page.html delete mode 100644 templates/peps/list.html diff --git a/.gitattributes b/.gitattributes index aab188762..6473b8dc5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ static/sass/*.css linguist-vendored -peps/tests/fake_pep_repo/*.html linguist-vendored static/js/libs/*.js linguist-vendored static/js/plugins/*.js linguist-vendored diff --git a/docs/source/commands.rst b/docs/source/commands.rst index baa94fa4f..06c1b8bff 100644 --- a/docs/source/commands.rst +++ b/docs/source/commands.rst @@ -35,30 +35,3 @@ Command-line options .. option:: --app-label <app_label> Create initial data with the *app_label* provided. - -.. _command-generate-pep-pages: - -generate_pep_pages ------------------- - -This command generates ``pages.Page`` objects from the output -of the existing PEP repository generation process. You run it like:: - - $ ./manage.py generate_pep_pages - -To get verbose output, specify ``--verbosity`` option:: - - $ ./manage.py generate_pep_pages --verbosity=2 - -It uses the conversion code in the ``peps/converters.py`` file, in an -attempt to normalize the formatting for display purposes. - -.. _command-dump-pep-pages: - -dump_pep_pages --------------- - -This command simply dumps our PEP related pages as JSON to :attr:`sys.stdout`. -You can run like:: - - $ ./manage.py dump_pep_pages diff --git a/docs/source/index.rst b/docs/source/index.rst index ab7b710ed..558604237 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -25,7 +25,6 @@ Contents: install.md contributing administration - pep_generation commands Indices and tables diff --git a/docs/source/pep_generation.rst b/docs/source/pep_generation.rst deleted file mode 100644 index dd68649af..000000000 --- a/docs/source/pep_generation.rst +++ /dev/null @@ -1,34 +0,0 @@ -PEP Page Generation -=================== - -.. _pep_process: - -Process Overview ----------------- - -We are generating the PEP pages by lightly parsing the HTML output from the -`PEP Repository`_ and then cleaning up some post-parsing formatting. - -The PEP Page Generation process is as follows: - -1. Clone the PEP Repository, if you have not already done so:: - - $ git clone https://github.com/python/peps.git - -2. From the cloned PEP Repository, run:: - - $ make -j - -3. Set ``PEP_REPO_PATH`` in ``pydotorg/settings/local.py`` to the location - of the cloned PEP Repository - -4. Generate PEP pages in your ``pythondotorg`` repository - (More details at :ref:`command-generate-pep-pages`). You can run like:: - - $ ./manage.py generate_pep_pages - -This process runs periodically via cron to keep the PEP pages up to date. - -See :ref:`management-commands` for all management commands. - -.. _PEP Repository: https://github.com/python/peps diff --git a/env_sample b/env_sample index 72c1e0b9a..499c155f8 100644 --- a/env_sample +++ b/env_sample @@ -2,9 +2,6 @@ DATABASE_URL=postgres:///pythondotorg SEARCHBOX_SSL_URL=http://127.0.0.1:9200/ -# development optional -#PEP_REPO_PATH=None - # production required SECRET_KEY= ALLOWED_HOSTS=127.0.0.1, @@ -13,7 +10,6 @@ EMAIL_HOST_USER= EMAIL_HOST_PASSWORD= EMAIL_PORT= DEFAULT_FROM_EMAIL= -PEP_ARTIFACT_URL= FASTLY_API_KEY= SENTRY_DSN= SOURCE_VERSION= diff --git a/pydotorg/settings/cabotage.py b/pydotorg/settings/cabotage.py index 654db889e..7d15fc18e 100644 --- a/pydotorg/settings/cabotage.py +++ b/pydotorg/settings/cabotage.py @@ -61,9 +61,6 @@ EMAIL_USE_TLS = True DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL') -PEP_REPO_PATH = None -PEP_ARTIFACT_URL = config('PEP_ARTIFACT_URL') - # Fastly API Key FASTLY_API_KEY = config('FASTLY_API_KEY') diff --git a/pydotorg/settings/local.py b/pydotorg/settings/local.py index 6525d9837..a8a4fdb09 100644 --- a/pydotorg/settings/local.py +++ b/pydotorg/settings/local.py @@ -34,15 +34,6 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -# Set the local pep repository path to fetch PEPs from, -# or none to fallback to the tarball specified by PEP_ARTIFACT_URL. -PEP_REPO_PATH = config('PEP_REPO_PATH', default=None) # directory path or None - -# Set the path to where to fetch PEP artifacts from. -# The value can be a local path or a remote URL. -# Ignored if PEP_REPO_PATH is set. -PEP_ARTIFACT_URL = os.path.join(BASE, 'peps/tests/peps.tar.gz') - # Use Dummy SASS compiler to avoid performance issues and remove the need to # have a sass compiler installed at all during local development if you aren't # adjusting the CSS at all. Comment this out or adjust it to suit your local diff --git a/static/sass/_layout.scss b/static/sass/_layout.scss index 3e256a6ac..3fbbb4c45 100644 --- a/static/sass/_layout.scss +++ b/static/sass/_layout.scss @@ -27,9 +27,6 @@ .container, .row, -.pep-list-header, -.pep-index-list li, -.info-key, .listing-company, .list-recent-jobs li { @extend %pie-clearfix; } @@ -377,43 +374,12 @@ .most-recent-posts { @include span-columns( 9 ); } - .pep-widget, .psf-widget, .python-needs-you-widget { padding: 1.5em 1.75em; clear: both; } - /* PEP landing page */ - .pep-list-header, - .pep-index-list li, - .info-key { margin: 0 -.5em; } - - .pep-list-header { display: block; } - - .pep-index-list { - - .label { display: none; } - a { display: block; } - li { - border-bottom: 1px solid darken($grey-lighterest, 5%); - margin-bottom: 0; - } - } - - .pep-type, - .pep-num, - .pep-title, - .pep-owner { - float: left; - border-bottom: 0; - } - - .pep-type { width: 15%; } - .pep-num { width: 10%; } - .pep-title { width: 50%; } - .pep-owner { width: 25%; } - /* Jobs landing page */ .jobs-intro { padding-top: 2em; padding-bottom: 2em; } @@ -1101,7 +1067,6 @@ } } - .pep-widget, .psf-widget, .python-needs-you-widget { padding: 1.5em 1.75em; @@ -1143,19 +1108,6 @@ } } - .pep-widget { - - .widget-title { - position: relative; - padding-right: 6em; - } - } - - .rss-link { - position: absolute; - top: 0; right: 0; - } - /* Footer */ .sitemap { diff --git a/static/sass/mq.css b/static/sass/mq.css index 7c49abf44..cdb3edee7 100644 --- a/static/sass/mq.css +++ b/static/sass/mq.css @@ -115,17 +115,11 @@ /* Other elements */ .container, .row, -.pep-list-header, -.pep-index-list li, -.info-key, .listing-company, .list-recent-jobs li { *zoom: 1; } .container:after, .row:after, - .pep-list-header:after, - .pep-index-list li:after, - .info-key:after, .listing-company:after, .list-recent-jobs li:after { content: ""; @@ -338,17 +332,11 @@ html[xmlns] .slides { display: block; } /* Other elements */ .container, .row, -.pep-list-header, -.pep-index-list li, -.info-key, .listing-company, .list-recent-jobs li { *zoom: 1; } .container:after, .row:after, - .pep-list-header:after, - .pep-index-list li:after, - .info-key:after, .listing-company:after, .list-recent-jobs li:after { content: ""; @@ -1423,48 +1411,11 @@ html[xmlns] .slides { display: block; } float: left; margin-right: 2.12766%; } - .pep-widget, .psf-widget, .python-needs-you-widget { padding: 1.5em 1.75em; clear: both; } - /* PEP landing page */ - .pep-list-header, - .pep-index-list li, - .info-key { - margin: 0 -.5em; } - - .pep-list-header { - display: block; } - - .pep-index-list .label { - display: none; } - .pep-index-list a { - display: block; } - .pep-index-list li { - border-bottom: 1px solid #e3e7ec; - margin-bottom: 0; } - - .pep-type, - .pep-num, - .pep-title, - .pep-owner { - float: left; - border-bottom: 0; } - - .pep-type { - width: 15%; } - - .pep-num { - width: 10%; } - - .pep-title { - width: 50%; } - - .pep-owner { - width: 25%; } - /* Jobs landing page */ .jobs-intro { padding-top: 2em; @@ -2302,7 +2253,6 @@ html[xmlns] .slides { display: block; } display: inline; visibility: visible; } - .pep-widget, .psf-widget, .python-needs-you-widget { padding: 1.5em 1.75em; } @@ -2349,15 +2299,6 @@ html[xmlns] .slides { display: block; } zoom: 1; display: inline; } - .pep-widget .widget-title { - position: relative; - padding-right: 6em; } - - .rss-link { - position: absolute; - top: 0; - right: 0; } - /* Footer */ .sitemap a { text-align: left; } diff --git a/static/sass/no-mq.css b/static/sass/no-mq.css index f50d4140c..52be49bef 100644 --- a/static/sass/no-mq.css +++ b/static/sass/no-mq.css @@ -115,17 +115,11 @@ /* Other elements */ .container, .row, -.pep-list-header, -.pep-index-list li, -.info-key, .listing-company, .list-recent-jobs li { *zoom: 1; } .container:after, .row:after, - .pep-list-header:after, - .pep-index-list li:after, - .info-key:after, .listing-company:after, .list-recent-jobs li:after { content: ""; @@ -338,17 +332,11 @@ html[xmlns] .slides { display: block; } /* Other elements */ .container, .row, -.pep-list-header, -.pep-index-list li, -.info-key, .listing-company, .list-recent-jobs li { *zoom: 1; } .container:after, .row:after, - .pep-list-header:after, - .pep-index-list li:after, - .info-key:after, .listing-company:after, .list-recent-jobs li:after { content: ""; @@ -1137,48 +1125,11 @@ a.button { float: left; margin-right: 2.12766%; } -.pep-widget, .psf-widget, .python-needs-you-widget { padding: 1.5em 1.75em; clear: both; } -/* PEP landing page */ -.pep-list-header, -.pep-index-list li, -.info-key { - margin: 0 -.5em; } - -.pep-list-header { - display: block; } - -.pep-index-list .label { - display: none; } -.pep-index-list a { - display: block; } -.pep-index-list li { - border-bottom: 1px solid #e3e7ec; - margin-bottom: 0; } - -.pep-type, -.pep-num, -.pep-title, -.pep-owner { - float: left; - border-bottom: 0; } - -.pep-type { - width: 15%; } - -.pep-num { - width: 10%; } - -.pep-title { - width: 50%; } - -.pep-owner { - width: 25%; } - /* Jobs landing page */ .jobs-intro { padding-top: 2em; @@ -1990,7 +1941,6 @@ a.button { display: inline; visibility: visible; } -.pep-widget, .psf-widget, .python-needs-you-widget { padding: 1.5em 1.75em; } @@ -2037,15 +1987,6 @@ a.button { zoom: 1; display: inline; } -.pep-widget .widget-title { - position: relative; - padding-right: 6em; } - -.rss-link { - position: absolute; - top: 0; - right: 0; } - /* Footer */ .sitemap a { text-align: left; } diff --git a/static/sass/style.css b/static/sass/style.css index b66cc9de4..894cd6214 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -133,7 +133,7 @@ display: table; clear: both; } -.pep-widget, .most-recent-events .more-by-location, .user-profile-controls div.section-links ul li, .more-by-location { +.most-recent-events .more-by-location, .user-profile-controls div.section-links ul li, .more-by-location { background-color: #d8dbde; *zoom: 1; filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFE6E8EA', endColorstr='#FFD8DBDE'); @@ -146,12 +146,12 @@ -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); } -.pep-widget, .most-recent-events .more-by-location, .user-profile-controls div.section-links ul li { +.most-recent-events .more-by-location, .user-profile-controls div.section-links ul li { border: 1px solid #caccce; margin-bottom: 0.5em; padding: 1.25em; *zoom: 1; } - .pep-widget:after, .most-recent-events .more-by-location:after, .user-profile-controls div.section-links ul li:after { + .most-recent-events .more-by-location:after, .user-profile-controls div.section-links ul li:after { content: ""; display: table; clear: both; } @@ -973,7 +973,7 @@ h2.not-column { /* ! ===== HELPFUL CLASSES ===== */ /* A useful class that helps control how lines might break. Use carefully and always test. */ -.pre, .rss-link { +.pre { white-space: nowrap; } /* Our own little class for progressive text. Yes, it is a Monty Python reference */ @@ -2264,133 +2264,6 @@ table tfoot { color: #b55863; font-family: SourceSansProBold, Arial, sans-serif; } -/* ! ===== PEP Widget ===== */ -.pep-widget { - margin-bottom: 1.3125em; } - .pep-widget .widget-title { - color: #737373; - margin-bottom: 0.35em; - font-size: 1.125em; } - .fontface .pep-widget .widget-title { - font-size: 1.29375em; } - .fontface .pep-widget .widget-title span:before { - font-size: .875em; } - .pep-widget .widget-title a { - color: #3776ab; } - .pep-widget .widget-title a:hover, .pep-widget .widget-title a:active { - color: #1f3b47; } - .pep-widget .pep-number { - color: #666666; - font-family: SourceSansProBold, Arial, sans-serif; - display: inline-block; - width: 3em; } - -.pep-list { - border-top: 1px solid #caccce; - line-height: 1.2em; - margin: 0; } - .pep-list li { - display: block; - line-height: 1.35em; } - .pep-list li a { - display: block; - color: #3776ab; - background-color: #f2f4f6; - border-bottom: 1px solid #e6eaee; - padding: .6em .75em .5em; } - .pep-list li a:hover, .pep-list li a:focus, .pep-list li a:active { - color: #222222; - background-color: #fefefe; } - -.rss-link { - line-height: 1em; } - .rss-link span:before { - color: #cc9547; } - -/* ! ===== PEP landing page ===== */ -/*<div class="pep-list-header list-row-headings"> - <span class="pep-type">Type</span> - <span class="pep-num">Number</span> - <span class="pep-title">Title <span class="say-no-more">(click for more)</span></span> - <span class="pep-owner">Owner</span> -</div> -<ul class="pep-index-list menu"> - <li> - <div class="pep-type"><span class="label">Type</span>info-act</div> - <div class="pep-num"><span class="label">Number</span><a href="http://hg.python.org/peps/file/tip/pep-0020.txt">20</a></div> - <div class="pep-title"><span class="label">Title</span><a href="http://hg.python.org/peps/file/tip/pep-0020.txt">The Zen of Python</a></div> - <div class="pep-owner"><span class="label">Owner</span>Tim Peters</div> - </li> -</ul>*/ -.pep-list-header { - font-family: SourceSansProBold, Arial, sans-serif; - display: none; } - -.pep-index-list { - margin-bottom: 2.625em; } - .pep-index-list .label { - font-family: SourceSansProBold, Arial, sans-serif; - display: inline-block; - width: 20%; } - .pep-index-list li { - background-color: #f2f4f6; - border-bottom: 1px solid #caccce; } - .pep-index-list a { - display: inline-block; - color: #3776ab; } - .pep-index-list a:hover, .pep-index-list a:focus, .pep-index-list a:active { - color: #222222; } - -.pep-type, .pep-num, .pep-title, .pep-owner { - padding: .5em .5em .4em; - border-bottom: 1px solid #e3e7ec; } - -.footnote .label { - width: 4em; } - -/*dl*/ -.info-key dt, .info-key dd { - display: block; - float: left; - padding: .5em .5em .4em; } -.info-key dt { - width: 25%; } -.info-key dd { - width: 75%; - border-bottom: 1px solid #e6e8ea; } - -/* <div class="pep-owner-header"> - <div class="label">Name</div> - <div class="label">Email Address</div> - </div> - <ul class="pep-owner-list menu"> - <li> - <div class="owner-name">Tim Peters</div> - <div class="owner-email">tim at zope.com</div> - </li> - </ul> */ -.pep-owner-header { - margin: 0 -.5em; - overflow: hidden; - *zoom: 1; } - .pep-owner-header .label { - font-family: SourceSansProBold, Arial, sans-serif; - float: left; - width: 50%; - padding: .25em .5em .2em; } - -.pep-owner-list li { - background-color: #f2f4f6; - border-bottom: 1px solid #caccce; - overflow: hidden; - *zoom: 1; } - .pep-owner-list li:hover { - background-color: #fefefe; } -.pep-owner-list .owner-name, .pep-owner-list .owner-email { - float: left; - width: 50%; - padding: .5em .5em .4em; } - /* ! ===== Success Stories landing page ===== */ .featured-success-story { padding: 1.3125em 0; diff --git a/static/sass/style.scss b/static/sass/style.scss index 174a73374..5988b00d1 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -1265,166 +1265,6 @@ $colors: $blue, $psf, $yellow, $green, $purple, $red; .draft-preview { color: $red; font-family: $default-font-bold; } -/* ! ===== PEP Widget ===== */ -.pep-widget { - @extend %grey-colorbox; - margin-bottom: rhythm( .75 ); - - .widget-title { - color: lighten($grey, 5%); - margin-bottom: 0.35em; - @include fontface-adjust( 18px ); - - a { - color: $blue; - - &:hover, &:active { color: $darkblue; } - } - } - - .pep-number { - color: $grey; - font-family: $default-font-bold; - display: inline-block; - width: 3em; - } -} - - .pep-list { - border-top: 1px solid $default-border-color; - line-height: 1.2em; - margin: 0; - - li { - display: block; - line-height: 1.35em; - - a { - display: block; - color: $blue; - background-color: $grey-lighterest; - border-bottom: 1px solid darken($grey-lighterest, 4%); - padding: .6em .75em .5em; - - &:hover, &:focus, &:active { - color: $grey-darker; - background-color: lighten($grey-lighterest, 4%); - } - } - } - } - -.rss-link { - @extend .pre; - line-height: 1em; - - span:before { color: $orange; } -} - -/* ! ===== PEP landing page ===== */ - /*<div class="pep-list-header list-row-headings"> - <span class="pep-type">Type</span> - <span class="pep-num">Number</span> - <span class="pep-title">Title <span class="say-no-more">(click for more)</span></span> - <span class="pep-owner">Owner</span> - </div> - <ul class="pep-index-list menu"> - <li> - <div class="pep-type"><span class="label">Type</span>info-act</div> - <div class="pep-num"><span class="label">Number</span><a href="http://hg.python.org/peps/file/tip/pep-0020.txt">20</a></div> - <div class="pep-title"><span class="label">Title</span><a href="http://hg.python.org/peps/file/tip/pep-0020.txt">The Zen of Python</a></div> - <div class="pep-owner"><span class="label">Owner</span>Tim Peters</div> - </li> - </ul>*/ -.pep-list-header, .pep-index-list li { } - -.pep-list-header { - font-family: $default-font-bold; - display: none; -} - -.pep-index-list { - margin-bottom: rhythm( 1.5 ); - - .label { - font-family: $default-font-bold; - display: inline-block; - width: 20%; - } - - li { - background-color: $grey-lighterest; - border-bottom: 1px solid $grey-lighter; - } - - a { - display: inline-block; - color: $blue; - - &:hover, &:focus, &:active { color: $grey-darker; } - } -} - -.pep-type, .pep-num, .pep-title, .pep-owner { - padding: .5em .5em .4em; - border-bottom: 1px solid darken($grey-lighterest, 5%); -} - -.footnote .label { - width: 4em; -} - -/*dl*/ .info-key { - - dt, dd { - display: block; - float: left; - padding: .5em .5em .4em; - } - - dt { width: 25%; } - dd { width: 75%; border-bottom: 1px solid $grey-lightest; } -} - -/* <div class="pep-owner-header"> - <div class="label">Name</div> - <div class="label">Email Address</div> - </div> - <ul class="pep-owner-list menu"> - <li> - <div class="owner-name">Tim Peters</div> - <div class="owner-email">tim at zope.com</div> - </li> - </ul> */ -.pep-owner-header { - margin: 0 -.5em; - @include clearfix(); - - .label { - font-family: $default-font-bold; - float: left; - width: 50%; - padding: .25em .5em .2em; - } -} -.pep-owner-list { - - li { - background-color: $grey-lighterest; - border-bottom: 1px solid $grey-lighter; - @include clearfix(); - - &:hover { background-color: lighten($grey-lighterest, 4%); } - } - - .owner-name, .owner-email { - float: left; - width: 50%; - padding: .5em .5em .4em; - } -} - - /* ! ===== Success Stories landing page ===== */ .featured-success-story { padding: rhythm( .75 ) 0; diff --git a/templates/pages/pep-page.html b/templates/pages/pep-page.html deleted file mode 100644 index 4b804df50..000000000 --- a/templates/pages/pep-page.html +++ /dev/null @@ -1,83 +0,0 @@ -{% extends "base.html" %} -{% load boxes %} -{% load sitetree %} - -{% block body_attributes %}class="python pages pep-page"{% endblock %} - -{% block content_attributes %}with-left-sidebar{% endblock %} - -{% block page_title %}{{ page.title }} | {{ SITE_INFO.site_name }}{% endblock %} -{% block og_title %}{{ page.title }}{% endblock %} - -{% block breadcrumbs %} -<ul class="breadcrumbs menu"> - <li> - <a href="/" title="The Python Programming Language">Python</a><span class="prompt">>>></span> - </li> - <li> - <a href="/dev/">Python Developer's Guide</a><span class="prompt">>>></span> - </li> - <li> - <a href="/dev/peps/">PEP Index</a><span class="prompt">>>></span> - </li> - <li>{{ page.title }}</li> -</ul> -{% endblock %} -. -{% block content %} -<style> - .pep-page pre { - padding: .5em; - background: inherit; - border-left: 0px; - -webkit-box-shadow: 0 0 0 0; - -moz-box-shadow: 0 0 0 0; - box-shadow: 0 0 0 0; - } - .pep-page pre.literal-block { - background-color: #e6e8ea; - border: 1px solid #ddd; - padding: 1em; - -webkit-box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); - -moz-box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); - box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); - } -</style> - - {% if not page.is_published %} - <div class="user-feedback level-notice"> - <p role="alert">This page is a draft and it hasn't been published yet. Only staff users can see it.</p> - </div> - {% endif %} - <article class="text"> - {% if request.user.is_staff %} - <a role="button" class="button" href="{% url 'admin:pages_page_change' page.pk %}">Edit this page</a> - {% endif %} - - <header class="article-header"> - <h1 class="page-title">{{ page.title }}</h1> - </header> - - {{ page.content }} - - </article> -{% endblock content %} - - -{% block left_sidebar %} -{% comment %} -TODO: should this partially come from sitetree? -{% endcomment %} - -<aside class="left-sidebar" role="secondary"> - - {% include "components/navigation-widget.html" %} - - <div class="psf-sidebar-widget sidebar-widget"> - {% box 'widget-sidebar-aboutpsf' %} - - </div> - -</aside> - -{% endblock left_sidebar %} diff --git a/templates/peps/list.html b/templates/peps/list.html deleted file mode 100644 index 597bf4c09..000000000 --- a/templates/peps/list.html +++ /dev/null @@ -1,106 +0,0 @@ -{% extends "base.html" %} - -{% block page_title %}Our Enhancement Proposals | {{ SITE_INFO.site_name }}{% endblock %} - -{% block body_attributes %}class="python pep-index default-page"{% endblock %} - -{% block content %} - - <article> - <h1>Index of Python Enhancement Proposals</h1> - - {% for cat in categories %} - - {% if cat.peps.all|length > 0 %} - <h2>{{ cat.name }}</h2> - - <div class="pep-list-header"> - <div class="pep-type">Type/Status</div> - <div class="pep-num">Number</div> - <div class="pep-title">Title <span class="say-no-more">(click for more)</span></div> - <div class="pep-owner">Owner</div> - </div> - <ul class="pep-index-list menu"> - {% for pep in cat.peps.all %} - <li> - <div class="pep-type"><span class="label">Type/Status</span>{{ pep.type.abbreviation }}{% if pep.status.abbreviation %}/{{ pep.status.abbreviation }}{% endif %}</div> - <div class="pep-num"><span class="label">Number</span><a href="{{ pep.url }}">{{ pep.number }}</a></div> - <div class="pep-title"><span class="label">Title</span><a href="{{ pep.url }}">{{ pep.title }}</a></div> - <div class="pep-owner"><span class="label">Owner</span>{{ pep.get_owner_names }}</div> - </li> - {% endfor %} - </ul> - {% endif %} - - {% endfor %} - - <h2>Numerical List</h2> - - <div class="pep-list-header"> - <div class="pep-type">Type/Status</div> - <div class="pep-num">Number</div> - <div class="pep-title">Title <span class="say-no-more">(click for more)</span></div> - <div class="pep-owner">Owner</div> - </div> - <ul class="pep-index-list menu"> - {% for pep in peps %} - <li> - <div class="pep-type"><span class="label">Type/Status</span>{{ pep.type.abbreviation }}{% if pep.status.abbreviation %}/{{ pep.status.abbreviation }}{% endif %}</div> - <div class="pep-num"><span class="label">Number</span><a href="{{ pep.url }}">{{ pep.number }}</a></div> - <div class="pep-title"><span class="label">Title</span><a href="{{ pep.url }}">{{ pep.title }}</a></div> - <div class="pep-owner"><span class="label">Owner</span>{{ pep.get_owner_names }}</div> - </li> - {% endfor %} - </ul> - - - <div class="col-row four-col"> - - <div class="column double-col"> - - <h2>Key</h2> - - <div class="col-row two-col"> - <div class="column"> - <h5>Types</h5> - <dl class="info-key"> - {% for t in types %} - <dt>{{ t.abbreviation }}</dt> - <dd>{{ t.name }}</dd> - {% endfor %} - </dl> - </div> - - <div class="column"> - <h5>Statuses</h5> - <dl class="info-key"> - {% for s in statuses %} - <dt>{{ s.abbreviation }}</dt> - <dd>{{ s.name }}</dd> - {% endfor %} - </dl> - </div> - </div> - - </div> - <div class="column double-col"> - - <h2>Owners</h2> - <div class="pep-owner-header"> - <div class="label">Name</div> - <div class="label">Email Address</div> - </div> - <ul class="pep-owner-list menu"> - {% for o in owners %} - <li> - <div class="owner-name">{{ o.name }}</div> - <div class="owner-email">{{ o.email_display }}</div> - </li> - {% endfor %} - </ul> - - </div> - </div><!-- end .four-col --> - - </article> -{% endblock %} \ No newline at end of file diff --git a/templates/python/documentation.html b/templates/python/documentation.html index e301b0010..a87de21d0 100644 --- a/templates/python/documentation.html +++ b/templates/python/documentation.html @@ -80,7 +80,7 @@ <h2 class="widget-title"><span aria-hidden="true" class="icon-versions"></span>P <h2 class="widget-title"><span aria-hidden="true" class="icon-versions"></span>Porting from Python 2 to Python 3</h2> <ul> <li><a href="https://www.python.org/doc/sunset-python-2/">FAQ: Sunsetting Python 2</a></li> - <li><a href="https://www.python.org/dev/peps/pep-0373/">Final Python 2.7 Release Schedule</a></li> + <li><a href="https://peps.python.org/pep-0373/">Final Python 2.7 Release Schedule</a></li> <li><a href="https://python3statement.github.io/">Python 3 Statement</a></li> <li> <a href="https://docs.python.org/3/howto/pyporting.html">Porting Python 2 Code to Python 3</a> From 578c62454a653abf7d665d5f4427cbe5827c6144 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 25 Nov 2025 23:15:29 +0200 Subject: [PATCH 212/235] Generate page of docs by version (#2813) --- pydotorg/urls.py | 1 + pydotorg/views.py | 114 +++++++++++++++++++++++++++++++++ templates/python/versions.html | 58 +++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 templates/python/versions.html diff --git a/pydotorg/urls.py b/pydotorg/urls.py index 8a70d5790..bd5496fb6 100644 --- a/pydotorg/urls.py +++ b/pydotorg/urls.py @@ -32,6 +32,7 @@ path('getit/', include('downloads.urls', namespace='getit')), path('downloads/', include('downloads.urls', namespace='download')), path('doc/', views.DocumentationIndexView.as_view(), name='documentation'), + path('doc/versions2/', views.DocsByVersionView.as_view(), name='docs-versions'), path('blogs/', include('blogs.urls')), path('inner/', TemplateView.as_view(template_name="python/inner.html"), name='inner'), diff --git a/pydotorg/views.py b/pydotorg/views.py index bbc30ec51..8d1bf7f05 100644 --- a/pydotorg/views.py +++ b/pydotorg/views.py @@ -1,5 +1,9 @@ +import datetime as dt import json import os +import re +from collections import defaultdict + from django.conf import settings from django.http import HttpResponse, JsonResponse from django.views.generic.base import RedirectView, TemplateView @@ -67,3 +71,113 @@ def get_redirect_url(self, *args, **kwargs): settings.AWS_STORAGE_BUCKET_NAME, image_path, ]) + + +class DocsByVersionView(TemplateView): + template_name = "python/versions.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + releases = Release.objects.filter( + is_published=True, + pre_release=False, + ).order_by("-release_date") + + # Some releases have no documentation + no_docs = {"2.3.6", "2.3.7", "2.4.5", "2.4.6", "2.5.5", "2.5.6"} + + # We'll group releases by major.minor version + version_groups = defaultdict(list) + + for release in releases: + # Extract version number from name ("Python 3.14.0" -> "3.14.0") + version_match = re.match(r"Python ([\d.]+)", release.name) + if version_match: + full_version = version_match.group(1) + + if full_version in no_docs: + continue + + # Get major.minor version ("3.14.0" -> "3.14") + version_parts = full_version.split(".") + major_minor = f"{version_parts[0]}.{version_parts[1]}" + + # For 3.2.0 and earlier, use X.Y instead of X.Y.0 + if len(version_parts) == 3: + major, minor, patch = map(int, version_parts) + # For versions <= 3.2.0 where patch is 0 + if (major, minor, patch) <= (3, 2, 0) and patch == 0: + full_version = major_minor + + release_data = { + "stage": full_version, + "date": release.release_date.replace(tzinfo=None), + } + version_groups[major_minor].append(release_data) + + # Add legacy releases not in the database + legacy_releases_data = { + "2.2": [ + {"stage": "2.2p1", "date": dt.datetime(2002, 3, 29)}, + ], + "2.1": [ + {"stage": "2.1.2", "date": dt.datetime(2002, 1, 16)}, + {"stage": "2.1.1", "date": dt.datetime(2001, 7, 20)}, + {"stage": "2.1", "date": dt.datetime(2001, 4, 15)}, + ], + "2.0": [ + {"stage": "2.0", "date": dt.datetime(2000, 10, 16)}, + ], + "1.6": [ + {"stage": "1.6", "date": dt.datetime(2000, 9, 5)}, + ], + "1.5": [ + {"stage": "1.5.2p2", "date": dt.datetime(2000, 3, 22)}, + {"stage": "1.5.2p1", "date": dt.datetime(1999, 7, 6)}, + {"stage": "1.5.2", "date": dt.datetime(1999, 4, 30)}, + {"stage": "1.5.1p1", "date": dt.datetime(1998, 8, 6)}, + {"stage": "1.5.1", "date": dt.datetime(1998, 4, 14)}, + {"stage": "1.5", "date": dt.datetime(1998, 2, 17)}, + ], + "1.4": [ + {"stage": "1.4", "date": dt.datetime(1996, 10, 25)}, + ], + } + + # Merge legacy releases in + for version, items in legacy_releases_data.items(): + version_groups[version].extend(items) + + # Convert to list for template and sort releases within each version + version_list = [] + for version, releases in version_groups.items(): + # Sort x.y.z newest first + releases = sorted( + releases, + key=lambda x: x.get("date", dt.datetime.min), + reverse=True, + ) + for release in releases: + release["date"] = release["date"].strftime("%-d %B %Y") + + version_list.append( + { + "version": version, + "releases": releases, + } + ) + + # Sort x.y versions (newest first) + version_list.sort( + key=lambda x: [ + int(n) if n.isdigit() else n for n in x["version"].split(".") + ], + reverse=True, + ) + + context.update({ + "version_list": version_list, + }) + + return context diff --git a/templates/python/versions.html b/templates/python/versions.html new file mode 100644 index 000000000..ab9c6a222 --- /dev/null +++ b/templates/python/versions.html @@ -0,0 +1,58 @@ +{% extends "base.html" %} +{% load boxes %} +{% load sitetree %} + +{% block page_title %}Python documentation by version | {{ SITE_INFO.site_name }}{% endblock %} + +{% block body_attributes %}class="python pages default-page"{% endblock %} + +{% block breadcrumbs %} +{% sitetree_breadcrumbs from "main" %} +{% endblock breadcrumbs %} + +{% block content_attributes %}with-left-sidebar{% endblock %} + +{% block content %} + <article class="text"> + <header class="article-header"> + <h1 class="page-title">Python documentation by version</h1> + </header> + + <p>Some previous versions of the documentation remain available online. Use the list below to select a version to view.</p> + + <p>For unreleased (in development) documentation, see <a href="#in-development-versions">In development versions</a>.</p> + + <h2>Release versions</h2> + + {% for version_data in version_list %} + <h3>Python {{ version_data.version }}</h3> + <ul> + {% for release in version_data.releases %} + <li> + {% if release.stage %} + <a href="https://docs.python.org/release/{{ release.stage|cut:" " }}/">Python {{ release.stage }}</a>{% if release.date %}, released on {{ release.date }}{% endif %} + {% endif %} + </li> + {% endfor %} + </ul> + {% endfor %} + + <h2 id="in-development-versions">In development versions</h2> + <p>The latest, and unreleased, documentation for versions of Python still under development:</p> + <ul> + <li><a href="https://docs.python.org/dev/">Development version</a></li> + <li><a href="https://docs.python.org/3/">Python 3.x</a></li> + </ul> + + </article> +{% endblock content %} + +{% block left_sidebar %} +<aside class="left-sidebar" role="secondary"> + {% include "components/navigation-widget.html" %} + + <div class="psf-sidebar-widget sidebar-widget"> + {% box 'widget-sidebar-aboutpsf' %} + </div> +</aside> +{% endblock left_sidebar %} From 95f50d79e146f3dc58de0ed8dc8ce84161b8e699 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 25 Nov 2025 23:15:47 +0200 Subject: [PATCH 213/235] Add `/downloads/latest/prerelease` redirect (#2823) --- downloads/managers.py | 6 ++++++ downloads/models.py | 1 + downloads/tests/test_models.py | 22 ++++++++++++++++++++++ downloads/tests/test_views.py | 12 ++++++++++++ downloads/urls.py | 1 + downloads/views.py | 17 +++++++++++++++++ fixtures/boxes.json | 8 ++++---- 7 files changed, 63 insertions(+), 4 deletions(-) diff --git a/downloads/managers.py b/downloads/managers.py index 22da0cdd0..f692524ce 100644 --- a/downloads/managers.py +++ b/downloads/managers.py @@ -35,6 +35,9 @@ def latest_python3(self, minor_version: int | None = None): pattern = rf"^Python 3\.{minor_version}\." return self.python3().filter(name__regex=pattern).order_by("-release_date") + def latest_prerelease(self): + return self.python3().filter(pre_release=True).order_by("-release_date") + def latest_pymanager(self): return self.pymanager().filter(is_latest=True) @@ -52,5 +55,8 @@ def latest_python2(self): def latest_python3(self, minor_version: int | None = None): return self.get_queryset().latest_python3(minor_version).first() + def latest_prerelease(self): + return self.get_queryset().latest_prerelease().first() + def latest_pymanager(self): return self.get_queryset().latest_pymanager().first() diff --git a/downloads/models.py b/downloads/models.py index f37a041d0..fb651c29a 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -298,6 +298,7 @@ def purge_fastly_download_pages(sender, instance, **kwargs): match = re.match(r'^3\.(\d+)', version) if match: purge_url(f'/downloads/latest/python3.{match.group(1)}/') + purge_url('/downloads/latest/prerelease/') purge_url('/downloads/latest/pymanager/') purge_url('/downloads/macos/') purge_url('/downloads/source/') diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index 1c8e9ba47..1f260e08a 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -74,6 +74,28 @@ def test_latest_python3(self): latest_3_99 = Release.objects.latest_python3(minor_version=99) self.assertIsNone(latest_3_99) + def test_latest_prerelease(self): + latest_prerelease = Release.objects.latest_prerelease() + self.assertEqual(latest_prerelease, self.pre_release) + + # Create a newer prerelease with a future date + newer_prerelease = Release.objects.create( + version=Release.PYTHON3, + name="Python 3.9.99", + is_published=True, + pre_release=True, + release_date=self.pre_release.release_date + dt.timedelta(days=1), + ) + latest_prerelease = Release.objects.latest_prerelease() + self.assertEqual(latest_prerelease, newer_prerelease) + self.assertNotEqual(latest_prerelease, self.pre_release) + + def test_latest_prerelease_when_no_prerelease(self): + # Delete the prerelease + self.pre_release.delete() + latest_prerelease = Release.objects.latest_prerelease() + self.assertIsNone(latest_prerelease) + def test_get_version(self): self.assertEqual(self.release_275.name, 'Python 2.7.5') self.assertEqual(self.release_275.get_version(), '2.7.5') diff --git a/downloads/tests/test_views.py b/downloads/tests/test_views.py index 1fbb687d0..5c5471d5a 100644 --- a/downloads/tests/test_views.py +++ b/downloads/tests/test_views.py @@ -95,6 +95,18 @@ def test_latest_python3x_redirects(self): response = self.client.get(url) self.assertRedirects(response, reverse("download:download")) + def test_latest_prerelease_redirect(self): + url = reverse("download:download_latest_prerelease") + response = self.client.get(url) + self.assertRedirects(response, self.pre_release.get_absolute_url()) + + def test_latest_prerelease_redirect_when_no_prerelease(self): + # Delete the prerelease to test fallback + self.pre_release.delete() + url = reverse("download:download_latest_prerelease") + response = self.client.get(url) + self.assertRedirects(response, reverse("download:download")) + def test_redirect_page_object_to_release_detail_page(self): self.release_275.release_page = None self.release_275.save() diff --git a/downloads/urls.py b/downloads/urls.py index 75dcef211..01f055fde 100644 --- a/downloads/urls.py +++ b/downloads/urls.py @@ -6,6 +6,7 @@ re_path(r'latest/python2/?$', views.DownloadLatestPython2.as_view(), name='download_latest_python2'), re_path(r'latest/python3/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), re_path(r'latest/python3\.(?P<minor>\d+)/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3x'), + re_path(r'latest/prerelease/?$', views.DownloadLatestPrerelease.as_view(), name='download_latest_prerelease'), re_path(r'latest/pymanager/?$', views.DownloadLatestPyManager.as_view(), name='download_latest_pymanager'), re_path(r'latest/?$', views.DownloadLatestPython3.as_view(), name='download_latest_python3'), path('operating-systems/', views.DownloadFullOSList.as_view(), name='download_full_os_list'), diff --git a/downloads/views.py b/downloads/views.py index 1d69a234c..fd1141c14 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -47,6 +47,23 @@ def get_redirect_url(self, **kwargs): return reverse("downloads:download") +class DownloadLatestPrerelease(RedirectView): + """Redirect to latest Python 3 prerelease""" + + permanent = False + + def get_redirect_url(self, **kwargs): + try: + latest_prerelease = Release.objects.latest_prerelease() + except Release.DoesNotExist: + latest_prerelease = None + + if latest_prerelease: + return latest_prerelease.get_absolute_url() + else: + return reverse("downloads:download") + + class DownloadLatestPyManager(RedirectView): """ Redirect to latest Python install manager release """ permanent = False diff --git a/fixtures/boxes.json b/fixtures/boxes.json index df66827b5..17103ee2f 100644 --- a/fixtures/boxes.json +++ b/fixtures/boxes.json @@ -642,9 +642,9 @@ "created": "2014-02-13T21:06:57.376Z", "updated": "2021-07-29T21:39:50.973Z", "label": "download-banner", - "content": "<p>\r\n Looking for Python with a different OS? Python for\r\n <a href=\"/downloads/windows/\">Windows</a>,\r\n <a href=\"/downloads/source/\">Linux/UNIX</a>,\r\n <a href=\"/downloads/macos/\">macOS</a>,\r\n <a href=\"/download/other/\">Other</a>\r\n</p>\r\n\r\n<p style=\"margin-top: 0.35em\">\r\n Want to help test development versions of Python?\r\n <a href=\"/download/pre-releases/\">Prereleases</a>,\r\n <a href=\"https://quay.io/repository/python-devs/ci-image\">Docker images</a> \r\n</p>\r\n\r\n<p style=\"margin-top: 0.35em\">\r\n Looking for Python 2.7? See below for specific releases\r\n</p>", + "content": "<p>\r\n Looking for Python with a different OS? Python for\r\n <a href=\"/downloads/windows/\">Windows</a>,\r\n <a href=\"/downloads/source/\">Linux/Unix</a>,\r\n <a href=\"/downloads/macos/\">macOS</a>,\r\n <a href=\"/downloads/android/\">Android</a>,\r\n <a href=\"/download/other/\">other</a>\r\n</p>\r\n<p style=\"margin-top: 0.35em\">\r\n Want to help test development versions of Python 3.15?\r\n <a href=\"/downloads/latest/prerelease/\">Pre-releases</a>,\r\n <a href=\"https://gitlab.com/python-devs/ci-images\">Docker images</a> \r\n</p>", "content_markup_type": "html", - "_content_rendered": "<p>\r\n Looking for Python with a different OS? Python for\r\n <a href=\"/downloads/windows/\">Windows</a>,\r\n <a href=\"/downloads/source/\">Linux/UNIX</a>,\r\n <a href=\"/downloads/macos/\">macOS</a>,\r\n <a href=\"/download/other/\">Other</a>\r\n</p>\r\n\r\n<p style=\"margin-top: 0.35em\">\r\n Want to help test development versions of Python?\r\n <a href=\"/download/pre-releases/\">Prereleases</a>,\r\n <a href=\"https://quay.io/repository/python-devs/ci-image\">Docker images</a> \r\n</p>\r\n\r\n<p style=\"margin-top: 0.35em\">\r\n Looking for Python 2.7? See below for specific releases\r\n</p>" + "_content_rendered": "<p>\r\n Looking for Python with a different OS? Python for\r\n <a href=\"/downloads/windows/\">Windows</a>,\r\n <a href=\"/downloads/source/\">Linux/Unix</a>,\r\n <a href=\"/downloads/macos/\">macOS</a>,\r\n <a href=\"/downloads/android/\">Android</a>,\r\n <a href=\"/download/other/\">other</a>\r\n</p>\r\n<p style=\"margin-top: 0.35em\">\r\n Want to help test development versions of Python 3.15?\r\n <a href=\"/downloads/latest/prerelease/\">Pre-releases</a>,\r\n <a href=\"https://gitlab.com/python-devs/ci-images\">Docker images</a> \r\n</p>" } }, { @@ -702,9 +702,9 @@ "created": "2020-10-05T17:33:33.157Z", "updated": "2022-05-17T17:22:45.210Z", "label": "downloads-active-releases", - "content": "<div class=\"list-row-headings\">\r\n <span class=\"release-version\">Python version</span>\r\n <span class=\"release-status\">Maintenance status</span>\r\n <span class=\"release-start\">First released</span>\r\n <span class=\"release-end\">End of support</span>\r\n <span class=\"release-pep\">Release schedule</span>\r\n</div>\r\n<ol class=\"list-row-container menu\">\r\n <li>\r\n <span class=\"release-version\">3.10</span>\r\n <span class=\"release-status\">bugfix</span>\r\n <span class=\"release-start\">2021-10-04</span>\r\n <span class=\"release-end\">2026-10</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0619\">PEP 619</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.9</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-start\">2020-10-05</span>\r\n <span class=\"release-end\">2025-10</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0596\">PEP 596</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.8</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-start\">2019-10-14</span>\r\n <span class=\"release-end\">2024-10</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0569\">PEP 569</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.7</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-start\">2018-06-27</span>\r\n <span class=\"release-end\">2023-06-27</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0537\">PEP 537</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">2.7</span>\r\n <span class=\"release-status\">end-of-life</span>\r\n <span class=\"release-start\">2010-07-03</span>\r\n <span class=\"release-end\">2020-01-01</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0373\">PEP 373</a></span>\r\n </li>\r\n</ol>", + "content": "<div class=\"list-row-headings\">\r\n <span class=\"release-version\">Python version</span>\r\n <span class=\"release-status\">Maintenance status</span>\r\n <span class=\"release-dl\"> </span>\r\n <span class=\"release-start\">First released</span>\r\n <span class=\"release-end\">End of support</span>\r\n <span class=\"release-pep\">Release schedule</span>\r\n</div>\r\n<ol class=\"list-row-container menu\">\r\n <li>\r\n <span class=\"release-version\">3.15</span>\r\n <span class=\"release-status\"><a href=\"/downloads/latest/prerelease/\">pre-release</a></span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.15/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2026-10-07 (planned)</span>\r\n <span class=\"release-end\">2031-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0790/\">PEP 790</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.14</span>\r\n <span class=\"release-status\">bugfix</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.14/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2025-10-07</span>\r\n <span class=\"release-end\">2030-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0745/\">PEP 745</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.13</span>\r\n <span class=\"release-status\">bugfix</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.13/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2024-10-07</span>\r\n <span class=\"release-end\">2029-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0719/\">PEP 719</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.12</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.12/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2023-10-02</span>\r\n <span class=\"release-end\">2028-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0693/\">PEP 693</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.11</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.11/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2022-10-24</span>\r\n <span class=\"release-end\">2027-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0664/\">PEP 664</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.10</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.10/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2021-10-04</span>\r\n <span class=\"release-end\">2026-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0619/\">PEP 619</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.9</span>\r\n <span class=\"release-status\">end of life, last release was <a href=\"https://www.python.org/downloads/release/python-3925/\">3.9.25</a></span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.9/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2020-10-05</span>\r\n <span class=\"release-end\">2025-10-31</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0596/\">PEP 596</a></span>\r\n </li>\r\n</ol>", "content_markup_type": "html", - "_content_rendered": "<div class=\"list-row-headings\">\r\n <span class=\"release-version\">Python version</span>\r\n <span class=\"release-status\">Maintenance status</span>\r\n <span class=\"release-start\">First released</span>\r\n <span class=\"release-end\">End of support</span>\r\n <span class=\"release-pep\">Release schedule</span>\r\n</div>\r\n<ol class=\"list-row-container menu\">\r\n <li>\r\n <span class=\"release-version\">3.10</span>\r\n <span class=\"release-status\">bugfix</span>\r\n <span class=\"release-start\">2021-10-04</span>\r\n <span class=\"release-end\">2026-10</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0619\">PEP 619</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.9</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-start\">2020-10-05</span>\r\n <span class=\"release-end\">2025-10</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0596\">PEP 596</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.8</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-start\">2019-10-14</span>\r\n <span class=\"release-end\">2024-10</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0569\">PEP 569</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.7</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-start\">2018-06-27</span>\r\n <span class=\"release-end\">2023-06-27</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0537\">PEP 537</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">2.7</span>\r\n <span class=\"release-status\">end-of-life</span>\r\n <span class=\"release-start\">2010-07-03</span>\r\n <span class=\"release-end\">2020-01-01</span>\r\n <span class=\"release-pep\"><a href=\"https://www.python.org/dev/peps/pep-0373\">PEP 373</a></span>\r\n </li>\r\n</ol>" + "_content_rendered": "<div class=\"list-row-headings\">\r\n <span class=\"release-version\">Python version</span>\r\n <span class=\"release-status\">Maintenance status</span>\r\n <span class=\"release-dl\"> </span>\r\n <span class=\"release-start\">First released</span>\r\n <span class=\"release-end\">End of support</span>\r\n <span class=\"release-pep\">Release schedule</span>\r\n</div>\r\n<ol class=\"list-row-container menu\">\r\n <li>\r\n <span class=\"release-version\">3.15</span>\r\n <span class=\"release-status\"><a href=\"/downloads/latest/prerelease/\">pre-release</a></span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.15/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2026-10-07 (planned)</span>\r\n <span class=\"release-end\">2031-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0790/\">PEP 790</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.14</span>\r\n <span class=\"release-status\">bugfix</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.14/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2025-10-07</span>\r\n <span class=\"release-end\">2030-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0745/\">PEP 745</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.13</span>\r\n <span class=\"release-status\">bugfix</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.13/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2024-10-07</span>\r\n <span class=\"release-end\">2029-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0719/\">PEP 719</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.12</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.12/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2023-10-02</span>\r\n <span class=\"release-end\">2028-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0693/\">PEP 693</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.11</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.11/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2022-10-24</span>\r\n <span class=\"release-end\">2027-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0664/\">PEP 664</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.10</span>\r\n <span class=\"release-status\">security</span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.10/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2021-10-04</span>\r\n <span class=\"release-end\">2026-10</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0619/\">PEP 619</a></span>\r\n </li>\r\n <li>\r\n <span class=\"release-version\">3.9</span>\r\n <span class=\"release-status\">end of life, last release was <a href=\"https://www.python.org/downloads/release/python-3925/\">3.9.25</a></span>\r\n <span class=\"release-dl\"><a href=\"/downloads/latest/python3.9/\"><span aria-hidden=\"true\" class=\"icon-download\"></span>Download</a></span>\r\n <span class=\"release-start\">2020-10-05</span>\r\n <span class=\"release-end\">2025-10-31</span>\r\n <span class=\"release-pep\"><a href=\"https://peps.python.org/pep-0596/\">PEP 596</a></span>\r\n </li>\r\n</ol>" } }, { From 901285e790098f84e179de94d113ff827bcf8ec0 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Tue, 25 Nov 2025 23:53:56 +0200 Subject: [PATCH 214/235] Rename to /doc/versions (#2824) --- pydotorg/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydotorg/urls.py b/pydotorg/urls.py index bd5496fb6..dbcbcd888 100644 --- a/pydotorg/urls.py +++ b/pydotorg/urls.py @@ -32,7 +32,7 @@ path('getit/', include('downloads.urls', namespace='getit')), path('downloads/', include('downloads.urls', namespace='download')), path('doc/', views.DocumentationIndexView.as_view(), name='documentation'), - path('doc/versions2/', views.DocsByVersionView.as_view(), name='docs-versions'), + path('doc/versions/', views.DocsByVersionView.as_view(), name='docs-versions'), path('blogs/', include('blogs.urls')), path('inner/', TemplateView.as_view(template_name="python/inner.html"), name='inner'), From 652484d3f2d0162a7d607a8db11f560a545bb96b Mon Sep 17 00:00:00 2001 From: Chen Zichan <139482965+czc0407@users.noreply.github.com> Date: Wed, 26 Nov 2025 17:36:12 +0800 Subject: [PATCH 215/235] Fix PSF membership link (#2787) with dynamic logic (#2799) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Jacob Coffee <jacob@z7x.org> --- templates/includes/authenticated.html | 14 ++++++++++- users/tests/test_membership_links.py | 36 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 users/tests/test_membership_links.py diff --git a/templates/includes/authenticated.html b/templates/includes/authenticated.html index 82d5b38f6..662872a27 100644 --- a/templates/includes/authenticated.html +++ b/templates/includes/authenticated.html @@ -7,7 +7,19 @@ <li class="tier-2 element-1" role="treeitem"><a href="{% url 'users:user_profile_edit' %}">Edit your user profile</a></li> <li class="tier-2 element-2" role="treeitem"><a href="{% url 'account_change_password' %}">Change your password</a></li> {% if request.user.has_membership %} - <li class="tier-2 element-3" role="treeitem"><a href="{% url 'users:user_membership_edit' %}">Edit your PSF Basic membership</a></li> + <li class="tier-2 element-3" role="treeitem"> + {% if user.is_authenticated %} + {% if user.has_membership %} + <a href="{% url 'users:user_membership_edit' %}">Edit your PSF Basic membership</a> + {% else %} + <a href="{% url 'users:user_membership_create' %}">Join the PSF</a> + {% endif %} + {% else %} + <a href="{% url 'account_login' %}?next=https://psfmember.org/membership/"> + Log in to manage membership + </a> + {% endif %} + </li> {% else %} <li class="tier-2 element-3" role="treeitem"><a href="{% url 'users:user_membership_create' %}">Become a PSF Basic member</a></li> {% endif %} diff --git a/users/tests/test_membership_links.py b/users/tests/test_membership_links.py new file mode 100644 index 000000000..234832c65 --- /dev/null +++ b/users/tests/test_membership_links.py @@ -0,0 +1,36 @@ +from django.test import TestCase, RequestFactory +from django.template import Context, Template +from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser +from users.models import Membership + +User = get_user_model() + +class MembershipLinkTests(TestCase): + + def setUp(self): + self.factory = RequestFactory() + self.user = User.objects.create_user(username='testuser', password='123') + self.template = Template(""" + {% include 'includes/authenticated.html' %} + """) + + def render_template(self, user): + request = self.factory.get('/') + request.user = user + return self.template.render(Context({'user': user, 'request': request})) + + def test_anonymous_user(self): + html = self.render_template(AnonymousUser()) + # Anonymous users should see "Sign In" + self.assertIn('Sign In', html) + + def test_logged_in_non_member(self): + html = self.render_template(self.user) + # Logged-in but not a member -> should see the membership join link + self.assertIn('Become a PSF Basic member', html) + + def test_logged_in_member(self): + Membership.objects.create(creator=self.user) + html = self.render_template(self.user) + self.assertIn('Edit your PSF Basic membership', html) From b51e4f8bd5428b6eaed4253e4f14a06206262f25 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 26 Nov 2025 21:51:00 +0200 Subject: [PATCH 216/235] Add 'superseded by' notice to older Python 3 releases (#2827) --- downloads/tests/test_views.py | 31 +++++++++++++++++++++++++ downloads/views.py | 12 ++++++++++ templates/downloads/release_detail.html | 6 ++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/downloads/tests/test_views.py b/downloads/tests/test_views.py index 5c5471d5a..247da04c8 100644 --- a/downloads/tests/test_views.py +++ b/downloads/tests/test_views.py @@ -46,6 +46,37 @@ def test_download_release_detail(self): response = self.client.get(url) self.assertEqual(response.status_code, 404) + def test_download_release_detail_not_superseded(self): + """Test that latest releases and Python 2 do not show a superseded notice.""" + for release in [self.python_3, self.python_3_8_20, self.release_275]: + with self.subTest(release=release.name): + url = reverse( + "download:download_release_detail", + kwargs={"release_slug": release.slug}, + ) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + self.assertNotIn("latest_in_series", response.context) + self.assertNotContains(response, "has been superseded by") + + def test_download_release_detail_superseded(self): + """Test that older releases show a superseded notice.""" + tests = [ + (self.python_3_10_18, self.python_3), + (self.python_3_8_19, self.python_3_8_20), + ] + for old_release, latest_release in tests: + with self.subTest(release=old_release.name): + url = reverse( + "download:download_release_detail", + kwargs={"release_slug": old_release.slug}, + ) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.context["latest_in_series"], latest_release) + self.assertContains(response, "has been superseded by") + self.assertContains(response, latest_release.name) + def test_download_os_list(self): url = reverse('download:download_os_list', kwargs={'slug': self.linux.slug}) response = self.client.get(url) diff --git a/downloads/views.py b/downloads/views.py index fd1141c14..41e8839ff 100644 --- a/downloads/views.py +++ b/downloads/views.py @@ -1,5 +1,6 @@ from typing import Any +import re from datetime import datetime from django.db.models import Case, IntegerField, Prefetch, When @@ -216,6 +217,17 @@ def get_context_data(self, **kwargs): ) ) + # Find the latest release in the feature series (such as 3.14.x) + # to show a "superseded by" notice on older releases + version = self.object.get_version() + if version and self.object.version == Release.PYTHON3: + match = re.match(r"^3\.(\d+)", version) + if match: + minor_version = int(match.group(1)) + latest_in_series = Release.objects.latest_python3(minor_version) + if latest_in_series and latest_in_series.pk != self.object.pk: + context["latest_in_series"] = latest_in_series + return context diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 5959dfe30..4faf51749 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -26,7 +26,11 @@ <h1 class="page-title">{{ release.name }}</h1> </header> - <p><strong>Release Date:</strong> {{ release.release_date|date }}</p> + {% if latest_in_series %} + <p><strong>Note:</strong> {{ release.name }} has been superseded by <a href="{{ latest_in_series.get_absolute_url }}">{{ latest_in_series.name }}</a>.</p> + {% endif %} + + <p><strong>Release date:</strong> {{ release.release_date|date }}</p> {% if release.content.raw %} {{ release.content.rendered|safe }} From 197ddadc388152a6aa0ad2f57a29570197099014 Mon Sep 17 00:00:00 2001 From: Dorian Adams <104034366+dorian-adams@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:56:00 -0500 Subject: [PATCH 217/235] fix(frontend): HTML leak in `job_detail` (#2316) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Jacob Coffee <jacob@z7x.org> --- templates/jobs/job_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/jobs/job_detail.html b/templates/jobs/job_detail.html index be073e551..cef7c1f2f 100644 --- a/templates/jobs/job_detail.html +++ b/templates/jobs/job_detail.html @@ -8,7 +8,7 @@ {% block content_attributes %}with-right-sidebar{% endblock %} {% block og_title %}Job: {{ object.job_title }} at {{ object.company_name }}{% endblock %} -{% block og-descript %}{{ object.description|escape|truncatechars:200 }}{% endblock %} +{% block og-descript %}{{ object.description.rendered|striptags|truncatechars:200 }}{% endblock %} {% block content %} {% load companies %} From e94fa01abbab23b50d74fe9099b9c42273c19118 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Thu, 27 Nov 2025 17:56:31 +0200 Subject: [PATCH 218/235] Prefill release notes URL field (#2828) --- downloads/admin.py | 3 ++ static/js/admin/releaseAdmin.js | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 static/js/admin/releaseAdmin.js diff --git a/downloads/admin.py b/downloads/admin.py index da5d94ad8..d0b93c3eb 100644 --- a/downloads/admin.py +++ b/downloads/admin.py @@ -31,3 +31,6 @@ def formfield_for_dbfield(self, db_field, request, **kwargs): if db_field.name == "name": field.widget.attrs["placeholder"] = "Python 3.X.YaN" return field + + class Media: + js = ["js/admin/releaseAdmin.js"] diff --git a/static/js/admin/releaseAdmin.js b/static/js/admin/releaseAdmin.js new file mode 100644 index 000000000..0eb13baac --- /dev/null +++ b/static/js/admin/releaseAdmin.js @@ -0,0 +1,53 @@ +'use strict'; + +function generateReleaseNotesUrl(name) { + // Match "Python X.Y.Z[aN]" + const match = name.match(/^Python (\d+)\.(\d+)\.(\d+)((?:a|b|rc)\d*)?$/); + if (!match) { + return ''; + } + + const major = match[1]; + const minor = match[2]; + const patch = match[3]; + const prerelease = match[4]; // e.g., "a2", "b1", "rc1" or undefined + + if (prerelease) { + // Prerelease: https://docs.python.org/3.15/whatsnew/3.15.html + return `https://docs.python.org/${major}.${minor}/whatsnew/${major}.${minor}.html`; + } else { + // Regular release: https://docs.python.org/release/3.13.9/whatsnew/changelog.html + return `https://docs.python.org/release/${major}.${minor}.${patch}/whatsnew/changelog.html`; + } +} + +document.addEventListener('DOMContentLoaded', function() { + // Only run on add page, not edit + if (!window.location.pathname.endsWith('/add/')) { + return; + } + + const nameField = document.getElementById('id_name'); + const releaseNotesUrlField = document.getElementById('id_release_notes_url'); + + if (!nameField || !releaseNotesUrlField) { + return; + } + + // Track if user has manually edited the field + let changed = false; + releaseNotesUrlField.addEventListener('change', function() { + changed = true; + }); + + nameField.addEventListener('keyup', populate); + nameField.addEventListener('change', populate); + nameField.addEventListener('focus', populate); + + function populate() { + if (changed) { + return; + } + releaseNotesUrlField.value = generateReleaseNotesUrl(nameField.value); + } +}); From b7f1cd287694d443b478a380c503e0a7a74c9e32 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 28 Nov 2025 18:56:44 +0200 Subject: [PATCH 219/235] Remove unused Requests security extra (#2831) --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index bfd2dece1..84fd40677 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -31,7 +31,7 @@ django-tastypie==0.14.7 # 0.14.6 is first version that supports Django 4.2 pytz==2021.1 python-dateutil==2.8.2 -requests[security]>=2.26.0 +requests>=2.26.0 django-honeypot==1.0.4 # 1.0.4 is first version that supports Django 4.2 django-markupfield==2.0.1 From 27aef89cab44c2126d1a934b0da86bfd1f42211d Mon Sep 17 00:00:00 2001 From: Ee Durbin <ewdurbin@gmail.com> Date: Tue, 2 Dec 2025 10:36:03 -0500 Subject: [PATCH 220/235] load fundraiser banner from donate.python.org (#2838) --- static/sass/style.css | 6 +++--- templates/base.html | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/static/sass/style.css b/static/sass/style.css index 894cd6214..d66c03a58 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -2267,7 +2267,7 @@ table tfoot { /* ! ===== Success Stories landing page ===== */ .featured-success-story { padding: 1.3125em 0; - background: center -230px no-repeat url('../img/success-glow2.png?1726783859') transparent; + background: center -230px no-repeat url('../img/success-glow2.png?1646853871') transparent; /*blockquote*/ } .featured-success-story img { padding: 10px 30px; } @@ -3271,11 +3271,11 @@ span.highlighted { .python .site-headline a:before { width: 290px; height: 82px; - content: url('../img/python-logo_print.png?1726783859'); } + content: url('../img/python-logo_print.png?1646853871'); } .psf .site-headline a:before { width: 334px; height: 82px; - content: url('../img/psf-logo_print.png?1726783859'); } } + content: url('../img/psf-logo_print.png?1646853871'); } } /* * When we want to review the markup for W3 and similar errors, turn some of these on * Uses :not selectors a bunch, so only modern browsers will support them diff --git a/templates/base.html b/templates/base.html index e0b692407..04e0c4036 100644 --- a/templates/base.html +++ b/templates/base.html @@ -31,6 +31,9 @@ crossorigin="anonymous" ></script> <script src="{{ STATIC_URL }}js/libs/modernizr.js"></script> + <script async + src="https://donate.python.org/fundraiser-banner/fundraiser-banner.js"></script> + {% stylesheet 'style' %} {% stylesheet 'mq' %} From 0d94709b269a0979a26079627841e590e3fc95e6 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Sun, 7 Dec 2025 21:19:48 +0200 Subject: [PATCH 221/235] Track file downloads via Plausible (#2845) * Remove obsolete Google Analytics JS * Track file downloads via Plausible --- templates/base.html | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/templates/base.html b/templates/base.html index 04e0c4036..c12e87b6f 100644 --- a/templates/base.html +++ b/templates/base.html @@ -5,7 +5,10 @@ <!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"> <!--<![endif]--> {% load pipeline sitetree %} <head> - <script defer data-domain="python.org" src="https://analytics.python.org/js/script.outbound-links.js"></script> + <script defer + file-types="bz2,chm,dmg,exe,gz,json,msi,msix,pdf,pkg,tgz,xz,zip" + data-domain="python.org" + src="https://analytics.python.org/js/script.file-downloads.outbound-links.js"></script> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> @@ -133,18 +136,6 @@ } </script> - {# Asynchronous Analytics snippet #} - <script type="text/javascript"> - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-39055973-1']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); - </script> {% block head %}{% endblock %} </head> From aff342dc2a623c9ef1d74742eaf3fb6fa6ad3a28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 17:15:24 -0600 Subject: [PATCH 222/235] chore(deps): bump django from 4.2.26 to 4.2.27 (#2840) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 84fd40677..428c85c60 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -4,7 +4,7 @@ django-sitetree==1.18.0 # >=1.17.1 is (?) first version that supports Django 4. django-apptemplates==1.5 django-admin-interface==0.28.9 django-translation-aliases==0.1.0 -Django==4.2.26 +Django==4.2.27 docutils==0.21.2 Markdown==3.7 cmarkgfm==2024.11.20 From f3699748a008b40d69bb9a9743c52da93c4f1de5 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Fri, 12 Dec 2025 01:16:18 +0200 Subject: [PATCH 223/235] Add "Edit this release" button to release pages (#2843) --- templates/downloads/release_detail.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 4faf51749..35d3ce316 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -21,6 +21,9 @@ {% block content %} <article class="text"> + {% if request.user.is_staff %} + <a role="button" class="button" href="{% url 'admin:downloads_release_change' release.pk %}">Edit this release</a> + {% endif %} <header class="article-header"> <h1 class="page-title">{{ release.name }}</h1> From 4bc69da140492d4aa016bffb81552ae6fc8e0543 Mon Sep 17 00:00:00 2001 From: Jacob Coffee <jacob@z7x.org> Date: Mon, 15 Dec 2025 13:49:58 -0600 Subject: [PATCH 224/235] add sha256 for release files (#2830) --- downloads/api.py | 2 +- .../migrations/0014_releasefile_sha256_sum.py | 18 ++++++++++++++++++ downloads/models.py | 1 + downloads/serializers.py | 1 + templates/downloads/release_detail.html | 4 +++- 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 downloads/migrations/0014_releasefile_sha256_sum.py diff --git a/downloads/api.py b/downloads/api.py index 73eb9b7bf..ea32421bc 100644 --- a/downloads/api.py +++ b/downloads/api.py @@ -68,7 +68,7 @@ class Meta(GenericResource.Meta): 'name', 'slug', 'creator', 'last_modified_by', 'os', 'release', 'description', 'is_source', 'url', 'gpg_signature_file', - 'md5_sum', 'filesize', 'download_button', 'sigstore_signature_file', + 'md5_sum', 'sha256_sum', 'filesize', 'download_button', 'sigstore_signature_file', 'sigstore_cert_file', 'sigstore_bundle_file', 'sbom_spdx2_file', ] filtering = { diff --git a/downloads/migrations/0014_releasefile_sha256_sum.py b/downloads/migrations/0014_releasefile_sha256_sum.py new file mode 100644 index 000000000..0aed813c2 --- /dev/null +++ b/downloads/migrations/0014_releasefile_sha256_sum.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.26 on 2025-11-27 16:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('downloads', '0013_alter_release_content_markup_type'), + ] + + operations = [ + migrations.AddField( + model_name='releasefile', + name='sha256_sum', + field=models.CharField(blank=True, max_length=200, verbose_name='SHA256 Sum'), + ), + ] diff --git a/downloads/models.py b/downloads/models.py index fb651c29a..0a0d0e525 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -360,6 +360,7 @@ class ReleaseFile(ContentManageable, NameSlugModel): "SPDX-2 SBOM URL", blank=True, help_text="SPDX-2 SBOM URL" ) md5_sum = models.CharField('MD5 Sum', max_length=200, blank=True) + sha256_sum = models.CharField('SHA256 Sum', max_length=200, blank=True) filesize = models.IntegerField(default=0) download_button = models.BooleanField(default=False, help_text="Use for the supernav download button for this OS") diff --git a/downloads/serializers.py b/downloads/serializers.py index 1ff57049f..29c95593d 100644 --- a/downloads/serializers.py +++ b/downloads/serializers.py @@ -43,6 +43,7 @@ class Meta: 'url', 'gpg_signature_file', 'md5_sum', + 'sha256_sum', 'filesize', 'download_button', 'resource_uri', diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 35d3ce316..318441ccd 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -74,7 +74,8 @@ <h3>{{ f.os.name }}</h3> <th>Version</th> <th>Operating System</th> <th>Description</th> - <th>MD5 Sum</th> + <th>MD5 Checksum</th> + <th>SHA256 Checksum</th> <th>File Size</th> {% if release_files|has_sigstore_materials %} <th colspan="2"><a href="https://www.python.org/download/sigstore/">Sigstore</a></th> @@ -94,6 +95,7 @@ <h3>{{ f.os.name }}</h3> <td>{{ f.os.name }}</td> <td>{{ f.description }}</td> <td>{{ f.md5_sum }}</td> + <td>{{ f.sha256_sum|default:"n/a" }}</td> <td>{{ f.filesize|filesizeformat }}</td> {% if release_files|has_sigstore_materials %} {% if f.sigstore_bundle_file %} From 00205c34b44dc19bf01aa334c68c15038ffb89e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 13:51:22 -0600 Subject: [PATCH 225/235] chore(deps): bump actions/cache from 4 to 5 in the github-actions group (#2848) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- .github/workflows/static.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6988c370e..f3de21d16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: with: python-version-file: '.python-version' - name: Cache Python dependencies - uses: actions/cache@v4 + uses: actions/cache@v5 env: cache-name: pythondotorg-cache-pip with: diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 9c06ff4a9..322dc20c3 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -12,7 +12,7 @@ jobs: with: python-version-file: '.python-version' - name: Cache Python dependencies - uses: actions/cache@v4 + uses: actions/cache@v5 env: cache-name: pythondotorg-cache-pip with: From 488f54d64f4f5e2d1e4346e89bdccb5cadf54b82 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 21:54:55 +0200 Subject: [PATCH 226/235] Improve contrast ratio of H2 (#2841) --- static/sass/style.css | 2 +- static/sass/style.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static/sass/style.css b/static/sass/style.css index d66c03a58..c6d67bc8e 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -781,7 +781,7 @@ h1, .alpha { margin-bottom: 0.4375em; } h2, .beta { - color: #999999; + color: #222222; font-family: SourceSansProRegular, Arial, sans-serif; font-size: 1.5em; margin-top: 1.3125em; diff --git a/static/sass/style.scss b/static/sass/style.scss index 5988b00d1..826473bdc 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -96,7 +96,7 @@ h1, .alpha { } h2, .beta { - color: $grey-light; + color: $grey-darker; font-family: $default-font; font-size: px2em( $headertwo ); @include leader(.75); From 8585af6ed2fada767bc55aae58509404c61e7e84 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 21:55:24 +0200 Subject: [PATCH 227/235] Fix OrderedModelBase warnings (#2835) --- sponsors/models/sponsorship.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sponsors/models/sponsorship.py b/sponsors/models/sponsorship.py index d230e91c3..529923602 100644 --- a/sponsors/models/sponsorship.py +++ b/sponsors/models/sponsorship.py @@ -17,7 +17,7 @@ from django.utils.functional import cached_property from num2words import num2words -from ordered_model.models import OrderedModel +from ordered_model.models import OrderedModel, OrderedModelManager from sponsors.exceptions import SponsorWithExistingApplicationException, InvalidStatusException, \ SponsorshipInvalidDateRangeException @@ -37,7 +37,8 @@ class SponsorshipPackage(OrderedModel): """ Represent default packages of benefits (visionary, sustainability etc) """ - objects = SponsorshipPackageQuerySet.as_manager() + + objects = OrderedModelManager.from_queryset(SponsorshipPackageQuerySet)() name = models.CharField(max_length=64) sponsorship_amount = models.PositiveIntegerField() @@ -408,7 +409,7 @@ class SponsorshipBenefit(OrderedModel): package and program. """ - objects = SponsorshipBenefitQuerySet.as_manager() + objects = OrderedModelManager.from_queryset(SponsorshipBenefitQuerySet)() # Public facing name = models.CharField( From e1b69b9102532946a98cae9cb62c9d70797355eb Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 21:59:57 +0200 Subject: [PATCH 228/235] Add EOL banner to EOL downloads (#2832) --- downloads/templatetags/download_tags.py | 70 ++++++++++ downloads/tests/test_template_tags.py | 170 ++++++++++++++++++++++++ static/sass/style.css | 10 +- static/sass/style.scss | 14 +- templates/downloads/release_detail.html | 15 ++- 5 files changed, 274 insertions(+), 5 deletions(-) create mode 100644 downloads/tests/test_template_tags.py diff --git a/downloads/templatetags/download_tags.py b/downloads/templatetags/download_tags.py index f61f25ada..0bc50ff8f 100644 --- a/downloads/templatetags/download_tags.py +++ b/downloads/templatetags/download_tags.py @@ -1,6 +1,76 @@ +import logging +import re + +import requests from django import template +from django.core.cache import cache register = template.Library() +logger = logging.getLogger(__name__) + +PYTHON_RELEASES_URL = "https://peps.python.org/api/python-releases.json" +PYTHON_RELEASES_CACHE_KEY = "python_python_releases" +PYTHON_RELEASES_CACHE_TIMEOUT = 3600 # 1 hour + + +def get_python_releases_data() -> dict | None: + """Fetch and cache the Python release cycle data from PEPs API.""" + data = cache.get(PYTHON_RELEASES_CACHE_KEY) + if data is not None: + return data + + try: + response = requests.get(PYTHON_RELEASES_URL, timeout=5) + response.raise_for_status() + data = response.json() + cache.set(PYTHON_RELEASES_CACHE_KEY, data, PYTHON_RELEASES_CACHE_TIMEOUT) + return data + except (requests.RequestException, ValueError) as e: + logger.warning("Failed to fetch release cycle data: %s", e) + return None + + +@register.simple_tag +def get_eol_info(release) -> dict: + """ + Check if a release's minor version is end-of-life. + + Returns a dict with 'is_eol' boolean and 'eol_date' if available. + Python 2 releases not found in the release cycle data, assumes EOL. + """ + result = {"is_eol": False, "eol_date": None} + + version = release.get_version() + if not version: + return result + + # Extract minor version (e.g. "3.9" from "3.9.14") + match = re.match(r"^(\d+)\.(\d+)", version) + if not match: + return result + + major = int(match.group(1)) + minor_version = f"{match.group(1)}.{match.group(2)}" + + python_releases = get_python_releases_data() + if python_releases is None: + # Can't determine EOL status, don't show warning + return result + + metadata = python_releases.get("metadata", {}) + version_info = metadata.get(minor_version) + + if version_info is None: + # Python 2 releases not in the list are EOL + if major <= 2: + result["is_eol"] = True + return result + + if version_info.get("status") == "end-of-life": + result["is_eol"] = True + result["eol_date"] = version_info.get("end_of_life") + + return result @register.filter diff --git a/downloads/tests/test_template_tags.py b/downloads/tests/test_template_tags.py new file mode 100644 index 000000000..a4a1b4104 --- /dev/null +++ b/downloads/tests/test_template_tags.py @@ -0,0 +1,170 @@ +import unittest.mock as mock + +import requests +from django.core.cache import cache +from django.test import TestCase, override_settings +from django.urls import reverse + +from ..templatetags.download_tags import get_eol_info, get_python_releases_data +from .base import BaseDownloadTests + +MOCK_PYTHON_RELEASE = { + "metadata": { + "2.7": {"status": "end-of-life", "end_of_life": "2020-01-01"}, + "3.8": {"status": "end-of-life", "end_of_life": "2024-10-07"}, + "3.10": {"status": "security", "end_of_life": "2026-10-04"}, + } +} + + +TEST_CACHES = { + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + "LOCATION": "test-cache", + } +} + + +@override_settings(CACHES=TEST_CACHES) +class GetEOLInfoTests(BaseDownloadTests): + def setUp(self): + super().setUp() + cache.clear() + + @mock.patch("downloads.templatetags.download_tags.get_python_releases_data") + def test_eol_status(self, mock_get_data): + """Test get_eol_info returns correct EOL status.""" + # Arrange + mock_get_data.return_value = MOCK_PYTHON_RELEASE + tests = [ + (self.release_275, True, "2020-01-01"), # EOL + (self.python_3_8_20, True, "2024-10-07"), # EOL + (self.python_3_10_18, False, None), # security + ] + + for release, expected_is_eol, expected_eol_date in tests: + with self.subTest(release=release.name): + # Act + result = get_eol_info(release) + + # Assert + self.assertEqual(result["is_eol"], expected_is_eol) + self.assertEqual(result["eol_date"], expected_eol_date) + + @mock.patch("downloads.templatetags.download_tags.get_python_releases_data") + def test_eol_status_api_failure(self, mock_get_data): + """Test that API failure results in not showing EOL warning.""" + # Arrange + mock_get_data.return_value = None + + # Act + result = get_eol_info(self.python_3_8_20) + + # Assert + self.assertFalse(result["is_eol"]) + self.assertIsNone(result["eol_date"]) + + +@override_settings(CACHES=TEST_CACHES) +class GetReleaseCycleDataTests(TestCase): + def setUp(self): + cache.clear() + + @mock.patch("downloads.templatetags.download_tags.requests.get") + def test_successful_fetch(self, mock_get): + """Test successful API fetch.""" + # Arrange + mock_response = mock.Mock() + mock_response.json.return_value = MOCK_PYTHON_RELEASE + mock_response.raise_for_status = mock.Mock() + mock_get.return_value = mock_response + + # Act + result = get_python_releases_data() + + # Assert + self.assertEqual(result, MOCK_PYTHON_RELEASE) + mock_get.assert_called_once() + + @mock.patch("downloads.templatetags.download_tags.requests.get") + def test_caches_result(self, mock_get): + """Test that the result is cached.""" + # Arrange + mock_response = mock.Mock() + mock_response.json.return_value = MOCK_PYTHON_RELEASE + mock_response.raise_for_status = mock.Mock() + mock_get.return_value = mock_response + + # Act + result1 = get_python_releases_data() + result2 = get_python_releases_data() + + # Assert + self.assertEqual(result1, result2) + mock_get.assert_called_once() + + @mock.patch("downloads.templatetags.download_tags.requests.get") + def test_request_exception_returns_none(self, mock_get): + """Test that request exceptions return None.""" + # Arrange + mock_get.side_effect = requests.RequestException("Connection error") + + # Act + result = get_python_releases_data() + + # Assert + self.assertIsNone(result) + + @mock.patch("downloads.templatetags.download_tags.requests.get") + def test_json_decode_error_returns_none(self, mock_get): + """Test that JSON decode errors return None.""" + # Arrange + mock_response = mock.Mock() + mock_response.raise_for_status = mock.Mock() + mock_response.json.side_effect = ValueError("Invalid JSON") + mock_get.return_value = mock_response + + # Act + result = get_python_releases_data() + + # Assert + self.assertIsNone(result) + + +@override_settings(CACHES=TEST_CACHES) +class EOLBannerViewTests(BaseDownloadTests): + + def setUp(self): + super().setUp() + cache.clear() + + @mock.patch("downloads.templatetags.download_tags.get_python_releases_data") + def test_eol_banner_visibility(self, mock_get_data): + """Test EOL banner is shown or hidden correctly.""" + # Arrange + tests = [ + ("release_275", MOCK_PYTHON_RELEASE, True), + ("python_3_8_20", MOCK_PYTHON_RELEASE, True), + ("python_3_10_18", MOCK_PYTHON_RELEASE, False), + ("python_3_8_20", None, False), + ] + + for release_attr, mock_data, expect_banner in tests: + with self.subTest(release=release_attr): + mock_get_data.return_value = mock_data + release = getattr(self, release_attr) + url = reverse( + "download:download_release_detail", + kwargs={"release_slug": release.slug}, + ) + + # Act + response = self.client.get(url) + + # Assert + self.assertEqual(response.status_code, 200) + if expect_banner: + self.assertContains(response, "level-error") + self.assertContains(response, "no longer supported") + else: + self.assertNotContains(response, "level-error") diff --git a/static/sass/style.css b/static/sass/style.css index c6d67bc8e..9c5cb26e3 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -2645,14 +2645,20 @@ p.quote-by-organization { background-color: #fff7dc; border: 2px solid #ffd343; } .level-notice span { - color: #dca900; } + color: #765a00; + font-weight: bold; } /* Something went wrong */ .level-error { background-color: #ecd4d7; border: 2px solid #b55863; } .level-error span { - color: #b55863; } + color: #853b44; + font-weight: bold; } + .level-error a { + color: #2b5b84; } + .level-error a:hover, .level-error a:focus { + color: #1e415e; } /* Yeah! It worked correctly */ .level-success { diff --git a/static/sass/style.scss b/static/sass/style.scss index 826473bdc..97963a5b9 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -1758,7 +1758,10 @@ $colors: $blue, $psf, $yellow, $green, $purple, $red; background-color: lighten( $yellow, 30% ); border: 2px solid $yellow; - span { color: darken( $yellow, 20% ); } + span { + color: darken( $yellow, 40% ); + font-weight: bold; + } } /* Something went wrong */ @@ -1766,7 +1769,14 @@ $colors: $blue, $psf, $yellow, $green, $purple, $red; background-color: lighten( $red, 35% ); border: 2px solid $red; - span { color: $red; } + span { + color: darken( $red, 15% ); + font-weight: bold; + } + a { + color: darken( $blue, 10% ); + &:hover, &:focus { color: darken( $blue, 20% ); } + } } /* Yeah! It worked correctly */ diff --git a/templates/downloads/release_detail.html b/templates/downloads/release_detail.html index 318441ccd..a41393711 100644 --- a/templates/downloads/release_detail.html +++ b/templates/downloads/release_detail.html @@ -5,6 +5,7 @@ {% load has_sigstore_materials from download_tags %} {% load has_sbom from download_tags %} {% load sort_windows from download_tags %} +{% load get_eol_info from download_tags %} {% block body_attributes %}class="python downloads"{% endblock %} @@ -29,8 +30,20 @@ <h1 class="page-title">{{ release.name }}</h1> </header> + {% get_eol_info release as eol_info %} + {% if eol_info.is_eol %} + <div class="user-feedback level-error"> + <span>Warning:</span> + Python {{ release.get_version|default:release.name }} reached end-of-life{% if eol_info.eol_date %} on {{ eol_info.eol_date }}{% endif %}. + It is no longer supported and does not receive security updates. + We recommend upgrading to the <a href="{% url 'downloads:download_latest_python3' %}">latest Python release</a>. + </div> + {% endif %} + {% if latest_in_series %} - <p><strong>Note:</strong> {{ release.name }} has been superseded by <a href="{{ latest_in_series.get_absolute_url }}">{{ latest_in_series.name }}</a>.</p> + <div class="user-feedback level-notice"> + <span>Note:</span> {{ release.name }} has been superseded by <a href="{{ latest_in_series.get_absolute_url }}">{{ latest_in_series.name }}</a>. + </div> {% endif %} <p><strong>Release date:</strong> {{ release.release_date|date }}</p> From 7803abeea4d4203aadfe86d5215a4cb12f521c45 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:03:25 +0200 Subject: [PATCH 229/235] Remove duplicate devguide link from footer (#2834) --- fixtures/sitetree_menus.json | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/fixtures/sitetree_menus.json b/fixtures/sitetree_menus.json index 69b9b34af..ee6d9e649 100644 --- a/fixtures/sitetree_menus.json +++ b/fixtures/sitetree_menus.json @@ -607,30 +607,6 @@ "access_permissions": [] } }, -{ - "model": "sitetree.treeitem", - "pk": 28, - "fields": { - "title": "Developer's Guide", - "hint": "", - "url": "https://devguide.python.org/", - "urlaspattern": false, - "tree": 1, - "hidden": false, - "alias": null, - "description": "", - "inmenu": true, - "inbreadcrumbs": true, - "insitetree": true, - "access_loggedin": false, - "access_guest": false, - "access_restricted": false, - "access_perm_type": 1, - "parent": 9, - "sort_order": 28, - "access_permissions": [] - } -}, { "model": "sitetree.treeitem", "pk": 29, From f26f49b3bb79e92d1751459cc817ad7ad7375903 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:04:16 +0200 Subject: [PATCH 230/235] Update blogs-subscriptions box fixture to match prod (#2836) --- fixtures/boxes.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fixtures/boxes.json b/fixtures/boxes.json index 17103ee2f..9825d1df7 100644 --- a/fixtures/boxes.json +++ b/fixtures/boxes.json @@ -472,11 +472,11 @@ "pk": 40, "fields": { "created": "2014-02-13T18:27:24.143Z", - "updated": "2014-07-20T16:52:47.929Z", + "updated": "2025-04-21T17:45:00.000Z", "label": "blogs-subscriptions", - "content": "<h2 class=\"widget-title\"><span class=\"blog-name\">Python Insider</span> Subscriptions</h2>\r\n<p>Subscribe to Python Insider via:</p>\r\n<ul class=\"subscription-channels menu\">\r\n <li><a href=\"http://feeds.feedburner.com/PythonInsider\"><span aria-hidden=\"true\" class=\"icon-feed\"></span>RSS</a></li>\r\n <li><a href=\"https://twitter.com/pythoninsider\"><span aria-hidden=\"true\" class=\"icon-twitter\"></span>Twitter</a></li>\r\n</ul>\r\n<p>Also check out the <a href=\"https://mail.python.org/pipermail/python-dev/\">Python-Dev mailing list</a></p>", + "content": "<h2 class=\"widget-title\"><span class=\"blog-name\">Python Insider</span> Subscriptions</h2>\r\n<p>Subscribe to Python Insider via:</p>\r\n<ul class=\"subscription-channels menu\">\r\n <li><a href=\"https://blog.python.org/feeds/posts/default?alt=rss\"><span aria-hidden=\"true\" class=\"icon-feed\"></span>RSS</a></li>\r\n</ul>\r\n<p>Also check out the <a href=\"https://discuss.python.org/\">Discussions on Python.org</a></p>", "content_markup_type": "html", - "_content_rendered": "<h2 class=\"widget-title\"><span class=\"blog-name\">Python Insider</span> Subscriptions</h2>\r\n<p>Subscribe to Python Insider via:</p>\r\n<ul class=\"subscription-channels menu\">\r\n <li><a href=\"http://feeds.feedburner.com/PythonInsider\"><span aria-hidden=\"true\" class=\"icon-feed\"></span>RSS</a></li>\r\n <li><a href=\"https://twitter.com/pythoninsider\"><span aria-hidden=\"true\" class=\"icon-twitter\"></span>Twitter</a></li>\r\n</ul>\r\n<p>Also check out the <a href=\"https://mail.python.org/pipermail/python-dev/\">Python-Dev mailing list</a></p>" + "_content_rendered": "<h2 class=\"widget-title\"><span class=\"blog-name\">Python Insider</span> Subscriptions</h2>\r\n<p>Subscribe to Python Insider via:</p>\r\n<ul class=\"subscription-channels menu\">\r\n <li><a href=\"https://blog.python.org/feeds/posts/default?alt=rss\"><span aria-hidden=\"true\" class=\"icon-feed\"></span>RSS</a></li>\r\n</ul>\r\n<p>Also check out the <a href=\"https://discuss.python.org/\">Discussions on Python.org</a></p>" } }, { From 7cfd705dc9a91f53b0383d57765989130c1e849f Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:06:56 +0200 Subject: [PATCH 231/235] Fix updating the supernav downloads (#2842) --- downloads/models.py | 9 +++---- downloads/tests/test_models.py | 46 +++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/downloads/models.py b/downloads/models.py index 0a0d0e525..d97f42f33 100644 --- a/downloads/models.py +++ b/downloads/models.py @@ -175,16 +175,13 @@ def update_supernav(): if latest_pymanager: data['pymanager'] = latest_pymanager.download_file_for_os(o.slug) - python_files.append(data) + # Only include OSes that have at least one download file + if data['python3'] or data['pymanager']: + python_files.append(data) if not python_files: return - if not all(f['python3'] or f['pymanager'] for f in python_files): - # We have a latest Python release, different OSes, but don't have release - # files for the release, so return early. - return - content = render_to_string('downloads/supernav.html', { 'python_files': python_files, 'last_updated': timezone.now(), diff --git a/downloads/tests/test_models.py b/downloads/tests/test_models.py index 1f260e08a..4d9918904 100644 --- a/downloads/tests/test_models.py +++ b/downloads/tests/test_models.py @@ -157,7 +157,7 @@ def test_update_supernav(self): release=self.python_3, slug=slug, name='Python 3.10', - url='/ftp/python/{}.zip'.format(slug), + url=f'/ftp/python/{slug}.zip', download_button=True, ) @@ -186,3 +186,47 @@ def test_update_supernav(self): self.assertIn('class="download-os-windows"', content) self.assertIn('pymanager-25.0.msix', content) self.assertIn('python3.10-windows.zip', content) + + def test_update_supernav_skips_os_without_files(self): + """Test that update_supernav works when an OS has no download files. + + Regression test for a bug where adding an OS (like Android) without + any release files would cause update_supernav to silently abort, + leaving the supernav showing outdated version information. + """ + # Arrange + from ..models import OS, update_supernav + from boxes.models import Box + + # Create an OS without any release files + OS.objects.create(name="Android", slug="android") + + # Create download files for other operating systems + for os, slug in [ + (self.osx, "python3.10-macos"), + (self.linux, "python3.10-linux"), + (self.windows, "python3.10-windows"), + ]: + ReleaseFile.objects.create( + os=os, + release=self.python_3, + slug=slug, + name="Python 3.10", + url=f"/ftp/python/{slug}.zip", + download_button=True, + ) + + # Act + update_supernav() + + # Assert: verify supernav was updated + box = Box.objects.get(label="supernav-python-downloads") + content = box.content.rendered + + # OSes with files should be present + self.assertIn('class="download-os-windows"', content) + self.assertIn('class="download-os-macos"', content) + self.assertIn('class="download-os-linux"', content) + + # Android (no files) should not be present + self.assertNotIn("android", content.lower()) From 7e43e012032cb6b13f31f458209b6e7224c2a715 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:24:32 +0200 Subject: [PATCH 232/235] Improve accessibility: wrap logo in div not H1 (#2844) --- static/sass/style.css | 1 - static/sass/style.scss | 2 +- templates/base.html | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/static/sass/style.css b/static/sass/style.css index 9c5cb26e3..bf81a6e0c 100644 --- a/static/sass/style.css +++ b/static/sass/style.css @@ -1078,7 +1078,6 @@ h2.not-column { text-align: center; padding: .75em 1em; } -/*h1*/ .site-headline { color: white; margin: 0.15em auto 0.2em; } diff --git a/static/sass/style.scss b/static/sass/style.scss index 97963a5b9..62fe23094 100644 --- a/static/sass/style.scss +++ b/static/sass/style.scss @@ -411,7 +411,7 @@ h2.not-column { } } -/*h1*/ .site-headline { +.site-headline { color: $white; margin: 0.15em auto 0.2em; diff --git a/templates/base.html b/templates/base.html index c12e87b6f..593bb2e3e 100644 --- a/templates/base.html +++ b/templates/base.html @@ -185,9 +185,9 @@ <header class="main-header" role="banner"> <div class="container"> - <h1 class="site-headline"> + <div class="site-headline"> {% block section-logo %}<a href="/"><img class="python-logo" src="{{ STATIC_URL }}img/python-logo.png" alt="python™"></a>{% endblock %} - </h1> + </div> <div class="options-bar-container do-not-print"> <a href="https://donate.python.org/" class="donate-button">Donate</a> From e4c418eb7f57c638ee5dc100bafe14470723cc2d Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:37:47 +0200 Subject: [PATCH 233/235] Upgrade three dependencies that trigger pkg_resources removal warning (#2833) --- base-requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base-requirements.txt b/base-requirements.txt index 428c85c60..0b6338c3e 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -23,7 +23,7 @@ celery[redis]==5.4.0 django-celery-beat==2.5.0 # TODO: We may drop 'django-imagekit' completely. django-imagekit==5.0 # 5.0 is first version that supports Django 4.2 -django-haystack==3.2.1 +django-haystack==3.3.0 elasticsearch>=7,<8 # TODO: 0.14.0 only supports Django 1.8 and 1.11. django-tastypie==0.14.7 # 0.14.6 is first version that supports Django 4.2 @@ -44,9 +44,9 @@ djangorestframework==3.14.0 # 3.14.0 is first version that supports Django 4.1, django-filter==2.4.0 django-ordered-model==3.7.4 django-widget-tweaks==1.5.0 -django-countries==7.2.1 +django-countries==8.2.0 num2words==0.5.13 -django-polymorphic==3.1.0 # 3.1.0 is first version that supports Django 4.0, unsure if it fully supports 4.2 +django-polymorphic==4.1.0 sorl-thumbnail==12.11.0 django-extensions==3.2.3 django-import-export==2.7.1 From 6afea27471d2de3fcd82ef83952577bd43212c2d Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:48:59 +0200 Subject: [PATCH 234/235] Run django-upgrade and linting on CI (#2820) Co-authored-by: Jacob Coffee <jacob@z7x.org> --- .github/workflows/lint.yml | 24 ++++++++++++++++++++ .pre-commit-config.yaml | 34 +++++++++++++++++++++++++++++ pydotorg/urls.py | 6 ++--- sponsors/admin.py | 2 +- successstories/tests/test_models.py | 2 +- 5 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..69c6415cf --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,24 @@ +name: Lint + +on: [push, pull_request, workflow_dispatch] + +permissions: {} + +env: + FORCE_COLOR: 1 + RUFF_OUTPUT_FORMAT: github + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + + - uses: actions/setup-python@v6 + with: + python-version: "3.x" + + - uses: j178/prek-action@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..55743f90d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,34 @@ +repos: + - repo: https://github.com/adamchainz/django-upgrade + rev: 1.29.1 + hooks: + - id: django-upgrade + args: [--target-version=4.2] + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-case-conflict + - id: check-merge-conflict + - id: check-json + - id: check-yaml + - id: debug-statements + + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.34.0 + hooks: + - id: check-dependabot + - id: check-github-workflows + + - repo: https://github.com/rhysd/actionlint + rev: v1.7.7 + hooks: + - id: actionlint + + - repo: meta + hooks: + - id: check-hooks-apply + - id: check-useless-excludes + +ci: + autoupdate_schedule: quarterly diff --git a/pydotorg/urls.py b/pydotorg/urls.py index dbcbcd888..06da1ecb8 100644 --- a/pydotorg/urls.py +++ b/pydotorg/urls.py @@ -19,9 +19,9 @@ path('', views.IndexView.as_view(), name='home'), re_path(r'^_health/?', views.health, name='health'), path('authenticated', views.AuthenticatedView.as_view(), name='authenticated'), - re_path(r'^humans.txt$', TemplateView.as_view(template_name='humans.txt', content_type='text/plain')), - re_path(r'^robots.txt$', TemplateView.as_view(template_name='robots.txt', content_type='text/plain')), - re_path(r'^funding.json$', views.serve_funding_json, name='funding_json'), + path('humans.txt', TemplateView.as_view(template_name='humans.txt', content_type='text/plain')), + path('robots.txt', TemplateView.as_view(template_name='robots.txt', content_type='text/plain')), + path('funding.json', views.serve_funding_json, name='funding_json'), path('shell/', TemplateView.as_view(template_name="python/shell.html"), name='shell'), # python section landing pages diff --git a/sponsors/admin.py b/sponsors/admin.py index dc7278c08..f6849c4d8 100644 --- a/sponsors/admin.py +++ b/sponsors/admin.py @@ -201,6 +201,7 @@ def get_prepopulated_fields(self, request, obj=None): return {'slug': ['name']} return {} + @admin.display(description="Revenue split") def get_benefit_split(self, obj: SponsorshipPackage) -> str: colors = [ "#ffde57", # Python Gold @@ -223,7 +224,6 @@ def get_benefit_split(self, obj: SponsorshipPackage) -> str: html = f"<div style='{style}'>{''.join(spans)}</div>" return mark_safe(html) - get_benefit_split.short_description = "Revenue split" class SponsorContactInline(admin.TabularInline): diff --git a/successstories/tests/test_models.py b/successstories/tests/test_models.py index 418d27062..f88f0ff36 100644 --- a/successstories/tests/test_models.py +++ b/successstories/tests/test_models.py @@ -21,7 +21,7 @@ def test_draft(self): def test_featured(self): featured_stories = Story.objects.featured() expected_repr = [f'<Story: {self.story3.name}>'] - self.assertQuerysetEqual(featured_stories, expected_repr, transform=repr) + self.assertQuerySetEqual(featured_stories, expected_repr, transform=repr) def test_get_admin_url(self): self.assertEqual(self.story1.get_admin_url(), From 047d3b214bc9a1081c8a3569605a8a0bec51ccf8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 14:01:42 -0600 Subject: [PATCH 235/235] chore(deps): bump django-allauth from 64.2.1 to 65.13.0 (#2854) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- base-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base-requirements.txt b/base-requirements.txt index 0b6338c3e..149093594 100644 --- a/base-requirements.txt +++ b/base-requirements.txt @@ -36,7 +36,7 @@ requests>=2.26.0 django-honeypot==1.0.4 # 1.0.4 is first version that supports Django 4.2 django-markupfield==2.0.1 -django-allauth==64.2.1 +django-allauth==65.13.0 django-waffle==2.2.1