Github messages for voidlinux
 help / color / mirror / Atom feed
* [PR PATCH] WIP: anki: update to 2.1.26
@ 2020-05-23  6:18 fosslinux
  2020-05-23  7:07 ` [PR PATCH] [Updated] " fosslinux
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: fosslinux @ 2020-05-23  6:18 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1565 bytes --]

There is a new pull request by fosslinux against master on the void-packages repository

https://github.com/fosslinux/void-packages anki-2.1.26
https://github.com/void-linux/void-packages/pull/22219

WIP: anki: update to 2.1.26
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust (nightly!), nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.
- anki uses rustup. This is because it and some of its dependencies require archd code (notably pyo3). This is unavoidable, afaict.

Still todo:

- [ ] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [ ] More extensive runtime testing. It opens, but seems to have weird icon issues?
- [ ] Runtime test on musl.

Questions:

- Is there any problems with removing `arch=nocross`?
- Does the rustup stuff look (somewhat) sane?
- Are the patches sane?

A patch file from https://github.com/void-linux/void-packages/pull/22219.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-anki-2.1.26-22219.patch --]
[-- Type: text/x-diff, Size: 16588 bytes --]

From e88132a875c981abbac9216cce895b2b034d8ed0 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:01 +1000
Subject: [PATCH 1/6] python3-mypy: update to 0.770, claim maintainership

---
 srcpkgs/python3-mypy/template | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/python3-mypy/template b/srcpkgs/python3-mypy/template
index 5d7f93d5772..bde1e7f4be6 100644
--- a/srcpkgs/python3-mypy/template
+++ b/srcpkgs/python3-mypy/template
@@ -1,19 +1,18 @@
 # Template file for 'python3-mypy'
 pkgname=python3-mypy
-version=0.761
+version=0.770
 revision=1
 archs=noarch
 wrksrc="mypy-${version}"
 build_style=python3-module
-pycompile_module="mypy"
 hostmakedepends="python3-setuptools"
 depends="python3-mypy_extensions python3-typed-ast python3-typing_extensions"
 short_desc="Optional static typing for Python3"
-maintainer="Orphaned <orphan@voidlinux.org>"
+maintainer="fosslinux <fosslinux@aussies.space>"
 license="MIT"
 homepage="https://github.com/python/mypy"
 distfiles="${PYPI_SITE}/m/mypy/mypy-${version}.tar.gz"
-checksum=85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf
+checksum=8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae
 
 post_install() {
 	vlicense LICENSE

From ae580c7dcc5fa9ee6c2040b185773341a8fdda2b Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:34:38 +1000
Subject: [PATCH 2/6] New package: maturin-0.8.1

---
 .../patches/cross-compile-setup-py.patch      | 14 +++++++++++++
 srcpkgs/maturin/template                      | 21 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 srcpkgs/maturin/patches/cross-compile-setup-py.patch
 create mode 100644 srcpkgs/maturin/template

diff --git a/srcpkgs/maturin/patches/cross-compile-setup-py.patch b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
new file mode 100644
index 00000000000..e57189cb7ab
--- /dev/null
+++ b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
@@ -0,0 +1,14 @@
+--- setup.py	2020-04-30 22:36:01.000000000 +1000
++++ setup.py	2020-05-20 14:31:40.404994499 +1000
+@@ -56,9 +56,9 @@
+                     "(https://www.rust-lang.org/tools/install) and try again"
+                 )
+             subprocess.check_call(
+-                ["cargo", "rustc", "--bin", "maturin", "--", "-C", "link-arg=-s"]
++                ["cargo", "rustc", "--bin", "maturin", "--release", "--target", os.environ["RUST_TARGET"], "--", "-C", "link-arg=-s", "-C", "linker=" + os.environ["CC"].split(" ", 1)[0]]
+             )
+-            source = os.path.join(source_dir, "target", "debug", executable_name)
++            source = os.path.join(source_dir, "target", os.environ["RUST_TARGET"], "release", executable_name)
+         # run this after trying to build with cargo (as otherwise this leaves
+         # venv in a bad state: https://github.com/benfred/py-spy/issues/69)
+         install.run(self)
diff --git a/srcpkgs/maturin/template b/srcpkgs/maturin/template
new file mode 100644
index 00000000000..7eba36204f9
--- /dev/null
+++ b/srcpkgs/maturin/template
@@ -0,0 +1,21 @@
+# Template file for 'maturin'
+pkgname=maturin
+version=0.8.1
+revision=1
+build_style=python3-module
+hostmakedepends="cargo python3-setuptools python3-toml"
+makedepends="rust rust-std llvm9"
+short_desc="Build and publish crates with python bindings"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0, MIT"
+homepage="https://github.com/PyO3/maturin"
+distfiles="https://github.com/PyO3/maturin/archive/v${version}.tar.gz"
+checksum=b72a9885cda3ba4e53906a43aab101acb790622218ade6405b2ddf1ef1461f8f
+
+post_install() {
+	# Dynamic detection of python version
+	PYTHON_VERSION=$(python3 --version | sed "s/^Python //" | rev | sed "s/^[0-9]*.//" | rev)
+	mkdir -p "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	mv "${DESTDIR}/maturin" "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	vlicense license-mit
+}

From 1bd1177a01ea7ce37e08a382eed7597a764ae457 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:25 +1000
Subject: [PATCH 3/6] New package: mypy-protobuf-python-1.13

---
 srcpkgs/mypy-protobuf-python/template | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-python/template

diff --git a/srcpkgs/mypy-protobuf-python/template b/srcpkgs/mypy-protobuf-python/template
new file mode 100644
index 00000000000..391d75f0c9e
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-python/template
@@ -0,0 +1,23 @@
+# Template file for 'mypy-protobuf-python'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-go
+#
+pkgname=mypy-protobuf-python
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_wrksrc=python
+build_style=python3-module
+hostmakedepends="python3-setuptools"
+depends="python3-mypy python3-typing_extensions python3-protobuf protobuf"
+short_desc="Generate mypy stubs from protobufs - Python implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74
+
+post_install() {
+	# We are not windows, remove the batch file
+	rm "${DESTDIR}/usr/bin/protoc_gen_mypy.bat"
+}

From 2005df10d61b46933f28eea0b17e701a09af437b Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:37 +1000
Subject: [PATCH 4/6] New package: mypy-protobuf-go-1.13

---
 .../patches/remote-go-improt.patch            | 11 +++++++++++
 srcpkgs/mypy-protobuf-go/template             | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
 create mode 100644 srcpkgs/mypy-protobuf-go/template

diff --git a/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
new file mode 100644
index 00000000000..300504bc70d
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
@@ -0,0 +1,11 @@
+--- go/src/protoc-gen-mypy/main.go.orig	2020-05-22 11:58:07.760761664 +1000
++++ go/src/protoc-gen-mypy/main.go	2020-05-22 11:58:00.595762190 +1000
+@@ -6,7 +6,7 @@
+ 	"sort"
+ 	"strings"
+ 
+-	"proto/mypy"
++	"github.com/dropbox/mypy-protobuf/go/src/proto/mypy"
+ 
+ 	"github.com/gogo/protobuf/proto"
+ 	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
diff --git a/srcpkgs/mypy-protobuf-go/template b/srcpkgs/mypy-protobuf-go/template
new file mode 100644
index 00000000000..8f00e43d8a8
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/template
@@ -0,0 +1,19 @@
+# Template file for 'mypy-protobuf-go'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-python
+#
+pkgname=mypy-protobuf-go
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_style=go
+go_import_path="github.com/dropbox/mypy-protobuf"
+go_package="${go_import_path}/go/src/protoc-gen-mypy"
+hostmakedepends="git"
+depends="protobuf"
+short_desc="Generate mypy stubs from protobufs - go implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74

From db650873d45635b6983c2d24717e827309303092 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:36 +1000
Subject: [PATCH 5/6] New package: python-stringcase-1.2.0

---
 srcpkgs/python-stringcase/template | 28 ++++++++++++++++++++++++++++
 srcpkgs/python3-stringcase         |  1 +
 2 files changed, 29 insertions(+)
 create mode 100644 srcpkgs/python-stringcase/template
 create mode 120000 srcpkgs/python3-stringcase

diff --git a/srcpkgs/python-stringcase/template b/srcpkgs/python-stringcase/template
new file mode 100644
index 00000000000..849e677c784
--- /dev/null
+++ b/srcpkgs/python-stringcase/template
@@ -0,0 +1,28 @@
+# Template file for 'python-stringcase'
+pkgname=python-stringcase
+version=1.2.0
+revision=1
+wrksrc="stringcase-${version}"
+build_style=python-module
+hostmakedepends="python-devel python3-devel"
+makedepends="${hostmakedepends}"
+depends="python"
+short_desc="String case converter for Python2"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="MIT"
+homepage="https://github.com/okunishinishi/python-stringcase"
+distfiles="${PYPI_SITE}/s/stringcase/stringcase-${version}.tar.gz"
+checksum=48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008
+
+post_install() {
+	vlicense LICENSE
+}
+
+python3-stringcase_package() {
+	depends="python3"
+	short_desc="${short_desc/Python2/Python3}"
+	pkg_install() {
+		vmove usr/lib/python3*
+		vlicense LICENSE
+	}
+}
diff --git a/srcpkgs/python3-stringcase b/srcpkgs/python3-stringcase
new file mode 120000
index 00000000000..53938bd1f0c
--- /dev/null
+++ b/srcpkgs/python3-stringcase
@@ -0,0 +1 @@
+python-stringcase
\ No newline at end of file

From 7b045648ba4caa04579616dff5022d9c65af8114 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:36:21 +1000
Subject: [PATCH 6/6] anki: update to 2.1.26

Has turned into a Bad Build System. Now uses rust nightly, python
(with bindings!), qt5, nodejs... the list goes on. There are quite
a few hacks and the like.
---
 .../anki/patches/rustc-cross-compile.patch    | 11 +++
 srcpkgs/anki/patches/vendored-deps.patch      | 94 +++++++++++++++++++
 srcpkgs/anki/template                         | 58 ++++++++++--
 3 files changed, 157 insertions(+), 6 deletions(-)
 create mode 100644 srcpkgs/anki/patches/rustc-cross-compile.patch
 create mode 100644 srcpkgs/anki/patches/vendored-deps.patch

diff --git a/srcpkgs/anki/patches/rustc-cross-compile.patch b/srcpkgs/anki/patches/rustc-cross-compile.patch
new file mode 100644
index 00000000000..15239ea4cf1
--- /dev/null
+++ b/srcpkgs/anki/patches/rustc-cross-compile.patch
@@ -0,0 +1,11 @@
+--- rspy/Makefile	2020-05-23 12:02:29.758286838 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -69,7 +69,7 @@
+ .build/build: $(DEPS)
+ 	touch ../proto/backend.proto
+ 	${BUILD_VARIABLES} \
+-		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS)
++		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS) --target $(RUST_TARGET)
+    touch $@
+ 
+ check: .build/check
diff --git a/srcpkgs/anki/patches/vendored-deps.patch b/srcpkgs/anki/patches/vendored-deps.patch
new file mode 100644
index 00000000000..1d2bc90ffb1
--- /dev/null
+++ b/srcpkgs/anki/patches/vendored-deps.patch
@@ -0,0 +1,94 @@
+diff -u -r Makefile Makefile
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 18:40:54.345223164 +1000
+@@ -92,7 +92,7 @@
+ 	fi
+ 
+ .PHONY: develop
+-develop: pyenv buildhash prepare
++develop: buildhash prepare
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	for dir in $(DEVEL); do \
+diff -u -r pylib/Makefile pylib/Makefile
+--- pylib/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ pylib/Makefile	2020-05-19 18:50:01.075182994 +1000
+@@ -52,7 +52,7 @@
+ 	python -m black anki/hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks
++BUILD_STEPS := .build/vernum .build/py-proto anki/buildinfo.py .build/hooks
+ 
+ # Checking
+ ######################
+diff -u -r qt/Makefile qt/Makefile
+--- qt/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ qt/Makefile	2020-05-19 18:50:17.520181786 +1000
+@@ -64,7 +64,7 @@
+ 	python -m black aqt/gui_hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
++BUILD_STEPS := .build/vernum .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
+ 
+ # Checking
+ ######################
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 19:01:35.602131965 +1000
+@@ -122,7 +122,7 @@
+ 	@echo "Build complete."
+ 
+ .PHONY: build-rspy
+-build-rspy: pyenv buildhash
++build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+--- Makefile	2020-05-19 19:41:44.191955000 +1000
++++ Makefile	2020-05-19 19:42:21.423952264 +1000
+@@ -124,19 +124,16 @@
+ .PHONY: build-rspy
+ build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+ 
+ .PHONY: build-pylib
+ build-pylib:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C pylib build
+ 
+ .PHONY: build-qt
+ build-qt:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C qt build
+ 
+ .PHONY: clean
+--- rspy/Makefile	2020-05-21 20:06:35.945720983 +1000
++++ rspy/Makefile	2020-05-21 20:07:54.295720504 +1000
+@@ -86,10 +86,10 @@
+ RUST_TOOLCHAIN := $(shell cat rust-toolchain)
+ 
+ .build/tools: requirements.txt rust-toolchain
+-	python -m pip install -r requirements.txt
+ 	rustup toolchain install $(RUST_TOOLCHAIN)
+ 	rustup component add rustfmt-preview --toolchain $(RUST_TOOLCHAIN)
+ 	rustup component add clippy-preview --toolchain $(RUST_TOOLCHAIN)
++	rustup target add $(RUST_TARGET)
+ 	@touch $@
+ 
+ # we should not call clippy because it break things when running make check Mac OS
+--- pylib/Makefile	2020-05-22 08:46:14.988607539 +1000
++++ pylib/Makefile	2020-05-22 08:46:38.376605821 +1000
+@@ -41,7 +41,7 @@
+ 
+ PROTODEPS := $(wildcard ../proto/*.proto)
+ 
+-.build/py-proto: .build/dev-deps $(PROTODEPS)
++.build/py-proto: $(PROTODEPS)
+ 	protoc --proto_path=../proto --python_out=anki --mypy_out=anki $(PROTODEPS)
+ 	perl -i'' -pe 's/from fluent_pb2/from anki.fluent_pb2/' anki/backend_pb2.pyi
+ 	perl -i'' -pe 's/import fluent_pb2/import anki.fluent_pb2/' anki/backend_pb2.py
diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template
index 680e008a9d4..d900ec19ce2 100644
--- a/srcpkgs/anki/template
+++ b/srcpkgs/anki/template
@@ -1,10 +1,14 @@
 # Template file for 'anki'
 pkgname=anki
-version=2.1.15
-revision=2
-archs=noarch
+version=2.1.26
+revision=1
 build_style=gnu-makefile
 pycompile_dirs="/usr/share/anki/anki /usr/share/anki/aqt"
+# rustup: anki needs nightly ... :(
+hostmakedepends="git python3 rustup maturin which protobuf
+ mypy-protobuf-python python3-stringcase black python3-wheel
+ rsync nodejs python3-PyQt5-devel-tools gettext
+ qt5-translations"
 depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy
  python3-PyAudio python3-mpv python3-Markdown python3-send2trash
  python3-BeautifulSoup4 python3-decorator python3-jsonschema"
@@ -13,11 +17,53 @@ maintainer="Steve Prybylski <sa.prybylx@gmail.com>"
 license="AGPL-3.0-or-later"
 homepage="https://apps.ankiweb.net"
 changelog="https://apps.ankiweb.net/docs/changes.html"
-distfiles="https://apps.ankiweb.net/downloads/current/anki-${version}-source.tgz"
-checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89
-
+distfiles="https://github.com/ankitects/anki/archive/${version}.tar.gz"
+checksum=f5a0c41f3eebe0e77de9d46f2a5cbbe20f7c3a4787f0f02e1d33f298428acbdf
 python_version=3
 
+# When a non-clean masterdir is used, rust is often left over from a
+# previous rust-enabled build. Unfortunatly, xbps-src dosen't seem
+# to clean out rust -.- So, use /usr/rustup, to avoid this issue.
+export PATH=/usr/rustup/bin:${PATH}
+export LD_LIBRARY_PATH=/usr/rustup/lib:${LD_LIBRARY_PATH}
+export CARGO_HOME=/usr/rustup
+export RUSTUP_HOME=/usr/rustup
+
+pre_configure() {
+	# If do_clean didn't run last time, we are stuffed. Run do_clean now.
+	do_clean || true
+	printf "1\\n" | rustup-init
+}
+
+pre_build() {
+	mkdir -p dist
+	make prepare
+}
+
+do_build() {
+	RUSTFLAGS="-C target-feature=-crt-static" make build
+}
+
+do_install() {
+	pushd pylib
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	pushd qt
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	# Copied from arch's PKGBUILD
+	install -Dm755 qt/runanki "${DESTDIR}/usr/bin/anki"
+	install -Dm644 qt/anki.desktop "${DESTDIR}/usr/share/applications/anki.desktop"
+	install -Dm644 qt/anki.png "${DESTDIR}/usr/share/pixmaps/anki.png"
+}
+
 post_install() {
 	vlicense LICENSE
 }
+
+# Remove rustup
+do_clean() {
+	rm -rf /usr/rustup
+}

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PR PATCH] [Updated] WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
@ 2020-05-23  7:07 ` fosslinux
  2020-05-24  5:37 ` fosslinux
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-05-23  7:07 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1570 bytes --]

There is an updated pull request by fosslinux against master on the void-packages repository

https://github.com/fosslinux/void-packages anki-2.1.26
https://github.com/void-linux/void-packages/pull/22219

WIP: anki: update to 2.1.26
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust (nightly!), nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.
- anki uses rustup. This is because it and some of its dependencies require archd code (notably pyo3). This is unavoidable, afaict.

Still todo:

- [ ] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [ ] More extensive runtime testing. It opens, but seems to have weird icon issues?
- [ ] Runtime test on musl.

Questions:

- Is there any problems with removing `arch=nocross`?
- Does the rustup stuff look (somewhat) sane?
- Are the patches sane?

A patch file from https://github.com/void-linux/void-packages/pull/22219.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-anki-2.1.26-22219.patch --]
[-- Type: text/x-diff, Size: 18460 bytes --]

From e88132a875c981abbac9216cce895b2b034d8ed0 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:01 +1000
Subject: [PATCH 1/6] python3-mypy: update to 0.770, claim maintainership

---
 srcpkgs/python3-mypy/template | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/python3-mypy/template b/srcpkgs/python3-mypy/template
index 5d7f93d5772..bde1e7f4be6 100644
--- a/srcpkgs/python3-mypy/template
+++ b/srcpkgs/python3-mypy/template
@@ -1,19 +1,18 @@
 # Template file for 'python3-mypy'
 pkgname=python3-mypy
-version=0.761
+version=0.770
 revision=1
 archs=noarch
 wrksrc="mypy-${version}"
 build_style=python3-module
-pycompile_module="mypy"
 hostmakedepends="python3-setuptools"
 depends="python3-mypy_extensions python3-typed-ast python3-typing_extensions"
 short_desc="Optional static typing for Python3"
-maintainer="Orphaned <orphan@voidlinux.org>"
+maintainer="fosslinux <fosslinux@aussies.space>"
 license="MIT"
 homepage="https://github.com/python/mypy"
 distfiles="${PYPI_SITE}/m/mypy/mypy-${version}.tar.gz"
-checksum=85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf
+checksum=8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae
 
 post_install() {
 	vlicense LICENSE

From ae580c7dcc5fa9ee6c2040b185773341a8fdda2b Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:34:38 +1000
Subject: [PATCH 2/6] New package: maturin-0.8.1

---
 .../patches/cross-compile-setup-py.patch      | 14 +++++++++++++
 srcpkgs/maturin/template                      | 21 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 srcpkgs/maturin/patches/cross-compile-setup-py.patch
 create mode 100644 srcpkgs/maturin/template

diff --git a/srcpkgs/maturin/patches/cross-compile-setup-py.patch b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
new file mode 100644
index 00000000000..e57189cb7ab
--- /dev/null
+++ b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
@@ -0,0 +1,14 @@
+--- setup.py	2020-04-30 22:36:01.000000000 +1000
++++ setup.py	2020-05-20 14:31:40.404994499 +1000
+@@ -56,9 +56,9 @@
+                     "(https://www.rust-lang.org/tools/install) and try again"
+                 )
+             subprocess.check_call(
+-                ["cargo", "rustc", "--bin", "maturin", "--", "-C", "link-arg=-s"]
++                ["cargo", "rustc", "--bin", "maturin", "--release", "--target", os.environ["RUST_TARGET"], "--", "-C", "link-arg=-s", "-C", "linker=" + os.environ["CC"].split(" ", 1)[0]]
+             )
+-            source = os.path.join(source_dir, "target", "debug", executable_name)
++            source = os.path.join(source_dir, "target", os.environ["RUST_TARGET"], "release", executable_name)
+         # run this after trying to build with cargo (as otherwise this leaves
+         # venv in a bad state: https://github.com/benfred/py-spy/issues/69)
+         install.run(self)
diff --git a/srcpkgs/maturin/template b/srcpkgs/maturin/template
new file mode 100644
index 00000000000..7eba36204f9
--- /dev/null
+++ b/srcpkgs/maturin/template
@@ -0,0 +1,21 @@
+# Template file for 'maturin'
+pkgname=maturin
+version=0.8.1
+revision=1
+build_style=python3-module
+hostmakedepends="cargo python3-setuptools python3-toml"
+makedepends="rust rust-std llvm9"
+short_desc="Build and publish crates with python bindings"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0, MIT"
+homepage="https://github.com/PyO3/maturin"
+distfiles="https://github.com/PyO3/maturin/archive/v${version}.tar.gz"
+checksum=b72a9885cda3ba4e53906a43aab101acb790622218ade6405b2ddf1ef1461f8f
+
+post_install() {
+	# Dynamic detection of python version
+	PYTHON_VERSION=$(python3 --version | sed "s/^Python //" | rev | sed "s/^[0-9]*.//" | rev)
+	mkdir -p "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	mv "${DESTDIR}/maturin" "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	vlicense license-mit
+}

From 1bd1177a01ea7ce37e08a382eed7597a764ae457 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:25 +1000
Subject: [PATCH 3/6] New package: mypy-protobuf-python-1.13

---
 srcpkgs/mypy-protobuf-python/template | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-python/template

diff --git a/srcpkgs/mypy-protobuf-python/template b/srcpkgs/mypy-protobuf-python/template
new file mode 100644
index 00000000000..391d75f0c9e
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-python/template
@@ -0,0 +1,23 @@
+# Template file for 'mypy-protobuf-python'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-go
+#
+pkgname=mypy-protobuf-python
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_wrksrc=python
+build_style=python3-module
+hostmakedepends="python3-setuptools"
+depends="python3-mypy python3-typing_extensions python3-protobuf protobuf"
+short_desc="Generate mypy stubs from protobufs - Python implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74
+
+post_install() {
+	# We are not windows, remove the batch file
+	rm "${DESTDIR}/usr/bin/protoc_gen_mypy.bat"
+}

From 2005df10d61b46933f28eea0b17e701a09af437b Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:37 +1000
Subject: [PATCH 4/6] New package: mypy-protobuf-go-1.13

---
 .../patches/remote-go-improt.patch            | 11 +++++++++++
 srcpkgs/mypy-protobuf-go/template             | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
 create mode 100644 srcpkgs/mypy-protobuf-go/template

diff --git a/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
new file mode 100644
index 00000000000..300504bc70d
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
@@ -0,0 +1,11 @@
+--- go/src/protoc-gen-mypy/main.go.orig	2020-05-22 11:58:07.760761664 +1000
++++ go/src/protoc-gen-mypy/main.go	2020-05-22 11:58:00.595762190 +1000
+@@ -6,7 +6,7 @@
+ 	"sort"
+ 	"strings"
+ 
+-	"proto/mypy"
++	"github.com/dropbox/mypy-protobuf/go/src/proto/mypy"
+ 
+ 	"github.com/gogo/protobuf/proto"
+ 	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
diff --git a/srcpkgs/mypy-protobuf-go/template b/srcpkgs/mypy-protobuf-go/template
new file mode 100644
index 00000000000..8f00e43d8a8
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/template
@@ -0,0 +1,19 @@
+# Template file for 'mypy-protobuf-go'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-python
+#
+pkgname=mypy-protobuf-go
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_style=go
+go_import_path="github.com/dropbox/mypy-protobuf"
+go_package="${go_import_path}/go/src/protoc-gen-mypy"
+hostmakedepends="git"
+depends="protobuf"
+short_desc="Generate mypy stubs from protobufs - go implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74

From db650873d45635b6983c2d24717e827309303092 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:36 +1000
Subject: [PATCH 5/6] New package: python-stringcase-1.2.0

---
 srcpkgs/python-stringcase/template | 28 ++++++++++++++++++++++++++++
 srcpkgs/python3-stringcase         |  1 +
 2 files changed, 29 insertions(+)
 create mode 100644 srcpkgs/python-stringcase/template
 create mode 120000 srcpkgs/python3-stringcase

diff --git a/srcpkgs/python-stringcase/template b/srcpkgs/python-stringcase/template
new file mode 100644
index 00000000000..849e677c784
--- /dev/null
+++ b/srcpkgs/python-stringcase/template
@@ -0,0 +1,28 @@
+# Template file for 'python-stringcase'
+pkgname=python-stringcase
+version=1.2.0
+revision=1
+wrksrc="stringcase-${version}"
+build_style=python-module
+hostmakedepends="python-devel python3-devel"
+makedepends="${hostmakedepends}"
+depends="python"
+short_desc="String case converter for Python2"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="MIT"
+homepage="https://github.com/okunishinishi/python-stringcase"
+distfiles="${PYPI_SITE}/s/stringcase/stringcase-${version}.tar.gz"
+checksum=48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008
+
+post_install() {
+	vlicense LICENSE
+}
+
+python3-stringcase_package() {
+	depends="python3"
+	short_desc="${short_desc/Python2/Python3}"
+	pkg_install() {
+		vmove usr/lib/python3*
+		vlicense LICENSE
+	}
+}
diff --git a/srcpkgs/python3-stringcase b/srcpkgs/python3-stringcase
new file mode 120000
index 00000000000..53938bd1f0c
--- /dev/null
+++ b/srcpkgs/python3-stringcase
@@ -0,0 +1 @@
+python-stringcase
\ No newline at end of file

From cb9978037d8ed6df1277d8c405978b9f9d9692cd Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:36:21 +1000
Subject: [PATCH 6/6] anki: update to 2.1.26

Has turned into a Bad Build System. Now uses rust nightly, python
(with bindings!), qt5, nodejs... the list goes on. There are quite
a few hacks and the like.
---
 srcpkgs/anki/patches/aqt_data-fhs.patch       | 45 +++++++++
 .../anki/patches/rustc-cross-compile.patch    | 11 +++
 srcpkgs/anki/patches/vendored-deps.patch      | 94 +++++++++++++++++++
 srcpkgs/anki/template                         | 58 ++++++++++--
 4 files changed, 202 insertions(+), 6 deletions(-)
 create mode 100644 srcpkgs/anki/patches/aqt_data-fhs.patch
 create mode 100644 srcpkgs/anki/patches/rustc-cross-compile.patch
 create mode 100644 srcpkgs/anki/patches/vendored-deps.patch

diff --git a/srcpkgs/anki/patches/aqt_data-fhs.patch b/srcpkgs/anki/patches/aqt_data-fhs.patch
new file mode 100644
index 00000000000..ac0d29ec082
--- /dev/null
+++ b/srcpkgs/anki/patches/aqt_data-fhs.patch
@@ -0,0 +1,45 @@
+From a0a9ac1aeb8b8678f1102aed81010a901ad8d9e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Johannes=20L=C3=B6thberg?= <johannes@kyriasis.com>
+Date: Sun, 29 Mar 2020 06:24:43 +0200
+Subject: [PATCH 1/4] Move aqt_data to sys.prefix/share
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+These files do _not_ belong right under sys.prefix.
+
+Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
+---
+ qt/aqt/utils.py | 2 +-
+ qt/setup.py     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git qt/aqt/utils.py qt/aqt/utils.py
+index a0e12362..4d8c8c34 100644
+--- qt/aqt/utils.py
++++ qt/aqt/utils.py
+@@ -21,7 +21,7 @@ from aqt.theme import theme_manager
+ 
+ def aqt_data_folder() -> str:
+     # wheel install?
+-    dir = os.path.join(sys.prefix, "aqt_data")
++    dir = os.path.join(sys.prefix,"share", "aqt_data")
+     if not os.path.exists(dir) or not os.listdir(dir):
+         # running in place?
+         dir = os.path.join(os.path.dirname(__file__), "..", "aqt_data")
+diff --git qt/setup.py qt/setup.py
+index 38f4e2b7..bdda3baa 100644
+--- qt/setup.py
++++ qt/setup.py
+@@ -8,7 +8,7 @@ import setuptools
+ def package_files(directory):
+     entries = []
+     for (path, directories, filenames) in os.walk(directory):
+-        entries.append((path, [os.path.join(path, f) for f in filenames]))
++        entries.append((os.path.join("share", path), [os.path.join(path, f) for f in filenames]))
+     return entries
+ 
+ 
+-- 
+2.26.2
+
diff --git a/srcpkgs/anki/patches/rustc-cross-compile.patch b/srcpkgs/anki/patches/rustc-cross-compile.patch
new file mode 100644
index 00000000000..15239ea4cf1
--- /dev/null
+++ b/srcpkgs/anki/patches/rustc-cross-compile.patch
@@ -0,0 +1,11 @@
+--- rspy/Makefile	2020-05-23 12:02:29.758286838 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -69,7 +69,7 @@
+ .build/build: $(DEPS)
+ 	touch ../proto/backend.proto
+ 	${BUILD_VARIABLES} \
+-		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS)
++		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS) --target $(RUST_TARGET)
+    touch $@
+ 
+ check: .build/check
diff --git a/srcpkgs/anki/patches/vendored-deps.patch b/srcpkgs/anki/patches/vendored-deps.patch
new file mode 100644
index 00000000000..1d2bc90ffb1
--- /dev/null
+++ b/srcpkgs/anki/patches/vendored-deps.patch
@@ -0,0 +1,94 @@
+diff -u -r Makefile Makefile
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 18:40:54.345223164 +1000
+@@ -92,7 +92,7 @@
+ 	fi
+ 
+ .PHONY: develop
+-develop: pyenv buildhash prepare
++develop: buildhash prepare
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	for dir in $(DEVEL); do \
+diff -u -r pylib/Makefile pylib/Makefile
+--- pylib/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ pylib/Makefile	2020-05-19 18:50:01.075182994 +1000
+@@ -52,7 +52,7 @@
+ 	python -m black anki/hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks
++BUILD_STEPS := .build/vernum .build/py-proto anki/buildinfo.py .build/hooks
+ 
+ # Checking
+ ######################
+diff -u -r qt/Makefile qt/Makefile
+--- qt/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ qt/Makefile	2020-05-19 18:50:17.520181786 +1000
+@@ -64,7 +64,7 @@
+ 	python -m black aqt/gui_hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
++BUILD_STEPS := .build/vernum .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
+ 
+ # Checking
+ ######################
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 19:01:35.602131965 +1000
+@@ -122,7 +122,7 @@
+ 	@echo "Build complete."
+ 
+ .PHONY: build-rspy
+-build-rspy: pyenv buildhash
++build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+--- Makefile	2020-05-19 19:41:44.191955000 +1000
++++ Makefile	2020-05-19 19:42:21.423952264 +1000
+@@ -124,19 +124,16 @@
+ .PHONY: build-rspy
+ build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+ 
+ .PHONY: build-pylib
+ build-pylib:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C pylib build
+ 
+ .PHONY: build-qt
+ build-qt:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C qt build
+ 
+ .PHONY: clean
+--- rspy/Makefile	2020-05-21 20:06:35.945720983 +1000
++++ rspy/Makefile	2020-05-21 20:07:54.295720504 +1000
+@@ -86,10 +86,10 @@
+ RUST_TOOLCHAIN := $(shell cat rust-toolchain)
+ 
+ .build/tools: requirements.txt rust-toolchain
+-	python -m pip install -r requirements.txt
+ 	rustup toolchain install $(RUST_TOOLCHAIN)
+ 	rustup component add rustfmt-preview --toolchain $(RUST_TOOLCHAIN)
+ 	rustup component add clippy-preview --toolchain $(RUST_TOOLCHAIN)
++	rustup target add $(RUST_TARGET)
+ 	@touch $@
+ 
+ # we should not call clippy because it break things when running make check Mac OS
+--- pylib/Makefile	2020-05-22 08:46:14.988607539 +1000
++++ pylib/Makefile	2020-05-22 08:46:38.376605821 +1000
+@@ -41,7 +41,7 @@
+ 
+ PROTODEPS := $(wildcard ../proto/*.proto)
+ 
+-.build/py-proto: .build/dev-deps $(PROTODEPS)
++.build/py-proto: $(PROTODEPS)
+ 	protoc --proto_path=../proto --python_out=anki --mypy_out=anki $(PROTODEPS)
+ 	perl -i'' -pe 's/from fluent_pb2/from anki.fluent_pb2/' anki/backend_pb2.pyi
+ 	perl -i'' -pe 's/import fluent_pb2/import anki.fluent_pb2/' anki/backend_pb2.py
diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template
index 680e008a9d4..7e4e2dcf916 100644
--- a/srcpkgs/anki/template
+++ b/srcpkgs/anki/template
@@ -1,10 +1,14 @@
 # Template file for 'anki'
 pkgname=anki
-version=2.1.15
-revision=2
-archs=noarch
+version=2.1.26
+revision=1
 build_style=gnu-makefile
 pycompile_dirs="/usr/share/anki/anki /usr/share/anki/aqt"
+# rustup: anki needs nightly ... :(
+hostmakedepends="git python3 rustup maturin which protobuf
+ mypy-protobuf-python python3-stringcase black python3-wheel
+ rsync nodejs python3-PyQt5-devel-tools gettext
+ qt5-translations"
 depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy
  python3-PyAudio python3-mpv python3-Markdown python3-send2trash
  python3-BeautifulSoup4 python3-decorator python3-jsonschema"
@@ -13,11 +17,53 @@ maintainer="Steve Prybylski <sa.prybylx@gmail.com>"
 license="AGPL-3.0-or-later"
 homepage="https://apps.ankiweb.net"
 changelog="https://apps.ankiweb.net/docs/changes.html"
-distfiles="https://apps.ankiweb.net/downloads/current/anki-${version}-source.tgz"
-checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89
-
+distfiles="https://github.com/ankitects/anki/archive/${version}.tar.gz"
+checksum=f5a0c41f3eebe0e77de9d46f2a5cbbe20f7c3a4787f0f02e1d33f298428acbdf
 python_version=3
 
+# When a non-clean masterdir is used, rust is often left over from a
+# previous rust-enabled build. Unfortunatly, xbps-src dosen't seem
+# to clean out rust -.- So, use /usr/rustup, to avoid this issue.
+export PATH=/usr/rustup/bin:${PATH}
+export LD_LIBRARY_PATH=/usr/rustup/lib:${LD_LIBRARY_PATH}
+export CARGO_HOME=/usr/rustup
+export RUSTUP_HOME=/usr/rustup
+
+pre_configure() {
+	# If do_clean didn't run last time, we are stuffed. Run do_clean now.
+	do_clean || true
+	printf "1\\n" | rustup-init -y
+}
+
+pre_build() {
+	mkdir -p dist
+	make prepare
+}
+
+do_build() {
+	RUSTFLAGS="-C target-feature=-crt-static" make build
+}
+
+do_install() {
+	pushd pylib
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	pushd qt
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	# Copied from arch's PKGBUILD
+	install -Dm755 qt/runanki "${DESTDIR}/usr/bin/anki"
+	install -Dm644 qt/anki.desktop "${DESTDIR}/usr/share/applications/anki.desktop"
+	install -Dm644 qt/anki.png "${DESTDIR}/usr/share/pixmaps/anki.png"
+}
+
 post_install() {
 	vlicense LICENSE
 }
+
+# Remove rustup
+do_clean() {
+	rm -rf /usr/rustup
+}

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PR PATCH] [Updated] WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
  2020-05-23  7:07 ` [PR PATCH] [Updated] " fosslinux
@ 2020-05-24  5:37 ` fosslinux
  2020-05-24  5:39 ` fosslinux
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-05-24  5:37 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 2045 bytes --]

There is an updated pull request by fosslinux against master on the void-packages repository

https://github.com/fosslinux/void-packages anki-2.1.26
https://github.com/void-linux/void-packages/pull/22219

WIP: anki: update to 2.1.26
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust (nightly!), nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.
- anki uses rustup. This is because it and some of its dependencies require archd code (notably pyo3). This is unavoidable, afaict.

Still todo:

- [x] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [x] Update python3-protobuf - hopefully will fix `AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'`.
- [ ] Look into travis musl error. https://github.com/rust-lang/rust/issues/40174. Hopefully, using rust 1.44 as the rust version *should* fix this. What a PITA. I understand that this is because it works when I cross-compile to x86_64-musl from x86_64 but we need it to work native build from x86_64-musl for the builders...
- [ ] Travis wth on i686?
- [x] Make it open.
- [ ] More extensive runtime testing.
- [ ] Runtime test on musl.

Questions:

- Is there any problems with removing `arch=nocross`?
- Does the rustup stuff look (somewhat) sane?
- Are the patches sane?

A patch file from https://github.com/void-linux/void-packages/pull/22219.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-anki-2.1.26-22219.patch --]
[-- Type: text/x-diff, Size: 20502 bytes --]

From 78816216511379aa1b82f106aeffe9266c10ca18 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sun, 24 May 2020 15:37:00 +1000
Subject: [PATCH 1/7] python-protobuf: update to 3.12.1

---
 srcpkgs/python-protobuf/template | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/srcpkgs/python-protobuf/template b/srcpkgs/python-protobuf/template
index 1a2d37a0a1e..a96fd539894 100644
--- a/srcpkgs/python-protobuf/template
+++ b/srcpkgs/python-protobuf/template
@@ -1,19 +1,19 @@
 # Template file for 'python-protobuf'
 pkgname=python-protobuf
-version=3.10.0
-revision=2
+version=3.12.1
+revision=1
 archs=noarch
 wrksrc="protobuf-${version}"
+build_wrksrc="python"
 build_style=python-module
-pycompile_module="google/protobuf"
-hostmakedepends="python-setuptools python3-setuptools"
+hostmakedepends="python-setuptools python3-setuptools protobuf"
 depends="python-setuptools python-six"
 short_desc="Python2 bindings for Google Protocol Buffers"
 maintainer="Charles E. Lehner <cel@celehner.com>"
 license="BSD-3-Clause"
 homepage="https://developers.google.com/protocol-buffers/"
-distfiles="${PYPI_SITE}/p/protobuf/protobuf-${version}.tar.gz"
-checksum=db83b5c12c0cd30150bb568e6feb2435c49ce4e68fe2d7b903113f0e221e58fe
+distfiles="https://github.com/protocolbuffers/protobuf/archive/v${version}.tar.gz"
+checksum=cb9b3f9d625b5739a358268eb3421de11cacd90025f5f7672c3930553eca810e
 
 post_install() {
 	sed -n 1,29p google/protobuf/__init__.py >LICENSE
@@ -22,7 +22,6 @@ post_install() {
 
 python3-protobuf_package() {
 	archs=noarch
-	pycompile_module="google/protobuf"
 	depends="python3-setuptools python3-six"
 	short_desc="${short_desc/Python2/Python3}"
 	pkg_install() {

From 7712eb76d5743a2c0c3d75747bc3ea0f5f2e4e0b Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:01 +1000
Subject: [PATCH 2/7] python3-mypy: update to 0.770, claim maintainership

---
 srcpkgs/python3-mypy/template | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/python3-mypy/template b/srcpkgs/python3-mypy/template
index 5d7f93d5772..bde1e7f4be6 100644
--- a/srcpkgs/python3-mypy/template
+++ b/srcpkgs/python3-mypy/template
@@ -1,19 +1,18 @@
 # Template file for 'python3-mypy'
 pkgname=python3-mypy
-version=0.761
+version=0.770
 revision=1
 archs=noarch
 wrksrc="mypy-${version}"
 build_style=python3-module
-pycompile_module="mypy"
 hostmakedepends="python3-setuptools"
 depends="python3-mypy_extensions python3-typed-ast python3-typing_extensions"
 short_desc="Optional static typing for Python3"
-maintainer="Orphaned <orphan@voidlinux.org>"
+maintainer="fosslinux <fosslinux@aussies.space>"
 license="MIT"
 homepage="https://github.com/python/mypy"
 distfiles="${PYPI_SITE}/m/mypy/mypy-${version}.tar.gz"
-checksum=85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf
+checksum=8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae
 
 post_install() {
 	vlicense LICENSE

From 6efdf584b76652d8f2df4ea2130474e3b1576340 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:34:38 +1000
Subject: [PATCH 3/7] New package: maturin-0.8.1

---
 .../patches/cross-compile-setup-py.patch      | 14 +++++++++++++
 srcpkgs/maturin/template                      | 21 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 srcpkgs/maturin/patches/cross-compile-setup-py.patch
 create mode 100644 srcpkgs/maturin/template

diff --git a/srcpkgs/maturin/patches/cross-compile-setup-py.patch b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
new file mode 100644
index 00000000000..e57189cb7ab
--- /dev/null
+++ b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
@@ -0,0 +1,14 @@
+--- setup.py	2020-04-30 22:36:01.000000000 +1000
++++ setup.py	2020-05-20 14:31:40.404994499 +1000
+@@ -56,9 +56,9 @@
+                     "(https://www.rust-lang.org/tools/install) and try again"
+                 )
+             subprocess.check_call(
+-                ["cargo", "rustc", "--bin", "maturin", "--", "-C", "link-arg=-s"]
++                ["cargo", "rustc", "--bin", "maturin", "--release", "--target", os.environ["RUST_TARGET"], "--", "-C", "link-arg=-s", "-C", "linker=" + os.environ["CC"].split(" ", 1)[0]]
+             )
+-            source = os.path.join(source_dir, "target", "debug", executable_name)
++            source = os.path.join(source_dir, "target", os.environ["RUST_TARGET"], "release", executable_name)
+         # run this after trying to build with cargo (as otherwise this leaves
+         # venv in a bad state: https://github.com/benfred/py-spy/issues/69)
+         install.run(self)
diff --git a/srcpkgs/maturin/template b/srcpkgs/maturin/template
new file mode 100644
index 00000000000..7eba36204f9
--- /dev/null
+++ b/srcpkgs/maturin/template
@@ -0,0 +1,21 @@
+# Template file for 'maturin'
+pkgname=maturin
+version=0.8.1
+revision=1
+build_style=python3-module
+hostmakedepends="cargo python3-setuptools python3-toml"
+makedepends="rust rust-std llvm9"
+short_desc="Build and publish crates with python bindings"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0, MIT"
+homepage="https://github.com/PyO3/maturin"
+distfiles="https://github.com/PyO3/maturin/archive/v${version}.tar.gz"
+checksum=b72a9885cda3ba4e53906a43aab101acb790622218ade6405b2ddf1ef1461f8f
+
+post_install() {
+	# Dynamic detection of python version
+	PYTHON_VERSION=$(python3 --version | sed "s/^Python //" | rev | sed "s/^[0-9]*.//" | rev)
+	mkdir -p "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	mv "${DESTDIR}/maturin" "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	vlicense license-mit
+}

From bf0b313f13c558529acb46ef74b3841997b9d5d9 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:25 +1000
Subject: [PATCH 4/7] New package: mypy-protobuf-python-1.13

---
 srcpkgs/mypy-protobuf-python/template | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-python/template

diff --git a/srcpkgs/mypy-protobuf-python/template b/srcpkgs/mypy-protobuf-python/template
new file mode 100644
index 00000000000..391d75f0c9e
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-python/template
@@ -0,0 +1,23 @@
+# Template file for 'mypy-protobuf-python'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-go
+#
+pkgname=mypy-protobuf-python
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_wrksrc=python
+build_style=python3-module
+hostmakedepends="python3-setuptools"
+depends="python3-mypy python3-typing_extensions python3-protobuf protobuf"
+short_desc="Generate mypy stubs from protobufs - Python implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74
+
+post_install() {
+	# We are not windows, remove the batch file
+	rm "${DESTDIR}/usr/bin/protoc_gen_mypy.bat"
+}

From 0e9530bdee8b9d76ea8bfd4e50087eac4294e2af Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:37 +1000
Subject: [PATCH 5/7] New package: mypy-protobuf-go-1.13

---
 .../patches/remote-go-improt.patch            | 11 +++++++++++
 srcpkgs/mypy-protobuf-go/template             | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
 create mode 100644 srcpkgs/mypy-protobuf-go/template

diff --git a/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
new file mode 100644
index 00000000000..300504bc70d
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
@@ -0,0 +1,11 @@
+--- go/src/protoc-gen-mypy/main.go.orig	2020-05-22 11:58:07.760761664 +1000
++++ go/src/protoc-gen-mypy/main.go	2020-05-22 11:58:00.595762190 +1000
+@@ -6,7 +6,7 @@
+ 	"sort"
+ 	"strings"
+ 
+-	"proto/mypy"
++	"github.com/dropbox/mypy-protobuf/go/src/proto/mypy"
+ 
+ 	"github.com/gogo/protobuf/proto"
+ 	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
diff --git a/srcpkgs/mypy-protobuf-go/template b/srcpkgs/mypy-protobuf-go/template
new file mode 100644
index 00000000000..8f00e43d8a8
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/template
@@ -0,0 +1,19 @@
+# Template file for 'mypy-protobuf-go'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-python
+#
+pkgname=mypy-protobuf-go
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_style=go
+go_import_path="github.com/dropbox/mypy-protobuf"
+go_package="${go_import_path}/go/src/protoc-gen-mypy"
+hostmakedepends="git"
+depends="protobuf"
+short_desc="Generate mypy stubs from protobufs - go implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74

From 7dbe4213090b5647b997d079f3a7823e15cfba0d Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:36 +1000
Subject: [PATCH 6/7] New package: python-stringcase-1.2.0

---
 srcpkgs/python-stringcase/template | 28 ++++++++++++++++++++++++++++
 srcpkgs/python3-stringcase         |  1 +
 2 files changed, 29 insertions(+)
 create mode 100644 srcpkgs/python-stringcase/template
 create mode 120000 srcpkgs/python3-stringcase

diff --git a/srcpkgs/python-stringcase/template b/srcpkgs/python-stringcase/template
new file mode 100644
index 00000000000..849e677c784
--- /dev/null
+++ b/srcpkgs/python-stringcase/template
@@ -0,0 +1,28 @@
+# Template file for 'python-stringcase'
+pkgname=python-stringcase
+version=1.2.0
+revision=1
+wrksrc="stringcase-${version}"
+build_style=python-module
+hostmakedepends="python-devel python3-devel"
+makedepends="${hostmakedepends}"
+depends="python"
+short_desc="String case converter for Python2"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="MIT"
+homepage="https://github.com/okunishinishi/python-stringcase"
+distfiles="${PYPI_SITE}/s/stringcase/stringcase-${version}.tar.gz"
+checksum=48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008
+
+post_install() {
+	vlicense LICENSE
+}
+
+python3-stringcase_package() {
+	depends="python3"
+	short_desc="${short_desc/Python2/Python3}"
+	pkg_install() {
+		vmove usr/lib/python3*
+		vlicense LICENSE
+	}
+}
diff --git a/srcpkgs/python3-stringcase b/srcpkgs/python3-stringcase
new file mode 120000
index 00000000000..53938bd1f0c
--- /dev/null
+++ b/srcpkgs/python3-stringcase
@@ -0,0 +1 @@
+python-stringcase
\ No newline at end of file

From 54e29ba6eac77f6e6ef6895ef1823c9595a3153a Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:36:21 +1000
Subject: [PATCH 7/7] anki: update to 2.1.26

Has turned into a Bad Build System. Now uses rust nightly, python
(with bindings!), qt5, nodejs... the list goes on. There are quite
a few hacks and the like.
---
 srcpkgs/anki/patches/aqt_data-fhs.patch       | 45 +++++++++
 .../anki/patches/rustc-cross-compile.patch    | 11 +++
 srcpkgs/anki/patches/vendored-deps.patch      | 94 +++++++++++++++++++
 srcpkgs/anki/template                         | 64 +++++++++++--
 4 files changed, 207 insertions(+), 7 deletions(-)
 create mode 100644 srcpkgs/anki/patches/aqt_data-fhs.patch
 create mode 100644 srcpkgs/anki/patches/rustc-cross-compile.patch
 create mode 100644 srcpkgs/anki/patches/vendored-deps.patch

diff --git a/srcpkgs/anki/patches/aqt_data-fhs.patch b/srcpkgs/anki/patches/aqt_data-fhs.patch
new file mode 100644
index 00000000000..ac0d29ec082
--- /dev/null
+++ b/srcpkgs/anki/patches/aqt_data-fhs.patch
@@ -0,0 +1,45 @@
+From a0a9ac1aeb8b8678f1102aed81010a901ad8d9e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Johannes=20L=C3=B6thberg?= <johannes@kyriasis.com>
+Date: Sun, 29 Mar 2020 06:24:43 +0200
+Subject: [PATCH 1/4] Move aqt_data to sys.prefix/share
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+These files do _not_ belong right under sys.prefix.
+
+Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
+---
+ qt/aqt/utils.py | 2 +-
+ qt/setup.py     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git qt/aqt/utils.py qt/aqt/utils.py
+index a0e12362..4d8c8c34 100644
+--- qt/aqt/utils.py
++++ qt/aqt/utils.py
+@@ -21,7 +21,7 @@ from aqt.theme import theme_manager
+ 
+ def aqt_data_folder() -> str:
+     # wheel install?
+-    dir = os.path.join(sys.prefix, "aqt_data")
++    dir = os.path.join(sys.prefix,"share", "aqt_data")
+     if not os.path.exists(dir) or not os.listdir(dir):
+         # running in place?
+         dir = os.path.join(os.path.dirname(__file__), "..", "aqt_data")
+diff --git qt/setup.py qt/setup.py
+index 38f4e2b7..bdda3baa 100644
+--- qt/setup.py
++++ qt/setup.py
+@@ -8,7 +8,7 @@ import setuptools
+ def package_files(directory):
+     entries = []
+     for (path, directories, filenames) in os.walk(directory):
+-        entries.append((path, [os.path.join(path, f) for f in filenames]))
++        entries.append((os.path.join("share", path), [os.path.join(path, f) for f in filenames]))
+     return entries
+ 
+ 
+-- 
+2.26.2
+
diff --git a/srcpkgs/anki/patches/rustc-cross-compile.patch b/srcpkgs/anki/patches/rustc-cross-compile.patch
new file mode 100644
index 00000000000..15239ea4cf1
--- /dev/null
+++ b/srcpkgs/anki/patches/rustc-cross-compile.patch
@@ -0,0 +1,11 @@
+--- rspy/Makefile	2020-05-23 12:02:29.758286838 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -69,7 +69,7 @@
+ .build/build: $(DEPS)
+ 	touch ../proto/backend.proto
+ 	${BUILD_VARIABLES} \
+-		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS)
++		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS) --target $(RUST_TARGET)
+    touch $@
+ 
+ check: .build/check
diff --git a/srcpkgs/anki/patches/vendored-deps.patch b/srcpkgs/anki/patches/vendored-deps.patch
new file mode 100644
index 00000000000..1d2bc90ffb1
--- /dev/null
+++ b/srcpkgs/anki/patches/vendored-deps.patch
@@ -0,0 +1,94 @@
+diff -u -r Makefile Makefile
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 18:40:54.345223164 +1000
+@@ -92,7 +92,7 @@
+ 	fi
+ 
+ .PHONY: develop
+-develop: pyenv buildhash prepare
++develop: buildhash prepare
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	for dir in $(DEVEL); do \
+diff -u -r pylib/Makefile pylib/Makefile
+--- pylib/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ pylib/Makefile	2020-05-19 18:50:01.075182994 +1000
+@@ -52,7 +52,7 @@
+ 	python -m black anki/hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks
++BUILD_STEPS := .build/vernum .build/py-proto anki/buildinfo.py .build/hooks
+ 
+ # Checking
+ ######################
+diff -u -r qt/Makefile qt/Makefile
+--- qt/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ qt/Makefile	2020-05-19 18:50:17.520181786 +1000
+@@ -64,7 +64,7 @@
+ 	python -m black aqt/gui_hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
++BUILD_STEPS := .build/vernum .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
+ 
+ # Checking
+ ######################
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 19:01:35.602131965 +1000
+@@ -122,7 +122,7 @@
+ 	@echo "Build complete."
+ 
+ .PHONY: build-rspy
+-build-rspy: pyenv buildhash
++build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+--- Makefile	2020-05-19 19:41:44.191955000 +1000
++++ Makefile	2020-05-19 19:42:21.423952264 +1000
+@@ -124,19 +124,16 @@
+ .PHONY: build-rspy
+ build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+ 
+ .PHONY: build-pylib
+ build-pylib:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C pylib build
+ 
+ .PHONY: build-qt
+ build-qt:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C qt build
+ 
+ .PHONY: clean
+--- rspy/Makefile	2020-05-21 20:06:35.945720983 +1000
++++ rspy/Makefile	2020-05-21 20:07:54.295720504 +1000
+@@ -86,10 +86,10 @@
+ RUST_TOOLCHAIN := $(shell cat rust-toolchain)
+ 
+ .build/tools: requirements.txt rust-toolchain
+-	python -m pip install -r requirements.txt
+ 	rustup toolchain install $(RUST_TOOLCHAIN)
+ 	rustup component add rustfmt-preview --toolchain $(RUST_TOOLCHAIN)
+ 	rustup component add clippy-preview --toolchain $(RUST_TOOLCHAIN)
++	rustup target add $(RUST_TARGET)
+ 	@touch $@
+ 
+ # we should not call clippy because it break things when running make check Mac OS
+--- pylib/Makefile	2020-05-22 08:46:14.988607539 +1000
++++ pylib/Makefile	2020-05-22 08:46:38.376605821 +1000
+@@ -41,7 +41,7 @@
+ 
+ PROTODEPS := $(wildcard ../proto/*.proto)
+ 
+-.build/py-proto: .build/dev-deps $(PROTODEPS)
++.build/py-proto: $(PROTODEPS)
+ 	protoc --proto_path=../proto --python_out=anki --mypy_out=anki $(PROTODEPS)
+ 	perl -i'' -pe 's/from fluent_pb2/from anki.fluent_pb2/' anki/backend_pb2.pyi
+ 	perl -i'' -pe 's/import fluent_pb2/import anki.fluent_pb2/' anki/backend_pb2.py
diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template
index 680e008a9d4..89e28d11b05 100644
--- a/srcpkgs/anki/template
+++ b/srcpkgs/anki/template
@@ -1,23 +1,73 @@
 # Template file for 'anki'
 pkgname=anki
-version=2.1.15
-revision=2
-archs=noarch
+version=2.1.26
+revision=1
 build_style=gnu-makefile
 pycompile_dirs="/usr/share/anki/anki /usr/share/anki/aqt"
+# rustup: anki needs nightly ... :(
+hostmakedepends="git python3 rustup maturin which protobuf
+ mypy-protobuf-python python3-stringcase black python3-wheel
+ rsync nodejs python3-PyQt5-devel-tools gettext
+ qt5-translations python3-pip"
 depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy
  python3-PyAudio python3-mpv python3-Markdown python3-send2trash
- python3-BeautifulSoup4 python3-decorator python3-jsonschema"
+ python3-BeautifulSoup4 python3-decorator python3-jsonschema
+ python3-protobuf"
 short_desc="Spaced repetition flashcard program"
 maintainer="Steve Prybylski <sa.prybylx@gmail.com>"
 license="AGPL-3.0-or-later"
 homepage="https://apps.ankiweb.net"
 changelog="https://apps.ankiweb.net/docs/changes.html"
-distfiles="https://apps.ankiweb.net/downloads/current/anki-${version}-source.tgz"
-checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89
-
+distfiles="https://github.com/ankitects/anki/archive/${version}.tar.gz"
+checksum=f5a0c41f3eebe0e77de9d46f2a5cbbe20f7c3a4787f0f02e1d33f298428acbdf
 python_version=3
 
+# When a non-clean masterdir is used, rust is often left over from a
+# previous rust-enabled build. Unfortunatly, xbps-src dosen't seem
+# to clean out rust -.- So, use /usr/rustup, to avoid this issue.
+export PATH=/usr/rustup/bin:${PATH}
+export LD_LIBRARY_PATH=/usr/rustup/lib:${LD_LIBRARY_PATH}
+export CARGO_HOME=/usr/rustup
+export RUSTUP_HOME=/usr/rustup
+
+pre_configure() {
+	# If do_clean didn't run last time, we are stuffed. Run do_clean now.
+	do_clean || true
+	printf "1\\n" | rustup-init -y
+}
+
+pre_build() {
+	mkdir -p dist
+	make prepare
+}
+
+do_build() {
+	RUSTFLAGS="-C target-feature=-crt-static" make build
+}
+
+do_install() {
+	pushd pylib
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	pushd qt
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	# maturin generates a .whl, this is all we can do
+	PIP_CONFIG_FILE=/dev/null pip3 install --isolated --root=${DESTDIR} --prefix=/usr --ignore-installed --no-deps dist/ankirspy*.whl
+
+	# Copied from arch's PKGBUILD
+	install -Dm755 qt/runanki "${DESTDIR}/usr/bin/anki"
+	install -Dm644 qt/anki.desktop "${DESTDIR}/usr/share/applications/anki.desktop"
+	install -Dm644 qt/anki.png "${DESTDIR}/usr/share/pixmaps/anki.png"
+}
+
 post_install() {
 	vlicense LICENSE
 }
+
+# Remove rustup
+do_clean() {
+	rm -rf /usr/rustup
+}

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
  2020-05-23  7:07 ` [PR PATCH] [Updated] " fosslinux
  2020-05-24  5:37 ` fosslinux
@ 2020-05-24  5:39 ` fosslinux
  2020-05-28  7:38 ` [PR PATCH] [Updated] " fosslinux
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-05-24  5:39 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 374 bytes --]

New comment by fosslinux on void-packages repository

https://github.com/void-linux/void-packages/pull/22219#issuecomment-633182822

Comment:
I have been using this for the past few hours, it now runs. Don't know if musl will work this time, if it dosen't I'll need to go through nightlys into I find one that builds, one of the crates doesn't build for the newest nightly.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PR PATCH] [Updated] WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (2 preceding siblings ...)
  2020-05-24  5:39 ` fosslinux
@ 2020-05-28  7:38 ` fosslinux
  2020-05-30  1:53 ` fosslinux
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-05-28  7:38 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 2109 bytes --]

There is an updated pull request by fosslinux against master on the void-packages repository

https://github.com/fosslinux/void-packages anki-2.1.26
https://github.com/void-linux/void-packages/pull/22219

WIP: anki: update to 2.1.26
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust (nightly!), nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- same thing with python-protobuf, but for anki and at runtime
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.
- anki uses rustup. This is because it and some of its dependencies require archd code (notably pyo3). This is unavoidable, afaict.

Still todo:

- [x] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [x] Update python3-protobuf - hopefully will fix `AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'`.
- [ ] Look into travis musl error. https://github.com/rust-lang/rust/issues/40174. Hopefully, using rust 1.44 as the rust version *should* fix this. What a PITA. I understand that this is because it works when I cross-compile to x86_64-musl from x86_64 but we need it to work native build from x86_64-musl for the builders...
- [ ] Travis wth on i686?
- [x] Make it open.
- [ ] More extensive runtime testing.
- [ ] Runtime test on musl.

Questions:

- Is there any problems with removing `arch=nocross`?
- Does the rustup stuff look (somewhat) sane?
- Are the patches sane?

A patch file from https://github.com/void-linux/void-packages/pull/22219.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-anki-2.1.26-22219.patch --]
[-- Type: text/x-diff, Size: 31841 bytes --]

From 78816216511379aa1b82f106aeffe9266c10ca18 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sun, 24 May 2020 15:37:00 +1000
Subject: [PATCH 1/7] python-protobuf: update to 3.12.1

---
 srcpkgs/python-protobuf/template | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/srcpkgs/python-protobuf/template b/srcpkgs/python-protobuf/template
index 1a2d37a0a1e..a96fd539894 100644
--- a/srcpkgs/python-protobuf/template
+++ b/srcpkgs/python-protobuf/template
@@ -1,19 +1,19 @@
 # Template file for 'python-protobuf'
 pkgname=python-protobuf
-version=3.10.0
-revision=2
+version=3.12.1
+revision=1
 archs=noarch
 wrksrc="protobuf-${version}"
+build_wrksrc="python"
 build_style=python-module
-pycompile_module="google/protobuf"
-hostmakedepends="python-setuptools python3-setuptools"
+hostmakedepends="python-setuptools python3-setuptools protobuf"
 depends="python-setuptools python-six"
 short_desc="Python2 bindings for Google Protocol Buffers"
 maintainer="Charles E. Lehner <cel@celehner.com>"
 license="BSD-3-Clause"
 homepage="https://developers.google.com/protocol-buffers/"
-distfiles="${PYPI_SITE}/p/protobuf/protobuf-${version}.tar.gz"
-checksum=db83b5c12c0cd30150bb568e6feb2435c49ce4e68fe2d7b903113f0e221e58fe
+distfiles="https://github.com/protocolbuffers/protobuf/archive/v${version}.tar.gz"
+checksum=cb9b3f9d625b5739a358268eb3421de11cacd90025f5f7672c3930553eca810e
 
 post_install() {
 	sed -n 1,29p google/protobuf/__init__.py >LICENSE
@@ -22,7 +22,6 @@ post_install() {
 
 python3-protobuf_package() {
 	archs=noarch
-	pycompile_module="google/protobuf"
 	depends="python3-setuptools python3-six"
 	short_desc="${short_desc/Python2/Python3}"
 	pkg_install() {

From 7712eb76d5743a2c0c3d75747bc3ea0f5f2e4e0b Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:01 +1000
Subject: [PATCH 2/7] python3-mypy: update to 0.770, claim maintainership

---
 srcpkgs/python3-mypy/template | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/python3-mypy/template b/srcpkgs/python3-mypy/template
index 5d7f93d5772..bde1e7f4be6 100644
--- a/srcpkgs/python3-mypy/template
+++ b/srcpkgs/python3-mypy/template
@@ -1,19 +1,18 @@
 # Template file for 'python3-mypy'
 pkgname=python3-mypy
-version=0.761
+version=0.770
 revision=1
 archs=noarch
 wrksrc="mypy-${version}"
 build_style=python3-module
-pycompile_module="mypy"
 hostmakedepends="python3-setuptools"
 depends="python3-mypy_extensions python3-typed-ast python3-typing_extensions"
 short_desc="Optional static typing for Python3"
-maintainer="Orphaned <orphan@voidlinux.org>"
+maintainer="fosslinux <fosslinux@aussies.space>"
 license="MIT"
 homepage="https://github.com/python/mypy"
 distfiles="${PYPI_SITE}/m/mypy/mypy-${version}.tar.gz"
-checksum=85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf
+checksum=8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae
 
 post_install() {
 	vlicense LICENSE

From 6efdf584b76652d8f2df4ea2130474e3b1576340 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:34:38 +1000
Subject: [PATCH 3/7] New package: maturin-0.8.1

---
 .../patches/cross-compile-setup-py.patch      | 14 +++++++++++++
 srcpkgs/maturin/template                      | 21 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 srcpkgs/maturin/patches/cross-compile-setup-py.patch
 create mode 100644 srcpkgs/maturin/template

diff --git a/srcpkgs/maturin/patches/cross-compile-setup-py.patch b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
new file mode 100644
index 00000000000..e57189cb7ab
--- /dev/null
+++ b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
@@ -0,0 +1,14 @@
+--- setup.py	2020-04-30 22:36:01.000000000 +1000
++++ setup.py	2020-05-20 14:31:40.404994499 +1000
+@@ -56,9 +56,9 @@
+                     "(https://www.rust-lang.org/tools/install) and try again"
+                 )
+             subprocess.check_call(
+-                ["cargo", "rustc", "--bin", "maturin", "--", "-C", "link-arg=-s"]
++                ["cargo", "rustc", "--bin", "maturin", "--release", "--target", os.environ["RUST_TARGET"], "--", "-C", "link-arg=-s", "-C", "linker=" + os.environ["CC"].split(" ", 1)[0]]
+             )
+-            source = os.path.join(source_dir, "target", "debug", executable_name)
++            source = os.path.join(source_dir, "target", os.environ["RUST_TARGET"], "release", executable_name)
+         # run this after trying to build with cargo (as otherwise this leaves
+         # venv in a bad state: https://github.com/benfred/py-spy/issues/69)
+         install.run(self)
diff --git a/srcpkgs/maturin/template b/srcpkgs/maturin/template
new file mode 100644
index 00000000000..7eba36204f9
--- /dev/null
+++ b/srcpkgs/maturin/template
@@ -0,0 +1,21 @@
+# Template file for 'maturin'
+pkgname=maturin
+version=0.8.1
+revision=1
+build_style=python3-module
+hostmakedepends="cargo python3-setuptools python3-toml"
+makedepends="rust rust-std llvm9"
+short_desc="Build and publish crates with python bindings"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0, MIT"
+homepage="https://github.com/PyO3/maturin"
+distfiles="https://github.com/PyO3/maturin/archive/v${version}.tar.gz"
+checksum=b72a9885cda3ba4e53906a43aab101acb790622218ade6405b2ddf1ef1461f8f
+
+post_install() {
+	# Dynamic detection of python version
+	PYTHON_VERSION=$(python3 --version | sed "s/^Python //" | rev | sed "s/^[0-9]*.//" | rev)
+	mkdir -p "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	mv "${DESTDIR}/maturin" "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	vlicense license-mit
+}

From bf0b313f13c558529acb46ef74b3841997b9d5d9 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:25 +1000
Subject: [PATCH 4/7] New package: mypy-protobuf-python-1.13

---
 srcpkgs/mypy-protobuf-python/template | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-python/template

diff --git a/srcpkgs/mypy-protobuf-python/template b/srcpkgs/mypy-protobuf-python/template
new file mode 100644
index 00000000000..391d75f0c9e
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-python/template
@@ -0,0 +1,23 @@
+# Template file for 'mypy-protobuf-python'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-go
+#
+pkgname=mypy-protobuf-python
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_wrksrc=python
+build_style=python3-module
+hostmakedepends="python3-setuptools"
+depends="python3-mypy python3-typing_extensions python3-protobuf protobuf"
+short_desc="Generate mypy stubs from protobufs - Python implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74
+
+post_install() {
+	# We are not windows, remove the batch file
+	rm "${DESTDIR}/usr/bin/protoc_gen_mypy.bat"
+}

From 0e9530bdee8b9d76ea8bfd4e50087eac4294e2af Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:37 +1000
Subject: [PATCH 5/7] New package: mypy-protobuf-go-1.13

---
 .../patches/remote-go-improt.patch            | 11 +++++++++++
 srcpkgs/mypy-protobuf-go/template             | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
 create mode 100644 srcpkgs/mypy-protobuf-go/template

diff --git a/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
new file mode 100644
index 00000000000..300504bc70d
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
@@ -0,0 +1,11 @@
+--- go/src/protoc-gen-mypy/main.go.orig	2020-05-22 11:58:07.760761664 +1000
++++ go/src/protoc-gen-mypy/main.go	2020-05-22 11:58:00.595762190 +1000
+@@ -6,7 +6,7 @@
+ 	"sort"
+ 	"strings"
+ 
+-	"proto/mypy"
++	"github.com/dropbox/mypy-protobuf/go/src/proto/mypy"
+ 
+ 	"github.com/gogo/protobuf/proto"
+ 	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
diff --git a/srcpkgs/mypy-protobuf-go/template b/srcpkgs/mypy-protobuf-go/template
new file mode 100644
index 00000000000..8f00e43d8a8
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/template
@@ -0,0 +1,19 @@
+# Template file for 'mypy-protobuf-go'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-python
+#
+pkgname=mypy-protobuf-go
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_style=go
+go_import_path="github.com/dropbox/mypy-protobuf"
+go_package="${go_import_path}/go/src/protoc-gen-mypy"
+hostmakedepends="git"
+depends="protobuf"
+short_desc="Generate mypy stubs from protobufs - go implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74

From 7dbe4213090b5647b997d079f3a7823e15cfba0d Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:36 +1000
Subject: [PATCH 6/7] New package: python-stringcase-1.2.0

---
 srcpkgs/python-stringcase/template | 28 ++++++++++++++++++++++++++++
 srcpkgs/python3-stringcase         |  1 +
 2 files changed, 29 insertions(+)
 create mode 100644 srcpkgs/python-stringcase/template
 create mode 120000 srcpkgs/python3-stringcase

diff --git a/srcpkgs/python-stringcase/template b/srcpkgs/python-stringcase/template
new file mode 100644
index 00000000000..849e677c784
--- /dev/null
+++ b/srcpkgs/python-stringcase/template
@@ -0,0 +1,28 @@
+# Template file for 'python-stringcase'
+pkgname=python-stringcase
+version=1.2.0
+revision=1
+wrksrc="stringcase-${version}"
+build_style=python-module
+hostmakedepends="python-devel python3-devel"
+makedepends="${hostmakedepends}"
+depends="python"
+short_desc="String case converter for Python2"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="MIT"
+homepage="https://github.com/okunishinishi/python-stringcase"
+distfiles="${PYPI_SITE}/s/stringcase/stringcase-${version}.tar.gz"
+checksum=48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008
+
+post_install() {
+	vlicense LICENSE
+}
+
+python3-stringcase_package() {
+	depends="python3"
+	short_desc="${short_desc/Python2/Python3}"
+	pkg_install() {
+		vmove usr/lib/python3*
+		vlicense LICENSE
+	}
+}
diff --git a/srcpkgs/python3-stringcase b/srcpkgs/python3-stringcase
new file mode 120000
index 00000000000..53938bd1f0c
--- /dev/null
+++ b/srcpkgs/python3-stringcase
@@ -0,0 +1 @@
+python-stringcase
\ No newline at end of file

From 0bb7feb6288a612ac0dd22879440c25fb227ed2d Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:36:21 +1000
Subject: [PATCH 7/7] anki: update to 2.1.26

Has turned into a Bad Build System. Now uses rust nightly, python
(with bindings!), qt5, nodejs... the list goes on. There are quite
a few hacks and the like.
---
 srcpkgs/anki/patches/aqt_data-fhs.patch       |  45 +++
 srcpkgs/anki/patches/rust-nightly-fix.patch   | 274 ++++++++++++++++++
 .../anki/patches/rustc-cross-compile.patch    |  11 +
 .../patches/update-rust-nightly-version.patch |   5 +
 srcpkgs/anki/patches/vendored-deps.patch      |  94 ++++++
 srcpkgs/anki/template                         |  64 +++-
 6 files changed, 486 insertions(+), 7 deletions(-)
 create mode 100644 srcpkgs/anki/patches/aqt_data-fhs.patch
 create mode 100644 srcpkgs/anki/patches/rust-nightly-fix.patch
 create mode 100644 srcpkgs/anki/patches/rustc-cross-compile.patch
 create mode 100644 srcpkgs/anki/patches/update-rust-nightly-version.patch
 create mode 100644 srcpkgs/anki/patches/vendored-deps.patch

diff --git a/srcpkgs/anki/patches/aqt_data-fhs.patch b/srcpkgs/anki/patches/aqt_data-fhs.patch
new file mode 100644
index 00000000000..ac0d29ec082
--- /dev/null
+++ b/srcpkgs/anki/patches/aqt_data-fhs.patch
@@ -0,0 +1,45 @@
+From a0a9ac1aeb8b8678f1102aed81010a901ad8d9e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Johannes=20L=C3=B6thberg?= <johannes@kyriasis.com>
+Date: Sun, 29 Mar 2020 06:24:43 +0200
+Subject: [PATCH 1/4] Move aqt_data to sys.prefix/share
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+These files do _not_ belong right under sys.prefix.
+
+Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
+---
+ qt/aqt/utils.py | 2 +-
+ qt/setup.py     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git qt/aqt/utils.py qt/aqt/utils.py
+index a0e12362..4d8c8c34 100644
+--- qt/aqt/utils.py
++++ qt/aqt/utils.py
+@@ -21,7 +21,7 @@ from aqt.theme import theme_manager
+ 
+ def aqt_data_folder() -> str:
+     # wheel install?
+-    dir = os.path.join(sys.prefix, "aqt_data")
++    dir = os.path.join(sys.prefix,"share", "aqt_data")
+     if not os.path.exists(dir) or not os.listdir(dir):
+         # running in place?
+         dir = os.path.join(os.path.dirname(__file__), "..", "aqt_data")
+diff --git qt/setup.py qt/setup.py
+index 38f4e2b7..bdda3baa 100644
+--- qt/setup.py
++++ qt/setup.py
+@@ -8,7 +8,7 @@ import setuptools
+ def package_files(directory):
+     entries = []
+     for (path, directories, filenames) in os.walk(directory):
+-        entries.append((path, [os.path.join(path, f) for f in filenames]))
++        entries.append((os.path.join("share", path), [os.path.join(path, f) for f in filenames]))
+     return entries
+ 
+ 
+-- 
+2.26.2
+
diff --git a/srcpkgs/anki/patches/rust-nightly-fix.patch b/srcpkgs/anki/patches/rust-nightly-fix.patch
new file mode 100644
index 00000000000..3d70aa36aad
--- /dev/null
+++ b/srcpkgs/anki/patches/rust-nightly-fix.patch
@@ -0,0 +1,274 @@
+From fb578a0c2dc391f37de7cb6969c40f34d0de845c Mon Sep 17 00:00:00 2001
+From: Damien Elmes <gpg@ankiweb.net>
+Date: Fri, 24 Apr 2020 13:39:14 +1000
+Subject: [PATCH] switch to owned strings in ParsedTemplate
+
+will make it easier to cache the parsed results in the future,
+and handle field renames & other transformations
+---
+ rslib/src/notetype/cardgen.rs   |  6 +-
+ rslib/src/notetype/templates.rs |  2 +-
+ rslib/src/template.rs           | 98 +++++++++++++++++----------------
+ 3 files changed, 56 insertions(+), 50 deletions(-)
+
+Backported by fossy to stable. notetype patch is not needed.
+
+diff --git rslib/src/template.rs rslib/src/template.rs
+index 4479899009..ed5fe7e916 100644
+--- rslib/src/template.rs
++++ rslib/src/template.rs
+@@ -147,26 +147,26 @@ fn legacy_tokens(mut data: &str) -> impl Iterator<Item = TemplateResult<Token>>
+ //----------------------------------------
+ 
+ #[derive(Debug, PartialEq)]
+-enum ParsedNode<'a> {
+-    Text(&'a str),
++enum ParsedNode {
++    Text(String),
+     Replacement {
+-        key: &'a str,
+-        filters: Vec<&'a str>,
++        key: String,
++        filters: Vec<String>,
+     },
+     Conditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+     NegatedConditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+ }
+ 
+ #[derive(Debug)]
+-pub struct ParsedTemplate<'a>(Vec<ParsedNode<'a>>);
++pub struct ParsedTemplate(Vec<ParsedNode>);
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Create a template from the provided text.
+     pub fn from_text(template: &str) -> TemplateResult<ParsedTemplate> {
+         let mut iter = tokens(template);
+@@ -177,26 +177,26 @@ impl ParsedTemplate<'_> {
+ fn parse_inner<'a, I: Iterator<Item = TemplateResult<Token<'a>>>>(
+     iter: &mut I,
+     open_tag: Option<&'a str>,
+-) -> TemplateResult<Vec<ParsedNode<'a>>> {
++) -> TemplateResult<Vec<ParsedNode>> {
+     let mut nodes = vec![];
+ 
+     while let Some(token) = iter.next() {
+         use Token::*;
+         nodes.push(match token? {
+-            Text(t) => ParsedNode::Text(t),
++            Text(t) => ParsedNode::Text(t.into()),
+             Replacement(t) => {
+                 let mut it = t.rsplit(':');
+                 ParsedNode::Replacement {
+-                    key: it.next().unwrap(),
+-                    filters: it.collect(),
++                    key: it.next().unwrap().into(),
++                    filters: it.map(Into::into).collect(),
+                 }
+             }
+             OpenConditional(t) => ParsedNode::Conditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             OpenNegated(t) => ParsedNode::NegatedConditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             CloseConditional(t) => {
+@@ -285,27 +285,27 @@ fn localized_template_error(i18n: &I18n, err: TemplateError) -> String {
+ // Checking if template is empty
+ //----------------------------------------
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// true if provided fields are sufficient to render the template
+     pub fn renders_with_fields(&self, nonempty_fields: &HashSet<&str>) -> bool {
+         !template_is_empty(nonempty_fields, &self.0)
+     }
+ }
+ 
+-fn template_is_empty<'a>(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode<'a>]) -> bool {
++fn template_is_empty(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode]) -> bool {
+     use ParsedNode::*;
+     for node in nodes {
+         match node {
+             // ignore normal text
+             Text(_) => (),
+             Replacement { key, .. } => {
+-                if nonempty_fields.contains(*key) {
++                if nonempty_fields.contains(key.as_str()) {
+                     // a single replacement is enough
+                     return false;
+                 }
+             }
+             Conditional { key, children } => {
+-                if !nonempty_fields.contains(*key) {
++                if !nonempty_fields.contains(key.as_str()) {
+                     continue;
+                 }
+                 if !template_is_empty(nonempty_fields, children) {
+@@ -347,7 +347,7 @@ pub(crate) struct RenderContext<'a> {
+     pub card_ord: u16,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Render the template with the provided fields.
+     ///
+     /// Replacements that use only standard filters will become part of
+@@ -373,10 +373,7 @@ fn render_into(
+             Text(text) => {
+                 append_str_to_nodes(rendered_nodes, text);
+             }
+-            Replacement {
+-                key: key @ "FrontSide",
+-                ..
+-            } => {
++            Replacement { key, .. } if key == "FrontSide" => {
+                 // defer FrontSide rendering to Python, as extra
+                 // filters may be required
+                 rendered_nodes.push(RenderedNode::Replacement {
+@@ -385,27 +382,36 @@ fn render_into(
+                     current_text: "".into(),
+                 });
+             }
+-            Replacement { key: "", filters } if !filters.is_empty() => {
++            Replacement { key, filters } if key == "" && !filters.is_empty() => {
+                 // if a filter is provided, we accept an empty field name to
+                 // mean 'pass an empty string to the filter, and it will add
+                 // its own text'
+                 rendered_nodes.push(RenderedNode::Replacement {
+                     field_name: "".to_string(),
+                     current_text: "".to_string(),
+-                    filters: filters.iter().map(|&f| f.to_string()).collect(),
++                    filters: filters.clone(),
+                 })
+             }
+             Replacement { key, filters } => {
+                 // apply built in filters if field exists
+-                let (text, remaining_filters) = match context.fields.get(key) {
+-                    Some(text) => apply_filters(text, filters, key, context),
++                let (text, remaining_filters) = match context.fields.get(key.as_str()) {
++                    Some(text) => apply_filters(
++                        text,
++                        filters
++                            .iter()
++                            .map(|s| s.as_str())
++                            .collect::<Vec<_>>()
++                            .as_slice(),
++                        key,
++                        context,
++                    ),
+                     None => {
+                         // unknown field encountered
+                         let filters_str = filters
+                             .iter()
+                             .rev()
+                             .cloned()
+-                            .chain(iter::once(""))
++                            .chain(iter::once("".into()))
+                             .collect::<Vec<_>>()
+                             .join(":");
+                         return Err(TemplateError::FieldNotFound {
+@@ -427,12 +433,12 @@ fn render_into(
+                 }
+             }
+             Conditional { key, children } => {
+-                if context.nonempty_fields.contains(key) {
++                if context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+             NegatedConditional { key, children } => {
+-                if !context.nonempty_fields.contains(key) {
++                if !context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+@@ -542,7 +548,7 @@ pub enum FieldRequirements {
+     None,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Return fields required by template.
+     ///
+     /// This is not able to represent negated expressions or combinations of
+@@ -613,11 +619,11 @@
+             vec![
+-                Text("foo "),
++                Text("foo ".into()),
+                 Replacement {
+-                    key: "bar",
++                    key: "bar".into(),
+                     filters: vec![]
+                 },
+-                Text(" "),
++                Text(" ".into()),
+                 Conditional {
+-                    key: "baz",
+-                    children: vec![Text(" quux ")]
++                    key: "baz".into(),
++                    children: vec![Text(" quux ".into())]
+                 }
+             ]
+@@ -630,7 +636,7 @@ mod test {
+         assert_eq!(
+             tmpl.0,
+             vec![NegatedConditional {
+-                key: "baz",
++                key: "baz".into(),
+                 children: vec![]
+             }]
+         );
+@@ -643,7 +649,7 @@ mod test {
+         assert_eq!(
+             PT::from_text("{{ tag }}").unwrap().0,
+             vec![Replacement {
+-                key: "tag",
++                key: "tag".into(),
+                 filters: vec![]
+             }]
+         );
+@@ -651,7 +657,7 @@ mod test {
+         // stray closing characters (like in javascript) are ignored
+         assert_eq!(
+             PT::from_text("text }} more").unwrap().0,
+-            vec![Text("text }} more")]
++            vec![Text("text }} more".into())]
+         );
+ 
+         PT::from_text("{{").unwrap_err();
+@@ -737,15 +743,15 @@ mod test {
+         assert_eq!(
+             PT::from_text(input).unwrap().0,
+             vec![
+-                Text("\n"),
++                Text("\n".into()),
+                 Replacement {
+-                    key: "Front",
++                    key: "Front".into(),
+                     filters: vec![]
+                 },
+-                Text("\n"),
++                Text("\n".into()),
+                 Conditional {
+-                    key: "Back",
+-                    children: vec![Text("\n")]
++                    key: "Back".into(),
++                    children: vec![Text("\n".into())]
+                 }
+             ]
+         );
diff --git a/srcpkgs/anki/patches/rustc-cross-compile.patch b/srcpkgs/anki/patches/rustc-cross-compile.patch
new file mode 100644
index 00000000000..15239ea4cf1
--- /dev/null
+++ b/srcpkgs/anki/patches/rustc-cross-compile.patch
@@ -0,0 +1,11 @@
+--- rspy/Makefile	2020-05-23 12:02:29.758286838 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -69,7 +69,7 @@
+ .build/build: $(DEPS)
+ 	touch ../proto/backend.proto
+ 	${BUILD_VARIABLES} \
+-		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS)
++		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS) --target $(RUST_TARGET)
+    touch $@
+ 
+ check: .build/check
diff --git a/srcpkgs/anki/patches/update-rust-nightly-version.patch b/srcpkgs/anki/patches/update-rust-nightly-version.patch
new file mode 100644
index 00000000000..51e8afa7cf0
--- /dev/null
+++ b/srcpkgs/anki/patches/update-rust-nightly-version.patch
@@ -0,0 +1,5 @@
+--- rspy/rust-toolchain	2020-05-24 08:54:25.130010169 +1000
++++ rspy/rust-toolchain	2020-05-24 18:02:34.496636771 +1000
+@@ -1 +1 @@
+-nightly-2020-02-27
++nightly-2020-05-15
diff --git a/srcpkgs/anki/patches/vendored-deps.patch b/srcpkgs/anki/patches/vendored-deps.patch
new file mode 100644
index 00000000000..1d2bc90ffb1
--- /dev/null
+++ b/srcpkgs/anki/patches/vendored-deps.patch
@@ -0,0 +1,94 @@
+diff -u -r Makefile Makefile
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 18:40:54.345223164 +1000
+@@ -92,7 +92,7 @@
+ 	fi
+ 
+ .PHONY: develop
+-develop: pyenv buildhash prepare
++develop: buildhash prepare
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	for dir in $(DEVEL); do \
+diff -u -r pylib/Makefile pylib/Makefile
+--- pylib/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ pylib/Makefile	2020-05-19 18:50:01.075182994 +1000
+@@ -52,7 +52,7 @@
+ 	python -m black anki/hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks
++BUILD_STEPS := .build/vernum .build/py-proto anki/buildinfo.py .build/hooks
+ 
+ # Checking
+ ######################
+diff -u -r qt/Makefile qt/Makefile
+--- qt/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ qt/Makefile	2020-05-19 18:50:17.520181786 +1000
+@@ -64,7 +64,7 @@
+ 	python -m black aqt/gui_hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
++BUILD_STEPS := .build/vernum .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
+ 
+ # Checking
+ ######################
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 19:01:35.602131965 +1000
+@@ -122,7 +122,7 @@
+ 	@echo "Build complete."
+ 
+ .PHONY: build-rspy
+-build-rspy: pyenv buildhash
++build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+--- Makefile	2020-05-19 19:41:44.191955000 +1000
++++ Makefile	2020-05-19 19:42:21.423952264 +1000
+@@ -124,19 +124,16 @@
+ .PHONY: build-rspy
+ build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+ 
+ .PHONY: build-pylib
+ build-pylib:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C pylib build
+ 
+ .PHONY: build-qt
+ build-qt:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C qt build
+ 
+ .PHONY: clean
+--- rspy/Makefile	2020-05-21 20:06:35.945720983 +1000
++++ rspy/Makefile	2020-05-21 20:07:54.295720504 +1000
+@@ -86,10 +86,10 @@
+ RUST_TOOLCHAIN := $(shell cat rust-toolchain)
+ 
+ .build/tools: requirements.txt rust-toolchain
+-	python -m pip install -r requirements.txt
+ 	rustup toolchain install $(RUST_TOOLCHAIN)
+ 	rustup component add rustfmt-preview --toolchain $(RUST_TOOLCHAIN)
+ 	rustup component add clippy-preview --toolchain $(RUST_TOOLCHAIN)
++	rustup target add $(RUST_TARGET)
+ 	@touch $@
+ 
+ # we should not call clippy because it break things when running make check Mac OS
+--- pylib/Makefile	2020-05-22 08:46:14.988607539 +1000
++++ pylib/Makefile	2020-05-22 08:46:38.376605821 +1000
+@@ -41,7 +41,7 @@
+ 
+ PROTODEPS := $(wildcard ../proto/*.proto)
+ 
+-.build/py-proto: .build/dev-deps $(PROTODEPS)
++.build/py-proto: $(PROTODEPS)
+ 	protoc --proto_path=../proto --python_out=anki --mypy_out=anki $(PROTODEPS)
+ 	perl -i'' -pe 's/from fluent_pb2/from anki.fluent_pb2/' anki/backend_pb2.pyi
+ 	perl -i'' -pe 's/import fluent_pb2/import anki.fluent_pb2/' anki/backend_pb2.py
diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template
index 680e008a9d4..89e28d11b05 100644
--- a/srcpkgs/anki/template
+++ b/srcpkgs/anki/template
@@ -1,23 +1,73 @@
 # Template file for 'anki'
 pkgname=anki
-version=2.1.15
-revision=2
-archs=noarch
+version=2.1.26
+revision=1
 build_style=gnu-makefile
 pycompile_dirs="/usr/share/anki/anki /usr/share/anki/aqt"
+# rustup: anki needs nightly ... :(
+hostmakedepends="git python3 rustup maturin which protobuf
+ mypy-protobuf-python python3-stringcase black python3-wheel
+ rsync nodejs python3-PyQt5-devel-tools gettext
+ qt5-translations python3-pip"
 depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy
  python3-PyAudio python3-mpv python3-Markdown python3-send2trash
- python3-BeautifulSoup4 python3-decorator python3-jsonschema"
+ python3-BeautifulSoup4 python3-decorator python3-jsonschema
+ python3-protobuf"
 short_desc="Spaced repetition flashcard program"
 maintainer="Steve Prybylski <sa.prybylx@gmail.com>"
 license="AGPL-3.0-or-later"
 homepage="https://apps.ankiweb.net"
 changelog="https://apps.ankiweb.net/docs/changes.html"
-distfiles="https://apps.ankiweb.net/downloads/current/anki-${version}-source.tgz"
-checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89
-
+distfiles="https://github.com/ankitects/anki/archive/${version}.tar.gz"
+checksum=f5a0c41f3eebe0e77de9d46f2a5cbbe20f7c3a4787f0f02e1d33f298428acbdf
 python_version=3
 
+# When a non-clean masterdir is used, rust is often left over from a
+# previous rust-enabled build. Unfortunatly, xbps-src dosen't seem
+# to clean out rust -.- So, use /usr/rustup, to avoid this issue.
+export PATH=/usr/rustup/bin:${PATH}
+export LD_LIBRARY_PATH=/usr/rustup/lib:${LD_LIBRARY_PATH}
+export CARGO_HOME=/usr/rustup
+export RUSTUP_HOME=/usr/rustup
+
+pre_configure() {
+	# If do_clean didn't run last time, we are stuffed. Run do_clean now.
+	do_clean || true
+	printf "1\\n" | rustup-init -y
+}
+
+pre_build() {
+	mkdir -p dist
+	make prepare
+}
+
+do_build() {
+	RUSTFLAGS="-C target-feature=-crt-static" make build
+}
+
+do_install() {
+	pushd pylib
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	pushd qt
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	# maturin generates a .whl, this is all we can do
+	PIP_CONFIG_FILE=/dev/null pip3 install --isolated --root=${DESTDIR} --prefix=/usr --ignore-installed --no-deps dist/ankirspy*.whl
+
+	# Copied from arch's PKGBUILD
+	install -Dm755 qt/runanki "${DESTDIR}/usr/bin/anki"
+	install -Dm644 qt/anki.desktop "${DESTDIR}/usr/share/applications/anki.desktop"
+	install -Dm644 qt/anki.png "${DESTDIR}/usr/share/pixmaps/anki.png"
+}
+
 post_install() {
 	vlicense LICENSE
 }
+
+# Remove rustup
+do_clean() {
+	rm -rf /usr/rustup
+}

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PR PATCH] [Updated] WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (3 preceding siblings ...)
  2020-05-28  7:38 ` [PR PATCH] [Updated] " fosslinux
@ 2020-05-30  1:53 ` fosslinux
  2020-06-01  9:58 ` fosslinux
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-05-30  1:53 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 2109 bytes --]

There is an updated pull request by fosslinux against master on the void-packages repository

https://github.com/fosslinux/void-packages anki-2.1.26
https://github.com/void-linux/void-packages/pull/22219

WIP: anki: update to 2.1.26
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust (nightly!), nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- same thing with python-protobuf, but for anki and at runtime
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.
- anki uses rustup. This is because it and some of its dependencies require archd code (notably pyo3). This is unavoidable, afaict.

Still todo:

- [x] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [x] Update python3-protobuf - hopefully will fix `AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'`.
- [ ] Look into travis musl error. https://github.com/rust-lang/rust/issues/40174. Hopefully, using rust 1.44 as the rust version *should* fix this. What a PITA. I understand that this is because it works when I cross-compile to x86_64-musl from x86_64 but we need it to work native build from x86_64-musl for the builders...
- [ ] Travis wth on i686?
- [x] Make it open.
- [ ] More extensive runtime testing.
- [ ] Runtime test on musl.

Questions:

- Is there any problems with removing `arch=nocross`?
- Does the rustup stuff look (somewhat) sane?
- Are the patches sane?

A patch file from https://github.com/void-linux/void-packages/pull/22219.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-anki-2.1.26-22219.patch --]
[-- Type: text/x-diff, Size: 31713 bytes --]

From 78816216511379aa1b82f106aeffe9266c10ca18 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sun, 24 May 2020 15:37:00 +1000
Subject: [PATCH 1/7] python-protobuf: update to 3.12.1

---
 srcpkgs/python-protobuf/template | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/srcpkgs/python-protobuf/template b/srcpkgs/python-protobuf/template
index 1a2d37a0a1e..a96fd539894 100644
--- a/srcpkgs/python-protobuf/template
+++ b/srcpkgs/python-protobuf/template
@@ -1,19 +1,19 @@
 # Template file for 'python-protobuf'
 pkgname=python-protobuf
-version=3.10.0
-revision=2
+version=3.12.1
+revision=1
 archs=noarch
 wrksrc="protobuf-${version}"
+build_wrksrc="python"
 build_style=python-module
-pycompile_module="google/protobuf"
-hostmakedepends="python-setuptools python3-setuptools"
+hostmakedepends="python-setuptools python3-setuptools protobuf"
 depends="python-setuptools python-six"
 short_desc="Python2 bindings for Google Protocol Buffers"
 maintainer="Charles E. Lehner <cel@celehner.com>"
 license="BSD-3-Clause"
 homepage="https://developers.google.com/protocol-buffers/"
-distfiles="${PYPI_SITE}/p/protobuf/protobuf-${version}.tar.gz"
-checksum=db83b5c12c0cd30150bb568e6feb2435c49ce4e68fe2d7b903113f0e221e58fe
+distfiles="https://github.com/protocolbuffers/protobuf/archive/v${version}.tar.gz"
+checksum=cb9b3f9d625b5739a358268eb3421de11cacd90025f5f7672c3930553eca810e
 
 post_install() {
 	sed -n 1,29p google/protobuf/__init__.py >LICENSE
@@ -22,7 +22,6 @@ post_install() {
 
 python3-protobuf_package() {
 	archs=noarch
-	pycompile_module="google/protobuf"
 	depends="python3-setuptools python3-six"
 	short_desc="${short_desc/Python2/Python3}"
 	pkg_install() {

From 7712eb76d5743a2c0c3d75747bc3ea0f5f2e4e0b Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:01 +1000
Subject: [PATCH 2/7] python3-mypy: update to 0.770, claim maintainership

---
 srcpkgs/python3-mypy/template | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/python3-mypy/template b/srcpkgs/python3-mypy/template
index 5d7f93d5772..bde1e7f4be6 100644
--- a/srcpkgs/python3-mypy/template
+++ b/srcpkgs/python3-mypy/template
@@ -1,19 +1,18 @@
 # Template file for 'python3-mypy'
 pkgname=python3-mypy
-version=0.761
+version=0.770
 revision=1
 archs=noarch
 wrksrc="mypy-${version}"
 build_style=python3-module
-pycompile_module="mypy"
 hostmakedepends="python3-setuptools"
 depends="python3-mypy_extensions python3-typed-ast python3-typing_extensions"
 short_desc="Optional static typing for Python3"
-maintainer="Orphaned <orphan@voidlinux.org>"
+maintainer="fosslinux <fosslinux@aussies.space>"
 license="MIT"
 homepage="https://github.com/python/mypy"
 distfiles="${PYPI_SITE}/m/mypy/mypy-${version}.tar.gz"
-checksum=85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf
+checksum=8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae
 
 post_install() {
 	vlicense LICENSE

From 6efdf584b76652d8f2df4ea2130474e3b1576340 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:34:38 +1000
Subject: [PATCH 3/7] New package: maturin-0.8.1

---
 .../patches/cross-compile-setup-py.patch      | 14 +++++++++++++
 srcpkgs/maturin/template                      | 21 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 srcpkgs/maturin/patches/cross-compile-setup-py.patch
 create mode 100644 srcpkgs/maturin/template

diff --git a/srcpkgs/maturin/patches/cross-compile-setup-py.patch b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
new file mode 100644
index 00000000000..e57189cb7ab
--- /dev/null
+++ b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
@@ -0,0 +1,14 @@
+--- setup.py	2020-04-30 22:36:01.000000000 +1000
++++ setup.py	2020-05-20 14:31:40.404994499 +1000
+@@ -56,9 +56,9 @@
+                     "(https://www.rust-lang.org/tools/install) and try again"
+                 )
+             subprocess.check_call(
+-                ["cargo", "rustc", "--bin", "maturin", "--", "-C", "link-arg=-s"]
++                ["cargo", "rustc", "--bin", "maturin", "--release", "--target", os.environ["RUST_TARGET"], "--", "-C", "link-arg=-s", "-C", "linker=" + os.environ["CC"].split(" ", 1)[0]]
+             )
+-            source = os.path.join(source_dir, "target", "debug", executable_name)
++            source = os.path.join(source_dir, "target", os.environ["RUST_TARGET"], "release", executable_name)
+         # run this after trying to build with cargo (as otherwise this leaves
+         # venv in a bad state: https://github.com/benfred/py-spy/issues/69)
+         install.run(self)
diff --git a/srcpkgs/maturin/template b/srcpkgs/maturin/template
new file mode 100644
index 00000000000..7eba36204f9
--- /dev/null
+++ b/srcpkgs/maturin/template
@@ -0,0 +1,21 @@
+# Template file for 'maturin'
+pkgname=maturin
+version=0.8.1
+revision=1
+build_style=python3-module
+hostmakedepends="cargo python3-setuptools python3-toml"
+makedepends="rust rust-std llvm9"
+short_desc="Build and publish crates with python bindings"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0, MIT"
+homepage="https://github.com/PyO3/maturin"
+distfiles="https://github.com/PyO3/maturin/archive/v${version}.tar.gz"
+checksum=b72a9885cda3ba4e53906a43aab101acb790622218ade6405b2ddf1ef1461f8f
+
+post_install() {
+	# Dynamic detection of python version
+	PYTHON_VERSION=$(python3 --version | sed "s/^Python //" | rev | sed "s/^[0-9]*.//" | rev)
+	mkdir -p "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	mv "${DESTDIR}/maturin" "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	vlicense license-mit
+}

From bf0b313f13c558529acb46ef74b3841997b9d5d9 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:25 +1000
Subject: [PATCH 4/7] New package: mypy-protobuf-python-1.13

---
 srcpkgs/mypy-protobuf-python/template | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-python/template

diff --git a/srcpkgs/mypy-protobuf-python/template b/srcpkgs/mypy-protobuf-python/template
new file mode 100644
index 00000000000..391d75f0c9e
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-python/template
@@ -0,0 +1,23 @@
+# Template file for 'mypy-protobuf-python'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-go
+#
+pkgname=mypy-protobuf-python
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_wrksrc=python
+build_style=python3-module
+hostmakedepends="python3-setuptools"
+depends="python3-mypy python3-typing_extensions python3-protobuf protobuf"
+short_desc="Generate mypy stubs from protobufs - Python implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74
+
+post_install() {
+	# We are not windows, remove the batch file
+	rm "${DESTDIR}/usr/bin/protoc_gen_mypy.bat"
+}

From 0e9530bdee8b9d76ea8bfd4e50087eac4294e2af Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:37 +1000
Subject: [PATCH 5/7] New package: mypy-protobuf-go-1.13

---
 .../patches/remote-go-improt.patch            | 11 +++++++++++
 srcpkgs/mypy-protobuf-go/template             | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
 create mode 100644 srcpkgs/mypy-protobuf-go/template

diff --git a/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
new file mode 100644
index 00000000000..300504bc70d
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
@@ -0,0 +1,11 @@
+--- go/src/protoc-gen-mypy/main.go.orig	2020-05-22 11:58:07.760761664 +1000
++++ go/src/protoc-gen-mypy/main.go	2020-05-22 11:58:00.595762190 +1000
+@@ -6,7 +6,7 @@
+ 	"sort"
+ 	"strings"
+ 
+-	"proto/mypy"
++	"github.com/dropbox/mypy-protobuf/go/src/proto/mypy"
+ 
+ 	"github.com/gogo/protobuf/proto"
+ 	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
diff --git a/srcpkgs/mypy-protobuf-go/template b/srcpkgs/mypy-protobuf-go/template
new file mode 100644
index 00000000000..8f00e43d8a8
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/template
@@ -0,0 +1,19 @@
+# Template file for 'mypy-protobuf-go'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-python
+#
+pkgname=mypy-protobuf-go
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_style=go
+go_import_path="github.com/dropbox/mypy-protobuf"
+go_package="${go_import_path}/go/src/protoc-gen-mypy"
+hostmakedepends="git"
+depends="protobuf"
+short_desc="Generate mypy stubs from protobufs - go implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74

From 7dbe4213090b5647b997d079f3a7823e15cfba0d Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:36 +1000
Subject: [PATCH 6/7] New package: python-stringcase-1.2.0

---
 srcpkgs/python-stringcase/template | 28 ++++++++++++++++++++++++++++
 srcpkgs/python3-stringcase         |  1 +
 2 files changed, 29 insertions(+)
 create mode 100644 srcpkgs/python-stringcase/template
 create mode 120000 srcpkgs/python3-stringcase

diff --git a/srcpkgs/python-stringcase/template b/srcpkgs/python-stringcase/template
new file mode 100644
index 00000000000..849e677c784
--- /dev/null
+++ b/srcpkgs/python-stringcase/template
@@ -0,0 +1,28 @@
+# Template file for 'python-stringcase'
+pkgname=python-stringcase
+version=1.2.0
+revision=1
+wrksrc="stringcase-${version}"
+build_style=python-module
+hostmakedepends="python-devel python3-devel"
+makedepends="${hostmakedepends}"
+depends="python"
+short_desc="String case converter for Python2"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="MIT"
+homepage="https://github.com/okunishinishi/python-stringcase"
+distfiles="${PYPI_SITE}/s/stringcase/stringcase-${version}.tar.gz"
+checksum=48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008
+
+post_install() {
+	vlicense LICENSE
+}
+
+python3-stringcase_package() {
+	depends="python3"
+	short_desc="${short_desc/Python2/Python3}"
+	pkg_install() {
+		vmove usr/lib/python3*
+		vlicense LICENSE
+	}
+}
diff --git a/srcpkgs/python3-stringcase b/srcpkgs/python3-stringcase
new file mode 120000
index 00000000000..53938bd1f0c
--- /dev/null
+++ b/srcpkgs/python3-stringcase
@@ -0,0 +1 @@
+python-stringcase
\ No newline at end of file

From 0100907ae5898f4915af97f93030dca784dc4909 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:36:21 +1000
Subject: [PATCH 7/7] anki: update to 2.1.26

Has turned into a Bad Build System. Now uses rust nightly, python
(with bindings!), qt5, nodejs... the list goes on. There are quite
a few hacks and the like.
---
 srcpkgs/anki/patches/aqt_data-fhs.patch       |  45 +++
 srcpkgs/anki/patches/rust-nightly-fix.patch   | 274 ++++++++++++++++++
 .../anki/patches/rustc-cross-compile.patch    |  11 +
 .../patches/update-rust-nightly-version.patch |   5 +
 srcpkgs/anki/patches/vendored-deps.patch      |  94 ++++++
 srcpkgs/anki/template                         |  57 +++-
 6 files changed, 479 insertions(+), 7 deletions(-)
 create mode 100644 srcpkgs/anki/patches/aqt_data-fhs.patch
 create mode 100644 srcpkgs/anki/patches/rust-nightly-fix.patch
 create mode 100644 srcpkgs/anki/patches/rustc-cross-compile.patch
 create mode 100644 srcpkgs/anki/patches/update-rust-nightly-version.patch
 create mode 100644 srcpkgs/anki/patches/vendored-deps.patch

diff --git a/srcpkgs/anki/patches/aqt_data-fhs.patch b/srcpkgs/anki/patches/aqt_data-fhs.patch
new file mode 100644
index 00000000000..ac0d29ec082
--- /dev/null
+++ b/srcpkgs/anki/patches/aqt_data-fhs.patch
@@ -0,0 +1,45 @@
+From a0a9ac1aeb8b8678f1102aed81010a901ad8d9e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Johannes=20L=C3=B6thberg?= <johannes@kyriasis.com>
+Date: Sun, 29 Mar 2020 06:24:43 +0200
+Subject: [PATCH 1/4] Move aqt_data to sys.prefix/share
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+These files do _not_ belong right under sys.prefix.
+
+Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
+---
+ qt/aqt/utils.py | 2 +-
+ qt/setup.py     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git qt/aqt/utils.py qt/aqt/utils.py
+index a0e12362..4d8c8c34 100644
+--- qt/aqt/utils.py
++++ qt/aqt/utils.py
+@@ -21,7 +21,7 @@ from aqt.theme import theme_manager
+ 
+ def aqt_data_folder() -> str:
+     # wheel install?
+-    dir = os.path.join(sys.prefix, "aqt_data")
++    dir = os.path.join(sys.prefix,"share", "aqt_data")
+     if not os.path.exists(dir) or not os.listdir(dir):
+         # running in place?
+         dir = os.path.join(os.path.dirname(__file__), "..", "aqt_data")
+diff --git qt/setup.py qt/setup.py
+index 38f4e2b7..bdda3baa 100644
+--- qt/setup.py
++++ qt/setup.py
+@@ -8,7 +8,7 @@ import setuptools
+ def package_files(directory):
+     entries = []
+     for (path, directories, filenames) in os.walk(directory):
+-        entries.append((path, [os.path.join(path, f) for f in filenames]))
++        entries.append((os.path.join("share", path), [os.path.join(path, f) for f in filenames]))
+     return entries
+ 
+ 
+-- 
+2.26.2
+
diff --git a/srcpkgs/anki/patches/rust-nightly-fix.patch b/srcpkgs/anki/patches/rust-nightly-fix.patch
new file mode 100644
index 00000000000..3d70aa36aad
--- /dev/null
+++ b/srcpkgs/anki/patches/rust-nightly-fix.patch
@@ -0,0 +1,274 @@
+From fb578a0c2dc391f37de7cb6969c40f34d0de845c Mon Sep 17 00:00:00 2001
+From: Damien Elmes <gpg@ankiweb.net>
+Date: Fri, 24 Apr 2020 13:39:14 +1000
+Subject: [PATCH] switch to owned strings in ParsedTemplate
+
+will make it easier to cache the parsed results in the future,
+and handle field renames & other transformations
+---
+ rslib/src/notetype/cardgen.rs   |  6 +-
+ rslib/src/notetype/templates.rs |  2 +-
+ rslib/src/template.rs           | 98 +++++++++++++++++----------------
+ 3 files changed, 56 insertions(+), 50 deletions(-)
+
+Backported by fossy to stable. notetype patch is not needed.
+
+diff --git rslib/src/template.rs rslib/src/template.rs
+index 4479899009..ed5fe7e916 100644
+--- rslib/src/template.rs
++++ rslib/src/template.rs
+@@ -147,26 +147,26 @@ fn legacy_tokens(mut data: &str) -> impl Iterator<Item = TemplateResult<Token>>
+ //----------------------------------------
+ 
+ #[derive(Debug, PartialEq)]
+-enum ParsedNode<'a> {
+-    Text(&'a str),
++enum ParsedNode {
++    Text(String),
+     Replacement {
+-        key: &'a str,
+-        filters: Vec<&'a str>,
++        key: String,
++        filters: Vec<String>,
+     },
+     Conditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+     NegatedConditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+ }
+ 
+ #[derive(Debug)]
+-pub struct ParsedTemplate<'a>(Vec<ParsedNode<'a>>);
++pub struct ParsedTemplate(Vec<ParsedNode>);
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Create a template from the provided text.
+     pub fn from_text(template: &str) -> TemplateResult<ParsedTemplate> {
+         let mut iter = tokens(template);
+@@ -177,26 +177,26 @@ impl ParsedTemplate<'_> {
+ fn parse_inner<'a, I: Iterator<Item = TemplateResult<Token<'a>>>>(
+     iter: &mut I,
+     open_tag: Option<&'a str>,
+-) -> TemplateResult<Vec<ParsedNode<'a>>> {
++) -> TemplateResult<Vec<ParsedNode>> {
+     let mut nodes = vec![];
+ 
+     while let Some(token) = iter.next() {
+         use Token::*;
+         nodes.push(match token? {
+-            Text(t) => ParsedNode::Text(t),
++            Text(t) => ParsedNode::Text(t.into()),
+             Replacement(t) => {
+                 let mut it = t.rsplit(':');
+                 ParsedNode::Replacement {
+-                    key: it.next().unwrap(),
+-                    filters: it.collect(),
++                    key: it.next().unwrap().into(),
++                    filters: it.map(Into::into).collect(),
+                 }
+             }
+             OpenConditional(t) => ParsedNode::Conditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             OpenNegated(t) => ParsedNode::NegatedConditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             CloseConditional(t) => {
+@@ -285,27 +285,27 @@ fn localized_template_error(i18n: &I18n, err: TemplateError) -> String {
+ // Checking if template is empty
+ //----------------------------------------
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// true if provided fields are sufficient to render the template
+     pub fn renders_with_fields(&self, nonempty_fields: &HashSet<&str>) -> bool {
+         !template_is_empty(nonempty_fields, &self.0)
+     }
+ }
+ 
+-fn template_is_empty<'a>(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode<'a>]) -> bool {
++fn template_is_empty(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode]) -> bool {
+     use ParsedNode::*;
+     for node in nodes {
+         match node {
+             // ignore normal text
+             Text(_) => (),
+             Replacement { key, .. } => {
+-                if nonempty_fields.contains(*key) {
++                if nonempty_fields.contains(key.as_str()) {
+                     // a single replacement is enough
+                     return false;
+                 }
+             }
+             Conditional { key, children } => {
+-                if !nonempty_fields.contains(*key) {
++                if !nonempty_fields.contains(key.as_str()) {
+                     continue;
+                 }
+                 if !template_is_empty(nonempty_fields, children) {
+@@ -347,7 +347,7 @@ pub(crate) struct RenderContext<'a> {
+     pub card_ord: u16,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Render the template with the provided fields.
+     ///
+     /// Replacements that use only standard filters will become part of
+@@ -373,10 +373,7 @@ fn render_into(
+             Text(text) => {
+                 append_str_to_nodes(rendered_nodes, text);
+             }
+-            Replacement {
+-                key: key @ "FrontSide",
+-                ..
+-            } => {
++            Replacement { key, .. } if key == "FrontSide" => {
+                 // defer FrontSide rendering to Python, as extra
+                 // filters may be required
+                 rendered_nodes.push(RenderedNode::Replacement {
+@@ -385,27 +382,36 @@ fn render_into(
+                     current_text: "".into(),
+                 });
+             }
+-            Replacement { key: "", filters } if !filters.is_empty() => {
++            Replacement { key, filters } if key == "" && !filters.is_empty() => {
+                 // if a filter is provided, we accept an empty field name to
+                 // mean 'pass an empty string to the filter, and it will add
+                 // its own text'
+                 rendered_nodes.push(RenderedNode::Replacement {
+                     field_name: "".to_string(),
+                     current_text: "".to_string(),
+-                    filters: filters.iter().map(|&f| f.to_string()).collect(),
++                    filters: filters.clone(),
+                 })
+             }
+             Replacement { key, filters } => {
+                 // apply built in filters if field exists
+-                let (text, remaining_filters) = match context.fields.get(key) {
+-                    Some(text) => apply_filters(text, filters, key, context),
++                let (text, remaining_filters) = match context.fields.get(key.as_str()) {
++                    Some(text) => apply_filters(
++                        text,
++                        filters
++                            .iter()
++                            .map(|s| s.as_str())
++                            .collect::<Vec<_>>()
++                            .as_slice(),
++                        key,
++                        context,
++                    ),
+                     None => {
+                         // unknown field encountered
+                         let filters_str = filters
+                             .iter()
+                             .rev()
+                             .cloned()
+-                            .chain(iter::once(""))
++                            .chain(iter::once("".into()))
+                             .collect::<Vec<_>>()
+                             .join(":");
+                         return Err(TemplateError::FieldNotFound {
+@@ -427,12 +433,12 @@ fn render_into(
+                 }
+             }
+             Conditional { key, children } => {
+-                if context.nonempty_fields.contains(key) {
++                if context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+             NegatedConditional { key, children } => {
+-                if !context.nonempty_fields.contains(key) {
++                if !context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+@@ -542,7 +548,7 @@ pub enum FieldRequirements {
+     None,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Return fields required by template.
+     ///
+     /// This is not able to represent negated expressions or combinations of
+@@ -613,11 +619,11 @@
+             vec![
+-                Text("foo "),
++                Text("foo ".into()),
+                 Replacement {
+-                    key: "bar",
++                    key: "bar".into(),
+                     filters: vec![]
+                 },
+-                Text(" "),
++                Text(" ".into()),
+                 Conditional {
+-                    key: "baz",
+-                    children: vec![Text(" quux ")]
++                    key: "baz".into(),
++                    children: vec![Text(" quux ".into())]
+                 }
+             ]
+@@ -630,7 +636,7 @@ mod test {
+         assert_eq!(
+             tmpl.0,
+             vec![NegatedConditional {
+-                key: "baz",
++                key: "baz".into(),
+                 children: vec![]
+             }]
+         );
+@@ -643,7 +649,7 @@ mod test {
+         assert_eq!(
+             PT::from_text("{{ tag }}").unwrap().0,
+             vec![Replacement {
+-                key: "tag",
++                key: "tag".into(),
+                 filters: vec![]
+             }]
+         );
+@@ -651,7 +657,7 @@ mod test {
+         // stray closing characters (like in javascript) are ignored
+         assert_eq!(
+             PT::from_text("text }} more").unwrap().0,
+-            vec![Text("text }} more")]
++            vec![Text("text }} more".into())]
+         );
+ 
+         PT::from_text("{{").unwrap_err();
+@@ -737,15 +743,15 @@ mod test {
+         assert_eq!(
+             PT::from_text(input).unwrap().0,
+             vec![
+-                Text("\n"),
++                Text("\n".into()),
+                 Replacement {
+-                    key: "Front",
++                    key: "Front".into(),
+                     filters: vec![]
+                 },
+-                Text("\n"),
++                Text("\n".into()),
+                 Conditional {
+-                    key: "Back",
+-                    children: vec![Text("\n")]
++                    key: "Back".into(),
++                    children: vec![Text("\n".into())]
+                 }
+             ]
+         );
diff --git a/srcpkgs/anki/patches/rustc-cross-compile.patch b/srcpkgs/anki/patches/rustc-cross-compile.patch
new file mode 100644
index 00000000000..15239ea4cf1
--- /dev/null
+++ b/srcpkgs/anki/patches/rustc-cross-compile.patch
@@ -0,0 +1,11 @@
+--- rspy/Makefile	2020-05-23 12:02:29.758286838 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -69,7 +69,7 @@
+ .build/build: $(DEPS)
+ 	touch ../proto/backend.proto
+ 	${BUILD_VARIABLES} \
+-		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS)
++		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS) --target $(RUST_TARGET)
+    touch $@
+ 
+ check: .build/check
diff --git a/srcpkgs/anki/patches/update-rust-nightly-version.patch b/srcpkgs/anki/patches/update-rust-nightly-version.patch
new file mode 100644
index 00000000000..51e8afa7cf0
--- /dev/null
+++ b/srcpkgs/anki/patches/update-rust-nightly-version.patch
@@ -0,0 +1,5 @@
+--- rspy/rust-toolchain	2020-05-24 08:54:25.130010169 +1000
++++ rspy/rust-toolchain	2020-05-24 18:02:34.496636771 +1000
+@@ -1 +1 @@
+-nightly-2020-02-27
++nightly-2020-05-15
diff --git a/srcpkgs/anki/patches/vendored-deps.patch b/srcpkgs/anki/patches/vendored-deps.patch
new file mode 100644
index 00000000000..1d2bc90ffb1
--- /dev/null
+++ b/srcpkgs/anki/patches/vendored-deps.patch
@@ -0,0 +1,94 @@
+diff -u -r Makefile Makefile
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 18:40:54.345223164 +1000
+@@ -92,7 +92,7 @@
+ 	fi
+ 
+ .PHONY: develop
+-develop: pyenv buildhash prepare
++develop: buildhash prepare
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	for dir in $(DEVEL); do \
+diff -u -r pylib/Makefile pylib/Makefile
+--- pylib/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ pylib/Makefile	2020-05-19 18:50:01.075182994 +1000
+@@ -52,7 +52,7 @@
+ 	python -m black anki/hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks
++BUILD_STEPS := .build/vernum .build/py-proto anki/buildinfo.py .build/hooks
+ 
+ # Checking
+ ######################
+diff -u -r qt/Makefile qt/Makefile
+--- qt/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ qt/Makefile	2020-05-19 18:50:17.520181786 +1000
+@@ -64,7 +64,7 @@
+ 	python -m black aqt/gui_hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
++BUILD_STEPS := .build/vernum .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
+ 
+ # Checking
+ ######################
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 19:01:35.602131965 +1000
+@@ -122,7 +122,7 @@
+ 	@echo "Build complete."
+ 
+ .PHONY: build-rspy
+-build-rspy: pyenv buildhash
++build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+--- Makefile	2020-05-19 19:41:44.191955000 +1000
++++ Makefile	2020-05-19 19:42:21.423952264 +1000
+@@ -124,19 +124,16 @@
+ .PHONY: build-rspy
+ build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+ 
+ .PHONY: build-pylib
+ build-pylib:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C pylib build
+ 
+ .PHONY: build-qt
+ build-qt:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C qt build
+ 
+ .PHONY: clean
+--- rspy/Makefile	2020-05-21 20:06:35.945720983 +1000
++++ rspy/Makefile	2020-05-21 20:07:54.295720504 +1000
+@@ -86,10 +86,10 @@
+ RUST_TOOLCHAIN := $(shell cat rust-toolchain)
+ 
+ .build/tools: requirements.txt rust-toolchain
+-	python -m pip install -r requirements.txt
+ 	rustup toolchain install $(RUST_TOOLCHAIN)
+ 	rustup component add rustfmt-preview --toolchain $(RUST_TOOLCHAIN)
+ 	rustup component add clippy-preview --toolchain $(RUST_TOOLCHAIN)
++	rustup target add $(RUST_TARGET)
+ 	@touch $@
+ 
+ # we should not call clippy because it break things when running make check Mac OS
+--- pylib/Makefile	2020-05-22 08:46:14.988607539 +1000
++++ pylib/Makefile	2020-05-22 08:46:38.376605821 +1000
+@@ -41,7 +41,7 @@
+ 
+ PROTODEPS := $(wildcard ../proto/*.proto)
+ 
+-.build/py-proto: .build/dev-deps $(PROTODEPS)
++.build/py-proto: $(PROTODEPS)
+ 	protoc --proto_path=../proto --python_out=anki --mypy_out=anki $(PROTODEPS)
+ 	perl -i'' -pe 's/from fluent_pb2/from anki.fluent_pb2/' anki/backend_pb2.pyi
+ 	perl -i'' -pe 's/import fluent_pb2/import anki.fluent_pb2/' anki/backend_pb2.py
diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template
index 680e008a9d4..ebc5fa6b333 100644
--- a/srcpkgs/anki/template
+++ b/srcpkgs/anki/template
@@ -1,23 +1,66 @@
 # Template file for 'anki'
 pkgname=anki
-version=2.1.15
-revision=2
-archs=noarch
+version=2.1.26
+revision=1
 build_style=gnu-makefile
 pycompile_dirs="/usr/share/anki/anki /usr/share/anki/aqt"
+# rustup: anki needs nightly ... :(
+hostmakedepends="git python3 rustup maturin which protobuf
+ mypy-protobuf-python python3-stringcase black python3-wheel
+ rsync nodejs python3-PyQt5-devel-tools gettext
+qt5-translations python3-pip strace"
 depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy
  python3-PyAudio python3-mpv python3-Markdown python3-send2trash
- python3-BeautifulSoup4 python3-decorator python3-jsonschema"
+ python3-BeautifulSoup4 python3-decorator python3-jsonschema
+ python3-protobuf"
 short_desc="Spaced repetition flashcard program"
 maintainer="Steve Prybylski <sa.prybylx@gmail.com>"
 license="AGPL-3.0-or-later"
 homepage="https://apps.ankiweb.net"
 changelog="https://apps.ankiweb.net/docs/changes.html"
-distfiles="https://apps.ankiweb.net/downloads/current/anki-${version}-source.tgz"
-checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89
-
+distfiles="https://github.com/ankitects/anki/archive/${version}.tar.gz"
+checksum=f5a0c41f3eebe0e77de9d46f2a5cbbe20f7c3a4787f0f02e1d33f298428acbdf
 python_version=3
 
+# When a non-clean masterdir is used, rust is often left over from a
+# previous rust-enabled build. Unfortunatly, xbps-src dosen't seem
+# to clean out rust -.- So, use /usr/rustup, to avoid this issue.
+export PATH=/usr/rustup/bin:${PATH}
+export LD_LIBRARY_PATH=/usr/rustup/lib:${LD_LIBRARY_PATH}
+export CARGO_HOME="${wrksrc}/rustup"
+export RUSTUP_HOME="${wrksrc}/rustup"
+
+pre_configure() {
+	printf "1\\n" | rustup-init -y
+}
+
+pre_build() {
+	mkdir -p dist
+	make prepare
+}
+
+do_build() {
+	RUSTFLAGS="-C target-feature=-crt-static" make build
+}
+
+do_install() {
+	pushd pylib
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	pushd qt
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	# maturin generates a .whl, this is all we can do
+	PIP_CONFIG_FILE=/dev/null pip3 install --isolated --root=${DESTDIR} --prefix=/usr --ignore-installed --no-deps dist/ankirspy*.whl
+
+	# Copied from arch's PKGBUILD
+	install -Dm755 qt/runanki "${DESTDIR}/usr/bin/anki"
+	install -Dm644 qt/anki.desktop "${DESTDIR}/usr/share/applications/anki.desktop"
+	install -Dm644 qt/anki.png "${DESTDIR}/usr/share/pixmaps/anki.png"
+}
+
 post_install() {
 	vlicense LICENSE
 }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PR PATCH] [Updated] WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (4 preceding siblings ...)
  2020-05-30  1:53 ` fosslinux
@ 2020-06-01  9:58 ` fosslinux
  2020-06-01  9:59 ` fosslinux
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-06-01  9:58 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 2262 bytes --]

There is an updated pull request by fosslinux against master on the void-packages repository

https://github.com/fosslinux/void-packages anki-2.1.26
https://github.com/void-linux/void-packages/pull/22219

WIP: anki: update to 2.1.26
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust (nightly!), nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- same thing with python-protobuf, but for anki and at runtime
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.
- anki uses rustup. This is because it and some of its dependencies require archd code (notably pyo3). This is unavoidable, afaict.

Still todo:

- [x] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [x] Update python3-protobuf - hopefully will fix `AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'`.
- [x] Look into travis musl error. https://github.com/rust-lang/rust/issues/40174. Hopefully, using rust 1.44 as the rust version *should* fix this. What a PITA. I understand that this is because it works when I cross-compile to x86_64-musl from x86_64 but we need it to work native build from x86_64-musl for the builders...
- [ ] Get off rustup and onto rust stable. Needs either a) pyo3 to work on stable or b) anki to be patched for rust-cpython. Also blocked by rust 1.44.
- [ ] Travis wth on i686?
- [x] Make it open.
- [ ] More extensive runtime testing.
- [ ] Runtime test on musl.

Questions:

- Is there any problems with removing `arch=nocross`?
- Does the rustup stuff look (somewhat) sane?
- Are the patches sane?

A patch file from https://github.com/void-linux/void-packages/pull/22219.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-anki-2.1.26-22219.patch --]
[-- Type: text/x-diff, Size: 330225 bytes --]

From dc49d200c37f20e082261214f30c9f0ec0a316a3 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:01 +1000
Subject: [PATCH 1/6] python3-mypy: update to 0.770, claim maintainership

---
 srcpkgs/python3-mypy/template | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/python3-mypy/template b/srcpkgs/python3-mypy/template
index 5d7f93d5772..bde1e7f4be6 100644
--- a/srcpkgs/python3-mypy/template
+++ b/srcpkgs/python3-mypy/template
@@ -1,19 +1,18 @@
 # Template file for 'python3-mypy'
 pkgname=python3-mypy
-version=0.761
+version=0.770
 revision=1
 archs=noarch
 wrksrc="mypy-${version}"
 build_style=python3-module
-pycompile_module="mypy"
 hostmakedepends="python3-setuptools"
 depends="python3-mypy_extensions python3-typed-ast python3-typing_extensions"
 short_desc="Optional static typing for Python3"
-maintainer="Orphaned <orphan@voidlinux.org>"
+maintainer="fosslinux <fosslinux@aussies.space>"
 license="MIT"
 homepage="https://github.com/python/mypy"
 distfiles="${PYPI_SITE}/m/mypy/mypy-${version}.tar.gz"
-checksum=85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf
+checksum=8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae
 
 post_install() {
 	vlicense LICENSE

From 7c67feaeffb4ddbdef9fbe1a0459ac5ac5ecc439 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:34:38 +1000
Subject: [PATCH 2/6] New package: maturin-0.8.1

---
 .../patches/cross-compile-setup-py.patch      | 14 +++++++++++++
 srcpkgs/maturin/template                      | 21 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 srcpkgs/maturin/patches/cross-compile-setup-py.patch
 create mode 100644 srcpkgs/maturin/template

diff --git a/srcpkgs/maturin/patches/cross-compile-setup-py.patch b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
new file mode 100644
index 00000000000..e57189cb7ab
--- /dev/null
+++ b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
@@ -0,0 +1,14 @@
+--- setup.py	2020-04-30 22:36:01.000000000 +1000
++++ setup.py	2020-05-20 14:31:40.404994499 +1000
+@@ -56,9 +56,9 @@
+                     "(https://www.rust-lang.org/tools/install) and try again"
+                 )
+             subprocess.check_call(
+-                ["cargo", "rustc", "--bin", "maturin", "--", "-C", "link-arg=-s"]
++                ["cargo", "rustc", "--bin", "maturin", "--release", "--target", os.environ["RUST_TARGET"], "--", "-C", "link-arg=-s", "-C", "linker=" + os.environ["CC"].split(" ", 1)[0]]
+             )
+-            source = os.path.join(source_dir, "target", "debug", executable_name)
++            source = os.path.join(source_dir, "target", os.environ["RUST_TARGET"], "release", executable_name)
+         # run this after trying to build with cargo (as otherwise this leaves
+         # venv in a bad state: https://github.com/benfred/py-spy/issues/69)
+         install.run(self)
diff --git a/srcpkgs/maturin/template b/srcpkgs/maturin/template
new file mode 100644
index 00000000000..7eba36204f9
--- /dev/null
+++ b/srcpkgs/maturin/template
@@ -0,0 +1,21 @@
+# Template file for 'maturin'
+pkgname=maturin
+version=0.8.1
+revision=1
+build_style=python3-module
+hostmakedepends="cargo python3-setuptools python3-toml"
+makedepends="rust rust-std llvm9"
+short_desc="Build and publish crates with python bindings"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0, MIT"
+homepage="https://github.com/PyO3/maturin"
+distfiles="https://github.com/PyO3/maturin/archive/v${version}.tar.gz"
+checksum=b72a9885cda3ba4e53906a43aab101acb790622218ade6405b2ddf1ef1461f8f
+
+post_install() {
+	# Dynamic detection of python version
+	PYTHON_VERSION=$(python3 --version | sed "s/^Python //" | rev | sed "s/^[0-9]*.//" | rev)
+	mkdir -p "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	mv "${DESTDIR}/maturin" "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	vlicense license-mit
+}

From 96de4dbb3c34bf4961ba0c1f601205b1215dc700 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:25 +1000
Subject: [PATCH 3/6] New package: mypy-protobuf-python-1.13

---
 srcpkgs/mypy-protobuf-python/template | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-python/template

diff --git a/srcpkgs/mypy-protobuf-python/template b/srcpkgs/mypy-protobuf-python/template
new file mode 100644
index 00000000000..391d75f0c9e
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-python/template
@@ -0,0 +1,23 @@
+# Template file for 'mypy-protobuf-python'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-go
+#
+pkgname=mypy-protobuf-python
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_wrksrc=python
+build_style=python3-module
+hostmakedepends="python3-setuptools"
+depends="python3-mypy python3-typing_extensions python3-protobuf protobuf"
+short_desc="Generate mypy stubs from protobufs - Python implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74
+
+post_install() {
+	# We are not windows, remove the batch file
+	rm "${DESTDIR}/usr/bin/protoc_gen_mypy.bat"
+}

From aeaa9e6a25d47eedecac921e56d647d93d3f46ad Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:37 +1000
Subject: [PATCH 4/6] New package: mypy-protobuf-go-1.13

---
 .../patches/remote-go-improt.patch            | 11 +++++++++++
 srcpkgs/mypy-protobuf-go/template             | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
 create mode 100644 srcpkgs/mypy-protobuf-go/template

diff --git a/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
new file mode 100644
index 00000000000..300504bc70d
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
@@ -0,0 +1,11 @@
+--- go/src/protoc-gen-mypy/main.go.orig	2020-05-22 11:58:07.760761664 +1000
++++ go/src/protoc-gen-mypy/main.go	2020-05-22 11:58:00.595762190 +1000
+@@ -6,7 +6,7 @@
+ 	"sort"
+ 	"strings"
+ 
+-	"proto/mypy"
++	"github.com/dropbox/mypy-protobuf/go/src/proto/mypy"
+ 
+ 	"github.com/gogo/protobuf/proto"
+ 	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
diff --git a/srcpkgs/mypy-protobuf-go/template b/srcpkgs/mypy-protobuf-go/template
new file mode 100644
index 00000000000..8f00e43d8a8
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/template
@@ -0,0 +1,19 @@
+# Template file for 'mypy-protobuf-go'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-python
+#
+pkgname=mypy-protobuf-go
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_style=go
+go_import_path="github.com/dropbox/mypy-protobuf"
+go_package="${go_import_path}/go/src/protoc-gen-mypy"
+hostmakedepends="git"
+depends="protobuf"
+short_desc="Generate mypy stubs from protobufs - go implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74

From e6d8f76eeb38c0a55f56ca0c4800d1d6d3c71c75 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:36 +1000
Subject: [PATCH 5/6] New package: python-stringcase-1.2.0

---
 srcpkgs/python-stringcase/template | 28 ++++++++++++++++++++++++++++
 srcpkgs/python3-stringcase         |  1 +
 2 files changed, 29 insertions(+)
 create mode 100644 srcpkgs/python-stringcase/template
 create mode 120000 srcpkgs/python3-stringcase

diff --git a/srcpkgs/python-stringcase/template b/srcpkgs/python-stringcase/template
new file mode 100644
index 00000000000..849e677c784
--- /dev/null
+++ b/srcpkgs/python-stringcase/template
@@ -0,0 +1,28 @@
+# Template file for 'python-stringcase'
+pkgname=python-stringcase
+version=1.2.0
+revision=1
+wrksrc="stringcase-${version}"
+build_style=python-module
+hostmakedepends="python-devel python3-devel"
+makedepends="${hostmakedepends}"
+depends="python"
+short_desc="String case converter for Python2"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="MIT"
+homepage="https://github.com/okunishinishi/python-stringcase"
+distfiles="${PYPI_SITE}/s/stringcase/stringcase-${version}.tar.gz"
+checksum=48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008
+
+post_install() {
+	vlicense LICENSE
+}
+
+python3-stringcase_package() {
+	depends="python3"
+	short_desc="${short_desc/Python2/Python3}"
+	pkg_install() {
+		vmove usr/lib/python3*
+		vlicense LICENSE
+	}
+}
diff --git a/srcpkgs/python3-stringcase b/srcpkgs/python3-stringcase
new file mode 120000
index 00000000000..53938bd1f0c
--- /dev/null
+++ b/srcpkgs/python3-stringcase
@@ -0,0 +1 @@
+python-stringcase
\ No newline at end of file

From 87202f92b8a4a31bc944b5e99e57220f76bcf8d2 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:36:21 +1000
Subject: [PATCH 6/6] anki: update to 2.1.26

Has turned into a Bad Build System. Now uses rust nightly, python
(with bindings!), qt5, nodejs... the list goes on. There are quite
a few hacks and the like.
---
 ...1da60c6c00fc8cd930efa34113a602a830e2.patch |  118 +
 ...2423c8e293f843115f617d04213f04f63a77.patch |  134 ++
 ...13bce9c80b0e7ff37c5317705ce0acf32c15.patch | 1209 ++++++++++
 ...28e23ab3dab4eaa2277734019f1b8e0210c1.patch | 1978 +++++++++++++++++
 ...fec729e00355bbd067e5770a9e8e889280cf.patch | 1659 ++++++++++++++
 ...1da60c6c00fc8cd930efa34113a602a830e2.patch |   69 +
 ...2948d9147689701a24de2fcdffafc32ebe62.patch |   93 +
 ...c30b15f467c9f5ab139564be0099fba5b27f.patch |  159 ++
 ...7c2ad89dad6be5cf454fe0012d9aba9e60b2.patch | 1387 ++++++++++++
 ...10fcd8932c3d83fe73b07412969cc42ff686.patch |   38 +
 ...2a4b93b16ba9b7b43a1c73614efbcb6e9814.patch |  732 ++++++
 ...58f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch | 1321 +++++++++++
 .../0020-remove-nightly-check.patch           |   17 +
 srcpkgs/anki/patches/0001-aqt_data-fhs.patch  |   45 +
 .../anki/patches/0002-rust-nightly-fix.patch  |  274 +++
 .../patches/0003-rustc-cross-compile.patch    |   11 +
 srcpkgs/anki/patches/0004-vendored-deps.patch |   91 +
 srcpkgs/anki/patches/0005-patched-pyo3.patch  |   11 +
 srcpkgs/anki/template                         |   69 +-
 19 files changed, 9408 insertions(+), 7 deletions(-)
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch
 create mode 100644 srcpkgs/anki/patches/0001-aqt_data-fhs.patch
 create mode 100644 srcpkgs/anki/patches/0002-rust-nightly-fix.patch
 create mode 100644 srcpkgs/anki/patches/0003-rustc-cross-compile.patch
 create mode 100644 srcpkgs/anki/patches/0004-vendored-deps.patch
 create mode 100644 srcpkgs/anki/patches/0005-patched-pyo3.patch

diff --git a/srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch b/srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
new file mode 100644
index 00000000000..5a3f02afe94
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
@@ -0,0 +1,118 @@
+From b0561da60c6c00fc8cd930efa34113a602a830e2 Mon Sep 17 00:00:00 2001
+From: Donlon <mdonlon@treyarch.com>
+Date: Wed, 30 Oct 2019 07:02:06 -0700
+Subject: [PATCH] Stubbed out a bunch of tests
+
+---
+ .../{test_arithmetics.rs => test_arithmetics.rp} |  0
+ ...uffer_protocol.rs => test_buffer_protocol.rp} |  0
+ tests/{test_bytes.rs => test_bytes.rp}           |  0
+ tests/{test_class_new.rs => test_class_new.rp}   |  0
+ ...st_compile_error.rs => test_compile_error.rp} |  0
+ tests/{test_datetime.rs => test_datetime.rp}     |  0
+ tests/{test_dict_iter.rs => test_dict_iter.rp}   |  0
+ tests/{test_dunder.rs => test_dunder.rp}         |  0
+ tests/{test_exceptions.rs => test_exceptions.rp} |  0
+ tests/{test_gc.rs => test_gc.rp}                 |  0
+ ...st_getter_setter.rs => test_getter_setter.rp} |  0
+ .../{test_inheritance.rs => test_inheritance.rp} |  0
+ tests/{test_methods.rs => test_methods.rp}       |  0
+ tests/{test_module.rs => test_module.rp}         |  0
+ tests/{test_pyself.rs => test_pyself.rp}         |  0
+ tests/{test_sequence.rs => test_sequence.rp}     |  0
+ tests/{test_string.rs => test_string.rp}         |  0
+ ...e_arguments.rs => test_variable_arguments.rp} |  0
+ tests/{test_various.rs => test_various.rp}       |  0
+ rename tests/{test_arithmetics.rs => test_arithmetics.rp} (100%)
+ mode change 100755 => 100644
+ rename tests/{test_buffer_protocol.rs => test_buffer_protocol.rp} (100%)
+ rename tests/{test_bytes.rs => test_bytes.rp} (100%)
+ rename tests/{test_class_new.rs => test_class_new.rp} (100%)
+ rename tests/{test_compile_error.rs => test_compile_error.rp} (100%)
+ mode change 100755 => 100644
+ rename tests/{test_datetime.rs => test_datetime.rp} (100%)
+ rename tests/{test_dict_iter.rs => test_dict_iter.rp} (100%)
+ rename tests/{test_dunder.rs => test_dunder.rp} (100%)
+ mode change 100755 => 100644
+ rename tests/{test_exceptions.rs => test_exceptions.rp} (100%)
+ rename tests/{test_gc.rs => test_gc.rp} (100%)
+ rename tests/{test_getter_setter.rs => test_getter_setter.rp} (100%)
+ rename tests/{test_inheritance.rs => test_inheritance.rp} (100%)
+ rename tests/{test_methods.rs => test_methods.rp} (100%)
+ rename tests/{test_module.rs => test_module.rp} (100%)
+ rename tests/{test_pyself.rs => test_pyself.rp} (100%)
+ rename tests/{test_sequence.rs => test_sequence.rp} (100%)
+ rename tests/{test_string.rs => test_string.rp} (100%)
+ rename tests/{test_variable_arguments.rs => test_variable_arguments.rp} (100%)
+ rename tests/{test_various.rs => test_various.rp} (100%)
+
+diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rp
+old mode 100755
+new mode 100644
+similarity index 100%
+rename from tests/test_arithmetics.rs
+rename to tests/test_arithmetics.rp
+diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rp
+similarity index 100%
+rename from tests/test_buffer_protocol.rs
+rename to tests/test_buffer_protocol.rp
+diff --git a/tests/test_compile_error.rs b/tests/test_compile_error.rp
+old mode 100755
+new mode 100644
+similarity index 100%
+rename from tests/test_compile_error.rs
+rename to tests/test_compile_error.rp
+diff --git a/tests/test_datetime.rs b/tests/test_datetime.rp
+similarity index 100%
+rename from tests/test_datetime.rs
+rename to tests/test_datetime.rp
+diff --git a/tests/test_dict_iter.rs b/tests/test_dict_iter.rp
+similarity index 100%
+rename from tests/test_dict_iter.rs
+rename to tests/test_dict_iter.rp
+diff --git a/tests/test_dunder.rs b/tests/test_dunder.rp
+old mode 100755
+new mode 100644
+similarity index 100%
+rename from tests/test_dunder.rs
+rename to tests/test_dunder.rp
+diff --git a/tests/test_exceptions.rs b/tests/test_exceptions.rp
+similarity index 100%
+rename from tests/test_exceptions.rs
+rename to tests/test_exceptions.rp
+diff --git a/tests/test_gc.rs b/tests/test_gc.rp
+similarity index 100%
+rename from tests/test_gc.rs
+rename to tests/test_gc.rp
+diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rp
+similarity index 100%
+rename from tests/test_getter_setter.rs
+rename to tests/test_getter_setter.rp
+diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rp
+similarity index 100%
+rename from tests/test_inheritance.rs
+rename to tests/test_inheritance.rp
+diff --git a/tests/test_methods.rs b/tests/test_methods.rp
+similarity index 100%
+rename from tests/test_methods.rs
+rename to tests/test_methods.rp
+diff --git a/tests/test_module.rs b/tests/test_module.rp
+similarity index 100%
+rename from tests/test_module.rs
+rename to tests/test_module.rp
+diff --git a/tests/test_pyself.rs b/tests/test_pyself.rp
+similarity index 100%
+rename from tests/test_pyself.rs
+rename to tests/test_pyself.rp
+diff --git a/tests/test_sequence.rs b/tests/test_sequence.rp
+similarity index 100%
+rename from tests/test_sequence.rs
+rename to tests/test_sequence.rp
+diff --git a/tests/test_variable_arguments.rs b/tests/test_variable_arguments.rp
+similarity index 100%
+rename from tests/test_variable_arguments.rs
+rename to tests/test_variable_arguments.rp
+diff --git a/tests/test_various.rs b/tests/test_various.rp
+similarity index 100%
+rename from tests/test_various.rs
+rename to tests/test_various.rp
diff --git a/srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch b/srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch
new file mode 100644
index 00000000000..957690f295a
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch
@@ -0,0 +1,134 @@
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index 0f9ca44b..5414704a 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -212,60 +212,6 @@ where
+     }
+ }
+ 
+-trait PySequenceSetItemProtocolImpl {
+-    fn sq_ass_item() -> Option<ffi::ssizeobjargproc>;
+-}
+-
+-impl<'p, T> PySequenceSetItemProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
+-    default fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
+-        None
+-    }
+-}
+-
+-impl<T> PySequenceSetItemProtocolImpl for T
+-where
+-    T: for<'p> PySequenceSetItemProtocol<'p>,
+-{
+-    fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
+-        unsafe extern "C" fn wrap<T>(
+-            slf: *mut ffi::PyObject,
+-            key: ffi::Py_ssize_t,
+-            value: *mut ffi::PyObject,
+-        ) -> c_int
+-        where
+-            T: for<'p> PySequenceSetItemProtocol<'p>,
+-        {
+-            let py = Python::assume_gil_acquired();
+-            let _pool = crate::GILPool::new(py);
+-            let slf = py.mut_from_borrowed_ptr::<T>(slf);
+-
+-            let result = if value.is_null() {
+-                Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
+-                    "Item deletion not supported by {:?}",
+-                    stringify!(T)
+-                )))
+-            } else {
+-                let value = py.from_borrowed_ptr::<PyAny>(value);
+-                match value.extract() {
+-                    Ok(value) => slf.__setitem__(key.into(), value).into(),
+-                    Err(e) => Err(e),
+-                }
+-            };
+-            match result {
+-                Ok(_) => 0,
+-                Err(e) => {
+-                    e.restore(py);
+-                    -1
+-                }
+-            }
+-        }
+-        Some(wrap::<T>)
+-    }
+-}
+-
+ /// It can be possible to delete and set items (PySequenceSetItemProtocol and
+ /// PySequenceDelItemProtocol implemented), only to delete (PySequenceDelItemProtocol implemented)
+ /// or no deleting or setting is possible
+@@ -286,11 +232,68 @@ mod sq_ass_item_impl {
+             Some(del_set_item)
+         } else if let Some(del_item) = T::del_item() {
+             Some(del_item)
++        } else if let Some(set_item) = T::set_item() {
++            Some(set_item)
+         } else {
+             None
+         }
+     }
+ 
++    trait SetItem {
++        fn set_item() -> Option<ffi::ssizeobjargproc>;
++    }
++
++    impl<'p, T> SetItem for T
++    where
++        T: PySequenceProtocol<'p>,
++    {
++        default fn set_item() -> Option<ffi::ssizeobjargproc> {
++            None
++        }
++    }
++
++    impl<T> SetItem for T
++    where
++        T: for<'p> PySequenceSetItemProtocol<'p>,
++    {
++        fn set_item() -> Option<ffi::ssizeobjargproc> {
++            unsafe extern "C" fn wrap<T>(
++                slf: *mut ffi::PyObject,
++                key: ffi::Py_ssize_t,
++                value: *mut ffi::PyObject,
++            ) -> c_int
++            where
++                T: for<'p> PySequenceSetItemProtocol<'p>,
++            {
++                let py = Python::assume_gil_acquired();
++                let _pool = crate::GILPool::new(py);
++                let slf = py.mut_from_borrowed_ptr::<T>(slf);
++
++                let result = if value.is_null() {
++                    Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
++                        "Item deletion is not supported by {:?}",
++                        stringify!(T)
++                    )))
++                } else {
++                    let value = py.from_borrowed_ptr::<PyAny>(value);
++                    match value.extract() {
++                        Ok(value) => slf.__setitem__(key.into(), value).into(),
++                        Err(e) => Err(e),
++                    }
++                };
++
++                match result {
++                    Ok(_) => 0,
++                    Err(e) => {
++                        e.restore(py);
++                        -1
++                    }
++                }
++            }
++            Some(wrap::<T>)
++        }
++    }
++
+     trait DelItem {
+         fn del_item() -> Option<ffi::ssizeobjargproc>;
+     }
diff --git a/srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch b/srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch
new file mode 100644
index 00000000000..53cf0172ba2
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch
@@ -0,0 +1,1209 @@
+From cb1313bce9c80b0e7ff37c5317705ce0acf32c15 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Fri, 25 Oct 2019 20:51:08 -0700
+Subject: [PATCH] Revert "Run `cargo fmt` on source code and update
+ `CHANGELOG.md`"
+
+This reverts commit 33bf37d3d8ca08d3af39de22547e32e7c8eb0f54.
+---
+ CHANGELOG.md                        |   1 -
+ pyo3-derive-backend/src/pymethod.rs |   6 +-
+ src/class/basic.rs                  |  55 ++-----
+ src/class/buffer.rs                 |   5 +-
+ src/class/context.rs                |  10 +-
+ src/class/descr.rs                  |  10 +-
+ src/class/gc.rs                     |  10 +-
+ src/class/iter.rs                   |  10 +-
+ src/class/mapping.rs                |  40 +----
+ src/class/number.rs                 | 245 ++++++----------------------
+ src/class/pyasync.rs                |  25 +--
+ src/class/sequence.rs               |  45 +----
+ src/conversion.rs                   |   5 +-
+ 13 files changed, 95 insertions(+), 372 deletions(-)
+
+diff --git a/CHANGELOG.md b/CHANGELOG.md
+index a3aff9b31..482e9b01d 100644
+--- a/CHANGELOG.md
++++ b/CHANGELOG.md
+@@ -27,7 +27,6 @@ and `PyString::to_string_lossy` [#642](https://github.com/PyO3/pyo3/pull/642).
+ ### Fixed
+ 
+  * Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604)
+- * Patch specialization being broken by Rust 1.40. [#614](https://github.com/PyO3/pyo3/issues/614)
+  * Fix a segfault around PyErr. [#597](https://github.com/PyO3/pyo3/pull/597)
+ 
+ ## [0.8.0] - 2018-09-05
+diff --git a/pyo3-derive-backend/src/pymethod.rs b/pyo3-derive-backend/src/pymethod.rs
+index 2f561cb9d..8c867a567 100644
+--- a/pyo3-derive-backend/src/pymethod.rs
++++ b/pyo3-derive-backend/src/pymethod.rs
+@@ -38,7 +38,7 @@ pub fn gen_py_method(
+                     return Err(syn::Error::new_spanned(
+                         spec.args[0].ty,
+                         "Getter function can only have one argument of type pyo3::Python!",
+-                    ));
++                    ))
+                 }
+             };
+             impl_py_getter_def(name, doc, getter, &impl_wrap_getter(cls, name, takes_py))
+@@ -60,10 +60,10 @@ fn check_generic(name: &syn::Ident, sig: &syn::Signature) -> syn::Result<()> {
+         match param {
+             syn::GenericParam::Lifetime(_) => {}
+             syn::GenericParam::Type(_) => {
+-                return Err(syn::Error::new_spanned(param, err_msg("type")));
++                return Err(syn::Error::new_spanned(param, err_msg("type")))
+             }
+             syn::GenericParam::Const(_) => {
+-                return Err(syn::Error::new_spanned(param, err_msg("const")));
++                return Err(syn::Error::new_spanned(param, err_msg("const")))
+             }
+         }
+     }
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index 8c670bf82..29e19871f 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -202,10 +202,7 @@ trait GetAttrProtocolImpl {
+     fn tp_getattro() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> GetAttrProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_getattro() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -299,10 +296,7 @@ mod tp_setattro_impl {
+         fn del_attr() -> Option<ffi::setattrofunc>;
+     }
+ 
+-    impl<'p, T> DelAttr for T
+-    where
+-        T: PyObjectProtocol<'p>,
+-    {
++    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {
+         default fn del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+@@ -321,10 +315,7 @@ mod tp_setattro_impl {
+         fn set_del_attr() -> Option<ffi::setattrofunc>;
+     }
+ 
+-    impl<'p, T> SetDelAttr for T
+-    where
+-        T: PyObjectProtocol<'p>,
+-    {
++    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {
+         default fn set_del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+@@ -349,10 +340,7 @@ mod tp_setattro_impl {
+ trait StrProtocolImpl {
+     fn tp_str() -> Option<ffi::unaryfunc>;
+ }
+-impl<'p, T> StrProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_str() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -374,10 +362,7 @@ where
+ trait ReprProtocolImpl {
+     fn tp_repr() -> Option<ffi::unaryfunc>;
+ }
+-impl<'p, T> ReprProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_repr() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -400,10 +385,7 @@ where
+ pub trait FormatProtocolImpl {
+     fn __format__() -> Option<PyMethodDef>;
+ }
+-impl<'p, T> FormatProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn __format__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -413,10 +395,7 @@ where
+ pub trait BytesProtocolImpl {
+     fn __bytes__() -> Option<PyMethodDef>;
+ }
+-impl<'p, T> BytesProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn __bytes__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -426,10 +405,7 @@ where
+ pub trait UnicodeProtocolImpl {
+     fn __unicode__() -> Option<PyMethodDef>;
+ }
+-impl<'p, T> UnicodeProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn __unicode__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -438,10 +414,7 @@ where
+ trait HashProtocolImpl {
+     fn tp_hash() -> Option<ffi::hashfunc>;
+ }
+-impl<'p, T> HashProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_hash() -> Option<ffi::hashfunc> {
+         None
+     }
+@@ -464,10 +437,7 @@ where
+ trait BoolProtocolImpl {
+     fn nb_bool() -> Option<ffi::inquiry>;
+ }
+-impl<'p, T> BoolProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn nb_bool() -> Option<ffi::inquiry> {
+         None
+     }
+@@ -490,10 +460,7 @@ where
+ trait RichcmpProtocolImpl {
+     fn tp_richcompare() -> Option<ffi::richcmpfunc>;
+ }
+-impl<'p, T> RichcmpProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_richcompare() -> Option<ffi::richcmpfunc> {
+         None
+     }
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index f0f462db9..c30f078cc 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -69,10 +69,7 @@ trait PyBufferGetBufferProtocolImpl {
+     fn cb_bf_getbuffer() -> Option<ffi::getbufferproc>;
+ }
+ 
+-impl<'p, T> PyBufferGetBufferProtocolImpl for T
+-where
+-    T: PyBufferProtocol<'p>,
+-{
++impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {
+     default fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
+         None
+     }
+diff --git a/src/class/context.rs b/src/class/context.rs
+index 50aea33e9..2ad59768d 100644
+--- a/src/class/context.rs
++++ b/src/class/context.rs
+@@ -80,10 +80,7 @@ pub trait PyContextEnterProtocolImpl {
+     fn __enter__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyContextEnterProtocolImpl for T
+-where
+-    T: PyContextProtocol<'p>,
+-{
++impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {
+     default fn __enter__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -94,10 +91,7 @@ pub trait PyContextExitProtocolImpl {
+     fn __exit__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyContextExitProtocolImpl for T
+-where
+-    T: PyContextProtocol<'p>,
+-{
++impl<'p, T> PyContextExitProtocolImpl for T where T: PyContextProtocol<'p> {
+     default fn __exit__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/descr.rs b/src/class/descr.rs
+index 57d9119ca..c7b5b9660 100644
+--- a/src/class/descr.rs
++++ b/src/class/descr.rs
+@@ -72,10 +72,7 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
+ trait PyDescrGetProtocolImpl {
+     fn tp_descr_get() -> Option<ffi::descrgetfunc>;
+ }
+-impl<'p, T> PyDescrGetProtocolImpl for T
+-where
+-    T: PyDescrProtocol<'p>,
+-{
++impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {
+     default fn tp_descr_get() -> Option<ffi::descrgetfunc> {
+         None
+     }
+@@ -98,10 +95,7 @@ where
+ trait PyDescrSetProtocolImpl {
+     fn tp_descr_set() -> Option<ffi::descrsetfunc>;
+ }
+-impl<'p, T> PyDescrSetProtocolImpl for T
+-where
+-    T: PyDescrProtocol<'p>,
+-{
++impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {
+     default fn tp_descr_set() -> Option<ffi::descrsetfunc> {
+         None
+     }
+diff --git a/src/class/gc.rs b/src/class/gc.rs
+index 591b686af..4b69c9643 100644
+--- a/src/class/gc.rs
++++ b/src/class/gc.rs
+@@ -68,10 +68,7 @@ trait PyGCTraverseProtocolImpl {
+     fn tp_traverse() -> Option<ffi::traverseproc>;
+ }
+ 
+-impl<'p, T> PyGCTraverseProtocolImpl for T
+-where
+-    T: PyGCProtocol<'p>,
+-{
++impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {
+     default fn tp_traverse() -> Option<ffi::traverseproc> {
+         None
+     }
+@@ -115,10 +112,7 @@ trait PyGCClearProtocolImpl {
+     fn tp_clear() -> Option<ffi::inquiry>;
+ }
+ 
+-impl<'p, T> PyGCClearProtocolImpl for T
+-where
+-    T: PyGCProtocol<'p>,
+-{
++impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {
+     default fn tp_clear() -> Option<ffi::inquiry> {
+         None
+     }
+diff --git a/src/class/iter.rs b/src/class/iter.rs
+index a528289dd..fcf76f2e5 100644
+--- a/src/class/iter.rs
++++ b/src/class/iter.rs
+@@ -66,10 +66,7 @@ trait PyIterIterProtocolImpl {
+     fn tp_iter() -> Option<ffi::getiterfunc>;
+ }
+ 
+-impl<'p, T> PyIterIterProtocolImpl for T
+-where
+-    T: PyIterProtocol<'p>,
+-{
++impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {
+     default fn tp_iter() -> Option<ffi::getiterfunc> {
+         None
+     }
+@@ -94,10 +91,7 @@ trait PyIterNextProtocolImpl {
+     fn tp_iternext() -> Option<ffi::iternextfunc>;
+ }
+ 
+-impl<'p, T> PyIterNextProtocolImpl for T
+-where
+-    T: PyIterProtocol<'p>,
+-{
++impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {
+     default fn tp_iternext() -> Option<ffi::iternextfunc> {
+         None
+     }
+diff --git a/src/class/mapping.rs b/src/class/mapping.rs
+index 32326ff46..64d7b57ce 100644
+--- a/src/class/mapping.rs
++++ b/src/class/mapping.rs
+@@ -160,10 +160,7 @@ trait PyMappingLenProtocolImpl {
+     fn mp_length() -> Option<ffi::lenfunc>;
+ }
+ 
+-impl<'p, T> PyMappingLenProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn mp_length() -> Option<ffi::lenfunc> {
+         None
+     }
+@@ -183,10 +180,7 @@ trait PyMappingGetItemProtocolImpl {
+     fn mp_subscript() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyMappingGetItemProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn mp_subscript() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -211,10 +205,7 @@ trait PyMappingSetItemProtocolImpl {
+     fn mp_ass_subscript() -> Option<ffi::objobjargproc>;
+ }
+ 
+-impl<'p, T> PyMappingSetItemProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+@@ -236,10 +227,7 @@ trait DeplItemDipatch {
+     fn mp_del_subscript() -> Option<ffi::objobjargproc>;
+ }
+ 
+-impl<'p, T> DeplItemDipatch for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> DeplItemDipatch for T where T: PyMappingProtocol<'p> {
+     default fn mp_del_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+@@ -250,10 +238,7 @@ trait DelSetItemDispatch: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+     fn det_set_dispatch() -> Option<ffi::objobjargproc>;
+ }
+ 
+-impl<T> DelSetItemDispatch for T
+-where
+-    T: Sized + for<'p> PyMappingDelItemProtocol<'p>,
+-{
++impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+     default fn det_set_dispatch() -> Option<ffi::objobjargproc> {
+         py_func_del!(PyMappingDelItemProtocol, Self, __delitem__)
+     }
+@@ -288,10 +273,7 @@ pub trait PyMappingContainsProtocolImpl {
+     fn __contains__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyMappingContainsProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingContainsProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn __contains__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -302,10 +284,7 @@ pub trait PyMappingReversedProtocolImpl {
+     fn __reversed__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyMappingReversedProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingReversedProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn __reversed__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -316,10 +295,7 @@ pub trait PyMappingIterProtocolImpl {
+     fn __iter__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyMappingIterProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingIterProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn __iter__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 796b8bad9..0ab162e72 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -749,10 +749,7 @@ trait PyNumberAddProtocolImpl {
+     fn nb_add() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberAddProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -776,10 +773,7 @@ trait PyNumberSubProtocolImpl {
+     fn nb_subtract() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberSubProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -803,10 +797,7 @@ trait PyNumberMulProtocolImpl {
+     fn nb_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberMulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -830,10 +821,7 @@ trait PyNumberMatmulProtocolImpl {
+     fn nb_matrix_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberMatmulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -857,10 +845,7 @@ trait PyNumberTruedivProtocolImpl {
+     fn nb_true_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberTruedivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -884,10 +869,7 @@ trait PyNumberFloordivProtocolImpl {
+     fn nb_floor_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberFloordivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -911,10 +893,7 @@ trait PyNumberModProtocolImpl {
+     fn nb_remainder() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberModProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -938,10 +917,7 @@ trait PyNumberDivmodProtocolImpl {
+     fn nb_divmod() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberDivmodProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_divmod() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -965,10 +941,7 @@ trait PyNumberPowProtocolImpl {
+     fn nb_power() -> Option<ffi::ternaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberPowProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+@@ -992,10 +965,7 @@ trait PyNumberLShiftProtocolImpl {
+     fn nb_lshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberLShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1019,10 +989,7 @@ trait PyNumberRShiftProtocolImpl {
+     fn nb_rshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberRShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1046,10 +1013,7 @@ trait PyNumberAndProtocolImpl {
+     fn nb_and() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberAndProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1073,10 +1037,7 @@ trait PyNumberXorProtocolImpl {
+     fn nb_xor() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberXorProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1100,10 +1061,7 @@ trait PyNumberOrProtocolImpl {
+     fn nb_or() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberOrProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1127,10 +1085,7 @@ trait PyNumberIAddProtocolImpl {
+     fn nb_inplace_add() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIAddProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1149,10 +1104,7 @@ trait PyNumberISubProtocolImpl {
+     fn nb_inplace_subtract() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberISubProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1171,10 +1123,7 @@ trait PyNumberIMulProtocolImpl {
+     fn nb_inplace_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIMulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1193,10 +1142,7 @@ trait PyNumberIMatmulProtocolImpl {
+     fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIMatmulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1215,10 +1161,7 @@ trait PyNumberITruedivProtocolImpl {
+     fn nb_inplace_true_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberITruedivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1237,10 +1180,7 @@ trait PyNumberIFloordivProtocolImpl {
+     fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIFloordivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1259,10 +1199,7 @@ trait PyNumberIModProtocolImpl {
+     fn nb_inplace_remainder() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIModProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1281,10 +1218,7 @@ trait PyNumberIPowProtocolImpl {
+     fn nb_inplace_power() -> Option<ffi::ternaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIPowProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+@@ -1303,10 +1237,7 @@ trait PyNumberILShiftProtocolImpl {
+     fn nb_inplace_lshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberILShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1325,10 +1256,7 @@ trait PyNumberIRShiftProtocolImpl {
+     fn nb_inplace_rshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIRShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1347,10 +1275,7 @@ trait PyNumberIAndProtocolImpl {
+     fn nb_inplace_and() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIAndProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1369,10 +1294,7 @@ trait PyNumberIXorProtocolImpl {
+     fn nb_inplace_xor() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIXorProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1391,10 +1313,7 @@ trait PyNumberIOrProtocolImpl {
+     fn nb_inplace_or() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIOrProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1414,10 +1333,7 @@ pub trait PyNumberRAddProtocolImpl {
+     fn __radd__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRAddProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __radd__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1437,10 +1353,7 @@ pub trait PyNumberRMulProtocolImpl {
+     fn __rmul__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRMulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rmul__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1451,10 +1364,7 @@ pub trait PyNumberRMatmulProtocolImpl {
+     fn __rmatmul__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRMatmulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rmatmul__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1465,10 +1375,7 @@ pub trait PyNumberRTruedivProtocolImpl {
+     fn __rtruediv__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRTruedivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rtruediv__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1479,10 +1386,7 @@ pub trait PyNumberRFloordivProtocolImpl {
+     fn __rfloordiv__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRFloordivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rfloordiv__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1493,10 +1397,7 @@ pub trait PyNumberRModProtocolImpl {
+     fn __rmod__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRModProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rmod__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1507,10 +1408,7 @@ pub trait PyNumberRDivmodProtocolImpl {
+     fn __rdivmod__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRDivmodProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rdivmod__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1521,10 +1419,7 @@ pub trait PyNumberRPowProtocolImpl {
+     fn __rpow__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRPowProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rpow__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1535,10 +1430,7 @@ pub trait PyNumberRLShiftProtocolImpl {
+     fn __rlshift__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRLShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rlshift__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1549,10 +1441,7 @@ pub trait PyNumberRRShiftProtocolImpl {
+     fn __rrshift__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRRShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rrshift__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1563,10 +1452,7 @@ pub trait PyNumberRAndProtocolImpl {
+     fn __rand__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRAndProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rand__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1577,10 +1463,7 @@ pub trait PyNumberRXorProtocolImpl {
+     fn __rxor__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRXorProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rxor__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1591,10 +1474,7 @@ pub trait PyNumberROrProtocolImpl {
+     fn __ror__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberROrProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __ror__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1604,10 +1484,7 @@ trait PyNumberNegProtocolImpl {
+     fn nb_negative() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberNegProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1632,10 +1509,7 @@ trait PyNumberPosProtocolImpl {
+     fn nb_positive() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberPosProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_positive() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1659,10 +1533,7 @@ trait PyNumberAbsProtocolImpl {
+     fn nb_absolute() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberAbsProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_absolute() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1686,10 +1557,7 @@ trait PyNumberInvertProtocolImpl {
+     fn nb_invert() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberInvertProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_invert() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1713,10 +1581,7 @@ trait PyNumberIntProtocolImpl {
+     fn nb_int() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIntProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_int() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1740,10 +1605,7 @@ trait PyNumberFloatProtocolImpl {
+     fn nb_float() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberFloatProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_float() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1767,10 +1629,7 @@ trait PyNumberIndexProtocolImpl {
+     fn nb_index() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIndexProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_index() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1794,10 +1653,7 @@ trait PyNumberComplexProtocolImpl {
+     fn __complex__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberComplexProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __complex__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1807,10 +1663,7 @@ trait PyNumberRoundProtocolImpl {
+     fn __round__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRoundProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __round__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs
+index 2536d4ce2..f977fadfa 100644
+--- a/src/class/pyasync.rs
++++ b/src/class/pyasync.rs
+@@ -137,10 +137,7 @@ trait PyAsyncAwaitProtocolImpl {
+     fn am_await() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyAsyncAwaitProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn am_await() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -165,10 +162,7 @@ trait PyAsyncAiterProtocolImpl {
+     fn am_aiter() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyAsyncAiterProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn am_aiter() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -193,10 +187,7 @@ trait PyAsyncAnextProtocolImpl {
+     fn am_anext() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyAsyncAnextProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn am_anext() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -254,10 +245,7 @@ trait PyAsyncAenterProtocolImpl {
+     fn __aenter__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyAsyncAenterProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn __aenter__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -267,10 +255,7 @@ trait PyAsyncAexitProtocolImpl {
+     fn __aexit__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyAsyncAexitProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAexitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn __aexit__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index 5414704a1..ce65508fd 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -167,10 +167,7 @@ trait PySequenceLenProtocolImpl {
+     fn sq_length() -> Option<ffi::lenfunc>;
+ }
+ 
+-impl<'p, T> PySequenceLenProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_length() -> Option<ffi::lenfunc> {
+         None
+     }
+@@ -189,10 +186,7 @@ trait PySequenceGetItemProtocolImpl {
+     fn sq_item() -> Option<ffi::ssizeargfunc>;
+ }
+ 
+-impl<'p, T> PySequenceGetItemProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_item() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+@@ -298,10 +292,7 @@ mod sq_ass_item_impl {
+         fn del_item() -> Option<ffi::ssizeobjargproc>;
+     }
+ 
+-    impl<'p, T> DelItem for T
+-    where
+-        T: PySequenceProtocol<'p>,
+-    {
++    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {
+         default fn del_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+@@ -349,10 +340,7 @@ mod sq_ass_item_impl {
+         fn del_set_item() -> Option<ffi::ssizeobjargproc>;
+     }
+ 
+-    impl<'p, T> DelSetItem for T
+-    where
+-        T: PySequenceProtocol<'p>,
+-    {
++    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {
+         default fn del_set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+@@ -401,10 +389,7 @@ trait PySequenceContainsProtocolImpl {
+     fn sq_contains() -> Option<ffi::objobjproc>;
+ }
+ 
+-impl<'p, T> PySequenceContainsProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_contains() -> Option<ffi::objobjproc> {
+         None
+     }
+@@ -429,10 +414,7 @@ trait PySequenceConcatProtocolImpl {
+     fn sq_concat() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PySequenceConcatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -456,10 +438,7 @@ trait PySequenceRepeatProtocolImpl {
+     fn sq_repeat() -> Option<ffi::ssizeargfunc>;
+ }
+ 
+-impl<'p, T> PySequenceRepeatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+@@ -483,10 +462,7 @@ trait PySequenceInplaceConcatProtocolImpl {
+     fn sq_inplace_concat() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PySequenceInplaceConcatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -510,10 +486,7 @@ trait PySequenceInplaceRepeatProtocolImpl {
+     fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc>;
+ }
+ 
+-impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+diff --git a/src/conversion.rs b/src/conversion.rs
+index 38f436de4..15ccdabde 100644
+--- a/src/conversion.rs
++++ b/src/conversion.rs
+@@ -100,10 +100,7 @@ pub trait ToBorrowedObject: ToPyObject {
+         F: FnOnce(*mut ffi::PyObject) -> R;
+ }
+ 
+-impl<T> ToBorrowedObject for T
+-where
+-    T: ToPyObject,
+-{
++impl<T> ToBorrowedObject for T where T: ToPyObject {
+     default fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
+     where
+         F: FnOnce(*mut ffi::PyObject) -> R,
diff --git a/srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch b/srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch
new file mode 100644
index 00000000000..ff6e46229e8
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch
@@ -0,0 +1,1978 @@
+From 89c028e23ab3dab4eaa2277734019f1b8e0210c1 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Fri, 25 Oct 2019 20:52:10 -0700
+Subject: [PATCH] Revert "Fix broken specialized implementations with Rust
+ 1.40"
+
+This reverts commit 5397a62f486a25b2f99aac7aa758161b993af6ae.
+---
+ src/class/basic.rs    |  94 ++++------
+ src/class/buffer.rs   |  16 +-
+ src/class/context.rs  |  24 +--
+ src/class/descr.rs    |  23 +--
+ src/class/gc.rs       |  22 +--
+ src/class/iter.rs     |  22 +--
+ src/class/mapping.rs  |  75 +++-----
+ src/class/number.rs   | 403 ++++++++++++++++--------------------------
+ src/class/pyasync.rs  |  51 ++----
+ src/class/sequence.rs |  80 ++++-----
+ src/conversion.rs     |   8 +-
+ src/instance.rs       |  39 ++--
+ 12 files changed, 319 insertions(+), 538 deletions(-)
+
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index 29e19871f..c3153dfa3 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -152,21 +152,17 @@ pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyObjectProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-    fn tp_as_object(_type_object: &mut ffi::PyTypeObject);
+-    fn nb_bool_fn() -> Option<ffi::inquiry>;
+-}
+-
+-impl<T> PyObjectProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+-    default fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
+-    default fn nb_bool_fn() -> Option<ffi::inquiry> {
++    fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
++    fn nb_bool_fn() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+ 
++impl<T> PyObjectProtocolImpl for T {}
++
+ impl<'p, T> PyObjectProtocolImpl for T
+ where
+     T: PyObjectProtocol<'p>,
+@@ -199,15 +195,13 @@ where
+ }
+ 
+ trait GetAttrProtocolImpl {
+-    fn tp_getattro() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_getattro() -> Option<ffi::binaryfunc> {
++    fn tp_getattro() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> GetAttrProtocolImpl for T
+ where
+     T: for<'p> PyObjectGetAttrProtocol<'p>,
+@@ -274,15 +268,13 @@ mod tp_setattro_impl {
+     }
+ 
+     trait SetAttr {
+-        fn set_attr() -> Option<ffi::setattrofunc>;
+-    }
+-
+-    impl<'p, T: PyObjectProtocol<'p>> SetAttr for T {
+-        default fn set_attr() -> Option<ffi::setattrofunc> {
++        fn set_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
++    impl<'p, T: PyObjectProtocol<'p>> SetAttr for T {}
++
+     impl<T> SetAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p>,
+@@ -293,15 +285,13 @@ mod tp_setattro_impl {
+     }
+ 
+     trait DelAttr {
+-        fn del_attr() -> Option<ffi::setattrofunc>;
+-    }
+-
+-    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {
+-        default fn del_attr() -> Option<ffi::setattrofunc> {
++        fn del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {}
++
+     impl<T> DelAttr for T
+     where
+         T: for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -312,15 +302,13 @@ mod tp_setattro_impl {
+     }
+ 
+     trait SetDelAttr {
+-        fn set_del_attr() -> Option<ffi::setattrofunc>;
+-    }
+-
+-    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {
+-        default fn set_del_attr() -> Option<ffi::setattrofunc> {
++        fn set_del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {}
++
+     impl<T> SetDelAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -338,13 +326,11 @@ mod tp_setattro_impl {
+ }
+ 
+ trait StrProtocolImpl {
+-    fn tp_str() -> Option<ffi::unaryfunc>;
+-}
+-impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_str() -> Option<ffi::unaryfunc> {
++    fn tp_str() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
++impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> StrProtocolImpl for T
+ where
+     T: for<'p> PyObjectStrProtocol<'p>,
+@@ -360,13 +346,11 @@ where
+ }
+ 
+ trait ReprProtocolImpl {
+-    fn tp_repr() -> Option<ffi::unaryfunc>;
+-}
+-impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_repr() -> Option<ffi::unaryfunc> {
++    fn tp_repr() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
++impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> ReprProtocolImpl for T
+ where
+     T: for<'p> PyObjectReprProtocol<'p>,
+@@ -383,42 +367,34 @@ where
+ 
+ #[doc(hidden)]
+ pub trait FormatProtocolImpl {
+-    fn __format__() -> Option<PyMethodDef>;
+-}
+-impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn __format__() -> Option<PyMethodDef> {
++    fn __format__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait BytesProtocolImpl {
+-    fn __bytes__() -> Option<PyMethodDef>;
+-}
+-impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn __bytes__() -> Option<PyMethodDef> {
++    fn __bytes__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait UnicodeProtocolImpl {
+-    fn __unicode__() -> Option<PyMethodDef>;
+-}
+-impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn __unicode__() -> Option<PyMethodDef> {
++    fn __unicode__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ trait HashProtocolImpl {
+-    fn tp_hash() -> Option<ffi::hashfunc>;
+-}
+-impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_hash() -> Option<ffi::hashfunc> {
++    fn tp_hash() -> Option<ffi::hashfunc> {
+         None
+     }
+ }
++impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> HashProtocolImpl for T
+ where
+     T: for<'p> PyObjectHashProtocol<'p>,
+@@ -435,13 +411,11 @@ where
+ }
+ 
+ trait BoolProtocolImpl {
+-    fn nb_bool() -> Option<ffi::inquiry>;
+-}
+-impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn nb_bool() -> Option<ffi::inquiry> {
++    fn nb_bool() -> Option<ffi::inquiry> {
+         None
+     }
+ }
++impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> BoolProtocolImpl for T
+ where
+     T: for<'p> PyObjectBoolProtocol<'p>,
+@@ -458,13 +432,11 @@ where
+ }
+ 
+ trait RichcmpProtocolImpl {
+-    fn tp_richcompare() -> Option<ffi::richcmpfunc>;
+-}
+-impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_richcompare() -> Option<ffi::richcmpfunc> {
++    fn tp_richcompare() -> Option<ffi::richcmpfunc> {
+         None
+     }
+ }
++impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> RichcmpProtocolImpl for T
+ where
+     T: for<'p> PyObjectRichcmpProtocol<'p>,
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index c30f078cc..d36524e7c 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -41,15 +41,13 @@ pub trait PyBufferReleaseBufferProtocol<'p>: PyBufferProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyBufferProtocolImpl {
+-    fn tp_as_buffer() -> Option<ffi::PyBufferProcs>;
+-}
+-
+-impl<T> PyBufferProtocolImpl for T {
+-    default fn tp_as_buffer() -> Option<ffi::PyBufferProcs> {
++    fn tp_as_buffer() -> Option<ffi::PyBufferProcs> {
+         None
+     }
+ }
+ 
++impl<T> PyBufferProtocolImpl for T {}
++
+ impl<'p, T> PyBufferProtocolImpl for T
+ where
+     T: PyBufferProtocol<'p>,
+@@ -66,15 +64,13 @@ where
+ }
+ 
+ trait PyBufferGetBufferProtocolImpl {
+-    fn cb_bf_getbuffer() -> Option<ffi::getbufferproc>;
+-}
+-
+-impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {
+-    default fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
++    fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {}
++
+ impl<T> PyBufferGetBufferProtocolImpl for T
+ where
+     T: for<'p> PyBufferGetBufferProtocol<'p>,
+diff --git a/src/class/context.rs b/src/class/context.rs
+index 2ad59768d..092527ba0 100644
+--- a/src/class/context.rs
++++ b/src/class/context.rs
+@@ -47,15 +47,13 @@ pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyContextProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-}
+-
+-impl<T> PyContextProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+ }
+ 
++impl<T> PyContextProtocolImpl for T {}
++
+ impl<'p, T> PyContextProtocolImpl for T
+ where
+     T: PyContextProtocol<'p>,
+@@ -77,22 +75,18 @@ where
+ 
+ #[doc(hidden)]
+ pub trait PyContextEnterProtocolImpl {
+-    fn __enter__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {
+-    default fn __enter__() -> Option<PyMethodDef> {
++    fn __enter__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyContextExitProtocolImpl {
+-    fn __exit__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyContextExitProtocolImpl for T where T: PyContextProtocol<'p> {
+-    default fn __exit__() -> Option<PyMethodDef> {
++    fn __exit__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyContextExitProtocolImpl for T where T: PyContextProtocol<'p> {}
+diff --git a/src/class/descr.rs b/src/class/descr.rs
+index c7b5b9660..5f7e68306 100644
+--- a/src/class/descr.rs
++++ b/src/class/descr.rs
+@@ -70,13 +70,11 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
+ }
+ 
+ trait PyDescrGetProtocolImpl {
+-    fn tp_descr_get() -> Option<ffi::descrgetfunc>;
+-}
+-impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {
+-    default fn tp_descr_get() -> Option<ffi::descrgetfunc> {
++    fn tp_descr_get() -> Option<ffi::descrgetfunc> {
+         None
+     }
+ }
++impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ 
+ impl<T> PyDescrGetProtocolImpl for T
+ where
+@@ -93,13 +91,11 @@ where
+ }
+ 
+ trait PyDescrSetProtocolImpl {
+-    fn tp_descr_set() -> Option<ffi::descrsetfunc>;
+-}
+-impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {
+-    default fn tp_descr_set() -> Option<ffi::descrsetfunc> {
++    fn tp_descr_set() -> Option<ffi::descrsetfunc> {
+         None
+     }
+ }
++impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ impl<T> PyDescrSetProtocolImpl for T
+ where
+     T: for<'p> PyDescrSetProtocol<'p>,
+@@ -131,17 +127,14 @@ impl<'p, T> PyDescrSetNameProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait PyDescrProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-    fn tp_as_descr(_type_object: &mut ffi::PyTypeObject);
+-}
+-
+-impl<T> PyDescrProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+-    default fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
++    fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
++impl<T> PyDescrProtocolImpl for T {}
++
+ impl<'p, T> PyDescrProtocolImpl for T
+ where
+     T: PyDescrProtocol<'p>,
+diff --git a/src/class/gc.rs b/src/class/gc.rs
+index 4b69c9643..eaa4d9015 100644
+--- a/src/class/gc.rs
++++ b/src/class/gc.rs
+@@ -23,12 +23,10 @@ pub trait PyGCClearProtocol<'p>: PyGCProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait PyGCProtocolImpl {
+-    fn update_type_object(_type_object: &mut ffi::PyTypeObject);
++    fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<'p, T> PyGCProtocolImpl for T {
+-    default fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
+-}
++impl<'p, T> PyGCProtocolImpl for T {}
+ 
+ impl<'p, T> PyGCProtocolImpl for T
+ where
+@@ -65,15 +63,13 @@ impl<'p> PyVisit<'p> {
+ }
+ 
+ trait PyGCTraverseProtocolImpl {
+-    fn tp_traverse() -> Option<ffi::traverseproc>;
+-}
+-
+-impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {
+-    default fn tp_traverse() -> Option<ffi::traverseproc> {
++    fn tp_traverse() -> Option<ffi::traverseproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {}
++
+ #[doc(hidden)]
+ impl<T> PyGCTraverseProtocolImpl for T
+ where
+@@ -109,15 +105,13 @@ where
+ }
+ 
+ trait PyGCClearProtocolImpl {
+-    fn tp_clear() -> Option<ffi::inquiry>;
+-}
+-
+-impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {
+-    default fn tp_clear() -> Option<ffi::inquiry> {
++    fn tp_clear() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {}
++
+ impl<T> PyGCClearProtocolImpl for T
+ where
+     T: for<'p> PyGCClearProtocol<'p>,
+diff --git a/src/class/iter.rs b/src/class/iter.rs
+index fcf76f2e5..9001d53ce 100644
+--- a/src/class/iter.rs
++++ b/src/class/iter.rs
+@@ -44,12 +44,10 @@ pub trait PyIterNextProtocol<'p>: PyIterProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyIterProtocolImpl {
+-    fn tp_as_iter(_typeob: &mut ffi::PyTypeObject);
++    fn tp_as_iter(_typeob: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<T> PyIterProtocolImpl for T {
+-    default fn tp_as_iter(_typeob: &mut ffi::PyTypeObject) {}
+-}
++impl<T> PyIterProtocolImpl for T {}
+ 
+ impl<'p, T> PyIterProtocolImpl for T
+ where
+@@ -63,15 +61,13 @@ where
+ }
+ 
+ trait PyIterIterProtocolImpl {
+-    fn tp_iter() -> Option<ffi::getiterfunc>;
+-}
+-
+-impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {
+-    default fn tp_iter() -> Option<ffi::getiterfunc> {
++    fn tp_iter() -> Option<ffi::getiterfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {}
++
+ impl<T> PyIterIterProtocolImpl for T
+ where
+     T: for<'p> PyIterIterProtocol<'p>,
+@@ -88,15 +84,13 @@ where
+ }
+ 
+ trait PyIterNextProtocolImpl {
+-    fn tp_iternext() -> Option<ffi::iternextfunc>;
+-}
+-
+-impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {
+-    default fn tp_iternext() -> Option<ffi::iternextfunc> {
++    fn tp_iternext() -> Option<ffi::iternextfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {}
++
+ impl<T> PyIterNextProtocolImpl for T
+ where
+     T: for<'p> PyIterNextProtocol<'p>,
+diff --git a/src/class/mapping.rs b/src/class/mapping.rs
+index 64d7b57ce..616763502 100644
+--- a/src/class/mapping.rs
++++ b/src/class/mapping.rs
+@@ -106,19 +106,16 @@ pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyMappingProtocolImpl {
+-    fn tp_as_mapping() -> Option<ffi::PyMappingMethods>;
+-    fn methods() -> Vec<PyMethodDef>;
+-}
+-
+-impl<T> PyMappingProtocolImpl for T {
+-    default fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
++    fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
+         None
+     }
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+ }
+ 
++impl<T> PyMappingProtocolImpl for T {}
++
+ impl<'p, T> PyMappingProtocolImpl for T
+ where
+     T: PyMappingProtocol<'p>,
+@@ -157,15 +154,13 @@ where
+ }
+ 
+ trait PyMappingLenProtocolImpl {
+-    fn mp_length() -> Option<ffi::lenfunc>;
+-}
+-
+-impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn mp_length() -> Option<ffi::lenfunc> {
++    fn mp_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ impl<T> PyMappingLenProtocolImpl for T
+ where
+     T: for<'p> PyMappingLenProtocol<'p>,
+@@ -177,15 +172,13 @@ where
+ }
+ 
+ trait PyMappingGetItemProtocolImpl {
+-    fn mp_subscript() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn mp_subscript() -> Option<ffi::binaryfunc> {
++    fn mp_subscript() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ impl<T> PyMappingGetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingGetItemProtocol<'p>,
+@@ -202,15 +195,13 @@ where
+ }
+ 
+ trait PyMappingSetItemProtocolImpl {
+-    fn mp_ass_subscript() -> Option<ffi::objobjargproc>;
+-}
+-
+-impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
++    fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ impl<T> PyMappingSetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p>,
+@@ -224,26 +215,22 @@ where
+ /// Returns `None` if PyMappingDelItemProtocol isn't implemented, otherwise dispatches to
+ /// `DelSetItemDispatch`
+ trait DeplItemDipatch {
+-    fn mp_del_subscript() -> Option<ffi::objobjargproc>;
+-}
+-
+-impl<'p, T> DeplItemDipatch for T where T: PyMappingProtocol<'p> {
+-    default fn mp_del_subscript() -> Option<ffi::objobjargproc> {
++    fn mp_del_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> DeplItemDipatch for T where T: PyMappingProtocol<'p> {}
++
+ /// Returns `py_func_set_del` if PyMappingSetItemProtocol is implemented, otherwise `py_func_del`
+ trait DelSetItemDispatch: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+-    fn det_set_dispatch() -> Option<ffi::objobjargproc>;
+-}
+-
+-impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+-    default fn det_set_dispatch() -> Option<ffi::objobjargproc> {
++    fn det_set_dispatch() -> Option<ffi::objobjargproc> {
+         py_func_del!(PyMappingDelItemProtocol, Self, __delitem__)
+     }
+ }
+ 
++impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {}
++
+ impl<T> DelSetItemDispatch for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p> + for<'p> PyMappingDelItemProtocol<'p>,
+@@ -270,33 +257,27 @@ where
+ 
+ #[doc(hidden)]
+ pub trait PyMappingContainsProtocolImpl {
+-    fn __contains__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyMappingContainsProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn __contains__() -> Option<PyMethodDef> {
++    fn __contains__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingContainsProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyMappingReversedProtocolImpl {
+-    fn __reversed__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyMappingReversedProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn __reversed__() -> Option<PyMethodDef> {
++    fn __reversed__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingReversedProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyMappingIterProtocolImpl {
+-    fn __iter__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyMappingIterProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn __iter__() -> Option<PyMethodDef> {
++    fn __iter__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyMappingIterProtocolImpl for T where T: PyMappingProtocol<'p> {}
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 0ab162e72..2ee3a57d5 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -622,15 +622,10 @@ pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyNumberProtocolImpl: PyObjectProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-    fn tp_as_number() -> Option<ffi::PyNumberMethods>;
+-}
+-
+-impl<'p, T> PyNumberProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+-    default fn tp_as_number() -> Option<ffi::PyNumberMethods> {
++    fn tp_as_number() -> Option<ffi::PyNumberMethods> {
+         if let Some(nb_bool) = <Self as PyObjectProtocolImpl>::nb_bool_fn() {
+             let meth = ffi::PyNumberMethods {
+                 nb_bool: Some(nb_bool),
+@@ -643,6 +638,8 @@ impl<'p, T> PyNumberProtocolImpl for T {
+     }
+ }
+ 
++impl<'p, T> PyNumberProtocolImpl for T {}
++
+ impl<'p, T> PyNumberProtocolImpl for T
+ where
+     T: PyNumberProtocol<'p>,
+@@ -746,15 +743,13 @@ where
+ }
+ 
+ trait PyNumberAddProtocolImpl {
+-    fn nb_add() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_add() -> Option<ffi::binaryfunc> {
++    fn nb_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberAddProtocol<'p>,
+@@ -770,15 +765,13 @@ where
+ }
+ 
+ trait PyNumberSubProtocolImpl {
+-    fn nb_subtract() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_subtract() -> Option<ffi::binaryfunc> {
++    fn nb_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberSubProtocolImpl for T
+ where
+     T: for<'p> PyNumberSubProtocol<'p>,
+@@ -794,15 +787,13 @@ where
+ }
+ 
+ trait PyNumberMulProtocolImpl {
+-    fn nb_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMulProtocol<'p>,
+@@ -818,15 +809,13 @@ where
+ }
+ 
+ trait PyNumberMatmulProtocolImpl {
+-    fn nb_matrix_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMatmulProtocol<'p>,
+@@ -842,15 +831,13 @@ where
+ }
+ 
+ trait PyNumberTruedivProtocolImpl {
+-    fn nb_true_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_true_divide() -> Option<ffi::binaryfunc> {
++    fn nb_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberTruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberTruedivProtocol<'p>,
+@@ -866,15 +853,13 @@ where
+ }
+ 
+ trait PyNumberFloordivProtocolImpl {
+-    fn nb_floor_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_floor_divide() -> Option<ffi::binaryfunc> {
++    fn nb_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloordivProtocol<'p>,
+@@ -890,15 +875,13 @@ where
+ }
+ 
+ trait PyNumberModProtocolImpl {
+-    fn nb_remainder() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_remainder() -> Option<ffi::binaryfunc> {
++    fn nb_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberModProtocolImpl for T
+ where
+     T: for<'p> PyNumberModProtocol<'p>,
+@@ -914,15 +897,13 @@ where
+ }
+ 
+ trait PyNumberDivmodProtocolImpl {
+-    fn nb_divmod() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_divmod() -> Option<ffi::binaryfunc> {
++    fn nb_divmod() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberDivmodProtocolImpl for T
+ where
+     T: for<'p> PyNumberDivmodProtocol<'p>,
+@@ -938,15 +919,13 @@ where
+ }
+ 
+ trait PyNumberPowProtocolImpl {
+-    fn nb_power() -> Option<ffi::ternaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_power() -> Option<ffi::ternaryfunc> {
++    fn nb_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberPowProtocol<'p>,
+@@ -962,15 +941,13 @@ where
+ }
+ 
+ trait PyNumberLShiftProtocolImpl {
+-    fn nb_lshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_lshift() -> Option<ffi::binaryfunc> {
++    fn nb_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberLShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberLShiftProtocol<'p>,
+@@ -986,15 +963,13 @@ where
+ }
+ 
+ trait PyNumberRShiftProtocolImpl {
+-    fn nb_rshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_rshift() -> Option<ffi::binaryfunc> {
++    fn nb_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberRShiftProtocol<'p>,
+@@ -1010,15 +985,13 @@ where
+ }
+ 
+ trait PyNumberAndProtocolImpl {
+-    fn nb_and() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_and() -> Option<ffi::binaryfunc> {
++    fn nb_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberAndProtocol<'p>,
+@@ -1034,15 +1007,13 @@ where
+ }
+ 
+ trait PyNumberXorProtocolImpl {
+-    fn nb_xor() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_xor() -> Option<ffi::binaryfunc> {
++    fn nb_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberXorProtocol<'p>,
+@@ -1058,15 +1029,13 @@ where
+ }
+ 
+ trait PyNumberOrProtocolImpl {
+-    fn nb_or() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_or() -> Option<ffi::binaryfunc> {
++    fn nb_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberOrProtocol<'p>,
+@@ -1082,15 +1051,13 @@ where
+ }
+ 
+ trait PyNumberIAddProtocolImpl {
+-    fn nb_inplace_add() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_add() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAddProtocol<'p>,
+@@ -1101,15 +1068,13 @@ where
+ }
+ 
+ trait PyNumberISubProtocolImpl {
+-    fn nb_inplace_subtract() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberISubProtocolImpl for T
+ where
+     T: for<'p> PyNumberISubProtocol<'p>,
+@@ -1120,15 +1085,13 @@ where
+ }
+ 
+ trait PyNumberIMulProtocolImpl {
+-    fn nb_inplace_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMulProtocol<'p>,
+@@ -1139,15 +1102,13 @@ where
+ }
+ 
+ trait PyNumberIMatmulProtocolImpl {
+-    fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMatmulProtocol<'p>,
+@@ -1158,15 +1119,13 @@ where
+ }
+ 
+ trait PyNumberITruedivProtocolImpl {
+-    fn nb_inplace_true_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberITruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberITruedivProtocol<'p>,
+@@ -1177,15 +1136,13 @@ where
+ }
+ 
+ trait PyNumberIFloordivProtocolImpl {
+-    fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberIFloordivProtocol<'p>,
+@@ -1196,15 +1153,13 @@ where
+ }
+ 
+ trait PyNumberIModProtocolImpl {
+-    fn nb_inplace_remainder() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIModProtocolImpl for T
+ where
+     T: for<'p> PyNumberIModProtocol<'p>,
+@@ -1215,15 +1170,13 @@ where
+ }
+ 
+ trait PyNumberIPowProtocolImpl {
+-    fn nb_inplace_power() -> Option<ffi::ternaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
++    fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberIPowProtocol<'p>,
+@@ -1234,15 +1187,13 @@ where
+ }
+ 
+ trait PyNumberILShiftProtocolImpl {
+-    fn nb_inplace_lshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberILShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberILShiftProtocol<'p>,
+@@ -1253,15 +1204,13 @@ where
+ }
+ 
+ trait PyNumberIRShiftProtocolImpl {
+-    fn nb_inplace_rshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberIRShiftProtocol<'p>,
+@@ -1272,15 +1221,13 @@ where
+ }
+ 
+ trait PyNumberIAndProtocolImpl {
+-    fn nb_inplace_and() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_and() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAndProtocol<'p>,
+@@ -1291,15 +1238,13 @@ where
+ }
+ 
+ trait PyNumberIXorProtocolImpl {
+-    fn nb_inplace_xor() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberIXorProtocol<'p>,
+@@ -1310,15 +1255,13 @@ where
+ }
+ 
+ trait PyNumberIOrProtocolImpl {
+-    fn nb_inplace_or() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_or() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberIOrProtocol<'p>,
+@@ -1330,15 +1273,13 @@ where
+ 
+ #[doc(hidden)]
+ pub trait PyNumberRAddProtocolImpl {
+-    fn __radd__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __radd__() -> Option<PyMethodDef> {
++    fn __radd__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRSubProtocolImpl {
+     fn __rsub__() -> Option<PyMethodDef> {
+@@ -1350,146 +1291,120 @@ impl<'p, T> PyNumberRSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait PyNumberRMulProtocolImpl {
+-    fn __rmul__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rmul__() -> Option<PyMethodDef> {
++    fn __rmul__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRMatmulProtocolImpl {
+-    fn __rmatmul__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rmatmul__() -> Option<PyMethodDef> {
++    fn __rmatmul__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRTruedivProtocolImpl {
+-    fn __rtruediv__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rtruediv__() -> Option<PyMethodDef> {
++    fn __rtruediv__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRFloordivProtocolImpl {
+-    fn __rfloordiv__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rfloordiv__() -> Option<PyMethodDef> {
++    fn __rfloordiv__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRModProtocolImpl {
+-    fn __rmod__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rmod__() -> Option<PyMethodDef> {
++    fn __rmod__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRDivmodProtocolImpl {
+-    fn __rdivmod__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rdivmod__() -> Option<PyMethodDef> {
++    fn __rdivmod__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRPowProtocolImpl {
+-    fn __rpow__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rpow__() -> Option<PyMethodDef> {
++    fn __rpow__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRLShiftProtocolImpl {
+-    fn __rlshift__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rlshift__() -> Option<PyMethodDef> {
++    fn __rlshift__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRRShiftProtocolImpl {
+-    fn __rrshift__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rrshift__() -> Option<PyMethodDef> {
++    fn __rrshift__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRAndProtocolImpl {
+-    fn __rand__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rand__() -> Option<PyMethodDef> {
++    fn __rand__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRXorProtocolImpl {
+-    fn __rxor__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rxor__() -> Option<PyMethodDef> {
++    fn __rxor__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberROrProtocolImpl {
+-    fn __ror__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __ror__() -> Option<PyMethodDef> {
++    fn __ror__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-trait PyNumberNegProtocolImpl {
+-    fn nb_negative() -> Option<ffi::unaryfunc>;
+-}
++impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+-impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_negative() -> Option<ffi::unaryfunc> {
++trait PyNumberNegProtocolImpl {
++    fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberNegProtocolImpl for T
+ where
+     T: for<'p> PyNumberNegProtocol<'p>,
+@@ -1506,15 +1421,13 @@ where
+ }
+ 
+ trait PyNumberPosProtocolImpl {
+-    fn nb_positive() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_positive() -> Option<ffi::unaryfunc> {
++    fn nb_positive() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberPosProtocolImpl for T
+ where
+     T: for<'p> PyNumberPosProtocol<'p>,
+@@ -1530,15 +1443,13 @@ where
+ }
+ 
+ trait PyNumberAbsProtocolImpl {
+-    fn nb_absolute() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_absolute() -> Option<ffi::unaryfunc> {
++    fn nb_absolute() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberAbsProtocolImpl for T
+ where
+     T: for<'p> PyNumberAbsProtocol<'p>,
+@@ -1554,15 +1465,13 @@ where
+ }
+ 
+ trait PyNumberInvertProtocolImpl {
+-    fn nb_invert() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_invert() -> Option<ffi::unaryfunc> {
++    fn nb_invert() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberInvertProtocolImpl for T
+ where
+     T: for<'p> PyNumberInvertProtocol<'p>,
+@@ -1578,15 +1487,13 @@ where
+ }
+ 
+ trait PyNumberIntProtocolImpl {
+-    fn nb_int() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_int() -> Option<ffi::unaryfunc> {
++    fn nb_int() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIntProtocolImpl for T
+ where
+     T: for<'p> PyNumberIntProtocol<'p>,
+@@ -1602,15 +1509,13 @@ where
+ }
+ 
+ trait PyNumberFloatProtocolImpl {
+-    fn nb_float() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_float() -> Option<ffi::unaryfunc> {
++    fn nb_float() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberFloatProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloatProtocol<'p>,
+@@ -1626,15 +1531,13 @@ where
+ }
+ 
+ trait PyNumberIndexProtocolImpl {
+-    fn nb_index() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_index() -> Option<ffi::unaryfunc> {
++    fn nb_index() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIndexProtocolImpl for T
+ where
+     T: for<'p> PyNumberIndexProtocol<'p>,
+@@ -1650,21 +1553,17 @@ where
+ }
+ 
+ trait PyNumberComplexProtocolImpl {
+-    fn __complex__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __complex__() -> Option<PyMethodDef> {
++    fn __complex__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-trait PyNumberRoundProtocolImpl {
+-    fn __round__() -> Option<PyMethodDef>;
+-}
++impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+-impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __round__() -> Option<PyMethodDef> {
++trait PyNumberRoundProtocolImpl {
++    fn __round__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {}
+diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs
+index f977fadfa..9afb72c17 100644
+--- a/src/class/pyasync.rs
++++ b/src/class/pyasync.rs
+@@ -91,20 +91,17 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyAsyncProtocolImpl {
+-    fn tp_as_async() -> Option<ffi::PyAsyncMethods>;
+-    fn methods() -> Vec<PyMethodDef>;
+-}
+-
+-impl<T> PyAsyncProtocolImpl for T {
+-    default fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
++    fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
+         None
+     }
+ 
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+ }
+ 
++impl<T> PyAsyncProtocolImpl for T {}
++
+ impl<'p, T> PyAsyncProtocolImpl for T
+ where
+     T: PyAsyncProtocol<'p>,
+@@ -134,15 +131,13 @@ where
+ }
+ 
+ trait PyAsyncAwaitProtocolImpl {
+-    fn am_await() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn am_await() -> Option<ffi::unaryfunc> {
++    fn am_await() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
++
+ impl<T> PyAsyncAwaitProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAwaitProtocol<'p>,
+@@ -159,15 +154,13 @@ where
+ }
+ 
+ trait PyAsyncAiterProtocolImpl {
+-    fn am_aiter() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn am_aiter() -> Option<ffi::unaryfunc> {
++    fn am_aiter() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
++
+ impl<T> PyAsyncAiterProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAiterProtocol<'p>,
+@@ -184,15 +177,13 @@ where
+ }
+ 
+ trait PyAsyncAnextProtocolImpl {
+-    fn am_anext() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn am_anext() -> Option<ffi::unaryfunc> {
++    fn am_anext() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {}
++
+ mod anext {
+     use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
+     use crate::callback::CallbackConverter;
+@@ -242,21 +233,17 @@ mod anext {
+ }
+ 
+ trait PyAsyncAenterProtocolImpl {
+-    fn __aenter__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn __aenter__() -> Option<PyMethodDef> {
++    fn __aenter__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-trait PyAsyncAexitProtocolImpl {
+-    fn __aexit__() -> Option<PyMethodDef>;
+-}
++impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+ 
+-impl<'p, T> PyAsyncAexitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn __aexit__() -> Option<PyMethodDef> {
++trait PyAsyncAexitProtocolImpl {
++    fn __aexit__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyAsyncAexitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index ce65508fd..23771ba0b 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -134,15 +134,13 @@ pub trait PySequenceInplaceRepeatProtocol<'p>: PySequenceProtocol<'p> + IntoPy<P
+ 
+ #[doc(hidden)]
+ pub trait PySequenceProtocolImpl {
+-    fn tp_as_sequence() -> Option<ffi::PySequenceMethods>;
+-}
+-
+-impl<T> PySequenceProtocolImpl for T {
+-    default fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
++    fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
+         None
+     }
+ }
+ 
++impl<T> PySequenceProtocolImpl for T {}
++
+ impl<'p, T> PySequenceProtocolImpl for T
+ where
+     T: PySequenceProtocol<'p>,
+@@ -164,15 +162,13 @@ where
+ }
+ 
+ trait PySequenceLenProtocolImpl {
+-    fn sq_length() -> Option<ffi::lenfunc>;
+-}
+-
+-impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_length() -> Option<ffi::lenfunc> {
++    fn sq_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceLenProtocolImpl for T
+ where
+     T: for<'p> PySequenceLenProtocol<'p>,
+@@ -183,15 +179,13 @@ where
+ }
+ 
+ trait PySequenceGetItemProtocolImpl {
+-    fn sq_item() -> Option<ffi::ssizeargfunc>;
+-}
+-
+-impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_item() -> Option<ffi::ssizeargfunc> {
++    fn sq_item() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceGetItemProtocolImpl for T
+ where
+     T: for<'p> PySequenceGetItemProtocol<'p>,
+@@ -289,15 +283,13 @@ mod sq_ass_item_impl {
+     }
+ 
+     trait DelItem {
+-        fn del_item() -> Option<ffi::ssizeobjargproc>;
+-    }
+-
+-    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {
+-        default fn del_item() -> Option<ffi::ssizeobjargproc> {
++        fn del_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {}
++
+     impl<T> DelItem for T
+     where
+         T: for<'p> PySequenceDelItemProtocol<'p>,
+@@ -337,15 +329,13 @@ mod sq_ass_item_impl {
+     }
+ 
+     trait DelSetItem {
+-        fn del_set_item() -> Option<ffi::ssizeobjargproc>;
+-    }
+-
+-    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {
+-        default fn del_set_item() -> Option<ffi::ssizeobjargproc> {
++        fn del_set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {}
++
+     impl<T> DelSetItem for T
+     where
+         T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
+@@ -386,15 +376,13 @@ mod sq_ass_item_impl {
+ }
+ 
+ trait PySequenceContainsProtocolImpl {
+-    fn sq_contains() -> Option<ffi::objobjproc>;
+-}
+-
+-impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_contains() -> Option<ffi::objobjproc> {
++    fn sq_contains() -> Option<ffi::objobjproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceContainsProtocolImpl for T
+ where
+     T: for<'p> PySequenceContainsProtocol<'p>,
+@@ -411,15 +399,13 @@ where
+ }
+ 
+ trait PySequenceConcatProtocolImpl {
+-    fn sq_concat() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_concat() -> Option<ffi::binaryfunc> {
++    fn sq_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceConcatProtocol<'p>,
+@@ -435,15 +421,13 @@ where
+ }
+ 
+ trait PySequenceRepeatProtocolImpl {
+-    fn sq_repeat() -> Option<ffi::ssizeargfunc>;
+-}
+-
+-impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_repeat() -> Option<ffi::ssizeargfunc> {
++    fn sq_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceRepeatProtocol<'p>,
+@@ -459,15 +443,13 @@ where
+ }
+ 
+ trait PySequenceInplaceConcatProtocolImpl {
+-    fn sq_inplace_concat() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
++    fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceInplaceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceConcatProtocol<'p>,
+@@ -483,15 +465,13 @@ where
+ }
+ 
+ trait PySequenceInplaceRepeatProtocolImpl {
+-    fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc>;
+-}
+-
+-impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
++    fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceInplaceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceRepeatProtocol<'p>,
+diff --git a/src/conversion.rs b/src/conversion.rs
+index 15ccdabde..a3bca1175 100644
+--- a/src/conversion.rs
++++ b/src/conversion.rs
+@@ -96,12 +96,6 @@ pub trait ToBorrowedObject: ToPyObject {
+     /// May be more efficient than `to_object` because it does not need
+     /// to touch any reference counts when the input object already is a Python object.
+     fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
+-    where
+-        F: FnOnce(*mut ffi::PyObject) -> R;
+-}
+-
+-impl<T> ToBorrowedObject for T where T: ToPyObject {
+-    default fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
+     where
+         F: FnOnce(*mut ffi::PyObject) -> R,
+     {
+@@ -114,6 +108,8 @@ impl<T> ToBorrowedObject for T where T: ToPyObject {
+     }
+ }
+ 
++impl<T> ToBorrowedObject for T where T: ToPyObject {}
++
+ impl<T> ToBorrowedObject for T
+ where
+     T: ToPyObject + AsPyPointer,
+diff --git a/src/instance.rs b/src/instance.rs
+index 779d18617..68bd45ec3 100644
+--- a/src/instance.rs
++++ b/src/instance.rs
+@@ -359,18 +359,13 @@ impl<T> Py<T> {
+ 
+ /// Specialization workaround
+ trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
+-    fn as_ref_dispatch(&self, _py: Python) -> &T;
+-    fn as_mut_dispatch(&mut self, _py: Python) -> &mut T;
+-}
+-
+-impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {
+-    default fn as_ref_dispatch(&self, _py: Python) -> &T {
++    fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe {
+             let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
+             ptr.as_ref().expect("Py has a null pointer")
+         }
+     }
+-    default fn as_mut_dispatch(&mut self, _py: Python) -> &mut T {
++    fn as_mut_dispatch(&mut self, _py: Python) -> &mut T {
+         unsafe {
+             let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
+             ptr.as_mut().expect("Py has a null pointer")
+@@ -378,6 +373,8 @@ impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {
+     }
+ }
+ 
++impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {}
++
+ impl<T: PyTypeInfo + PyNativeType> AsPyRefDispatch<T> for Py<T> {
+     fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe { &*(self as *const instance::Py<T> as *const T) }
+@@ -556,21 +553,9 @@ impl<'p, T: ToPyObject> AsPyPointer for ManagedPyRef<'p, T> {
+ /// Helper trait to choose the right implementation for [ManagedPyRef]
+ pub trait ManagedPyRefDispatch: ToPyObject {
+     /// Optionally converts into a python object and stores the pointer to the python heap.
+-    fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self>;
+-
+-    /// Dispatch over a xdecref and a noop drop impl
+-    fn drop_impl(borrowed: &mut ManagedPyRef<Self>);
+-}
+-
+-/// Case 1: It's a rust object which still needs to be converted to a python object.
+-/// This means we're storing the owned pointer that into_ptr() has given us
+-/// and therefore need to xdecref when we're done.
+-///
+-/// Note that the actual implementations are part of the trait declaration to avoid
+-/// a specialization error
+-impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {
++    ///
+     /// Contains the case 1 impl (with to_object) to avoid a specialization error
+-    default fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self> {
++    fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self> {
+         ManagedPyRef {
+             data: self.to_object(py).into_ptr(),
+             data_type: PhantomData,
+@@ -578,12 +563,22 @@ impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {
+         }
+     }
+ 
++    /// Dispatch over a xdecref and a noop drop impl
++    ///
+     /// Contains the case 1 impl (decref) to avoid a specialization error
+-    default fn drop_impl(borrowed: &mut ManagedPyRef<Self>) {
++    fn drop_impl(borrowed: &mut ManagedPyRef<Self>) {
+         unsafe { ffi::Py_DECREF(borrowed.data) };
+     }
+ }
+ 
++/// Case 1: It's a rust object which still needs to be converted to a python object.
++/// This means we're storing the owned pointer that into_ptr() has given us
++/// and therefore need to xdecref when we're done.
++///
++/// Note that the actual implementations are part of the trait declaration to avoid
++/// a specialization error
++impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {}
++
+ /// Case 2: It's an object on the python heap, we're just storing a borrowed pointer.
+ /// The object we're getting is an owned pointer, it might have it's own drop impl.
+ impl<T: ToPyObject + AsPyPointer + ?Sized> ManagedPyRefDispatch for T {
diff --git a/srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch b/srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch
new file mode 100644
index 00000000000..c4315a09425
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch
@@ -0,0 +1,1659 @@
+From 2f4dfec729e00355bbd067e5770a9e8e889280cf Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Mon, 28 Oct 2019 14:44:26 -0700
+Subject: [PATCH] Removed specialization for all traits
+
+Crate compiles but tests all fail due to missing trait implementations
+---
+ build.rs              |   5 --
+ src/class/basic.rs    |  55 ++++++------
+ src/class/buffer.rs   |   8 +-
+ src/class/context.rs  |   2 -
+ src/class/descr.rs    |  11 +--
+ src/class/gc.rs       |  12 +--
+ src/class/iter.rs     |  12 +--
+ src/class/mapping.rs  |  24 ++---
+ src/class/number.rs   | 199 +++++++++++++++++++-----------------------
+ src/class/pyasync.rs  |  19 ++--
+ src/class/sequence.rs |  63 +++++--------
+ src/conversion.rs     |   9 +-
+ src/instance.rs       |  13 ++-
+ src/lib.rs            |   2 -
+ src/object.rs         |   2 +-
+ src/type_object.rs    |  50 +++++++++--
+ src/types/sequence.rs |   5 +-
+ 17 files changed, 229 insertions(+), 262 deletions(-)
+
+diff --git a/build.rs b/build.rs
+index 7f1060acc..d6b38c489 100644
+--- a/build.rs
++++ b/build.rs
+@@ -537,11 +537,6 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<(String), String>
+ }
+ 
+ fn check_rustc_version() {
+-    let channel = Channel::read().expect("Failed to determine rustc channel");
+-    if !channel.supports_features() {
+-        panic!("Error: pyo3 requires a nightly or dev version of Rust.");
+-    }
+-
+     let actual_version = Version::read().expect("Failed to determine the rustc version");
+     if !actual_version.at_least(MIN_VERSION) {
+         panic!(
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index c3153dfa3..f87a0d029 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -161,11 +161,21 @@ pub trait PyObjectProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyObjectProtocolImpl for T {}
++//impl<T> PyObjectProtocolImpl for T {}
+ 
+ impl<'p, T> PyObjectProtocolImpl for T
+ where
+-    T: PyObjectProtocol<'p>,
++    T: PyObjectProtocol<'p>
++        + PyObjectSetAttrProtocol<'p>
++        + GetAttrProtocolImpl
++        + StrProtocolImpl
++        + ReprProtocolImpl
++        + HashProtocolImpl
++        + RichcmpProtocolImpl
++        + BoolProtocolImpl
++        + tp_setattro_impl::DelAttr
++        + tp_setattro_impl::SetAttr
++        + tp_setattro_impl::SetDelAttr,
+ {
+     fn methods() -> Vec<PyMethodDef> {
+         let mut methods = Vec::new();
+@@ -194,14 +204,12 @@ where
+     }
+ }
+ 
+-trait GetAttrProtocolImpl {
++pub trait GetAttrProtocolImpl {
+     fn tp_getattro() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
+-
+ impl<T> GetAttrProtocolImpl for T
+ where
+     T: for<'p> PyObjectGetAttrProtocol<'p>,
+@@ -255,7 +263,10 @@ mod tp_setattro_impl {
+     /// The signature is the same as for PyObject_SetAttr(), but setting v to NULL to delete an
+     /// attribute must be supported. It is usually convenient to set this field to
+     /// PyObject_GenericSetAttr(), which implements the normal way of setting object attributes.
+-    pub(super) fn tp_setattro<'p, T: PyObjectProtocol<'p>>() -> Option<ffi::setattrofunc> {
++    pub(super) fn tp_setattro<'p, T>() -> Option<ffi::setattrofunc>
++    where
++        T: PyObjectProtocol<'p> + SetDelAttr + SetAttr + DelAttr,
++    {
+         if let Some(set_del) = T::set_del_attr() {
+             Some(set_del)
+         } else if let Some(set) = T::set_attr() {
+@@ -267,14 +278,12 @@ mod tp_setattro_impl {
+         }
+     }
+ 
+-    trait SetAttr {
++    pub trait SetAttr {
+         fn set_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T: PyObjectProtocol<'p>> SetAttr for T {}
+-
+     impl<T> SetAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p>,
+@@ -284,14 +293,12 @@ mod tp_setattro_impl {
+         }
+     }
+ 
+-    trait DelAttr {
++    pub trait DelAttr {
+         fn del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {}
+-
+     impl<T> DelAttr for T
+     where
+         T: for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -301,14 +308,12 @@ mod tp_setattro_impl {
+         }
+     }
+ 
+-    trait SetDelAttr {
++    pub trait SetDelAttr {
+         fn set_del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {}
+-
+     impl<T> SetDelAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -325,12 +330,12 @@ mod tp_setattro_impl {
+     }
+ }
+ 
+-trait StrProtocolImpl {
++pub trait StrProtocolImpl {
+     fn tp_str() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+-impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> StrProtocolImpl for T
+ where
+     T: for<'p> PyObjectStrProtocol<'p>,
+@@ -345,12 +350,12 @@ where
+     }
+ }
+ 
+-trait ReprProtocolImpl {
++pub trait ReprProtocolImpl {
+     fn tp_repr() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+-impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> ReprProtocolImpl for T
+ where
+     T: for<'p> PyObjectReprProtocol<'p>,
+@@ -389,12 +394,12 @@ pub trait UnicodeProtocolImpl {
+ }
+ impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+-trait HashProtocolImpl {
++pub trait HashProtocolImpl {
+     fn tp_hash() -> Option<ffi::hashfunc> {
+         None
+     }
+ }
+-impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> HashProtocolImpl for T
+ where
+     T: for<'p> PyObjectHashProtocol<'p>,
+@@ -410,12 +415,12 @@ where
+     }
+ }
+ 
+-trait BoolProtocolImpl {
++pub trait BoolProtocolImpl {
+     fn nb_bool() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+-impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> BoolProtocolImpl for T
+ where
+     T: for<'p> PyObjectBoolProtocol<'p>,
+@@ -431,12 +436,12 @@ where
+     }
+ }
+ 
+-trait RichcmpProtocolImpl {
++pub trait RichcmpProtocolImpl {
+     fn tp_richcompare() -> Option<ffi::richcmpfunc> {
+         None
+     }
+ }
+-impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> RichcmpProtocolImpl for T
+ where
+     T: for<'p> PyObjectRichcmpProtocol<'p>,
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index d36524e7c..32d1a25af 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -46,11 +46,9 @@ pub trait PyBufferProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyBufferProtocolImpl for T {}
+-
+ impl<'p, T> PyBufferProtocolImpl for T
+ where
+-    T: PyBufferProtocol<'p>,
++    T: PyBufferProtocol<'p> + PyBufferGetBufferProtocolImpl,
+ {
+     #[inline]
+     #[allow(clippy::needless_update)] // For python 2 it's not useless
+@@ -63,14 +61,12 @@ where
+     }
+ }
+ 
+-trait PyBufferGetBufferProtocolImpl {
++pub trait PyBufferGetBufferProtocolImpl {
+     fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {}
+-
+ impl<T> PyBufferGetBufferProtocolImpl for T
+ where
+     T: for<'p> PyBufferGetBufferProtocol<'p>,
+diff --git a/src/class/context.rs b/src/class/context.rs
+index 092527ba0..e5dd56b90 100644
+--- a/src/class/context.rs
++++ b/src/class/context.rs
+@@ -52,8 +52,6 @@ pub trait PyContextProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyContextProtocolImpl for T {}
+-
+ impl<'p, T> PyContextProtocolImpl for T
+ where
+     T: PyContextProtocol<'p>,
+diff --git a/src/class/descr.rs b/src/class/descr.rs
+index 5f7e68306..ea1dbf012 100644
+--- a/src/class/descr.rs
++++ b/src/class/descr.rs
+@@ -69,12 +69,11 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
+     type Result: Into<PyResult<()>>;
+ }
+ 
+-trait PyDescrGetProtocolImpl {
++pub trait PyDescrGetProtocolImpl {
+     fn tp_descr_get() -> Option<ffi::descrgetfunc> {
+         None
+     }
+ }
+-impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ 
+ impl<T> PyDescrGetProtocolImpl for T
+ where
+@@ -90,12 +89,12 @@ where
+     }
+ }
+ 
+-trait PyDescrSetProtocolImpl {
++pub trait PyDescrSetProtocolImpl {
+     fn tp_descr_set() -> Option<ffi::descrsetfunc> {
+         None
+     }
+ }
+-impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {}
++
+ impl<T> PyDescrSetProtocolImpl for T
+ where
+     T: for<'p> PyDescrSetProtocol<'p>,
+@@ -133,11 +132,9 @@ pub trait PyDescrProtocolImpl {
+     fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<T> PyDescrProtocolImpl for T {}
+-
+ impl<'p, T> PyDescrProtocolImpl for T
+ where
+-    T: PyDescrProtocol<'p>,
++    T: PyDescrProtocol<'p> + PyDescrGetProtocolImpl + PyDescrSetProtocolImpl,
+ {
+     fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+diff --git a/src/class/gc.rs b/src/class/gc.rs
+index eaa4d9015..7e6bc8b45 100644
+--- a/src/class/gc.rs
++++ b/src/class/gc.rs
+@@ -26,11 +26,9 @@ pub trait PyGCProtocolImpl {
+     fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<'p, T> PyGCProtocolImpl for T {}
+-
+ impl<'p, T> PyGCProtocolImpl for T
+ where
+-    T: PyGCProtocol<'p>,
++    T: PyGCProtocol<'p> + PyGCTraverseProtocolImpl + PyGCClearProtocolImpl,
+ {
+     fn update_type_object(type_object: &mut ffi::PyTypeObject) {
+         type_object.tp_traverse = Self::tp_traverse();
+@@ -62,14 +60,12 @@ impl<'p> PyVisit<'p> {
+     }
+ }
+ 
+-trait PyGCTraverseProtocolImpl {
++pub trait PyGCTraverseProtocolImpl {
+     fn tp_traverse() -> Option<ffi::traverseproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {}
+-
+ #[doc(hidden)]
+ impl<T> PyGCTraverseProtocolImpl for T
+ where
+@@ -104,14 +100,12 @@ where
+     }
+ }
+ 
+-trait PyGCClearProtocolImpl {
++pub trait PyGCClearProtocolImpl {
+     fn tp_clear() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {}
+-
+ impl<T> PyGCClearProtocolImpl for T
+ where
+     T: for<'p> PyGCClearProtocol<'p>,
+diff --git a/src/class/iter.rs b/src/class/iter.rs
+index 9001d53ce..b1e896420 100644
+--- a/src/class/iter.rs
++++ b/src/class/iter.rs
+@@ -47,11 +47,9 @@ pub trait PyIterProtocolImpl {
+     fn tp_as_iter(_typeob: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<T> PyIterProtocolImpl for T {}
+-
+ impl<'p, T> PyIterProtocolImpl for T
+ where
+-    T: PyIterProtocol<'p>,
++    T: PyIterProtocol<'p> + PyIterIterProtocolImpl + PyIterNextProtocolImpl,
+ {
+     #[inline]
+     fn tp_as_iter(typeob: &mut ffi::PyTypeObject) {
+@@ -60,14 +58,12 @@ where
+     }
+ }
+ 
+-trait PyIterIterProtocolImpl {
++pub trait PyIterIterProtocolImpl {
+     fn tp_iter() -> Option<ffi::getiterfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {}
+-
+ impl<T> PyIterIterProtocolImpl for T
+ where
+     T: for<'p> PyIterIterProtocol<'p>,
+@@ -83,14 +79,12 @@ where
+     }
+ }
+ 
+-trait PyIterNextProtocolImpl {
++pub trait PyIterNextProtocolImpl {
+     fn tp_iternext() -> Option<ffi::iternextfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {}
+-
+ impl<T> PyIterNextProtocolImpl for T
+ where
+     T: for<'p> PyIterNextProtocol<'p>,
+diff --git a/src/class/mapping.rs b/src/class/mapping.rs
+index 616763502..df2ede958 100644
+--- a/src/class/mapping.rs
++++ b/src/class/mapping.rs
+@@ -114,11 +114,12 @@ pub trait PyMappingProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyMappingProtocolImpl for T {}
+-
+ impl<'p, T> PyMappingProtocolImpl for T
+ where
+-    T: PyMappingProtocol<'p>,
++    T: PyMappingProtocol<'p>
++        + PyMappingSetItemProtocolImpl
++        + PyMappingGetItemProtocolImpl
++        + PyMappingLenProtocolImpl,
+ {
+     #[inline]
+     fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
+@@ -153,14 +154,12 @@ where
+     }
+ }
+ 
+-trait PyMappingLenProtocolImpl {
++pub trait PyMappingLenProtocolImpl {
+     fn mp_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {}
+-
+ impl<T> PyMappingLenProtocolImpl for T
+ where
+     T: for<'p> PyMappingLenProtocol<'p>,
+@@ -171,14 +170,12 @@ where
+     }
+ }
+ 
+-trait PyMappingGetItemProtocolImpl {
++pub trait PyMappingGetItemProtocolImpl {
+     fn mp_subscript() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
+-
+ impl<T> PyMappingGetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingGetItemProtocol<'p>,
+@@ -194,14 +191,12 @@ where
+     }
+ }
+ 
+-trait PyMappingSetItemProtocolImpl {
++pub trait PyMappingSetItemProtocolImpl {
+     fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
+-
+ impl<T> PyMappingSetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p>,
+@@ -229,8 +224,6 @@ trait DelSetItemDispatch: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+     }
+ }
+ 
+-impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {}
+-
+ impl<T> DelSetItemDispatch for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p> + for<'p> PyMappingDelItemProtocol<'p>,
+@@ -246,6 +239,7 @@ where
+     }
+ }
+ 
++/* MJDFIXME
+ impl<T> DeplItemDipatch for T
+ where
+     T: Sized + for<'p> PyMappingDelItemProtocol<'p>,
+@@ -253,7 +247,7 @@ where
+     fn mp_del_subscript() -> Option<ffi::objobjargproc> {
+         <T as DelSetItemDispatch>::det_set_dispatch()
+     }
+-}
++}*/
+ 
+ #[doc(hidden)]
+ pub trait PyMappingContainsProtocolImpl {
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 2ee3a57d5..796a1c7ea 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -638,11 +638,60 @@ pub trait PyNumberProtocolImpl: PyObjectProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberProtocolImpl for T {}
+-
+ impl<'p, T> PyNumberProtocolImpl for T
+ where
+-    T: PyNumberProtocol<'p>,
++    T: PyNumberProtocol<'p>
++        + PyNumberAbsProtocolImpl
++        + PyNumberAddProtocolImpl
++        + PyNumberAndProtocolImpl
++        + PyNumberComplexProtocolImpl
++        + PyNumberDivmodProtocolImpl
++        + PyNumberFloatProtocolImpl
++        + PyNumberFloordivProtocolImpl
++        + PyNumberIAddProtocolImpl
++        + PyNumberIAndProtocolImpl
++        + PyNumberIFloordivProtocolImpl
++        + PyNumberILShiftProtocolImpl
++        + PyNumberIMatmulProtocolImpl
++        + PyNumberIModProtocolImpl
++        + PyNumberIMulProtocolImpl
++        + PyNumberIOrProtocolImpl
++        + PyNumberIPowProtocolImpl
++        + PyNumberIRShiftProtocolImpl
++        + PyNumberISubProtocolImpl
++        + PyNumberITruedivProtocolImpl
++        + PyNumberIXorProtocolImpl
++        + PyNumberIndexProtocolImpl
++        + PyNumberIntProtocolImpl
++        + PyNumberInvertProtocolImpl
++        + PyNumberLShiftProtocolImpl
++        + PyNumberMatmulProtocolImpl
++        + PyNumberModProtocolImpl
++        + PyNumberMulProtocolImpl
++        + PyNumberNegProtocolImpl
++        + PyNumberOrProtocolImpl
++        + PyNumberPosProtocolImpl
++        + PyNumberPowProtocolImpl
++        + PyNumberRAddProtocolImpl
++        + PyNumberRAndProtocolImpl
++        + PyNumberRDivmodProtocolImpl
++        + PyNumberRFloordivProtocolImpl
++        + PyNumberRLShiftProtocolImpl
++        + PyNumberRMatmulProtocolImpl
++        + PyNumberRModProtocolImpl
++        + PyNumberRMulProtocolImpl
++        + PyNumberROrProtocolImpl
++        + PyNumberRPowProtocolImpl
++        + PyNumberRRShiftProtocolImpl
++        + PyNumberRShiftProtocolImpl
++        + PyNumberRSubProtocolImpl
++        + PyNumberRTruedivProtocolImpl
++        + PyNumberRXorProtocolImpl
++        + PyNumberRoundProtocolImpl
++        + PyNumberSubProtocolImpl
++        + PyNumberTruedivProtocolImpl
++        + PyNumberXorProtocolImpl
++        + PyObjectProtocolImpl,
+ {
+     fn tp_as_number() -> Option<ffi::PyNumberMethods> {
+         Some(ffi::PyNumberMethods {
+@@ -742,14 +791,12 @@ where
+     }
+ }
+ 
+-trait PyNumberAddProtocolImpl {
++pub trait PyNumberAddProtocolImpl {
+     fn nb_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberAddProtocol<'p>,
+@@ -764,14 +811,12 @@ where
+     }
+ }
+ 
+-trait PyNumberSubProtocolImpl {
++pub trait PyNumberSubProtocolImpl {
+     fn nb_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberSubProtocolImpl for T
+ where
+     T: for<'p> PyNumberSubProtocol<'p>,
+@@ -786,14 +831,12 @@ where
+     }
+ }
+ 
+-trait PyNumberMulProtocolImpl {
++pub trait PyNumberMulProtocolImpl {
+     fn nb_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMulProtocol<'p>,
+@@ -808,14 +851,12 @@ where
+     }
+ }
+ 
+-trait PyNumberMatmulProtocolImpl {
++pub trait PyNumberMatmulProtocolImpl {
+     fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMatmulProtocol<'p>,
+@@ -830,14 +871,12 @@ where
+     }
+ }
+ 
+-trait PyNumberTruedivProtocolImpl {
++pub trait PyNumberTruedivProtocolImpl {
+     fn nb_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberTruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberTruedivProtocol<'p>,
+@@ -852,14 +891,12 @@ where
+     }
+ }
+ 
+-trait PyNumberFloordivProtocolImpl {
++pub trait PyNumberFloordivProtocolImpl {
+     fn nb_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloordivProtocol<'p>,
+@@ -874,14 +911,12 @@ where
+     }
+ }
+ 
+-trait PyNumberModProtocolImpl {
++pub trait PyNumberModProtocolImpl {
+     fn nb_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberModProtocolImpl for T
+ where
+     T: for<'p> PyNumberModProtocol<'p>,
+@@ -896,14 +931,12 @@ where
+     }
+ }
+ 
+-trait PyNumberDivmodProtocolImpl {
++pub trait PyNumberDivmodProtocolImpl {
+     fn nb_divmod() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberDivmodProtocolImpl for T
+ where
+     T: for<'p> PyNumberDivmodProtocol<'p>,
+@@ -918,14 +951,12 @@ where
+     }
+ }
+ 
+-trait PyNumberPowProtocolImpl {
++pub trait PyNumberPowProtocolImpl {
+     fn nb_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberPowProtocol<'p>,
+@@ -940,14 +971,12 @@ where
+     }
+ }
+ 
+-trait PyNumberLShiftProtocolImpl {
++pub trait PyNumberLShiftProtocolImpl {
+     fn nb_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberLShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberLShiftProtocol<'p>,
+@@ -962,14 +991,12 @@ where
+     }
+ }
+ 
+-trait PyNumberRShiftProtocolImpl {
++pub trait PyNumberRShiftProtocolImpl {
+     fn nb_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberRShiftProtocol<'p>,
+@@ -984,14 +1011,12 @@ where
+     }
+ }
+ 
+-trait PyNumberAndProtocolImpl {
++pub trait PyNumberAndProtocolImpl {
+     fn nb_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberAndProtocol<'p>,
+@@ -1006,14 +1031,12 @@ where
+     }
+ }
+ 
+-trait PyNumberXorProtocolImpl {
++pub trait PyNumberXorProtocolImpl {
+     fn nb_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberXorProtocol<'p>,
+@@ -1028,14 +1051,12 @@ where
+     }
+ }
+ 
+-trait PyNumberOrProtocolImpl {
++pub trait PyNumberOrProtocolImpl {
+     fn nb_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberOrProtocol<'p>,
+@@ -1050,14 +1071,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIAddProtocolImpl {
++pub trait PyNumberIAddProtocolImpl {
+     fn nb_inplace_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAddProtocol<'p>,
+@@ -1067,14 +1086,12 @@ where
+     }
+ }
+ 
+-trait PyNumberISubProtocolImpl {
++pub trait PyNumberISubProtocolImpl {
+     fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberISubProtocolImpl for T
+ where
+     T: for<'p> PyNumberISubProtocol<'p>,
+@@ -1084,14 +1101,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIMulProtocolImpl {
++pub trait PyNumberIMulProtocolImpl {
+     fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMulProtocol<'p>,
+@@ -1101,14 +1116,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIMatmulProtocolImpl {
++pub trait PyNumberIMatmulProtocolImpl {
+     fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMatmulProtocol<'p>,
+@@ -1118,14 +1131,12 @@ where
+     }
+ }
+ 
+-trait PyNumberITruedivProtocolImpl {
++pub trait PyNumberITruedivProtocolImpl {
+     fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberITruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberITruedivProtocol<'p>,
+@@ -1135,14 +1146,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIFloordivProtocolImpl {
++pub trait PyNumberIFloordivProtocolImpl {
+     fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberIFloordivProtocol<'p>,
+@@ -1152,14 +1161,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIModProtocolImpl {
++pub trait PyNumberIModProtocolImpl {
+     fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIModProtocolImpl for T
+ where
+     T: for<'p> PyNumberIModProtocol<'p>,
+@@ -1169,14 +1176,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIPowProtocolImpl {
++pub trait PyNumberIPowProtocolImpl {
+     fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberIPowProtocol<'p>,
+@@ -1186,14 +1191,12 @@ where
+     }
+ }
+ 
+-trait PyNumberILShiftProtocolImpl {
++pub trait PyNumberILShiftProtocolImpl {
+     fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberILShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberILShiftProtocol<'p>,
+@@ -1203,14 +1206,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIRShiftProtocolImpl {
++pub trait PyNumberIRShiftProtocolImpl {
+     fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberIRShiftProtocol<'p>,
+@@ -1220,14 +1221,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIAndProtocolImpl {
++pub trait PyNumberIAndProtocolImpl {
+     fn nb_inplace_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAndProtocol<'p>,
+@@ -1237,14 +1236,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIXorProtocolImpl {
++pub trait PyNumberIXorProtocolImpl {
+     fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberIXorProtocol<'p>,
+@@ -1254,14 +1251,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIOrProtocolImpl {
++pub trait PyNumberIOrProtocolImpl {
+     fn nb_inplace_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberIOrProtocol<'p>,
+@@ -1397,14 +1392,12 @@ pub trait PyNumberROrProtocolImpl {
+ 
+ impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+-trait PyNumberNegProtocolImpl {
++pub trait PyNumberNegProtocolImpl {
+     fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberNegProtocolImpl for T
+ where
+     T: for<'p> PyNumberNegProtocol<'p>,
+@@ -1420,14 +1413,12 @@ where
+     }
+ }
+ 
+-trait PyNumberPosProtocolImpl {
++pub trait PyNumberPosProtocolImpl {
+     fn nb_positive() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberPosProtocolImpl for T
+ where
+     T: for<'p> PyNumberPosProtocol<'p>,
+@@ -1442,14 +1433,12 @@ where
+     }
+ }
+ 
+-trait PyNumberAbsProtocolImpl {
++pub trait PyNumberAbsProtocolImpl {
+     fn nb_absolute() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberAbsProtocolImpl for T
+ where
+     T: for<'p> PyNumberAbsProtocol<'p>,
+@@ -1464,14 +1453,12 @@ where
+     }
+ }
+ 
+-trait PyNumberInvertProtocolImpl {
++pub trait PyNumberInvertProtocolImpl {
+     fn nb_invert() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberInvertProtocolImpl for T
+ where
+     T: for<'p> PyNumberInvertProtocol<'p>,
+@@ -1486,14 +1473,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIntProtocolImpl {
++pub trait PyNumberIntProtocolImpl {
+     fn nb_int() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIntProtocolImpl for T
+ where
+     T: for<'p> PyNumberIntProtocol<'p>,
+@@ -1508,14 +1493,12 @@ where
+     }
+ }
+ 
+-trait PyNumberFloatProtocolImpl {
++pub trait PyNumberFloatProtocolImpl {
+     fn nb_float() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberFloatProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloatProtocol<'p>,
+@@ -1530,14 +1513,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIndexProtocolImpl {
++pub trait PyNumberIndexProtocolImpl {
+     fn nb_index() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIndexProtocolImpl for T
+ where
+     T: for<'p> PyNumberIndexProtocol<'p>,
+@@ -1552,18 +1533,14 @@ where
+     }
+ }
+ 
+-trait PyNumberComplexProtocolImpl {
++pub trait PyNumberComplexProtocolImpl {
+     fn __complex__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+-trait PyNumberRoundProtocolImpl {
++pub trait PyNumberRoundProtocolImpl {
+     fn __round__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+-
+-impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {}
+diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs
+index 9afb72c17..e04aea33b 100644
+--- a/src/class/pyasync.rs
++++ b/src/class/pyasync.rs
+@@ -100,11 +100,12 @@ pub trait PyAsyncProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyAsyncProtocolImpl for T {}
+-
+ impl<'p, T> PyAsyncProtocolImpl for T
+ where
+-    T: PyAsyncProtocol<'p>,
++    T: PyAsyncProtocol<'p>
++        + PyAsyncAwaitProtocolImpl
++        + PyAsyncAiterProtocolImpl
++        + PyAsyncAnextProtocolImpl,
+ {
+     #[inline]
+     fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
+@@ -130,14 +131,12 @@ where
+     }
+ }
+ 
+-trait PyAsyncAwaitProtocolImpl {
++pub trait PyAsyncAwaitProtocolImpl {
+     fn am_await() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+-
+ impl<T> PyAsyncAwaitProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAwaitProtocol<'p>,
+@@ -153,14 +152,12 @@ where
+     }
+ }
+ 
+-trait PyAsyncAiterProtocolImpl {
++pub trait PyAsyncAiterProtocolImpl {
+     fn am_aiter() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+-
+ impl<T> PyAsyncAiterProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAiterProtocol<'p>,
+@@ -176,14 +173,12 @@ where
+     }
+ }
+ 
+-trait PyAsyncAnextProtocolImpl {
++pub trait PyAsyncAnextProtocolImpl {
+     fn am_anext() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+-
+ mod anext {
+     use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
+     use crate::callback::CallbackConverter;
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index 23771ba0b..840c11b97 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -139,11 +139,19 @@ pub trait PySequenceProtocolImpl {
+     }
+ }
+ 
+-impl<T> PySequenceProtocolImpl for T {}
+-
+ impl<'p, T> PySequenceProtocolImpl for T
+ where
+-    T: PySequenceProtocol<'p>,
++    T: PySequenceProtocol<'p>
++        + PySequenceConcatProtocolImpl
++        + PySequenceContainsProtocolImpl
++        + PySequenceGetItemProtocolImpl
++        + PySequenceInplaceConcatProtocolImpl
++        + PySequenceInplaceRepeatProtocolImpl
++        + PySequenceLenProtocolImpl
++        + PySequenceRepeatProtocolImpl
++        + sq_ass_item_impl::SetItem
++        + sq_ass_item_impl::DelItem
++        + sq_ass_item_impl::DelSetItem,
+ {
+     fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
+         Some(ffi::PySequenceMethods {
+@@ -161,14 +169,12 @@ where
+     }
+ }
+ 
+-trait PySequenceLenProtocolImpl {
++pub trait PySequenceLenProtocolImpl {
+     fn sq_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceLenProtocolImpl for T
+ where
+     T: for<'p> PySequenceLenProtocol<'p>,
+@@ -178,14 +184,12 @@ where
+     }
+ }
+ 
+-trait PySequenceGetItemProtocolImpl {
++pub trait PySequenceGetItemProtocolImpl {
+     fn sq_item() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceGetItemProtocolImpl for T
+ where
+     T: for<'p> PySequenceGetItemProtocol<'p>,
+@@ -214,7 +218,7 @@ mod sq_ass_item_impl {
+     /// item assignment and deletion.
+     pub(super) fn sq_ass_item<'p, T>() -> Option<ffi::ssizeobjargproc>
+     where
+-        T: PySequenceProtocol<'p>,
++        T: PySequenceProtocol<'p> + SetItem + DelItem + DelSetItem,
+     {
+         if let Some(del_set_item) = T::del_set_item() {
+             Some(del_set_item)
+@@ -227,15 +231,8 @@ mod sq_ass_item_impl {
+         }
+     }
+ 
+-    trait SetItem {
+-        fn set_item() -> Option<ffi::ssizeobjargproc>;
+-    }
+-
+-    impl<'p, T> SetItem for T
+-    where
+-        T: PySequenceProtocol<'p>,
+-    {
+-        default fn set_item() -> Option<ffi::ssizeobjargproc> {
++    pub trait SetItem {
++        fn set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+@@ -282,14 +279,12 @@ mod sq_ass_item_impl {
+         }
+     }
+ 
+-    trait DelItem {
++    pub trait DelItem {
+         fn del_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {}
+-
+     impl<T> DelItem for T
+     where
+         T: for<'p> PySequenceDelItemProtocol<'p>,
+@@ -328,14 +323,12 @@ mod sq_ass_item_impl {
+         }
+     }
+ 
+-    trait DelSetItem {
++    pub trait DelSetItem {
+         fn del_set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {}
+-
+     impl<T> DelSetItem for T
+     where
+         T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
+@@ -375,14 +368,12 @@ mod sq_ass_item_impl {
+     }
+ }
+ 
+-trait PySequenceContainsProtocolImpl {
++pub trait PySequenceContainsProtocolImpl {
+     fn sq_contains() -> Option<ffi::objobjproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceContainsProtocolImpl for T
+ where
+     T: for<'p> PySequenceContainsProtocol<'p>,
+@@ -398,14 +389,12 @@ where
+     }
+ }
+ 
+-trait PySequenceConcatProtocolImpl {
++pub trait PySequenceConcatProtocolImpl {
+     fn sq_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceConcatProtocol<'p>,
+@@ -420,14 +409,12 @@ where
+     }
+ }
+ 
+-trait PySequenceRepeatProtocolImpl {
++pub trait PySequenceRepeatProtocolImpl {
+     fn sq_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceRepeatProtocol<'p>,
+@@ -442,14 +429,12 @@ where
+     }
+ }
+ 
+-trait PySequenceInplaceConcatProtocolImpl {
++pub trait PySequenceInplaceConcatProtocolImpl {
+     fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceInplaceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceConcatProtocol<'p>,
+@@ -464,14 +449,12 @@ where
+     }
+ }
+ 
+-trait PySequenceInplaceRepeatProtocolImpl {
++pub trait PySequenceInplaceRepeatProtocolImpl {
+     fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceInplaceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceRepeatProtocol<'p>,
+diff --git a/src/conversion.rs b/src/conversion.rs
+index a3bca1175..76094694d 100644
+--- a/src/conversion.rs
++++ b/src/conversion.rs
+@@ -110,6 +110,7 @@ pub trait ToBorrowedObject: ToPyObject {
+ 
+ impl<T> ToBorrowedObject for T where T: ToPyObject {}
+ 
++/*MJDFIXME
+ impl<T> ToBorrowedObject for T
+ where
+     T: ToPyObject + AsPyPointer,
+@@ -120,7 +121,7 @@ where
+     {
+         f(self.as_ptr())
+     }
+-}
++}*/
+ 
+ /// Similar to [std::convert::From], just that it requires a gil token.
+ pub trait FromPy<T>: Sized {
+@@ -139,7 +140,7 @@ impl<T, U> IntoPy<U> for T
+ where
+     U: FromPy<T>,
+ {
+-    default fn into_py(self, py: Python) -> U {
++    fn into_py(self, py: Python) -> U {
+         U::from_py(self, py)
+     }
+ }
+@@ -243,7 +244,7 @@ where
+     T: PyTryFrom<'a>,
+ {
+     #[inline]
+-    default fn extract(ob: &'a PyAny) -> PyResult<&'a T> {
++    fn extract(ob: &'a PyAny) -> PyResult<&'a T> {
+         Ok(T::try_from(ob)?)
+     }
+ }
+@@ -254,7 +255,7 @@ where
+     T: PyTryFrom<'a>,
+ {
+     #[inline]
+-    default fn extract(ob: &'a PyAny) -> PyResult<&'a mut T> {
++    fn extract(ob: &'a PyAny) -> PyResult<&'a mut T> {
+         Ok(T::try_from_mut(ob)?)
+     }
+ }
+diff --git a/src/instance.rs b/src/instance.rs
+index 68bd45ec3..ccbd07c57 100644
+--- a/src/instance.rs
++++ b/src/instance.rs
+@@ -358,7 +358,7 @@ impl<T> Py<T> {
+ }
+ 
+ /// Specialization workaround
+-trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
++pub trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
+     fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe {
+             let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
+@@ -373,8 +373,6 @@ trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
+     }
+ }
+ 
+-impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {}
+-
+ impl<T: PyTypeInfo + PyNativeType> AsPyRefDispatch<T> for Py<T> {
+     fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe { &*(self as *const instance::Py<T> as *const T) }
+@@ -387,6 +385,7 @@ impl<T: PyTypeInfo + PyNativeType> AsPyRefDispatch<T> for Py<T> {
+ impl<T> AsPyRef<T> for Py<T>
+ where
+     T: PyTypeInfo,
++    Py<T>: AsPyRefDispatch<T>,
+ {
+     #[inline]
+     fn as_ref(&self, py: Python) -> PyRef<T> {
+@@ -538,7 +537,7 @@ pub struct ManagedPyRef<'p, T: ToPyObject + ?Sized> {
+ 
+ /// This should eventually be replaced with a generic `IntoPy` trait impl by figuring
+ /// out the correct lifetime annotation to make the compiler happy
+-impl<'p, T: ToPyObject> ManagedPyRef<'p, T> {
++impl<'p, T: ToPyObject + ManagedPyRefDispatch> ManagedPyRef<'p, T> {
+     pub fn from_to_pyobject(py: Python<'p>, to_pyobject: &T) -> Self {
+         to_pyobject.to_managed_py_ref(py)
+     }
+@@ -577,7 +576,6 @@ pub trait ManagedPyRefDispatch: ToPyObject {
+ ///
+ /// Note that the actual implementations are part of the trait declaration to avoid
+ /// a specialization error
+-impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {}
+ 
+ /// Case 2: It's an object on the python heap, we're just storing a borrowed pointer.
+ /// The object we're getting is an owned pointer, it might have it's own drop impl.
+@@ -595,13 +593,14 @@ impl<T: ToPyObject + AsPyPointer + ?Sized> ManagedPyRefDispatch for T {
+     fn drop_impl(_: &mut ManagedPyRef<T>) {}
+ }
+ 
+-impl<'p, T: ToPyObject + ?Sized> Drop for ManagedPyRef<'p, T> {
++/* MJDFIXME
++impl<'p, T: ToPyObject + ?Sized + AsPyPointer> Drop for ManagedPyRef<'p, T> {
+     /// Uses the internal [ManagedPyRefDispatch] trait to get the right drop impl without causing
+     /// a specialization error
+     fn drop(&mut self) {
+         ManagedPyRefDispatch::drop_impl(self);
+     }
+-}
++}*/
+ 
+ #[cfg(test)]
+ mod test {
+diff --git a/src/lib.rs b/src/lib.rs
+index b5cb5402a..65fb611db 100755
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -1,5 +1,3 @@
+-#![feature(specialization)]
+-
+ //! Rust bindings to the Python interpreter.
+ //!
+ //! Look at [the guide](https://pyo3.rs/) for a detailed introduction.
+diff --git a/src/object.rs b/src/object.rs
+index 128ef8377..5d46bfc71 100644
+--- a/src/object.rs
++++ b/src/object.rs
+@@ -171,7 +171,7 @@ impl PyObject {
+     /// This is equivalent to the Python expression 'self.attr_name'.
+     pub fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject>
+     where
+-        N: ToPyObject,
++        N: ToPyObject + ToBorrowedObject,
+     {
+         attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
+             PyObject::from_owned_ptr_or_err(py, ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
+diff --git a/src/type_object.rs b/src/type_object.rs
+index 4cdd2d8db..3038afb40 100644
+--- a/src/type_object.rs
++++ b/src/type_object.rs
+@@ -2,6 +2,7 @@
+ 
+ //! Python type object information
+ 
++use crate::class::gc::PyGCProtocolImpl;
+ use crate::class::methods::PyMethodDefType;
+ use crate::err::{PyErr, PyResult};
+ use crate::instance::{Py, PyNativeType};
+@@ -249,7 +250,19 @@ pub unsafe trait PyTypeObject {
+ 
+ unsafe impl<T> PyTypeObject for T
+ where
+-    T: PyTypeInfo + PyMethodsProtocol + PyObjectAlloc,
++    T: PyTypeInfo
++        + PyMethodsProtocol
++        + PyObjectAlloc
++        + class::gc::PyGCProtocolImpl
++        + class::context::PyContextProtocolImpl
++        + class::descr::PyDescrProtocolImpl
++        + class::iter::PyIterProtocolImpl
++        + class::basic::PyObjectProtocolImpl
++        + class::number::PyNumberProtocolImpl
++        + class::mapping::PyMappingProtocolImpl
++        + class::sequence::PySequenceProtocolImpl
++        + class::pyasync::PyAsyncProtocolImpl
++        + class::buffer::PyBufferProtocolImpl,
+ {
+     fn init_type() -> NonNull<ffi::PyTypeObject> {
+         let type_object = unsafe { <Self as PyTypeInfo>::type_object() };
+@@ -297,7 +310,19 @@ impl<T> PyTypeCreate for T where T: PyObjectAlloc + PyTypeObject + Sized {}
+ #[cfg(not(Py_LIMITED_API))]
+ pub fn initialize_type<T>(py: Python, module_name: Option<&str>) -> PyResult<*mut ffi::PyTypeObject>
+ where
+-    T: PyObjectAlloc + PyTypeInfo + PyMethodsProtocol,
++    T: PyObjectAlloc
++        + PyTypeInfo
++        + PyMethodsProtocol
++        + class::gc::PyGCProtocolImpl
++        + class::context::PyContextProtocolImpl
++        + class::descr::PyDescrProtocolImpl
++        + class::iter::PyIterProtocolImpl
++        + class::basic::PyObjectProtocolImpl
++        + class::number::PyNumberProtocolImpl
++        + class::mapping::PyMappingProtocolImpl
++        + class::sequence::PySequenceProtocolImpl
++        + class::pyasync::PyAsyncProtocolImpl
++        + class::buffer::PyBufferProtocolImpl,
+ {
+     let type_object: &mut ffi::PyTypeObject = unsafe { T::type_object() };
+     let base_type_object: &mut ffi::PyTypeObject =
+@@ -438,12 +463,25 @@ fn py_class_flags<T: PyTypeInfo>(type_object: &mut ffi::PyTypeObject) {
+     }
+ }
+ 
+-fn py_class_method_defs<T: PyMethodsProtocol>() -> (
++fn py_class_method_defs<T>() -> (
+     Option<ffi::newfunc>,
+     Option<ffi::initproc>,
+     Option<ffi::PyCFunctionWithKeywords>,
+     Vec<ffi::PyMethodDef>,
+-) {
++)
++where
++    T: PyMethodsProtocol
++        + class::gc::PyGCProtocolImpl
++        + class::context::PyContextProtocolImpl
++        + class::descr::PyDescrProtocolImpl
++        + class::iter::PyIterProtocolImpl
++        + class::basic::PyObjectProtocolImpl
++        + class::number::PyNumberProtocolImpl
++        + class::mapping::PyMappingProtocolImpl
++        + class::sequence::PySequenceProtocolImpl
++        + class::pyasync::PyAsyncProtocolImpl
++        + class::buffer::PyBufferProtocolImpl,
++{
+     let mut defs = Vec::new();
+     let mut call = None;
+     let mut new = None;
+@@ -500,7 +538,9 @@ fn py_class_method_defs<T: PyMethodsProtocol>() -> (
+     (new, init, call, defs)
+ }
+ 
+-fn py_class_async_methods<T>(defs: &mut Vec<ffi::PyMethodDef>) {
++fn py_class_async_methods<T: class::pyasync::PyAsyncProtocolImpl>(
++    defs: &mut Vec<ffi::PyMethodDef>,
++) {
+     for def in <T as class::pyasync::PyAsyncProtocolImpl>::methods() {
+         defs.push(def.as_method_def());
+     }
+diff --git a/src/types/sequence.rs b/src/types/sequence.rs
+index d81ffbdd9..08d38b072 100644
+--- a/src/types/sequence.rs
++++ b/src/types/sequence.rs
+@@ -244,11 +244,12 @@ impl<'a, T> FromPyObject<'a> for Vec<T>
+ where
+     T: FromPyObject<'a>,
+ {
+-    default fn extract(obj: &'a PyAny) -> PyResult<Self> {
++    fn extract(obj: &'a PyAny) -> PyResult<Self> {
+         extract_sequence(obj)
+     }
+ }
+ 
++/* MJDFIXME
+ impl<'source, T> FromPyObject<'source> for Vec<T>
+ where
+     for<'a> T: FromPyObject<'a> + buffer::Element + Copy,
+@@ -267,7 +268,7 @@ where
+         // fall back to sequence protocol
+         extract_sequence(obj)
+     }
+-}
++}*/
+ 
+ fn extract_sequence<'s, T>(obj: &'s PyAny) -> PyResult<Vec<T>>
+ where
diff --git a/srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch b/srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
new file mode 100644
index 00000000000..8e8e4e9cff7
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
@@ -0,0 +1,69 @@
+From b0561da60c6c00fc8cd930efa34113a602a830e2 Mon Sep 17 00:00:00 2001
+From: Donlon <mdonlon@treyarch.com>
+Date: Wed, 30 Oct 2019 07:02:06 -0700
+Subject: [PATCH] Stubbed out a bunch of tests
+
+---
+ src/instance.rs                                  |  3 ++-
+ tests/test_class_basics.rs                       | 16 ++++++++++++++--
+
+diff --git a/src/instance.rs b/src/instance.rs
+index ccbd07c57..af0cd4382 100644
+--- a/src/instance.rs
++++ b/src/instance.rs
+@@ -602,6 +602,7 @@ impl<'p, T: ToPyObject + ?Sized + AsPyPointer> Drop for ManagedPyRef<'p, T> {
+     }
+ }*/
+ 
++/* MJDFIXME
+ #[cfg(test)]
+ mod test {
+     use crate::ffi;
+@@ -640,4 +641,4 @@ mod test {
+             ffi::Py_DECREF(ptr);
+         }
+     }
+-}
++}*/
+diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs
+index 00e2674e6..53e4df51e 100644
+--- a/tests/test_class_basics.rs
++++ b/tests/test_class_basics.rs
+@@ -1,3 +1,4 @@
++use pyo3::class;
+ use pyo3::prelude::*;
+ use pyo3::py_run;
+ use pyo3::type_object::initialize_type;
+@@ -7,6 +8,17 @@ mod common;
+ #[pyclass]
+ struct EmptyClass {}
+ 
++impl class::gc::PyGCProtocolImpl for EmptyClass {}
++impl class::buffer::PyBufferProtocolImpl for EmptyClass {}
++impl class::context::PyContextProtocolImpl for EmptyClass {}
++impl class::iter::PyIterProtocolImpl for EmptyClass {}
++impl class::descr::PyDescrProtocolImpl for EmptyClass {}
++impl class::basic::PyObjectProtocolImpl for EmptyClass {}
++impl class::number::PyNumberProtocolImpl for EmptyClass {}
++impl class::mapping::PyMappingProtocolImpl for EmptyClass {}
++impl class::sequence::PySequenceProtocolImpl for EmptyClass {}
++impl class::pyasync::PyAsyncProtocolImpl for EmptyClass {}
++
+ #[test]
+ fn empty_class() {
+     let gil = Python::acquire_gil();
+@@ -17,7 +29,7 @@ fn empty_class() {
+ 
+     py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
+ }
+-
++/*
+ /// Line1
+ ///Line2
+ ///  Line3
+@@ -77,4 +89,4 @@ fn empty_class_in_module() {
+     initialize_type::<EmptyClassInModule>(py, Some("test_module.nested")).unwrap();
+     let module: String = ty.getattr("__module__").unwrap().extract().unwrap();
+     assert_eq!(module, "test_module.nested");
+-}
++}*/
diff --git a/srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch b/srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch
new file mode 100644
index 00000000000..1d00862ff05
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch
@@ -0,0 +1,93 @@
+From c7e52948d9147689701a24de2fcdffafc32ebe62 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Wed, 30 Oct 2019 22:12:49 -0700
+Subject: [PATCH] pyclass protocols attribute parsing
+
+---
+ .vscode/settings.json              |  4 ++++
+ pyo3-derive-backend/src/pyclass.rs | 32 ++++++++++++++++++++++++++++++
+ tests/test_class_basics.rs         |  2 +-
+ 3 files changed, 37 insertions(+), 1 deletion(-)
+ create mode 100644 .vscode/settings.json
+
+diff --git a/.vscode/settings.json b/.vscode/settings.json
+new file mode 100644
+index 000000000..2b5f84ecc
+--- /dev/null
++++ b/.vscode/settings.json
+@@ -0,0 +1,4 @@
++{
++    "rust.all_targets": false,
++    "editor.formatOnSave": true
++}
+\ No newline at end of file
+diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs
+index 1f902a959..3ac5d4cde 100644
+--- a/pyo3-derive-backend/src/pyclass.rs
++++ b/pyo3-derive-backend/src/pyclass.rs
+@@ -16,6 +16,7 @@ pub struct PyClassArgs {
+     pub flags: Vec<syn::Expr>,
+     pub base: syn::TypePath,
+     pub module: Option<syn::LitStr>,
++    pub protocols: Vec<syn::Ident>,
+ }
+ 
+ impl Parse for PyClassArgs {
+@@ -40,6 +41,7 @@ impl Default for PyClassArgs {
+             // are no other flags
+             flags: vec![parse_quote! {0}],
+             base: parse_quote! {pyo3::types::PyAny},
++            protocols: Vec::new(),
+         }
+     }
+ }
+@@ -110,6 +112,36 @@ impl PyClassArgs {
+                     ));
+                 }
+             },
++            "protocols" => match *assign.right {
++                syn::Expr::Array(syn::ExprArray { ref elems, .. }) => {
++                    for elem in elems.iter() {
++                        match elem {
++                            syn::Expr::Path(syn::ExprPath { ref path, .. }) => {
++                                if path.segments.len() == 1 {
++                                    self.protocols.push(path.segments[0].ident.clone());
++                                } else {
++                                    return Err(syn::Error::new_spanned(
++                                        path.clone(),
++                                        "Expected an unqualified name for protocol",
++                                    ));
++                                }
++                            }
++                            _ => {
++                                return Err(syn::Error::new_spanned(
++                                    elem.clone(),
++                                    "Wrong format for protocol entry",
++                                ));
++                            }
++                        }
++                    }
++                }
++                _ => {
++                    return Err(syn::Error::new_spanned(
++                        *assign.right.clone(),
++                        "Wrong format for protocol",
++                    ));
++                }
++            },
+             _ => {
+                 return Err(syn::Error::new_spanned(
+                     *assign.left.clone(),
+diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs
+index 53e4df51e..c8e1a42df 100644
+--- a/tests/test_class_basics.rs
++++ b/tests/test_class_basics.rs
+@@ -5,7 +5,7 @@ use pyo3::type_object::initialize_type;
+ 
+ mod common;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PySequenceProtocol])]
+ struct EmptyClass {}
+ 
+ impl class::gc::PyGCProtocolImpl for EmptyClass {}
diff --git a/srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch b/srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch
new file mode 100644
index 00000000000..b7436efdee9
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch
@@ -0,0 +1,159 @@
+From 81f2c30b15f467c9f5ab139564be0099fba5b27f Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Thu, 31 Oct 2019 22:40:33 -0700
+Subject: [PATCH] Add lookup function for protocol defs
+
+---
+ pyo3-derive-backend/src/defs.rs    | 40 ++++++++++++++++++++++--------
+ pyo3-derive-backend/src/pyproto.rs | 15 +++--------
+ 2 files changed, 33 insertions(+), 22 deletions(-)
+
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index 04c1fa3b0..52024c12b 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -7,12 +7,22 @@ pub struct Proto {
+     pub py_methods: &'static [PyMethod],
+ }
+ 
++impl Proto {
++    pub fn protocol_trait(&self) -> String {
++        format!("Py{}Protocol", self.name)
++    }
++
++    pub fn _impl_trait(&self) -> String {
++        format!("Py{}ProtocolImpl", self.name)
++    }
++}
++
+ pub struct PyMethod {
+     pub name: &'static str,
+     pub proto: &'static str,
+ }
+ 
+-pub const OBJECT: Proto = Proto {
++const OBJECT: Proto = Proto {
+     name: "Object",
+     methods: &[
+         MethodProto::Binary {
+@@ -88,7 +98,7 @@ pub const OBJECT: Proto = Proto {
+     ],
+ };
+ 
+-pub const ASYNC: Proto = Proto {
++const ASYNC: Proto = Proto {
+     name: "Async",
+     methods: &[
+         MethodProto::Unary {
+@@ -131,7 +141,7 @@ pub const ASYNC: Proto = Proto {
+     ],
+ };
+ 
+-pub const BUFFER: Proto = Proto {
++const BUFFER: Proto = Proto {
+     name: "Buffer",
+     methods: &[
+         MethodProto::Unary {
+@@ -148,7 +158,7 @@ pub const BUFFER: Proto = Proto {
+     py_methods: &[],
+ };
+ 
+-pub const CONTEXT: Proto = Proto {
++const CONTEXT: Proto = Proto {
+     name: "Context",
+     methods: &[
+         MethodProto::Unary {
+@@ -176,7 +186,7 @@ pub const CONTEXT: Proto = Proto {
+     ],
+ };
+ 
+-pub const GC: Proto = Proto {
++const GC: Proto = Proto {
+     name: "GC",
+     methods: &[
+         MethodProto::Free {
+@@ -191,7 +201,7 @@ pub const GC: Proto = Proto {
+     py_methods: &[],
+ };
+ 
+-pub const DESCR: Proto = Proto {
++const DESCR: Proto = Proto {
+     name: "Descriptor",
+     methods: &[
+         MethodProto::Ternary {
+@@ -233,7 +243,7 @@ pub const DESCR: Proto = Proto {
+     ],
+ };
+ 
+-pub const ITER: Proto = Proto {
++const ITER: Proto = Proto {
+     name: "Iter",
+     py_methods: &[],
+     methods: &[
+@@ -250,7 +260,7 @@ pub const ITER: Proto = Proto {
+     ],
+ };
+ 
+-pub const MAPPING: Proto = Proto {
++const MAPPING: Proto = Proto {
+     name: "Mapping",
+     methods: &[
+         MethodProto::Unary {
+@@ -310,7 +320,7 @@ pub const MAPPING: Proto = Proto {
+     ],
+ };
+ 
+-pub const SEQ: Proto = Proto {
++const SEQ: Proto = Proto {
+     name: "Sequence",
+     methods: &[
+         MethodProto::Unary {
+@@ -371,7 +381,7 @@ pub const SEQ: Proto = Proto {
+     py_methods: &[],
+ };
+ 
+-pub const NUM: Proto = Proto {
++const NUM: Proto = Proto {
+     name: "Number",
+     methods: &[
+         MethodProto::BinaryS {
+@@ -750,3 +760,13 @@ pub const NUM: Proto = Proto {
+         },
+     ],
+ };
++
++const PROTOCOLS: &[Proto] = &[
++    OBJECT, ASYNC, MAPPING, ITER, CONTEXT, SEQ, NUM, DESCR, BUFFER, GC,
++];
++
++pub fn find_protocol(protocol_trait: &str) -> Option<&'static Proto> {
++    PROTOCOLS
++        .iter()
++        .find(|p| p.protocol_trait() == protocol_trait)
++}
+diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs
+index c0921bcbb..41f1deaf9 100644
+--- a/pyo3-derive-backend/src/pyproto.rs
++++ b/pyo3-derive-backend/src/pyproto.rs
+@@ -12,18 +12,9 @@ use quote::ToTokens;
+ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> syn::Result<TokenStream> {
+     if let Some((_, ref mut path, _)) = ast.trait_ {
+         let proto = if let Some(ref mut segment) = path.segments.last() {
+-            match segment.ident.to_string().as_str() {
+-                "PyObjectProtocol" => &defs::OBJECT,
+-                "PyAsyncProtocol" => &defs::ASYNC,
+-                "PyMappingProtocol" => &defs::MAPPING,
+-                "PyIterProtocol" => &defs::ITER,
+-                "PyContextProtocol" => &defs::CONTEXT,
+-                "PySequenceProtocol" => &defs::SEQ,
+-                "PyNumberProtocol" => &defs::NUM,
+-                "PyDescrProtocol" => &defs::DESCR,
+-                "PyBufferProtocol" => &defs::BUFFER,
+-                "PyGCProtocol" => &defs::GC,
+-                _ => {
++            match defs::find_protocol(segment.ident.to_string().as_str()) {
++                Some(p) => p,
++                None => {
+                     return Err(syn::Error::new_spanned(
+                         path,
+                         "#[pyproto] can not be used with this block",
diff --git a/srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch b/srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch
new file mode 100644
index 00000000000..615bd92790b
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch
@@ -0,0 +1,1387 @@
+From eb617c2ad89dad6be5cf454fe0012d9aba9e60b2 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Sun, 3 Nov 2019 18:06:54 -0800
+Subject: [PATCH] Proc macros now add the necessary default implementations
+
+---
+ .vscode/settings.json                         |   3 +-
+ pyo3-derive-backend/src/defs.rs               | 137 ++++++++++++++++--
+ pyo3-derive-backend/src/func.rs               |  37 +++++
+ pyo3-derive-backend/src/pyclass.rs            |  34 ++++-
+ pyo3-derive-backend/src/pyproto.rs            |  91 +++++++-----
+ src/buffer.rs                                 |   5 +-
+ src/class/buffer.rs                           |   6 +
+ src/lib.rs                                    |   4 +-
+ tests/test_arithmetics.rp                     |  12 +-
+ ...er_protocol.rp => test_buffer_protocol.rs} |   2 +-
+ tests/{test_bytes.rp => test_bytes.rs}        |   0
+ tests/test_class_basics.rs                    |  17 +--
+ .../{test_class_new.rp => test_class_new.rs}  |   0
+ ...compile_error.rp => test_compile_error.rs} |   0
+ tests/test_datetime.rp                        |   2 -
+ tests/{test_gc.rp => test_gc.rs}              |   4 +-
+ ...getter_setter.rp => test_getter_setter.rs} |   0
+ tests/{test_sequence.rp => test_sequence.rs}  |   2 +-
+ tests/{test_string.rp => test_string.rs}      |   0
+ ...rguments.rp => test_variable_arguments.rs} |   0
+ tests/{test_various.rp => test_various.rs}    |   3 +-
+ 21 files changed, 280 insertions(+), 79 deletions(-)
+ rename tests/{test_buffer_protocol.rp => test_buffer_protocol.rs} (98%)
+ rename tests/{test_bytes.rp => test_bytes.rs} (100%)
+ rename tests/{test_class_new.rp => test_class_new.rs} (100%)
+ rename tests/{test_compile_error.rp => test_compile_error.rs} (100%)
+ rename tests/{test_gc.rp => test_gc.rs} (98%)
+ rename tests/{test_getter_setter.rp => test_getter_setter.rs} (100%)
+ rename tests/{test_sequence.rp => test_sequence.rs} (99%)
+ rename tests/{test_string.rp => test_string.rs} (100%)
+ rename tests/{test_variable_arguments.rp => test_variable_arguments.rs} (100%)
+ rename tests/{test_various.rp => test_various.rs} (98%)
+
+diff --git a/.vscode/settings.json b/.vscode/settings.json
+index 2b5f84ecc..38768fd72 100644
+--- a/.vscode/settings.json
++++ b/.vscode/settings.json
+@@ -1,4 +1,5 @@
+ {
+     "rust.all_targets": false,
+-    "editor.formatOnSave": true
++    "editor.formatOnSave": true,
++    "rust-analyzer.enableEnhancedTyping": false
+ }
+\ No newline at end of file
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index 52024c12b..06c1c6754 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -3,20 +3,12 @@ use crate::func::MethodProto;
+ 
+ pub struct Proto {
+     pub name: &'static str,
++    pub protocol_trait: &'static str,
++    pub impl_trait: &'static str,
+     pub methods: &'static [MethodProto],
+     pub py_methods: &'static [PyMethod],
+ }
+ 
+-impl Proto {
+-    pub fn protocol_trait(&self) -> String {
+-        format!("Py{}Protocol", self.name)
+-    }
+-
+-    pub fn _impl_trait(&self) -> String {
+-        format!("Py{}ProtocolImpl", self.name)
+-    }
+-}
+-
+ pub struct PyMethod {
+     pub name: &'static str,
+     pub proto: &'static str,
+@@ -24,12 +16,15 @@ pub struct PyMethod {
+ 
+ const OBJECT: Proto = Proto {
+     name: "Object",
++    protocol_trait: "pyo3::class::basic::PyObjectProtocol",
++    impl_trait: "pyo3::class::basic::PyObjectProtocolImpl",
+     methods: &[
+         MethodProto::Binary {
+             name: "__getattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
++            default: "pyo3::class::basic::PyObjectGetAttrProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__setattr__",
+@@ -37,49 +32,58 @@ const OBJECT: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
++            default: "pyo3::class::basic::PyObjectSetAttrProtocol",
+         },
+         MethodProto::Binary {
+             name: "__delattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
++            default: "pyo3::class::basic::PyObjectDelAttrProtocol",
+         },
+         MethodProto::Unary {
+             name: "__str__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectStrProtocol",
++            default: "pyo3::class::basic::PyObjectStrProtocol",
+         },
+         MethodProto::Unary {
+             name: "__repr__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectReprProtocol",
++            default: "pyo3::class::basic::PyObjectReprProtocol",
+         },
+         MethodProto::Binary {
+             name: "__format__",
+             arg: "Format",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectFormatProtocol",
++            default: "pyo3::class::basic::PyObjectFormatProtocol",
+         },
+         MethodProto::Unary {
+             name: "__hash__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectHashProtocol",
++            default: "pyo3::class::basic::PyObjectHashProtocol",
+         },
+         MethodProto::Unary {
+             name: "__bytes__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectBytesProtocol",
++            default: "pyo3::class::basic::PyObjectBytesProtocol",
+         },
+         MethodProto::Unary {
+             name: "__bool__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectBoolProtocol",
++            default: "pyo3::class::basic::PyObjectBoolProtocol",
+         },
+         MethodProto::Binary {
+             name: "__richcmp__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
++            default: "pyo3::class::basic::PyObjectRichcmpProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -100,26 +104,32 @@ const OBJECT: Proto = Proto {
+ 
+ const ASYNC: Proto = Proto {
+     name: "Async",
++    protocol_trait: "pyo3::class::pyasync::PyAsyncProtocol",
++    impl_trait: "pyo3::class::pyasync::PyAsyncProtocolImpl",
+     methods: &[
+         MethodProto::Unary {
+             name: "__await__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aiter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAiterProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAiterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__anext__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAnextProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAnextProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aenter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAenterProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAenterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__aexit__",
+@@ -127,6 +137,7 @@ const ASYNC: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::pyasync::PyAsyncAexitProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAexitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -143,16 +154,20 @@ const ASYNC: Proto = Proto {
+ 
+ const BUFFER: Proto = Proto {
+     name: "Buffer",
++    protocol_trait: "pyo3::class::buffer::PyBufferProtocol",
++    impl_trait: "pyo3::class::buffer::PyBufferProtocolImpl",
+     methods: &[
+         MethodProto::Unary {
+             name: "bf_getbuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferGetBufferProtocol",
++            default: "pyo3::class::buffer::PyBufferGetBufferProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "bf_releasebuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferReleaseBufferProtocol",
++            default: "pyo3::class::buffer::PyBufferReleaseBufferProtocolImpl",
+         },
+     ],
+     py_methods: &[],
+@@ -160,11 +175,14 @@ const BUFFER: Proto = Proto {
+ 
+ const CONTEXT: Proto = Proto {
+     name: "Context",
++    protocol_trait: "pyo3::class::context::PyContextProtocol",
++    impl_trait: "pyo3::class::context::PyContextProtocolImpl",
+     methods: &[
+         MethodProto::Unary {
+             name: "__enter__",
+             pyres: true,
+             proto: "pyo3::class::context::PyContextEnterProtocol",
++            default: "pyo3::class::context::PyContextEnterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__exit__",
+@@ -172,6 +190,7 @@ const CONTEXT: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::context::PyContextExitProtocol",
++            default: "pyo3::class::context::PyContextExitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -188,14 +207,19 @@ const CONTEXT: Proto = Proto {
+ 
+ const GC: Proto = Proto {
+     name: "GC",
++    protocol_trait: "pyo3::class::gc::PyGCProtocol",
++    impl_trait: "pyo3::class::gc::PyGCProtocolImpl",
++
+     methods: &[
+         MethodProto::Free {
+             name: "__traverse__",
+             proto: "pyo3::class::gc::PyGCTraverseProtocol",
++            default: "pyo3::class::gc::PyGCTraverseProtocolImpl",
+         },
+         MethodProto::Free {
+             name: "__clear__",
+             proto: "pyo3::class::gc::PyGCClearProtocol",
++            default: "pyo3::class::gc::PyGCClearProtocolImpl",
+         },
+     ],
+     py_methods: &[],
+@@ -203,6 +227,9 @@ const GC: Proto = Proto {
+ 
+ const DESCR: Proto = Proto {
+     name: "Descriptor",
++    protocol_trait: "pyo3::class::descr::PyDescrProtocol",
++    impl_trait: "pyo3::class::descr::PyDescrProtocolImpl",
++
+     methods: &[
+         MethodProto::Ternary {
+             name: "__get__",
+@@ -210,6 +237,7 @@ const DESCR: Proto = Proto {
+             arg2: "Owner",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrGetProtocol",
++            default: "pyo3::class::descr::PyDescrGetProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__set__",
+@@ -217,18 +245,21 @@ const DESCR: Proto = Proto {
+             arg2: "Value",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrSetProtocol",
++            default: "pyo3::class::descr::PyDescrSetProtocol",
+         },
+         MethodProto::Binary {
+             name: "__det__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrDelProtocol",
++            default: "pyo3::class::descr::PyDescrDelProtocol",
+         },
+         MethodProto::Binary {
+             name: "__set_name__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrSetNameProtocol",
++            default: "pyo3::class::descr::PyDescrSetNameProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -245,34 +276,44 @@ const DESCR: Proto = Proto {
+ 
+ const ITER: Proto = Proto {
+     name: "Iter",
++    protocol_trait: "pyo3::class::iter::PyIterProtocol",
++    impl_trait: "pyo3::class::iter::PyIterProtocolImpl",
++
+     py_methods: &[],
+     methods: &[
+         MethodProto::Unary {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterIterProtocol",
++            default: "pyo3::class::iter::PyIterIterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__next__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterNextProtocol",
++            default: "pyo3::class::iter::PyIterNextProtocol",
+         },
+     ],
+ };
+ 
+ const MAPPING: Proto = Proto {
+     name: "Mapping",
++    protocol_trait: "pyo3::class::mapping::PyMappingProtocol",
++    impl_trait: "pyo3::class::mapping::PyMappingProtocolImpl",
++
+     methods: &[
+         MethodProto::Unary {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingLenProtocol",
++            default: "pyo3::class::mapping::PyMappingLenProtocol",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Key",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingGetItemProtocol",
++            default: "pyo3::class::mapping::PyMappingGetItemProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -280,28 +321,33 @@ const MAPPING: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingSetItemProtocol",
++            default: "pyo3::class::mapping::PyMappingSetItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Key",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingDelItemProtocol",
++            default: "pyo3::class::mapping::PyMappingDelItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingContainsProtocol",
++            default: "pyo3::class::mapping::PyMappingContainsProtocol",
+         },
+         MethodProto::Unary {
+             name: "__reversed__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingReversedProtocol",
++            default: "pyo3::class::mapping::PyMappingReversedProtocol",
+         },
+         MethodProto::Unary {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingIterProtocol",
++            default: "pyo3::class::mapping::PyMappingIterProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -322,17 +368,22 @@ const MAPPING: Proto = Proto {
+ 
+ const SEQ: Proto = Proto {
+     name: "Sequence",
++    protocol_trait: "pyo3::class::sequence::PySequenceProtocol",
++    impl_trait: "pyo3::class::sequence::PySequenceProtocolImpl",
++
+     methods: &[
+         MethodProto::Unary {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceLenProtocol",
++            default: "pyo3::class::sequence::PySequenceLenProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceGetItemProtocol",
++            default: "pyo3::class::sequence::PySequenceGetItemProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -340,42 +391,49 @@ const SEQ: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceSetItemProtocol",
++            default: "pyo3::class::sequence::PySequenceSetItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Index",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceDelItemProtocol",
++            default: "pyo3::class::sequence::PySequenceDelItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Item",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceContainsProtocol",
++            default: "pyo3::class::sequence::PySequenceContainsProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceConcatProtocol",
++            default: "pyo3::class::sequence::PySequenceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceRepeatProtocol",
++            default: "pyo3::class::sequence::PySequenceRepeatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceConcatProtocol",
++            default: "pyo3::class::sequence::PySequenceInplaceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceRepeatProtocol",
++            default: "pyo3::class::sequence::PySequenceInplaceRepeatProtocolImpl",
+         },
+     ],
+     py_methods: &[],
+@@ -383,6 +441,9 @@ const SEQ: Proto = Proto {
+ 
+ const NUM: Proto = Proto {
+     name: "Number",
++    protocol_trait: "pyo3::class::number::PyNumberProtocol",
++    impl_trait: "pyo3::class::number::PyNumberProtocolImpl",
++
+     methods: &[
+         MethodProto::BinaryS {
+             name: "__add__",
+@@ -390,6 +451,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAddProtocol",
++            default: "pyo3::class::number::PyNumberAddProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__sub__",
+@@ -397,6 +459,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberSubProtocol",
++            default: "pyo3::class::number::PyNumberSubProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__mul__",
+@@ -404,6 +467,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMulProtocol",
++            default: "pyo3::class::number::PyNumberMulProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__matmul__",
+@@ -411,6 +475,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMatmulProtocol",
++            default: "pyo3::class::number::PyNumberMatmulProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__truediv__",
+@@ -418,6 +483,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberTruedivProtocol",
++            default: "pyo3::class::number::PyNumberTruedivProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__floordiv__",
+@@ -425,6 +491,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloordivProtocol",
++            default: "pyo3::class::number::PyNumberFloordivProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__mod__",
+@@ -432,6 +499,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberModProtocol",
++            default: "pyo3::class::number::PyNumberModProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__divmod__",
+@@ -439,6 +507,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberDivmodProtocol",
++            default: "pyo3::class::number::PyNumberDivmodProtocol",
+         },
+         MethodProto::TernaryS {
+             name: "__pow__",
+@@ -447,6 +516,7 @@ const NUM: Proto = Proto {
+             arg3: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPowProtocol",
++            default: "pyo3::class::number::PyNumberPowProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__lshift__",
+@@ -454,6 +524,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberLShiftProtocol",
++            default: "pyo3::class::number::PyNumberLShiftProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__rshift__",
+@@ -461,6 +532,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRShiftProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__and__",
+@@ -468,6 +540,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAndProtocol",
++            default: "pyo3::class::number::PyNumberAndProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__xor__",
+@@ -475,6 +548,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberXorProtocol",
++            default: "pyo3::class::number::PyNumberXorProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__or__",
+@@ -482,54 +556,63 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberOrProtocol",
++            default: "pyo3::class::number::PyNumberOrProtocol",
+         },
+         MethodProto::Binary {
+             name: "__radd__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAddProtocol",
++            default: "pyo3::class::number::PyNumberRAddProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rsub__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRSubProtocol",
++            default: "pyo3::class::number::PyNumberRSubProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMulProtocol",
++            default: "pyo3::class::number::PyNumberRMulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rmatmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMatmulProtocol",
++            default: "pyo3::class::number::PyNumberRMatmulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rtruediv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRTruedivProtocol",
++            default: "pyo3::class::number::PyNumberRTruedivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rfloordiv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRFloordivProtocol",
++            default: "pyo3::class::number::PyNumberRFloordivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRModProtocol",
++            default: "pyo3::class::number::PyNumberRModProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rdivmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRDivmodProtocol",
++            default: "pyo3::class::number::PyNumberRDivmodProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__rpow__",
+@@ -537,78 +620,91 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRPowProtocol",
++            default: "pyo3::class::number::PyNumberRPowProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rlshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRLShiftProtocol",
++            default: "pyo3::class::number::PyNumberRLShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rrshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRRShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rand__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAndProtocol",
++            default: "pyo3::class::number::PyNumberRAndProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rxor__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRXorProtocol",
++            default: "pyo3::class::number::PyNumberRXorProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ror__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberROrProtocol",
++            default: "pyo3::class::number::PyNumberROrProtocol",
+         },
+         MethodProto::Binary {
+             name: "__iadd__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAddProtocol",
++            default: "pyo3::class::number::PyNumberIAddProtocol",
+         },
+         MethodProto::Binary {
+             name: "__isub__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberISubProtocol",
++            default: "pyo3::class::number::PyNumberISubProtocol",
+         },
+         MethodProto::Binary {
+             name: "__imul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMulProtocol",
++            default: "pyo3::class::number::PyNumberIMulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__imatmul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMatmulProtocol",
++            default: "pyo3::class::number::PyNumberIMatmulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__itruediv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberITruedivProtocol",
++            default: "pyo3::class::number::PyNumberITruedivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ifloordiv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIFloordivProtocol",
++            default: "pyo3::class::number::PyNumberIFloordivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__imod__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIModProtocol",
++            default: "pyo3::class::number::PyNumberIModProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__ipow__",
+@@ -616,81 +712,96 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIPowProtocol",
++            default: "pyo3::class::number::PyNumberIPowProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ilshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberILShiftProtocol",
++            default: "pyo3::class::number::PyNumberILShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__irshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIRShiftProtocol",
++            default: "pyo3::class::number::PyNumberIRShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__iand__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAndProtocol",
++            default: "pyo3::class::number::PyNumberIAndProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ixor__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIXorProtocol",
++            default: "pyo3::class::number::PyNumberIXorProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ior__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIOrProtocol",
++            default: "pyo3::class::number::PyNumberIOrProtocol",
+         },
+         MethodProto::Unary {
+             name: "__neg__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberNegProtocol",
++            default: "pyo3::class::number::PyNumberNegProtocol",
+         },
+         MethodProto::Unary {
+             name: "__pos__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPosProtocol",
++            default: "pyo3::class::number::PyNumberPosProtocol",
+         },
+         MethodProto::Unary {
+             name: "__abs__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAbsProtocol",
++            default: "pyo3::class::number::PyNumberAbsProtocol",
+         },
+         MethodProto::Unary {
+             name: "__invert__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberInvertProtocol",
++            default: "pyo3::class::number::PyNumberInvertProtocol",
+         },
+         MethodProto::Unary {
+             name: "__complex__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberComplexProtocol",
++            default: "pyo3::class::number::PyNumberComplexProtocol",
+         },
+         MethodProto::Unary {
+             name: "__int__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIntProtocol",
++            default: "pyo3::class::number::PyNumberIntProtocol",
+         },
+         MethodProto::Unary {
+             name: "__float__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloatProtocol",
++            default: "pyo3::class::number::PyNumberFloatProtocol",
+         },
+         MethodProto::Unary {
+             name: "__round__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRoundProtocol",
++            default: "pyo3::class::number::PyNumberRoundProtocol",
+         },
+         MethodProto::Unary {
+             name: "__index__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIndexProtocol",
++            default: "pyo3::class::number::PyNumberIndexProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -765,8 +876,12 @@ const PROTOCOLS: &[Proto] = &[
+     OBJECT, ASYNC, MAPPING, ITER, CONTEXT, SEQ, NUM, DESCR, BUFFER, GC,
+ ];
+ 
++pub fn all_protocols() -> &'static [Proto] {
++    PROTOCOLS
++}
++
+ pub fn find_protocol(protocol_trait: &str) -> Option<&'static Proto> {
+     PROTOCOLS
+         .iter()
+-        .find(|p| p.protocol_trait() == protocol_trait)
++        .find(|p| p.protocol_trait.ends_with(protocol_trait))
+ }
+diff --git a/pyo3-derive-backend/src/func.rs b/pyo3-derive-backend/src/func.rs
+index 2b7f69aca..ce06716f4 100644
+--- a/pyo3-derive-backend/src/func.rs
++++ b/pyo3-derive-backend/src/func.rs
+@@ -12,17 +12,20 @@ pub enum MethodProto {
+     Free {
+         name: &'static str,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Unary {
+         name: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Binary {
+         name: &'static str,
+         arg: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     BinaryS {
+         name: &'static str,
+@@ -30,6 +33,7 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Ternary {
+         name: &'static str,
+@@ -37,6 +41,7 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     TernaryS {
+         name: &'static str,
+@@ -45,6 +50,7 @@ pub enum MethodProto {
+         arg3: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Quaternary {
+         name: &'static str,
+@@ -52,6 +58,7 @@ pub enum MethodProto {
+         arg2: &'static str,
+         arg3: &'static str,
+         proto: &'static str,
++        default: &'static str,
+     },
+ }
+ 
+@@ -69,6 +76,31 @@ impl PartialEq<str> for MethodProto {
+     }
+ }
+ 
++impl MethodProto {
++    pub fn get_proto(&self) -> &'static str {
++        match *self {
++            MethodProto::Free { proto: p, .. } => p,
++            MethodProto::Unary { proto: p, .. } => p,
++            MethodProto::Binary { proto: p, .. } => p,
++            MethodProto::BinaryS { proto: p, .. } => p,
++            MethodProto::Ternary { proto: p, .. } => p,
++            MethodProto::TernaryS { proto: p, .. } => p,
++            MethodProto::Quaternary { proto: p, .. } => p,
++        }
++    }
++    pub fn get_default(&self) -> &'static str {
++        match *self {
++            MethodProto::Free { default: d, .. } => d,
++            MethodProto::Unary { default: d, .. } => d,
++            MethodProto::Binary { default: d, .. } => d,
++            MethodProto::BinaryS { default: d, .. } => d,
++            MethodProto::Ternary { default: d, .. } => d,
++            MethodProto::TernaryS { default: d, .. } => d,
++            MethodProto::Quaternary { default: d, .. } => d,
++        }
++    }
++}
++
+ pub fn impl_method_proto(
+     cls: &syn::Type,
+     sig: &mut syn::Signature,
+@@ -119,6 +151,7 @@ pub fn impl_method_proto(
+             arg,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 println!("Not enough arguments for {}", name);
+@@ -164,6 +197,7 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -213,6 +247,7 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -266,6 +301,7 @@ pub fn impl_method_proto(
+             arg3,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -322,6 +358,7 @@ pub fn impl_method_proto(
+             arg2,
+             arg3,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 3 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs
+index 3ac5d4cde..59a0ab29f 100644
+--- a/pyo3-derive-backend/src/pyclass.rs
++++ b/pyo3-derive-backend/src/pyclass.rs
+@@ -1,10 +1,10 @@
+ // Copyright (c) 2017-present PyO3 Project and Contributors
+-
++use crate::defs;
+ use crate::method::{FnArg, FnSpec, FnType};
+ use crate::pymethod::{impl_py_getter_def, impl_py_setter_def, impl_wrap_getter, impl_wrap_setter};
+ use crate::utils;
+ use proc_macro2::{Span, TokenStream};
+-use quote::quote;
++use quote::{format_ident, quote};
+ use syn::parse::{Parse, ParseStream};
+ use syn::punctuated::Punctuated;
+ use syn::{parse_quote, Expr, Token};
+@@ -326,6 +326,14 @@ fn impl_class(
+         extra
+     };
+ 
++    let extra = {
++        let default_impls = impl_default_protocols(&cls, &attr);
++        quote! {
++            #default_impls
++            #extra
++        }
++    };
++
+     // insert space for weak ref
+     let mut has_weakref = false;
+     let mut has_dict = false;
+@@ -414,6 +422,9 @@ fn impl_class(
+             }
+         }
+ 
++        //impl<T: pyo3::type_object::PyTypeInfo> pyo3::AsPyRefDispatch<T> for #cls {}
++        //impl pyo3::ManagedPyRefDispatch for #cls {}
++
+         #inventory_impl
+ 
+         #extra
+@@ -531,3 +542,22 @@ fn check_generics(class: &mut syn::ItemStruct) -> syn::Result<()> {
+         ))
+     }
+ }
++
++fn impl_default_protocols(cls: &syn::Ident, attr: &PyClassArgs) -> TokenStream {
++    let impls: Vec<TokenStream> = defs::all_protocols()
++        .iter()
++        .filter_map(|proto| {
++            if attr
++                .protocols
++                .iter()
++                .any(|x| proto.protocol_trait.ends_with(&x.to_string()))
++            {
++                None
++            } else {
++                let impl_trait: syn::Path = syn::parse_str(proto.impl_trait).unwrap();
++                Some(quote! { impl #impl_trait for #cls {} })
++            }
++        })
++        .collect();
++    quote! { #(#impls)* }
++}
+diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs
+index 41f1deaf9..a73232e1f 100644
+--- a/pyo3-derive-backend/src/pyproto.rs
++++ b/pyo3-derive-backend/src/pyproto.rs
+@@ -1,7 +1,7 @@
+ // Copyright (c) 2017-present PyO3 Project and Contributors
+ 
+ use crate::defs;
+-use crate::func::impl_method_proto;
++use crate::func::{impl_method_proto, MethodProto};
+ use crate::method::FnSpec;
+ use crate::pymethod;
+ use proc_macro2::Span;
+@@ -53,49 +53,70 @@ fn impl_proto_impl(
+     let mut tokens = TokenStream::new();
+     let mut py_methods = Vec::new();
+ 
++    let mut unimpl_methods: Vec<&MethodProto> = proto.methods.iter().collect();
++    let mut unimpl_py_methods: Vec<&defs::PyMethod> = proto.py_methods.iter().collect();
++
+     for iimpl in impls.iter_mut() {
+         if let syn::ImplItem::Method(ref mut met) = iimpl {
+-            for m in proto.methods {
+-                if m == met.sig.ident.to_string().as_str() {
+-                    impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
+-                }
+-            }
+-            for m in proto.py_methods {
+-                let ident = met.sig.ident.clone();
+-                if m.name == ident.to_string().as_str() {
+-                    let name = syn::Ident::new(m.name, Span::call_site());
+-                    let proto: syn::Path = syn::parse_str(m.proto).unwrap();
+-
+-                    let fn_spec = match FnSpec::parse(&ident, &met.sig, &mut met.attrs) {
+-                        Ok(fn_spec) => fn_spec,
+-                        Err(err) => return err.to_compile_error(),
+-                    };
+-                    let meth = pymethod::impl_proto_wrap(ty, &ident, &fn_spec);
+-
+-                    py_methods.push(quote! {
+-                        impl #proto for #ty
+-                        {
+-                            #[inline]
+-                            fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
+-                                #meth
+-
+-                                Some(pyo3::class::PyMethodDef {
+-                                    ml_name: stringify!(#name),
+-                                    ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
+-                                    ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
+-                                    ml_doc: ""
+-                                })
+-                            }
++            let method_name = met.sig.ident.to_string();
++            // Find the method in unimpl_methods, remove it and implement it
++            unimpl_methods
++                .iter()
++                .position(|m| *m == method_name.as_str())
++                .map(|idx| {
++                    let method = unimpl_methods.swap_remove(idx);
++                    impl_method_proto(ty, &mut met.sig, method).to_tokens(&mut tokens);
++                });
++
++            // MJDFIXME - undo this change
++            let py_method_name = &met.sig.ident;
++            let method = unimpl_py_methods
++                .iter()
++                .position(|m| m.name == py_method_name.to_string().as_str())
++                .map(|idx| unimpl_py_methods.swap_remove(idx));
++
++            if let Some(m) = method {
++                let name = syn::Ident::new(m.name, Span::call_site());
++                let proto: syn::Path = syn::parse_str(m.proto).unwrap();
++
++                let fn_spec = match FnSpec::parse(&py_method_name, &met.sig, &mut met.attrs) {
++                    Ok(fn_spec) => fn_spec,
++                    Err(err) => return err.to_compile_error(),
++                };
++                let meth = pymethod::impl_proto_wrap(ty, &py_method_name, &fn_spec);
++
++                py_methods.push(quote! {
++                    impl #proto for #ty
++                    {
++                        #[inline]
++                        fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
++                            #meth
++
++                            Some(pyo3::class::PyMethodDef {
++                                ml_name: stringify!(#name),
++                                ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
++                                ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
++                                ml_doc: ""
++                            })
+                         }
+-                    });
+-                }
+-            }
++                    }
++                });
++            };
+         }
+     }
+ 
++    let default_impls: Vec<_> = unimpl_methods
++        .iter()
++        .map(|m| {
++            let proto: syn::Path = syn::parse_str(m.get_default()).unwrap();
++            quote! { impl #proto for #ty {} }
++        })
++        .collect();
+     quote! {
+         #tokens
+ 
+         #(#py_methods)*
++
++        #(#default_impls)*
+     }
+ }
+diff --git a/src/buffer.rs b/src/buffer.rs
+index 91c317f6e..cdb305ad4 100644
+--- a/src/buffer.rs
++++ b/src/buffer.rs
+@@ -710,8 +710,9 @@ mod test {
+     fn test_array_buffer() {
+         let gil = Python::acquire_gil();
+         let py = gil.python();
+-        let array = py
+-            .import("array")
++        let arr = py.import("array");
++        println!("{:?}", arr);
++        let array = arr
+             .unwrap()
+             .call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None)
+             .unwrap();
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index 32d1a25af..48ecc58ce 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -91,3 +91,9 @@ where
+         Some(wrap::<T>)
+     }
+ }
++
++pub trait PyBufferReleaseBufferProtocolImpl {
++    fn cb_bf_releasebuffer() -> Option<ffi::releasebufferproc> {
++        None
++    }
++}
+diff --git a/src/lib.rs b/src/lib.rs
+index 65fb611db..49e71ef6d 100755
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -122,7 +122,9 @@ pub use crate::conversion::{
+ };
+ pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
+ pub use crate::gil::{init_once, GILGuard, GILPool};
+-pub use crate::instance::{AsPyRef, ManagedPyRef, Py, PyNativeType, PyRef, PyRefMut};
++pub use crate::instance::{
++    AsPyRef, AsPyRefDispatch, ManagedPyRef, ManagedPyRefDispatch, Py, PyNativeType, PyRef, PyRefMut,
++};
+ pub use crate::object::PyObject;
+ pub use crate::objectprotocol::ObjectProtocol;
+ pub use crate::python::{prepare_freethreaded_python, Python};
+diff --git a/tests/test_arithmetics.rp b/tests/test_arithmetics.rp
+index 77e8b64fe..42e378b5c 100644
+--- a/tests/test_arithmetics.rp
++++ b/tests/test_arithmetics.rp
+@@ -8,7 +8,7 @@ use pyo3::types::PyAny;
+ 
+ mod common;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol])]
+ struct UnaryArithmetic {}
+ 
+ #[pyproto]
+@@ -42,7 +42,7 @@ fn unary_arithmetic() {
+     py_run!(py, c, "assert ~c == 'invert'");
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol, PyObjectProtocol])]
+ struct BinaryArithmetic {}
+ 
+ #[pyproto]
+@@ -52,7 +52,7 @@ impl PyObjectProtocol for BinaryArithmetic {
+     }
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol, PyObjectProtocol])]
+ struct InPlaceOperations {
+     value: u32,
+ }
+@@ -188,7 +188,7 @@ fn binary_arithmetic() {
+     py_run!(py, c, "assert 1 | c == '1 | BA'");
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol])]
+ struct RhsArithmetic {}
+ 
+ #[pyproto]
+@@ -210,7 +210,7 @@ fn rhs_arithmetic() {
+     // py_run!(py, c, "assert 1 + c == '1 + RA'");
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyObjectProtocol])]
+ struct RichComparisons {}
+ 
+ #[pyproto]
+@@ -231,7 +231,7 @@ impl PyObjectProtocol for RichComparisons {
+     }
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyObjectProtocol])]
+ struct RichComparisons2 {}
+ 
+ #[pyproto]
+diff --git a/tests/test_buffer_protocol.rp b/tests/test_buffer_protocol.rs
+similarity index 98%
+rename from tests/test_buffer_protocol.rp
+rename to tests/test_buffer_protocol.rs
+index 64aa4b944..ecbc6038d 100644
+--- a/tests/test_buffer_protocol.rp
++++ b/tests/test_buffer_protocol.rs
+@@ -7,7 +7,7 @@ use std::ffi::CStr;
+ use std::os::raw::{c_int, c_void};
+ use std::ptr;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyBufferProtocol])]
+ struct TestClass {
+     vec: Vec<u8>,
+ }
+diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs
+index c8e1a42df..7b3ff6bc8 100644
+--- a/tests/test_class_basics.rs
++++ b/tests/test_class_basics.rs
+@@ -5,20 +5,9 @@ use pyo3::type_object::initialize_type;
+ 
+ mod common;
+ 
+-#[pyclass(protocols=[PySequenceProtocol])]
++#[pyclass]
+ struct EmptyClass {}
+ 
+-impl class::gc::PyGCProtocolImpl for EmptyClass {}
+-impl class::buffer::PyBufferProtocolImpl for EmptyClass {}
+-impl class::context::PyContextProtocolImpl for EmptyClass {}
+-impl class::iter::PyIterProtocolImpl for EmptyClass {}
+-impl class::descr::PyDescrProtocolImpl for EmptyClass {}
+-impl class::basic::PyObjectProtocolImpl for EmptyClass {}
+-impl class::number::PyNumberProtocolImpl for EmptyClass {}
+-impl class::mapping::PyMappingProtocolImpl for EmptyClass {}
+-impl class::sequence::PySequenceProtocolImpl for EmptyClass {}
+-impl class::pyasync::PyAsyncProtocolImpl for EmptyClass {}
+-
+ #[test]
+ fn empty_class() {
+     let gil = Python::acquire_gil();
+@@ -29,7 +18,7 @@ fn empty_class() {
+ 
+     py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
+ }
+-/*
++
+ /// Line1
+ ///Line2
+ ///  Line3
+@@ -89,4 +78,4 @@ fn empty_class_in_module() {
+     initialize_type::<EmptyClassInModule>(py, Some("test_module.nested")).unwrap();
+     let module: String = ty.getattr("__module__").unwrap().extract().unwrap();
+     assert_eq!(module, "test_module.nested");
+-}*/
++}
+diff --git a/tests/test_class_new.rp b/tests/test_class_new.rs
+similarity index 100%
+rename from tests/test_class_new.rp
+rename to tests/test_class_new.rs
+diff --git a/tests/test_compile_error.rp b/tests/test_compile_error.rs
+similarity index 100%
+rename from tests/test_compile_error.rp
+rename to tests/test_compile_error.rs
+diff --git a/tests/test_datetime.rp b/tests/test_datetime.rp
+index 2819f92c4..a8de5f638 100644
+--- a/tests/test_datetime.rp
++++ b/tests/test_datetime.rp
+@@ -1,5 +1,3 @@
+-#![feature(concat_idents)]
+-
+ use pyo3::ffi::*;
+ use pyo3::prelude::*;
+ use pyo3::types::{IntoPyDict, PyAny};
+diff --git a/tests/test_gc.rp b/tests/test_gc.rs
+similarity index 98%
+rename from tests/test_gc.rp
+rename to tests/test_gc.rs
+index 26465438a..fa0c3d9cf 100644
+--- a/tests/test_gc.rp
++++ b/tests/test_gc.rs
+@@ -132,7 +132,7 @@ fn create_pointers_in_drop() {
+ }
+ 
+ #[allow(dead_code)]
+-#[pyclass]
++#[pyclass(protocols=[PyGCProtocol])]
+ struct GCIntegration {
+     self_ref: RefCell<PyObject>,
+     dropped: TestDropCall,
+@@ -177,7 +177,7 @@ fn gc_integration() {
+     assert!(drop_called.load(Ordering::Relaxed));
+ }
+ 
+-#[pyclass(gc)]
++#[pyclass(gc, protocols=[PyGCProtocol])]
+ struct GCIntegration2 {}
+ 
+ #[pyproto]
+diff --git a/tests/test_getter_setter.rp b/tests/test_getter_setter.rs
+similarity index 100%
+rename from tests/test_getter_setter.rp
+rename to tests/test_getter_setter.rs
+diff --git a/tests/test_sequence.rp b/tests/test_sequence.rs
+similarity index 99%
+rename from tests/test_sequence.rp
+rename to tests/test_sequence.rs
+index 6241f33ec..861ba6988 100644
+--- a/tests/test_sequence.rp
++++ b/tests/test_sequence.rs
+@@ -6,7 +6,7 @@ use pyo3::types::IntoPyDict;
+ use pyo3::types::PyAny;
+ use pyo3::types::PyList;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PySequenceProtocol])]
+ struct ByteSequence {
+     elements: Vec<u8>,
+ }
+diff --git a/tests/test_variable_arguments.rp b/tests/test_variable_arguments.rs
+similarity index 100%
+rename from tests/test_variable_arguments.rp
+rename to tests/test_variable_arguments.rs
+diff --git a/tests/test_various.rp b/tests/test_various.rs
+similarity index 98%
+rename from tests/test_various.rp
+rename to tests/test_various.rs
+index 655101db2..101bdabb0 100644
+--- a/tests/test_various.rp
++++ b/tests/test_various.rs
+@@ -33,7 +33,8 @@ fn mut_ref_arg() {
+     let d = [("inst1", &inst1), ("inst2", &inst2)].into_py_dict(py);
+ 
+     py.run("inst1.set_other(inst2)", None, Some(d)).unwrap();
+-    assert_eq!(inst2.as_ref(py).n, 100);
++    // MJDFIXME
++    //assert_eq!(inst2.as_ref(py).n, 100);
+ }
+ 
+ #[pyclass]
diff --git a/srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch b/srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch
new file mode 100644
index 00000000000..c9946de5852
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch
@@ -0,0 +1,38 @@
+From c27d10fcd8932c3d83fe73b07412969cc42ff686 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Sun, 3 Nov 2019 19:29:06 -0800
+Subject: [PATCH] impl AsPyRefDispatch for every pyclass
+
+---
+ pyo3-derive-backend/src/pyclass.rs | 3 +--
+ tests/test_various.rs              | 3 +--
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs
+index 59a0ab29f..ea6c0f513 100644
+--- a/pyo3-derive-backend/src/pyclass.rs
++++ b/pyo3-derive-backend/src/pyclass.rs
+@@ -422,8 +422,7 @@ fn impl_class(
+             }
+         }
+ 
+-        //impl<T: pyo3::type_object::PyTypeInfo> pyo3::AsPyRefDispatch<T> for #cls {}
+-        //impl pyo3::ManagedPyRefDispatch for #cls {}
++        impl pyo3::AsPyRefDispatch<#cls> for Py<#cls> {}
+ 
+         #inventory_impl
+ 
+diff --git a/tests/test_various.rs b/tests/test_various.rs
+index 101bdabb0..655101db2 100644
+--- a/tests/test_various.rs
++++ b/tests/test_various.rs
+@@ -33,8 +33,7 @@ fn mut_ref_arg() {
+     let d = [("inst1", &inst1), ("inst2", &inst2)].into_py_dict(py);
+ 
+     py.run("inst1.set_other(inst2)", None, Some(d)).unwrap();
+-    // MJDFIXME
+-    //assert_eq!(inst2.as_ref(py).n, 100);
++    assert_eq!(inst2.as_ref(py).n, 100);
+ }
+ 
+ #[pyclass]
diff --git a/srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch b/srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch
new file mode 100644
index 00000000000..a66cb076d41
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch
@@ -0,0 +1,732 @@
+From d6102a4b93b16ba9b7b43a1c73614efbcb6e9814 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Mon, 4 Nov 2019 21:13:08 -0800
+Subject: [PATCH] Hack and slash to get arithmetic tests working
+
+---
+ pyo3-derive-backend/src/defs.rs               | 127 +++++++++---------
+ src/class/basic.rs                            |  14 +-
+ src/class/number.rs                           |  28 ----
+ ...est_arithmetics.rp => test_arithmetics.rs} |   3 -
+ 4 files changed, 75 insertions(+), 97 deletions(-)
+ rename tests/{test_arithmetics.rp => test_arithmetics.rs} (99%)
+
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index 06c1c6754..d793c9628 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -24,7 +24,7 @@ const OBJECT: Proto = Proto {
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
+-            default: "pyo3::class::basic::PyObjectGetAttrProtocol",
++            default: "pyo3::class::basic::GetAttrProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setattr__",
+@@ -32,58 +32,65 @@ const OBJECT: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
+-            default: "pyo3::class::basic::PyObjectSetAttrProtocol",
++            default: "pyo3::class::basic::tp_setattro_impl::SetAttr",
+         },
+         MethodProto::Binary {
+             name: "__delattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
+-            default: "pyo3::class::basic::PyObjectDelAttrProtocol",
++            default: "pyo3::class::basic::tp_setattro_impl::DelAttr",
+         },
+         MethodProto::Unary {
+             name: "__str__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectStrProtocol",
+-            default: "pyo3::class::basic::PyObjectStrProtocol",
++            default: "pyo3::class::basic::StrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__repr__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectReprProtocol",
+-            default: "pyo3::class::basic::PyObjectReprProtocol",
++            default: "pyo3::class::basic::ReprProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__format__",
+             arg: "Format",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectFormatProtocol",
+-            default: "pyo3::class::basic::PyObjectFormatProtocol",
++            default: "pyo3::class::basic::FormatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__hash__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectHashProtocol",
+-            default: "pyo3::class::basic::PyObjectHashProtocol",
++            default: "pyo3::class::basic::HashProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bytes__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectBytesProtocol",
+-            default: "pyo3::class::basic::PyObjectBytesProtocol",
++            default: "pyo3::class::basic::BytesProtocolImpl",
++        },
++        MethodProto::Unary {
++            // MJDFIXME ???
++            name: "__unicode__",
++            pyres: true,
++            proto: "pyo3::class::basic::PyObjectUnicodeProtocol",
++            default: "pyo3::class::basic::UnicodeProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bool__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectBoolProtocol",
+-            default: "pyo3::class::basic::PyObjectBoolProtocol",
++            default: "pyo3::class::basic::BoolProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__richcmp__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
+-            default: "pyo3::class::basic::PyObjectRichcmpProtocol",
++            default: "pyo3::class::basic::RichcmpProtocolImpl",
+         },
+     ],
+     py_methods: &[
+@@ -451,7 +458,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAddProtocol",
+-            default: "pyo3::class::number::PyNumberAddProtocol",
++            default: "pyo3::class::number::PyNumberAddProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__sub__",
+@@ -459,7 +466,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberSubProtocol",
+-            default: "pyo3::class::number::PyNumberSubProtocol",
++            default: "pyo3::class::number::PyNumberSubProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mul__",
+@@ -467,7 +474,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMulProtocol",
+-            default: "pyo3::class::number::PyNumberMulProtocol",
++            default: "pyo3::class::number::PyNumberMulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__matmul__",
+@@ -475,7 +482,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberMatmulProtocol",
++            default: "pyo3::class::number::PyNumberMatmulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__truediv__",
+@@ -483,7 +490,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberTruedivProtocol",
++            default: "pyo3::class::number::PyNumberTruedivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__floordiv__",
+@@ -491,7 +498,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberFloordivProtocol",
++            default: "pyo3::class::number::PyNumberFloordivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mod__",
+@@ -499,7 +506,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberModProtocol",
+-            default: "pyo3::class::number::PyNumberModProtocol",
++            default: "pyo3::class::number::PyNumberModProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__divmod__",
+@@ -507,7 +514,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberDivmodProtocol",
++            default: "pyo3::class::number::PyNumberDivmodProtocolImpl",
+         },
+         MethodProto::TernaryS {
+             name: "__pow__",
+@@ -516,7 +523,7 @@ const NUM: Proto = Proto {
+             arg3: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPowProtocol",
+-            default: "pyo3::class::number::PyNumberPowProtocol",
++            default: "pyo3::class::number::PyNumberPowProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__lshift__",
+@@ -524,7 +531,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberLShiftProtocol",
++            default: "pyo3::class::number::PyNumberLShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__rshift__",
+@@ -532,7 +539,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__and__",
+@@ -540,7 +547,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAndProtocol",
+-            default: "pyo3::class::number::PyNumberAndProtocol",
++            default: "pyo3::class::number::PyNumberAndProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__xor__",
+@@ -548,7 +555,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberXorProtocol",
+-            default: "pyo3::class::number::PyNumberXorProtocol",
++            default: "pyo3::class::number::PyNumberXorProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__or__",
+@@ -556,63 +563,63 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberOrProtocol",
+-            default: "pyo3::class::number::PyNumberOrProtocol",
++            default: "pyo3::class::number::PyNumberOrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__radd__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAddProtocol",
+-            default: "pyo3::class::number::PyNumberRAddProtocol",
++            default: "pyo3::class::number::PyNumberRAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rsub__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRSubProtocol",
+-            default: "pyo3::class::number::PyNumberRSubProtocol",
++            default: "pyo3::class::number::PyNumberRSubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMulProtocol",
+-            default: "pyo3::class::number::PyNumberRMulProtocol",
++            default: "pyo3::class::number::PyNumberRMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmatmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberRMatmulProtocol",
++            default: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rtruediv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberRTruedivProtocol",
++            default: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rfloordiv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberRFloordivProtocol",
++            default: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRModProtocol",
+-            default: "pyo3::class::number::PyNumberRModProtocol",
++            default: "pyo3::class::number::PyNumberRModProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rdivmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberRDivmodProtocol",
++            default: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__rpow__",
+@@ -620,91 +627,91 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRPowProtocol",
+-            default: "pyo3::class::number::PyNumberRPowProtocol",
++            default: "pyo3::class::number::PyNumberRPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rlshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRLShiftProtocol",
++            default: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rrshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rand__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAndProtocol",
+-            default: "pyo3::class::number::PyNumberRAndProtocol",
++            default: "pyo3::class::number::PyNumberRAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rxor__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRXorProtocol",
+-            default: "pyo3::class::number::PyNumberRXorProtocol",
++            default: "pyo3::class::number::PyNumberRXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ror__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberROrProtocol",
+-            default: "pyo3::class::number::PyNumberROrProtocol",
++            default: "pyo3::class::number::PyNumberROrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iadd__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAddProtocol",
+-            default: "pyo3::class::number::PyNumberIAddProtocol",
++            default: "pyo3::class::number::PyNumberIAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__isub__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberISubProtocol",
+-            default: "pyo3::class::number::PyNumberISubProtocol",
++            default: "pyo3::class::number::PyNumberISubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMulProtocol",
+-            default: "pyo3::class::number::PyNumberIMulProtocol",
++            default: "pyo3::class::number::PyNumberIMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imatmul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberIMatmulProtocol",
++            default: "pyo3::class::number::PyNumberIMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__itruediv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberITruedivProtocol",
+-            default: "pyo3::class::number::PyNumberITruedivProtocol",
++            default: "pyo3::class::number::PyNumberITruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ifloordiv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberIFloordivProtocol",
++            default: "pyo3::class::number::PyNumberIFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imod__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIModProtocol",
+-            default: "pyo3::class::number::PyNumberIModProtocol",
++            default: "pyo3::class::number::PyNumberIModProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__ipow__",
+@@ -712,96 +719,96 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIPowProtocol",
+-            default: "pyo3::class::number::PyNumberIPowProtocol",
++            default: "pyo3::class::number::PyNumberIPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ilshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberILShiftProtocol",
+-            default: "pyo3::class::number::PyNumberILShiftProtocol",
++            default: "pyo3::class::number::PyNumberILShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__irshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberIRShiftProtocol",
++            default: "pyo3::class::number::PyNumberIRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iand__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAndProtocol",
+-            default: "pyo3::class::number::PyNumberIAndProtocol",
++            default: "pyo3::class::number::PyNumberIAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ixor__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIXorProtocol",
+-            default: "pyo3::class::number::PyNumberIXorProtocol",
++            default: "pyo3::class::number::PyNumberIXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ior__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIOrProtocol",
+-            default: "pyo3::class::number::PyNumberIOrProtocol",
++            default: "pyo3::class::number::PyNumberIOrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__neg__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberNegProtocol",
+-            default: "pyo3::class::number::PyNumberNegProtocol",
++            default: "pyo3::class::number::PyNumberNegProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__pos__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPosProtocol",
+-            default: "pyo3::class::number::PyNumberPosProtocol",
++            default: "pyo3::class::number::PyNumberPosProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__abs__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAbsProtocol",
+-            default: "pyo3::class::number::PyNumberAbsProtocol",
++            default: "pyo3::class::number::PyNumberAbsProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__invert__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberInvertProtocol",
+-            default: "pyo3::class::number::PyNumberInvertProtocol",
++            default: "pyo3::class::number::PyNumberInvertProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__complex__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberComplexProtocol",
+-            default: "pyo3::class::number::PyNumberComplexProtocol",
++            default: "pyo3::class::number::PyNumberComplexProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__int__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIntProtocol",
+-            default: "pyo3::class::number::PyNumberIntProtocol",
++            default: "pyo3::class::number::PyNumberIntProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__float__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloatProtocol",
+-            default: "pyo3::class::number::PyNumberFloatProtocol",
++            default: "pyo3::class::number::PyNumberFloatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__round__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRoundProtocol",
+-            default: "pyo3::class::number::PyNumberRoundProtocol",
++            default: "pyo3::class::number::PyNumberRoundProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__index__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIndexProtocol",
+-            default: "pyo3::class::number::PyNumberIndexProtocol",
++            default: "pyo3::class::number::PyNumberIndexProtocolImpl",
+         },
+     ],
+     py_methods: &[
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index f87a0d029..15d682886 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -166,13 +166,15 @@ pub trait PyObjectProtocolImpl {
+ impl<'p, T> PyObjectProtocolImpl for T
+ where
+     T: PyObjectProtocol<'p>
+-        + PyObjectSetAttrProtocol<'p>
+         + GetAttrProtocolImpl
+         + StrProtocolImpl
+         + ReprProtocolImpl
+         + HashProtocolImpl
+         + RichcmpProtocolImpl
+         + BoolProtocolImpl
++        + FormatProtocolImpl
++        + BytesProtocolImpl
++        + UnicodeProtocolImpl
+         + tp_setattro_impl::DelAttr
+         + tp_setattro_impl::SetAttr
+         + tp_setattro_impl::SetDelAttr,
+@@ -253,7 +255,7 @@ where
+ /// and may support deleting attributes (by implementing PyObjectDelAttrProtocol)
+ /// and we need to generate a single extern c function that supports only setting, only deleting
+ /// or both, and return None in case none of the two is supported.
+-mod tp_setattro_impl {
++pub mod tp_setattro_impl {
+     use super::*;
+ 
+     /// setattrofunc PyTypeObject.tp_setattro
+@@ -314,6 +316,9 @@ mod tp_setattro_impl {
+         }
+     }
+ 
++    impl<T> SetDelAttr for T {}
++
++    /* MJDFIXME
+     impl<T> SetDelAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -327,7 +332,7 @@ mod tp_setattro_impl {
+                 __delattr__
+             )
+         }
+-    }
++    } */
+ }
+ 
+ pub trait StrProtocolImpl {
+@@ -376,7 +381,6 @@ pub trait FormatProtocolImpl {
+         None
+     }
+ }
+-impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait BytesProtocolImpl {
+@@ -384,7 +388,6 @@ pub trait BytesProtocolImpl {
+         None
+     }
+ }
+-impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait UnicodeProtocolImpl {
+@@ -392,7 +395,6 @@ pub trait UnicodeProtocolImpl {
+         None
+     }
+ }
+-impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ pub trait HashProtocolImpl {
+     fn tp_hash() -> Option<ffi::hashfunc> {
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 796a1c7ea..faad83039 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -1273,8 +1273,6 @@ pub trait PyNumberRAddProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRSubProtocolImpl {
+     fn __rsub__() -> Option<PyMethodDef> {
+@@ -1282,8 +1280,6 @@ pub trait PyNumberRSubProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRMulProtocolImpl {
+     fn __rmul__() -> Option<PyMethodDef> {
+@@ -1291,8 +1287,6 @@ pub trait PyNumberRMulProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRMatmulProtocolImpl {
+     fn __rmatmul__() -> Option<PyMethodDef> {
+@@ -1300,8 +1294,6 @@ pub trait PyNumberRMatmulProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRTruedivProtocolImpl {
+     fn __rtruediv__() -> Option<PyMethodDef> {
+@@ -1309,8 +1301,6 @@ pub trait PyNumberRTruedivProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRFloordivProtocolImpl {
+     fn __rfloordiv__() -> Option<PyMethodDef> {
+@@ -1318,8 +1308,6 @@ pub trait PyNumberRFloordivProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRModProtocolImpl {
+     fn __rmod__() -> Option<PyMethodDef> {
+@@ -1327,8 +1315,6 @@ pub trait PyNumberRModProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRDivmodProtocolImpl {
+     fn __rdivmod__() -> Option<PyMethodDef> {
+@@ -1336,8 +1322,6 @@ pub trait PyNumberRDivmodProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRPowProtocolImpl {
+     fn __rpow__() -> Option<PyMethodDef> {
+@@ -1345,8 +1329,6 @@ pub trait PyNumberRPowProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRLShiftProtocolImpl {
+     fn __rlshift__() -> Option<PyMethodDef> {
+@@ -1354,8 +1336,6 @@ pub trait PyNumberRLShiftProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRRShiftProtocolImpl {
+     fn __rrshift__() -> Option<PyMethodDef> {
+@@ -1363,8 +1343,6 @@ pub trait PyNumberRRShiftProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRAndProtocolImpl {
+     fn __rand__() -> Option<PyMethodDef> {
+@@ -1372,8 +1350,6 @@ pub trait PyNumberRAndProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRXorProtocolImpl {
+     fn __rxor__() -> Option<PyMethodDef> {
+@@ -1381,8 +1357,6 @@ pub trait PyNumberRXorProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberROrProtocolImpl {
+     fn __ror__() -> Option<PyMethodDef> {
+@@ -1390,8 +1364,6 @@ pub trait PyNumberROrProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ pub trait PyNumberNegProtocolImpl {
+     fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+diff --git a/tests/test_arithmetics.rp b/tests/test_arithmetics.rs
+similarity index 99%
+rename from tests/test_arithmetics.rp
+rename to tests/test_arithmetics.rs
+index 42e378b5c..2fb25adf5 100644
+--- a/tests/test_arithmetics.rp
++++ b/tests/test_arithmetics.rs
+@@ -1,5 +1,3 @@
+-#![feature(specialization)]
+-
+ use pyo3::class::basic::CompareOp;
+ use pyo3::class::*;
+ use pyo3::prelude::*;
+@@ -16,7 +14,6 @@ impl PyNumberProtocol for UnaryArithmetic {
+     fn __neg__(&self) -> PyResult<&'static str> {
+         Ok("neg")
+     }
+-
+     fn __pos__(&self) -> PyResult<&'static str> {
+         Ok("pos")
+     }
diff --git a/srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch b/srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch
new file mode 100644
index 00000000000..20781e716f9
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch
@@ -0,0 +1,1321 @@
+From ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Sun, 17 Nov 2019 08:23:49 -0800
+Subject: [PATCH] But default impls into a separate array in defs rather than
+ storing them in the MethodProto
+
+---
+ pyo3-derive-backend/src/defs.rs               | 500 ++++++++++++++----
+ pyo3-derive-backend/src/func.rs               |  23 -
+ pyo3-derive-backend/src/pyproto.rs            |  17 +-
+ .../{test_dict_iter.rp => test_dict_iter.rs}  |   0
+ tests/test_dunder.rp                          |  26 +-
+ 5 files changed, 426 insertions(+), 140 deletions(-)
+ rename tests/{test_dict_iter.rp => test_dict_iter.rs} (100%)
+
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index d793c9628..f7ac2da01 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -7,6 +7,7 @@ pub struct Proto {
+     pub impl_trait: &'static str,
+     pub methods: &'static [MethodProto],
+     pub py_methods: &'static [PyMethod],
++    pub default_impls: &'static [DefaultImpl],
+ }
+ 
+ pub struct PyMethod {
+@@ -14,6 +15,11 @@ pub struct PyMethod {
+     pub proto: &'static str,
+ }
+ 
++pub struct DefaultImpl {
++    pub name: &'static str,
++    pub default: &'static str,
++}
++
+ const OBJECT: Proto = Proto {
+     name: "Object",
+     protocol_trait: "pyo3::class::basic::PyObjectProtocol",
+@@ -24,7 +30,6 @@ const OBJECT: Proto = Proto {
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
+-            default: "pyo3::class::basic::GetAttrProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setattr__",
+@@ -32,65 +37,49 @@ const OBJECT: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
+-            default: "pyo3::class::basic::tp_setattro_impl::SetAttr",
+         },
+         MethodProto::Binary {
+             name: "__delattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
+-            default: "pyo3::class::basic::tp_setattro_impl::DelAttr",
+         },
+         MethodProto::Unary {
+             name: "__str__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectStrProtocol",
+-            default: "pyo3::class::basic::StrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__repr__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectReprProtocol",
+-            default: "pyo3::class::basic::ReprProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__format__",
+             arg: "Format",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectFormatProtocol",
+-            default: "pyo3::class::basic::FormatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__hash__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectHashProtocol",
+-            default: "pyo3::class::basic::HashProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bytes__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectBytesProtocol",
+-            default: "pyo3::class::basic::BytesProtocolImpl",
+-        },
+-        MethodProto::Unary {
+-            // MJDFIXME ???
+-            name: "__unicode__",
+-            pyres: true,
+-            proto: "pyo3::class::basic::PyObjectUnicodeProtocol",
+-            default: "pyo3::class::basic::UnicodeProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bool__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectBoolProtocol",
+-            default: "pyo3::class::basic::BoolProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__richcmp__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
+-            default: "pyo3::class::basic::RichcmpProtocolImpl",
+         },
+     ],
+     py_methods: &[
+@@ -107,6 +96,52 @@ const OBJECT: Proto = Proto {
+             proto: "pyo3::class::basic::UnicodeProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__getattr__",
++            default: "pyo3::class::basic::GetAttrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__setattr__",
++            default: "pyo3::class::basic::tp_setattro_impl::SetAttr",
++        },
++        DefaultImpl {
++            name: "__delattr__",
++            default: "pyo3::class::basic::tp_setattro_impl::DelAttr",
++        },
++        DefaultImpl {
++            name: "__str__",
++            default: "pyo3::class::basic::StrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__repr__",
++            default: "pyo3::class::basic::ReprProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__format__",
++            default: "pyo3::class::basic::FormatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__hash__",
++            default: "pyo3::class::basic::HashProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__bytes__",
++            default: "pyo3::class::basic::BytesProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__unicode__",
++            default: "pyo3::class::basic::UnicodeProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__bool__",
++            default: "pyo3::class::basic::BoolProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__richcmp__",
++            default: "pyo3::class::basic::RichcmpProtocolImpl",
++        },
++    ],
+ };
+ 
+ const ASYNC: Proto = Proto {
+@@ -118,25 +153,21 @@ const ASYNC: Proto = Proto {
+             name: "__await__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aiter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAiterProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAiterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__anext__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAnextProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAnextProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aenter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAenterProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAenterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__aexit__",
+@@ -144,7 +175,6 @@ const ASYNC: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::pyasync::PyAsyncAexitProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAexitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -157,6 +187,28 @@ const ASYNC: Proto = Proto {
+             proto: "pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__await__",
++            default: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
++        },
++        DefaultImpl {
++            name: "__aiter__",
++            default: "pyo3::class::pyasync::PyAsyncAiterProtocol",
++        },
++        DefaultImpl {
++            name: "__anext__",
++            default: "pyo3::class::pyasync::PyAsyncAnextProtocol",
++        },
++        DefaultImpl {
++            name: "__aenter__",
++            default: "pyo3::class::pyasync::PyAsyncAenterProtocol",
++        },
++        DefaultImpl {
++            name: "__aexit__",
++            default: "pyo3::class::pyasync::PyAsyncAexitProtocol",
++        },
++    ],
+ };
+ 
+ const BUFFER: Proto = Proto {
+@@ -168,16 +220,24 @@ const BUFFER: Proto = Proto {
+             name: "bf_getbuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferGetBufferProtocol",
+-            default: "pyo3::class::buffer::PyBufferGetBufferProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "bf_releasebuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferReleaseBufferProtocol",
+-            default: "pyo3::class::buffer::PyBufferReleaseBufferProtocolImpl",
+         },
+     ],
+     py_methods: &[],
++    default_impls: &[
++        DefaultImpl {
++            name: "bf_getbuffer",
++            default: "pyo3::class::buffer::PyBufferGetBufferProtocolImpl",
++        },
++        DefaultImpl {
++            name: "bf_releasebuffer",
++            default: "pyo3::class::buffer::PyBufferReleaseBufferProtocolImpl",
++        },
++    ],
+ };
+ 
+ const CONTEXT: Proto = Proto {
+@@ -189,7 +249,6 @@ const CONTEXT: Proto = Proto {
+             name: "__enter__",
+             pyres: true,
+             proto: "pyo3::class::context::PyContextEnterProtocol",
+-            default: "pyo3::class::context::PyContextEnterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__exit__",
+@@ -197,7 +256,6 @@ const CONTEXT: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::context::PyContextExitProtocol",
+-            default: "pyo3::class::context::PyContextExitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -210,6 +268,16 @@ const CONTEXT: Proto = Proto {
+             proto: "pyo3::class::context::PyContextExitProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__enter__",
++            default: "pyo3::class::context::PyContextEnterProtocol",
++        },
++        DefaultImpl {
++            name: "__exit__",
++            default: "pyo3::class::context::PyContextExitProtocol",
++        },
++    ],
+ };
+ 
+ const GC: Proto = Proto {
+@@ -221,15 +289,23 @@ const GC: Proto = Proto {
+         MethodProto::Free {
+             name: "__traverse__",
+             proto: "pyo3::class::gc::PyGCTraverseProtocol",
+-            default: "pyo3::class::gc::PyGCTraverseProtocolImpl",
+         },
+         MethodProto::Free {
+             name: "__clear__",
+             proto: "pyo3::class::gc::PyGCClearProtocol",
+-            default: "pyo3::class::gc::PyGCClearProtocolImpl",
+         },
+     ],
+     py_methods: &[],
++    default_impls: &[
++        DefaultImpl {
++            name: "__traverse__",
++            default: "pyo3::class::gc::PyGCTraverseProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__clear__",
++            default: "pyo3::class::gc::PyGCClearProtocolImpl",
++        },
++    ],
+ };
+ 
+ const DESCR: Proto = Proto {
+@@ -244,7 +320,6 @@ const DESCR: Proto = Proto {
+             arg2: "Owner",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrGetProtocol",
+-            default: "pyo3::class::descr::PyDescrGetProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__set__",
+@@ -252,21 +327,18 @@ const DESCR: Proto = Proto {
+             arg2: "Value",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrSetProtocol",
+-            default: "pyo3::class::descr::PyDescrSetProtocol",
+         },
+         MethodProto::Binary {
+             name: "__det__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrDelProtocol",
+-            default: "pyo3::class::descr::PyDescrDelProtocol",
+         },
+         MethodProto::Binary {
+             name: "__set_name__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrSetNameProtocol",
+-            default: "pyo3::class::descr::PyDescrSetNameProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -279,6 +351,24 @@ const DESCR: Proto = Proto {
+             proto: "pyo3::class::context::PyDescrNameProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__get__",
++            default: "pyo3::class::descr::PyDescrGetProtocol",
++        },
++        DefaultImpl {
++            name: "__set__",
++            default: "pyo3::class::descr::PyDescrSetProtocol",
++        },
++        DefaultImpl {
++            name: "__det__",
++            default: "pyo3::class::descr::PyDescrDelProtocol",
++        },
++        DefaultImpl {
++            name: "__set_name__",
++            default: "pyo3::class::descr::PyDescrSetNameProtocol",
++        },
++    ],
+ };
+ 
+ const ITER: Proto = Proto {
+@@ -292,12 +382,20 @@ const ITER: Proto = Proto {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterIterProtocol",
+-            default: "pyo3::class::iter::PyIterIterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__next__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterNextProtocol",
++        },
++    ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__iter__",
++            default: "pyo3::class::iter::PyIterIterProtocol",
++        },
++        DefaultImpl {
++            name: "__next__",
+             default: "pyo3::class::iter::PyIterNextProtocol",
+         },
+     ],
+@@ -313,14 +411,12 @@ const MAPPING: Proto = Proto {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingLenProtocol",
+-            default: "pyo3::class::mapping::PyMappingLenProtocol",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Key",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingGetItemProtocol",
+-            default: "pyo3::class::mapping::PyMappingGetItemProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -328,33 +424,28 @@ const MAPPING: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingSetItemProtocol",
+-            default: "pyo3::class::mapping::PyMappingSetItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Key",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingDelItemProtocol",
+-            default: "pyo3::class::mapping::PyMappingDelItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingContainsProtocol",
+-            default: "pyo3::class::mapping::PyMappingContainsProtocol",
+         },
+         MethodProto::Unary {
+             name: "__reversed__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingReversedProtocol",
+-            default: "pyo3::class::mapping::PyMappingReversedProtocol",
+         },
+         MethodProto::Unary {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingIterProtocol",
+-            default: "pyo3::class::mapping::PyMappingIterProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -371,6 +462,36 @@ const MAPPING: Proto = Proto {
+             proto: "pyo3::class::mapping::PyMappingReversedProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__len__",
++            default: "pyo3::class::mapping::PyMappingLenProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__getitem__",
++            default: "pyo3::class::mapping::PyMappingGetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__setitem__",
++            default: "pyo3::class::mapping::PyMappingSetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__delitem__",
++            default: "pyo3::class::mapping::PyMappingDelItemProtocolNotImpl",
++        },
++        DefaultImpl {
++            name: "__contains__",
++            default: "pyo3::class::mapping::PyMappingContainsProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__reversed__",
++            default: "pyo3::class::mapping::PyMappingReversedProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__iter__",
++            default: "pyo3::class::mapping::PyMappingIterProtocolImpl",
++        },
++    ],
+ };
+ 
+ const SEQ: Proto = Proto {
+@@ -383,14 +504,12 @@ const SEQ: Proto = Proto {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceLenProtocol",
+-            default: "pyo3::class::sequence::PySequenceLenProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceGetItemProtocol",
+-            default: "pyo3::class::sequence::PySequenceGetItemProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -398,52 +517,83 @@ const SEQ: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceSetItemProtocol",
+-            default: "pyo3::class::sequence::PySequenceSetItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Index",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceDelItemProtocol",
+-            default: "pyo3::class::sequence::PySequenceDelItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Item",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceContainsProtocol",
+-            default: "pyo3::class::sequence::PySequenceContainsProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceConcatProtocol",
+-            default: "pyo3::class::sequence::PySequenceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceRepeatProtocol",
+-            default: "pyo3::class::sequence::PySequenceRepeatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceConcatProtocol",
+-            default: "pyo3::class::sequence::PySequenceInplaceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceRepeatProtocol",
+-            default: "pyo3::class::sequence::PySequenceInplaceRepeatProtocolImpl",
+         },
+     ],
+     py_methods: &[],
++    default_impls: &[
++        DefaultImpl {
++            name: "__len__",
++            default: "pyo3::class::sequence::PySequenceLenProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__getitem__",
++            default: "pyo3::class::sequence::PySequenceGetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__setitem__",
++            default: "pyo3::class::sequence::PySequenceSetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__delitem__",
++            default: "pyo3::class::sequence::PySequenceDelItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__contains__",
++            default: "pyo3::class::sequence::PySequenceContainsProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__concat__",
++            default: "pyo3::class::sequence::PySequenceConcatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__repeat__",
++            default: "pyo3::class::sequence::PySequenceRepeatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__inplace_concat__",
++            default: "pyo3::class::sequence::PySequenceInplaceConcatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__inplace_repeat__",
++            default: "pyo3::class::sequence::PySequenceInplaceRepeatProtocolImpl",
++        },
++    ],
+ };
+ 
+ const NUM: Proto = Proto {
+@@ -458,7 +608,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAddProtocol",
+-            default: "pyo3::class::number::PyNumberAddProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__sub__",
+@@ -466,7 +615,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberSubProtocol",
+-            default: "pyo3::class::number::PyNumberSubProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mul__",
+@@ -474,7 +622,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMulProtocol",
+-            default: "pyo3::class::number::PyNumberMulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__matmul__",
+@@ -482,7 +629,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberMatmulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__truediv__",
+@@ -490,7 +636,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberTruedivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__floordiv__",
+@@ -498,7 +643,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberFloordivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mod__",
+@@ -506,7 +650,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberModProtocol",
+-            default: "pyo3::class::number::PyNumberModProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__divmod__",
+@@ -514,7 +657,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberDivmodProtocolImpl",
+         },
+         MethodProto::TernaryS {
+             name: "__pow__",
+@@ -523,7 +665,6 @@ const NUM: Proto = Proto {
+             arg3: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPowProtocol",
+-            default: "pyo3::class::number::PyNumberPowProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__lshift__",
+@@ -531,7 +672,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberLShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__rshift__",
+@@ -539,7 +679,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__and__",
+@@ -547,7 +686,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAndProtocol",
+-            default: "pyo3::class::number::PyNumberAndProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__xor__",
+@@ -555,7 +693,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberXorProtocol",
+-            default: "pyo3::class::number::PyNumberXorProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__or__",
+@@ -563,63 +700,54 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberOrProtocol",
+-            default: "pyo3::class::number::PyNumberOrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__radd__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAddProtocol",
+-            default: "pyo3::class::number::PyNumberRAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rsub__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRSubProtocol",
+-            default: "pyo3::class::number::PyNumberRSubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMulProtocol",
+-            default: "pyo3::class::number::PyNumberRMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmatmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rtruediv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rfloordiv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRModProtocol",
+-            default: "pyo3::class::number::PyNumberRModProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rdivmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__rpow__",
+@@ -627,91 +755,78 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRPowProtocol",
+-            default: "pyo3::class::number::PyNumberRPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rlshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rrshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rand__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAndProtocol",
+-            default: "pyo3::class::number::PyNumberRAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rxor__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRXorProtocol",
+-            default: "pyo3::class::number::PyNumberRXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ror__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberROrProtocol",
+-            default: "pyo3::class::number::PyNumberROrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iadd__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAddProtocol",
+-            default: "pyo3::class::number::PyNumberIAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__isub__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberISubProtocol",
+-            default: "pyo3::class::number::PyNumberISubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMulProtocol",
+-            default: "pyo3::class::number::PyNumberIMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imatmul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberIMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__itruediv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberITruedivProtocol",
+-            default: "pyo3::class::number::PyNumberITruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ifloordiv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberIFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imod__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIModProtocol",
+-            default: "pyo3::class::number::PyNumberIModProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__ipow__",
+@@ -719,96 +834,81 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIPowProtocol",
+-            default: "pyo3::class::number::PyNumberIPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ilshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberILShiftProtocol",
+-            default: "pyo3::class::number::PyNumberILShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__irshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberIRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iand__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAndProtocol",
+-            default: "pyo3::class::number::PyNumberIAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ixor__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIXorProtocol",
+-            default: "pyo3::class::number::PyNumberIXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ior__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIOrProtocol",
+-            default: "pyo3::class::number::PyNumberIOrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__neg__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberNegProtocol",
+-            default: "pyo3::class::number::PyNumberNegProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__pos__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPosProtocol",
+-            default: "pyo3::class::number::PyNumberPosProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__abs__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAbsProtocol",
+-            default: "pyo3::class::number::PyNumberAbsProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__invert__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberInvertProtocol",
+-            default: "pyo3::class::number::PyNumberInvertProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__complex__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberComplexProtocol",
+-            default: "pyo3::class::number::PyNumberComplexProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__int__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIntProtocol",
+-            default: "pyo3::class::number::PyNumberIntProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__float__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloatProtocol",
+-            default: "pyo3::class::number::PyNumberFloatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__round__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRoundProtocol",
+-            default: "pyo3::class::number::PyNumberRoundProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__index__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIndexProtocol",
+-            default: "pyo3::class::number::PyNumberIndexProtocolImpl",
+         },
+     ],
+     py_methods: &[
+@@ -877,6 +977,208 @@ const NUM: Proto = Proto {
+             proto: "pyo3::class::number::PyNumberRoundProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__add__",
++            default: "pyo3::class::number::PyNumberAddProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__sub__",
++            default: "pyo3::class::number::PyNumberSubProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__mul__",
++            default: "pyo3::class::number::PyNumberMulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__matmul__",
++            default: "pyo3::class::number::PyNumberMatmulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__truediv__",
++            default: "pyo3::class::number::PyNumberTruedivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__floordiv__",
++            default: "pyo3::class::number::PyNumberFloordivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__mod__",
++            default: "pyo3::class::number::PyNumberModProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__divmod__",
++            default: "pyo3::class::number::PyNumberDivmodProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__pow__",
++            default: "pyo3::class::number::PyNumberPowProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__lshift__",
++            default: "pyo3::class::number::PyNumberLShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rshift__",
++            default: "pyo3::class::number::PyNumberRShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__and__",
++            default: "pyo3::class::number::PyNumberAndProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__xor__",
++            default: "pyo3::class::number::PyNumberXorProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__or__",
++            default: "pyo3::class::number::PyNumberOrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__radd__",
++            default: "pyo3::class::number::PyNumberRAddProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rsub__",
++            default: "pyo3::class::number::PyNumberRSubProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rmul__",
++            default: "pyo3::class::number::PyNumberRMulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rmatmul__",
++            default: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rtruediv__",
++            default: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rfloordiv__",
++            default: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rmod__",
++            default: "pyo3::class::number::PyNumberRModProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rdivmod__",
++            default: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rpow__",
++            default: "pyo3::class::number::PyNumberRPowProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rlshift__",
++            default: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rrshift__",
++            default: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rand__",
++            default: "pyo3::class::number::PyNumberRAndProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rxor__",
++            default: "pyo3::class::number::PyNumberRXorProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ror__",
++            default: "pyo3::class::number::PyNumberROrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__iadd__",
++            default: "pyo3::class::number::PyNumberIAddProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__isub__",
++            default: "pyo3::class::number::PyNumberISubProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__imul__",
++            default: "pyo3::class::number::PyNumberIMulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__imatmul__",
++            default: "pyo3::class::number::PyNumberIMatmulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__itruediv__",
++            default: "pyo3::class::number::PyNumberITruedivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ifloordiv__",
++            default: "pyo3::class::number::PyNumberIFloordivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__imod__",
++            default: "pyo3::class::number::PyNumberIModProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ipow__",
++            default: "pyo3::class::number::PyNumberIPowProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ilshift__",
++            default: "pyo3::class::number::PyNumberILShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__irshift__",
++            default: "pyo3::class::number::PyNumberIRShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__iand__",
++            default: "pyo3::class::number::PyNumberIAndProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ixor__",
++            default: "pyo3::class::number::PyNumberIXorProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ior__",
++            default: "pyo3::class::number::PyNumberIOrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__neg__",
++            default: "pyo3::class::number::PyNumberNegProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__pos__",
++            default: "pyo3::class::number::PyNumberPosProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__abs__",
++            default: "pyo3::class::number::PyNumberAbsProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__invert__",
++            default: "pyo3::class::number::PyNumberInvertProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__complex__",
++            default: "pyo3::class::number::PyNumberComplexProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__int__",
++            default: "pyo3::class::number::PyNumberIntProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__float__",
++            default: "pyo3::class::number::PyNumberFloatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__round__",
++            default: "pyo3::class::number::PyNumberRoundProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__index__",
++            default: "pyo3::class::number::PyNumberIndexProtocolImpl",
++        },
++    ],
+ };
+ 
+ const PROTOCOLS: &[Proto] = &[
+diff --git a/pyo3-derive-backend/src/func.rs b/pyo3-derive-backend/src/func.rs
+index ce06716f4..05aede490 100644
+--- a/pyo3-derive-backend/src/func.rs
++++ b/pyo3-derive-backend/src/func.rs
+@@ -12,20 +12,17 @@ pub enum MethodProto {
+     Free {
+         name: &'static str,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Unary {
+         name: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Binary {
+         name: &'static str,
+         arg: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     BinaryS {
+         name: &'static str,
+@@ -33,7 +30,6 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Ternary {
+         name: &'static str,
+@@ -41,7 +37,6 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     TernaryS {
+         name: &'static str,
+@@ -50,7 +45,6 @@ pub enum MethodProto {
+         arg3: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Quaternary {
+         name: &'static str,
+@@ -58,7 +52,6 @@ pub enum MethodProto {
+         arg2: &'static str,
+         arg3: &'static str,
+         proto: &'static str,
+-        default: &'static str,
+     },
+ }
+ 
+@@ -88,17 +81,6 @@ impl MethodProto {
+             MethodProto::Quaternary { proto: p, .. } => p,
+         }
+     }
+-    pub fn get_default(&self) -> &'static str {
+-        match *self {
+-            MethodProto::Free { default: d, .. } => d,
+-            MethodProto::Unary { default: d, .. } => d,
+-            MethodProto::Binary { default: d, .. } => d,
+-            MethodProto::BinaryS { default: d, .. } => d,
+-            MethodProto::Ternary { default: d, .. } => d,
+-            MethodProto::TernaryS { default: d, .. } => d,
+-            MethodProto::Quaternary { default: d, .. } => d,
+-        }
+-    }
+ }
+ 
+ pub fn impl_method_proto(
+@@ -151,7 +133,6 @@ pub fn impl_method_proto(
+             arg,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 println!("Not enough arguments for {}", name);
+@@ -197,7 +178,6 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -247,7 +227,6 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -301,7 +280,6 @@ pub fn impl_method_proto(
+             arg3,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -358,7 +336,6 @@ pub fn impl_method_proto(
+             arg2,
+             arg3,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 3 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs
+index a73232e1f..807be9052 100644
+--- a/pyo3-derive-backend/src/pyproto.rs
++++ b/pyo3-derive-backend/src/pyproto.rs
+@@ -9,6 +9,8 @@ use proc_macro2::TokenStream;
+ use quote::quote;
+ use quote::ToTokens;
+ 
++use std::collections::HashSet;
++
+ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> syn::Result<TokenStream> {
+     if let Some((_, ref mut path, _)) = ast.trait_ {
+         let proto = if let Some(ref mut segment) = path.segments.last() {
+@@ -52,6 +54,7 @@ fn impl_proto_impl(
+ ) -> TokenStream {
+     let mut tokens = TokenStream::new();
+     let mut py_methods = Vec::new();
++    let mut implemented = HashSet::new();
+ 
+     let mut unimpl_methods: Vec<&MethodProto> = proto.methods.iter().collect();
+     let mut unimpl_py_methods: Vec<&defs::PyMethod> = proto.py_methods.iter().collect();
+@@ -59,6 +62,7 @@ fn impl_proto_impl(
+     for iimpl in impls.iter_mut() {
+         if let syn::ImplItem::Method(ref mut met) = iimpl {
+             let method_name = met.sig.ident.to_string();
++            implemented.insert(method_name.clone());
+             // Find the method in unimpl_methods, remove it and implement it
+             unimpl_methods
+                 .iter()
+@@ -105,13 +109,18 @@ fn impl_proto_impl(
+         }
+     }
+ 
+-    let default_impls: Vec<_> = unimpl_methods
++    let default_impls: Vec<_> = proto
++        .default_impls
+         .iter()
+-        .map(|m| {
+-            let proto: syn::Path = syn::parse_str(m.get_default()).unwrap();
+-            quote! { impl #proto for #ty {} }
++        .filter_map(|def| match implemented.contains(def.name) {
++            true => None,
++            false => {
++                let proto: syn::Path = syn::parse_str(def.default).unwrap();
++                Some(quote! { impl #proto for #ty {} })
++            }
+         })
+         .collect();
++
+     quote! {
+         #tokens
+ 
+diff --git a/tests/test_dict_iter.rp b/tests/test_dict_iter.rs
+similarity index 100%
+rename from tests/test_dict_iter.rp
+rename to tests/test_dict_iter.rs
diff --git a/srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch b/srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch
new file mode 100644
index 00000000000..a92cfe08a5b
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch
@@ -0,0 +1,17 @@
+--- a/build.rs	2020-06-01 19:27:44.819141296 +1000
++++ b/build.rs	2020-06-01 19:29:51.770147574 +1000
+@@ -539,14 +539,6 @@
+             MIN_VERSION, actual_version
+         )
+     }
+-
+-    let actual_date = Date::read().expect("Failed to determine the rustc date");
+-    if !actual_date.at_least(MIN_DATE) {
+-        panic!(
+-            "pyo3 requires at least rustc {}, while the current rustc date is {}",
+-            MIN_DATE, actual_date
+-        )
+-    }
+ }
+ 
+ fn main() -> Result<(), String> {
diff --git a/srcpkgs/anki/patches/0001-aqt_data-fhs.patch b/srcpkgs/anki/patches/0001-aqt_data-fhs.patch
new file mode 100644
index 00000000000..ac0d29ec082
--- /dev/null
+++ b/srcpkgs/anki/patches/0001-aqt_data-fhs.patch
@@ -0,0 +1,45 @@
+From a0a9ac1aeb8b8678f1102aed81010a901ad8d9e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Johannes=20L=C3=B6thberg?= <johannes@kyriasis.com>
+Date: Sun, 29 Mar 2020 06:24:43 +0200
+Subject: [PATCH 1/4] Move aqt_data to sys.prefix/share
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+These files do _not_ belong right under sys.prefix.
+
+Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
+---
+ qt/aqt/utils.py | 2 +-
+ qt/setup.py     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git qt/aqt/utils.py qt/aqt/utils.py
+index a0e12362..4d8c8c34 100644
+--- qt/aqt/utils.py
++++ qt/aqt/utils.py
+@@ -21,7 +21,7 @@ from aqt.theme import theme_manager
+ 
+ def aqt_data_folder() -> str:
+     # wheel install?
+-    dir = os.path.join(sys.prefix, "aqt_data")
++    dir = os.path.join(sys.prefix,"share", "aqt_data")
+     if not os.path.exists(dir) or not os.listdir(dir):
+         # running in place?
+         dir = os.path.join(os.path.dirname(__file__), "..", "aqt_data")
+diff --git qt/setup.py qt/setup.py
+index 38f4e2b7..bdda3baa 100644
+--- qt/setup.py
++++ qt/setup.py
+@@ -8,7 +8,7 @@ import setuptools
+ def package_files(directory):
+     entries = []
+     for (path, directories, filenames) in os.walk(directory):
+-        entries.append((path, [os.path.join(path, f) for f in filenames]))
++        entries.append((os.path.join("share", path), [os.path.join(path, f) for f in filenames]))
+     return entries
+ 
+ 
+-- 
+2.26.2
+
diff --git a/srcpkgs/anki/patches/0002-rust-nightly-fix.patch b/srcpkgs/anki/patches/0002-rust-nightly-fix.patch
new file mode 100644
index 00000000000..3d70aa36aad
--- /dev/null
+++ b/srcpkgs/anki/patches/0002-rust-nightly-fix.patch
@@ -0,0 +1,274 @@
+From fb578a0c2dc391f37de7cb6969c40f34d0de845c Mon Sep 17 00:00:00 2001
+From: Damien Elmes <gpg@ankiweb.net>
+Date: Fri, 24 Apr 2020 13:39:14 +1000
+Subject: [PATCH] switch to owned strings in ParsedTemplate
+
+will make it easier to cache the parsed results in the future,
+and handle field renames & other transformations
+---
+ rslib/src/notetype/cardgen.rs   |  6 +-
+ rslib/src/notetype/templates.rs |  2 +-
+ rslib/src/template.rs           | 98 +++++++++++++++++----------------
+ 3 files changed, 56 insertions(+), 50 deletions(-)
+
+Backported by fossy to stable. notetype patch is not needed.
+
+diff --git rslib/src/template.rs rslib/src/template.rs
+index 4479899009..ed5fe7e916 100644
+--- rslib/src/template.rs
++++ rslib/src/template.rs
+@@ -147,26 +147,26 @@ fn legacy_tokens(mut data: &str) -> impl Iterator<Item = TemplateResult<Token>>
+ //----------------------------------------
+ 
+ #[derive(Debug, PartialEq)]
+-enum ParsedNode<'a> {
+-    Text(&'a str),
++enum ParsedNode {
++    Text(String),
+     Replacement {
+-        key: &'a str,
+-        filters: Vec<&'a str>,
++        key: String,
++        filters: Vec<String>,
+     },
+     Conditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+     NegatedConditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+ }
+ 
+ #[derive(Debug)]
+-pub struct ParsedTemplate<'a>(Vec<ParsedNode<'a>>);
++pub struct ParsedTemplate(Vec<ParsedNode>);
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Create a template from the provided text.
+     pub fn from_text(template: &str) -> TemplateResult<ParsedTemplate> {
+         let mut iter = tokens(template);
+@@ -177,26 +177,26 @@ impl ParsedTemplate<'_> {
+ fn parse_inner<'a, I: Iterator<Item = TemplateResult<Token<'a>>>>(
+     iter: &mut I,
+     open_tag: Option<&'a str>,
+-) -> TemplateResult<Vec<ParsedNode<'a>>> {
++) -> TemplateResult<Vec<ParsedNode>> {
+     let mut nodes = vec![];
+ 
+     while let Some(token) = iter.next() {
+         use Token::*;
+         nodes.push(match token? {
+-            Text(t) => ParsedNode::Text(t),
++            Text(t) => ParsedNode::Text(t.into()),
+             Replacement(t) => {
+                 let mut it = t.rsplit(':');
+                 ParsedNode::Replacement {
+-                    key: it.next().unwrap(),
+-                    filters: it.collect(),
++                    key: it.next().unwrap().into(),
++                    filters: it.map(Into::into).collect(),
+                 }
+             }
+             OpenConditional(t) => ParsedNode::Conditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             OpenNegated(t) => ParsedNode::NegatedConditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             CloseConditional(t) => {
+@@ -285,27 +285,27 @@ fn localized_template_error(i18n: &I18n, err: TemplateError) -> String {
+ // Checking if template is empty
+ //----------------------------------------
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// true if provided fields are sufficient to render the template
+     pub fn renders_with_fields(&self, nonempty_fields: &HashSet<&str>) -> bool {
+         !template_is_empty(nonempty_fields, &self.0)
+     }
+ }
+ 
+-fn template_is_empty<'a>(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode<'a>]) -> bool {
++fn template_is_empty(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode]) -> bool {
+     use ParsedNode::*;
+     for node in nodes {
+         match node {
+             // ignore normal text
+             Text(_) => (),
+             Replacement { key, .. } => {
+-                if nonempty_fields.contains(*key) {
++                if nonempty_fields.contains(key.as_str()) {
+                     // a single replacement is enough
+                     return false;
+                 }
+             }
+             Conditional { key, children } => {
+-                if !nonempty_fields.contains(*key) {
++                if !nonempty_fields.contains(key.as_str()) {
+                     continue;
+                 }
+                 if !template_is_empty(nonempty_fields, children) {
+@@ -347,7 +347,7 @@ pub(crate) struct RenderContext<'a> {
+     pub card_ord: u16,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Render the template with the provided fields.
+     ///
+     /// Replacements that use only standard filters will become part of
+@@ -373,10 +373,7 @@ fn render_into(
+             Text(text) => {
+                 append_str_to_nodes(rendered_nodes, text);
+             }
+-            Replacement {
+-                key: key @ "FrontSide",
+-                ..
+-            } => {
++            Replacement { key, .. } if key == "FrontSide" => {
+                 // defer FrontSide rendering to Python, as extra
+                 // filters may be required
+                 rendered_nodes.push(RenderedNode::Replacement {
+@@ -385,27 +382,36 @@ fn render_into(
+                     current_text: "".into(),
+                 });
+             }
+-            Replacement { key: "", filters } if !filters.is_empty() => {
++            Replacement { key, filters } if key == "" && !filters.is_empty() => {
+                 // if a filter is provided, we accept an empty field name to
+                 // mean 'pass an empty string to the filter, and it will add
+                 // its own text'
+                 rendered_nodes.push(RenderedNode::Replacement {
+                     field_name: "".to_string(),
+                     current_text: "".to_string(),
+-                    filters: filters.iter().map(|&f| f.to_string()).collect(),
++                    filters: filters.clone(),
+                 })
+             }
+             Replacement { key, filters } => {
+                 // apply built in filters if field exists
+-                let (text, remaining_filters) = match context.fields.get(key) {
+-                    Some(text) => apply_filters(text, filters, key, context),
++                let (text, remaining_filters) = match context.fields.get(key.as_str()) {
++                    Some(text) => apply_filters(
++                        text,
++                        filters
++                            .iter()
++                            .map(|s| s.as_str())
++                            .collect::<Vec<_>>()
++                            .as_slice(),
++                        key,
++                        context,
++                    ),
+                     None => {
+                         // unknown field encountered
+                         let filters_str = filters
+                             .iter()
+                             .rev()
+                             .cloned()
+-                            .chain(iter::once(""))
++                            .chain(iter::once("".into()))
+                             .collect::<Vec<_>>()
+                             .join(":");
+                         return Err(TemplateError::FieldNotFound {
+@@ -427,12 +433,12 @@ fn render_into(
+                 }
+             }
+             Conditional { key, children } => {
+-                if context.nonempty_fields.contains(key) {
++                if context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+             NegatedConditional { key, children } => {
+-                if !context.nonempty_fields.contains(key) {
++                if !context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+@@ -542,7 +548,7 @@ pub enum FieldRequirements {
+     None,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Return fields required by template.
+     ///
+     /// This is not able to represent negated expressions or combinations of
+@@ -613,11 +619,11 @@
+             vec![
+-                Text("foo "),
++                Text("foo ".into()),
+                 Replacement {
+-                    key: "bar",
++                    key: "bar".into(),
+                     filters: vec![]
+                 },
+-                Text(" "),
++                Text(" ".into()),
+                 Conditional {
+-                    key: "baz",
+-                    children: vec![Text(" quux ")]
++                    key: "baz".into(),
++                    children: vec![Text(" quux ".into())]
+                 }
+             ]
+@@ -630,7 +636,7 @@ mod test {
+         assert_eq!(
+             tmpl.0,
+             vec![NegatedConditional {
+-                key: "baz",
++                key: "baz".into(),
+                 children: vec![]
+             }]
+         );
+@@ -643,7 +649,7 @@ mod test {
+         assert_eq!(
+             PT::from_text("{{ tag }}").unwrap().0,
+             vec![Replacement {
+-                key: "tag",
++                key: "tag".into(),
+                 filters: vec![]
+             }]
+         );
+@@ -651,7 +657,7 @@ mod test {
+         // stray closing characters (like in javascript) are ignored
+         assert_eq!(
+             PT::from_text("text }} more").unwrap().0,
+-            vec![Text("text }} more")]
++            vec![Text("text }} more".into())]
+         );
+ 
+         PT::from_text("{{").unwrap_err();
+@@ -737,15 +743,15 @@ mod test {
+         assert_eq!(
+             PT::from_text(input).unwrap().0,
+             vec![
+-                Text("\n"),
++                Text("\n".into()),
+                 Replacement {
+-                    key: "Front",
++                    key: "Front".into(),
+                     filters: vec![]
+                 },
+-                Text("\n"),
++                Text("\n".into()),
+                 Conditional {
+-                    key: "Back",
+-                    children: vec![Text("\n")]
++                    key: "Back".into(),
++                    children: vec![Text("\n".into())]
+                 }
+             ]
+         );
diff --git a/srcpkgs/anki/patches/0003-rustc-cross-compile.patch b/srcpkgs/anki/patches/0003-rustc-cross-compile.patch
new file mode 100644
index 00000000000..15239ea4cf1
--- /dev/null
+++ b/srcpkgs/anki/patches/0003-rustc-cross-compile.patch
@@ -0,0 +1,11 @@
+--- rspy/Makefile	2020-05-23 12:02:29.758286838 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -69,7 +69,7 @@
+ .build/build: $(DEPS)
+ 	touch ../proto/backend.proto
+ 	${BUILD_VARIABLES} \
+-		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS)
++		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS) --target $(RUST_TARGET)
+    touch $@
+ 
+ check: .build/check
diff --git a/srcpkgs/anki/patches/0004-vendored-deps.patch b/srcpkgs/anki/patches/0004-vendored-deps.patch
new file mode 100644
index 00000000000..7ca936804fc
--- /dev/null
+++ b/srcpkgs/anki/patches/0004-vendored-deps.patch
@@ -0,0 +1,91 @@
+diff -u -r Makefile Makefile
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 18:40:54.345223164 +1000
+@@ -92,7 +92,7 @@
+ 	fi
+ 
+ .PHONY: develop
+-develop: pyenv buildhash prepare
++develop: buildhash prepare
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	for dir in $(DEVEL); do \
+diff -u -r pylib/Makefile pylib/Makefile
+--- pylib/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ pylib/Makefile	2020-05-19 18:50:01.075182994 +1000
+@@ -52,7 +52,7 @@
+ 	python -m black anki/hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks
++BUILD_STEPS := .build/vernum .build/py-proto anki/buildinfo.py .build/hooks
+ 
+ # Checking
+ ######################
+diff -u -r qt/Makefile qt/Makefile
+--- qt/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ qt/Makefile	2020-05-19 18:50:17.520181786 +1000
+@@ -64,7 +64,7 @@
+ 	python -m black aqt/gui_hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
++BUILD_STEPS := .build/vernum .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
+ 
+ # Checking
+ ######################
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 19:01:35.602131965 +1000
+@@ -122,7 +122,7 @@
+ 	@echo "Build complete."
+ 
+ .PHONY: build-rspy
+-build-rspy: pyenv buildhash
++build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+--- Makefile	2020-05-19 19:41:44.191955000 +1000
++++ Makefile	2020-05-19 19:42:21.423952264 +1000
+@@ -124,19 +124,16 @@
+ .PHONY: build-rspy
+ build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+ 
+ .PHONY: build-pylib
+ build-pylib:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C pylib build
+ 
+ .PHONY: build-qt
+ build-qt:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C qt build
+ 
+ .PHONY: clean
+--- pylib/Makefile	2020-05-22 08:46:14.988607539 +1000
++++ pylib/Makefile	2020-05-22 08:46:38.376605821 +1000
+@@ -41,7 +41,7 @@
+ 
+ PROTODEPS := $(wildcard ../proto/*.proto)
+ 
+-.build/py-proto: .build/dev-deps $(PROTODEPS)
++.build/py-proto: $(PROTODEPS)
+ 	protoc --proto_path=../proto --python_out=anki --mypy_out=anki $(PROTODEPS)
+ 	perl -i'' -pe 's/from fluent_pb2/from anki.fluent_pb2/' anki/backend_pb2.pyi
+ 	perl -i'' -pe 's/import fluent_pb2/import anki.fluent_pb2/' anki/backend_pb2.py
+--- rspy/Makefile	2020-05-31 08:59:03.810152342 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -51,7 +51,7 @@
+ 
+ develop: .build/develop
+ 
+-DEPS := .build/tools .build/vernum ../meta/buildhash \
++DEPS := .build/vernum ../meta/buildhash \
+ 	$(wildcard $(QT_FTL_TEMPLATES)/*.ftl) \
+ 	$(wildcard $(QT_FTL_LOCALES)/*/*.ftl) \
+ 	$(shell "${FIND}" ../rslib/src -name '*.rs') $(wildcard ../proto/*) \
diff --git a/srcpkgs/anki/patches/0005-patched-pyo3.patch b/srcpkgs/anki/patches/0005-patched-pyo3.patch
new file mode 100644
index 00000000000..15844cc15fe
--- /dev/null
+++ b/srcpkgs/anki/patches/0005-patched-pyo3.patch
@@ -0,0 +1,11 @@
+--- rspy/Cargo.toml	2020-05-08 18:17:57.000000000 +1000
++++ rspy/Cargo.toml.new	2020-05-30 17:46:26.548157472 +1000
+@@ -12,7 +12,7 @@
+ tokio = "0.2.11"
+ 
+ [dependencies.pyo3]
+-version = "0.8.0"
++path = "../../pyo3" 
+ features = ["extension-module"]
+ 
+ [lib]
diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template
index 680e008a9d4..f3e777a3395 100644
--- a/srcpkgs/anki/template
+++ b/srcpkgs/anki/template
@@ -1,23 +1,78 @@
 # Template file for 'anki'
+#
+# NOTE: This template does use rust stable. It has a rather large
+# pyo3 patchset taken from github.com/wickerwaka/pyo3/removing-specialization
+# which allows it to operate on rust stable. But, it is currently on pyo3
+# 0.8.1. This patchset should ideally be rebased for the new version.
+# Preliminary tests found this would be slightly difficult. Anki dosen't
+# need a newer version.. yet.
+#
 pkgname=anki
-version=2.1.15
-revision=2
-archs=noarch
+version=2.1.26
+_pyo3_version=0.8.1
+revision=1
 build_style=gnu-makefile
 pycompile_dirs="/usr/share/anki/anki /usr/share/anki/aqt"
+hostmakedepends="git python3 rust cargo maturin which protobuf
+ mypy-protobuf-python python3-stringcase black python3-wheel
+ rsync nodejs python3-PyQt5-devel-tools gettext
+ qt5-translations python3-pip strace"
 depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy
  python3-PyAudio python3-mpv python3-Markdown python3-send2trash
- python3-BeautifulSoup4 python3-decorator python3-jsonschema"
+ python3-BeautifulSoup4 python3-decorator python3-jsonschema
+ python3-protobuf"
 short_desc="Spaced repetition flashcard program"
 maintainer="Steve Prybylski <sa.prybylx@gmail.com>"
 license="AGPL-3.0-or-later"
 homepage="https://apps.ankiweb.net"
 changelog="https://apps.ankiweb.net/docs/changes.html"
-distfiles="https://apps.ankiweb.net/downloads/current/anki-${version}-source.tgz"
-checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89
-
+distfiles="https://github.com/ankitects/anki/archive/${version}.tar.gz
+           https://github.com/PyO3/pyo3/archive/v${_pyo3_version}.tar.gz"
+checksum="f5a0c41f3eebe0e77de9d46f2a5cbbe20f7c3a4787f0f02e1d33f298428acbdf
+          437a5fcb54113da9e2999fb957c8948ca40f4f31081b6e8cf1d798033071eb57"
 python_version=3
 
+post_extract() {
+    # Constant place for 0006-patched-pyo3.patch
+    mv "${XBPS_BUILDDIR}/pyo3-${_pyo3_version}" "${XBPS_BUILDDIR}/pyo3"
+}
+
+post_patch() {
+    # Apply patches for pyo3
+    cd "${XBPS_BUILDDIR}/pyo3"
+    for p in ${FILESDIR}/pyo3-patches/*.patch ; do
+        msg_normal "Applying ${p} to pyo3\n"
+        patch -Np1 -i ${p}
+    done
+}
+
+pre_build() {
+	mkdir -p dist
+	make prepare
+}
+
+do_build() {
+	RUSTFLAGS="-C target-feature=-crt-static" make build
+}
+
+do_install() {
+	pushd pylib
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	pushd qt
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	# maturin generates a .whl, this is all we can do
+	PIP_CONFIG_FILE=/dev/null pip3 install --isolated --root=${DESTDIR} --prefix=/usr --ignore-installed --no-deps dist/ankirspy*.whl
+
+	# Copied from arch's PKGBUILD
+	install -Dm755 qt/runanki "${DESTDIR}/usr/bin/anki"
+	install -Dm644 qt/anki.desktop "${DESTDIR}/usr/share/applications/anki.desktop"
+	install -Dm644 qt/anki.png "${DESTDIR}/usr/share/pixmaps/anki.png"
+}
+
 post_install() {
 	vlicense LICENSE
 }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (5 preceding siblings ...)
  2020-06-01  9:58 ` fosslinux
@ 2020-06-01  9:59 ` fosslinux
  2020-06-01 10:05 ` [PR PATCH] [Updated] " fosslinux
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-06-01  9:59 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 407 bytes --]

New comment by fosslinux on void-packages repository

https://github.com/void-linux/void-packages/pull/22219#issuecomment-636753232

Comment:
Well, we can hardly have packages on rust nightly, as I have come to believe after a discussion on IRC, and especially not using rustup.

Luckily I found a patchset for pyo3!

So now it builds on rust stable. Now, this is just waiting on rust 1.44 to come out.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PR PATCH] [Updated] WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (6 preceding siblings ...)
  2020-06-01  9:59 ` fosslinux
@ 2020-06-01 10:05 ` fosslinux
  2020-06-01 10:28 ` fosslinux
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-06-01 10:05 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 2264 bytes --]

There is an updated pull request by fosslinux against master on the void-packages repository

https://github.com/fosslinux/void-packages anki-2.1.26
https://github.com/void-linux/void-packages/pull/22219

WIP: anki: update to 2.1.26
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust (nightly!), nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- same thing with python-protobuf, but for anki and at runtime
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.
- anki uses rustup. This is because it and some of its dependencies require archd code (notably pyo3). This is unavoidable, afaict.

Still todo:

- [x] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [x] Update python3-protobuf - hopefully will fix `AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'`.
- [x] Look into travis musl error. https://github.com/rust-lang/rust/issues/40174. Hopefully, using rust 1.44 as the rust version *should* fix this. What a PITA. I understand that this is because it works when I cross-compile to x86_64-musl from x86_64 but we need it to work native build from x86_64-musl for the builders...
- [x] Get off rustup and onto rust stable. Needs either a) pyo3 to work on stable or b) anki to be patched for rust-cpython.
- [ ] Blocked by rust 1.44.
- [ ] Travis wth on i686?
- [x] Make it open.
- [x] More extensive runtime testing.
- [ ] Runtime test on musl.

Questions:

- Is there any problems with removing `arch=nocross`?
- Does the rustup stuff look (somewhat) sane?
- Are the patches sane?

A patch file from https://github.com/void-linux/void-packages/pull/22219.patch is attached

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-anki-2.1.26-22219.patch --]
[-- Type: text/x-diff, Size: 330183 bytes --]

From dc49d200c37f20e082261214f30c9f0ec0a316a3 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:01 +1000
Subject: [PATCH 1/6] python3-mypy: update to 0.770, claim maintainership

---
 srcpkgs/python3-mypy/template | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/srcpkgs/python3-mypy/template b/srcpkgs/python3-mypy/template
index 5d7f93d5772..bde1e7f4be6 100644
--- a/srcpkgs/python3-mypy/template
+++ b/srcpkgs/python3-mypy/template
@@ -1,19 +1,18 @@
 # Template file for 'python3-mypy'
 pkgname=python3-mypy
-version=0.761
+version=0.770
 revision=1
 archs=noarch
 wrksrc="mypy-${version}"
 build_style=python3-module
-pycompile_module="mypy"
 hostmakedepends="python3-setuptools"
 depends="python3-mypy_extensions python3-typed-ast python3-typing_extensions"
 short_desc="Optional static typing for Python3"
-maintainer="Orphaned <orphan@voidlinux.org>"
+maintainer="fosslinux <fosslinux@aussies.space>"
 license="MIT"
 homepage="https://github.com/python/mypy"
 distfiles="${PYPI_SITE}/m/mypy/mypy-${version}.tar.gz"
-checksum=85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf
+checksum=8a627507ef9b307b46a1fea9513d5c98680ba09591253082b4c48697ba05a4ae
 
 post_install() {
 	vlicense LICENSE

From 7c67feaeffb4ddbdef9fbe1a0459ac5ac5ecc439 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:34:38 +1000
Subject: [PATCH 2/6] New package: maturin-0.8.1

---
 .../patches/cross-compile-setup-py.patch      | 14 +++++++++++++
 srcpkgs/maturin/template                      | 21 +++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 srcpkgs/maturin/patches/cross-compile-setup-py.patch
 create mode 100644 srcpkgs/maturin/template

diff --git a/srcpkgs/maturin/patches/cross-compile-setup-py.patch b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
new file mode 100644
index 00000000000..e57189cb7ab
--- /dev/null
+++ b/srcpkgs/maturin/patches/cross-compile-setup-py.patch
@@ -0,0 +1,14 @@
+--- setup.py	2020-04-30 22:36:01.000000000 +1000
++++ setup.py	2020-05-20 14:31:40.404994499 +1000
+@@ -56,9 +56,9 @@
+                     "(https://www.rust-lang.org/tools/install) and try again"
+                 )
+             subprocess.check_call(
+-                ["cargo", "rustc", "--bin", "maturin", "--", "-C", "link-arg=-s"]
++                ["cargo", "rustc", "--bin", "maturin", "--release", "--target", os.environ["RUST_TARGET"], "--", "-C", "link-arg=-s", "-C", "linker=" + os.environ["CC"].split(" ", 1)[0]]
+             )
+-            source = os.path.join(source_dir, "target", "debug", executable_name)
++            source = os.path.join(source_dir, "target", os.environ["RUST_TARGET"], "release", executable_name)
+         # run this after trying to build with cargo (as otherwise this leaves
+         # venv in a bad state: https://github.com/benfred/py-spy/issues/69)
+         install.run(self)
diff --git a/srcpkgs/maturin/template b/srcpkgs/maturin/template
new file mode 100644
index 00000000000..7eba36204f9
--- /dev/null
+++ b/srcpkgs/maturin/template
@@ -0,0 +1,21 @@
+# Template file for 'maturin'
+pkgname=maturin
+version=0.8.1
+revision=1
+build_style=python3-module
+hostmakedepends="cargo python3-setuptools python3-toml"
+makedepends="rust rust-std llvm9"
+short_desc="Build and publish crates with python bindings"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0, MIT"
+homepage="https://github.com/PyO3/maturin"
+distfiles="https://github.com/PyO3/maturin/archive/v${version}.tar.gz"
+checksum=b72a9885cda3ba4e53906a43aab101acb790622218ade6405b2ddf1ef1461f8f
+
+post_install() {
+	# Dynamic detection of python version
+	PYTHON_VERSION=$(python3 --version | sed "s/^Python //" | rev | sed "s/^[0-9]*.//" | rev)
+	mkdir -p "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	mv "${DESTDIR}/maturin" "${DESTDIR}/usr/lib/python${PYTHON_VERSION}/site-packages/"
+	vlicense license-mit
+}

From 96de4dbb3c34bf4961ba0c1f601205b1215dc700 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:25 +1000
Subject: [PATCH 3/6] New package: mypy-protobuf-python-1.13

---
 srcpkgs/mypy-protobuf-python/template | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-python/template

diff --git a/srcpkgs/mypy-protobuf-python/template b/srcpkgs/mypy-protobuf-python/template
new file mode 100644
index 00000000000..391d75f0c9e
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-python/template
@@ -0,0 +1,23 @@
+# Template file for 'mypy-protobuf-python'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-go
+#
+pkgname=mypy-protobuf-python
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_wrksrc=python
+build_style=python3-module
+hostmakedepends="python3-setuptools"
+depends="python3-mypy python3-typing_extensions python3-protobuf protobuf"
+short_desc="Generate mypy stubs from protobufs - Python implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74
+
+post_install() {
+	# We are not windows, remove the batch file
+	rm "${DESTDIR}/usr/bin/protoc_gen_mypy.bat"
+}

From aeaa9e6a25d47eedecac921e56d647d93d3f46ad Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:35:37 +1000
Subject: [PATCH 4/6] New package: mypy-protobuf-go-1.13

---
 .../patches/remote-go-improt.patch            | 11 +++++++++++
 srcpkgs/mypy-protobuf-go/template             | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
 create mode 100644 srcpkgs/mypy-protobuf-go/template

diff --git a/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
new file mode 100644
index 00000000000..300504bc70d
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/patches/remote-go-improt.patch
@@ -0,0 +1,11 @@
+--- go/src/protoc-gen-mypy/main.go.orig	2020-05-22 11:58:07.760761664 +1000
++++ go/src/protoc-gen-mypy/main.go	2020-05-22 11:58:00.595762190 +1000
+@@ -6,7 +6,7 @@
+ 	"sort"
+ 	"strings"
+ 
+-	"proto/mypy"
++	"github.com/dropbox/mypy-protobuf/go/src/proto/mypy"
+ 
+ 	"github.com/gogo/protobuf/proto"
+ 	"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
diff --git a/srcpkgs/mypy-protobuf-go/template b/srcpkgs/mypy-protobuf-go/template
new file mode 100644
index 00000000000..8f00e43d8a8
--- /dev/null
+++ b/srcpkgs/mypy-protobuf-go/template
@@ -0,0 +1,19 @@
+# Template file for 'mypy-protobuf-go'
+#
+# WARNING: THIS TEMPLATE SHOULD BE SYNCRONISED WITH mypy-protobuf-python
+#
+pkgname=mypy-protobuf-go
+version=1.13
+revision=1
+wrksrc="mypy-protobuf-${version}"
+build_style=go
+go_import_path="github.com/dropbox/mypy-protobuf"
+go_package="${go_import_path}/go/src/protoc-gen-mypy"
+hostmakedepends="git"
+depends="protobuf"
+short_desc="Generate mypy stubs from protobufs - go implementation"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="Apache-2.0"
+homepage="https://github.com/dropbox/mypy-protobuf"
+distfiles="https://github.com/dropbox/mypy-protobuf/archive/v${version}.tar.gz"
+checksum=7d86dfc076f8b51814fbfd3a66998a0b570fd1b82ebeda68ae6728cd538adb74

From e6d8f76eeb38c0a55f56ca0c4800d1d6d3c71c75 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:33:36 +1000
Subject: [PATCH 5/6] New package: python-stringcase-1.2.0

---
 srcpkgs/python-stringcase/template | 28 ++++++++++++++++++++++++++++
 srcpkgs/python3-stringcase         |  1 +
 2 files changed, 29 insertions(+)
 create mode 100644 srcpkgs/python-stringcase/template
 create mode 120000 srcpkgs/python3-stringcase

diff --git a/srcpkgs/python-stringcase/template b/srcpkgs/python-stringcase/template
new file mode 100644
index 00000000000..849e677c784
--- /dev/null
+++ b/srcpkgs/python-stringcase/template
@@ -0,0 +1,28 @@
+# Template file for 'python-stringcase'
+pkgname=python-stringcase
+version=1.2.0
+revision=1
+wrksrc="stringcase-${version}"
+build_style=python-module
+hostmakedepends="python-devel python3-devel"
+makedepends="${hostmakedepends}"
+depends="python"
+short_desc="String case converter for Python2"
+maintainer="fosslinux <fosslinux@aussies.space>"
+license="MIT"
+homepage="https://github.com/okunishinishi/python-stringcase"
+distfiles="${PYPI_SITE}/s/stringcase/stringcase-${version}.tar.gz"
+checksum=48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008
+
+post_install() {
+	vlicense LICENSE
+}
+
+python3-stringcase_package() {
+	depends="python3"
+	short_desc="${short_desc/Python2/Python3}"
+	pkg_install() {
+		vmove usr/lib/python3*
+		vlicense LICENSE
+	}
+}
diff --git a/srcpkgs/python3-stringcase b/srcpkgs/python3-stringcase
new file mode 120000
index 00000000000..53938bd1f0c
--- /dev/null
+++ b/srcpkgs/python3-stringcase
@@ -0,0 +1 @@
+python-stringcase
\ No newline at end of file

From 9fe95f38a28d042f1be3cc542646fddcd21c6c21 Mon Sep 17 00:00:00 2001
From: fosslinux <fosslinux@aussies.space>
Date: Sat, 23 May 2020 14:36:21 +1000
Subject: [PATCH 6/6] anki: update to 2.1.26

Has turned into a Bad Build System. Now uses rust nightly, python
(with bindings!), qt5, nodejs... the list goes on. There are quite
a few hacks and the like.
---
 ...1da60c6c00fc8cd930efa34113a602a830e2.patch |  118 +
 ...2423c8e293f843115f617d04213f04f63a77.patch |  134 ++
 ...13bce9c80b0e7ff37c5317705ce0acf32c15.patch | 1209 ++++++++++
 ...28e23ab3dab4eaa2277734019f1b8e0210c1.patch | 1978 +++++++++++++++++
 ...fec729e00355bbd067e5770a9e8e889280cf.patch | 1659 ++++++++++++++
 ...1da60c6c00fc8cd930efa34113a602a830e2.patch |   69 +
 ...2948d9147689701a24de2fcdffafc32ebe62.patch |   93 +
 ...c30b15f467c9f5ab139564be0099fba5b27f.patch |  159 ++
 ...7c2ad89dad6be5cf454fe0012d9aba9e60b2.patch | 1387 ++++++++++++
 ...10fcd8932c3d83fe73b07412969cc42ff686.patch |   38 +
 ...2a4b93b16ba9b7b43a1c73614efbcb6e9814.patch |  732 ++++++
 ...58f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch | 1321 +++++++++++
 .../0020-remove-nightly-check.patch           |   17 +
 srcpkgs/anki/patches/0001-aqt_data-fhs.patch  |   45 +
 .../anki/patches/0002-rust-nightly-fix.patch  |  274 +++
 .../patches/0003-rustc-cross-compile.patch    |   11 +
 srcpkgs/anki/patches/0004-vendored-deps.patch |   91 +
 srcpkgs/anki/patches/0005-patched-pyo3.patch  |   11 +
 srcpkgs/anki/template                         |   69 +-
 19 files changed, 9408 insertions(+), 7 deletions(-)
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch
 create mode 100644 srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch
 create mode 100644 srcpkgs/anki/patches/0001-aqt_data-fhs.patch
 create mode 100644 srcpkgs/anki/patches/0002-rust-nightly-fix.patch
 create mode 100644 srcpkgs/anki/patches/0003-rustc-cross-compile.patch
 create mode 100644 srcpkgs/anki/patches/0004-vendored-deps.patch
 create mode 100644 srcpkgs/anki/patches/0005-patched-pyo3.patch

diff --git a/srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch b/srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
new file mode 100644
index 00000000000..5a3f02afe94
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0001-stub-tests-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
@@ -0,0 +1,118 @@
+From b0561da60c6c00fc8cd930efa34113a602a830e2 Mon Sep 17 00:00:00 2001
+From: Donlon <mdonlon@treyarch.com>
+Date: Wed, 30 Oct 2019 07:02:06 -0700
+Subject: [PATCH] Stubbed out a bunch of tests
+
+---
+ .../{test_arithmetics.rs => test_arithmetics.rp} |  0
+ ...uffer_protocol.rs => test_buffer_protocol.rp} |  0
+ tests/{test_bytes.rs => test_bytes.rp}           |  0
+ tests/{test_class_new.rs => test_class_new.rp}   |  0
+ ...st_compile_error.rs => test_compile_error.rp} |  0
+ tests/{test_datetime.rs => test_datetime.rp}     |  0
+ tests/{test_dict_iter.rs => test_dict_iter.rp}   |  0
+ tests/{test_dunder.rs => test_dunder.rp}         |  0
+ tests/{test_exceptions.rs => test_exceptions.rp} |  0
+ tests/{test_gc.rs => test_gc.rp}                 |  0
+ ...st_getter_setter.rs => test_getter_setter.rp} |  0
+ .../{test_inheritance.rs => test_inheritance.rp} |  0
+ tests/{test_methods.rs => test_methods.rp}       |  0
+ tests/{test_module.rs => test_module.rp}         |  0
+ tests/{test_pyself.rs => test_pyself.rp}         |  0
+ tests/{test_sequence.rs => test_sequence.rp}     |  0
+ tests/{test_string.rs => test_string.rp}         |  0
+ ...e_arguments.rs => test_variable_arguments.rp} |  0
+ tests/{test_various.rs => test_various.rp}       |  0
+ rename tests/{test_arithmetics.rs => test_arithmetics.rp} (100%)
+ mode change 100755 => 100644
+ rename tests/{test_buffer_protocol.rs => test_buffer_protocol.rp} (100%)
+ rename tests/{test_bytes.rs => test_bytes.rp} (100%)
+ rename tests/{test_class_new.rs => test_class_new.rp} (100%)
+ rename tests/{test_compile_error.rs => test_compile_error.rp} (100%)
+ mode change 100755 => 100644
+ rename tests/{test_datetime.rs => test_datetime.rp} (100%)
+ rename tests/{test_dict_iter.rs => test_dict_iter.rp} (100%)
+ rename tests/{test_dunder.rs => test_dunder.rp} (100%)
+ mode change 100755 => 100644
+ rename tests/{test_exceptions.rs => test_exceptions.rp} (100%)
+ rename tests/{test_gc.rs => test_gc.rp} (100%)
+ rename tests/{test_getter_setter.rs => test_getter_setter.rp} (100%)
+ rename tests/{test_inheritance.rs => test_inheritance.rp} (100%)
+ rename tests/{test_methods.rs => test_methods.rp} (100%)
+ rename tests/{test_module.rs => test_module.rp} (100%)
+ rename tests/{test_pyself.rs => test_pyself.rp} (100%)
+ rename tests/{test_sequence.rs => test_sequence.rp} (100%)
+ rename tests/{test_string.rs => test_string.rp} (100%)
+ rename tests/{test_variable_arguments.rs => test_variable_arguments.rp} (100%)
+ rename tests/{test_various.rs => test_various.rp} (100%)
+
+diff --git a/tests/test_arithmetics.rs b/tests/test_arithmetics.rp
+old mode 100755
+new mode 100644
+similarity index 100%
+rename from tests/test_arithmetics.rs
+rename to tests/test_arithmetics.rp
+diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rp
+similarity index 100%
+rename from tests/test_buffer_protocol.rs
+rename to tests/test_buffer_protocol.rp
+diff --git a/tests/test_compile_error.rs b/tests/test_compile_error.rp
+old mode 100755
+new mode 100644
+similarity index 100%
+rename from tests/test_compile_error.rs
+rename to tests/test_compile_error.rp
+diff --git a/tests/test_datetime.rs b/tests/test_datetime.rp
+similarity index 100%
+rename from tests/test_datetime.rs
+rename to tests/test_datetime.rp
+diff --git a/tests/test_dict_iter.rs b/tests/test_dict_iter.rp
+similarity index 100%
+rename from tests/test_dict_iter.rs
+rename to tests/test_dict_iter.rp
+diff --git a/tests/test_dunder.rs b/tests/test_dunder.rp
+old mode 100755
+new mode 100644
+similarity index 100%
+rename from tests/test_dunder.rs
+rename to tests/test_dunder.rp
+diff --git a/tests/test_exceptions.rs b/tests/test_exceptions.rp
+similarity index 100%
+rename from tests/test_exceptions.rs
+rename to tests/test_exceptions.rp
+diff --git a/tests/test_gc.rs b/tests/test_gc.rp
+similarity index 100%
+rename from tests/test_gc.rs
+rename to tests/test_gc.rp
+diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rp
+similarity index 100%
+rename from tests/test_getter_setter.rs
+rename to tests/test_getter_setter.rp
+diff --git a/tests/test_inheritance.rs b/tests/test_inheritance.rp
+similarity index 100%
+rename from tests/test_inheritance.rs
+rename to tests/test_inheritance.rp
+diff --git a/tests/test_methods.rs b/tests/test_methods.rp
+similarity index 100%
+rename from tests/test_methods.rs
+rename to tests/test_methods.rp
+diff --git a/tests/test_module.rs b/tests/test_module.rp
+similarity index 100%
+rename from tests/test_module.rs
+rename to tests/test_module.rp
+diff --git a/tests/test_pyself.rs b/tests/test_pyself.rp
+similarity index 100%
+rename from tests/test_pyself.rs
+rename to tests/test_pyself.rp
+diff --git a/tests/test_sequence.rs b/tests/test_sequence.rp
+similarity index 100%
+rename from tests/test_sequence.rs
+rename to tests/test_sequence.rp
+diff --git a/tests/test_variable_arguments.rs b/tests/test_variable_arguments.rp
+similarity index 100%
+rename from tests/test_variable_arguments.rs
+rename to tests/test_variable_arguments.rp
+diff --git a/tests/test_various.rs b/tests/test_various.rp
+similarity index 100%
+rename from tests/test_various.rs
+rename to tests/test_various.rp
diff --git a/srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch b/srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch
new file mode 100644
index 00000000000..957690f295a
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0002-sequence-prepatch-d57f2423c8e293f843115f617d04213f04f63a77.patch
@@ -0,0 +1,134 @@
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index 0f9ca44b..5414704a 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -212,60 +212,6 @@ where
+     }
+ }
+ 
+-trait PySequenceSetItemProtocolImpl {
+-    fn sq_ass_item() -> Option<ffi::ssizeobjargproc>;
+-}
+-
+-impl<'p, T> PySequenceSetItemProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
+-    default fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
+-        None
+-    }
+-}
+-
+-impl<T> PySequenceSetItemProtocolImpl for T
+-where
+-    T: for<'p> PySequenceSetItemProtocol<'p>,
+-{
+-    fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
+-        unsafe extern "C" fn wrap<T>(
+-            slf: *mut ffi::PyObject,
+-            key: ffi::Py_ssize_t,
+-            value: *mut ffi::PyObject,
+-        ) -> c_int
+-        where
+-            T: for<'p> PySequenceSetItemProtocol<'p>,
+-        {
+-            let py = Python::assume_gil_acquired();
+-            let _pool = crate::GILPool::new(py);
+-            let slf = py.mut_from_borrowed_ptr::<T>(slf);
+-
+-            let result = if value.is_null() {
+-                Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
+-                    "Item deletion not supported by {:?}",
+-                    stringify!(T)
+-                )))
+-            } else {
+-                let value = py.from_borrowed_ptr::<PyAny>(value);
+-                match value.extract() {
+-                    Ok(value) => slf.__setitem__(key.into(), value).into(),
+-                    Err(e) => Err(e),
+-                }
+-            };
+-            match result {
+-                Ok(_) => 0,
+-                Err(e) => {
+-                    e.restore(py);
+-                    -1
+-                }
+-            }
+-        }
+-        Some(wrap::<T>)
+-    }
+-}
+-
+ /// It can be possible to delete and set items (PySequenceSetItemProtocol and
+ /// PySequenceDelItemProtocol implemented), only to delete (PySequenceDelItemProtocol implemented)
+ /// or no deleting or setting is possible
+@@ -286,11 +232,68 @@ mod sq_ass_item_impl {
+             Some(del_set_item)
+         } else if let Some(del_item) = T::del_item() {
+             Some(del_item)
++        } else if let Some(set_item) = T::set_item() {
++            Some(set_item)
+         } else {
+             None
+         }
+     }
+ 
++    trait SetItem {
++        fn set_item() -> Option<ffi::ssizeobjargproc>;
++    }
++
++    impl<'p, T> SetItem for T
++    where
++        T: PySequenceProtocol<'p>,
++    {
++        default fn set_item() -> Option<ffi::ssizeobjargproc> {
++            None
++        }
++    }
++
++    impl<T> SetItem for T
++    where
++        T: for<'p> PySequenceSetItemProtocol<'p>,
++    {
++        fn set_item() -> Option<ffi::ssizeobjargproc> {
++            unsafe extern "C" fn wrap<T>(
++                slf: *mut ffi::PyObject,
++                key: ffi::Py_ssize_t,
++                value: *mut ffi::PyObject,
++            ) -> c_int
++            where
++                T: for<'p> PySequenceSetItemProtocol<'p>,
++            {
++                let py = Python::assume_gil_acquired();
++                let _pool = crate::GILPool::new(py);
++                let slf = py.mut_from_borrowed_ptr::<T>(slf);
++
++                let result = if value.is_null() {
++                    Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
++                        "Item deletion is not supported by {:?}",
++                        stringify!(T)
++                    )))
++                } else {
++                    let value = py.from_borrowed_ptr::<PyAny>(value);
++                    match value.extract() {
++                        Ok(value) => slf.__setitem__(key.into(), value).into(),
++                        Err(e) => Err(e),
++                    }
++                };
++
++                match result {
++                    Ok(_) => 0,
++                    Err(e) => {
++                        e.restore(py);
++                        -1
++                    }
++                }
++            }
++            Some(wrap::<T>)
++        }
++    }
++
+     trait DelItem {
+         fn del_item() -> Option<ffi::ssizeobjargproc>;
+     }
diff --git a/srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch b/srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch
new file mode 100644
index 00000000000..53cf0172ba2
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0010-specialization-cb1313bce9c80b0e7ff37c5317705ce0acf32c15.patch
@@ -0,0 +1,1209 @@
+From cb1313bce9c80b0e7ff37c5317705ce0acf32c15 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Fri, 25 Oct 2019 20:51:08 -0700
+Subject: [PATCH] Revert "Run `cargo fmt` on source code and update
+ `CHANGELOG.md`"
+
+This reverts commit 33bf37d3d8ca08d3af39de22547e32e7c8eb0f54.
+---
+ CHANGELOG.md                        |   1 -
+ pyo3-derive-backend/src/pymethod.rs |   6 +-
+ src/class/basic.rs                  |  55 ++-----
+ src/class/buffer.rs                 |   5 +-
+ src/class/context.rs                |  10 +-
+ src/class/descr.rs                  |  10 +-
+ src/class/gc.rs                     |  10 +-
+ src/class/iter.rs                   |  10 +-
+ src/class/mapping.rs                |  40 +----
+ src/class/number.rs                 | 245 ++++++----------------------
+ src/class/pyasync.rs                |  25 +--
+ src/class/sequence.rs               |  45 +----
+ src/conversion.rs                   |   5 +-
+ 13 files changed, 95 insertions(+), 372 deletions(-)
+
+diff --git a/CHANGELOG.md b/CHANGELOG.md
+index a3aff9b31..482e9b01d 100644
+--- a/CHANGELOG.md
++++ b/CHANGELOG.md
+@@ -27,7 +27,6 @@ and `PyString::to_string_lossy` [#642](https://github.com/PyO3/pyo3/pull/642).
+ ### Fixed
+ 
+  * Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604)
+- * Patch specialization being broken by Rust 1.40. [#614](https://github.com/PyO3/pyo3/issues/614)
+  * Fix a segfault around PyErr. [#597](https://github.com/PyO3/pyo3/pull/597)
+ 
+ ## [0.8.0] - 2018-09-05
+diff --git a/pyo3-derive-backend/src/pymethod.rs b/pyo3-derive-backend/src/pymethod.rs
+index 2f561cb9d..8c867a567 100644
+--- a/pyo3-derive-backend/src/pymethod.rs
++++ b/pyo3-derive-backend/src/pymethod.rs
+@@ -38,7 +38,7 @@ pub fn gen_py_method(
+                     return Err(syn::Error::new_spanned(
+                         spec.args[0].ty,
+                         "Getter function can only have one argument of type pyo3::Python!",
+-                    ));
++                    ))
+                 }
+             };
+             impl_py_getter_def(name, doc, getter, &impl_wrap_getter(cls, name, takes_py))
+@@ -60,10 +60,10 @@ fn check_generic(name: &syn::Ident, sig: &syn::Signature) -> syn::Result<()> {
+         match param {
+             syn::GenericParam::Lifetime(_) => {}
+             syn::GenericParam::Type(_) => {
+-                return Err(syn::Error::new_spanned(param, err_msg("type")));
++                return Err(syn::Error::new_spanned(param, err_msg("type")))
+             }
+             syn::GenericParam::Const(_) => {
+-                return Err(syn::Error::new_spanned(param, err_msg("const")));
++                return Err(syn::Error::new_spanned(param, err_msg("const")))
+             }
+         }
+     }
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index 8c670bf82..29e19871f 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -202,10 +202,7 @@ trait GetAttrProtocolImpl {
+     fn tp_getattro() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> GetAttrProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_getattro() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -299,10 +296,7 @@ mod tp_setattro_impl {
+         fn del_attr() -> Option<ffi::setattrofunc>;
+     }
+ 
+-    impl<'p, T> DelAttr for T
+-    where
+-        T: PyObjectProtocol<'p>,
+-    {
++    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {
+         default fn del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+@@ -321,10 +315,7 @@ mod tp_setattro_impl {
+         fn set_del_attr() -> Option<ffi::setattrofunc>;
+     }
+ 
+-    impl<'p, T> SetDelAttr for T
+-    where
+-        T: PyObjectProtocol<'p>,
+-    {
++    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {
+         default fn set_del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+@@ -349,10 +340,7 @@ mod tp_setattro_impl {
+ trait StrProtocolImpl {
+     fn tp_str() -> Option<ffi::unaryfunc>;
+ }
+-impl<'p, T> StrProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_str() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -374,10 +362,7 @@ where
+ trait ReprProtocolImpl {
+     fn tp_repr() -> Option<ffi::unaryfunc>;
+ }
+-impl<'p, T> ReprProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_repr() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -400,10 +385,7 @@ where
+ pub trait FormatProtocolImpl {
+     fn __format__() -> Option<PyMethodDef>;
+ }
+-impl<'p, T> FormatProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn __format__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -413,10 +395,7 @@ where
+ pub trait BytesProtocolImpl {
+     fn __bytes__() -> Option<PyMethodDef>;
+ }
+-impl<'p, T> BytesProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn __bytes__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -426,10 +405,7 @@ where
+ pub trait UnicodeProtocolImpl {
+     fn __unicode__() -> Option<PyMethodDef>;
+ }
+-impl<'p, T> UnicodeProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn __unicode__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -438,10 +414,7 @@ where
+ trait HashProtocolImpl {
+     fn tp_hash() -> Option<ffi::hashfunc>;
+ }
+-impl<'p, T> HashProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_hash() -> Option<ffi::hashfunc> {
+         None
+     }
+@@ -464,10 +437,7 @@ where
+ trait BoolProtocolImpl {
+     fn nb_bool() -> Option<ffi::inquiry>;
+ }
+-impl<'p, T> BoolProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn nb_bool() -> Option<ffi::inquiry> {
+         None
+     }
+@@ -490,10 +460,7 @@ where
+ trait RichcmpProtocolImpl {
+     fn tp_richcompare() -> Option<ffi::richcmpfunc>;
+ }
+-impl<'p, T> RichcmpProtocolImpl for T
+-where
+-    T: PyObjectProtocol<'p>,
+-{
++impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {
+     default fn tp_richcompare() -> Option<ffi::richcmpfunc> {
+         None
+     }
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index f0f462db9..c30f078cc 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -69,10 +69,7 @@ trait PyBufferGetBufferProtocolImpl {
+     fn cb_bf_getbuffer() -> Option<ffi::getbufferproc>;
+ }
+ 
+-impl<'p, T> PyBufferGetBufferProtocolImpl for T
+-where
+-    T: PyBufferProtocol<'p>,
+-{
++impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {
+     default fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
+         None
+     }
+diff --git a/src/class/context.rs b/src/class/context.rs
+index 50aea33e9..2ad59768d 100644
+--- a/src/class/context.rs
++++ b/src/class/context.rs
+@@ -80,10 +80,7 @@ pub trait PyContextEnterProtocolImpl {
+     fn __enter__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyContextEnterProtocolImpl for T
+-where
+-    T: PyContextProtocol<'p>,
+-{
++impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {
+     default fn __enter__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -94,10 +91,7 @@ pub trait PyContextExitProtocolImpl {
+     fn __exit__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyContextExitProtocolImpl for T
+-where
+-    T: PyContextProtocol<'p>,
+-{
++impl<'p, T> PyContextExitProtocolImpl for T where T: PyContextProtocol<'p> {
+     default fn __exit__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/descr.rs b/src/class/descr.rs
+index 57d9119ca..c7b5b9660 100644
+--- a/src/class/descr.rs
++++ b/src/class/descr.rs
+@@ -72,10 +72,7 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
+ trait PyDescrGetProtocolImpl {
+     fn tp_descr_get() -> Option<ffi::descrgetfunc>;
+ }
+-impl<'p, T> PyDescrGetProtocolImpl for T
+-where
+-    T: PyDescrProtocol<'p>,
+-{
++impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {
+     default fn tp_descr_get() -> Option<ffi::descrgetfunc> {
+         None
+     }
+@@ -98,10 +95,7 @@ where
+ trait PyDescrSetProtocolImpl {
+     fn tp_descr_set() -> Option<ffi::descrsetfunc>;
+ }
+-impl<'p, T> PyDescrSetProtocolImpl for T
+-where
+-    T: PyDescrProtocol<'p>,
+-{
++impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {
+     default fn tp_descr_set() -> Option<ffi::descrsetfunc> {
+         None
+     }
+diff --git a/src/class/gc.rs b/src/class/gc.rs
+index 591b686af..4b69c9643 100644
+--- a/src/class/gc.rs
++++ b/src/class/gc.rs
+@@ -68,10 +68,7 @@ trait PyGCTraverseProtocolImpl {
+     fn tp_traverse() -> Option<ffi::traverseproc>;
+ }
+ 
+-impl<'p, T> PyGCTraverseProtocolImpl for T
+-where
+-    T: PyGCProtocol<'p>,
+-{
++impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {
+     default fn tp_traverse() -> Option<ffi::traverseproc> {
+         None
+     }
+@@ -115,10 +112,7 @@ trait PyGCClearProtocolImpl {
+     fn tp_clear() -> Option<ffi::inquiry>;
+ }
+ 
+-impl<'p, T> PyGCClearProtocolImpl for T
+-where
+-    T: PyGCProtocol<'p>,
+-{
++impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {
+     default fn tp_clear() -> Option<ffi::inquiry> {
+         None
+     }
+diff --git a/src/class/iter.rs b/src/class/iter.rs
+index a528289dd..fcf76f2e5 100644
+--- a/src/class/iter.rs
++++ b/src/class/iter.rs
+@@ -66,10 +66,7 @@ trait PyIterIterProtocolImpl {
+     fn tp_iter() -> Option<ffi::getiterfunc>;
+ }
+ 
+-impl<'p, T> PyIterIterProtocolImpl for T
+-where
+-    T: PyIterProtocol<'p>,
+-{
++impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {
+     default fn tp_iter() -> Option<ffi::getiterfunc> {
+         None
+     }
+@@ -94,10 +91,7 @@ trait PyIterNextProtocolImpl {
+     fn tp_iternext() -> Option<ffi::iternextfunc>;
+ }
+ 
+-impl<'p, T> PyIterNextProtocolImpl for T
+-where
+-    T: PyIterProtocol<'p>,
+-{
++impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {
+     default fn tp_iternext() -> Option<ffi::iternextfunc> {
+         None
+     }
+diff --git a/src/class/mapping.rs b/src/class/mapping.rs
+index 32326ff46..64d7b57ce 100644
+--- a/src/class/mapping.rs
++++ b/src/class/mapping.rs
+@@ -160,10 +160,7 @@ trait PyMappingLenProtocolImpl {
+     fn mp_length() -> Option<ffi::lenfunc>;
+ }
+ 
+-impl<'p, T> PyMappingLenProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn mp_length() -> Option<ffi::lenfunc> {
+         None
+     }
+@@ -183,10 +180,7 @@ trait PyMappingGetItemProtocolImpl {
+     fn mp_subscript() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyMappingGetItemProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn mp_subscript() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -211,10 +205,7 @@ trait PyMappingSetItemProtocolImpl {
+     fn mp_ass_subscript() -> Option<ffi::objobjargproc>;
+ }
+ 
+-impl<'p, T> PyMappingSetItemProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+@@ -236,10 +227,7 @@ trait DeplItemDipatch {
+     fn mp_del_subscript() -> Option<ffi::objobjargproc>;
+ }
+ 
+-impl<'p, T> DeplItemDipatch for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> DeplItemDipatch for T where T: PyMappingProtocol<'p> {
+     default fn mp_del_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+@@ -250,10 +238,7 @@ trait DelSetItemDispatch: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+     fn det_set_dispatch() -> Option<ffi::objobjargproc>;
+ }
+ 
+-impl<T> DelSetItemDispatch for T
+-where
+-    T: Sized + for<'p> PyMappingDelItemProtocol<'p>,
+-{
++impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+     default fn det_set_dispatch() -> Option<ffi::objobjargproc> {
+         py_func_del!(PyMappingDelItemProtocol, Self, __delitem__)
+     }
+@@ -288,10 +273,7 @@ pub trait PyMappingContainsProtocolImpl {
+     fn __contains__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyMappingContainsProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingContainsProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn __contains__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -302,10 +284,7 @@ pub trait PyMappingReversedProtocolImpl {
+     fn __reversed__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyMappingReversedProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingReversedProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn __reversed__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -316,10 +295,7 @@ pub trait PyMappingIterProtocolImpl {
+     fn __iter__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyMappingIterProtocolImpl for T
+-where
+-    T: PyMappingProtocol<'p>,
+-{
++impl<'p, T> PyMappingIterProtocolImpl for T where T: PyMappingProtocol<'p> {
+     default fn __iter__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 796b8bad9..0ab162e72 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -749,10 +749,7 @@ trait PyNumberAddProtocolImpl {
+     fn nb_add() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberAddProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -776,10 +773,7 @@ trait PyNumberSubProtocolImpl {
+     fn nb_subtract() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberSubProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -803,10 +797,7 @@ trait PyNumberMulProtocolImpl {
+     fn nb_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberMulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -830,10 +821,7 @@ trait PyNumberMatmulProtocolImpl {
+     fn nb_matrix_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberMatmulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -857,10 +845,7 @@ trait PyNumberTruedivProtocolImpl {
+     fn nb_true_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberTruedivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -884,10 +869,7 @@ trait PyNumberFloordivProtocolImpl {
+     fn nb_floor_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberFloordivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -911,10 +893,7 @@ trait PyNumberModProtocolImpl {
+     fn nb_remainder() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberModProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -938,10 +917,7 @@ trait PyNumberDivmodProtocolImpl {
+     fn nb_divmod() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberDivmodProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_divmod() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -965,10 +941,7 @@ trait PyNumberPowProtocolImpl {
+     fn nb_power() -> Option<ffi::ternaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberPowProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+@@ -992,10 +965,7 @@ trait PyNumberLShiftProtocolImpl {
+     fn nb_lshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberLShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1019,10 +989,7 @@ trait PyNumberRShiftProtocolImpl {
+     fn nb_rshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberRShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1046,10 +1013,7 @@ trait PyNumberAndProtocolImpl {
+     fn nb_and() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberAndProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1073,10 +1037,7 @@ trait PyNumberXorProtocolImpl {
+     fn nb_xor() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberXorProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1100,10 +1061,7 @@ trait PyNumberOrProtocolImpl {
+     fn nb_or() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberOrProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1127,10 +1085,7 @@ trait PyNumberIAddProtocolImpl {
+     fn nb_inplace_add() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIAddProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1149,10 +1104,7 @@ trait PyNumberISubProtocolImpl {
+     fn nb_inplace_subtract() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberISubProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1171,10 +1123,7 @@ trait PyNumberIMulProtocolImpl {
+     fn nb_inplace_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIMulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1193,10 +1142,7 @@ trait PyNumberIMatmulProtocolImpl {
+     fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIMatmulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1215,10 +1161,7 @@ trait PyNumberITruedivProtocolImpl {
+     fn nb_inplace_true_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberITruedivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1237,10 +1180,7 @@ trait PyNumberIFloordivProtocolImpl {
+     fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIFloordivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1259,10 +1199,7 @@ trait PyNumberIModProtocolImpl {
+     fn nb_inplace_remainder() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIModProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1281,10 +1218,7 @@ trait PyNumberIPowProtocolImpl {
+     fn nb_inplace_power() -> Option<ffi::ternaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIPowProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+@@ -1303,10 +1237,7 @@ trait PyNumberILShiftProtocolImpl {
+     fn nb_inplace_lshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberILShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1325,10 +1256,7 @@ trait PyNumberIRShiftProtocolImpl {
+     fn nb_inplace_rshift() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIRShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1347,10 +1275,7 @@ trait PyNumberIAndProtocolImpl {
+     fn nb_inplace_and() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIAndProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1369,10 +1294,7 @@ trait PyNumberIXorProtocolImpl {
+     fn nb_inplace_xor() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIXorProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1391,10 +1313,7 @@ trait PyNumberIOrProtocolImpl {
+     fn nb_inplace_or() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIOrProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_inplace_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -1414,10 +1333,7 @@ pub trait PyNumberRAddProtocolImpl {
+     fn __radd__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRAddProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __radd__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1437,10 +1353,7 @@ pub trait PyNumberRMulProtocolImpl {
+     fn __rmul__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRMulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rmul__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1451,10 +1364,7 @@ pub trait PyNumberRMatmulProtocolImpl {
+     fn __rmatmul__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRMatmulProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rmatmul__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1465,10 +1375,7 @@ pub trait PyNumberRTruedivProtocolImpl {
+     fn __rtruediv__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRTruedivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rtruediv__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1479,10 +1386,7 @@ pub trait PyNumberRFloordivProtocolImpl {
+     fn __rfloordiv__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRFloordivProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rfloordiv__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1493,10 +1397,7 @@ pub trait PyNumberRModProtocolImpl {
+     fn __rmod__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRModProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rmod__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1507,10 +1408,7 @@ pub trait PyNumberRDivmodProtocolImpl {
+     fn __rdivmod__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRDivmodProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rdivmod__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1521,10 +1419,7 @@ pub trait PyNumberRPowProtocolImpl {
+     fn __rpow__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRPowProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rpow__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1535,10 +1430,7 @@ pub trait PyNumberRLShiftProtocolImpl {
+     fn __rlshift__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRLShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rlshift__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1549,10 +1441,7 @@ pub trait PyNumberRRShiftProtocolImpl {
+     fn __rrshift__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRRShiftProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rrshift__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1563,10 +1452,7 @@ pub trait PyNumberRAndProtocolImpl {
+     fn __rand__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRAndProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rand__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1577,10 +1463,7 @@ pub trait PyNumberRXorProtocolImpl {
+     fn __rxor__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRXorProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __rxor__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1591,10 +1474,7 @@ pub trait PyNumberROrProtocolImpl {
+     fn __ror__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberROrProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __ror__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1604,10 +1484,7 @@ trait PyNumberNegProtocolImpl {
+     fn nb_negative() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberNegProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1632,10 +1509,7 @@ trait PyNumberPosProtocolImpl {
+     fn nb_positive() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberPosProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_positive() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1659,10 +1533,7 @@ trait PyNumberAbsProtocolImpl {
+     fn nb_absolute() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberAbsProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_absolute() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1686,10 +1557,7 @@ trait PyNumberInvertProtocolImpl {
+     fn nb_invert() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberInvertProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_invert() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1713,10 +1581,7 @@ trait PyNumberIntProtocolImpl {
+     fn nb_int() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIntProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_int() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1740,10 +1605,7 @@ trait PyNumberFloatProtocolImpl {
+     fn nb_float() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberFloatProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_float() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1767,10 +1629,7 @@ trait PyNumberIndexProtocolImpl {
+     fn nb_index() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyNumberIndexProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn nb_index() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -1794,10 +1653,7 @@ trait PyNumberComplexProtocolImpl {
+     fn __complex__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberComplexProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __complex__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -1807,10 +1663,7 @@ trait PyNumberRoundProtocolImpl {
+     fn __round__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyNumberRoundProtocolImpl for T
+-where
+-    T: PyNumberProtocol<'p>,
+-{
++impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {
+     default fn __round__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs
+index 2536d4ce2..f977fadfa 100644
+--- a/src/class/pyasync.rs
++++ b/src/class/pyasync.rs
+@@ -137,10 +137,7 @@ trait PyAsyncAwaitProtocolImpl {
+     fn am_await() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyAsyncAwaitProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn am_await() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -165,10 +162,7 @@ trait PyAsyncAiterProtocolImpl {
+     fn am_aiter() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyAsyncAiterProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn am_aiter() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -193,10 +187,7 @@ trait PyAsyncAnextProtocolImpl {
+     fn am_anext() -> Option<ffi::unaryfunc>;
+ }
+ 
+-impl<'p, T> PyAsyncAnextProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn am_anext() -> Option<ffi::unaryfunc> {
+         None
+     }
+@@ -254,10 +245,7 @@ trait PyAsyncAenterProtocolImpl {
+     fn __aenter__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyAsyncAenterProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn __aenter__() -> Option<PyMethodDef> {
+         None
+     }
+@@ -267,10 +255,7 @@ trait PyAsyncAexitProtocolImpl {
+     fn __aexit__() -> Option<PyMethodDef>;
+ }
+ 
+-impl<'p, T> PyAsyncAexitProtocolImpl for T
+-where
+-    T: PyAsyncProtocol<'p>,
+-{
++impl<'p, T> PyAsyncAexitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+     default fn __aexit__() -> Option<PyMethodDef> {
+         None
+     }
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index 5414704a1..ce65508fd 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -167,10 +167,7 @@ trait PySequenceLenProtocolImpl {
+     fn sq_length() -> Option<ffi::lenfunc>;
+ }
+ 
+-impl<'p, T> PySequenceLenProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_length() -> Option<ffi::lenfunc> {
+         None
+     }
+@@ -189,10 +186,7 @@ trait PySequenceGetItemProtocolImpl {
+     fn sq_item() -> Option<ffi::ssizeargfunc>;
+ }
+ 
+-impl<'p, T> PySequenceGetItemProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_item() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+@@ -298,10 +292,7 @@ mod sq_ass_item_impl {
+         fn del_item() -> Option<ffi::ssizeobjargproc>;
+     }
+ 
+-    impl<'p, T> DelItem for T
+-    where
+-        T: PySequenceProtocol<'p>,
+-    {
++    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {
+         default fn del_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+@@ -349,10 +340,7 @@ mod sq_ass_item_impl {
+         fn del_set_item() -> Option<ffi::ssizeobjargproc>;
+     }
+ 
+-    impl<'p, T> DelSetItem for T
+-    where
+-        T: PySequenceProtocol<'p>,
+-    {
++    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {
+         default fn del_set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+@@ -401,10 +389,7 @@ trait PySequenceContainsProtocolImpl {
+     fn sq_contains() -> Option<ffi::objobjproc>;
+ }
+ 
+-impl<'p, T> PySequenceContainsProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_contains() -> Option<ffi::objobjproc> {
+         None
+     }
+@@ -429,10 +414,7 @@ trait PySequenceConcatProtocolImpl {
+     fn sq_concat() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PySequenceConcatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -456,10 +438,7 @@ trait PySequenceRepeatProtocolImpl {
+     fn sq_repeat() -> Option<ffi::ssizeargfunc>;
+ }
+ 
+-impl<'p, T> PySequenceRepeatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+@@ -483,10 +462,7 @@ trait PySequenceInplaceConcatProtocolImpl {
+     fn sq_inplace_concat() -> Option<ffi::binaryfunc>;
+ }
+ 
+-impl<'p, T> PySequenceInplaceConcatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+@@ -510,10 +486,7 @@ trait PySequenceInplaceRepeatProtocolImpl {
+     fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc>;
+ }
+ 
+-impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T
+-where
+-    T: PySequenceProtocol<'p>,
+-{
++impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+     default fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+diff --git a/src/conversion.rs b/src/conversion.rs
+index 38f436de4..15ccdabde 100644
+--- a/src/conversion.rs
++++ b/src/conversion.rs
+@@ -100,10 +100,7 @@ pub trait ToBorrowedObject: ToPyObject {
+         F: FnOnce(*mut ffi::PyObject) -> R;
+ }
+ 
+-impl<T> ToBorrowedObject for T
+-where
+-    T: ToPyObject,
+-{
++impl<T> ToBorrowedObject for T where T: ToPyObject {
+     default fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
+     where
+         F: FnOnce(*mut ffi::PyObject) -> R,
diff --git a/srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch b/srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch
new file mode 100644
index 00000000000..ff6e46229e8
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0011-specialization-89c028e23ab3dab4eaa2277734019f1b8e0210c1.patch
@@ -0,0 +1,1978 @@
+From 89c028e23ab3dab4eaa2277734019f1b8e0210c1 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Fri, 25 Oct 2019 20:52:10 -0700
+Subject: [PATCH] Revert "Fix broken specialized implementations with Rust
+ 1.40"
+
+This reverts commit 5397a62f486a25b2f99aac7aa758161b993af6ae.
+---
+ src/class/basic.rs    |  94 ++++------
+ src/class/buffer.rs   |  16 +-
+ src/class/context.rs  |  24 +--
+ src/class/descr.rs    |  23 +--
+ src/class/gc.rs       |  22 +--
+ src/class/iter.rs     |  22 +--
+ src/class/mapping.rs  |  75 +++-----
+ src/class/number.rs   | 403 ++++++++++++++++--------------------------
+ src/class/pyasync.rs  |  51 ++----
+ src/class/sequence.rs |  80 ++++-----
+ src/conversion.rs     |   8 +-
+ src/instance.rs       |  39 ++--
+ 12 files changed, 319 insertions(+), 538 deletions(-)
+
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index 29e19871f..c3153dfa3 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -152,21 +152,17 @@ pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyObjectProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-    fn tp_as_object(_type_object: &mut ffi::PyTypeObject);
+-    fn nb_bool_fn() -> Option<ffi::inquiry>;
+-}
+-
+-impl<T> PyObjectProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+-    default fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
+-    default fn nb_bool_fn() -> Option<ffi::inquiry> {
++    fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
++    fn nb_bool_fn() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+ 
++impl<T> PyObjectProtocolImpl for T {}
++
+ impl<'p, T> PyObjectProtocolImpl for T
+ where
+     T: PyObjectProtocol<'p>,
+@@ -199,15 +195,13 @@ where
+ }
+ 
+ trait GetAttrProtocolImpl {
+-    fn tp_getattro() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_getattro() -> Option<ffi::binaryfunc> {
++    fn tp_getattro() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> GetAttrProtocolImpl for T
+ where
+     T: for<'p> PyObjectGetAttrProtocol<'p>,
+@@ -274,15 +268,13 @@ mod tp_setattro_impl {
+     }
+ 
+     trait SetAttr {
+-        fn set_attr() -> Option<ffi::setattrofunc>;
+-    }
+-
+-    impl<'p, T: PyObjectProtocol<'p>> SetAttr for T {
+-        default fn set_attr() -> Option<ffi::setattrofunc> {
++        fn set_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
++    impl<'p, T: PyObjectProtocol<'p>> SetAttr for T {}
++
+     impl<T> SetAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p>,
+@@ -293,15 +285,13 @@ mod tp_setattro_impl {
+     }
+ 
+     trait DelAttr {
+-        fn del_attr() -> Option<ffi::setattrofunc>;
+-    }
+-
+-    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {
+-        default fn del_attr() -> Option<ffi::setattrofunc> {
++        fn del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {}
++
+     impl<T> DelAttr for T
+     where
+         T: for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -312,15 +302,13 @@ mod tp_setattro_impl {
+     }
+ 
+     trait SetDelAttr {
+-        fn set_del_attr() -> Option<ffi::setattrofunc>;
+-    }
+-
+-    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {
+-        default fn set_del_attr() -> Option<ffi::setattrofunc> {
++        fn set_del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {}
++
+     impl<T> SetDelAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -338,13 +326,11 @@ mod tp_setattro_impl {
+ }
+ 
+ trait StrProtocolImpl {
+-    fn tp_str() -> Option<ffi::unaryfunc>;
+-}
+-impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_str() -> Option<ffi::unaryfunc> {
++    fn tp_str() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
++impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> StrProtocolImpl for T
+ where
+     T: for<'p> PyObjectStrProtocol<'p>,
+@@ -360,13 +346,11 @@ where
+ }
+ 
+ trait ReprProtocolImpl {
+-    fn tp_repr() -> Option<ffi::unaryfunc>;
+-}
+-impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_repr() -> Option<ffi::unaryfunc> {
++    fn tp_repr() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
++impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> ReprProtocolImpl for T
+ where
+     T: for<'p> PyObjectReprProtocol<'p>,
+@@ -383,42 +367,34 @@ where
+ 
+ #[doc(hidden)]
+ pub trait FormatProtocolImpl {
+-    fn __format__() -> Option<PyMethodDef>;
+-}
+-impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn __format__() -> Option<PyMethodDef> {
++    fn __format__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait BytesProtocolImpl {
+-    fn __bytes__() -> Option<PyMethodDef>;
+-}
+-impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn __bytes__() -> Option<PyMethodDef> {
++    fn __bytes__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait UnicodeProtocolImpl {
+-    fn __unicode__() -> Option<PyMethodDef>;
+-}
+-impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn __unicode__() -> Option<PyMethodDef> {
++    fn __unicode__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ trait HashProtocolImpl {
+-    fn tp_hash() -> Option<ffi::hashfunc>;
+-}
+-impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_hash() -> Option<ffi::hashfunc> {
++    fn tp_hash() -> Option<ffi::hashfunc> {
+         None
+     }
+ }
++impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> HashProtocolImpl for T
+ where
+     T: for<'p> PyObjectHashProtocol<'p>,
+@@ -435,13 +411,11 @@ where
+ }
+ 
+ trait BoolProtocolImpl {
+-    fn nb_bool() -> Option<ffi::inquiry>;
+-}
+-impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn nb_bool() -> Option<ffi::inquiry> {
++    fn nb_bool() -> Option<ffi::inquiry> {
+         None
+     }
+ }
++impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> BoolProtocolImpl for T
+ where
+     T: for<'p> PyObjectBoolProtocol<'p>,
+@@ -458,13 +432,11 @@ where
+ }
+ 
+ trait RichcmpProtocolImpl {
+-    fn tp_richcompare() -> Option<ffi::richcmpfunc>;
+-}
+-impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {
+-    default fn tp_richcompare() -> Option<ffi::richcmpfunc> {
++    fn tp_richcompare() -> Option<ffi::richcmpfunc> {
+         None
+     }
+ }
++impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ impl<T> RichcmpProtocolImpl for T
+ where
+     T: for<'p> PyObjectRichcmpProtocol<'p>,
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index c30f078cc..d36524e7c 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -41,15 +41,13 @@ pub trait PyBufferReleaseBufferProtocol<'p>: PyBufferProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyBufferProtocolImpl {
+-    fn tp_as_buffer() -> Option<ffi::PyBufferProcs>;
+-}
+-
+-impl<T> PyBufferProtocolImpl for T {
+-    default fn tp_as_buffer() -> Option<ffi::PyBufferProcs> {
++    fn tp_as_buffer() -> Option<ffi::PyBufferProcs> {
+         None
+     }
+ }
+ 
++impl<T> PyBufferProtocolImpl for T {}
++
+ impl<'p, T> PyBufferProtocolImpl for T
+ where
+     T: PyBufferProtocol<'p>,
+@@ -66,15 +64,13 @@ where
+ }
+ 
+ trait PyBufferGetBufferProtocolImpl {
+-    fn cb_bf_getbuffer() -> Option<ffi::getbufferproc>;
+-}
+-
+-impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {
+-    default fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
++    fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {}
++
+ impl<T> PyBufferGetBufferProtocolImpl for T
+ where
+     T: for<'p> PyBufferGetBufferProtocol<'p>,
+diff --git a/src/class/context.rs b/src/class/context.rs
+index 2ad59768d..092527ba0 100644
+--- a/src/class/context.rs
++++ b/src/class/context.rs
+@@ -47,15 +47,13 @@ pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyContextProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-}
+-
+-impl<T> PyContextProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+ }
+ 
++impl<T> PyContextProtocolImpl for T {}
++
+ impl<'p, T> PyContextProtocolImpl for T
+ where
+     T: PyContextProtocol<'p>,
+@@ -77,22 +75,18 @@ where
+ 
+ #[doc(hidden)]
+ pub trait PyContextEnterProtocolImpl {
+-    fn __enter__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {
+-    default fn __enter__() -> Option<PyMethodDef> {
++    fn __enter__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyContextExitProtocolImpl {
+-    fn __exit__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyContextExitProtocolImpl for T where T: PyContextProtocol<'p> {
+-    default fn __exit__() -> Option<PyMethodDef> {
++    fn __exit__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyContextExitProtocolImpl for T where T: PyContextProtocol<'p> {}
+diff --git a/src/class/descr.rs b/src/class/descr.rs
+index c7b5b9660..5f7e68306 100644
+--- a/src/class/descr.rs
++++ b/src/class/descr.rs
+@@ -70,13 +70,11 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
+ }
+ 
+ trait PyDescrGetProtocolImpl {
+-    fn tp_descr_get() -> Option<ffi::descrgetfunc>;
+-}
+-impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {
+-    default fn tp_descr_get() -> Option<ffi::descrgetfunc> {
++    fn tp_descr_get() -> Option<ffi::descrgetfunc> {
+         None
+     }
+ }
++impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ 
+ impl<T> PyDescrGetProtocolImpl for T
+ where
+@@ -93,13 +91,11 @@ where
+ }
+ 
+ trait PyDescrSetProtocolImpl {
+-    fn tp_descr_set() -> Option<ffi::descrsetfunc>;
+-}
+-impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {
+-    default fn tp_descr_set() -> Option<ffi::descrsetfunc> {
++    fn tp_descr_set() -> Option<ffi::descrsetfunc> {
+         None
+     }
+ }
++impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ impl<T> PyDescrSetProtocolImpl for T
+ where
+     T: for<'p> PyDescrSetProtocol<'p>,
+@@ -131,17 +127,14 @@ impl<'p, T> PyDescrSetNameProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait PyDescrProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-    fn tp_as_descr(_type_object: &mut ffi::PyTypeObject);
+-}
+-
+-impl<T> PyDescrProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+-    default fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
++    fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
++impl<T> PyDescrProtocolImpl for T {}
++
+ impl<'p, T> PyDescrProtocolImpl for T
+ where
+     T: PyDescrProtocol<'p>,
+diff --git a/src/class/gc.rs b/src/class/gc.rs
+index 4b69c9643..eaa4d9015 100644
+--- a/src/class/gc.rs
++++ b/src/class/gc.rs
+@@ -23,12 +23,10 @@ pub trait PyGCClearProtocol<'p>: PyGCProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait PyGCProtocolImpl {
+-    fn update_type_object(_type_object: &mut ffi::PyTypeObject);
++    fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<'p, T> PyGCProtocolImpl for T {
+-    default fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
+-}
++impl<'p, T> PyGCProtocolImpl for T {}
+ 
+ impl<'p, T> PyGCProtocolImpl for T
+ where
+@@ -65,15 +63,13 @@ impl<'p> PyVisit<'p> {
+ }
+ 
+ trait PyGCTraverseProtocolImpl {
+-    fn tp_traverse() -> Option<ffi::traverseproc>;
+-}
+-
+-impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {
+-    default fn tp_traverse() -> Option<ffi::traverseproc> {
++    fn tp_traverse() -> Option<ffi::traverseproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {}
++
+ #[doc(hidden)]
+ impl<T> PyGCTraverseProtocolImpl for T
+ where
+@@ -109,15 +105,13 @@ where
+ }
+ 
+ trait PyGCClearProtocolImpl {
+-    fn tp_clear() -> Option<ffi::inquiry>;
+-}
+-
+-impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {
+-    default fn tp_clear() -> Option<ffi::inquiry> {
++    fn tp_clear() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {}
++
+ impl<T> PyGCClearProtocolImpl for T
+ where
+     T: for<'p> PyGCClearProtocol<'p>,
+diff --git a/src/class/iter.rs b/src/class/iter.rs
+index fcf76f2e5..9001d53ce 100644
+--- a/src/class/iter.rs
++++ b/src/class/iter.rs
+@@ -44,12 +44,10 @@ pub trait PyIterNextProtocol<'p>: PyIterProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyIterProtocolImpl {
+-    fn tp_as_iter(_typeob: &mut ffi::PyTypeObject);
++    fn tp_as_iter(_typeob: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<T> PyIterProtocolImpl for T {
+-    default fn tp_as_iter(_typeob: &mut ffi::PyTypeObject) {}
+-}
++impl<T> PyIterProtocolImpl for T {}
+ 
+ impl<'p, T> PyIterProtocolImpl for T
+ where
+@@ -63,15 +61,13 @@ where
+ }
+ 
+ trait PyIterIterProtocolImpl {
+-    fn tp_iter() -> Option<ffi::getiterfunc>;
+-}
+-
+-impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {
+-    default fn tp_iter() -> Option<ffi::getiterfunc> {
++    fn tp_iter() -> Option<ffi::getiterfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {}
++
+ impl<T> PyIterIterProtocolImpl for T
+ where
+     T: for<'p> PyIterIterProtocol<'p>,
+@@ -88,15 +84,13 @@ where
+ }
+ 
+ trait PyIterNextProtocolImpl {
+-    fn tp_iternext() -> Option<ffi::iternextfunc>;
+-}
+-
+-impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {
+-    default fn tp_iternext() -> Option<ffi::iternextfunc> {
++    fn tp_iternext() -> Option<ffi::iternextfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {}
++
+ impl<T> PyIterNextProtocolImpl for T
+ where
+     T: for<'p> PyIterNextProtocol<'p>,
+diff --git a/src/class/mapping.rs b/src/class/mapping.rs
+index 64d7b57ce..616763502 100644
+--- a/src/class/mapping.rs
++++ b/src/class/mapping.rs
+@@ -106,19 +106,16 @@ pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyMappingProtocolImpl {
+-    fn tp_as_mapping() -> Option<ffi::PyMappingMethods>;
+-    fn methods() -> Vec<PyMethodDef>;
+-}
+-
+-impl<T> PyMappingProtocolImpl for T {
+-    default fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
++    fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
+         None
+     }
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+ }
+ 
++impl<T> PyMappingProtocolImpl for T {}
++
+ impl<'p, T> PyMappingProtocolImpl for T
+ where
+     T: PyMappingProtocol<'p>,
+@@ -157,15 +154,13 @@ where
+ }
+ 
+ trait PyMappingLenProtocolImpl {
+-    fn mp_length() -> Option<ffi::lenfunc>;
+-}
+-
+-impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn mp_length() -> Option<ffi::lenfunc> {
++    fn mp_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ impl<T> PyMappingLenProtocolImpl for T
+ where
+     T: for<'p> PyMappingLenProtocol<'p>,
+@@ -177,15 +172,13 @@ where
+ }
+ 
+ trait PyMappingGetItemProtocolImpl {
+-    fn mp_subscript() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn mp_subscript() -> Option<ffi::binaryfunc> {
++    fn mp_subscript() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ impl<T> PyMappingGetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingGetItemProtocol<'p>,
+@@ -202,15 +195,13 @@ where
+ }
+ 
+ trait PyMappingSetItemProtocolImpl {
+-    fn mp_ass_subscript() -> Option<ffi::objobjargproc>;
+-}
+-
+-impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
++    fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ impl<T> PyMappingSetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p>,
+@@ -224,26 +215,22 @@ where
+ /// Returns `None` if PyMappingDelItemProtocol isn't implemented, otherwise dispatches to
+ /// `DelSetItemDispatch`
+ trait DeplItemDipatch {
+-    fn mp_del_subscript() -> Option<ffi::objobjargproc>;
+-}
+-
+-impl<'p, T> DeplItemDipatch for T where T: PyMappingProtocol<'p> {
+-    default fn mp_del_subscript() -> Option<ffi::objobjargproc> {
++    fn mp_del_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> DeplItemDipatch for T where T: PyMappingProtocol<'p> {}
++
+ /// Returns `py_func_set_del` if PyMappingSetItemProtocol is implemented, otherwise `py_func_del`
+ trait DelSetItemDispatch: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+-    fn det_set_dispatch() -> Option<ffi::objobjargproc>;
+-}
+-
+-impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+-    default fn det_set_dispatch() -> Option<ffi::objobjargproc> {
++    fn det_set_dispatch() -> Option<ffi::objobjargproc> {
+         py_func_del!(PyMappingDelItemProtocol, Self, __delitem__)
+     }
+ }
+ 
++impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {}
++
+ impl<T> DelSetItemDispatch for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p> + for<'p> PyMappingDelItemProtocol<'p>,
+@@ -270,33 +257,27 @@ where
+ 
+ #[doc(hidden)]
+ pub trait PyMappingContainsProtocolImpl {
+-    fn __contains__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyMappingContainsProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn __contains__() -> Option<PyMethodDef> {
++    fn __contains__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingContainsProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyMappingReversedProtocolImpl {
+-    fn __reversed__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyMappingReversedProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn __reversed__() -> Option<PyMethodDef> {
++    fn __reversed__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyMappingReversedProtocolImpl for T where T: PyMappingProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyMappingIterProtocolImpl {
+-    fn __iter__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyMappingIterProtocolImpl for T where T: PyMappingProtocol<'p> {
+-    default fn __iter__() -> Option<PyMethodDef> {
++    fn __iter__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyMappingIterProtocolImpl for T where T: PyMappingProtocol<'p> {}
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 0ab162e72..2ee3a57d5 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -622,15 +622,10 @@ pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyNumberProtocolImpl: PyObjectProtocolImpl {
+-    fn methods() -> Vec<PyMethodDef>;
+-    fn tp_as_number() -> Option<ffi::PyNumberMethods>;
+-}
+-
+-impl<'p, T> PyNumberProtocolImpl for T {
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+-    default fn tp_as_number() -> Option<ffi::PyNumberMethods> {
++    fn tp_as_number() -> Option<ffi::PyNumberMethods> {
+         if let Some(nb_bool) = <Self as PyObjectProtocolImpl>::nb_bool_fn() {
+             let meth = ffi::PyNumberMethods {
+                 nb_bool: Some(nb_bool),
+@@ -643,6 +638,8 @@ impl<'p, T> PyNumberProtocolImpl for T {
+     }
+ }
+ 
++impl<'p, T> PyNumberProtocolImpl for T {}
++
+ impl<'p, T> PyNumberProtocolImpl for T
+ where
+     T: PyNumberProtocol<'p>,
+@@ -746,15 +743,13 @@ where
+ }
+ 
+ trait PyNumberAddProtocolImpl {
+-    fn nb_add() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_add() -> Option<ffi::binaryfunc> {
++    fn nb_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberAddProtocol<'p>,
+@@ -770,15 +765,13 @@ where
+ }
+ 
+ trait PyNumberSubProtocolImpl {
+-    fn nb_subtract() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_subtract() -> Option<ffi::binaryfunc> {
++    fn nb_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberSubProtocolImpl for T
+ where
+     T: for<'p> PyNumberSubProtocol<'p>,
+@@ -794,15 +787,13 @@ where
+ }
+ 
+ trait PyNumberMulProtocolImpl {
+-    fn nb_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMulProtocol<'p>,
+@@ -818,15 +809,13 @@ where
+ }
+ 
+ trait PyNumberMatmulProtocolImpl {
+-    fn nb_matrix_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMatmulProtocol<'p>,
+@@ -842,15 +831,13 @@ where
+ }
+ 
+ trait PyNumberTruedivProtocolImpl {
+-    fn nb_true_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_true_divide() -> Option<ffi::binaryfunc> {
++    fn nb_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberTruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberTruedivProtocol<'p>,
+@@ -866,15 +853,13 @@ where
+ }
+ 
+ trait PyNumberFloordivProtocolImpl {
+-    fn nb_floor_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_floor_divide() -> Option<ffi::binaryfunc> {
++    fn nb_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloordivProtocol<'p>,
+@@ -890,15 +875,13 @@ where
+ }
+ 
+ trait PyNumberModProtocolImpl {
+-    fn nb_remainder() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_remainder() -> Option<ffi::binaryfunc> {
++    fn nb_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberModProtocolImpl for T
+ where
+     T: for<'p> PyNumberModProtocol<'p>,
+@@ -914,15 +897,13 @@ where
+ }
+ 
+ trait PyNumberDivmodProtocolImpl {
+-    fn nb_divmod() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_divmod() -> Option<ffi::binaryfunc> {
++    fn nb_divmod() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberDivmodProtocolImpl for T
+ where
+     T: for<'p> PyNumberDivmodProtocol<'p>,
+@@ -938,15 +919,13 @@ where
+ }
+ 
+ trait PyNumberPowProtocolImpl {
+-    fn nb_power() -> Option<ffi::ternaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_power() -> Option<ffi::ternaryfunc> {
++    fn nb_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberPowProtocol<'p>,
+@@ -962,15 +941,13 @@ where
+ }
+ 
+ trait PyNumberLShiftProtocolImpl {
+-    fn nb_lshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_lshift() -> Option<ffi::binaryfunc> {
++    fn nb_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberLShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberLShiftProtocol<'p>,
+@@ -986,15 +963,13 @@ where
+ }
+ 
+ trait PyNumberRShiftProtocolImpl {
+-    fn nb_rshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_rshift() -> Option<ffi::binaryfunc> {
++    fn nb_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberRShiftProtocol<'p>,
+@@ -1010,15 +985,13 @@ where
+ }
+ 
+ trait PyNumberAndProtocolImpl {
+-    fn nb_and() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_and() -> Option<ffi::binaryfunc> {
++    fn nb_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberAndProtocol<'p>,
+@@ -1034,15 +1007,13 @@ where
+ }
+ 
+ trait PyNumberXorProtocolImpl {
+-    fn nb_xor() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_xor() -> Option<ffi::binaryfunc> {
++    fn nb_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberXorProtocol<'p>,
+@@ -1058,15 +1029,13 @@ where
+ }
+ 
+ trait PyNumberOrProtocolImpl {
+-    fn nb_or() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_or() -> Option<ffi::binaryfunc> {
++    fn nb_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberOrProtocol<'p>,
+@@ -1082,15 +1051,13 @@ where
+ }
+ 
+ trait PyNumberIAddProtocolImpl {
+-    fn nb_inplace_add() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_add() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAddProtocol<'p>,
+@@ -1101,15 +1068,13 @@ where
+ }
+ 
+ trait PyNumberISubProtocolImpl {
+-    fn nb_inplace_subtract() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberISubProtocolImpl for T
+ where
+     T: for<'p> PyNumberISubProtocol<'p>,
+@@ -1120,15 +1085,13 @@ where
+ }
+ 
+ trait PyNumberIMulProtocolImpl {
+-    fn nb_inplace_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMulProtocol<'p>,
+@@ -1139,15 +1102,13 @@ where
+ }
+ 
+ trait PyNumberIMatmulProtocolImpl {
+-    fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMatmulProtocol<'p>,
+@@ -1158,15 +1119,13 @@ where
+ }
+ 
+ trait PyNumberITruedivProtocolImpl {
+-    fn nb_inplace_true_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberITruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberITruedivProtocol<'p>,
+@@ -1177,15 +1136,13 @@ where
+ }
+ 
+ trait PyNumberIFloordivProtocolImpl {
+-    fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberIFloordivProtocol<'p>,
+@@ -1196,15 +1153,13 @@ where
+ }
+ 
+ trait PyNumberIModProtocolImpl {
+-    fn nb_inplace_remainder() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIModProtocolImpl for T
+ where
+     T: for<'p> PyNumberIModProtocol<'p>,
+@@ -1215,15 +1170,13 @@ where
+ }
+ 
+ trait PyNumberIPowProtocolImpl {
+-    fn nb_inplace_power() -> Option<ffi::ternaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
++    fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberIPowProtocol<'p>,
+@@ -1234,15 +1187,13 @@ where
+ }
+ 
+ trait PyNumberILShiftProtocolImpl {
+-    fn nb_inplace_lshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberILShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberILShiftProtocol<'p>,
+@@ -1253,15 +1204,13 @@ where
+ }
+ 
+ trait PyNumberIRShiftProtocolImpl {
+-    fn nb_inplace_rshift() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberIRShiftProtocol<'p>,
+@@ -1272,15 +1221,13 @@ where
+ }
+ 
+ trait PyNumberIAndProtocolImpl {
+-    fn nb_inplace_and() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_and() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAndProtocol<'p>,
+@@ -1291,15 +1238,13 @@ where
+ }
+ 
+ trait PyNumberIXorProtocolImpl {
+-    fn nb_inplace_xor() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberIXorProtocol<'p>,
+@@ -1310,15 +1255,13 @@ where
+ }
+ 
+ trait PyNumberIOrProtocolImpl {
+-    fn nb_inplace_or() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_inplace_or() -> Option<ffi::binaryfunc> {
++    fn nb_inplace_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberIOrProtocol<'p>,
+@@ -1330,15 +1273,13 @@ where
+ 
+ #[doc(hidden)]
+ pub trait PyNumberRAddProtocolImpl {
+-    fn __radd__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __radd__() -> Option<PyMethodDef> {
++    fn __radd__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRSubProtocolImpl {
+     fn __rsub__() -> Option<PyMethodDef> {
+@@ -1350,146 +1291,120 @@ impl<'p, T> PyNumberRSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait PyNumberRMulProtocolImpl {
+-    fn __rmul__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rmul__() -> Option<PyMethodDef> {
++    fn __rmul__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRMatmulProtocolImpl {
+-    fn __rmatmul__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rmatmul__() -> Option<PyMethodDef> {
++    fn __rmatmul__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRTruedivProtocolImpl {
+-    fn __rtruediv__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rtruediv__() -> Option<PyMethodDef> {
++    fn __rtruediv__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRFloordivProtocolImpl {
+-    fn __rfloordiv__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rfloordiv__() -> Option<PyMethodDef> {
++    fn __rfloordiv__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRModProtocolImpl {
+-    fn __rmod__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rmod__() -> Option<PyMethodDef> {
++    fn __rmod__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRDivmodProtocolImpl {
+-    fn __rdivmod__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rdivmod__() -> Option<PyMethodDef> {
++    fn __rdivmod__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRPowProtocolImpl {
+-    fn __rpow__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rpow__() -> Option<PyMethodDef> {
++    fn __rpow__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRLShiftProtocolImpl {
+-    fn __rlshift__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rlshift__() -> Option<PyMethodDef> {
++    fn __rlshift__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRRShiftProtocolImpl {
+-    fn __rrshift__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rrshift__() -> Option<PyMethodDef> {
++    fn __rrshift__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRAndProtocolImpl {
+-    fn __rand__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rand__() -> Option<PyMethodDef> {
++    fn __rand__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberRXorProtocolImpl {
+-    fn __rxor__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __rxor__() -> Option<PyMethodDef> {
++    fn __rxor__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ #[doc(hidden)]
+ pub trait PyNumberROrProtocolImpl {
+-    fn __ror__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __ror__() -> Option<PyMethodDef> {
++    fn __ror__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-trait PyNumberNegProtocolImpl {
+-    fn nb_negative() -> Option<ffi::unaryfunc>;
+-}
++impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+-impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_negative() -> Option<ffi::unaryfunc> {
++trait PyNumberNegProtocolImpl {
++    fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberNegProtocolImpl for T
+ where
+     T: for<'p> PyNumberNegProtocol<'p>,
+@@ -1506,15 +1421,13 @@ where
+ }
+ 
+ trait PyNumberPosProtocolImpl {
+-    fn nb_positive() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_positive() -> Option<ffi::unaryfunc> {
++    fn nb_positive() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberPosProtocolImpl for T
+ where
+     T: for<'p> PyNumberPosProtocol<'p>,
+@@ -1530,15 +1443,13 @@ where
+ }
+ 
+ trait PyNumberAbsProtocolImpl {
+-    fn nb_absolute() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_absolute() -> Option<ffi::unaryfunc> {
++    fn nb_absolute() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberAbsProtocolImpl for T
+ where
+     T: for<'p> PyNumberAbsProtocol<'p>,
+@@ -1554,15 +1465,13 @@ where
+ }
+ 
+ trait PyNumberInvertProtocolImpl {
+-    fn nb_invert() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_invert() -> Option<ffi::unaryfunc> {
++    fn nb_invert() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberInvertProtocolImpl for T
+ where
+     T: for<'p> PyNumberInvertProtocol<'p>,
+@@ -1578,15 +1487,13 @@ where
+ }
+ 
+ trait PyNumberIntProtocolImpl {
+-    fn nb_int() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_int() -> Option<ffi::unaryfunc> {
++    fn nb_int() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIntProtocolImpl for T
+ where
+     T: for<'p> PyNumberIntProtocol<'p>,
+@@ -1602,15 +1509,13 @@ where
+ }
+ 
+ trait PyNumberFloatProtocolImpl {
+-    fn nb_float() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_float() -> Option<ffi::unaryfunc> {
++    fn nb_float() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberFloatProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloatProtocol<'p>,
+@@ -1626,15 +1531,13 @@ where
+ }
+ 
+ trait PyNumberIndexProtocolImpl {
+-    fn nb_index() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn nb_index() -> Option<ffi::unaryfunc> {
++    fn nb_index() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {}
++
+ impl<T> PyNumberIndexProtocolImpl for T
+ where
+     T: for<'p> PyNumberIndexProtocol<'p>,
+@@ -1650,21 +1553,17 @@ where
+ }
+ 
+ trait PyNumberComplexProtocolImpl {
+-    fn __complex__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __complex__() -> Option<PyMethodDef> {
++    fn __complex__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-trait PyNumberRoundProtocolImpl {
+-    fn __round__() -> Option<PyMethodDef>;
+-}
++impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+-impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {
+-    default fn __round__() -> Option<PyMethodDef> {
++trait PyNumberRoundProtocolImpl {
++    fn __round__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {}
+diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs
+index f977fadfa..9afb72c17 100644
+--- a/src/class/pyasync.rs
++++ b/src/class/pyasync.rs
+@@ -91,20 +91,17 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
+ 
+ #[doc(hidden)]
+ pub trait PyAsyncProtocolImpl {
+-    fn tp_as_async() -> Option<ffi::PyAsyncMethods>;
+-    fn methods() -> Vec<PyMethodDef>;
+-}
+-
+-impl<T> PyAsyncProtocolImpl for T {
+-    default fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
++    fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
+         None
+     }
+ 
+-    default fn methods() -> Vec<PyMethodDef> {
++    fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+     }
+ }
+ 
++impl<T> PyAsyncProtocolImpl for T {}
++
+ impl<'p, T> PyAsyncProtocolImpl for T
+ where
+     T: PyAsyncProtocol<'p>,
+@@ -134,15 +131,13 @@ where
+ }
+ 
+ trait PyAsyncAwaitProtocolImpl {
+-    fn am_await() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn am_await() -> Option<ffi::unaryfunc> {
++    fn am_await() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
++
+ impl<T> PyAsyncAwaitProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAwaitProtocol<'p>,
+@@ -159,15 +154,13 @@ where
+ }
+ 
+ trait PyAsyncAiterProtocolImpl {
+-    fn am_aiter() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn am_aiter() -> Option<ffi::unaryfunc> {
++    fn am_aiter() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
++
+ impl<T> PyAsyncAiterProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAiterProtocol<'p>,
+@@ -184,15 +177,13 @@ where
+ }
+ 
+ trait PyAsyncAnextProtocolImpl {
+-    fn am_anext() -> Option<ffi::unaryfunc>;
+-}
+-
+-impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn am_anext() -> Option<ffi::unaryfunc> {
++    fn am_anext() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {}
++
+ mod anext {
+     use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
+     use crate::callback::CallbackConverter;
+@@ -242,21 +233,17 @@ mod anext {
+ }
+ 
+ trait PyAsyncAenterProtocolImpl {
+-    fn __aenter__() -> Option<PyMethodDef>;
+-}
+-
+-impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn __aenter__() -> Option<PyMethodDef> {
++    fn __aenter__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-trait PyAsyncAexitProtocolImpl {
+-    fn __aexit__() -> Option<PyMethodDef>;
+-}
++impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+ 
+-impl<'p, T> PyAsyncAexitProtocolImpl for T where T: PyAsyncProtocol<'p> {
+-    default fn __aexit__() -> Option<PyMethodDef> {
++trait PyAsyncAexitProtocolImpl {
++    fn __aexit__() -> Option<PyMethodDef> {
+         None
+     }
+ }
++
++impl<'p, T> PyAsyncAexitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index ce65508fd..23771ba0b 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -134,15 +134,13 @@ pub trait PySequenceInplaceRepeatProtocol<'p>: PySequenceProtocol<'p> + IntoPy<P
+ 
+ #[doc(hidden)]
+ pub trait PySequenceProtocolImpl {
+-    fn tp_as_sequence() -> Option<ffi::PySequenceMethods>;
+-}
+-
+-impl<T> PySequenceProtocolImpl for T {
+-    default fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
++    fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
+         None
+     }
+ }
+ 
++impl<T> PySequenceProtocolImpl for T {}
++
+ impl<'p, T> PySequenceProtocolImpl for T
+ where
+     T: PySequenceProtocol<'p>,
+@@ -164,15 +162,13 @@ where
+ }
+ 
+ trait PySequenceLenProtocolImpl {
+-    fn sq_length() -> Option<ffi::lenfunc>;
+-}
+-
+-impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_length() -> Option<ffi::lenfunc> {
++    fn sq_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceLenProtocolImpl for T
+ where
+     T: for<'p> PySequenceLenProtocol<'p>,
+@@ -183,15 +179,13 @@ where
+ }
+ 
+ trait PySequenceGetItemProtocolImpl {
+-    fn sq_item() -> Option<ffi::ssizeargfunc>;
+-}
+-
+-impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_item() -> Option<ffi::ssizeargfunc> {
++    fn sq_item() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceGetItemProtocolImpl for T
+ where
+     T: for<'p> PySequenceGetItemProtocol<'p>,
+@@ -289,15 +283,13 @@ mod sq_ass_item_impl {
+     }
+ 
+     trait DelItem {
+-        fn del_item() -> Option<ffi::ssizeobjargproc>;
+-    }
+-
+-    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {
+-        default fn del_item() -> Option<ffi::ssizeobjargproc> {
++        fn del_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {}
++
+     impl<T> DelItem for T
+     where
+         T: for<'p> PySequenceDelItemProtocol<'p>,
+@@ -337,15 +329,13 @@ mod sq_ass_item_impl {
+     }
+ 
+     trait DelSetItem {
+-        fn del_set_item() -> Option<ffi::ssizeobjargproc>;
+-    }
+-
+-    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {
+-        default fn del_set_item() -> Option<ffi::ssizeobjargproc> {
++        fn del_set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
++    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {}
++
+     impl<T> DelSetItem for T
+     where
+         T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
+@@ -386,15 +376,13 @@ mod sq_ass_item_impl {
+ }
+ 
+ trait PySequenceContainsProtocolImpl {
+-    fn sq_contains() -> Option<ffi::objobjproc>;
+-}
+-
+-impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_contains() -> Option<ffi::objobjproc> {
++    fn sq_contains() -> Option<ffi::objobjproc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceContainsProtocolImpl for T
+ where
+     T: for<'p> PySequenceContainsProtocol<'p>,
+@@ -411,15 +399,13 @@ where
+ }
+ 
+ trait PySequenceConcatProtocolImpl {
+-    fn sq_concat() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_concat() -> Option<ffi::binaryfunc> {
++    fn sq_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceConcatProtocol<'p>,
+@@ -435,15 +421,13 @@ where
+ }
+ 
+ trait PySequenceRepeatProtocolImpl {
+-    fn sq_repeat() -> Option<ffi::ssizeargfunc>;
+-}
+-
+-impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_repeat() -> Option<ffi::ssizeargfunc> {
++    fn sq_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceRepeatProtocol<'p>,
+@@ -459,15 +443,13 @@ where
+ }
+ 
+ trait PySequenceInplaceConcatProtocolImpl {
+-    fn sq_inplace_concat() -> Option<ffi::binaryfunc>;
+-}
+-
+-impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
++    fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceInplaceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceConcatProtocol<'p>,
+@@ -483,15 +465,13 @@ where
+ }
+ 
+ trait PySequenceInplaceRepeatProtocolImpl {
+-    fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc>;
+-}
+-
+-impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {
+-    default fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
++    fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
++impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
++
+ impl<T> PySequenceInplaceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceRepeatProtocol<'p>,
+diff --git a/src/conversion.rs b/src/conversion.rs
+index 15ccdabde..a3bca1175 100644
+--- a/src/conversion.rs
++++ b/src/conversion.rs
+@@ -96,12 +96,6 @@ pub trait ToBorrowedObject: ToPyObject {
+     /// May be more efficient than `to_object` because it does not need
+     /// to touch any reference counts when the input object already is a Python object.
+     fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
+-    where
+-        F: FnOnce(*mut ffi::PyObject) -> R;
+-}
+-
+-impl<T> ToBorrowedObject for T where T: ToPyObject {
+-    default fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
+     where
+         F: FnOnce(*mut ffi::PyObject) -> R,
+     {
+@@ -114,6 +108,8 @@ impl<T> ToBorrowedObject for T where T: ToPyObject {
+     }
+ }
+ 
++impl<T> ToBorrowedObject for T where T: ToPyObject {}
++
+ impl<T> ToBorrowedObject for T
+ where
+     T: ToPyObject + AsPyPointer,
+diff --git a/src/instance.rs b/src/instance.rs
+index 779d18617..68bd45ec3 100644
+--- a/src/instance.rs
++++ b/src/instance.rs
+@@ -359,18 +359,13 @@ impl<T> Py<T> {
+ 
+ /// Specialization workaround
+ trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
+-    fn as_ref_dispatch(&self, _py: Python) -> &T;
+-    fn as_mut_dispatch(&mut self, _py: Python) -> &mut T;
+-}
+-
+-impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {
+-    default fn as_ref_dispatch(&self, _py: Python) -> &T {
++    fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe {
+             let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
+             ptr.as_ref().expect("Py has a null pointer")
+         }
+     }
+-    default fn as_mut_dispatch(&mut self, _py: Python) -> &mut T {
++    fn as_mut_dispatch(&mut self, _py: Python) -> &mut T {
+         unsafe {
+             let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
+             ptr.as_mut().expect("Py has a null pointer")
+@@ -378,6 +373,8 @@ impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {
+     }
+ }
+ 
++impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {}
++
+ impl<T: PyTypeInfo + PyNativeType> AsPyRefDispatch<T> for Py<T> {
+     fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe { &*(self as *const instance::Py<T> as *const T) }
+@@ -556,21 +553,9 @@ impl<'p, T: ToPyObject> AsPyPointer for ManagedPyRef<'p, T> {
+ /// Helper trait to choose the right implementation for [ManagedPyRef]
+ pub trait ManagedPyRefDispatch: ToPyObject {
+     /// Optionally converts into a python object and stores the pointer to the python heap.
+-    fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self>;
+-
+-    /// Dispatch over a xdecref and a noop drop impl
+-    fn drop_impl(borrowed: &mut ManagedPyRef<Self>);
+-}
+-
+-/// Case 1: It's a rust object which still needs to be converted to a python object.
+-/// This means we're storing the owned pointer that into_ptr() has given us
+-/// and therefore need to xdecref when we're done.
+-///
+-/// Note that the actual implementations are part of the trait declaration to avoid
+-/// a specialization error
+-impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {
++    ///
+     /// Contains the case 1 impl (with to_object) to avoid a specialization error
+-    default fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self> {
++    fn to_managed_py_ref<'p>(&self, py: Python<'p>) -> ManagedPyRef<'p, Self> {
+         ManagedPyRef {
+             data: self.to_object(py).into_ptr(),
+             data_type: PhantomData,
+@@ -578,12 +563,22 @@ impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {
+         }
+     }
+ 
++    /// Dispatch over a xdecref and a noop drop impl
++    ///
+     /// Contains the case 1 impl (decref) to avoid a specialization error
+-    default fn drop_impl(borrowed: &mut ManagedPyRef<Self>) {
++    fn drop_impl(borrowed: &mut ManagedPyRef<Self>) {
+         unsafe { ffi::Py_DECREF(borrowed.data) };
+     }
+ }
+ 
++/// Case 1: It's a rust object which still needs to be converted to a python object.
++/// This means we're storing the owned pointer that into_ptr() has given us
++/// and therefore need to xdecref when we're done.
++///
++/// Note that the actual implementations are part of the trait declaration to avoid
++/// a specialization error
++impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {}
++
+ /// Case 2: It's an object on the python heap, we're just storing a borrowed pointer.
+ /// The object we're getting is an owned pointer, it might have it's own drop impl.
+ impl<T: ToPyObject + AsPyPointer + ?Sized> ManagedPyRefDispatch for T {
diff --git a/srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch b/srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch
new file mode 100644
index 00000000000..c4315a09425
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0012-specialization-2f4dfec729e00355bbd067e5770a9e8e889280cf.patch
@@ -0,0 +1,1659 @@
+From 2f4dfec729e00355bbd067e5770a9e8e889280cf Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Mon, 28 Oct 2019 14:44:26 -0700
+Subject: [PATCH] Removed specialization for all traits
+
+Crate compiles but tests all fail due to missing trait implementations
+---
+ build.rs              |   5 --
+ src/class/basic.rs    |  55 ++++++------
+ src/class/buffer.rs   |   8 +-
+ src/class/context.rs  |   2 -
+ src/class/descr.rs    |  11 +--
+ src/class/gc.rs       |  12 +--
+ src/class/iter.rs     |  12 +--
+ src/class/mapping.rs  |  24 ++---
+ src/class/number.rs   | 199 +++++++++++++++++++-----------------------
+ src/class/pyasync.rs  |  19 ++--
+ src/class/sequence.rs |  63 +++++--------
+ src/conversion.rs     |   9 +-
+ src/instance.rs       |  13 ++-
+ src/lib.rs            |   2 -
+ src/object.rs         |   2 +-
+ src/type_object.rs    |  50 +++++++++--
+ src/types/sequence.rs |   5 +-
+ 17 files changed, 229 insertions(+), 262 deletions(-)
+
+diff --git a/build.rs b/build.rs
+index 7f1060acc..d6b38c489 100644
+--- a/build.rs
++++ b/build.rs
+@@ -537,11 +537,6 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<(String), String>
+ }
+ 
+ fn check_rustc_version() {
+-    let channel = Channel::read().expect("Failed to determine rustc channel");
+-    if !channel.supports_features() {
+-        panic!("Error: pyo3 requires a nightly or dev version of Rust.");
+-    }
+-
+     let actual_version = Version::read().expect("Failed to determine the rustc version");
+     if !actual_version.at_least(MIN_VERSION) {
+         panic!(
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index c3153dfa3..f87a0d029 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -161,11 +161,21 @@ pub trait PyObjectProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyObjectProtocolImpl for T {}
++//impl<T> PyObjectProtocolImpl for T {}
+ 
+ impl<'p, T> PyObjectProtocolImpl for T
+ where
+-    T: PyObjectProtocol<'p>,
++    T: PyObjectProtocol<'p>
++        + PyObjectSetAttrProtocol<'p>
++        + GetAttrProtocolImpl
++        + StrProtocolImpl
++        + ReprProtocolImpl
++        + HashProtocolImpl
++        + RichcmpProtocolImpl
++        + BoolProtocolImpl
++        + tp_setattro_impl::DelAttr
++        + tp_setattro_impl::SetAttr
++        + tp_setattro_impl::SetDelAttr,
+ {
+     fn methods() -> Vec<PyMethodDef> {
+         let mut methods = Vec::new();
+@@ -194,14 +204,12 @@ where
+     }
+ }
+ 
+-trait GetAttrProtocolImpl {
++pub trait GetAttrProtocolImpl {
+     fn tp_getattro() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> GetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
+-
+ impl<T> GetAttrProtocolImpl for T
+ where
+     T: for<'p> PyObjectGetAttrProtocol<'p>,
+@@ -255,7 +263,10 @@ mod tp_setattro_impl {
+     /// The signature is the same as for PyObject_SetAttr(), but setting v to NULL to delete an
+     /// attribute must be supported. It is usually convenient to set this field to
+     /// PyObject_GenericSetAttr(), which implements the normal way of setting object attributes.
+-    pub(super) fn tp_setattro<'p, T: PyObjectProtocol<'p>>() -> Option<ffi::setattrofunc> {
++    pub(super) fn tp_setattro<'p, T>() -> Option<ffi::setattrofunc>
++    where
++        T: PyObjectProtocol<'p> + SetDelAttr + SetAttr + DelAttr,
++    {
+         if let Some(set_del) = T::set_del_attr() {
+             Some(set_del)
+         } else if let Some(set) = T::set_attr() {
+@@ -267,14 +278,12 @@ mod tp_setattro_impl {
+         }
+     }
+ 
+-    trait SetAttr {
++    pub trait SetAttr {
+         fn set_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T: PyObjectProtocol<'p>> SetAttr for T {}
+-
+     impl<T> SetAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p>,
+@@ -284,14 +293,12 @@ mod tp_setattro_impl {
+         }
+     }
+ 
+-    trait DelAttr {
++    pub trait DelAttr {
+         fn del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> DelAttr for T where T: PyObjectProtocol<'p> {}
+-
+     impl<T> DelAttr for T
+     where
+         T: for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -301,14 +308,12 @@ mod tp_setattro_impl {
+         }
+     }
+ 
+-    trait SetDelAttr {
++    pub trait SetDelAttr {
+         fn set_del_attr() -> Option<ffi::setattrofunc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> SetDelAttr for T where T: PyObjectProtocol<'p> {}
+-
+     impl<T> SetDelAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -325,12 +330,12 @@ mod tp_setattro_impl {
+     }
+ }
+ 
+-trait StrProtocolImpl {
++pub trait StrProtocolImpl {
+     fn tp_str() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+-impl<'p, T> StrProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> StrProtocolImpl for T
+ where
+     T: for<'p> PyObjectStrProtocol<'p>,
+@@ -345,12 +350,12 @@ where
+     }
+ }
+ 
+-trait ReprProtocolImpl {
++pub trait ReprProtocolImpl {
+     fn tp_repr() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+-impl<'p, T> ReprProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> ReprProtocolImpl for T
+ where
+     T: for<'p> PyObjectReprProtocol<'p>,
+@@ -389,12 +394,12 @@ pub trait UnicodeProtocolImpl {
+ }
+ impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+-trait HashProtocolImpl {
++pub trait HashProtocolImpl {
+     fn tp_hash() -> Option<ffi::hashfunc> {
+         None
+     }
+ }
+-impl<'p, T> HashProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> HashProtocolImpl for T
+ where
+     T: for<'p> PyObjectHashProtocol<'p>,
+@@ -410,12 +415,12 @@ where
+     }
+ }
+ 
+-trait BoolProtocolImpl {
++pub trait BoolProtocolImpl {
+     fn nb_bool() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+-impl<'p, T> BoolProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> BoolProtocolImpl for T
+ where
+     T: for<'p> PyObjectBoolProtocol<'p>,
+@@ -431,12 +436,12 @@ where
+     }
+ }
+ 
+-trait RichcmpProtocolImpl {
++pub trait RichcmpProtocolImpl {
+     fn tp_richcompare() -> Option<ffi::richcmpfunc> {
+         None
+     }
+ }
+-impl<'p, T> RichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {}
++
+ impl<T> RichcmpProtocolImpl for T
+ where
+     T: for<'p> PyObjectRichcmpProtocol<'p>,
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index d36524e7c..32d1a25af 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -46,11 +46,9 @@ pub trait PyBufferProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyBufferProtocolImpl for T {}
+-
+ impl<'p, T> PyBufferProtocolImpl for T
+ where
+-    T: PyBufferProtocol<'p>,
++    T: PyBufferProtocol<'p> + PyBufferGetBufferProtocolImpl,
+ {
+     #[inline]
+     #[allow(clippy::needless_update)] // For python 2 it's not useless
+@@ -63,14 +61,12 @@ where
+     }
+ }
+ 
+-trait PyBufferGetBufferProtocolImpl {
++pub trait PyBufferGetBufferProtocolImpl {
+     fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {}
+-
+ impl<T> PyBufferGetBufferProtocolImpl for T
+ where
+     T: for<'p> PyBufferGetBufferProtocol<'p>,
+diff --git a/src/class/context.rs b/src/class/context.rs
+index 092527ba0..e5dd56b90 100644
+--- a/src/class/context.rs
++++ b/src/class/context.rs
+@@ -52,8 +52,6 @@ pub trait PyContextProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyContextProtocolImpl for T {}
+-
+ impl<'p, T> PyContextProtocolImpl for T
+ where
+     T: PyContextProtocol<'p>,
+diff --git a/src/class/descr.rs b/src/class/descr.rs
+index 5f7e68306..ea1dbf012 100644
+--- a/src/class/descr.rs
++++ b/src/class/descr.rs
+@@ -69,12 +69,11 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
+     type Result: Into<PyResult<()>>;
+ }
+ 
+-trait PyDescrGetProtocolImpl {
++pub trait PyDescrGetProtocolImpl {
+     fn tp_descr_get() -> Option<ffi::descrgetfunc> {
+         None
+     }
+ }
+-impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {}
+ 
+ impl<T> PyDescrGetProtocolImpl for T
+ where
+@@ -90,12 +89,12 @@ where
+     }
+ }
+ 
+-trait PyDescrSetProtocolImpl {
++pub trait PyDescrSetProtocolImpl {
+     fn tp_descr_set() -> Option<ffi::descrsetfunc> {
+         None
+     }
+ }
+-impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {}
++
+ impl<T> PyDescrSetProtocolImpl for T
+ where
+     T: for<'p> PyDescrSetProtocol<'p>,
+@@ -133,11 +132,9 @@ pub trait PyDescrProtocolImpl {
+     fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<T> PyDescrProtocolImpl for T {}
+-
+ impl<'p, T> PyDescrProtocolImpl for T
+ where
+-    T: PyDescrProtocol<'p>,
++    T: PyDescrProtocol<'p> + PyDescrGetProtocolImpl + PyDescrSetProtocolImpl,
+ {
+     fn methods() -> Vec<PyMethodDef> {
+         Vec::new()
+diff --git a/src/class/gc.rs b/src/class/gc.rs
+index eaa4d9015..7e6bc8b45 100644
+--- a/src/class/gc.rs
++++ b/src/class/gc.rs
+@@ -26,11 +26,9 @@ pub trait PyGCProtocolImpl {
+     fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<'p, T> PyGCProtocolImpl for T {}
+-
+ impl<'p, T> PyGCProtocolImpl for T
+ where
+-    T: PyGCProtocol<'p>,
++    T: PyGCProtocol<'p> + PyGCTraverseProtocolImpl + PyGCClearProtocolImpl,
+ {
+     fn update_type_object(type_object: &mut ffi::PyTypeObject) {
+         type_object.tp_traverse = Self::tp_traverse();
+@@ -62,14 +60,12 @@ impl<'p> PyVisit<'p> {
+     }
+ }
+ 
+-trait PyGCTraverseProtocolImpl {
++pub trait PyGCTraverseProtocolImpl {
+     fn tp_traverse() -> Option<ffi::traverseproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {}
+-
+ #[doc(hidden)]
+ impl<T> PyGCTraverseProtocolImpl for T
+ where
+@@ -104,14 +100,12 @@ where
+     }
+ }
+ 
+-trait PyGCClearProtocolImpl {
++pub trait PyGCClearProtocolImpl {
+     fn tp_clear() -> Option<ffi::inquiry> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {}
+-
+ impl<T> PyGCClearProtocolImpl for T
+ where
+     T: for<'p> PyGCClearProtocol<'p>,
+diff --git a/src/class/iter.rs b/src/class/iter.rs
+index 9001d53ce..b1e896420 100644
+--- a/src/class/iter.rs
++++ b/src/class/iter.rs
+@@ -47,11 +47,9 @@ pub trait PyIterProtocolImpl {
+     fn tp_as_iter(_typeob: &mut ffi::PyTypeObject) {}
+ }
+ 
+-impl<T> PyIterProtocolImpl for T {}
+-
+ impl<'p, T> PyIterProtocolImpl for T
+ where
+-    T: PyIterProtocol<'p>,
++    T: PyIterProtocol<'p> + PyIterIterProtocolImpl + PyIterNextProtocolImpl,
+ {
+     #[inline]
+     fn tp_as_iter(typeob: &mut ffi::PyTypeObject) {
+@@ -60,14 +58,12 @@ where
+     }
+ }
+ 
+-trait PyIterIterProtocolImpl {
++pub trait PyIterIterProtocolImpl {
+     fn tp_iter() -> Option<ffi::getiterfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {}
+-
+ impl<T> PyIterIterProtocolImpl for T
+ where
+     T: for<'p> PyIterIterProtocol<'p>,
+@@ -83,14 +79,12 @@ where
+     }
+ }
+ 
+-trait PyIterNextProtocolImpl {
++pub trait PyIterNextProtocolImpl {
+     fn tp_iternext() -> Option<ffi::iternextfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {}
+-
+ impl<T> PyIterNextProtocolImpl for T
+ where
+     T: for<'p> PyIterNextProtocol<'p>,
+diff --git a/src/class/mapping.rs b/src/class/mapping.rs
+index 616763502..df2ede958 100644
+--- a/src/class/mapping.rs
++++ b/src/class/mapping.rs
+@@ -114,11 +114,12 @@ pub trait PyMappingProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyMappingProtocolImpl for T {}
+-
+ impl<'p, T> PyMappingProtocolImpl for T
+ where
+-    T: PyMappingProtocol<'p>,
++    T: PyMappingProtocol<'p>
++        + PyMappingSetItemProtocolImpl
++        + PyMappingGetItemProtocolImpl
++        + PyMappingLenProtocolImpl,
+ {
+     #[inline]
+     fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
+@@ -153,14 +154,12 @@ where
+     }
+ }
+ 
+-trait PyMappingLenProtocolImpl {
++pub trait PyMappingLenProtocolImpl {
+     fn mp_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {}
+-
+ impl<T> PyMappingLenProtocolImpl for T
+ where
+     T: for<'p> PyMappingLenProtocol<'p>,
+@@ -171,14 +170,12 @@ where
+     }
+ }
+ 
+-trait PyMappingGetItemProtocolImpl {
++pub trait PyMappingGetItemProtocolImpl {
+     fn mp_subscript() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
+-
+ impl<T> PyMappingGetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingGetItemProtocol<'p>,
+@@ -194,14 +191,12 @@ where
+     }
+ }
+ 
+-trait PyMappingSetItemProtocolImpl {
++pub trait PyMappingSetItemProtocolImpl {
+     fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
+-
+ impl<T> PyMappingSetItemProtocolImpl for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p>,
+@@ -229,8 +224,6 @@ trait DelSetItemDispatch: Sized + for<'p> PyMappingDelItemProtocol<'p> {
+     }
+ }
+ 
+-impl<T> DelSetItemDispatch for T where T: Sized + for<'p> PyMappingDelItemProtocol<'p> {}
+-
+ impl<T> DelSetItemDispatch for T
+ where
+     T: for<'p> PyMappingSetItemProtocol<'p> + for<'p> PyMappingDelItemProtocol<'p>,
+@@ -246,6 +239,7 @@ where
+     }
+ }
+ 
++/* MJDFIXME
+ impl<T> DeplItemDipatch for T
+ where
+     T: Sized + for<'p> PyMappingDelItemProtocol<'p>,
+@@ -253,7 +247,7 @@ where
+     fn mp_del_subscript() -> Option<ffi::objobjargproc> {
+         <T as DelSetItemDispatch>::det_set_dispatch()
+     }
+-}
++}*/
+ 
+ #[doc(hidden)]
+ pub trait PyMappingContainsProtocolImpl {
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 2ee3a57d5..796a1c7ea 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -638,11 +638,60 @@ pub trait PyNumberProtocolImpl: PyObjectProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberProtocolImpl for T {}
+-
+ impl<'p, T> PyNumberProtocolImpl for T
+ where
+-    T: PyNumberProtocol<'p>,
++    T: PyNumberProtocol<'p>
++        + PyNumberAbsProtocolImpl
++        + PyNumberAddProtocolImpl
++        + PyNumberAndProtocolImpl
++        + PyNumberComplexProtocolImpl
++        + PyNumberDivmodProtocolImpl
++        + PyNumberFloatProtocolImpl
++        + PyNumberFloordivProtocolImpl
++        + PyNumberIAddProtocolImpl
++        + PyNumberIAndProtocolImpl
++        + PyNumberIFloordivProtocolImpl
++        + PyNumberILShiftProtocolImpl
++        + PyNumberIMatmulProtocolImpl
++        + PyNumberIModProtocolImpl
++        + PyNumberIMulProtocolImpl
++        + PyNumberIOrProtocolImpl
++        + PyNumberIPowProtocolImpl
++        + PyNumberIRShiftProtocolImpl
++        + PyNumberISubProtocolImpl
++        + PyNumberITruedivProtocolImpl
++        + PyNumberIXorProtocolImpl
++        + PyNumberIndexProtocolImpl
++        + PyNumberIntProtocolImpl
++        + PyNumberInvertProtocolImpl
++        + PyNumberLShiftProtocolImpl
++        + PyNumberMatmulProtocolImpl
++        + PyNumberModProtocolImpl
++        + PyNumberMulProtocolImpl
++        + PyNumberNegProtocolImpl
++        + PyNumberOrProtocolImpl
++        + PyNumberPosProtocolImpl
++        + PyNumberPowProtocolImpl
++        + PyNumberRAddProtocolImpl
++        + PyNumberRAndProtocolImpl
++        + PyNumberRDivmodProtocolImpl
++        + PyNumberRFloordivProtocolImpl
++        + PyNumberRLShiftProtocolImpl
++        + PyNumberRMatmulProtocolImpl
++        + PyNumberRModProtocolImpl
++        + PyNumberRMulProtocolImpl
++        + PyNumberROrProtocolImpl
++        + PyNumberRPowProtocolImpl
++        + PyNumberRRShiftProtocolImpl
++        + PyNumberRShiftProtocolImpl
++        + PyNumberRSubProtocolImpl
++        + PyNumberRTruedivProtocolImpl
++        + PyNumberRXorProtocolImpl
++        + PyNumberRoundProtocolImpl
++        + PyNumberSubProtocolImpl
++        + PyNumberTruedivProtocolImpl
++        + PyNumberXorProtocolImpl
++        + PyObjectProtocolImpl,
+ {
+     fn tp_as_number() -> Option<ffi::PyNumberMethods> {
+         Some(ffi::PyNumberMethods {
+@@ -742,14 +791,12 @@ where
+     }
+ }
+ 
+-trait PyNumberAddProtocolImpl {
++pub trait PyNumberAddProtocolImpl {
+     fn nb_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberAddProtocol<'p>,
+@@ -764,14 +811,12 @@ where
+     }
+ }
+ 
+-trait PyNumberSubProtocolImpl {
++pub trait PyNumberSubProtocolImpl {
+     fn nb_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberSubProtocolImpl for T
+ where
+     T: for<'p> PyNumberSubProtocol<'p>,
+@@ -786,14 +831,12 @@ where
+     }
+ }
+ 
+-trait PyNumberMulProtocolImpl {
++pub trait PyNumberMulProtocolImpl {
+     fn nb_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMulProtocol<'p>,
+@@ -808,14 +851,12 @@ where
+     }
+ }
+ 
+-trait PyNumberMatmulProtocolImpl {
++pub trait PyNumberMatmulProtocolImpl {
+     fn nb_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberMatmulProtocol<'p>,
+@@ -830,14 +871,12 @@ where
+     }
+ }
+ 
+-trait PyNumberTruedivProtocolImpl {
++pub trait PyNumberTruedivProtocolImpl {
+     fn nb_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberTruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberTruedivProtocol<'p>,
+@@ -852,14 +891,12 @@ where
+     }
+ }
+ 
+-trait PyNumberFloordivProtocolImpl {
++pub trait PyNumberFloordivProtocolImpl {
+     fn nb_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloordivProtocol<'p>,
+@@ -874,14 +911,12 @@ where
+     }
+ }
+ 
+-trait PyNumberModProtocolImpl {
++pub trait PyNumberModProtocolImpl {
+     fn nb_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberModProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberModProtocolImpl for T
+ where
+     T: for<'p> PyNumberModProtocol<'p>,
+@@ -896,14 +931,12 @@ where
+     }
+ }
+ 
+-trait PyNumberDivmodProtocolImpl {
++pub trait PyNumberDivmodProtocolImpl {
+     fn nb_divmod() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberDivmodProtocolImpl for T
+ where
+     T: for<'p> PyNumberDivmodProtocol<'p>,
+@@ -918,14 +951,12 @@ where
+     }
+ }
+ 
+-trait PyNumberPowProtocolImpl {
++pub trait PyNumberPowProtocolImpl {
+     fn nb_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberPowProtocol<'p>,
+@@ -940,14 +971,12 @@ where
+     }
+ }
+ 
+-trait PyNumberLShiftProtocolImpl {
++pub trait PyNumberLShiftProtocolImpl {
+     fn nb_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberLShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberLShiftProtocol<'p>,
+@@ -962,14 +991,12 @@ where
+     }
+ }
+ 
+-trait PyNumberRShiftProtocolImpl {
++pub trait PyNumberRShiftProtocolImpl {
+     fn nb_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberRShiftProtocol<'p>,
+@@ -984,14 +1011,12 @@ where
+     }
+ }
+ 
+-trait PyNumberAndProtocolImpl {
++pub trait PyNumberAndProtocolImpl {
+     fn nb_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberAndProtocol<'p>,
+@@ -1006,14 +1031,12 @@ where
+     }
+ }
+ 
+-trait PyNumberXorProtocolImpl {
++pub trait PyNumberXorProtocolImpl {
+     fn nb_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberXorProtocol<'p>,
+@@ -1028,14 +1051,12 @@ where
+     }
+ }
+ 
+-trait PyNumberOrProtocolImpl {
++pub trait PyNumberOrProtocolImpl {
+     fn nb_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberOrProtocol<'p>,
+@@ -1050,14 +1071,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIAddProtocolImpl {
++pub trait PyNumberIAddProtocolImpl {
+     fn nb_inplace_add() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIAddProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAddProtocol<'p>,
+@@ -1067,14 +1086,12 @@ where
+     }
+ }
+ 
+-trait PyNumberISubProtocolImpl {
++pub trait PyNumberISubProtocolImpl {
+     fn nb_inplace_subtract() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberISubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberISubProtocolImpl for T
+ where
+     T: for<'p> PyNumberISubProtocol<'p>,
+@@ -1084,14 +1101,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIMulProtocolImpl {
++pub trait PyNumberIMulProtocolImpl {
+     fn nb_inplace_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIMulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMulProtocol<'p>,
+@@ -1101,14 +1116,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIMatmulProtocolImpl {
++pub trait PyNumberIMatmulProtocolImpl {
+     fn nb_inplace_matrix_multiply() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIMatmulProtocolImpl for T
+ where
+     T: for<'p> PyNumberIMatmulProtocol<'p>,
+@@ -1118,14 +1131,12 @@ where
+     }
+ }
+ 
+-trait PyNumberITruedivProtocolImpl {
++pub trait PyNumberITruedivProtocolImpl {
+     fn nb_inplace_true_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberITruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberITruedivProtocolImpl for T
+ where
+     T: for<'p> PyNumberITruedivProtocol<'p>,
+@@ -1135,14 +1146,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIFloordivProtocolImpl {
++pub trait PyNumberIFloordivProtocolImpl {
+     fn nb_inplace_floor_divide() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIFloordivProtocolImpl for T
+ where
+     T: for<'p> PyNumberIFloordivProtocol<'p>,
+@@ -1152,14 +1161,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIModProtocolImpl {
++pub trait PyNumberIModProtocolImpl {
+     fn nb_inplace_remainder() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIModProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIModProtocolImpl for T
+ where
+     T: for<'p> PyNumberIModProtocol<'p>,
+@@ -1169,14 +1176,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIPowProtocolImpl {
++pub trait PyNumberIPowProtocolImpl {
+     fn nb_inplace_power() -> Option<ffi::ternaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIPowProtocolImpl for T
+ where
+     T: for<'p> PyNumberIPowProtocol<'p>,
+@@ -1186,14 +1191,12 @@ where
+     }
+ }
+ 
+-trait PyNumberILShiftProtocolImpl {
++pub trait PyNumberILShiftProtocolImpl {
+     fn nb_inplace_lshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberILShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberILShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberILShiftProtocol<'p>,
+@@ -1203,14 +1206,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIRShiftProtocolImpl {
++pub trait PyNumberIRShiftProtocolImpl {
+     fn nb_inplace_rshift() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIRShiftProtocolImpl for T
+ where
+     T: for<'p> PyNumberIRShiftProtocol<'p>,
+@@ -1220,14 +1221,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIAndProtocolImpl {
++pub trait PyNumberIAndProtocolImpl {
+     fn nb_inplace_and() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIAndProtocolImpl for T
+ where
+     T: for<'p> PyNumberIAndProtocol<'p>,
+@@ -1237,14 +1236,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIXorProtocolImpl {
++pub trait PyNumberIXorProtocolImpl {
+     fn nb_inplace_xor() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIXorProtocolImpl for T
+ where
+     T: for<'p> PyNumberIXorProtocol<'p>,
+@@ -1254,14 +1251,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIOrProtocolImpl {
++pub trait PyNumberIOrProtocolImpl {
+     fn nb_inplace_or() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIOrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIOrProtocolImpl for T
+ where
+     T: for<'p> PyNumberIOrProtocol<'p>,
+@@ -1397,14 +1392,12 @@ pub trait PyNumberROrProtocolImpl {
+ 
+ impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+ 
+-trait PyNumberNegProtocolImpl {
++pub trait PyNumberNegProtocolImpl {
+     fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberNegProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberNegProtocolImpl for T
+ where
+     T: for<'p> PyNumberNegProtocol<'p>,
+@@ -1420,14 +1413,12 @@ where
+     }
+ }
+ 
+-trait PyNumberPosProtocolImpl {
++pub trait PyNumberPosProtocolImpl {
+     fn nb_positive() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberPosProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberPosProtocolImpl for T
+ where
+     T: for<'p> PyNumberPosProtocol<'p>,
+@@ -1442,14 +1433,12 @@ where
+     }
+ }
+ 
+-trait PyNumberAbsProtocolImpl {
++pub trait PyNumberAbsProtocolImpl {
+     fn nb_absolute() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberAbsProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberAbsProtocolImpl for T
+ where
+     T: for<'p> PyNumberAbsProtocol<'p>,
+@@ -1464,14 +1453,12 @@ where
+     }
+ }
+ 
+-trait PyNumberInvertProtocolImpl {
++pub trait PyNumberInvertProtocolImpl {
+     fn nb_invert() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberInvertProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberInvertProtocolImpl for T
+ where
+     T: for<'p> PyNumberInvertProtocol<'p>,
+@@ -1486,14 +1473,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIntProtocolImpl {
++pub trait PyNumberIntProtocolImpl {
+     fn nb_int() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIntProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIntProtocolImpl for T
+ where
+     T: for<'p> PyNumberIntProtocol<'p>,
+@@ -1508,14 +1493,12 @@ where
+     }
+ }
+ 
+-trait PyNumberFloatProtocolImpl {
++pub trait PyNumberFloatProtocolImpl {
+     fn nb_float() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberFloatProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberFloatProtocolImpl for T
+ where
+     T: for<'p> PyNumberFloatProtocol<'p>,
+@@ -1530,14 +1513,12 @@ where
+     }
+ }
+ 
+-trait PyNumberIndexProtocolImpl {
++pub trait PyNumberIndexProtocolImpl {
+     fn nb_index() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberIndexProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ impl<T> PyNumberIndexProtocolImpl for T
+ where
+     T: for<'p> PyNumberIndexProtocol<'p>,
+@@ -1552,18 +1533,14 @@ where
+     }
+ }
+ 
+-trait PyNumberComplexProtocolImpl {
++pub trait PyNumberComplexProtocolImpl {
+     fn __complex__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyNumberComplexProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+-trait PyNumberRoundProtocolImpl {
++pub trait PyNumberRoundProtocolImpl {
+     fn __round__() -> Option<PyMethodDef> {
+         None
+     }
+ }
+-
+-impl<'p, T> PyNumberRoundProtocolImpl for T where T: PyNumberProtocol<'p> {}
+diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs
+index 9afb72c17..e04aea33b 100644
+--- a/src/class/pyasync.rs
++++ b/src/class/pyasync.rs
+@@ -100,11 +100,12 @@ pub trait PyAsyncProtocolImpl {
+     }
+ }
+ 
+-impl<T> PyAsyncProtocolImpl for T {}
+-
+ impl<'p, T> PyAsyncProtocolImpl for T
+ where
+-    T: PyAsyncProtocol<'p>,
++    T: PyAsyncProtocol<'p>
++        + PyAsyncAwaitProtocolImpl
++        + PyAsyncAiterProtocolImpl
++        + PyAsyncAnextProtocolImpl,
+ {
+     #[inline]
+     fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
+@@ -130,14 +131,12 @@ where
+     }
+ }
+ 
+-trait PyAsyncAwaitProtocolImpl {
++pub trait PyAsyncAwaitProtocolImpl {
+     fn am_await() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+-
+ impl<T> PyAsyncAwaitProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAwaitProtocol<'p>,
+@@ -153,14 +152,12 @@ where
+     }
+ }
+ 
+-trait PyAsyncAiterProtocolImpl {
++pub trait PyAsyncAiterProtocolImpl {
+     fn am_aiter() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+-
+ impl<T> PyAsyncAiterProtocolImpl for T
+ where
+     T: for<'p> PyAsyncAiterProtocol<'p>,
+@@ -176,14 +173,12 @@ where
+     }
+ }
+ 
+-trait PyAsyncAnextProtocolImpl {
++pub trait PyAsyncAnextProtocolImpl {
+     fn am_anext() -> Option<ffi::unaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {}
+-
+ mod anext {
+     use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
+     use crate::callback::CallbackConverter;
+diff --git a/src/class/sequence.rs b/src/class/sequence.rs
+index 23771ba0b..840c11b97 100644
+--- a/src/class/sequence.rs
++++ b/src/class/sequence.rs
+@@ -139,11 +139,19 @@ pub trait PySequenceProtocolImpl {
+     }
+ }
+ 
+-impl<T> PySequenceProtocolImpl for T {}
+-
+ impl<'p, T> PySequenceProtocolImpl for T
+ where
+-    T: PySequenceProtocol<'p>,
++    T: PySequenceProtocol<'p>
++        + PySequenceConcatProtocolImpl
++        + PySequenceContainsProtocolImpl
++        + PySequenceGetItemProtocolImpl
++        + PySequenceInplaceConcatProtocolImpl
++        + PySequenceInplaceRepeatProtocolImpl
++        + PySequenceLenProtocolImpl
++        + PySequenceRepeatProtocolImpl
++        + sq_ass_item_impl::SetItem
++        + sq_ass_item_impl::DelItem
++        + sq_ass_item_impl::DelSetItem,
+ {
+     fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
+         Some(ffi::PySequenceMethods {
+@@ -161,14 +169,12 @@ where
+     }
+ }
+ 
+-trait PySequenceLenProtocolImpl {
++pub trait PySequenceLenProtocolImpl {
+     fn sq_length() -> Option<ffi::lenfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceLenProtocolImpl for T
+ where
+     T: for<'p> PySequenceLenProtocol<'p>,
+@@ -178,14 +184,12 @@ where
+     }
+ }
+ 
+-trait PySequenceGetItemProtocolImpl {
++pub trait PySequenceGetItemProtocolImpl {
+     fn sq_item() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceGetItemProtocolImpl for T
+ where
+     T: for<'p> PySequenceGetItemProtocol<'p>,
+@@ -214,7 +218,7 @@ mod sq_ass_item_impl {
+     /// item assignment and deletion.
+     pub(super) fn sq_ass_item<'p, T>() -> Option<ffi::ssizeobjargproc>
+     where
+-        T: PySequenceProtocol<'p>,
++        T: PySequenceProtocol<'p> + SetItem + DelItem + DelSetItem,
+     {
+         if let Some(del_set_item) = T::del_set_item() {
+             Some(del_set_item)
+@@ -227,15 +231,8 @@ mod sq_ass_item_impl {
+         }
+     }
+ 
+-    trait SetItem {
+-        fn set_item() -> Option<ffi::ssizeobjargproc>;
+-    }
+-
+-    impl<'p, T> SetItem for T
+-    where
+-        T: PySequenceProtocol<'p>,
+-    {
+-        default fn set_item() -> Option<ffi::ssizeobjargproc> {
++    pub trait SetItem {
++        fn set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+@@ -282,14 +279,12 @@ mod sq_ass_item_impl {
+         }
+     }
+ 
+-    trait DelItem {
++    pub trait DelItem {
+         fn del_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> DelItem for T where T: PySequenceProtocol<'p> {}
+-
+     impl<T> DelItem for T
+     where
+         T: for<'p> PySequenceDelItemProtocol<'p>,
+@@ -328,14 +323,12 @@ mod sq_ass_item_impl {
+         }
+     }
+ 
+-    trait DelSetItem {
++    pub trait DelSetItem {
+         fn del_set_item() -> Option<ffi::ssizeobjargproc> {
+             None
+         }
+     }
+ 
+-    impl<'p, T> DelSetItem for T where T: PySequenceProtocol<'p> {}
+-
+     impl<T> DelSetItem for T
+     where
+         T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
+@@ -375,14 +368,12 @@ mod sq_ass_item_impl {
+     }
+ }
+ 
+-trait PySequenceContainsProtocolImpl {
++pub trait PySequenceContainsProtocolImpl {
+     fn sq_contains() -> Option<ffi::objobjproc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceContainsProtocolImpl for T
+ where
+     T: for<'p> PySequenceContainsProtocol<'p>,
+@@ -398,14 +389,12 @@ where
+     }
+ }
+ 
+-trait PySequenceConcatProtocolImpl {
++pub trait PySequenceConcatProtocolImpl {
+     fn sq_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceConcatProtocol<'p>,
+@@ -420,14 +409,12 @@ where
+     }
+ }
+ 
+-trait PySequenceRepeatProtocolImpl {
++pub trait PySequenceRepeatProtocolImpl {
+     fn sq_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceRepeatProtocol<'p>,
+@@ -442,14 +429,12 @@ where
+     }
+ }
+ 
+-trait PySequenceInplaceConcatProtocolImpl {
++pub trait PySequenceInplaceConcatProtocolImpl {
+     fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceInplaceConcatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceConcatProtocol<'p>,
+@@ -464,14 +449,12 @@ where
+     }
+ }
+ 
+-trait PySequenceInplaceRepeatProtocolImpl {
++pub trait PySequenceInplaceRepeatProtocolImpl {
+     fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
+         None
+     }
+ }
+ 
+-impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
+-
+ impl<T> PySequenceInplaceRepeatProtocolImpl for T
+ where
+     T: for<'p> PySequenceInplaceRepeatProtocol<'p>,
+diff --git a/src/conversion.rs b/src/conversion.rs
+index a3bca1175..76094694d 100644
+--- a/src/conversion.rs
++++ b/src/conversion.rs
+@@ -110,6 +110,7 @@ pub trait ToBorrowedObject: ToPyObject {
+ 
+ impl<T> ToBorrowedObject for T where T: ToPyObject {}
+ 
++/*MJDFIXME
+ impl<T> ToBorrowedObject for T
+ where
+     T: ToPyObject + AsPyPointer,
+@@ -120,7 +121,7 @@ where
+     {
+         f(self.as_ptr())
+     }
+-}
++}*/
+ 
+ /// Similar to [std::convert::From], just that it requires a gil token.
+ pub trait FromPy<T>: Sized {
+@@ -139,7 +140,7 @@ impl<T, U> IntoPy<U> for T
+ where
+     U: FromPy<T>,
+ {
+-    default fn into_py(self, py: Python) -> U {
++    fn into_py(self, py: Python) -> U {
+         U::from_py(self, py)
+     }
+ }
+@@ -243,7 +244,7 @@ where
+     T: PyTryFrom<'a>,
+ {
+     #[inline]
+-    default fn extract(ob: &'a PyAny) -> PyResult<&'a T> {
++    fn extract(ob: &'a PyAny) -> PyResult<&'a T> {
+         Ok(T::try_from(ob)?)
+     }
+ }
+@@ -254,7 +255,7 @@ where
+     T: PyTryFrom<'a>,
+ {
+     #[inline]
+-    default fn extract(ob: &'a PyAny) -> PyResult<&'a mut T> {
++    fn extract(ob: &'a PyAny) -> PyResult<&'a mut T> {
+         Ok(T::try_from_mut(ob)?)
+     }
+ }
+diff --git a/src/instance.rs b/src/instance.rs
+index 68bd45ec3..ccbd07c57 100644
+--- a/src/instance.rs
++++ b/src/instance.rs
+@@ -358,7 +358,7 @@ impl<T> Py<T> {
+ }
+ 
+ /// Specialization workaround
+-trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
++pub trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
+     fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe {
+             let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
+@@ -373,8 +373,6 @@ trait AsPyRefDispatch<T: PyTypeInfo>: AsPyPointer {
+     }
+ }
+ 
+-impl<T: PyTypeInfo> AsPyRefDispatch<T> for Py<T> {}
+-
+ impl<T: PyTypeInfo + PyNativeType> AsPyRefDispatch<T> for Py<T> {
+     fn as_ref_dispatch(&self, _py: Python) -> &T {
+         unsafe { &*(self as *const instance::Py<T> as *const T) }
+@@ -387,6 +385,7 @@ impl<T: PyTypeInfo + PyNativeType> AsPyRefDispatch<T> for Py<T> {
+ impl<T> AsPyRef<T> for Py<T>
+ where
+     T: PyTypeInfo,
++    Py<T>: AsPyRefDispatch<T>,
+ {
+     #[inline]
+     fn as_ref(&self, py: Python) -> PyRef<T> {
+@@ -538,7 +537,7 @@ pub struct ManagedPyRef<'p, T: ToPyObject + ?Sized> {
+ 
+ /// This should eventually be replaced with a generic `IntoPy` trait impl by figuring
+ /// out the correct lifetime annotation to make the compiler happy
+-impl<'p, T: ToPyObject> ManagedPyRef<'p, T> {
++impl<'p, T: ToPyObject + ManagedPyRefDispatch> ManagedPyRef<'p, T> {
+     pub fn from_to_pyobject(py: Python<'p>, to_pyobject: &T) -> Self {
+         to_pyobject.to_managed_py_ref(py)
+     }
+@@ -577,7 +576,6 @@ pub trait ManagedPyRefDispatch: ToPyObject {
+ ///
+ /// Note that the actual implementations are part of the trait declaration to avoid
+ /// a specialization error
+-impl<T: ToPyObject + ?Sized> ManagedPyRefDispatch for T {}
+ 
+ /// Case 2: It's an object on the python heap, we're just storing a borrowed pointer.
+ /// The object we're getting is an owned pointer, it might have it's own drop impl.
+@@ -595,13 +593,14 @@ impl<T: ToPyObject + AsPyPointer + ?Sized> ManagedPyRefDispatch for T {
+     fn drop_impl(_: &mut ManagedPyRef<T>) {}
+ }
+ 
+-impl<'p, T: ToPyObject + ?Sized> Drop for ManagedPyRef<'p, T> {
++/* MJDFIXME
++impl<'p, T: ToPyObject + ?Sized + AsPyPointer> Drop for ManagedPyRef<'p, T> {
+     /// Uses the internal [ManagedPyRefDispatch] trait to get the right drop impl without causing
+     /// a specialization error
+     fn drop(&mut self) {
+         ManagedPyRefDispatch::drop_impl(self);
+     }
+-}
++}*/
+ 
+ #[cfg(test)]
+ mod test {
+diff --git a/src/lib.rs b/src/lib.rs
+index b5cb5402a..65fb611db 100755
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -1,5 +1,3 @@
+-#![feature(specialization)]
+-
+ //! Rust bindings to the Python interpreter.
+ //!
+ //! Look at [the guide](https://pyo3.rs/) for a detailed introduction.
+diff --git a/src/object.rs b/src/object.rs
+index 128ef8377..5d46bfc71 100644
+--- a/src/object.rs
++++ b/src/object.rs
+@@ -171,7 +171,7 @@ impl PyObject {
+     /// This is equivalent to the Python expression 'self.attr_name'.
+     pub fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject>
+     where
+-        N: ToPyObject,
++        N: ToPyObject + ToBorrowedObject,
+     {
+         attr_name.with_borrowed_ptr(py, |attr_name| unsafe {
+             PyObject::from_owned_ptr_or_err(py, ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
+diff --git a/src/type_object.rs b/src/type_object.rs
+index 4cdd2d8db..3038afb40 100644
+--- a/src/type_object.rs
++++ b/src/type_object.rs
+@@ -2,6 +2,7 @@
+ 
+ //! Python type object information
+ 
++use crate::class::gc::PyGCProtocolImpl;
+ use crate::class::methods::PyMethodDefType;
+ use crate::err::{PyErr, PyResult};
+ use crate::instance::{Py, PyNativeType};
+@@ -249,7 +250,19 @@ pub unsafe trait PyTypeObject {
+ 
+ unsafe impl<T> PyTypeObject for T
+ where
+-    T: PyTypeInfo + PyMethodsProtocol + PyObjectAlloc,
++    T: PyTypeInfo
++        + PyMethodsProtocol
++        + PyObjectAlloc
++        + class::gc::PyGCProtocolImpl
++        + class::context::PyContextProtocolImpl
++        + class::descr::PyDescrProtocolImpl
++        + class::iter::PyIterProtocolImpl
++        + class::basic::PyObjectProtocolImpl
++        + class::number::PyNumberProtocolImpl
++        + class::mapping::PyMappingProtocolImpl
++        + class::sequence::PySequenceProtocolImpl
++        + class::pyasync::PyAsyncProtocolImpl
++        + class::buffer::PyBufferProtocolImpl,
+ {
+     fn init_type() -> NonNull<ffi::PyTypeObject> {
+         let type_object = unsafe { <Self as PyTypeInfo>::type_object() };
+@@ -297,7 +310,19 @@ impl<T> PyTypeCreate for T where T: PyObjectAlloc + PyTypeObject + Sized {}
+ #[cfg(not(Py_LIMITED_API))]
+ pub fn initialize_type<T>(py: Python, module_name: Option<&str>) -> PyResult<*mut ffi::PyTypeObject>
+ where
+-    T: PyObjectAlloc + PyTypeInfo + PyMethodsProtocol,
++    T: PyObjectAlloc
++        + PyTypeInfo
++        + PyMethodsProtocol
++        + class::gc::PyGCProtocolImpl
++        + class::context::PyContextProtocolImpl
++        + class::descr::PyDescrProtocolImpl
++        + class::iter::PyIterProtocolImpl
++        + class::basic::PyObjectProtocolImpl
++        + class::number::PyNumberProtocolImpl
++        + class::mapping::PyMappingProtocolImpl
++        + class::sequence::PySequenceProtocolImpl
++        + class::pyasync::PyAsyncProtocolImpl
++        + class::buffer::PyBufferProtocolImpl,
+ {
+     let type_object: &mut ffi::PyTypeObject = unsafe { T::type_object() };
+     let base_type_object: &mut ffi::PyTypeObject =
+@@ -438,12 +463,25 @@ fn py_class_flags<T: PyTypeInfo>(type_object: &mut ffi::PyTypeObject) {
+     }
+ }
+ 
+-fn py_class_method_defs<T: PyMethodsProtocol>() -> (
++fn py_class_method_defs<T>() -> (
+     Option<ffi::newfunc>,
+     Option<ffi::initproc>,
+     Option<ffi::PyCFunctionWithKeywords>,
+     Vec<ffi::PyMethodDef>,
+-) {
++)
++where
++    T: PyMethodsProtocol
++        + class::gc::PyGCProtocolImpl
++        + class::context::PyContextProtocolImpl
++        + class::descr::PyDescrProtocolImpl
++        + class::iter::PyIterProtocolImpl
++        + class::basic::PyObjectProtocolImpl
++        + class::number::PyNumberProtocolImpl
++        + class::mapping::PyMappingProtocolImpl
++        + class::sequence::PySequenceProtocolImpl
++        + class::pyasync::PyAsyncProtocolImpl
++        + class::buffer::PyBufferProtocolImpl,
++{
+     let mut defs = Vec::new();
+     let mut call = None;
+     let mut new = None;
+@@ -500,7 +538,9 @@ fn py_class_method_defs<T: PyMethodsProtocol>() -> (
+     (new, init, call, defs)
+ }
+ 
+-fn py_class_async_methods<T>(defs: &mut Vec<ffi::PyMethodDef>) {
++fn py_class_async_methods<T: class::pyasync::PyAsyncProtocolImpl>(
++    defs: &mut Vec<ffi::PyMethodDef>,
++) {
+     for def in <T as class::pyasync::PyAsyncProtocolImpl>::methods() {
+         defs.push(def.as_method_def());
+     }
+diff --git a/src/types/sequence.rs b/src/types/sequence.rs
+index d81ffbdd9..08d38b072 100644
+--- a/src/types/sequence.rs
++++ b/src/types/sequence.rs
+@@ -244,11 +244,12 @@ impl<'a, T> FromPyObject<'a> for Vec<T>
+ where
+     T: FromPyObject<'a>,
+ {
+-    default fn extract(obj: &'a PyAny) -> PyResult<Self> {
++    fn extract(obj: &'a PyAny) -> PyResult<Self> {
+         extract_sequence(obj)
+     }
+ }
+ 
++/* MJDFIXME
+ impl<'source, T> FromPyObject<'source> for Vec<T>
+ where
+     for<'a> T: FromPyObject<'a> + buffer::Element + Copy,
+@@ -267,7 +268,7 @@ where
+         // fall back to sequence protocol
+         extract_sequence(obj)
+     }
+-}
++}*/
+ 
+ fn extract_sequence<'s, T>(obj: &'s PyAny) -> PyResult<Vec<T>>
+ where
diff --git a/srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch b/srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
new file mode 100644
index 00000000000..8e8e4e9cff7
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0013-specialization-b0561da60c6c00fc8cd930efa34113a602a830e2.patch
@@ -0,0 +1,69 @@
+From b0561da60c6c00fc8cd930efa34113a602a830e2 Mon Sep 17 00:00:00 2001
+From: Donlon <mdonlon@treyarch.com>
+Date: Wed, 30 Oct 2019 07:02:06 -0700
+Subject: [PATCH] Stubbed out a bunch of tests
+
+---
+ src/instance.rs                                  |  3 ++-
+ tests/test_class_basics.rs                       | 16 ++++++++++++++--
+
+diff --git a/src/instance.rs b/src/instance.rs
+index ccbd07c57..af0cd4382 100644
+--- a/src/instance.rs
++++ b/src/instance.rs
+@@ -602,6 +602,7 @@ impl<'p, T: ToPyObject + ?Sized + AsPyPointer> Drop for ManagedPyRef<'p, T> {
+     }
+ }*/
+ 
++/* MJDFIXME
+ #[cfg(test)]
+ mod test {
+     use crate::ffi;
+@@ -640,4 +641,4 @@ mod test {
+             ffi::Py_DECREF(ptr);
+         }
+     }
+-}
++}*/
+diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs
+index 00e2674e6..53e4df51e 100644
+--- a/tests/test_class_basics.rs
++++ b/tests/test_class_basics.rs
+@@ -1,3 +1,4 @@
++use pyo3::class;
+ use pyo3::prelude::*;
+ use pyo3::py_run;
+ use pyo3::type_object::initialize_type;
+@@ -7,6 +8,17 @@ mod common;
+ #[pyclass]
+ struct EmptyClass {}
+ 
++impl class::gc::PyGCProtocolImpl for EmptyClass {}
++impl class::buffer::PyBufferProtocolImpl for EmptyClass {}
++impl class::context::PyContextProtocolImpl for EmptyClass {}
++impl class::iter::PyIterProtocolImpl for EmptyClass {}
++impl class::descr::PyDescrProtocolImpl for EmptyClass {}
++impl class::basic::PyObjectProtocolImpl for EmptyClass {}
++impl class::number::PyNumberProtocolImpl for EmptyClass {}
++impl class::mapping::PyMappingProtocolImpl for EmptyClass {}
++impl class::sequence::PySequenceProtocolImpl for EmptyClass {}
++impl class::pyasync::PyAsyncProtocolImpl for EmptyClass {}
++
+ #[test]
+ fn empty_class() {
+     let gil = Python::acquire_gil();
+@@ -17,7 +29,7 @@ fn empty_class() {
+ 
+     py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
+ }
+-
++/*
+ /// Line1
+ ///Line2
+ ///  Line3
+@@ -77,4 +89,4 @@ fn empty_class_in_module() {
+     initialize_type::<EmptyClassInModule>(py, Some("test_module.nested")).unwrap();
+     let module: String = ty.getattr("__module__").unwrap().extract().unwrap();
+     assert_eq!(module, "test_module.nested");
+-}
++}*/
diff --git a/srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch b/srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch
new file mode 100644
index 00000000000..1d00862ff05
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0014-specialization-c7e52948d9147689701a24de2fcdffafc32ebe62.patch
@@ -0,0 +1,93 @@
+From c7e52948d9147689701a24de2fcdffafc32ebe62 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Wed, 30 Oct 2019 22:12:49 -0700
+Subject: [PATCH] pyclass protocols attribute parsing
+
+---
+ .vscode/settings.json              |  4 ++++
+ pyo3-derive-backend/src/pyclass.rs | 32 ++++++++++++++++++++++++++++++
+ tests/test_class_basics.rs         |  2 +-
+ 3 files changed, 37 insertions(+), 1 deletion(-)
+ create mode 100644 .vscode/settings.json
+
+diff --git a/.vscode/settings.json b/.vscode/settings.json
+new file mode 100644
+index 000000000..2b5f84ecc
+--- /dev/null
++++ b/.vscode/settings.json
+@@ -0,0 +1,4 @@
++{
++    "rust.all_targets": false,
++    "editor.formatOnSave": true
++}
+\ No newline at end of file
+diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs
+index 1f902a959..3ac5d4cde 100644
+--- a/pyo3-derive-backend/src/pyclass.rs
++++ b/pyo3-derive-backend/src/pyclass.rs
+@@ -16,6 +16,7 @@ pub struct PyClassArgs {
+     pub flags: Vec<syn::Expr>,
+     pub base: syn::TypePath,
+     pub module: Option<syn::LitStr>,
++    pub protocols: Vec<syn::Ident>,
+ }
+ 
+ impl Parse for PyClassArgs {
+@@ -40,6 +41,7 @@ impl Default for PyClassArgs {
+             // are no other flags
+             flags: vec![parse_quote! {0}],
+             base: parse_quote! {pyo3::types::PyAny},
++            protocols: Vec::new(),
+         }
+     }
+ }
+@@ -110,6 +112,36 @@ impl PyClassArgs {
+                     ));
+                 }
+             },
++            "protocols" => match *assign.right {
++                syn::Expr::Array(syn::ExprArray { ref elems, .. }) => {
++                    for elem in elems.iter() {
++                        match elem {
++                            syn::Expr::Path(syn::ExprPath { ref path, .. }) => {
++                                if path.segments.len() == 1 {
++                                    self.protocols.push(path.segments[0].ident.clone());
++                                } else {
++                                    return Err(syn::Error::new_spanned(
++                                        path.clone(),
++                                        "Expected an unqualified name for protocol",
++                                    ));
++                                }
++                            }
++                            _ => {
++                                return Err(syn::Error::new_spanned(
++                                    elem.clone(),
++                                    "Wrong format for protocol entry",
++                                ));
++                            }
++                        }
++                    }
++                }
++                _ => {
++                    return Err(syn::Error::new_spanned(
++                        *assign.right.clone(),
++                        "Wrong format for protocol",
++                    ));
++                }
++            },
+             _ => {
+                 return Err(syn::Error::new_spanned(
+                     *assign.left.clone(),
+diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs
+index 53e4df51e..c8e1a42df 100644
+--- a/tests/test_class_basics.rs
++++ b/tests/test_class_basics.rs
+@@ -5,7 +5,7 @@ use pyo3::type_object::initialize_type;
+ 
+ mod common;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PySequenceProtocol])]
+ struct EmptyClass {}
+ 
+ impl class::gc::PyGCProtocolImpl for EmptyClass {}
diff --git a/srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch b/srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch
new file mode 100644
index 00000000000..b7436efdee9
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0015-specialization-81f2c30b15f467c9f5ab139564be0099fba5b27f.patch
@@ -0,0 +1,159 @@
+From 81f2c30b15f467c9f5ab139564be0099fba5b27f Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Thu, 31 Oct 2019 22:40:33 -0700
+Subject: [PATCH] Add lookup function for protocol defs
+
+---
+ pyo3-derive-backend/src/defs.rs    | 40 ++++++++++++++++++++++--------
+ pyo3-derive-backend/src/pyproto.rs | 15 +++--------
+ 2 files changed, 33 insertions(+), 22 deletions(-)
+
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index 04c1fa3b0..52024c12b 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -7,12 +7,22 @@ pub struct Proto {
+     pub py_methods: &'static [PyMethod],
+ }
+ 
++impl Proto {
++    pub fn protocol_trait(&self) -> String {
++        format!("Py{}Protocol", self.name)
++    }
++
++    pub fn _impl_trait(&self) -> String {
++        format!("Py{}ProtocolImpl", self.name)
++    }
++}
++
+ pub struct PyMethod {
+     pub name: &'static str,
+     pub proto: &'static str,
+ }
+ 
+-pub const OBJECT: Proto = Proto {
++const OBJECT: Proto = Proto {
+     name: "Object",
+     methods: &[
+         MethodProto::Binary {
+@@ -88,7 +98,7 @@ pub const OBJECT: Proto = Proto {
+     ],
+ };
+ 
+-pub const ASYNC: Proto = Proto {
++const ASYNC: Proto = Proto {
+     name: "Async",
+     methods: &[
+         MethodProto::Unary {
+@@ -131,7 +141,7 @@ pub const ASYNC: Proto = Proto {
+     ],
+ };
+ 
+-pub const BUFFER: Proto = Proto {
++const BUFFER: Proto = Proto {
+     name: "Buffer",
+     methods: &[
+         MethodProto::Unary {
+@@ -148,7 +158,7 @@ pub const BUFFER: Proto = Proto {
+     py_methods: &[],
+ };
+ 
+-pub const CONTEXT: Proto = Proto {
++const CONTEXT: Proto = Proto {
+     name: "Context",
+     methods: &[
+         MethodProto::Unary {
+@@ -176,7 +186,7 @@ pub const CONTEXT: Proto = Proto {
+     ],
+ };
+ 
+-pub const GC: Proto = Proto {
++const GC: Proto = Proto {
+     name: "GC",
+     methods: &[
+         MethodProto::Free {
+@@ -191,7 +201,7 @@ pub const GC: Proto = Proto {
+     py_methods: &[],
+ };
+ 
+-pub const DESCR: Proto = Proto {
++const DESCR: Proto = Proto {
+     name: "Descriptor",
+     methods: &[
+         MethodProto::Ternary {
+@@ -233,7 +243,7 @@ pub const DESCR: Proto = Proto {
+     ],
+ };
+ 
+-pub const ITER: Proto = Proto {
++const ITER: Proto = Proto {
+     name: "Iter",
+     py_methods: &[],
+     methods: &[
+@@ -250,7 +260,7 @@ pub const ITER: Proto = Proto {
+     ],
+ };
+ 
+-pub const MAPPING: Proto = Proto {
++const MAPPING: Proto = Proto {
+     name: "Mapping",
+     methods: &[
+         MethodProto::Unary {
+@@ -310,7 +320,7 @@ pub const MAPPING: Proto = Proto {
+     ],
+ };
+ 
+-pub const SEQ: Proto = Proto {
++const SEQ: Proto = Proto {
+     name: "Sequence",
+     methods: &[
+         MethodProto::Unary {
+@@ -371,7 +381,7 @@ pub const SEQ: Proto = Proto {
+     py_methods: &[],
+ };
+ 
+-pub const NUM: Proto = Proto {
++const NUM: Proto = Proto {
+     name: "Number",
+     methods: &[
+         MethodProto::BinaryS {
+@@ -750,3 +760,13 @@ pub const NUM: Proto = Proto {
+         },
+     ],
+ };
++
++const PROTOCOLS: &[Proto] = &[
++    OBJECT, ASYNC, MAPPING, ITER, CONTEXT, SEQ, NUM, DESCR, BUFFER, GC,
++];
++
++pub fn find_protocol(protocol_trait: &str) -> Option<&'static Proto> {
++    PROTOCOLS
++        .iter()
++        .find(|p| p.protocol_trait() == protocol_trait)
++}
+diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs
+index c0921bcbb..41f1deaf9 100644
+--- a/pyo3-derive-backend/src/pyproto.rs
++++ b/pyo3-derive-backend/src/pyproto.rs
+@@ -12,18 +12,9 @@ use quote::ToTokens;
+ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> syn::Result<TokenStream> {
+     if let Some((_, ref mut path, _)) = ast.trait_ {
+         let proto = if let Some(ref mut segment) = path.segments.last() {
+-            match segment.ident.to_string().as_str() {
+-                "PyObjectProtocol" => &defs::OBJECT,
+-                "PyAsyncProtocol" => &defs::ASYNC,
+-                "PyMappingProtocol" => &defs::MAPPING,
+-                "PyIterProtocol" => &defs::ITER,
+-                "PyContextProtocol" => &defs::CONTEXT,
+-                "PySequenceProtocol" => &defs::SEQ,
+-                "PyNumberProtocol" => &defs::NUM,
+-                "PyDescrProtocol" => &defs::DESCR,
+-                "PyBufferProtocol" => &defs::BUFFER,
+-                "PyGCProtocol" => &defs::GC,
+-                _ => {
++            match defs::find_protocol(segment.ident.to_string().as_str()) {
++                Some(p) => p,
++                None => {
+                     return Err(syn::Error::new_spanned(
+                         path,
+                         "#[pyproto] can not be used with this block",
diff --git a/srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch b/srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch
new file mode 100644
index 00000000000..615bd92790b
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0016-specialization-eb617c2ad89dad6be5cf454fe0012d9aba9e60b2.patch
@@ -0,0 +1,1387 @@
+From eb617c2ad89dad6be5cf454fe0012d9aba9e60b2 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Sun, 3 Nov 2019 18:06:54 -0800
+Subject: [PATCH] Proc macros now add the necessary default implementations
+
+---
+ .vscode/settings.json                         |   3 +-
+ pyo3-derive-backend/src/defs.rs               | 137 ++++++++++++++++--
+ pyo3-derive-backend/src/func.rs               |  37 +++++
+ pyo3-derive-backend/src/pyclass.rs            |  34 ++++-
+ pyo3-derive-backend/src/pyproto.rs            |  91 +++++++-----
+ src/buffer.rs                                 |   5 +-
+ src/class/buffer.rs                           |   6 +
+ src/lib.rs                                    |   4 +-
+ tests/test_arithmetics.rp                     |  12 +-
+ ...er_protocol.rp => test_buffer_protocol.rs} |   2 +-
+ tests/{test_bytes.rp => test_bytes.rs}        |   0
+ tests/test_class_basics.rs                    |  17 +--
+ .../{test_class_new.rp => test_class_new.rs}  |   0
+ ...compile_error.rp => test_compile_error.rs} |   0
+ tests/test_datetime.rp                        |   2 -
+ tests/{test_gc.rp => test_gc.rs}              |   4 +-
+ ...getter_setter.rp => test_getter_setter.rs} |   0
+ tests/{test_sequence.rp => test_sequence.rs}  |   2 +-
+ tests/{test_string.rp => test_string.rs}      |   0
+ ...rguments.rp => test_variable_arguments.rs} |   0
+ tests/{test_various.rp => test_various.rs}    |   3 +-
+ 21 files changed, 280 insertions(+), 79 deletions(-)
+ rename tests/{test_buffer_protocol.rp => test_buffer_protocol.rs} (98%)
+ rename tests/{test_bytes.rp => test_bytes.rs} (100%)
+ rename tests/{test_class_new.rp => test_class_new.rs} (100%)
+ rename tests/{test_compile_error.rp => test_compile_error.rs} (100%)
+ rename tests/{test_gc.rp => test_gc.rs} (98%)
+ rename tests/{test_getter_setter.rp => test_getter_setter.rs} (100%)
+ rename tests/{test_sequence.rp => test_sequence.rs} (99%)
+ rename tests/{test_string.rp => test_string.rs} (100%)
+ rename tests/{test_variable_arguments.rp => test_variable_arguments.rs} (100%)
+ rename tests/{test_various.rp => test_various.rs} (98%)
+
+diff --git a/.vscode/settings.json b/.vscode/settings.json
+index 2b5f84ecc..38768fd72 100644
+--- a/.vscode/settings.json
++++ b/.vscode/settings.json
+@@ -1,4 +1,5 @@
+ {
+     "rust.all_targets": false,
+-    "editor.formatOnSave": true
++    "editor.formatOnSave": true,
++    "rust-analyzer.enableEnhancedTyping": false
+ }
+\ No newline at end of file
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index 52024c12b..06c1c6754 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -3,20 +3,12 @@ use crate::func::MethodProto;
+ 
+ pub struct Proto {
+     pub name: &'static str,
++    pub protocol_trait: &'static str,
++    pub impl_trait: &'static str,
+     pub methods: &'static [MethodProto],
+     pub py_methods: &'static [PyMethod],
+ }
+ 
+-impl Proto {
+-    pub fn protocol_trait(&self) -> String {
+-        format!("Py{}Protocol", self.name)
+-    }
+-
+-    pub fn _impl_trait(&self) -> String {
+-        format!("Py{}ProtocolImpl", self.name)
+-    }
+-}
+-
+ pub struct PyMethod {
+     pub name: &'static str,
+     pub proto: &'static str,
+@@ -24,12 +16,15 @@ pub struct PyMethod {
+ 
+ const OBJECT: Proto = Proto {
+     name: "Object",
++    protocol_trait: "pyo3::class::basic::PyObjectProtocol",
++    impl_trait: "pyo3::class::basic::PyObjectProtocolImpl",
+     methods: &[
+         MethodProto::Binary {
+             name: "__getattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
++            default: "pyo3::class::basic::PyObjectGetAttrProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__setattr__",
+@@ -37,49 +32,58 @@ const OBJECT: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
++            default: "pyo3::class::basic::PyObjectSetAttrProtocol",
+         },
+         MethodProto::Binary {
+             name: "__delattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
++            default: "pyo3::class::basic::PyObjectDelAttrProtocol",
+         },
+         MethodProto::Unary {
+             name: "__str__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectStrProtocol",
++            default: "pyo3::class::basic::PyObjectStrProtocol",
+         },
+         MethodProto::Unary {
+             name: "__repr__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectReprProtocol",
++            default: "pyo3::class::basic::PyObjectReprProtocol",
+         },
+         MethodProto::Binary {
+             name: "__format__",
+             arg: "Format",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectFormatProtocol",
++            default: "pyo3::class::basic::PyObjectFormatProtocol",
+         },
+         MethodProto::Unary {
+             name: "__hash__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectHashProtocol",
++            default: "pyo3::class::basic::PyObjectHashProtocol",
+         },
+         MethodProto::Unary {
+             name: "__bytes__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectBytesProtocol",
++            default: "pyo3::class::basic::PyObjectBytesProtocol",
+         },
+         MethodProto::Unary {
+             name: "__bool__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectBoolProtocol",
++            default: "pyo3::class::basic::PyObjectBoolProtocol",
+         },
+         MethodProto::Binary {
+             name: "__richcmp__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
++            default: "pyo3::class::basic::PyObjectRichcmpProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -100,26 +104,32 @@ const OBJECT: Proto = Proto {
+ 
+ const ASYNC: Proto = Proto {
+     name: "Async",
++    protocol_trait: "pyo3::class::pyasync::PyAsyncProtocol",
++    impl_trait: "pyo3::class::pyasync::PyAsyncProtocolImpl",
+     methods: &[
+         MethodProto::Unary {
+             name: "__await__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aiter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAiterProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAiterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__anext__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAnextProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAnextProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aenter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAenterProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAenterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__aexit__",
+@@ -127,6 +137,7 @@ const ASYNC: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::pyasync::PyAsyncAexitProtocol",
++            default: "pyo3::class::pyasync::PyAsyncAexitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -143,16 +154,20 @@ const ASYNC: Proto = Proto {
+ 
+ const BUFFER: Proto = Proto {
+     name: "Buffer",
++    protocol_trait: "pyo3::class::buffer::PyBufferProtocol",
++    impl_trait: "pyo3::class::buffer::PyBufferProtocolImpl",
+     methods: &[
+         MethodProto::Unary {
+             name: "bf_getbuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferGetBufferProtocol",
++            default: "pyo3::class::buffer::PyBufferGetBufferProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "bf_releasebuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferReleaseBufferProtocol",
++            default: "pyo3::class::buffer::PyBufferReleaseBufferProtocolImpl",
+         },
+     ],
+     py_methods: &[],
+@@ -160,11 +175,14 @@ const BUFFER: Proto = Proto {
+ 
+ const CONTEXT: Proto = Proto {
+     name: "Context",
++    protocol_trait: "pyo3::class::context::PyContextProtocol",
++    impl_trait: "pyo3::class::context::PyContextProtocolImpl",
+     methods: &[
+         MethodProto::Unary {
+             name: "__enter__",
+             pyres: true,
+             proto: "pyo3::class::context::PyContextEnterProtocol",
++            default: "pyo3::class::context::PyContextEnterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__exit__",
+@@ -172,6 +190,7 @@ const CONTEXT: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::context::PyContextExitProtocol",
++            default: "pyo3::class::context::PyContextExitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -188,14 +207,19 @@ const CONTEXT: Proto = Proto {
+ 
+ const GC: Proto = Proto {
+     name: "GC",
++    protocol_trait: "pyo3::class::gc::PyGCProtocol",
++    impl_trait: "pyo3::class::gc::PyGCProtocolImpl",
++
+     methods: &[
+         MethodProto::Free {
+             name: "__traverse__",
+             proto: "pyo3::class::gc::PyGCTraverseProtocol",
++            default: "pyo3::class::gc::PyGCTraverseProtocolImpl",
+         },
+         MethodProto::Free {
+             name: "__clear__",
+             proto: "pyo3::class::gc::PyGCClearProtocol",
++            default: "pyo3::class::gc::PyGCClearProtocolImpl",
+         },
+     ],
+     py_methods: &[],
+@@ -203,6 +227,9 @@ const GC: Proto = Proto {
+ 
+ const DESCR: Proto = Proto {
+     name: "Descriptor",
++    protocol_trait: "pyo3::class::descr::PyDescrProtocol",
++    impl_trait: "pyo3::class::descr::PyDescrProtocolImpl",
++
+     methods: &[
+         MethodProto::Ternary {
+             name: "__get__",
+@@ -210,6 +237,7 @@ const DESCR: Proto = Proto {
+             arg2: "Owner",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrGetProtocol",
++            default: "pyo3::class::descr::PyDescrGetProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__set__",
+@@ -217,18 +245,21 @@ const DESCR: Proto = Proto {
+             arg2: "Value",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrSetProtocol",
++            default: "pyo3::class::descr::PyDescrSetProtocol",
+         },
+         MethodProto::Binary {
+             name: "__det__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrDelProtocol",
++            default: "pyo3::class::descr::PyDescrDelProtocol",
+         },
+         MethodProto::Binary {
+             name: "__set_name__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrSetNameProtocol",
++            default: "pyo3::class::descr::PyDescrSetNameProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -245,34 +276,44 @@ const DESCR: Proto = Proto {
+ 
+ const ITER: Proto = Proto {
+     name: "Iter",
++    protocol_trait: "pyo3::class::iter::PyIterProtocol",
++    impl_trait: "pyo3::class::iter::PyIterProtocolImpl",
++
+     py_methods: &[],
+     methods: &[
+         MethodProto::Unary {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterIterProtocol",
++            default: "pyo3::class::iter::PyIterIterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__next__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterNextProtocol",
++            default: "pyo3::class::iter::PyIterNextProtocol",
+         },
+     ],
+ };
+ 
+ const MAPPING: Proto = Proto {
+     name: "Mapping",
++    protocol_trait: "pyo3::class::mapping::PyMappingProtocol",
++    impl_trait: "pyo3::class::mapping::PyMappingProtocolImpl",
++
+     methods: &[
+         MethodProto::Unary {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingLenProtocol",
++            default: "pyo3::class::mapping::PyMappingLenProtocol",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Key",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingGetItemProtocol",
++            default: "pyo3::class::mapping::PyMappingGetItemProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -280,28 +321,33 @@ const MAPPING: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingSetItemProtocol",
++            default: "pyo3::class::mapping::PyMappingSetItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Key",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingDelItemProtocol",
++            default: "pyo3::class::mapping::PyMappingDelItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingContainsProtocol",
++            default: "pyo3::class::mapping::PyMappingContainsProtocol",
+         },
+         MethodProto::Unary {
+             name: "__reversed__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingReversedProtocol",
++            default: "pyo3::class::mapping::PyMappingReversedProtocol",
+         },
+         MethodProto::Unary {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingIterProtocol",
++            default: "pyo3::class::mapping::PyMappingIterProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -322,17 +368,22 @@ const MAPPING: Proto = Proto {
+ 
+ const SEQ: Proto = Proto {
+     name: "Sequence",
++    protocol_trait: "pyo3::class::sequence::PySequenceProtocol",
++    impl_trait: "pyo3::class::sequence::PySequenceProtocolImpl",
++
+     methods: &[
+         MethodProto::Unary {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceLenProtocol",
++            default: "pyo3::class::sequence::PySequenceLenProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceGetItemProtocol",
++            default: "pyo3::class::sequence::PySequenceGetItemProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -340,42 +391,49 @@ const SEQ: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceSetItemProtocol",
++            default: "pyo3::class::sequence::PySequenceSetItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Index",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceDelItemProtocol",
++            default: "pyo3::class::sequence::PySequenceDelItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Item",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceContainsProtocol",
++            default: "pyo3::class::sequence::PySequenceContainsProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceConcatProtocol",
++            default: "pyo3::class::sequence::PySequenceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceRepeatProtocol",
++            default: "pyo3::class::sequence::PySequenceRepeatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceConcatProtocol",
++            default: "pyo3::class::sequence::PySequenceInplaceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceRepeatProtocol",
++            default: "pyo3::class::sequence::PySequenceInplaceRepeatProtocolImpl",
+         },
+     ],
+     py_methods: &[],
+@@ -383,6 +441,9 @@ const SEQ: Proto = Proto {
+ 
+ const NUM: Proto = Proto {
+     name: "Number",
++    protocol_trait: "pyo3::class::number::PyNumberProtocol",
++    impl_trait: "pyo3::class::number::PyNumberProtocolImpl",
++
+     methods: &[
+         MethodProto::BinaryS {
+             name: "__add__",
+@@ -390,6 +451,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAddProtocol",
++            default: "pyo3::class::number::PyNumberAddProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__sub__",
+@@ -397,6 +459,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberSubProtocol",
++            default: "pyo3::class::number::PyNumberSubProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__mul__",
+@@ -404,6 +467,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMulProtocol",
++            default: "pyo3::class::number::PyNumberMulProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__matmul__",
+@@ -411,6 +475,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMatmulProtocol",
++            default: "pyo3::class::number::PyNumberMatmulProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__truediv__",
+@@ -418,6 +483,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberTruedivProtocol",
++            default: "pyo3::class::number::PyNumberTruedivProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__floordiv__",
+@@ -425,6 +491,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloordivProtocol",
++            default: "pyo3::class::number::PyNumberFloordivProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__mod__",
+@@ -432,6 +499,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberModProtocol",
++            default: "pyo3::class::number::PyNumberModProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__divmod__",
+@@ -439,6 +507,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberDivmodProtocol",
++            default: "pyo3::class::number::PyNumberDivmodProtocol",
+         },
+         MethodProto::TernaryS {
+             name: "__pow__",
+@@ -447,6 +516,7 @@ const NUM: Proto = Proto {
+             arg3: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPowProtocol",
++            default: "pyo3::class::number::PyNumberPowProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__lshift__",
+@@ -454,6 +524,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberLShiftProtocol",
++            default: "pyo3::class::number::PyNumberLShiftProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__rshift__",
+@@ -461,6 +532,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRShiftProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__and__",
+@@ -468,6 +540,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAndProtocol",
++            default: "pyo3::class::number::PyNumberAndProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__xor__",
+@@ -475,6 +548,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberXorProtocol",
++            default: "pyo3::class::number::PyNumberXorProtocol",
+         },
+         MethodProto::BinaryS {
+             name: "__or__",
+@@ -482,54 +556,63 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberOrProtocol",
++            default: "pyo3::class::number::PyNumberOrProtocol",
+         },
+         MethodProto::Binary {
+             name: "__radd__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAddProtocol",
++            default: "pyo3::class::number::PyNumberRAddProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rsub__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRSubProtocol",
++            default: "pyo3::class::number::PyNumberRSubProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMulProtocol",
++            default: "pyo3::class::number::PyNumberRMulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rmatmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMatmulProtocol",
++            default: "pyo3::class::number::PyNumberRMatmulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rtruediv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRTruedivProtocol",
++            default: "pyo3::class::number::PyNumberRTruedivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rfloordiv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRFloordivProtocol",
++            default: "pyo3::class::number::PyNumberRFloordivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRModProtocol",
++            default: "pyo3::class::number::PyNumberRModProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rdivmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRDivmodProtocol",
++            default: "pyo3::class::number::PyNumberRDivmodProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__rpow__",
+@@ -537,78 +620,91 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRPowProtocol",
++            default: "pyo3::class::number::PyNumberRPowProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rlshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRLShiftProtocol",
++            default: "pyo3::class::number::PyNumberRLShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rrshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRRShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rand__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAndProtocol",
++            default: "pyo3::class::number::PyNumberRAndProtocol",
+         },
+         MethodProto::Binary {
+             name: "__rxor__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRXorProtocol",
++            default: "pyo3::class::number::PyNumberRXorProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ror__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberROrProtocol",
++            default: "pyo3::class::number::PyNumberROrProtocol",
+         },
+         MethodProto::Binary {
+             name: "__iadd__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAddProtocol",
++            default: "pyo3::class::number::PyNumberIAddProtocol",
+         },
+         MethodProto::Binary {
+             name: "__isub__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberISubProtocol",
++            default: "pyo3::class::number::PyNumberISubProtocol",
+         },
+         MethodProto::Binary {
+             name: "__imul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMulProtocol",
++            default: "pyo3::class::number::PyNumberIMulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__imatmul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMatmulProtocol",
++            default: "pyo3::class::number::PyNumberIMatmulProtocol",
+         },
+         MethodProto::Binary {
+             name: "__itruediv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberITruedivProtocol",
++            default: "pyo3::class::number::PyNumberITruedivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ifloordiv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIFloordivProtocol",
++            default: "pyo3::class::number::PyNumberIFloordivProtocol",
+         },
+         MethodProto::Binary {
+             name: "__imod__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIModProtocol",
++            default: "pyo3::class::number::PyNumberIModProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__ipow__",
+@@ -616,81 +712,96 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIPowProtocol",
++            default: "pyo3::class::number::PyNumberIPowProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ilshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberILShiftProtocol",
++            default: "pyo3::class::number::PyNumberILShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__irshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIRShiftProtocol",
++            default: "pyo3::class::number::PyNumberIRShiftProtocol",
+         },
+         MethodProto::Binary {
+             name: "__iand__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAndProtocol",
++            default: "pyo3::class::number::PyNumberIAndProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ixor__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIXorProtocol",
++            default: "pyo3::class::number::PyNumberIXorProtocol",
+         },
+         MethodProto::Binary {
+             name: "__ior__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIOrProtocol",
++            default: "pyo3::class::number::PyNumberIOrProtocol",
+         },
+         MethodProto::Unary {
+             name: "__neg__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberNegProtocol",
++            default: "pyo3::class::number::PyNumberNegProtocol",
+         },
+         MethodProto::Unary {
+             name: "__pos__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPosProtocol",
++            default: "pyo3::class::number::PyNumberPosProtocol",
+         },
+         MethodProto::Unary {
+             name: "__abs__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAbsProtocol",
++            default: "pyo3::class::number::PyNumberAbsProtocol",
+         },
+         MethodProto::Unary {
+             name: "__invert__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberInvertProtocol",
++            default: "pyo3::class::number::PyNumberInvertProtocol",
+         },
+         MethodProto::Unary {
+             name: "__complex__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberComplexProtocol",
++            default: "pyo3::class::number::PyNumberComplexProtocol",
+         },
+         MethodProto::Unary {
+             name: "__int__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIntProtocol",
++            default: "pyo3::class::number::PyNumberIntProtocol",
+         },
+         MethodProto::Unary {
+             name: "__float__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloatProtocol",
++            default: "pyo3::class::number::PyNumberFloatProtocol",
+         },
+         MethodProto::Unary {
+             name: "__round__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRoundProtocol",
++            default: "pyo3::class::number::PyNumberRoundProtocol",
+         },
+         MethodProto::Unary {
+             name: "__index__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIndexProtocol",
++            default: "pyo3::class::number::PyNumberIndexProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -765,8 +876,12 @@ const PROTOCOLS: &[Proto] = &[
+     OBJECT, ASYNC, MAPPING, ITER, CONTEXT, SEQ, NUM, DESCR, BUFFER, GC,
+ ];
+ 
++pub fn all_protocols() -> &'static [Proto] {
++    PROTOCOLS
++}
++
+ pub fn find_protocol(protocol_trait: &str) -> Option<&'static Proto> {
+     PROTOCOLS
+         .iter()
+-        .find(|p| p.protocol_trait() == protocol_trait)
++        .find(|p| p.protocol_trait.ends_with(protocol_trait))
+ }
+diff --git a/pyo3-derive-backend/src/func.rs b/pyo3-derive-backend/src/func.rs
+index 2b7f69aca..ce06716f4 100644
+--- a/pyo3-derive-backend/src/func.rs
++++ b/pyo3-derive-backend/src/func.rs
+@@ -12,17 +12,20 @@ pub enum MethodProto {
+     Free {
+         name: &'static str,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Unary {
+         name: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Binary {
+         name: &'static str,
+         arg: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     BinaryS {
+         name: &'static str,
+@@ -30,6 +33,7 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Ternary {
+         name: &'static str,
+@@ -37,6 +41,7 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     TernaryS {
+         name: &'static str,
+@@ -45,6 +50,7 @@ pub enum MethodProto {
+         arg3: &'static str,
+         pyres: bool,
+         proto: &'static str,
++        default: &'static str,
+     },
+     Quaternary {
+         name: &'static str,
+@@ -52,6 +58,7 @@ pub enum MethodProto {
+         arg2: &'static str,
+         arg3: &'static str,
+         proto: &'static str,
++        default: &'static str,
+     },
+ }
+ 
+@@ -69,6 +76,31 @@ impl PartialEq<str> for MethodProto {
+     }
+ }
+ 
++impl MethodProto {
++    pub fn get_proto(&self) -> &'static str {
++        match *self {
++            MethodProto::Free { proto: p, .. } => p,
++            MethodProto::Unary { proto: p, .. } => p,
++            MethodProto::Binary { proto: p, .. } => p,
++            MethodProto::BinaryS { proto: p, .. } => p,
++            MethodProto::Ternary { proto: p, .. } => p,
++            MethodProto::TernaryS { proto: p, .. } => p,
++            MethodProto::Quaternary { proto: p, .. } => p,
++        }
++    }
++    pub fn get_default(&self) -> &'static str {
++        match *self {
++            MethodProto::Free { default: d, .. } => d,
++            MethodProto::Unary { default: d, .. } => d,
++            MethodProto::Binary { default: d, .. } => d,
++            MethodProto::BinaryS { default: d, .. } => d,
++            MethodProto::Ternary { default: d, .. } => d,
++            MethodProto::TernaryS { default: d, .. } => d,
++            MethodProto::Quaternary { default: d, .. } => d,
++        }
++    }
++}
++
+ pub fn impl_method_proto(
+     cls: &syn::Type,
+     sig: &mut syn::Signature,
+@@ -119,6 +151,7 @@ pub fn impl_method_proto(
+             arg,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 println!("Not enough arguments for {}", name);
+@@ -164,6 +197,7 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -213,6 +247,7 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -266,6 +301,7 @@ pub fn impl_method_proto(
+             arg3,
+             pyres,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -322,6 +358,7 @@ pub fn impl_method_proto(
+             arg2,
+             arg3,
+             proto,
++            default: _,
+         } => {
+             if sig.inputs.len() <= 3 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs
+index 3ac5d4cde..59a0ab29f 100644
+--- a/pyo3-derive-backend/src/pyclass.rs
++++ b/pyo3-derive-backend/src/pyclass.rs
+@@ -1,10 +1,10 @@
+ // Copyright (c) 2017-present PyO3 Project and Contributors
+-
++use crate::defs;
+ use crate::method::{FnArg, FnSpec, FnType};
+ use crate::pymethod::{impl_py_getter_def, impl_py_setter_def, impl_wrap_getter, impl_wrap_setter};
+ use crate::utils;
+ use proc_macro2::{Span, TokenStream};
+-use quote::quote;
++use quote::{format_ident, quote};
+ use syn::parse::{Parse, ParseStream};
+ use syn::punctuated::Punctuated;
+ use syn::{parse_quote, Expr, Token};
+@@ -326,6 +326,14 @@ fn impl_class(
+         extra
+     };
+ 
++    let extra = {
++        let default_impls = impl_default_protocols(&cls, &attr);
++        quote! {
++            #default_impls
++            #extra
++        }
++    };
++
+     // insert space for weak ref
+     let mut has_weakref = false;
+     let mut has_dict = false;
+@@ -414,6 +422,9 @@ fn impl_class(
+             }
+         }
+ 
++        //impl<T: pyo3::type_object::PyTypeInfo> pyo3::AsPyRefDispatch<T> for #cls {}
++        //impl pyo3::ManagedPyRefDispatch for #cls {}
++
+         #inventory_impl
+ 
+         #extra
+@@ -531,3 +542,22 @@ fn check_generics(class: &mut syn::ItemStruct) -> syn::Result<()> {
+         ))
+     }
+ }
++
++fn impl_default_protocols(cls: &syn::Ident, attr: &PyClassArgs) -> TokenStream {
++    let impls: Vec<TokenStream> = defs::all_protocols()
++        .iter()
++        .filter_map(|proto| {
++            if attr
++                .protocols
++                .iter()
++                .any(|x| proto.protocol_trait.ends_with(&x.to_string()))
++            {
++                None
++            } else {
++                let impl_trait: syn::Path = syn::parse_str(proto.impl_trait).unwrap();
++                Some(quote! { impl #impl_trait for #cls {} })
++            }
++        })
++        .collect();
++    quote! { #(#impls)* }
++}
+diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs
+index 41f1deaf9..a73232e1f 100644
+--- a/pyo3-derive-backend/src/pyproto.rs
++++ b/pyo3-derive-backend/src/pyproto.rs
+@@ -1,7 +1,7 @@
+ // Copyright (c) 2017-present PyO3 Project and Contributors
+ 
+ use crate::defs;
+-use crate::func::impl_method_proto;
++use crate::func::{impl_method_proto, MethodProto};
+ use crate::method::FnSpec;
+ use crate::pymethod;
+ use proc_macro2::Span;
+@@ -53,49 +53,70 @@ fn impl_proto_impl(
+     let mut tokens = TokenStream::new();
+     let mut py_methods = Vec::new();
+ 
++    let mut unimpl_methods: Vec<&MethodProto> = proto.methods.iter().collect();
++    let mut unimpl_py_methods: Vec<&defs::PyMethod> = proto.py_methods.iter().collect();
++
+     for iimpl in impls.iter_mut() {
+         if let syn::ImplItem::Method(ref mut met) = iimpl {
+-            for m in proto.methods {
+-                if m == met.sig.ident.to_string().as_str() {
+-                    impl_method_proto(ty, &mut met.sig, m).to_tokens(&mut tokens);
+-                }
+-            }
+-            for m in proto.py_methods {
+-                let ident = met.sig.ident.clone();
+-                if m.name == ident.to_string().as_str() {
+-                    let name = syn::Ident::new(m.name, Span::call_site());
+-                    let proto: syn::Path = syn::parse_str(m.proto).unwrap();
+-
+-                    let fn_spec = match FnSpec::parse(&ident, &met.sig, &mut met.attrs) {
+-                        Ok(fn_spec) => fn_spec,
+-                        Err(err) => return err.to_compile_error(),
+-                    };
+-                    let meth = pymethod::impl_proto_wrap(ty, &ident, &fn_spec);
+-
+-                    py_methods.push(quote! {
+-                        impl #proto for #ty
+-                        {
+-                            #[inline]
+-                            fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
+-                                #meth
+-
+-                                Some(pyo3::class::PyMethodDef {
+-                                    ml_name: stringify!(#name),
+-                                    ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
+-                                    ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
+-                                    ml_doc: ""
+-                                })
+-                            }
++            let method_name = met.sig.ident.to_string();
++            // Find the method in unimpl_methods, remove it and implement it
++            unimpl_methods
++                .iter()
++                .position(|m| *m == method_name.as_str())
++                .map(|idx| {
++                    let method = unimpl_methods.swap_remove(idx);
++                    impl_method_proto(ty, &mut met.sig, method).to_tokens(&mut tokens);
++                });
++
++            // MJDFIXME - undo this change
++            let py_method_name = &met.sig.ident;
++            let method = unimpl_py_methods
++                .iter()
++                .position(|m| m.name == py_method_name.to_string().as_str())
++                .map(|idx| unimpl_py_methods.swap_remove(idx));
++
++            if let Some(m) = method {
++                let name = syn::Ident::new(m.name, Span::call_site());
++                let proto: syn::Path = syn::parse_str(m.proto).unwrap();
++
++                let fn_spec = match FnSpec::parse(&py_method_name, &met.sig, &mut met.attrs) {
++                    Ok(fn_spec) => fn_spec,
++                    Err(err) => return err.to_compile_error(),
++                };
++                let meth = pymethod::impl_proto_wrap(ty, &py_method_name, &fn_spec);
++
++                py_methods.push(quote! {
++                    impl #proto for #ty
++                    {
++                        #[inline]
++                        fn #name() -> Option<pyo3::class::methods::PyMethodDef> {
++                            #meth
++
++                            Some(pyo3::class::PyMethodDef {
++                                ml_name: stringify!(#name),
++                                ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
++                                ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
++                                ml_doc: ""
++                            })
+                         }
+-                    });
+-                }
+-            }
++                    }
++                });
++            };
+         }
+     }
+ 
++    let default_impls: Vec<_> = unimpl_methods
++        .iter()
++        .map(|m| {
++            let proto: syn::Path = syn::parse_str(m.get_default()).unwrap();
++            quote! { impl #proto for #ty {} }
++        })
++        .collect();
+     quote! {
+         #tokens
+ 
+         #(#py_methods)*
++
++        #(#default_impls)*
+     }
+ }
+diff --git a/src/buffer.rs b/src/buffer.rs
+index 91c317f6e..cdb305ad4 100644
+--- a/src/buffer.rs
++++ b/src/buffer.rs
+@@ -710,8 +710,9 @@ mod test {
+     fn test_array_buffer() {
+         let gil = Python::acquire_gil();
+         let py = gil.python();
+-        let array = py
+-            .import("array")
++        let arr = py.import("array");
++        println!("{:?}", arr);
++        let array = arr
+             .unwrap()
+             .call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None)
+             .unwrap();
+diff --git a/src/class/buffer.rs b/src/class/buffer.rs
+index 32d1a25af..48ecc58ce 100644
+--- a/src/class/buffer.rs
++++ b/src/class/buffer.rs
+@@ -91,3 +91,9 @@ where
+         Some(wrap::<T>)
+     }
+ }
++
++pub trait PyBufferReleaseBufferProtocolImpl {
++    fn cb_bf_releasebuffer() -> Option<ffi::releasebufferproc> {
++        None
++    }
++}
+diff --git a/src/lib.rs b/src/lib.rs
+index 65fb611db..49e71ef6d 100755
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -122,7 +122,9 @@ pub use crate::conversion::{
+ };
+ pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
+ pub use crate::gil::{init_once, GILGuard, GILPool};
+-pub use crate::instance::{AsPyRef, ManagedPyRef, Py, PyNativeType, PyRef, PyRefMut};
++pub use crate::instance::{
++    AsPyRef, AsPyRefDispatch, ManagedPyRef, ManagedPyRefDispatch, Py, PyNativeType, PyRef, PyRefMut,
++};
+ pub use crate::object::PyObject;
+ pub use crate::objectprotocol::ObjectProtocol;
+ pub use crate::python::{prepare_freethreaded_python, Python};
+diff --git a/tests/test_arithmetics.rp b/tests/test_arithmetics.rp
+index 77e8b64fe..42e378b5c 100644
+--- a/tests/test_arithmetics.rp
++++ b/tests/test_arithmetics.rp
+@@ -8,7 +8,7 @@ use pyo3::types::PyAny;
+ 
+ mod common;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol])]
+ struct UnaryArithmetic {}
+ 
+ #[pyproto]
+@@ -42,7 +42,7 @@ fn unary_arithmetic() {
+     py_run!(py, c, "assert ~c == 'invert'");
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol, PyObjectProtocol])]
+ struct BinaryArithmetic {}
+ 
+ #[pyproto]
+@@ -52,7 +52,7 @@ impl PyObjectProtocol for BinaryArithmetic {
+     }
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol, PyObjectProtocol])]
+ struct InPlaceOperations {
+     value: u32,
+ }
+@@ -188,7 +188,7 @@ fn binary_arithmetic() {
+     py_run!(py, c, "assert 1 | c == '1 | BA'");
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyNumberProtocol])]
+ struct RhsArithmetic {}
+ 
+ #[pyproto]
+@@ -210,7 +210,7 @@ fn rhs_arithmetic() {
+     // py_run!(py, c, "assert 1 + c == '1 + RA'");
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyObjectProtocol])]
+ struct RichComparisons {}
+ 
+ #[pyproto]
+@@ -231,7 +231,7 @@ impl PyObjectProtocol for RichComparisons {
+     }
+ }
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyObjectProtocol])]
+ struct RichComparisons2 {}
+ 
+ #[pyproto]
+diff --git a/tests/test_buffer_protocol.rp b/tests/test_buffer_protocol.rs
+similarity index 98%
+rename from tests/test_buffer_protocol.rp
+rename to tests/test_buffer_protocol.rs
+index 64aa4b944..ecbc6038d 100644
+--- a/tests/test_buffer_protocol.rp
++++ b/tests/test_buffer_protocol.rs
+@@ -7,7 +7,7 @@ use std::ffi::CStr;
+ use std::os::raw::{c_int, c_void};
+ use std::ptr;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PyBufferProtocol])]
+ struct TestClass {
+     vec: Vec<u8>,
+ }
+diff --git a/tests/test_class_basics.rs b/tests/test_class_basics.rs
+index c8e1a42df..7b3ff6bc8 100644
+--- a/tests/test_class_basics.rs
++++ b/tests/test_class_basics.rs
+@@ -5,20 +5,9 @@ use pyo3::type_object::initialize_type;
+ 
+ mod common;
+ 
+-#[pyclass(protocols=[PySequenceProtocol])]
++#[pyclass]
+ struct EmptyClass {}
+ 
+-impl class::gc::PyGCProtocolImpl for EmptyClass {}
+-impl class::buffer::PyBufferProtocolImpl for EmptyClass {}
+-impl class::context::PyContextProtocolImpl for EmptyClass {}
+-impl class::iter::PyIterProtocolImpl for EmptyClass {}
+-impl class::descr::PyDescrProtocolImpl for EmptyClass {}
+-impl class::basic::PyObjectProtocolImpl for EmptyClass {}
+-impl class::number::PyNumberProtocolImpl for EmptyClass {}
+-impl class::mapping::PyMappingProtocolImpl for EmptyClass {}
+-impl class::sequence::PySequenceProtocolImpl for EmptyClass {}
+-impl class::pyasync::PyAsyncProtocolImpl for EmptyClass {}
+-
+ #[test]
+ fn empty_class() {
+     let gil = Python::acquire_gil();
+@@ -29,7 +18,7 @@ fn empty_class() {
+ 
+     py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
+ }
+-/*
++
+ /// Line1
+ ///Line2
+ ///  Line3
+@@ -89,4 +78,4 @@ fn empty_class_in_module() {
+     initialize_type::<EmptyClassInModule>(py, Some("test_module.nested")).unwrap();
+     let module: String = ty.getattr("__module__").unwrap().extract().unwrap();
+     assert_eq!(module, "test_module.nested");
+-}*/
++}
+diff --git a/tests/test_class_new.rp b/tests/test_class_new.rs
+similarity index 100%
+rename from tests/test_class_new.rp
+rename to tests/test_class_new.rs
+diff --git a/tests/test_compile_error.rp b/tests/test_compile_error.rs
+similarity index 100%
+rename from tests/test_compile_error.rp
+rename to tests/test_compile_error.rs
+diff --git a/tests/test_datetime.rp b/tests/test_datetime.rp
+index 2819f92c4..a8de5f638 100644
+--- a/tests/test_datetime.rp
++++ b/tests/test_datetime.rp
+@@ -1,5 +1,3 @@
+-#![feature(concat_idents)]
+-
+ use pyo3::ffi::*;
+ use pyo3::prelude::*;
+ use pyo3::types::{IntoPyDict, PyAny};
+diff --git a/tests/test_gc.rp b/tests/test_gc.rs
+similarity index 98%
+rename from tests/test_gc.rp
+rename to tests/test_gc.rs
+index 26465438a..fa0c3d9cf 100644
+--- a/tests/test_gc.rp
++++ b/tests/test_gc.rs
+@@ -132,7 +132,7 @@ fn create_pointers_in_drop() {
+ }
+ 
+ #[allow(dead_code)]
+-#[pyclass]
++#[pyclass(protocols=[PyGCProtocol])]
+ struct GCIntegration {
+     self_ref: RefCell<PyObject>,
+     dropped: TestDropCall,
+@@ -177,7 +177,7 @@ fn gc_integration() {
+     assert!(drop_called.load(Ordering::Relaxed));
+ }
+ 
+-#[pyclass(gc)]
++#[pyclass(gc, protocols=[PyGCProtocol])]
+ struct GCIntegration2 {}
+ 
+ #[pyproto]
+diff --git a/tests/test_getter_setter.rp b/tests/test_getter_setter.rs
+similarity index 100%
+rename from tests/test_getter_setter.rp
+rename to tests/test_getter_setter.rs
+diff --git a/tests/test_sequence.rp b/tests/test_sequence.rs
+similarity index 99%
+rename from tests/test_sequence.rp
+rename to tests/test_sequence.rs
+index 6241f33ec..861ba6988 100644
+--- a/tests/test_sequence.rp
++++ b/tests/test_sequence.rs
+@@ -6,7 +6,7 @@ use pyo3::types::IntoPyDict;
+ use pyo3::types::PyAny;
+ use pyo3::types::PyList;
+ 
+-#[pyclass]
++#[pyclass(protocols=[PySequenceProtocol])]
+ struct ByteSequence {
+     elements: Vec<u8>,
+ }
+diff --git a/tests/test_variable_arguments.rp b/tests/test_variable_arguments.rs
+similarity index 100%
+rename from tests/test_variable_arguments.rp
+rename to tests/test_variable_arguments.rs
+diff --git a/tests/test_various.rp b/tests/test_various.rs
+similarity index 98%
+rename from tests/test_various.rp
+rename to tests/test_various.rs
+index 655101db2..101bdabb0 100644
+--- a/tests/test_various.rp
++++ b/tests/test_various.rs
+@@ -33,7 +33,8 @@ fn mut_ref_arg() {
+     let d = [("inst1", &inst1), ("inst2", &inst2)].into_py_dict(py);
+ 
+     py.run("inst1.set_other(inst2)", None, Some(d)).unwrap();
+-    assert_eq!(inst2.as_ref(py).n, 100);
++    // MJDFIXME
++    //assert_eq!(inst2.as_ref(py).n, 100);
+ }
+ 
+ #[pyclass]
diff --git a/srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch b/srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch
new file mode 100644
index 00000000000..c9946de5852
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0017-specialization-c27d10fcd8932c3d83fe73b07412969cc42ff686.patch
@@ -0,0 +1,38 @@
+From c27d10fcd8932c3d83fe73b07412969cc42ff686 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Sun, 3 Nov 2019 19:29:06 -0800
+Subject: [PATCH] impl AsPyRefDispatch for every pyclass
+
+---
+ pyo3-derive-backend/src/pyclass.rs | 3 +--
+ tests/test_various.rs              | 3 +--
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs
+index 59a0ab29f..ea6c0f513 100644
+--- a/pyo3-derive-backend/src/pyclass.rs
++++ b/pyo3-derive-backend/src/pyclass.rs
+@@ -422,8 +422,7 @@ fn impl_class(
+             }
+         }
+ 
+-        //impl<T: pyo3::type_object::PyTypeInfo> pyo3::AsPyRefDispatch<T> for #cls {}
+-        //impl pyo3::ManagedPyRefDispatch for #cls {}
++        impl pyo3::AsPyRefDispatch<#cls> for Py<#cls> {}
+ 
+         #inventory_impl
+ 
+diff --git a/tests/test_various.rs b/tests/test_various.rs
+index 101bdabb0..655101db2 100644
+--- a/tests/test_various.rs
++++ b/tests/test_various.rs
+@@ -33,8 +33,7 @@ fn mut_ref_arg() {
+     let d = [("inst1", &inst1), ("inst2", &inst2)].into_py_dict(py);
+ 
+     py.run("inst1.set_other(inst2)", None, Some(d)).unwrap();
+-    // MJDFIXME
+-    //assert_eq!(inst2.as_ref(py).n, 100);
++    assert_eq!(inst2.as_ref(py).n, 100);
+ }
+ 
+ #[pyclass]
diff --git a/srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch b/srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch
new file mode 100644
index 00000000000..a66cb076d41
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0018-specialization-d6102a4b93b16ba9b7b43a1c73614efbcb6e9814.patch
@@ -0,0 +1,732 @@
+From d6102a4b93b16ba9b7b43a1c73614efbcb6e9814 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Mon, 4 Nov 2019 21:13:08 -0800
+Subject: [PATCH] Hack and slash to get arithmetic tests working
+
+---
+ pyo3-derive-backend/src/defs.rs               | 127 +++++++++---------
+ src/class/basic.rs                            |  14 +-
+ src/class/number.rs                           |  28 ----
+ ...est_arithmetics.rp => test_arithmetics.rs} |   3 -
+ 4 files changed, 75 insertions(+), 97 deletions(-)
+ rename tests/{test_arithmetics.rp => test_arithmetics.rs} (99%)
+
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index 06c1c6754..d793c9628 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -24,7 +24,7 @@ const OBJECT: Proto = Proto {
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
+-            default: "pyo3::class::basic::PyObjectGetAttrProtocol",
++            default: "pyo3::class::basic::GetAttrProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setattr__",
+@@ -32,58 +32,65 @@ const OBJECT: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
+-            default: "pyo3::class::basic::PyObjectSetAttrProtocol",
++            default: "pyo3::class::basic::tp_setattro_impl::SetAttr",
+         },
+         MethodProto::Binary {
+             name: "__delattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
+-            default: "pyo3::class::basic::PyObjectDelAttrProtocol",
++            default: "pyo3::class::basic::tp_setattro_impl::DelAttr",
+         },
+         MethodProto::Unary {
+             name: "__str__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectStrProtocol",
+-            default: "pyo3::class::basic::PyObjectStrProtocol",
++            default: "pyo3::class::basic::StrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__repr__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectReprProtocol",
+-            default: "pyo3::class::basic::PyObjectReprProtocol",
++            default: "pyo3::class::basic::ReprProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__format__",
+             arg: "Format",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectFormatProtocol",
+-            default: "pyo3::class::basic::PyObjectFormatProtocol",
++            default: "pyo3::class::basic::FormatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__hash__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectHashProtocol",
+-            default: "pyo3::class::basic::PyObjectHashProtocol",
++            default: "pyo3::class::basic::HashProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bytes__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectBytesProtocol",
+-            default: "pyo3::class::basic::PyObjectBytesProtocol",
++            default: "pyo3::class::basic::BytesProtocolImpl",
++        },
++        MethodProto::Unary {
++            // MJDFIXME ???
++            name: "__unicode__",
++            pyres: true,
++            proto: "pyo3::class::basic::PyObjectUnicodeProtocol",
++            default: "pyo3::class::basic::UnicodeProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bool__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectBoolProtocol",
+-            default: "pyo3::class::basic::PyObjectBoolProtocol",
++            default: "pyo3::class::basic::BoolProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__richcmp__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
+-            default: "pyo3::class::basic::PyObjectRichcmpProtocol",
++            default: "pyo3::class::basic::RichcmpProtocolImpl",
+         },
+     ],
+     py_methods: &[
+@@ -451,7 +458,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAddProtocol",
+-            default: "pyo3::class::number::PyNumberAddProtocol",
++            default: "pyo3::class::number::PyNumberAddProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__sub__",
+@@ -459,7 +466,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberSubProtocol",
+-            default: "pyo3::class::number::PyNumberSubProtocol",
++            default: "pyo3::class::number::PyNumberSubProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mul__",
+@@ -467,7 +474,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMulProtocol",
+-            default: "pyo3::class::number::PyNumberMulProtocol",
++            default: "pyo3::class::number::PyNumberMulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__matmul__",
+@@ -475,7 +482,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberMatmulProtocol",
++            default: "pyo3::class::number::PyNumberMatmulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__truediv__",
+@@ -483,7 +490,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberTruedivProtocol",
++            default: "pyo3::class::number::PyNumberTruedivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__floordiv__",
+@@ -491,7 +498,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberFloordivProtocol",
++            default: "pyo3::class::number::PyNumberFloordivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mod__",
+@@ -499,7 +506,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberModProtocol",
+-            default: "pyo3::class::number::PyNumberModProtocol",
++            default: "pyo3::class::number::PyNumberModProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__divmod__",
+@@ -507,7 +514,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberDivmodProtocol",
++            default: "pyo3::class::number::PyNumberDivmodProtocolImpl",
+         },
+         MethodProto::TernaryS {
+             name: "__pow__",
+@@ -516,7 +523,7 @@ const NUM: Proto = Proto {
+             arg3: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPowProtocol",
+-            default: "pyo3::class::number::PyNumberPowProtocol",
++            default: "pyo3::class::number::PyNumberPowProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__lshift__",
+@@ -524,7 +531,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberLShiftProtocol",
++            default: "pyo3::class::number::PyNumberLShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__rshift__",
+@@ -532,7 +539,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__and__",
+@@ -540,7 +547,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAndProtocol",
+-            default: "pyo3::class::number::PyNumberAndProtocol",
++            default: "pyo3::class::number::PyNumberAndProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__xor__",
+@@ -548,7 +555,7 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberXorProtocol",
+-            default: "pyo3::class::number::PyNumberXorProtocol",
++            default: "pyo3::class::number::PyNumberXorProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__or__",
+@@ -556,63 +563,63 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberOrProtocol",
+-            default: "pyo3::class::number::PyNumberOrProtocol",
++            default: "pyo3::class::number::PyNumberOrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__radd__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAddProtocol",
+-            default: "pyo3::class::number::PyNumberRAddProtocol",
++            default: "pyo3::class::number::PyNumberRAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rsub__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRSubProtocol",
+-            default: "pyo3::class::number::PyNumberRSubProtocol",
++            default: "pyo3::class::number::PyNumberRSubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMulProtocol",
+-            default: "pyo3::class::number::PyNumberRMulProtocol",
++            default: "pyo3::class::number::PyNumberRMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmatmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberRMatmulProtocol",
++            default: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rtruediv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberRTruedivProtocol",
++            default: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rfloordiv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberRFloordivProtocol",
++            default: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRModProtocol",
+-            default: "pyo3::class::number::PyNumberRModProtocol",
++            default: "pyo3::class::number::PyNumberRModProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rdivmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberRDivmodProtocol",
++            default: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__rpow__",
+@@ -620,91 +627,91 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRPowProtocol",
+-            default: "pyo3::class::number::PyNumberRPowProtocol",
++            default: "pyo3::class::number::PyNumberRPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rlshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRLShiftProtocol",
++            default: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rrshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRRShiftProtocol",
++            default: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rand__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAndProtocol",
+-            default: "pyo3::class::number::PyNumberRAndProtocol",
++            default: "pyo3::class::number::PyNumberRAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rxor__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRXorProtocol",
+-            default: "pyo3::class::number::PyNumberRXorProtocol",
++            default: "pyo3::class::number::PyNumberRXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ror__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberROrProtocol",
+-            default: "pyo3::class::number::PyNumberROrProtocol",
++            default: "pyo3::class::number::PyNumberROrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iadd__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAddProtocol",
+-            default: "pyo3::class::number::PyNumberIAddProtocol",
++            default: "pyo3::class::number::PyNumberIAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__isub__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberISubProtocol",
+-            default: "pyo3::class::number::PyNumberISubProtocol",
++            default: "pyo3::class::number::PyNumberISubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMulProtocol",
+-            default: "pyo3::class::number::PyNumberIMulProtocol",
++            default: "pyo3::class::number::PyNumberIMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imatmul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberIMatmulProtocol",
++            default: "pyo3::class::number::PyNumberIMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__itruediv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberITruedivProtocol",
+-            default: "pyo3::class::number::PyNumberITruedivProtocol",
++            default: "pyo3::class::number::PyNumberITruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ifloordiv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberIFloordivProtocol",
++            default: "pyo3::class::number::PyNumberIFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imod__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIModProtocol",
+-            default: "pyo3::class::number::PyNumberIModProtocol",
++            default: "pyo3::class::number::PyNumberIModProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__ipow__",
+@@ -712,96 +719,96 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIPowProtocol",
+-            default: "pyo3::class::number::PyNumberIPowProtocol",
++            default: "pyo3::class::number::PyNumberIPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ilshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberILShiftProtocol",
+-            default: "pyo3::class::number::PyNumberILShiftProtocol",
++            default: "pyo3::class::number::PyNumberILShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__irshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberIRShiftProtocol",
++            default: "pyo3::class::number::PyNumberIRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iand__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAndProtocol",
+-            default: "pyo3::class::number::PyNumberIAndProtocol",
++            default: "pyo3::class::number::PyNumberIAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ixor__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIXorProtocol",
+-            default: "pyo3::class::number::PyNumberIXorProtocol",
++            default: "pyo3::class::number::PyNumberIXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ior__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIOrProtocol",
+-            default: "pyo3::class::number::PyNumberIOrProtocol",
++            default: "pyo3::class::number::PyNumberIOrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__neg__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberNegProtocol",
+-            default: "pyo3::class::number::PyNumberNegProtocol",
++            default: "pyo3::class::number::PyNumberNegProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__pos__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPosProtocol",
+-            default: "pyo3::class::number::PyNumberPosProtocol",
++            default: "pyo3::class::number::PyNumberPosProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__abs__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAbsProtocol",
+-            default: "pyo3::class::number::PyNumberAbsProtocol",
++            default: "pyo3::class::number::PyNumberAbsProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__invert__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberInvertProtocol",
+-            default: "pyo3::class::number::PyNumberInvertProtocol",
++            default: "pyo3::class::number::PyNumberInvertProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__complex__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberComplexProtocol",
+-            default: "pyo3::class::number::PyNumberComplexProtocol",
++            default: "pyo3::class::number::PyNumberComplexProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__int__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIntProtocol",
+-            default: "pyo3::class::number::PyNumberIntProtocol",
++            default: "pyo3::class::number::PyNumberIntProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__float__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloatProtocol",
+-            default: "pyo3::class::number::PyNumberFloatProtocol",
++            default: "pyo3::class::number::PyNumberFloatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__round__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRoundProtocol",
+-            default: "pyo3::class::number::PyNumberRoundProtocol",
++            default: "pyo3::class::number::PyNumberRoundProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__index__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIndexProtocol",
+-            default: "pyo3::class::number::PyNumberIndexProtocol",
++            default: "pyo3::class::number::PyNumberIndexProtocolImpl",
+         },
+     ],
+     py_methods: &[
+diff --git a/src/class/basic.rs b/src/class/basic.rs
+index f87a0d029..15d682886 100644
+--- a/src/class/basic.rs
++++ b/src/class/basic.rs
+@@ -166,13 +166,15 @@ pub trait PyObjectProtocolImpl {
+ impl<'p, T> PyObjectProtocolImpl for T
+ where
+     T: PyObjectProtocol<'p>
+-        + PyObjectSetAttrProtocol<'p>
+         + GetAttrProtocolImpl
+         + StrProtocolImpl
+         + ReprProtocolImpl
+         + HashProtocolImpl
+         + RichcmpProtocolImpl
+         + BoolProtocolImpl
++        + FormatProtocolImpl
++        + BytesProtocolImpl
++        + UnicodeProtocolImpl
+         + tp_setattro_impl::DelAttr
+         + tp_setattro_impl::SetAttr
+         + tp_setattro_impl::SetDelAttr,
+@@ -253,7 +255,7 @@ where
+ /// and may support deleting attributes (by implementing PyObjectDelAttrProtocol)
+ /// and we need to generate a single extern c function that supports only setting, only deleting
+ /// or both, and return None in case none of the two is supported.
+-mod tp_setattro_impl {
++pub mod tp_setattro_impl {
+     use super::*;
+ 
+     /// setattrofunc PyTypeObject.tp_setattro
+@@ -314,6 +316,9 @@ mod tp_setattro_impl {
+         }
+     }
+ 
++    impl<T> SetDelAttr for T {}
++
++    /* MJDFIXME
+     impl<T> SetDelAttr for T
+     where
+         T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
+@@ -327,7 +332,7 @@ mod tp_setattro_impl {
+                 __delattr__
+             )
+         }
+-    }
++    } */
+ }
+ 
+ pub trait StrProtocolImpl {
+@@ -376,7 +381,6 @@ pub trait FormatProtocolImpl {
+         None
+     }
+ }
+-impl<'p, T> FormatProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait BytesProtocolImpl {
+@@ -384,7 +388,6 @@ pub trait BytesProtocolImpl {
+         None
+     }
+ }
+-impl<'p, T> BytesProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ #[doc(hidden)]
+ pub trait UnicodeProtocolImpl {
+@@ -392,7 +395,6 @@ pub trait UnicodeProtocolImpl {
+         None
+     }
+ }
+-impl<'p, T> UnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
+ 
+ pub trait HashProtocolImpl {
+     fn tp_hash() -> Option<ffi::hashfunc> {
+diff --git a/src/class/number.rs b/src/class/number.rs
+index 796a1c7ea..faad83039 100644
+--- a/src/class/number.rs
++++ b/src/class/number.rs
+@@ -1273,8 +1273,6 @@ pub trait PyNumberRAddProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRAddProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRSubProtocolImpl {
+     fn __rsub__() -> Option<PyMethodDef> {
+@@ -1282,8 +1280,6 @@ pub trait PyNumberRSubProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRSubProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRMulProtocolImpl {
+     fn __rmul__() -> Option<PyMethodDef> {
+@@ -1291,8 +1287,6 @@ pub trait PyNumberRMulProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRMulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRMatmulProtocolImpl {
+     fn __rmatmul__() -> Option<PyMethodDef> {
+@@ -1300,8 +1294,6 @@ pub trait PyNumberRMatmulProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRMatmulProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRTruedivProtocolImpl {
+     fn __rtruediv__() -> Option<PyMethodDef> {
+@@ -1309,8 +1301,6 @@ pub trait PyNumberRTruedivProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRTruedivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRFloordivProtocolImpl {
+     fn __rfloordiv__() -> Option<PyMethodDef> {
+@@ -1318,8 +1308,6 @@ pub trait PyNumberRFloordivProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRFloordivProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRModProtocolImpl {
+     fn __rmod__() -> Option<PyMethodDef> {
+@@ -1327,8 +1315,6 @@ pub trait PyNumberRModProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRModProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRDivmodProtocolImpl {
+     fn __rdivmod__() -> Option<PyMethodDef> {
+@@ -1336,8 +1322,6 @@ pub trait PyNumberRDivmodProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRDivmodProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRPowProtocolImpl {
+     fn __rpow__() -> Option<PyMethodDef> {
+@@ -1345,8 +1329,6 @@ pub trait PyNumberRPowProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRPowProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRLShiftProtocolImpl {
+     fn __rlshift__() -> Option<PyMethodDef> {
+@@ -1354,8 +1336,6 @@ pub trait PyNumberRLShiftProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRLShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRRShiftProtocolImpl {
+     fn __rrshift__() -> Option<PyMethodDef> {
+@@ -1363,8 +1343,6 @@ pub trait PyNumberRRShiftProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRRShiftProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRAndProtocolImpl {
+     fn __rand__() -> Option<PyMethodDef> {
+@@ -1372,8 +1350,6 @@ pub trait PyNumberRAndProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRAndProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberRXorProtocolImpl {
+     fn __rxor__() -> Option<PyMethodDef> {
+@@ -1381,8 +1357,6 @@ pub trait PyNumberRXorProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberRXorProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ #[doc(hidden)]
+ pub trait PyNumberROrProtocolImpl {
+     fn __ror__() -> Option<PyMethodDef> {
+@@ -1390,8 +1364,6 @@ pub trait PyNumberROrProtocolImpl {
+     }
+ }
+ 
+-impl<'p, T> PyNumberROrProtocolImpl for T where T: PyNumberProtocol<'p> {}
+-
+ pub trait PyNumberNegProtocolImpl {
+     fn nb_negative() -> Option<ffi::unaryfunc> {
+         None
+diff --git a/tests/test_arithmetics.rp b/tests/test_arithmetics.rs
+similarity index 99%
+rename from tests/test_arithmetics.rp
+rename to tests/test_arithmetics.rs
+index 42e378b5c..2fb25adf5 100644
+--- a/tests/test_arithmetics.rp
++++ b/tests/test_arithmetics.rs
+@@ -1,5 +1,3 @@
+-#![feature(specialization)]
+-
+ use pyo3::class::basic::CompareOp;
+ use pyo3::class::*;
+ use pyo3::prelude::*;
+@@ -16,7 +14,6 @@ impl PyNumberProtocol for UnaryArithmetic {
+     fn __neg__(&self) -> PyResult<&'static str> {
+         Ok("neg")
+     }
+-
+     fn __pos__(&self) -> PyResult<&'static str> {
+         Ok("pos")
+     }
diff --git a/srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch b/srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch
new file mode 100644
index 00000000000..20781e716f9
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0019-specialization-ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5.patch
@@ -0,0 +1,1321 @@
+From ac0158f18c02de6ab9dd9a6b96fd97a935d6f9b5 Mon Sep 17 00:00:00 2001
+From: Martin Donlon <github-martin@donlons.com>
+Date: Sun, 17 Nov 2019 08:23:49 -0800
+Subject: [PATCH] But default impls into a separate array in defs rather than
+ storing them in the MethodProto
+
+---
+ pyo3-derive-backend/src/defs.rs               | 500 ++++++++++++++----
+ pyo3-derive-backend/src/func.rs               |  23 -
+ pyo3-derive-backend/src/pyproto.rs            |  17 +-
+ .../{test_dict_iter.rp => test_dict_iter.rs}  |   0
+ tests/test_dunder.rp                          |  26 +-
+ 5 files changed, 426 insertions(+), 140 deletions(-)
+ rename tests/{test_dict_iter.rp => test_dict_iter.rs} (100%)
+
+diff --git a/pyo3-derive-backend/src/defs.rs b/pyo3-derive-backend/src/defs.rs
+index d793c9628..f7ac2da01 100644
+--- a/pyo3-derive-backend/src/defs.rs
++++ b/pyo3-derive-backend/src/defs.rs
+@@ -7,6 +7,7 @@ pub struct Proto {
+     pub impl_trait: &'static str,
+     pub methods: &'static [MethodProto],
+     pub py_methods: &'static [PyMethod],
++    pub default_impls: &'static [DefaultImpl],
+ }
+ 
+ pub struct PyMethod {
+@@ -14,6 +15,11 @@ pub struct PyMethod {
+     pub proto: &'static str,
+ }
+ 
++pub struct DefaultImpl {
++    pub name: &'static str,
++    pub default: &'static str,
++}
++
+ const OBJECT: Proto = Proto {
+     name: "Object",
+     protocol_trait: "pyo3::class::basic::PyObjectProtocol",
+@@ -24,7 +30,6 @@ const OBJECT: Proto = Proto {
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
+-            default: "pyo3::class::basic::GetAttrProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setattr__",
+@@ -32,65 +37,49 @@ const OBJECT: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
+-            default: "pyo3::class::basic::tp_setattro_impl::SetAttr",
+         },
+         MethodProto::Binary {
+             name: "__delattr__",
+             arg: "Name",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
+-            default: "pyo3::class::basic::tp_setattro_impl::DelAttr",
+         },
+         MethodProto::Unary {
+             name: "__str__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectStrProtocol",
+-            default: "pyo3::class::basic::StrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__repr__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectReprProtocol",
+-            default: "pyo3::class::basic::ReprProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__format__",
+             arg: "Format",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectFormatProtocol",
+-            default: "pyo3::class::basic::FormatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__hash__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectHashProtocol",
+-            default: "pyo3::class::basic::HashProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bytes__",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectBytesProtocol",
+-            default: "pyo3::class::basic::BytesProtocolImpl",
+-        },
+-        MethodProto::Unary {
+-            // MJDFIXME ???
+-            name: "__unicode__",
+-            pyres: true,
+-            proto: "pyo3::class::basic::PyObjectUnicodeProtocol",
+-            default: "pyo3::class::basic::UnicodeProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__bool__",
+             pyres: false,
+             proto: "pyo3::class::basic::PyObjectBoolProtocol",
+-            default: "pyo3::class::basic::BoolProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__richcmp__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
+-            default: "pyo3::class::basic::RichcmpProtocolImpl",
+         },
+     ],
+     py_methods: &[
+@@ -107,6 +96,52 @@ const OBJECT: Proto = Proto {
+             proto: "pyo3::class::basic::UnicodeProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__getattr__",
++            default: "pyo3::class::basic::GetAttrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__setattr__",
++            default: "pyo3::class::basic::tp_setattro_impl::SetAttr",
++        },
++        DefaultImpl {
++            name: "__delattr__",
++            default: "pyo3::class::basic::tp_setattro_impl::DelAttr",
++        },
++        DefaultImpl {
++            name: "__str__",
++            default: "pyo3::class::basic::StrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__repr__",
++            default: "pyo3::class::basic::ReprProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__format__",
++            default: "pyo3::class::basic::FormatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__hash__",
++            default: "pyo3::class::basic::HashProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__bytes__",
++            default: "pyo3::class::basic::BytesProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__unicode__",
++            default: "pyo3::class::basic::UnicodeProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__bool__",
++            default: "pyo3::class::basic::BoolProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__richcmp__",
++            default: "pyo3::class::basic::RichcmpProtocolImpl",
++        },
++    ],
+ };
+ 
+ const ASYNC: Proto = Proto {
+@@ -118,25 +153,21 @@ const ASYNC: Proto = Proto {
+             name: "__await__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aiter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAiterProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAiterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__anext__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAnextProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAnextProtocol",
+         },
+         MethodProto::Unary {
+             name: "__aenter__",
+             pyres: true,
+             proto: "pyo3::class::pyasync::PyAsyncAenterProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAenterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__aexit__",
+@@ -144,7 +175,6 @@ const ASYNC: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::pyasync::PyAsyncAexitProtocol",
+-            default: "pyo3::class::pyasync::PyAsyncAexitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -157,6 +187,28 @@ const ASYNC: Proto = Proto {
+             proto: "pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__await__",
++            default: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
++        },
++        DefaultImpl {
++            name: "__aiter__",
++            default: "pyo3::class::pyasync::PyAsyncAiterProtocol",
++        },
++        DefaultImpl {
++            name: "__anext__",
++            default: "pyo3::class::pyasync::PyAsyncAnextProtocol",
++        },
++        DefaultImpl {
++            name: "__aenter__",
++            default: "pyo3::class::pyasync::PyAsyncAenterProtocol",
++        },
++        DefaultImpl {
++            name: "__aexit__",
++            default: "pyo3::class::pyasync::PyAsyncAexitProtocol",
++        },
++    ],
+ };
+ 
+ const BUFFER: Proto = Proto {
+@@ -168,16 +220,24 @@ const BUFFER: Proto = Proto {
+             name: "bf_getbuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferGetBufferProtocol",
+-            default: "pyo3::class::buffer::PyBufferGetBufferProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "bf_releasebuffer",
+             pyres: false,
+             proto: "pyo3::class::buffer::PyBufferReleaseBufferProtocol",
+-            default: "pyo3::class::buffer::PyBufferReleaseBufferProtocolImpl",
+         },
+     ],
+     py_methods: &[],
++    default_impls: &[
++        DefaultImpl {
++            name: "bf_getbuffer",
++            default: "pyo3::class::buffer::PyBufferGetBufferProtocolImpl",
++        },
++        DefaultImpl {
++            name: "bf_releasebuffer",
++            default: "pyo3::class::buffer::PyBufferReleaseBufferProtocolImpl",
++        },
++    ],
+ };
+ 
+ const CONTEXT: Proto = Proto {
+@@ -189,7 +249,6 @@ const CONTEXT: Proto = Proto {
+             name: "__enter__",
+             pyres: true,
+             proto: "pyo3::class::context::PyContextEnterProtocol",
+-            default: "pyo3::class::context::PyContextEnterProtocol",
+         },
+         MethodProto::Quaternary {
+             name: "__exit__",
+@@ -197,7 +256,6 @@ const CONTEXT: Proto = Proto {
+             arg2: "ExcValue",
+             arg3: "Traceback",
+             proto: "pyo3::class::context::PyContextExitProtocol",
+-            default: "pyo3::class::context::PyContextExitProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -210,6 +268,16 @@ const CONTEXT: Proto = Proto {
+             proto: "pyo3::class::context::PyContextExitProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__enter__",
++            default: "pyo3::class::context::PyContextEnterProtocol",
++        },
++        DefaultImpl {
++            name: "__exit__",
++            default: "pyo3::class::context::PyContextExitProtocol",
++        },
++    ],
+ };
+ 
+ const GC: Proto = Proto {
+@@ -221,15 +289,23 @@ const GC: Proto = Proto {
+         MethodProto::Free {
+             name: "__traverse__",
+             proto: "pyo3::class::gc::PyGCTraverseProtocol",
+-            default: "pyo3::class::gc::PyGCTraverseProtocolImpl",
+         },
+         MethodProto::Free {
+             name: "__clear__",
+             proto: "pyo3::class::gc::PyGCClearProtocol",
+-            default: "pyo3::class::gc::PyGCClearProtocolImpl",
+         },
+     ],
+     py_methods: &[],
++    default_impls: &[
++        DefaultImpl {
++            name: "__traverse__",
++            default: "pyo3::class::gc::PyGCTraverseProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__clear__",
++            default: "pyo3::class::gc::PyGCClearProtocolImpl",
++        },
++    ],
+ };
+ 
+ const DESCR: Proto = Proto {
+@@ -244,7 +320,6 @@ const DESCR: Proto = Proto {
+             arg2: "Owner",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrGetProtocol",
+-            default: "pyo3::class::descr::PyDescrGetProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__set__",
+@@ -252,21 +327,18 @@ const DESCR: Proto = Proto {
+             arg2: "Value",
+             pyres: true,
+             proto: "pyo3::class::descr::PyDescrSetProtocol",
+-            default: "pyo3::class::descr::PyDescrSetProtocol",
+         },
+         MethodProto::Binary {
+             name: "__det__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrDelProtocol",
+-            default: "pyo3::class::descr::PyDescrDelProtocol",
+         },
+         MethodProto::Binary {
+             name: "__set_name__",
+             arg: "Inst",
+             pyres: false,
+             proto: "pyo3::class::descr::PyDescrSetNameProtocol",
+-            default: "pyo3::class::descr::PyDescrSetNameProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -279,6 +351,24 @@ const DESCR: Proto = Proto {
+             proto: "pyo3::class::context::PyDescrNameProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__get__",
++            default: "pyo3::class::descr::PyDescrGetProtocol",
++        },
++        DefaultImpl {
++            name: "__set__",
++            default: "pyo3::class::descr::PyDescrSetProtocol",
++        },
++        DefaultImpl {
++            name: "__det__",
++            default: "pyo3::class::descr::PyDescrDelProtocol",
++        },
++        DefaultImpl {
++            name: "__set_name__",
++            default: "pyo3::class::descr::PyDescrSetNameProtocol",
++        },
++    ],
+ };
+ 
+ const ITER: Proto = Proto {
+@@ -292,12 +382,20 @@ const ITER: Proto = Proto {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterIterProtocol",
+-            default: "pyo3::class::iter::PyIterIterProtocol",
+         },
+         MethodProto::Unary {
+             name: "__next__",
+             pyres: true,
+             proto: "pyo3::class::iter::PyIterNextProtocol",
++        },
++    ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__iter__",
++            default: "pyo3::class::iter::PyIterIterProtocol",
++        },
++        DefaultImpl {
++            name: "__next__",
+             default: "pyo3::class::iter::PyIterNextProtocol",
+         },
+     ],
+@@ -313,14 +411,12 @@ const MAPPING: Proto = Proto {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingLenProtocol",
+-            default: "pyo3::class::mapping::PyMappingLenProtocol",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Key",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingGetItemProtocol",
+-            default: "pyo3::class::mapping::PyMappingGetItemProtocol",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -328,33 +424,28 @@ const MAPPING: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingSetItemProtocol",
+-            default: "pyo3::class::mapping::PyMappingSetItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Key",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingDelItemProtocol",
+-            default: "pyo3::class::mapping::PyMappingDelItemProtocol",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Value",
+             pyres: false,
+             proto: "pyo3::class::mapping::PyMappingContainsProtocol",
+-            default: "pyo3::class::mapping::PyMappingContainsProtocol",
+         },
+         MethodProto::Unary {
+             name: "__reversed__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingReversedProtocol",
+-            default: "pyo3::class::mapping::PyMappingReversedProtocol",
+         },
+         MethodProto::Unary {
+             name: "__iter__",
+             pyres: true,
+             proto: "pyo3::class::mapping::PyMappingIterProtocol",
+-            default: "pyo3::class::mapping::PyMappingIterProtocol",
+         },
+     ],
+     py_methods: &[
+@@ -371,6 +462,36 @@ const MAPPING: Proto = Proto {
+             proto: "pyo3::class::mapping::PyMappingReversedProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__len__",
++            default: "pyo3::class::mapping::PyMappingLenProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__getitem__",
++            default: "pyo3::class::mapping::PyMappingGetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__setitem__",
++            default: "pyo3::class::mapping::PyMappingSetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__delitem__",
++            default: "pyo3::class::mapping::PyMappingDelItemProtocolNotImpl",
++        },
++        DefaultImpl {
++            name: "__contains__",
++            default: "pyo3::class::mapping::PyMappingContainsProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__reversed__",
++            default: "pyo3::class::mapping::PyMappingReversedProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__iter__",
++            default: "pyo3::class::mapping::PyMappingIterProtocolImpl",
++        },
++    ],
+ };
+ 
+ const SEQ: Proto = Proto {
+@@ -383,14 +504,12 @@ const SEQ: Proto = Proto {
+             name: "__len__",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceLenProtocol",
+-            default: "pyo3::class::sequence::PySequenceLenProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__getitem__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceGetItemProtocol",
+-            default: "pyo3::class::sequence::PySequenceGetItemProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__setitem__",
+@@ -398,52 +517,83 @@ const SEQ: Proto = Proto {
+             arg2: "Value",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceSetItemProtocol",
+-            default: "pyo3::class::sequence::PySequenceSetItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__delitem__",
+             arg: "Index",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceDelItemProtocol",
+-            default: "pyo3::class::sequence::PySequenceDelItemProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__contains__",
+             arg: "Item",
+             pyres: false,
+             proto: "pyo3::class::sequence::PySequenceContainsProtocol",
+-            default: "pyo3::class::sequence::PySequenceContainsProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceConcatProtocol",
+-            default: "pyo3::class::sequence::PySequenceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceRepeatProtocol",
+-            default: "pyo3::class::sequence::PySequenceRepeatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_concat__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceConcatProtocol",
+-            default: "pyo3::class::sequence::PySequenceInplaceConcatProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__inplace_repeat__",
+             arg: "Index",
+             pyres: true,
+             proto: "pyo3::class::sequence::PySequenceInplaceRepeatProtocol",
+-            default: "pyo3::class::sequence::PySequenceInplaceRepeatProtocolImpl",
+         },
+     ],
+     py_methods: &[],
++    default_impls: &[
++        DefaultImpl {
++            name: "__len__",
++            default: "pyo3::class::sequence::PySequenceLenProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__getitem__",
++            default: "pyo3::class::sequence::PySequenceGetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__setitem__",
++            default: "pyo3::class::sequence::PySequenceSetItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__delitem__",
++            default: "pyo3::class::sequence::PySequenceDelItemProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__contains__",
++            default: "pyo3::class::sequence::PySequenceContainsProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__concat__",
++            default: "pyo3::class::sequence::PySequenceConcatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__repeat__",
++            default: "pyo3::class::sequence::PySequenceRepeatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__inplace_concat__",
++            default: "pyo3::class::sequence::PySequenceInplaceConcatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__inplace_repeat__",
++            default: "pyo3::class::sequence::PySequenceInplaceRepeatProtocolImpl",
++        },
++    ],
+ };
+ 
+ const NUM: Proto = Proto {
+@@ -458,7 +608,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAddProtocol",
+-            default: "pyo3::class::number::PyNumberAddProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__sub__",
+@@ -466,7 +615,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberSubProtocol",
+-            default: "pyo3::class::number::PyNumberSubProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mul__",
+@@ -474,7 +622,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMulProtocol",
+-            default: "pyo3::class::number::PyNumberMulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__matmul__",
+@@ -482,7 +629,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberMatmulProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__truediv__",
+@@ -490,7 +636,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberTruedivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__floordiv__",
+@@ -498,7 +643,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberFloordivProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__mod__",
+@@ -506,7 +650,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberModProtocol",
+-            default: "pyo3::class::number::PyNumberModProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__divmod__",
+@@ -514,7 +657,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberDivmodProtocolImpl",
+         },
+         MethodProto::TernaryS {
+             name: "__pow__",
+@@ -523,7 +665,6 @@ const NUM: Proto = Proto {
+             arg3: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPowProtocol",
+-            default: "pyo3::class::number::PyNumberPowProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__lshift__",
+@@ -531,7 +672,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberLShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__rshift__",
+@@ -539,7 +679,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRShiftProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__and__",
+@@ -547,7 +686,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAndProtocol",
+-            default: "pyo3::class::number::PyNumberAndProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__xor__",
+@@ -555,7 +693,6 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberXorProtocol",
+-            default: "pyo3::class::number::PyNumberXorProtocolImpl",
+         },
+         MethodProto::BinaryS {
+             name: "__or__",
+@@ -563,63 +700,54 @@ const NUM: Proto = Proto {
+             arg2: "Right",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberOrProtocol",
+-            default: "pyo3::class::number::PyNumberOrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__radd__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAddProtocol",
+-            default: "pyo3::class::number::PyNumberRAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rsub__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRSubProtocol",
+-            default: "pyo3::class::number::PyNumberRSubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMulProtocol",
+-            default: "pyo3::class::number::PyNumberRMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmatmul__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rtruediv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRTruedivProtocol",
+-            default: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rfloordiv__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRModProtocol",
+-            default: "pyo3::class::number::PyNumberRModProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rdivmod__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRDivmodProtocol",
+-            default: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__rpow__",
+@@ -627,91 +755,78 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRPowProtocol",
+-            default: "pyo3::class::number::PyNumberRPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rlshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRLShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rrshift__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rand__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRAndProtocol",
+-            default: "pyo3::class::number::PyNumberRAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__rxor__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRXorProtocol",
+-            default: "pyo3::class::number::PyNumberRXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ror__",
+             arg: "Other",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberROrProtocol",
+-            default: "pyo3::class::number::PyNumberROrProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iadd__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAddProtocol",
+-            default: "pyo3::class::number::PyNumberIAddProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__isub__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberISubProtocol",
+-            default: "pyo3::class::number::PyNumberISubProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMulProtocol",
+-            default: "pyo3::class::number::PyNumberIMulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imatmul__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIMatmulProtocol",
+-            default: "pyo3::class::number::PyNumberIMatmulProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__itruediv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberITruedivProtocol",
+-            default: "pyo3::class::number::PyNumberITruedivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ifloordiv__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIFloordivProtocol",
+-            default: "pyo3::class::number::PyNumberIFloordivProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__imod__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIModProtocol",
+-            default: "pyo3::class::number::PyNumberIModProtocolImpl",
+         },
+         MethodProto::Ternary {
+             name: "__ipow__",
+@@ -719,96 +834,81 @@ const NUM: Proto = Proto {
+             arg2: "Modulo",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIPowProtocol",
+-            default: "pyo3::class::number::PyNumberIPowProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ilshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberILShiftProtocol",
+-            default: "pyo3::class::number::PyNumberILShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__irshift__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIRShiftProtocol",
+-            default: "pyo3::class::number::PyNumberIRShiftProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__iand__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIAndProtocol",
+-            default: "pyo3::class::number::PyNumberIAndProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ixor__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIXorProtocol",
+-            default: "pyo3::class::number::PyNumberIXorProtocolImpl",
+         },
+         MethodProto::Binary {
+             name: "__ior__",
+             arg: "Other",
+             pyres: false,
+             proto: "pyo3::class::number::PyNumberIOrProtocol",
+-            default: "pyo3::class::number::PyNumberIOrProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__neg__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberNegProtocol",
+-            default: "pyo3::class::number::PyNumberNegProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__pos__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberPosProtocol",
+-            default: "pyo3::class::number::PyNumberPosProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__abs__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberAbsProtocol",
+-            default: "pyo3::class::number::PyNumberAbsProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__invert__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberInvertProtocol",
+-            default: "pyo3::class::number::PyNumberInvertProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__complex__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberComplexProtocol",
+-            default: "pyo3::class::number::PyNumberComplexProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__int__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIntProtocol",
+-            default: "pyo3::class::number::PyNumberIntProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__float__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberFloatProtocol",
+-            default: "pyo3::class::number::PyNumberFloatProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__round__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberRoundProtocol",
+-            default: "pyo3::class::number::PyNumberRoundProtocolImpl",
+         },
+         MethodProto::Unary {
+             name: "__index__",
+             pyres: true,
+             proto: "pyo3::class::number::PyNumberIndexProtocol",
+-            default: "pyo3::class::number::PyNumberIndexProtocolImpl",
+         },
+     ],
+     py_methods: &[
+@@ -877,6 +977,208 @@ const NUM: Proto = Proto {
+             proto: "pyo3::class::number::PyNumberRoundProtocolImpl",
+         },
+     ],
++    default_impls: &[
++        DefaultImpl {
++            name: "__add__",
++            default: "pyo3::class::number::PyNumberAddProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__sub__",
++            default: "pyo3::class::number::PyNumberSubProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__mul__",
++            default: "pyo3::class::number::PyNumberMulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__matmul__",
++            default: "pyo3::class::number::PyNumberMatmulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__truediv__",
++            default: "pyo3::class::number::PyNumberTruedivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__floordiv__",
++            default: "pyo3::class::number::PyNumberFloordivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__mod__",
++            default: "pyo3::class::number::PyNumberModProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__divmod__",
++            default: "pyo3::class::number::PyNumberDivmodProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__pow__",
++            default: "pyo3::class::number::PyNumberPowProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__lshift__",
++            default: "pyo3::class::number::PyNumberLShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rshift__",
++            default: "pyo3::class::number::PyNumberRShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__and__",
++            default: "pyo3::class::number::PyNumberAndProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__xor__",
++            default: "pyo3::class::number::PyNumberXorProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__or__",
++            default: "pyo3::class::number::PyNumberOrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__radd__",
++            default: "pyo3::class::number::PyNumberRAddProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rsub__",
++            default: "pyo3::class::number::PyNumberRSubProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rmul__",
++            default: "pyo3::class::number::PyNumberRMulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rmatmul__",
++            default: "pyo3::class::number::PyNumberRMatmulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rtruediv__",
++            default: "pyo3::class::number::PyNumberRTruedivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rfloordiv__",
++            default: "pyo3::class::number::PyNumberRFloordivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rmod__",
++            default: "pyo3::class::number::PyNumberRModProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rdivmod__",
++            default: "pyo3::class::number::PyNumberRDivmodProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rpow__",
++            default: "pyo3::class::number::PyNumberRPowProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rlshift__",
++            default: "pyo3::class::number::PyNumberRLShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rrshift__",
++            default: "pyo3::class::number::PyNumberRRShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rand__",
++            default: "pyo3::class::number::PyNumberRAndProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__rxor__",
++            default: "pyo3::class::number::PyNumberRXorProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ror__",
++            default: "pyo3::class::number::PyNumberROrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__iadd__",
++            default: "pyo3::class::number::PyNumberIAddProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__isub__",
++            default: "pyo3::class::number::PyNumberISubProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__imul__",
++            default: "pyo3::class::number::PyNumberIMulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__imatmul__",
++            default: "pyo3::class::number::PyNumberIMatmulProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__itruediv__",
++            default: "pyo3::class::number::PyNumberITruedivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ifloordiv__",
++            default: "pyo3::class::number::PyNumberIFloordivProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__imod__",
++            default: "pyo3::class::number::PyNumberIModProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ipow__",
++            default: "pyo3::class::number::PyNumberIPowProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ilshift__",
++            default: "pyo3::class::number::PyNumberILShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__irshift__",
++            default: "pyo3::class::number::PyNumberIRShiftProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__iand__",
++            default: "pyo3::class::number::PyNumberIAndProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ixor__",
++            default: "pyo3::class::number::PyNumberIXorProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__ior__",
++            default: "pyo3::class::number::PyNumberIOrProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__neg__",
++            default: "pyo3::class::number::PyNumberNegProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__pos__",
++            default: "pyo3::class::number::PyNumberPosProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__abs__",
++            default: "pyo3::class::number::PyNumberAbsProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__invert__",
++            default: "pyo3::class::number::PyNumberInvertProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__complex__",
++            default: "pyo3::class::number::PyNumberComplexProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__int__",
++            default: "pyo3::class::number::PyNumberIntProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__float__",
++            default: "pyo3::class::number::PyNumberFloatProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__round__",
++            default: "pyo3::class::number::PyNumberRoundProtocolImpl",
++        },
++        DefaultImpl {
++            name: "__index__",
++            default: "pyo3::class::number::PyNumberIndexProtocolImpl",
++        },
++    ],
+ };
+ 
+ const PROTOCOLS: &[Proto] = &[
+diff --git a/pyo3-derive-backend/src/func.rs b/pyo3-derive-backend/src/func.rs
+index ce06716f4..05aede490 100644
+--- a/pyo3-derive-backend/src/func.rs
++++ b/pyo3-derive-backend/src/func.rs
+@@ -12,20 +12,17 @@ pub enum MethodProto {
+     Free {
+         name: &'static str,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Unary {
+         name: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Binary {
+         name: &'static str,
+         arg: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     BinaryS {
+         name: &'static str,
+@@ -33,7 +30,6 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Ternary {
+         name: &'static str,
+@@ -41,7 +37,6 @@ pub enum MethodProto {
+         arg2: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     TernaryS {
+         name: &'static str,
+@@ -50,7 +45,6 @@ pub enum MethodProto {
+         arg3: &'static str,
+         pyres: bool,
+         proto: &'static str,
+-        default: &'static str,
+     },
+     Quaternary {
+         name: &'static str,
+@@ -58,7 +52,6 @@ pub enum MethodProto {
+         arg2: &'static str,
+         arg3: &'static str,
+         proto: &'static str,
+-        default: &'static str,
+     },
+ }
+ 
+@@ -88,17 +81,6 @@ impl MethodProto {
+             MethodProto::Quaternary { proto: p, .. } => p,
+         }
+     }
+-    pub fn get_default(&self) -> &'static str {
+-        match *self {
+-            MethodProto::Free { default: d, .. } => d,
+-            MethodProto::Unary { default: d, .. } => d,
+-            MethodProto::Binary { default: d, .. } => d,
+-            MethodProto::BinaryS { default: d, .. } => d,
+-            MethodProto::Ternary { default: d, .. } => d,
+-            MethodProto::TernaryS { default: d, .. } => d,
+-            MethodProto::Quaternary { default: d, .. } => d,
+-        }
+-    }
+ }
+ 
+ pub fn impl_method_proto(
+@@ -151,7 +133,6 @@ pub fn impl_method_proto(
+             arg,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 println!("Not enough arguments for {}", name);
+@@ -197,7 +178,6 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 1 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -247,7 +227,6 @@ pub fn impl_method_proto(
+             arg2,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -301,7 +280,6 @@ pub fn impl_method_proto(
+             arg3,
+             pyres,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 2 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+@@ -358,7 +336,6 @@ pub fn impl_method_proto(
+             arg2,
+             arg3,
+             proto,
+-            default: _,
+         } => {
+             if sig.inputs.len() <= 3 {
+                 print_err(format!("Not enough arguments {}", name), quote!(sig));
+diff --git a/pyo3-derive-backend/src/pyproto.rs b/pyo3-derive-backend/src/pyproto.rs
+index a73232e1f..807be9052 100644
+--- a/pyo3-derive-backend/src/pyproto.rs
++++ b/pyo3-derive-backend/src/pyproto.rs
+@@ -9,6 +9,8 @@ use proc_macro2::TokenStream;
+ use quote::quote;
+ use quote::ToTokens;
+ 
++use std::collections::HashSet;
++
+ pub fn build_py_proto(ast: &mut syn::ItemImpl) -> syn::Result<TokenStream> {
+     if let Some((_, ref mut path, _)) = ast.trait_ {
+         let proto = if let Some(ref mut segment) = path.segments.last() {
+@@ -52,6 +54,7 @@ fn impl_proto_impl(
+ ) -> TokenStream {
+     let mut tokens = TokenStream::new();
+     let mut py_methods = Vec::new();
++    let mut implemented = HashSet::new();
+ 
+     let mut unimpl_methods: Vec<&MethodProto> = proto.methods.iter().collect();
+     let mut unimpl_py_methods: Vec<&defs::PyMethod> = proto.py_methods.iter().collect();
+@@ -59,6 +62,7 @@ fn impl_proto_impl(
+     for iimpl in impls.iter_mut() {
+         if let syn::ImplItem::Method(ref mut met) = iimpl {
+             let method_name = met.sig.ident.to_string();
++            implemented.insert(method_name.clone());
+             // Find the method in unimpl_methods, remove it and implement it
+             unimpl_methods
+                 .iter()
+@@ -105,13 +109,18 @@ fn impl_proto_impl(
+         }
+     }
+ 
+-    let default_impls: Vec<_> = unimpl_methods
++    let default_impls: Vec<_> = proto
++        .default_impls
+         .iter()
+-        .map(|m| {
+-            let proto: syn::Path = syn::parse_str(m.get_default()).unwrap();
+-            quote! { impl #proto for #ty {} }
++        .filter_map(|def| match implemented.contains(def.name) {
++            true => None,
++            false => {
++                let proto: syn::Path = syn::parse_str(def.default).unwrap();
++                Some(quote! { impl #proto for #ty {} })
++            }
+         })
+         .collect();
++
+     quote! {
+         #tokens
+ 
+diff --git a/tests/test_dict_iter.rp b/tests/test_dict_iter.rs
+similarity index 100%
+rename from tests/test_dict_iter.rp
+rename to tests/test_dict_iter.rs
diff --git a/srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch b/srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch
new file mode 100644
index 00000000000..a92cfe08a5b
--- /dev/null
+++ b/srcpkgs/anki/files/pyo3-patches/0020-remove-nightly-check.patch
@@ -0,0 +1,17 @@
+--- a/build.rs	2020-06-01 19:27:44.819141296 +1000
++++ b/build.rs	2020-06-01 19:29:51.770147574 +1000
+@@ -539,14 +539,6 @@
+             MIN_VERSION, actual_version
+         )
+     }
+-
+-    let actual_date = Date::read().expect("Failed to determine the rustc date");
+-    if !actual_date.at_least(MIN_DATE) {
+-        panic!(
+-            "pyo3 requires at least rustc {}, while the current rustc date is {}",
+-            MIN_DATE, actual_date
+-        )
+-    }
+ }
+ 
+ fn main() -> Result<(), String> {
diff --git a/srcpkgs/anki/patches/0001-aqt_data-fhs.patch b/srcpkgs/anki/patches/0001-aqt_data-fhs.patch
new file mode 100644
index 00000000000..ac0d29ec082
--- /dev/null
+++ b/srcpkgs/anki/patches/0001-aqt_data-fhs.patch
@@ -0,0 +1,45 @@
+From a0a9ac1aeb8b8678f1102aed81010a901ad8d9e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Johannes=20L=C3=B6thberg?= <johannes@kyriasis.com>
+Date: Sun, 29 Mar 2020 06:24:43 +0200
+Subject: [PATCH 1/4] Move aqt_data to sys.prefix/share
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+These files do _not_ belong right under sys.prefix.
+
+Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
+---
+ qt/aqt/utils.py | 2 +-
+ qt/setup.py     | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git qt/aqt/utils.py qt/aqt/utils.py
+index a0e12362..4d8c8c34 100644
+--- qt/aqt/utils.py
++++ qt/aqt/utils.py
+@@ -21,7 +21,7 @@ from aqt.theme import theme_manager
+ 
+ def aqt_data_folder() -> str:
+     # wheel install?
+-    dir = os.path.join(sys.prefix, "aqt_data")
++    dir = os.path.join(sys.prefix,"share", "aqt_data")
+     if not os.path.exists(dir) or not os.listdir(dir):
+         # running in place?
+         dir = os.path.join(os.path.dirname(__file__), "..", "aqt_data")
+diff --git qt/setup.py qt/setup.py
+index 38f4e2b7..bdda3baa 100644
+--- qt/setup.py
++++ qt/setup.py
+@@ -8,7 +8,7 @@ import setuptools
+ def package_files(directory):
+     entries = []
+     for (path, directories, filenames) in os.walk(directory):
+-        entries.append((path, [os.path.join(path, f) for f in filenames]))
++        entries.append((os.path.join("share", path), [os.path.join(path, f) for f in filenames]))
+     return entries
+ 
+ 
+-- 
+2.26.2
+
diff --git a/srcpkgs/anki/patches/0002-rust-nightly-fix.patch b/srcpkgs/anki/patches/0002-rust-nightly-fix.patch
new file mode 100644
index 00000000000..3d70aa36aad
--- /dev/null
+++ b/srcpkgs/anki/patches/0002-rust-nightly-fix.patch
@@ -0,0 +1,274 @@
+From fb578a0c2dc391f37de7cb6969c40f34d0de845c Mon Sep 17 00:00:00 2001
+From: Damien Elmes <gpg@ankiweb.net>
+Date: Fri, 24 Apr 2020 13:39:14 +1000
+Subject: [PATCH] switch to owned strings in ParsedTemplate
+
+will make it easier to cache the parsed results in the future,
+and handle field renames & other transformations
+---
+ rslib/src/notetype/cardgen.rs   |  6 +-
+ rslib/src/notetype/templates.rs |  2 +-
+ rslib/src/template.rs           | 98 +++++++++++++++++----------------
+ 3 files changed, 56 insertions(+), 50 deletions(-)
+
+Backported by fossy to stable. notetype patch is not needed.
+
+diff --git rslib/src/template.rs rslib/src/template.rs
+index 4479899009..ed5fe7e916 100644
+--- rslib/src/template.rs
++++ rslib/src/template.rs
+@@ -147,26 +147,26 @@ fn legacy_tokens(mut data: &str) -> impl Iterator<Item = TemplateResult<Token>>
+ //----------------------------------------
+ 
+ #[derive(Debug, PartialEq)]
+-enum ParsedNode<'a> {
+-    Text(&'a str),
++enum ParsedNode {
++    Text(String),
+     Replacement {
+-        key: &'a str,
+-        filters: Vec<&'a str>,
++        key: String,
++        filters: Vec<String>,
+     },
+     Conditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+     NegatedConditional {
+-        key: &'a str,
+-        children: Vec<ParsedNode<'a>>,
++        key: String,
++        children: Vec<ParsedNode>,
+     },
+ }
+ 
+ #[derive(Debug)]
+-pub struct ParsedTemplate<'a>(Vec<ParsedNode<'a>>);
++pub struct ParsedTemplate(Vec<ParsedNode>);
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Create a template from the provided text.
+     pub fn from_text(template: &str) -> TemplateResult<ParsedTemplate> {
+         let mut iter = tokens(template);
+@@ -177,26 +177,26 @@ impl ParsedTemplate<'_> {
+ fn parse_inner<'a, I: Iterator<Item = TemplateResult<Token<'a>>>>(
+     iter: &mut I,
+     open_tag: Option<&'a str>,
+-) -> TemplateResult<Vec<ParsedNode<'a>>> {
++) -> TemplateResult<Vec<ParsedNode>> {
+     let mut nodes = vec![];
+ 
+     while let Some(token) = iter.next() {
+         use Token::*;
+         nodes.push(match token? {
+-            Text(t) => ParsedNode::Text(t),
++            Text(t) => ParsedNode::Text(t.into()),
+             Replacement(t) => {
+                 let mut it = t.rsplit(':');
+                 ParsedNode::Replacement {
+-                    key: it.next().unwrap(),
+-                    filters: it.collect(),
++                    key: it.next().unwrap().into(),
++                    filters: it.map(Into::into).collect(),
+                 }
+             }
+             OpenConditional(t) => ParsedNode::Conditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             OpenNegated(t) => ParsedNode::NegatedConditional {
+-                key: t,
++                key: t.into(),
+                 children: parse_inner(iter, Some(t))?,
+             },
+             CloseConditional(t) => {
+@@ -285,27 +285,27 @@ fn localized_template_error(i18n: &I18n, err: TemplateError) -> String {
+ // Checking if template is empty
+ //----------------------------------------
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// true if provided fields are sufficient to render the template
+     pub fn renders_with_fields(&self, nonempty_fields: &HashSet<&str>) -> bool {
+         !template_is_empty(nonempty_fields, &self.0)
+     }
+ }
+ 
+-fn template_is_empty<'a>(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode<'a>]) -> bool {
++fn template_is_empty(nonempty_fields: &HashSet<&str>, nodes: &[ParsedNode]) -> bool {
+     use ParsedNode::*;
+     for node in nodes {
+         match node {
+             // ignore normal text
+             Text(_) => (),
+             Replacement { key, .. } => {
+-                if nonempty_fields.contains(*key) {
++                if nonempty_fields.contains(key.as_str()) {
+                     // a single replacement is enough
+                     return false;
+                 }
+             }
+             Conditional { key, children } => {
+-                if !nonempty_fields.contains(*key) {
++                if !nonempty_fields.contains(key.as_str()) {
+                     continue;
+                 }
+                 if !template_is_empty(nonempty_fields, children) {
+@@ -347,7 +347,7 @@ pub(crate) struct RenderContext<'a> {
+     pub card_ord: u16,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Render the template with the provided fields.
+     ///
+     /// Replacements that use only standard filters will become part of
+@@ -373,10 +373,7 @@ fn render_into(
+             Text(text) => {
+                 append_str_to_nodes(rendered_nodes, text);
+             }
+-            Replacement {
+-                key: key @ "FrontSide",
+-                ..
+-            } => {
++            Replacement { key, .. } if key == "FrontSide" => {
+                 // defer FrontSide rendering to Python, as extra
+                 // filters may be required
+                 rendered_nodes.push(RenderedNode::Replacement {
+@@ -385,27 +382,36 @@ fn render_into(
+                     current_text: "".into(),
+                 });
+             }
+-            Replacement { key: "", filters } if !filters.is_empty() => {
++            Replacement { key, filters } if key == "" && !filters.is_empty() => {
+                 // if a filter is provided, we accept an empty field name to
+                 // mean 'pass an empty string to the filter, and it will add
+                 // its own text'
+                 rendered_nodes.push(RenderedNode::Replacement {
+                     field_name: "".to_string(),
+                     current_text: "".to_string(),
+-                    filters: filters.iter().map(|&f| f.to_string()).collect(),
++                    filters: filters.clone(),
+                 })
+             }
+             Replacement { key, filters } => {
+                 // apply built in filters if field exists
+-                let (text, remaining_filters) = match context.fields.get(key) {
+-                    Some(text) => apply_filters(text, filters, key, context),
++                let (text, remaining_filters) = match context.fields.get(key.as_str()) {
++                    Some(text) => apply_filters(
++                        text,
++                        filters
++                            .iter()
++                            .map(|s| s.as_str())
++                            .collect::<Vec<_>>()
++                            .as_slice(),
++                        key,
++                        context,
++                    ),
+                     None => {
+                         // unknown field encountered
+                         let filters_str = filters
+                             .iter()
+                             .rev()
+                             .cloned()
+-                            .chain(iter::once(""))
++                            .chain(iter::once("".into()))
+                             .collect::<Vec<_>>()
+                             .join(":");
+                         return Err(TemplateError::FieldNotFound {
+@@ -427,12 +433,12 @@ fn render_into(
+                 }
+             }
+             Conditional { key, children } => {
+-                if context.nonempty_fields.contains(key) {
++                if context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+             NegatedConditional { key, children } => {
+-                if !context.nonempty_fields.contains(key) {
++                if !context.nonempty_fields.contains(key.as_str()) {
+                     render_into(rendered_nodes, children.as_ref(), context)?;
+                 }
+             }
+@@ -542,7 +548,7 @@ pub enum FieldRequirements {
+     None,
+ }
+ 
+-impl ParsedTemplate<'_> {
++impl ParsedTemplate {
+     /// Return fields required by template.
+     ///
+     /// This is not able to represent negated expressions or combinations of
+@@ -613,11 +619,11 @@
+             vec![
+-                Text("foo "),
++                Text("foo ".into()),
+                 Replacement {
+-                    key: "bar",
++                    key: "bar".into(),
+                     filters: vec![]
+                 },
+-                Text(" "),
++                Text(" ".into()),
+                 Conditional {
+-                    key: "baz",
+-                    children: vec![Text(" quux ")]
++                    key: "baz".into(),
++                    children: vec![Text(" quux ".into())]
+                 }
+             ]
+@@ -630,7 +636,7 @@ mod test {
+         assert_eq!(
+             tmpl.0,
+             vec![NegatedConditional {
+-                key: "baz",
++                key: "baz".into(),
+                 children: vec![]
+             }]
+         );
+@@ -643,7 +649,7 @@ mod test {
+         assert_eq!(
+             PT::from_text("{{ tag }}").unwrap().0,
+             vec![Replacement {
+-                key: "tag",
++                key: "tag".into(),
+                 filters: vec![]
+             }]
+         );
+@@ -651,7 +657,7 @@ mod test {
+         // stray closing characters (like in javascript) are ignored
+         assert_eq!(
+             PT::from_text("text }} more").unwrap().0,
+-            vec![Text("text }} more")]
++            vec![Text("text }} more".into())]
+         );
+ 
+         PT::from_text("{{").unwrap_err();
+@@ -737,15 +743,15 @@ mod test {
+         assert_eq!(
+             PT::from_text(input).unwrap().0,
+             vec![
+-                Text("\n"),
++                Text("\n".into()),
+                 Replacement {
+-                    key: "Front",
++                    key: "Front".into(),
+                     filters: vec![]
+                 },
+-                Text("\n"),
++                Text("\n".into()),
+                 Conditional {
+-                    key: "Back",
+-                    children: vec![Text("\n")]
++                    key: "Back".into(),
++                    children: vec![Text("\n".into())]
+                 }
+             ]
+         );
diff --git a/srcpkgs/anki/patches/0003-rustc-cross-compile.patch b/srcpkgs/anki/patches/0003-rustc-cross-compile.patch
new file mode 100644
index 00000000000..15239ea4cf1
--- /dev/null
+++ b/srcpkgs/anki/patches/0003-rustc-cross-compile.patch
@@ -0,0 +1,11 @@
+--- rspy/Makefile	2020-05-23 12:02:29.758286838 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -69,7 +69,7 @@
+ .build/build: $(DEPS)
+ 	touch ../proto/backend.proto
+ 	${BUILD_VARIABLES} \
+-		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS)
++		maturin build -i "${PYTHON_FILE}" -o "$(OUTDIR)" $(BUILDFLAGS) --target $(RUST_TARGET)
+    touch $@
+ 
+ check: .build/check
diff --git a/srcpkgs/anki/patches/0004-vendored-deps.patch b/srcpkgs/anki/patches/0004-vendored-deps.patch
new file mode 100644
index 00000000000..7ca936804fc
--- /dev/null
+++ b/srcpkgs/anki/patches/0004-vendored-deps.patch
@@ -0,0 +1,91 @@
+diff -u -r Makefile Makefile
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 18:40:54.345223164 +1000
+@@ -92,7 +92,7 @@
+ 	fi
+ 
+ .PHONY: develop
+-develop: pyenv buildhash prepare
++develop: buildhash prepare
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	for dir in $(DEVEL); do \
+diff -u -r pylib/Makefile pylib/Makefile
+--- pylib/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ pylib/Makefile	2020-05-19 18:50:01.075182994 +1000
+@@ -52,7 +52,7 @@
+ 	python -m black anki/hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks
++BUILD_STEPS := .build/vernum .build/py-proto anki/buildinfo.py .build/hooks
+ 
+ # Checking
+ ######################
+diff -u -r qt/Makefile qt/Makefile
+--- qt/Makefile	2020-05-08 18:17:57.000000000 +1000
++++ qt/Makefile	2020-05-19 18:50:17.520181786 +1000
+@@ -64,7 +64,7 @@
+ 	python -m black aqt/gui_hooks.py
+ 	@touch $@
+ 
+-BUILD_STEPS := .build/vernum .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
++BUILD_STEPS := .build/vernum .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n
+ 
+ # Checking
+ ######################
+--- Makefile	2020-05-08 18:17:57.000000000 +1000
++++ Makefile	2020-05-19 19:01:35.602131965 +1000
+@@ -122,7 +122,7 @@
+ 	@echo "Build complete."
+ 
+ .PHONY: build-rspy
+-build-rspy: pyenv buildhash
++build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+ 	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+--- Makefile	2020-05-19 19:41:44.191955000 +1000
++++ Makefile	2020-05-19 19:42:21.423952264 +1000
+@@ -124,19 +124,16 @@
+ .PHONY: build-rspy
+ build-rspy: buildhash
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C rspy build BUILDFLAGS="$(BUILDFLAGS)"
+ 
+ .PHONY: build-pylib
+ build-pylib:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C pylib build
+ 
+ .PHONY: build-qt
+ build-qt:
+ 	@set -eu -o pipefail ${SHELLFLAGS}; \
+-	. "${ACTIVATE_SCRIPT}"; \
+ 	$(SUBMAKE) -C qt build
+ 
+ .PHONY: clean
+--- pylib/Makefile	2020-05-22 08:46:14.988607539 +1000
++++ pylib/Makefile	2020-05-22 08:46:38.376605821 +1000
+@@ -41,7 +41,7 @@
+ 
+ PROTODEPS := $(wildcard ../proto/*.proto)
+ 
+-.build/py-proto: .build/dev-deps $(PROTODEPS)
++.build/py-proto: $(PROTODEPS)
+ 	protoc --proto_path=../proto --python_out=anki --mypy_out=anki $(PROTODEPS)
+ 	perl -i'' -pe 's/from fluent_pb2/from anki.fluent_pb2/' anki/backend_pb2.pyi
+ 	perl -i'' -pe 's/import fluent_pb2/import anki.fluent_pb2/' anki/backend_pb2.py
+--- rspy/Makefile	2020-05-31 08:59:03.810152342 +1000
++++ rspy/Makefile	2020-05-08 18:17:57.000000000 +1000
+@@ -51,7 +51,7 @@
+ 
+ develop: .build/develop
+ 
+-DEPS := .build/tools .build/vernum ../meta/buildhash \
++DEPS := .build/vernum ../meta/buildhash \
+ 	$(wildcard $(QT_FTL_TEMPLATES)/*.ftl) \
+ 	$(wildcard $(QT_FTL_LOCALES)/*/*.ftl) \
+ 	$(shell "${FIND}" ../rslib/src -name '*.rs') $(wildcard ../proto/*) \
diff --git a/srcpkgs/anki/patches/0005-patched-pyo3.patch b/srcpkgs/anki/patches/0005-patched-pyo3.patch
new file mode 100644
index 00000000000..15844cc15fe
--- /dev/null
+++ b/srcpkgs/anki/patches/0005-patched-pyo3.patch
@@ -0,0 +1,11 @@
+--- rspy/Cargo.toml	2020-05-08 18:17:57.000000000 +1000
++++ rspy/Cargo.toml.new	2020-05-30 17:46:26.548157472 +1000
+@@ -12,7 +12,7 @@
+ tokio = "0.2.11"
+ 
+ [dependencies.pyo3]
+-version = "0.8.0"
++path = "../../pyo3" 
+ features = ["extension-module"]
+ 
+ [lib]
diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template
index 680e008a9d4..4b89be6f8d0 100644
--- a/srcpkgs/anki/template
+++ b/srcpkgs/anki/template
@@ -1,23 +1,78 @@
 # Template file for 'anki'
+#
+# NOTE: This template does use rust stable. It has a rather large
+# pyo3 patchset taken from github.com/wickerwaka/pyo3/removing-specialization
+# which allows it to operate on rust stable. But, it is currently on pyo3
+# 0.8.1. This patchset should ideally be rebased for the new version.
+# Preliminary tests found this would be slightly difficult. Anki dosen't
+# need a newer version.. yet.
+#
 pkgname=anki
-version=2.1.15
-revision=2
-archs=noarch
+version=2.1.26
+revision=1
+_pyo3_version=0.8.1
 build_style=gnu-makefile
 pycompile_dirs="/usr/share/anki/anki /usr/share/anki/aqt"
+hostmakedepends="git python3 rust cargo maturin which protobuf
+ mypy-protobuf-python python3-stringcase black python3-wheel
+ rsync nodejs python3-PyQt5-devel-tools gettext
+ qt5-translations python3-pip strace"
 depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy
  python3-PyAudio python3-mpv python3-Markdown python3-send2trash
- python3-BeautifulSoup4 python3-decorator python3-jsonschema"
+ python3-BeautifulSoup4 python3-decorator python3-jsonschema
+ python3-protobuf"
 short_desc="Spaced repetition flashcard program"
 maintainer="Steve Prybylski <sa.prybylx@gmail.com>"
 license="AGPL-3.0-or-later"
 homepage="https://apps.ankiweb.net"
 changelog="https://apps.ankiweb.net/docs/changes.html"
-distfiles="https://apps.ankiweb.net/downloads/current/anki-${version}-source.tgz"
-checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89
-
+distfiles="https://github.com/ankitects/anki/archive/${version}.tar.gz
+		   https://github.com/PyO3/pyo3/archive/v${_pyo3_version}.tar.gz"
+checksum="f5a0c41f3eebe0e77de9d46f2a5cbbe20f7c3a4787f0f02e1d33f298428acbdf
+		  437a5fcb54113da9e2999fb957c8948ca40f4f31081b6e8cf1d798033071eb57"
 python_version=3
 
+post_extract() {
+	# Constant place for 0006-patched-pyo3.patch
+	mv "${XBPS_BUILDDIR}/pyo3-${_pyo3_version}" "${XBPS_BUILDDIR}/pyo3"
+}
+
+post_patch() {
+	# Apply patches for pyo3
+	cd "${XBPS_BUILDDIR}/pyo3"
+	for p in ${FILESDIR}/pyo3-patches/*.patch ; do
+		msg_normal "Applying ${p} to pyo3\n"
+		patch -Np1 -i ${p}
+	done
+}
+
+pre_build() {
+	mkdir -p dist
+	make prepare
+}
+
+do_build() {
+	RUSTFLAGS="-C target-feature=-crt-static" make build
+}
+
+do_install() {
+	pushd pylib
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	pushd qt
+		 python3 setup.py install --prefix=/usr --root=${DESTDIR}
+	popd
+
+	# maturin generates a .whl, this is all we can do
+	PIP_CONFIG_FILE=/dev/null pip3 install --isolated --root=${DESTDIR} --prefix=/usr --ignore-installed --no-deps dist/ankirspy*.whl
+
+	# Copied from arch's PKGBUILD
+	install -Dm755 qt/runanki "${DESTDIR}/usr/bin/anki"
+	install -Dm644 qt/anki.desktop "${DESTDIR}/usr/share/applications/anki.desktop"
+	install -Dm644 qt/anki.png "${DESTDIR}/usr/share/pixmaps/anki.png"
+}
+
 post_install() {
 	vlicense LICENSE
 }

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (7 preceding siblings ...)
  2020-06-01 10:05 ` [PR PATCH] [Updated] " fosslinux
@ 2020-06-01 10:28 ` fosslinux
  2020-06-01 12:05 ` stpx
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-06-01 10:28 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 285 bytes --]

New comment by fosslinux on void-packages repository

https://github.com/void-linux/void-packages/pull/22219#issuecomment-636769476

Comment:
@stpx Since this has pretty much morphed into a different, much more complex package, would you mind if I took maintainership of this package?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (8 preceding siblings ...)
  2020-06-01 10:28 ` fosslinux
@ 2020-06-01 12:05 ` stpx
  2020-12-23  1:33 ` [PR PATCH] [Closed]: " fosslinux
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: stpx @ 2020-06-01 12:05 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 708 bytes --]

New comment by stpx on void-packages repository

https://github.com/void-linux/void-packages/pull/22219#issuecomment-636819582

Comment:
Yes

On Mon, Jun 1, 2020, 6:28 AM fosslinux <notifications@github.com> wrote:

> @stpx <https://github.com/stpx> Since this has pretty much morphed into a
> different, much more complex package, would you mind if I took
> maintainership of this package?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/void-linux/void-packages/pull/22219#issuecomment-636769476>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AA4QBBOZCGOT5TG3MIIXYS3RUN7EBANCNFSM4NIKDL6A>
> .
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PR PATCH] [Closed]: WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (9 preceding siblings ...)
  2020-06-01 12:05 ` stpx
@ 2020-12-23  1:33 ` fosslinux
  2021-05-19 14:54 ` ericonr
  2021-05-19 16:12 ` sgn
  12 siblings, 0 replies; 14+ messages in thread
From: fosslinux @ 2020-12-23  1:33 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 1831 bytes --]

There's a closed pull request on the void-packages repository

WIP: anki: update to 2.1.26
https://github.com/void-linux/void-packages/pull/22219

Description:
This has a wide variety of changes as if you have heard my ranting in #xbps it has turned into a Bad Build System - there is rust, nodejs, python, etc etc, no proper install target...

A few things to note:

- python3-mypy is updated as mypy-protobuf needs the new version, otherwise the build failed.
- same thing with python-protobuf, but for anki and at runtime
- maturin is some weird build system at the intersection of rust and python.
- mypy-protobuf-python is what anki uses for binding python and rust together, partly.
- mypy-protobuf-go is the go implementation of mypy-protobuf-python that I thought should be packaged anywway.
- python-stringcase is a new dependency.
- anki is an archd package (not nocross), because the rust code is obviously platform specific.

Still todo:

- [x] Apply archlinux's aqt_build patch, which stops it from polluting /usr directly (:vomiting_face:)
- [x] Update python3-protobuf - hopefully will fix `AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'`.
- [x] Look into travis musl error. https://github.com/rust-lang/rust/issues/40174. Hopefully, using rust 1.44 as the rust version *should* fix this. What a PITA. I understand that this is because it works when I cross-compile to x86_64-musl from x86_64 but we need it to work native build from x86_64-musl for the builders...
- [x] Get off rustup and onto rust stable. Needs either a) pyo3 to work on stable or b) anki to be patched for rust-cpython.
- [x] Blocked by rust 1.44. Blocked by #22739
- [ ] Travis wth on i686?
- [x] Make it open.
- [x] More extensive runtime testing.
- [ ] Runtime test on musl.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (10 preceding siblings ...)
  2020-12-23  1:33 ` [PR PATCH] [Closed]: " fosslinux
@ 2021-05-19 14:54 ` ericonr
  2021-05-19 16:12 ` sgn
  12 siblings, 0 replies; 14+ messages in thread
From: ericonr @ 2021-05-19 14:54 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 229 bytes --]

New comment by ericonr on void-packages repository

https://github.com/void-linux/void-packages/pull/22219#issuecomment-844184088

Comment:
@fosslinux we supposedly have working maturin in repos now, if you want to try it again?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: WIP: anki: update to 2.1.26
  2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
                   ` (11 preceding siblings ...)
  2021-05-19 14:54 ` ericonr
@ 2021-05-19 16:12 ` sgn
  12 siblings, 0 replies; 14+ messages in thread
From: sgn @ 2021-05-19 16:12 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 238 bytes --]

New comment by sgn on void-packages repository

https://github.com/void-linux/void-packages/pull/22219#issuecomment-844254110

Comment:
The situation has been changed. Last I check, anki has been moved to bazel, which is another monster.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2021-05-19 16:12 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-23  6:18 [PR PATCH] WIP: anki: update to 2.1.26 fosslinux
2020-05-23  7:07 ` [PR PATCH] [Updated] " fosslinux
2020-05-24  5:37 ` fosslinux
2020-05-24  5:39 ` fosslinux
2020-05-28  7:38 ` [PR PATCH] [Updated] " fosslinux
2020-05-30  1:53 ` fosslinux
2020-06-01  9:58 ` fosslinux
2020-06-01  9:59 ` fosslinux
2020-06-01 10:05 ` [PR PATCH] [Updated] " fosslinux
2020-06-01 10:28 ` fosslinux
2020-06-01 12:05 ` stpx
2020-12-23  1:33 ` [PR PATCH] [Closed]: " fosslinux
2021-05-19 14:54 ` ericonr
2021-05-19 16:12 ` sgn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).