Skip to content

Instantly share code, notes, and snippets.

@simonw
Last active July 30, 2022 19:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simonw/027408c5df8a579053957ceaaef3a144 to your computer and use it in GitHub Desktop.
Save simonw/027408c5df8a579053957ceaaef3a144 to your computer and use it in GitHub Desktop.
Scraping PSF board resolutions from https://www.python.org/psf/records/board/resolutions/
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "ad0e844c",
"metadata": {},
"source": [
"# Scraping PSF board resolutions\n",
"\n",
"https://www.python.org/psf/records/board/resolutions/\n",
"\n",
"This scraper gets most but not all of them, due to insconsistencies in how some of them are formatted.\n",
"\n",
"There are 152 that could not be parsed - a bit of extra human data cleanup could fix those too."
]
},
{
"cell_type": "code",
"execution_count": 147,
"id": "e834ddde",
"metadata": {},
"outputs": [],
"source": [
"from bs4 import BeautifulSoup as Soup\n",
"import httpx\n",
"from dateutil.parser import parse, ParserError\n",
"import re"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "72da13aa",
"metadata": {},
"outputs": [],
"source": [
"html = httpx.get(\"https://www.python.org/psf/records/board/resolutions/\").text"
]
},
{
"cell_type": "code",
"execution_count": 140,
"id": "2fda99bd",
"metadata": {},
"outputs": [],
"source": [
"# Fix one bit of the HTML that breaks the parser\n",
"html = html.replace('<div class=\"section\" id=\"approved-10-0-0-by-irc-vote-8-june-2015\">', '')\n",
"html = html.replace(\n",
" '<h1>Approved, 10-0-0 by IRC vote, 8 June 2015.</h1>',\n",
" '<p>Approved, 10-0-0 by IRC vote, 8 June 2015.</p>'\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 141,
"id": "18e45bb4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1806"
]
},
"execution_count": 141,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"soup = Soup(html)\n",
"blockquotes = soup.select(\"article > blockquote\"); len(blockquotes)"
]
},
{
"cell_type": "code",
"execution_count": 142,
"id": "5ca75c15",
"metadata": {},
"outputs": [],
"source": [
"pairs = [(bq.text.strip(), bq.find_next('p').text.strip()) for bq in blockquotes]"
]
},
{
"cell_type": "code",
"execution_count": 143,
"id": "edd42b39",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(('RESOLVED, that the Python Software Foundation Board grant $10,000 USD to the PyCon DE & PyData Berlin 2022 event happening in Berlin, Germany on April 11, 2022.',\n",
" 'Approved, 10-0-0, 2022-03-22'),\n",
" ('RESOLVED, that the Python Software Foundation Grants Work Group grant $1000 USD to the Data Science Research Perú training program happening in Lima, Peru April 6, 2019',\n",
" 'Approved 7-0-0, March 25, 2019'),\n",
" ('RESOLVED, that the principal office of the Corporation shall be\\n\\n\\nThe Python Software Foundation\\n7700 Leesburg Pike, Suite 208\\nFalls Church, VA 22043\\nU.S.A.',\n",
" 'RESOLVED, that the principal office of the Corporation shall be'))"
]
},
"execution_count": 143,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pairs[0], pairs[342], pairs[-1]"
]
},
{
"cell_type": "code",
"execution_count": 44,
"id": "b9787449",
"metadata": {},
"outputs": [],
"source": [
"resolutions = [p[1] for p in pairs]"
]
},
{
"cell_type": "code",
"execution_count": 145,
"id": "d0bcb4e1",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Approved, 10-0-0, 2022-03-22\n",
"Denied, 0-9-0, 2022-03-22\n",
"Approved, 9-0-0, 2022-03-22\n",
"Approved, 9-0-0, 2022-03-22\n",
"Approved, 4-0-0, 2022-03-11\n",
"Approved, 7-0-0, 2022-03-11\n",
"Approved, 8-0-0, 2022-02-25\n",
"Approved, 10-0-1, 2022-02-24\n",
"Denied, 0-7-0, 2022-02-17\n",
"Approved, 4-0-0, 2022-02-12\n",
"Approved, 10-0-0, 2022-01-25\n",
"Approved, 9-0-1, 2022-01-25\n",
"Approved, 7-0-3, 2022-01-25\n",
"Approved, 9-0-1, 2022-01-25\n",
"Approved, 9-0-1, 2022-01-25\n",
"Approved, 7-0-0, 2022-01-12\n",
"Denied; 0-8-0, 2022-01-12\n",
"Approved, 7-0-0, 2021-12-13\n",
"Denied, 0-7-0, 2021-12-13\n",
"Approved, 8-0-0, 2021-12-13\n",
"Approved unanimously by IRC vote Sep 9, 2003.\n",
"Approved unanimously by IRC vote Aug 12, 2003.\n",
"Approved by 4/0/2 by IRC vote Aug 12, 2003.\n",
"Approved unanimously by IRC vote Aug 12, 2003.\n",
"Approved unanimously at the board meeting on March 11, 2003.\n",
"Approved unanimously at the board meeting on February 11, 2003.\n",
"Approved unanimously at the board meeting on October 8, 2002.\n",
"Approved by a 4-0-1 vote at the board meeting on September 10, 2002.\n",
"Approved by a 4-0-1 vote at the board meeting on September 10, 2002.\n",
"Approved unanimously at the board meeting on August 13, 2002.\n",
"In order to\n",
"Approved by unanimous written consent on February 19, 2002.\n",
"RESOLVED, that PSF accepts the membership application forms, as shown\n",
"in the attachment (one form for nominated members, and a second form\n",
"for sponsor members).\n",
"RESOLVED, the the principal office of the PSF shall be\n",
"Approved by unanimous written consent on September 14, 2001.\n",
"Approved by unanimous written consent on September 14, 2001.\n",
"Approved by unanimous written consent on September 14, 2001.\n",
"Approved by unanimous written consent on September 14, 2001.\n",
"Approved by unanimous written consent on April 14, 2001.\n",
"RESOLVED, that the principal office of the Corporation shall be\n"
]
}
],
"source": [
"# Sample what those resolutions look like:\n",
"print(\"\\n\".join(resolutions[:20] + resolutions[-20:]))"
]
},
{
"cell_type": "code",
"execution_count": 146,
"id": "4d5ef187",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"datetime.datetime(2019, 7, 30, 0, 0)"
]
},
"execution_count": 146,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check I can fuzzy date parse\n",
"parse('Approved July 30, 2019', fuzzy=True)"
]
},
{
"cell_type": "code",
"execution_count": 148,
"id": "a91b3537",
"metadata": {},
"outputs": [],
"source": [
"# Rexeg to extract 7-0-0 style vote counts\n",
"votes_re = re.compile(r'\\b(?P<yes>\\d{1,2})-(?P<no>\\d{1,2})-(?P<abstain>\\d{1,2})\\b')"
]
},
{
"cell_type": "code",
"execution_count": 149,
"id": "d9a2352d",
"metadata": {},
"outputs": [],
"source": [
"s = 'Approved 7-0-0 at Jan 11, 2005 IRC meeting'"
]
},
{
"cell_type": "code",
"execution_count": 128,
"id": "a82e461f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<re.Match object; span=(9, 14), match='7-0-0'>"
]
},
"execution_count": 128,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"votes_re.search(s)"
]
},
{
"cell_type": "code",
"execution_count": 150,
"id": "fa2df68f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"datetime.datetime(2005, 1, 11, 0, 0)"
]
},
"execution_count": 150,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# If I remove the votes I can then use fuzzy date parsing to get the date\n",
"parse(votes_re.sub('', s), fuzzy=True)"
]
},
{
"cell_type": "code",
"execution_count": 151,
"id": "a70c44a3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'yes': '7', 'no': '0', 'abstain': '0'}"
]
},
"execution_count": 151,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"votes_re.search(s).groupdict()"
]
},
{
"cell_type": "code",
"execution_count": 161,
"id": "cf945280",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<re.Match object; span=(15, 22), match='$44,009'>"
]
},
"execution_count": 161,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dollars_re = re.compile(r'(\\$[\\d,\\.]+)')"
]
},
{
"cell_type": "code",
"execution_count": 152,
"id": "cc75295c",
"metadata": {},
"outputs": [],
"source": [
"# Can I use the first word to decide if something was approved or denied?\n",
"first_words = set(r.split()[0].lower() for r in resolutions)"
]
},
{
"cell_type": "code",
"execution_count": 153,
"id": "57095af7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'approved',\n",
" 'approved,',\n",
" 'approved.',\n",
" 'august',\n",
" 'chair:',\n",
" 'denied',\n",
" 'denied,',\n",
" 'denied;',\n",
" 'in',\n",
" 'president:',\n",
" 'resolution',\n",
" 'resolved,',\n",
" 'september',\n",
" 'this',\n",
" 'whereas'}"
]
},
"execution_count": 153,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"first_words"
]
},
{
"cell_type": "code",
"execution_count": 169,
"id": "dbda2db1",
"metadata": {},
"outputs": [],
"source": [
"def to_resolution(blockquote):\n",
" # Returns (True, {resolution} if it works, False, \"reason\" if it fails)\n",
" info = {}\n",
" info[\"text\"] = blockquote.text.strip()\n",
" votes = blockquote.find_next('p').text.strip()\n",
" match = votes_re.search(votes)\n",
" votes_lower = votes.lower()\n",
" if not (votes_lower.startswith('approved') or votes_lower.startswith(\"denied\")):\n",
" return False, \"Did not start with approved or denied: {}\".format(votes)\n",
" info[\"resolution\"] = \"Approved\" if votes_lower.startswith(\"approved\") else \"Denied\"\n",
" if not match:\n",
" return False, \"Could not find x-x-x votes in: {}\".format(votes)\n",
" info.update({k: int(v) for k, v in match.groupdict().items()})\n",
" # Remove x-x-x so we can fuzzy date parse\n",
" votes = votes_re.sub('', votes)\n",
" try:\n",
" date = parse(votes, fuzzy=True)\n",
" except ParserError:\n",
" return False, \"Could not parse date in: {}\".format(votes)\n",
" info[\"date\"] = str(date.date())\n",
" # Are there any dollars in there?\n",
" dollars_match = dollars_re.search(info[\"text\"])\n",
" info[\"dollars\"] = \"\"\n",
" if dollars_match:\n",
" s = dollars_match.group(1).replace('$', '').replace(',', '')\n",
" s = s.rstrip('.')\n",
" if s:\n",
" info[\"dollars\"] = float(s)\n",
" return True, info\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 170,
"id": "9220aa3a",
"metadata": {},
"outputs": [],
"source": [
"good = []\n",
"bad = []\n",
"for blockquote in blockquotes:\n",
" ok, info = to_resolution(blockquote)\n",
" [bad, good][int(ok)].append(info)"
]
},
{
"cell_type": "code",
"execution_count": 171,
"id": "d540cd97",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1654, 152)"
]
},
"execution_count": 171,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(good), len(bad)"
]
},
{
"cell_type": "code",
"execution_count": 172,
"id": "98a76654",
"metadata": {},
"outputs": [],
"source": [
"import csv, io"
]
},
{
"cell_type": "code",
"execution_count": 174,
"id": "e7f9c58b",
"metadata": {},
"outputs": [],
"source": [
"s = io.StringIO()\n",
"writer = csv.DictWriter(s, fieldnames=[\"text\", \"date\", \"resolution\", \"yes\", \"no\", \"abstain\", \"dollars\"])\n",
"writer.writeheader()\n",
"writer.writerows(good)"
]
},
{
"cell_type": "code",
"execution_count": 175,
"id": "74d03b07",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"337002"
]
},
"execution_count": 175,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"open(\"/tmp/blah.txt\", \"w\").write(s.getvalue())"
]
},
{
"cell_type": "code",
"execution_count": 158,
"id": "9fc62a09",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Could not find x-x-x votes in: Approved by director allowance, 2021-09-27\n",
"Could not find x-x-x votes in: Approved via board director allowance, April 12, 2021\n",
"Could not find x-x-x votes in: Approved December 22, 2021\n",
"Could not find x-x-x votes in: Approved November 30, 2020\n",
"Could not find x-x-x votes in: Approved November 24, 2020\n",
"Could not find x-x-x votes in: Approved June 30, 2020\n",
"Could not parse date in: Approved \n",
"Could not find x-x-x votes in: Approved March 10, 2020\n",
"Could not find x-x-x votes in: Approved March 10, 2020\n",
"Could not find x-x-x votes in: Approved March 10, 2020\n",
"Could not find x-x-x votes in: Approved August 23, 2019\n",
"Could not find x-x-x votes in: Approved August 21, 2019\n",
"Could not find x-x-x votes in: Approved August 21, 2019\n",
"Could not find x-x-x votes in: Approved August 13, 2019\n",
"Could not find x-x-x votes in: Approved 7-0-, August 6, 2019\n",
"Did not start with approved or denied: RESOLVED, that the Python Software Foundation Grants Work Group grant $700 USD to the PyDay La Paz event happening in La Paz, Bolivia August 10, 2019\n",
"Could not find x-x-x votes in: Approved 6-0--0, July 19, 2019\n",
"Could not find x-x-x votes in: Approved March 25, 2019\n",
"Could not find x-x-x votes in: Approved March 4, 2019\n",
"Could not find x-x-x votes in: Approved December 18, 2018\n",
"Could not find x-x-x votes in: Approved November 5, 2018\n",
"Could not find x-x-x votes in: Approved October 31, 2018\n",
"Could not find x-x-x votes in: Approved October 30, 2018\n",
"Did not start with approved or denied: September 4, 2018\n",
"Did not start with approved or denied: August 29, 2018\n",
"Did not start with approved or denied: RESOLVED, that the Python Software Foundation Grants Work Group grant $2000 USD to the first PyLadies Conference happening in São Paulo, Brazil October 16, 2018\n",
"Did not start with approved or denied: President: Guido van Rossum\n",
"Secretary: Ewa Jodlowska\n",
"Assistant Secretary: Betsy Waliszewski\n",
"Treasurer: Kurt Kaiser\n",
"PyCon US Chair: Ernest W. Durbin III\n",
"Did not start with approved or denied: Chair: Naomi Ceder\n",
"Vice Chair/Chair-Elect: Jackie Kazil\n",
"Vice Chair: Thomas Wouters, Van Lindberg\n",
"Communications Co-Chairs: Lorena Mesa, Marlene Mhangami\n",
"General Counsel: Van Lindberg\n",
"Could not find x-x-x votes in: Approved by Director's Allowance on June 25, 2018\n",
"Could not find x-x-x votes in: Approved May 31, 2018\n",
"Could not find x-x-x votes in: Approved May 31, 2018\n",
"Could not find x-x-x votes in: Approved April 9, 2018\n",
"Could not find x-x-x votes in: Approved April 4, 2018\n",
"Could not find x-x-x votes in: Approved 8-0-, March 9, 2018\n",
"Did not start with approved or denied: RESOLVED, that the Python Software Foundation appoint the following Officers for the 2017/2018 term:\n",
"Could not find x-x-x votes in: Approved June 7, 2017\n",
"Could not find x-x-x votes in: Approved 8-0-, February 28, 2017\n",
"Could not find x-x-x votes in: Approved by director's allowance February 3, 2017.\n",
"Could not find x-x-x votes in: Approved through directors' allowance on May 19, 2016.\n",
"Could not find x-x-x votes in: Approved on April 15, 2016\n",
"Could not find x-x-x votes in: Approved March 24, 2016\n",
"Could not find x-x-x votes in: Approved March 14, 2016\n",
"Could not find x-x-x votes in: Approved on February 26, 2016\n",
"Could not find x-x-x votes in: Approved 8–1-0 on February 25, 2016.\n",
"Could not find x-x-x votes in: Approved by the Scientific Python Working Group January 8, 2016.\n",
"Could not find x-x-x votes in: Approved December 1, 2015.\n",
"Could not find x-x-x votes in: Approved November 19, 2015\n",
"Could not find x-x-x votes in: Approved November 12, 2015.\n",
"Could not find x-x-x votes in: Approved by the Scientific Python Work Group on October 19, 2015\n",
"Did not start with approved or denied: Resolution denied 1-4-2 by IRC vote, October 12, 2015\n",
"Could not find x-x-x votes in: Approved per Diana Clarke on October 2, 2015.\n",
"Could not find x-x-x votes in: Approved by Scientific Python Work Group, Aug 27, 2015.\n",
"Did not start with approved or denied: RESOLVED, that the Python Software Foundation adopt these mailing list actions to further support the Python Software Foundation bylaws, improve governance, and provide greater transparency for the membership:\n",
"Could not find x-x-x votes in: Approved via email vote, 8 April, 2015.\n",
"Could not find x-x-x votes in: Denied, 1–5-0 by IRC vote, 17 October 2014.\n",
"Could not find x-x-x votes in: Denied, 0–6-0 by IRC vote, 17 October 2014.\n",
"Could not find x-x-x votes in: Approved, 7–0-0 by IRC vote, 01 October 2014.\n",
"Could not find x-x-x votes in: Approved, 6–0-0 by IRC vote, 18 July 2014.\n",
"Could not find x-x-x votes in: Approved, 6–0-0 by IRC vote, 20 June 2014.\n",
"Could not find x-x-x votes in: Approved, 8–0-0 by IRC vote, 06 June 2014.\n",
"Could not find x-x-x votes in: Approved, 9–0-0 by IRC vote, 05 May 2014.\n",
"Could not find x-x-x votes in: Approved, 7–0-0 by IRC vote, 28 March 2014.\n",
"Could not find x-x-x votes in: Approved, 5–0-3 by voice via call because the IRC server stopped working, 28 February 2014.\n",
"Could not parse date in: Approved by email vote.\n",
"Did not start with approved or denied: This resolution was presented on 16 January, 2013, but was postponed until a later time because more details were necessary from T. Waldmann. On 17 January it was decided that two board members would offer their \"director allowance\" towards T. Waldmann's proposal. Marc-Andre Lemburg and Jesse Noller contributed $500 USD each.\n",
"Did not start with approved or denied: This motion was postponed on 18 June 2012, then Approved 5-3-2 by IRC vote, 25 June 2012\n",
"Did not start with approved or denied: RESOLVED, that the following people be appointed as officers until\n",
"the next Board election (or their resignation).\n",
"Did not start with approved or denied: RESOLVED, that the respective current chairmen of the following\n",
"active project management committees be reappointed as chairman of the\n",
"committee for the 2012/2013 term and that each chairman shall appoint\n",
"the members of the their committee for the term:\n",
"Did not start with approved or denied: RESOLVED, that the board repeals the previously passed resolution of\n",
"June 12, 2006 which states \"until further notice, the Officers of the\n",
"Corporation may spend up to USD 500 per expense without prior Board\n",
"approval, but subject to prompt reporting to the Board, and consistent\n",
"with the mission statement and requirements of maintaining our status as\n",
"a 501(c)3 non-profit.\"\n",
"Did not start with approved or denied: RESOLVED, that the following people be appointed as officers until the\n",
"next Board election (or their resignation).\n",
"Did not start with approved or denied: RESOLVED, that the PSF Board of Directors may adopt binding\n",
"resolutions between regularly scheduled full-board meetings by\n",
"email, subject to the following procedures:\n",
"Could not find x-x-x votes in: Approved by IRC vote, 18 October 2010.\n",
"Could not parse date in: Approved, .\n",
"Did not start with approved or denied: RESOLVED, that the PSF offers a grant of US$2500 to the organizers of\n",
"the\n",
"PyCon Argentina & Python Brasil 2010 conferences to be held October 2010, to\n",
"Did not start with approved or denied: RESOLVED, that the Board of Directors implement the creation of a new\n",
"membership class, called \"honorary associate members\", as requested and\n",
"approved by the members at the 2010 first annual PSF members meeting, as\n",
"follows:\n",
"Did not start with approved or denied: RESOLVED, that the Infrastructure Committee may contract companies\n",
"affiliated with IC members under the condition that:\n",
"Did not start with approved or denied: RESOLVED, that expense receipts and invoices for any PSF funded\n",
"activity or equipment must be sent to the PSF Treasurer within 90 days\n",
"of date of receipt or invoice. Late filings will not be processed or\n",
"refunded, unless prior arrangements\n",
"have been made with the PSF Board, with a summary sent to psf@python.org.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote (3 abstentions), 22 February 2010.\n",
"Did not start with approved or denied: RESOLVED, that the PSF adopt the following diversity statement,\n",
"and publish it with links to ancillary materials maintained by\n",
"members of the diversity list:\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, August 31, 2009.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote (one abstention), June 25, 2009.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, June 9, 2009.\n",
"Did not start with approved or denied: RESOLVED, that David Goodger is authorized to obligate the PSF\n",
"under the Conference Technology Enhancements, Inc. (CTE) Housing &\n",
"Meeting Planning contracts ([1], [2]) for PyCon 2010.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, May 14, 2009.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, May 14, 2009.\n",
"Could not parse date in: Approved, .\n",
"Could not find x-x-x votes in: Approved by unanimous email vote (1 abstention), January 26, 2009.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, November 14, 2008.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, November 14, 2008.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote (1 abstention), November 14, 2008.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, June 26, 2008.\n",
"Did not start with approved or denied: RESOLVED, that the PyCon Chair (David Goodger) is authorized to\n",
"obligate the PSF under the Conference Technology Enhancements,\n",
"Inc. (CTE) Housing & Meeting Planning contracts ([1], [2]) for\n",
"PyCon 2009.\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, March 24, 2008.\n",
"Did not start with approved or denied: WHEREAS the role of the Conference Committee is to advise the\n",
"PyCon Chair and the PyCon organizing committee, and\n",
"Did not start with approved or denied: RESOLVED, that $2000 will be made available for issuing awards to\n",
"the following Python community members for their dedication to\n",
"Python through volunteerism:\n",
"Did not start with approved or denied: RESOLVED, that the Foundation institute an awards program to\n",
"provide recognition for services which further the Foundation's\n",
"mission. Nominations for awards can be made by any member.\n",
"Awards must be unanimously approved by the Board, and may take the\n",
"form of either:\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, November 27, 2007.\n",
"Did not start with approved or denied: RESOLVED, that the mailing address of the PSF shall be:\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, September 17, 2007.\n",
"Did not start with approved or denied: RESOLVED, that the mailing address of the PSF shall be:\n",
"Could not find x-x-x votes in: Approved by unanimous email vote, January 3, 2007.\n",
"Did not start with approved or denied: RESOLVED, that the PSF will fund Jeff Rush as Advocacy\n",
"Coordinator for a period of 6 months effective August 15th, 2006\n",
"for the work outlined in his proposal at:\n",
"Did not start with approved or denied: RESOLVED, that the PSF mission statement approved by\n",
"unanimous written consent on March 2, 2002, and published on the web\n",
"at http://python.org/psf/mission,\n",
"be revised as follows, to take effect on August 31, 2006.\n",
"Did not start with approved or denied: WHEREAS some of the offices held by officers of the PSF\n",
"require substantial time commitment, on the order of hundreds of\n",
"hours per year,\n",
"Did not start with approved or denied: RESOLVED, that the PSF adopt the policies contained in version\n",
"1.03 of the draft weblog policy [1] for managing access and\n",
"editorial content for the PSF weblog [2].\n",
"Could not find x-x-x votes in: Approved by unanimous email vote May 31 2005\n",
"Could not find x-x-x votes in: Approved by unanimous email vote May 06 2005\n",
"Could not find x-x-x votes in: Approved by unanimous email vote Apr 04 2005\n",
"Did not start with approved or denied: RESOLVED, that the PSF accepts the recommendation of the grants\n",
"committee to execute the following three projects in 2005:\n",
"Did not start with approved or denied: RESOLVED,\n",
"that the PSF asks past and future contributors of\n",
"Python to fill out and send in the contributor form currently\n",
"shown at:\n",
"Could not find x-x-x votes in: Approved unanimously via email vote on October 22, 2004\n",
"Could not find x-x-x votes in: Approved unanimously via email vote on Sept. 22, 2004\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote August 10, 2004\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote August 10, 2004\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote June 15, 2004.\n",
"Did not start with approved or denied: RESOLVED, that the principal office and official headquarters of the PSF\n",
"shall be:\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote May 11, 2004.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote April 13th, 2004.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote April 13th, 2004.\n",
"Did not start with approved or denied: RESOLVED, that a Public Relations (PR) Committee is formed,\n",
"with Tim Parkin, Kevin Altis, Aahz, Barry Warsaw, Andrew\n",
"Kuchling, and Steve Holden as initial members, and Steve Holden\n",
"as the initial chairman and Vice President of Public Relations,\n",
"that the PR Committee replaces and subsumes the activities of\n",
"the previously disbanded Web Committee, and that the PR Committee\n",
"shall:\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote April 13th, 2004.\n",
"Could not find x-x-x votes in: Approved unanimously by email vote on February 4, 2004.\n",
"Did not start with approved or denied: WHEREAS the PSF Treasurer has identified the following expenses\n",
"related to PyCon 2004:\n",
"Could not find x-x-x votes in: Approved with 4/2/0 by IRC vote Jan 13, 2004\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Jan 13, 2004.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Jan 13, 2004.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Dec 9, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Oct 14, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Oct 14, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Oct 14, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Oct 14, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Oct 14, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Sep 9, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Sep 9, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Sep 9, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Aug 12, 2003.\n",
"Could not find x-x-x votes in: Approved by 4/0/2 by IRC vote Aug 12, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously by IRC vote Aug 12, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously at the board meeting on March 11, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously at the board meeting on February 11, 2003.\n",
"Could not find x-x-x votes in: Approved unanimously at the board meeting on October 8, 2002.\n",
"Could not find x-x-x votes in: Approved unanimously at the board meeting on August 13, 2002.\n",
"Did not start with approved or denied: In order to\n",
"Could not find x-x-x votes in: Approved by unanimous written consent on February 19, 2002.\n",
"Did not start with approved or denied: RESOLVED, that PSF accepts the membership application forms, as shown\n",
"in the attachment (one form for nominated members, and a second form\n",
"for sponsor members).\n",
"Did not start with approved or denied: RESOLVED, the the principal office of the PSF shall be\n",
"Could not find x-x-x votes in: Approved by unanimous written consent on September 14, 2001.\n",
"Could not find x-x-x votes in: Approved by unanimous written consent on September 14, 2001.\n",
"Could not find x-x-x votes in: Approved by unanimous written consent on September 14, 2001.\n",
"Could not find x-x-x votes in: Approved by unanimous written consent on September 14, 2001.\n",
"Could not find x-x-x votes in: Approved by unanimous written consent on April 14, 2001.\n",
"Did not start with approved or denied: RESOLVED, that the principal office of the Corporation shall be\n"
]
}
],
"source": [
"print(\"\\n\".join(bad))"
]
},
{
"cell_type": "code",
"execution_count": 176,
"id": "15539ea8",
"metadata": {},
"outputs": [],
"source": [
"!cat /tmp/blah.txt | pbcopy"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@simonw
Copy link
Author

simonw commented Jul 30, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment