From 9dd54c421b835d0dde14291160237d2e176d3869 Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Mon, 16 Mar 2020 13:53:56 -0300 Subject: [PATCH 01/24] Fixed UnicodeEncodeError: 'charmap' codec can't encode character '\u2068' in position 2724: character maps to for pylib/tests/test_stats.py --- pylib/tests/test_stats.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pylib/tests/test_stats.py b/pylib/tests/test_stats.py index 7de3dc831..045983ac0 100644 --- a/pylib/tests/test_stats.py +++ b/pylib/tests/test_stats.py @@ -1,4 +1,5 @@ -# coding: utf-8 +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- import os import tempfile @@ -34,6 +35,6 @@ def test_graphs(): d = aopen(os.path.join(dir, "test.anki2")) g = d.stats() rep = g.report() - with open(os.path.join(dir, "test.html"), "w") as f: + with open(os.path.join(dir, "test.html"), "w", encoding="UTF-8") as f: f.write(rep) return From 88ea0b18bf583182ede5c5aa6915646c205c6fa1 Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Mon, 16 Mar 2020 15:18:37 -0300 Subject: [PATCH 02/24] Fixed test_importing.py unit tests failing on windows with PermissionError: [Errno 13] Permission denied --- pylib/tests/test_importing.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/pylib/tests/test_importing.py b/pylib/tests/test_importing.py index fc90dcfe0..b563c1734 100644 --- a/pylib/tests/test_importing.py +++ b/pylib/tests/test_importing.py @@ -18,6 +18,15 @@ srcNotes = None srcCards = None +def clear_tempfile(tf): + """ https://stackoverflow.com/questions/23212435/permission-denied-to-write-to-my-temporary-file """ + try: + tf.close() + os.unlink(tf.name) + except: + pass + + def test_anki2_mediadupes(): tmp = getEmptyCol() # add a note that references a sound @@ -208,13 +217,15 @@ def test_tsv_tag_modified(): n.addTag("four") deck.addNote(n) - with NamedTemporaryFile(mode="w") as tf: + # https://stackoverflow.com/questions/23212435/permission-denied-to-write-to-my-temporary-file + with NamedTemporaryFile(mode="w", delete=False) as tf: tf.write("1\tb\tc\n") tf.flush() i = TextImporter(deck, tf.name) i.initMapping() i.tagModified = "boom" i.run() + clear_tempfile(tf) n.load() assert n["Front"] == "1" @@ -243,13 +254,15 @@ def test_tsv_tag_multiple_tags(): n.addTag("five") deck.addNote(n) - with NamedTemporaryFile(mode="w") as tf: + # https://stackoverflow.com/questions/23212435/permission-denied-to-write-to-my-temporary-file + with NamedTemporaryFile(mode="w", delete=False) as tf: tf.write("1\tb\tc\n") tf.flush() i = TextImporter(deck, tf.name) i.initMapping() i.tagModified = "five six" i.run() + clear_tempfile(tf) n.load() assert n["Front"] == "1" @@ -273,13 +286,15 @@ def test_csv_tag_only_if_modified(): n["Left"] = "3" deck.addNote(n) - with NamedTemporaryFile(mode="w") as tf: + # https://stackoverflow.com/questions/23212435/permission-denied-to-write-to-my-temporary-file + with NamedTemporaryFile(mode="w", delete=False) as tf: tf.write("1,2,3\n") tf.flush() i = TextImporter(deck, tf.name) i.initMapping() i.tagModified = "right" i.run() + clear_tempfile(tf) n.load() assert n.tags == [] From d6f900647b95358ada23f5777b99490c910669db Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Mon, 16 Mar 2020 15:39:37 -0300 Subject: [PATCH 03/24] Fixed trailing-newlines.sh not failing when rg is not installed --- .github/scripts/trailing-newlines.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/scripts/trailing-newlines.sh b/.github/scripts/trailing-newlines.sh index e2009df8c..b5fc4bac4 100755 --- a/.github/scripts/trailing-newlines.sh +++ b/.github/scripts/trailing-newlines.sh @@ -1,8 +1,12 @@ #!/bin/bash -set -e +set -eo pipefail -files=$(rg -l '[^\n]\z' -g '!*.{svg,scss,json}' || true) +# Checking version to force it fail the build if rg is not installed. +# Because `set -e` does not work inside the subshell $() +rg --version + +files=$(rg -l '[^\n]\z' -g '!*.{png,svg,scss,json}' || true) if [ "$files" != "" ]; then echo "the following files are missing a newline on the last line:" echo $files From 07a24c0d42a773cb62b8e5a10a70d1ec3d1e96ed Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Mon, 16 Mar 2020 15:53:10 -0300 Subject: [PATCH 04/24] Fixed make check for pylint not working on Windows due F:\Python\python.exe: can't open file '/cygdrive/f/anki/pyenv/Scripts/pylint': [Errno 2] No such file or directory --- pylib/Makefile | 10 +++++----- qt/Makefile | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pylib/Makefile b/pylib/Makefile index c78af5bf4..96ed9cfd0 100644 --- a/pylib/Makefile +++ b/pylib/Makefile @@ -33,7 +33,7 @@ PROTODEPS := $(wildcard ../proto/*.proto) .build/hooks: tools/genhooks.py tools/hookslib.py python tools/genhooks.py - black anki/hooks.py + python -m black anki/hooks.py @touch $@ BUILD_STEPS := .build/run-deps .build/dev-deps .build/py-proto anki/buildinfo.py .build/hooks @@ -47,7 +47,7 @@ check: $(BUILD_STEPS) .build/mypy .build/test .build/fmt .build/imports .build/l .PHONY: fix fix: $(BUILD_STEPS) isort $(ISORTARGS) - black $(BLACKARGS) + python -m black $(BLACKARGS) .PHONY: clean clean: @@ -59,7 +59,7 @@ clean: CHECKDEPS := $(shell ${FIND} anki tests -name '*.py' | grep -v buildinfo.py) .build/mypy: $(CHECKDEPS) - mypy anki + python -m mypy anki @touch $@ .build/test: $(CHECKDEPS) @@ -67,7 +67,7 @@ CHECKDEPS := $(shell ${FIND} anki tests -name '*.py' | grep -v buildinfo.py) @touch $@ .build/lint: $(CHECKDEPS) - pylint -j 0 --rcfile=.pylintrc -f colorized --extension-pkg-whitelist=ankirspy anki tests setup.py + python -m pylint -j 0 --rcfile=.pylintrc -f colorized --extension-pkg-whitelist=ankirspy anki tests setup.py @touch $@ .build/imports: $(CHECKDEPS) @@ -75,7 +75,7 @@ CHECKDEPS := $(shell ${FIND} anki tests -name '*.py' | grep -v buildinfo.py) @touch $@ .build/fmt: $(CHECKDEPS) - black --check $(BLACKARGS) + python -m black --check $(BLACKARGS) @touch $@ # Building diff --git a/qt/Makefile b/qt/Makefile index 82cd91292..e6aa5e899 100644 --- a/qt/Makefile +++ b/qt/Makefile @@ -42,7 +42,7 @@ TSDEPS := $(wildcard ts/src/*.ts) $(wildcard ts/scss/*.scss) .build/hooks: tools/genhooks_gui.py ../pylib/tools/hookslib.py python tools/genhooks_gui.py - black aqt/gui_hooks.py + python -m black aqt/gui_hooks.py @touch $@ BUILD_STEPS := .build/run-deps .build/dev-deps .build/js .build/ui aqt/buildinfo.py .build/hooks .build/i18n @@ -56,7 +56,7 @@ check: $(BUILD_STEPS) .build/mypy .build/test .build/fmt .build/imports .build/l .PHONY: fix fix: $(BUILD_STEPS) isort $(ISORTARGS) - black $(BLACKARGS) + python -m black $(BLACKARGS) (cd ts && npm run pretty) .PHONY: clean @@ -80,7 +80,7 @@ PYLIB := ../pylib CHECKDEPS := $(shell ${FIND} aqt tests -name '*.py' | grep -v buildinfo.py) .build/mypy: $(CHECKDEPS) .build/qt-stubs - mypy aqt + python -m mypy aqt @touch $@ .build/test: $(CHECKDEPS) @@ -88,7 +88,7 @@ CHECKDEPS := $(shell ${FIND} aqt tests -name '*.py' | grep -v buildinfo.py) @touch $@ .build/lint: $(CHECKDEPS) - pylint -j 0 --rcfile=.pylintrc -f colorized --extension-pkg-whitelist=PyQt5,ankirspy aqt tests setup.py + python -m pylint -j 0 --rcfile=.pylintrc -f colorized --extension-pkg-whitelist=PyQt5,ankirspy aqt tests setup.py @touch $@ .build/imports: $(CHECKDEPS) @@ -96,7 +96,7 @@ CHECKDEPS := $(shell ${FIND} aqt tests -name '*.py' | grep -v buildinfo.py) @touch $@ .build/fmt: $(CHECKDEPS) - black --check $(BLACKARGS) + python -m black --check $(BLACKARGS) @touch $@ .build/qt-stubs: From 51823bf1ff64ad41b5dc2e648401056595118edb Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Mon, 16 Mar 2020 15:54:59 -0300 Subject: [PATCH 05/24] Fixed typecheck-setup.sh: sudo: command not found on Windows --- qt/po/scripts/copy-qt-files | 2 +- qt/tools/typecheck-setup.sh | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/qt/po/scripts/copy-qt-files b/qt/po/scripts/copy-qt-files index 0a8a7eb25..71218733a 100755 --- a/qt/po/scripts/copy-qt-files +++ b/qt/po/scripts/copy-qt-files @@ -14,4 +14,4 @@ case "${unameOut}" in ;; esac -rsync -a "$qtTranslations"/qt* "$out" +rsync -a "$qtTranslations/" "$out/" diff --git a/qt/tools/typecheck-setup.sh b/qt/tools/typecheck-setup.sh index 65311f07c..a8c3cca25 100755 --- a/qt/tools/typecheck-setup.sh +++ b/qt/tools/typecheck-setup.sh @@ -6,8 +6,23 @@ # able to resolve. A solution that doesn't require modifying the python install # would be welcome! -TOOLS="$(cd "`dirname "$0"`"; pwd)" -modDir=$(python -c 'import PyQt5, sys, os; print(os.path.dirname(sys.modules["PyQt5"].__file__))') -cmd="rsync -a $TOOLS/stubs/PyQt5/* $modDir/" +set -eo pipefail -$cmd > /dev/null 2>&1 || sudo $cmd +TOOLS="$(cd "`dirname "$0"`"; pwd)" +modDir=$(python -c 'import PyQt5, sys, os; sys.stdout.write(os.path.dirname(sys.modules["PyQt5"].__file__))') + +unameOut="$(uname -s)" +case "${unameOut}" in + CYGWIN*) + modDir="$(cygpath -u "${modDir}")" + ;; +esac + +cmd="rsync -a \"${TOOLS}/stubs/PyQt5/\" \"${modDir}/\"" + +if [[ "w${OS}" == "wWindows_NT" ]]; +then + eval "${cmd}" > /dev/null 2>&1 || eval "${cmd}" +else + eval "${cmd}" > /dev/null 2>&1 || eval "${cmd}" || eval "sudo ${cmd}" +fi From 034ac10cf46e8cf26982fcef87864bc3c751ce09 Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Tue, 17 Mar 2020 00:24:37 -0300 Subject: [PATCH 06/24] Fixed error: Incompatible types in assignment on qt/aqt/main.py aqt\main.py:1437: error: Incompatible types in assignment (expression has type Module, variable has type "LibraryLoader[WinDLL]") [assignment] _dummy = wintypes ^ --- qt/aqt/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qt/aqt/main.py b/qt/aqt/main.py index 3f3034bb5..7b17bf50f 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -1430,11 +1430,11 @@ will be lost. Continue?""" self.maybeHideAccelerators() self.hideStatusTips() elif isWin: - # make sure ctypes is bundled from ctypes import windll, wintypes # type: ignore - _dummy = windll - _dummy = wintypes + # make sure ctypes is bundled + _dummy1 = windll + _dummy2 = wintypes def maybeHideAccelerators(self, tgt: Optional[Any] = None) -> None: if not self.hideMenuAccels: From 802c5b59cb3e7e7a241c764ef92f117f4510f4c6 Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Tue, 17 Mar 2020 01:11:49 -0300 Subject: [PATCH 07/24] Fixed mypy and pylint not building on Windows 1. error: unused 'type: ignore' comment 2. Module 'pywintypes' has no 'error' member 3. Module 'win32pipe' has no 'SetNamedPipeHandleState' member, but source is unavailable. Consider adding this module to extension-pkg-whitelist if you want to perform analysis based on run-time introspection of living objects. --- Makefile | 2 +- pylib/Makefile | 21 +++++++++++++++++++-- pylib/mypy.ini | 1 - qt/Makefile | 24 ++++++++++++++++++++++-- qt/mypy.ini | 1 - rspy/Makefile | 2 +- 6 files changed, 43 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index fdfa2c182..5ade34310 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ifndef OS OS := unknown endif -ifeq ($(OS),Windows_NT) +ifeq (${OS},Windows_NT) ifndef ACTIVATE_SCRIPT ACTIVATE_SCRIPT := pyenv/Scripts/activate endif diff --git a/pylib/Makefile b/pylib/Makefile index 96ed9cfd0..a81d32416 100644 --- a/pylib/Makefile +++ b/pylib/Makefile @@ -1,5 +1,21 @@ SHELL := /bin/bash FIND := $(if $(wildcard /bin/find),/bin/find,/usr/bin/find) +MYPY_IGNORED_IMPORTS := + +ifndef OS + OS := unknown +endif + +ifndef UNAME + UNAME := unknown +endif + +# https://anki.tenderapp.com/discussions/beta-testing/1860-error-unused-type-ignore-comment +ifneq (${OS},Windows_NT) + ifneq (${UNAME},Darwin) + MYPY_IGNORED_IMPORTS := --warn-unused-ignores + endif +endif .SHELLFLAGS := -eu -o pipefail -c .DELETE_ON_ERROR: @@ -59,7 +75,7 @@ clean: CHECKDEPS := $(shell ${FIND} anki tests -name '*.py' | grep -v buildinfo.py) .build/mypy: $(CHECKDEPS) - python -m mypy anki + python -m mypy ${MYPY_IGNORED_IMPORTS} anki @touch $@ .build/test: $(CHECKDEPS) @@ -67,7 +83,8 @@ CHECKDEPS := $(shell ${FIND} anki tests -name '*.py' | grep -v buildinfo.py) @touch $@ .build/lint: $(CHECKDEPS) - python -m pylint -j 0 --rcfile=.pylintrc -f colorized --extension-pkg-whitelist=ankirspy anki tests setup.py + python -m pylint -j 0 --rcfile=.pylintrc -f colorized \ + --extension-pkg-whitelist=ankirspy anki tests setup.py @touch $@ .build/imports: $(CHECKDEPS) diff --git a/pylib/mypy.ini b/pylib/mypy.ini index 4215061bb..6ad6b351b 100644 --- a/pylib/mypy.ini +++ b/pylib/mypy.ini @@ -7,7 +7,6 @@ check_untyped_defs = true disallow_untyped_decorators = True warn_redundant_casts = True warn_unused_configs = True -warn_unused_ignores = True [mypy-win32file] ignore_missing_imports = True diff --git a/qt/Makefile b/qt/Makefile index e6aa5e899..ce9f8961f 100644 --- a/qt/Makefile +++ b/qt/Makefile @@ -1,5 +1,24 @@ SHELL := /bin/bash FIND := $(if $(wildcard /bin/find),/bin/find,/usr/bin/find) +MYPY_IGNORED_IMPORTS := +PYLINT_IGNORED_MODULES := + +ifndef OS + OS := unknown +endif + +ifndef UNAME + UNAME := unknown +endif + +# https://anki.tenderapp.com/discussions/beta-testing/1860-error-unused-type-ignore-comment +ifneq (${OS},Windows_NT) + ifneq (${UNAME},Darwin) + MYPY_IGNORED_IMPORTS := --warn-unused-ignores + endif +else + PYLINT_IGNORED_MODULES := --ignored-modules=win32file,pywintypes,socket,win32pipe +endif .SHELLFLAGS := -eu -o pipefail -c .DELETE_ON_ERROR: @@ -80,7 +99,7 @@ PYLIB := ../pylib CHECKDEPS := $(shell ${FIND} aqt tests -name '*.py' | grep -v buildinfo.py) .build/mypy: $(CHECKDEPS) .build/qt-stubs - python -m mypy aqt + python -m mypy ${MYPY_IGNORED_IMPORTS} aqt @touch $@ .build/test: $(CHECKDEPS) @@ -88,7 +107,8 @@ CHECKDEPS := $(shell ${FIND} aqt tests -name '*.py' | grep -v buildinfo.py) @touch $@ .build/lint: $(CHECKDEPS) - python -m pylint -j 0 --rcfile=.pylintrc -f colorized --extension-pkg-whitelist=PyQt5,ankirspy aqt tests setup.py + python -m pylint -j 0 --rcfile=.pylintrc -f colorized ${PYLINT_IGNORED_MODULES} \ + --extension-pkg-whitelist=PyQt5,ankirspy aqt tests setup.py @touch $@ .build/imports: $(CHECKDEPS) diff --git a/qt/mypy.ini b/qt/mypy.ini index 5d5a5ca40..a69375016 100644 --- a/qt/mypy.ini +++ b/qt/mypy.ini @@ -6,7 +6,6 @@ show_error_codes = true disallow_untyped_decorators = True warn_redundant_casts = True warn_unused_configs = True -warn_unused_ignores = True [mypy-win32file] ignore_missing_imports = True diff --git a/rspy/Makefile b/rspy/Makefile index 798a67515..49c5237b6 100644 --- a/rspy/Makefile +++ b/rspy/Makefile @@ -5,7 +5,7 @@ ifndef OS OS := unknown endif -ifeq ($(OS),Windows_NT) +ifeq (${OS},Windows_NT) ifndef PYTHON_BIN PYTHON_BIN := python endif From 1ade1a1a0f79b8d6a4343e02fdd6a799115467e3 Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Wed, 18 Mar 2020 11:36:32 -0300 Subject: [PATCH 08/24] Fixed moved comment line on qt/aqt/main.py, long variables names on pylib/Makefile and qt/Makefile, and rg --version not going to /dev/null on .github/scripts/trailing-newlines.sh --- .github/scripts/trailing-newlines.sh | 2 +- pylib/Makefile | 8 +++----- qt/Makefile | 14 ++++++-------- qt/aqt/main.py | 2 +- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.github/scripts/trailing-newlines.sh b/.github/scripts/trailing-newlines.sh index b5fc4bac4..cf27e9695 100755 --- a/.github/scripts/trailing-newlines.sh +++ b/.github/scripts/trailing-newlines.sh @@ -4,7 +4,7 @@ set -eo pipefail # Checking version to force it fail the build if rg is not installed. # Because `set -e` does not work inside the subshell $() -rg --version +rg --version > /dev/null 2>&1 files=$(rg -l '[^\n]\z' -g '!*.{png,svg,scss,json}' || true) if [ "$files" != "" ]; then diff --git a/pylib/Makefile b/pylib/Makefile index a81d32416..a168d00dc 100644 --- a/pylib/Makefile +++ b/pylib/Makefile @@ -1,6 +1,6 @@ SHELL := /bin/bash FIND := $(if $(wildcard /bin/find),/bin/find,/usr/bin/find) -MYPY_IGNORED_IMPORTS := +MYPY_ARGS := ifndef OS OS := unknown @@ -12,9 +12,7 @@ endif # https://anki.tenderapp.com/discussions/beta-testing/1860-error-unused-type-ignore-comment ifneq (${OS},Windows_NT) - ifneq (${UNAME},Darwin) - MYPY_IGNORED_IMPORTS := --warn-unused-ignores - endif + MYPY_ARGS := --warn-unused-ignores endif .SHELLFLAGS := -eu -o pipefail -c @@ -75,7 +73,7 @@ clean: CHECKDEPS := $(shell ${FIND} anki tests -name '*.py' | grep -v buildinfo.py) .build/mypy: $(CHECKDEPS) - python -m mypy ${MYPY_IGNORED_IMPORTS} anki + python -m mypy ${MYPY_ARGS} anki @touch $@ .build/test: $(CHECKDEPS) diff --git a/qt/Makefile b/qt/Makefile index ce9f8961f..9793e0cb8 100644 --- a/qt/Makefile +++ b/qt/Makefile @@ -1,7 +1,7 @@ SHELL := /bin/bash FIND := $(if $(wildcard /bin/find),/bin/find,/usr/bin/find) -MYPY_IGNORED_IMPORTS := -PYLINT_IGNORED_MODULES := +MYPY_ARGS := +PYLINT_ARGS := ifndef OS OS := unknown @@ -13,11 +13,9 @@ endif # https://anki.tenderapp.com/discussions/beta-testing/1860-error-unused-type-ignore-comment ifneq (${OS},Windows_NT) - ifneq (${UNAME},Darwin) - MYPY_IGNORED_IMPORTS := --warn-unused-ignores - endif + MYPY_ARGS := --warn-unused-ignores else - PYLINT_IGNORED_MODULES := --ignored-modules=win32file,pywintypes,socket,win32pipe + PYLINT_ARGS := --ignored-modules=win32file,pywintypes,socket,win32pipe endif .SHELLFLAGS := -eu -o pipefail -c @@ -99,7 +97,7 @@ PYLIB := ../pylib CHECKDEPS := $(shell ${FIND} aqt tests -name '*.py' | grep -v buildinfo.py) .build/mypy: $(CHECKDEPS) .build/qt-stubs - python -m mypy ${MYPY_IGNORED_IMPORTS} aqt + python -m mypy ${MYPY_ARGS} aqt @touch $@ .build/test: $(CHECKDEPS) @@ -107,7 +105,7 @@ CHECKDEPS := $(shell ${FIND} aqt tests -name '*.py' | grep -v buildinfo.py) @touch $@ .build/lint: $(CHECKDEPS) - python -m pylint -j 0 --rcfile=.pylintrc -f colorized ${PYLINT_IGNORED_MODULES} \ + python -m pylint -j 0 --rcfile=.pylintrc -f colorized ${PYLINT_ARGS} \ --extension-pkg-whitelist=PyQt5,ankirspy aqt tests setup.py @touch $@ diff --git a/qt/aqt/main.py b/qt/aqt/main.py index 7b17bf50f..b31d40ebe 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -1430,9 +1430,9 @@ will be lost. Continue?""" self.maybeHideAccelerators() self.hideStatusTips() elif isWin: + # make sure ctypes is bundled from ctypes import windll, wintypes # type: ignore - # make sure ctypes is bundled _dummy1 = windll _dummy2 = wintypes From f2f92fb0c398503382184456919ef08878ef096e Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 22 Mar 2020 17:15:47 +0100 Subject: [PATCH 09/24] editor_did_init That would be useful to add elements in the editor, such as in multi column editor --- qt/aqt/editor.py | 1 + qt/aqt/gui_hooks.py | 24 ++++++++++++++++++++++++ qt/tools/genhooks_gui.py | 1 + 3 files changed, 26 insertions(+) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index ed183e40e..b2199a238 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -83,6 +83,7 @@ class Editor: self.setupWeb() self.setupShortcuts() self.setupTags() + gui_hooks.editor_did_init(self) # Initial setup ############################################################ diff --git a/qt/aqt/gui_hooks.py b/qt/aqt/gui_hooks.py index a066504ab..0115ef948 100644 --- a/qt/aqt/gui_hooks.py +++ b/qt/aqt/gui_hooks.py @@ -1028,6 +1028,30 @@ class _EditorDidFocusFieldHook: editor_did_focus_field = _EditorDidFocusFieldHook() +class _EditorDidInitHook: + _hooks: List[Callable[["aqt.editor.Editor"], None]] = [] + + def append(self, cb: Callable[["aqt.editor.Editor"], None]) -> None: + """(editor: aqt.editor.Editor)""" + self._hooks.append(cb) + + def remove(self, cb: Callable[["aqt.editor.Editor"], None]) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__(self, editor: aqt.editor.Editor) -> None: + for hook in self._hooks: + try: + hook(editor) + except: + # if the hook fails, remove it + self._hooks.remove(hook) + raise + + +editor_did_init = _EditorDidInitHook() + + class _EditorDidInitButtonsHook: _hooks: List[Callable[[List, "aqt.editor.Editor"], None]] = [] diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index be3232a92..1dd08c430 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -497,6 +497,7 @@ def emptyNewCard(): name="editor_web_view_did_init", args=["editor_web_view: aqt.editor.EditorWebView"], ), + Hook(name="editor_did_init", args=["editor: aqt.editor.Editor"],), # Sound/video ################### Hook(name="av_player_will_play", args=["tag: anki.sound.AVTag"]), From 349d145014cd48bbe6f1a2eb864904f2797f5922 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Mon, 23 Mar 2020 07:55:48 +0100 Subject: [PATCH 10/24] Ident html in editor Sometime I like to print html to understand why it bugs. And I really prefer to have html indented if it's okay with you. There is no change appart from the identation and quotes --- qt/aqt/editor.py | 75 +++++++++++++++++++++++++++++++-------------- qt/ts/src/editor.ts | 41 +++++++++++++++++-------- 2 files changed, 80 insertions(+), 36 deletions(-) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index ed183e40e..6bbb830aa 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -63,9 +63,18 @@ _html = """ html { background: %s; } #topbutsOuter { background: %s; } -
%s
-
- +
+
+%s +
+
+
+
+ """ # caller is responsible for resetting note on reset @@ -117,20 +126,35 @@ class Editor: # The color selection buttons do not use an icon so the HTML must be specified manually tip = _("Set foreground colour (F7)") righttopbtns.append( - """""".format( + """ """.format( tip ) ) tip = _("Change colour (F8)") righttopbtns.extend( [ - """""".format( + """""".format( tip ), self._addButton( @@ -249,18 +273,23 @@ class Editor: theclass = "linkb" if not disables: theclass += " perm" - return ( - '''""".format( - imgelm=imgelm, - cmd=cmd, - tip=tip, - labelelm=labelelm, - id=idstr, - togglesc=toggleScript, - theclass=theclass, - ) + return """ """.format( + imgelm=imgelm, + cmd=cmd, + tip=tip, + labelelm=labelelm, + id=idstr, + togglesc=toggleScript, + theclass=theclass, ) def setupShortcuts(self) -> None: diff --git a/qt/ts/src/editor.ts b/qt/ts/src/editor.ts index f3eba5c4a..87bf61e80 100644 --- a/qt/ts/src/editor.ts +++ b/qt/ts/src/editor.ts @@ -333,20 +333,35 @@ function setFields(fields) { if (!f) { f = "
"; } - txt += `${n}`; - txt += `
${f}
`; - txt += ""; + txt += ` + + ${n} + + + +
+${f} +
+ + `; } - $("#fields").html( - "" + - txt + - "
" - ); + $("#fields").html(` + +${txt} +
`); maybeDisableButtons(); } From 0c39c4f106f6b901200f073200f6ac0b0fac1c80 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Mon, 23 Mar 2020 16:52:24 +0100 Subject: [PATCH 11/24] add an id to name tab --- qt/ts/src/editor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt/ts/src/editor.ts b/qt/ts/src/editor.ts index 87bf61e80..890e884b0 100644 --- a/qt/ts/src/editor.ts +++ b/qt/ts/src/editor.ts @@ -335,7 +335,7 @@ function setFields(fields) { } txt += ` - ${n} + ${n} From 521b0e9e142aa7d0b3564011efeea225d649d491 Mon Sep 17 00:00:00 2001 From: Hk-tang Date: Mon, 23 Mar 2020 11:16:39 -0600 Subject: [PATCH 12/24] Change not not to bool --- qt/aqt/browser.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index 4c38a70ec..bb587a78a 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -865,7 +865,7 @@ QTableView {{ gridline-color: {grid} }} def _onRowChanged(self, current, previous) -> None: update = self.updateTitle() show = self.model.cards and update == 1 - self.form.splitter.widget(1).setVisible(not not show) + self.form.splitter.widget(1).setVisible(bool(show)) idx = self.form.tableView.selectionModel().currentIndex() if idx.isValid(): self.card = self.model.getCard(idx) @@ -1660,12 +1660,12 @@ where id in %s""" and self._previewState == "answer" and not self._previewBothSides ) - self._previewPrev.setEnabled(not not (self.singleCard and canBack)) + self._previewPrev.setEnabled(bool(self.singleCard and canBack)) canForward = ( self.currentRow() < self.model.rowCount(None) - 1 or self._previewState == "question" ) - self._previewNext.setEnabled(not not (self.singleCard and canForward)) + self._previewNext.setEnabled(bool(self.singleCard and canForward)) def _closePreview(self): if self._previewWindow: @@ -1925,7 +1925,7 @@ update cards set usn=?, mod=?, did=? where id in """ ###################################################################### def isSuspended(self): - return not not (self.card and self.card.queue == QUEUE_TYPE_SUSPENDED) + return bool(self.card and self.card.queue == QUEUE_TYPE_SUSPENDED) def onSuspend(self): self.editor.saveNow(self._onSuspend) @@ -1986,7 +1986,7 @@ update cards set usn=?, mod=?, did=? where id in """ self.deleteTags(tags="marked", label=False) def isMarked(self): - return not not (self.card and self.card.note().hasTag("Marked")) + return bool(self.card and self.card.note().hasTag("Marked")) # Repositioning ###################################################################### From f4874941c8a1890a57dcac978d979b2a63437fb6 Mon Sep 17 00:00:00 2001 From: Hk-tang Date: Mon, 23 Mar 2020 13:08:50 -0600 Subject: [PATCH 13/24] Added name to contributors --- CONTRIBUTORS | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index d19694caa..9ed7429b9 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -29,6 +29,7 @@ Yoonchae Lee Evandro Coan Alan Du Yuchen Lei +Henry Tang ******************** From 6c8b005cab67417d352ef0db8f984e4b58cfaa77 Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Mon, 23 Mar 2020 18:54:24 -0300 Subject: [PATCH 14/24] Deprecated eval usage on qt/tools/typecheck-setup.sh --- qt/tools/typecheck-setup.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/qt/tools/typecheck-setup.sh b/qt/tools/typecheck-setup.sh index a8c3cca25..93cca0447 100755 --- a/qt/tools/typecheck-setup.sh +++ b/qt/tools/typecheck-setup.sh @@ -18,11 +18,9 @@ case "${unameOut}" in ;; esac -cmd="rsync -a \"${TOOLS}/stubs/PyQt5/\" \"${modDir}/\"" - -if [[ "w${OS}" == "wWindows_NT" ]]; +if [[ "w${OS}" == "wWindows_NT" ]]; then - eval "${cmd}" > /dev/null 2>&1 || eval "${cmd}" + rsync -a "${TOOLS}/stubs/PyQt5/" "${modDir}/" else - eval "${cmd}" > /dev/null 2>&1 || eval "${cmd}" || eval "sudo ${cmd}" + rsync -a "${TOOLS}/stubs/PyQt5/" "${modDir}/" || sudo rsync -a "${TOOLS}/stubs/PyQt5/" "${modDir}/" fi From 5c5d1c2af5f0b1544fb14b6818e2acc5712e7bf2 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 24 Mar 2020 10:37:12 +1000 Subject: [PATCH 15/24] remove : check from dbproxy --- pylib/anki/dbproxy.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pylib/anki/dbproxy.py b/pylib/anki/dbproxy.py index a6ea0fec0..6ce136160 100644 --- a/pylib/anki/dbproxy.py +++ b/pylib/anki/dbproxy.py @@ -48,7 +48,6 @@ class DBProxy: for stmt in "insert", "update", "delete": if s.startswith(stmt): self.mod = True - assert ":" not in sql # fetch rows return self._backend.db_query(sql, args, first_row_only) @@ -84,7 +83,6 @@ class DBProxy: def executemany(self, sql: str, args: Iterable[Sequence[ValueForDB]]) -> None: self.mod = True - assert ":" not in sql if isinstance(args, list): list_args = args else: From 289bdde20c7f7e35e3cfac750cf525a8a3f94edc Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 24 Mar 2020 14:53:33 +1000 Subject: [PATCH 16/24] handle fields with embedded nuls --- rslib/Cargo.toml | 13 +++-- rslib/src/storage/sqlite.rs | 97 +++++++++++++++++++++---------------- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/rslib/Cargo.toml b/rslib/Cargo.toml index 627d96efa..906fb1692 100644 --- a/rslib/Cargo.toml +++ b/rslib/Cargo.toml @@ -40,11 +40,16 @@ serde_repr = "0.1.5" num_enum = "0.4.2" unicase = "2.6.0" -[target.'cfg(target_vendor="apple")'.dependencies] -rusqlite = { version = "0.21.0", features = ["trace", "functions", "collation"] } +# pinned until rusqlite 0.22 comes out +[target.'cfg(target_vendor="apple")'.dependencies.rusqlite] +git = "https://github.com/ankitects/rusqlite.git" +branch="nulsafe-text" +features = ["trace", "functions", "collation"] -[target.'cfg(not(target_vendor="apple"))'.dependencies] -rusqlite = { version = "0.21.0", features = ["trace", "functions", "collation", "bundled"] } +[target.'cfg(not(target_vendor="apple"))'.dependencies.rusqlite] +git = "https://github.com/ankitects/rusqlite.git" +branch="nulsafe-text" +features = ["trace", "functions", "collation", "bundled"] [target.'cfg(linux)'.dependencies] reqwest = { version = "0.10.1", features = ["json", "native-tls-vendored"] } diff --git a/rslib/src/storage/sqlite.rs b/rslib/src/storage/sqlite.rs index 7e5b2f87a..b56510717 100644 --- a/rslib/src/storage/sqlite.rs +++ b/rslib/src/storage/sqlite.rs @@ -14,7 +14,7 @@ use crate::{ types::{ObjID, Usn}, }; use regex::Regex; -use rusqlite::{params, Connection, NO_PARAMS}; +use rusqlite::{functions::FunctionFlags, params, Connection, NO_PARAMS}; use std::cmp::Ordering; use std::{ borrow::Cow, @@ -71,58 +71,73 @@ fn open_or_create_collection_db(path: &Path) -> Result { /// to split provided fields and return field at zero-based index. /// If out of range, returns empty string. fn add_field_index_function(db: &Connection) -> rusqlite::Result<()> { - db.create_scalar_function("field_at_index", 2, true, |ctx| { - let mut fields = ctx.get_raw(0).as_str()?.split('\x1f'); - let idx: u16 = ctx.get(1)?; - Ok(fields.nth(idx as usize).unwrap_or("").to_string()) - }) + db.create_scalar_function( + "field_at_index", + 2, + FunctionFlags::SQLITE_DETERMINISTIC, + |ctx| { + let mut fields = ctx.get_raw(0).as_str()?.split('\x1f'); + let idx: u16 = ctx.get(1)?; + Ok(fields.nth(idx as usize).unwrap_or("").to_string()) + }, + ) } fn add_without_combining_function(db: &Connection) -> rusqlite::Result<()> { - db.create_scalar_function("without_combining", 1, true, |ctx| { - let text = ctx.get_raw(0).as_str()?; - Ok(match without_combining(text) { - Cow::Borrowed(_) => None, - Cow::Owned(o) => Some(o), - }) - }) + db.create_scalar_function( + "without_combining", + 1, + FunctionFlags::SQLITE_DETERMINISTIC, + |ctx| { + let text = ctx.get_raw(0).as_str()?; + Ok(match without_combining(text) { + Cow::Borrowed(_) => None, + Cow::Owned(o) => Some(o), + }) + }, + ) } /// Adds sql function regexp(regex, string) -> is_match /// Taken from the rusqlite docs fn add_regexp_function(db: &Connection) -> rusqlite::Result<()> { - db.create_scalar_function("regexp", 2, true, move |ctx| { - assert_eq!(ctx.len(), 2, "called with unexpected number of arguments"); + db.create_scalar_function( + "regexp", + 2, + FunctionFlags::SQLITE_DETERMINISTIC, + move |ctx| { + assert_eq!(ctx.len(), 2, "called with unexpected number of arguments"); - let saved_re: Option<&Regex> = ctx.get_aux(0)?; - let new_re = match saved_re { - None => { - let s = ctx.get::(0)?; - match Regex::new(&s) { - Ok(r) => Some(r), - Err(err) => return Err(rusqlite::Error::UserFunctionError(Box::new(err))), + let saved_re: Option<&Regex> = ctx.get_aux(0)?; + let new_re = match saved_re { + None => { + let s = ctx.get::(0)?; + match Regex::new(&s) { + Ok(r) => Some(r), + Err(err) => return Err(rusqlite::Error::UserFunctionError(Box::new(err))), + } } + Some(_) => None, + }; + + let is_match = { + let re = saved_re.unwrap_or_else(|| new_re.as_ref().unwrap()); + + let text = ctx + .get_raw(1) + .as_str() + .map_err(|e| rusqlite::Error::UserFunctionError(e.into()))?; + + re.is_match(text) + }; + + if let Some(re) = new_re { + ctx.set_aux(0, re); } - Some(_) => None, - }; - let is_match = { - let re = saved_re.unwrap_or_else(|| new_re.as_ref().unwrap()); - - let text = ctx - .get_raw(1) - .as_str() - .map_err(|e| rusqlite::Error::UserFunctionError(e.into()))?; - - re.is_match(text) - }; - - if let Some(re) = new_re { - ctx.set_aux(0, re); - } - - Ok(is_match) - }) + Ok(is_match) + }, + ) } /// Fetch schema version from database. From d5cbd78798a46a109e6907e78172ff6df0b32196 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 24 Mar 2020 15:50:40 +1000 Subject: [PATCH 17/24] use forked proto action --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 4871a7c18..9e78b1537 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -12,7 +12,7 @@ jobs: with: python-version: 3.7 - name: Set up protoc - uses: Arduino/actions/setup-protoc@master + uses: ankitects/setup-protoc@master - name: Set up node uses: actions/setup-node@v1 with: From 31f18e3c94ede16e299185d845017f1518032978 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Tue, 24 Mar 2020 10:17:01 +0100 Subject: [PATCH 18/24] Hook editor_note_will_load A current problem I have is that there is nothing similar to hook inside of javascript. It seems that it would be easier to be able to add other methods in javascript and call them in loadNote. Currently I simply redefined loadNote, which is far from perfect --- qt/aqt/editor.py | 1 + qt/aqt/gui_hooks.py | 34 ++++++++++++++++++++++++++++++++++ qt/tools/genhooks_gui.py | 7 +++++++ 3 files changed, 42 insertions(+) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 31c5d3b8f..3d5341e73 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -456,6 +456,7 @@ class Editor: json.dumps(focusTo), json.dumps(self.note.id), ) + js = gui_hooks.editor_will_load_note(js, self.note, self) self.web.evalWithCallback(js, oncallback) def fonts(self) -> List[Tuple[str, int, bool]]: diff --git a/qt/aqt/gui_hooks.py b/qt/aqt/gui_hooks.py index 0115ef948..aecaaec3c 100644 --- a/qt/aqt/gui_hooks.py +++ b/qt/aqt/gui_hooks.py @@ -1207,6 +1207,40 @@ class _EditorWebViewDidInitHook: editor_web_view_did_init = _EditorWebViewDidInitHook() +class _EditorWillLoadNoteFilter: + """Allows changing the javascript commands to load note before + executing it and do change in the QT editor.""" + + _hooks: List[Callable[[str, "anki.notes.Note", "aqt.editor.Editor"], str]] = [] + + def append( + self, cb: Callable[[str, "anki.notes.Note", "aqt.editor.Editor"], str] + ) -> None: + """(js: str, note: anki.notes.Note, editor: aqt.editor.Editor)""" + self._hooks.append(cb) + + def remove( + self, cb: Callable[[str, "anki.notes.Note", "aqt.editor.Editor"], str] + ) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__( + self, js: str, note: anki.notes.Note, editor: aqt.editor.Editor + ) -> str: + for filter in self._hooks: + try: + js = filter(js, note, editor) + except: + # if the hook fails, remove it + self._hooks.remove(filter) + raise + return js + + +editor_will_load_note = _EditorWillLoadNoteFilter() + + class _EditorWillShowContextMenuHook: _hooks: List[Callable[["aqt.editor.EditorWebView", QMenu], None]] = [] diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index 1dd08c430..a8887e10b 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -498,6 +498,13 @@ def emptyNewCard(): args=["editor_web_view: aqt.editor.EditorWebView"], ), Hook(name="editor_did_init", args=["editor: aqt.editor.Editor"],), + Hook( + name="editor_will_load_note", + args=["js: str", "note: anki.notes.Note", "editor: aqt.editor.Editor"], + return_type="str", + doc="""Allows changing the javascript commands to load note before + executing it and do change in the QT editor.""", + ), # Sound/video ################### Hook(name="av_player_will_play", args=["tag: anki.sound.AVTag"]), From e29d380d4cd6063abf6d55abc9b9d2351435c0ed Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 24 Mar 2020 19:30:35 +1000 Subject: [PATCH 19/24] fix sync getting stuck in a loop when changes is a multiple of 250 --- pylib/anki/sync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylib/anki/sync.py b/pylib/anki/sync.py index 396d8fd1a..84f0a9e9f 100644 --- a/pylib/anki/sync.py +++ b/pylib/anki/sync.py @@ -279,7 +279,7 @@ from notes where %s""" lim = 250 while self.tablesLeft and lim: curTable = self.tablesLeft[0] - if not self.chunkRows: + if self.chunkRows is None: self.chunkRows = self.getChunkRows(curTable) rows = self.chunkRows[:lim] self.chunkRows = self.chunkRows[lim:] From 3799b8504fca2373bc5e9972662b01c35bf43409 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Tue, 24 Mar 2020 11:54:19 +0100 Subject: [PATCH 20/24] strip to test whether field is empty --- qt/aqt/editor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 31c5d3b8f..77e89ac77 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -496,9 +496,10 @@ class Editor: return True m = self.note.model() for c, f in enumerate(self.note.fields): + f = f.replace("
", "").strip() notChangedvalues = {"", "
"} if previousNote and m["flds"][c]["sticky"]: - notChangedvalues.add(previousNote.fields[c]) + notChangedvalues.add(previousNote.fields[c].replace("
", "").strip()) if f not in notChangedvalues: return False return True From c1a8c413b003787614787fa4f8a9858a3b2424c3 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Tue, 24 Mar 2020 12:26:48 +0100 Subject: [PATCH 21/24] remove space in fields --- qt/ts/src/editor.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/qt/ts/src/editor.ts b/qt/ts/src/editor.ts index 890e884b0..eea5fd8c5 100644 --- a/qt/ts/src/editor.ts +++ b/qt/ts/src/editor.ts @@ -352,9 +352,7 @@ function setFields(fields) { oncut='onCutOrCopy(this);' contentEditable=true class=field - > -${f} - + >${f} `; } From ea3c6cad4278de956beed9c8f871393fe0b3276c Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 25 Mar 2020 08:53:31 +1000 Subject: [PATCH 22/24] don't error when -l passes in language without _ --- pylib/anki/lang.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pylib/anki/lang.py b/pylib/anki/lang.py index e679b5d85..50bf528a7 100644 --- a/pylib/anki/lang.py +++ b/pylib/anki/lang.py @@ -133,7 +133,11 @@ def lang_to_disk_lang(lang: str) -> str: ): return lang.replace("_", "-") # other languages have the region portion stripped - return re.match("(.*)_", lang).group(1) + m = re.match("(.*)_", lang) + if m: + return m.group(1) + else: + return lang # the currently set interface language From 01e9f889b7a27f185c0d4c3403d293e98d534fd4 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 25 Mar 2020 08:53:42 +1000 Subject: [PATCH 23/24] add newline to mear clearly separate different ftl files --- rslib/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rslib/build.rs b/rslib/build.rs index 7d147f5c0..ef384d339 100644 --- a/rslib/build.rs +++ b/rslib/build.rs @@ -108,6 +108,7 @@ fn main() -> std::io::Result<()> { let path = entry.path(); println!("cargo:rerun-if-changed=./ftl/{}", fname); buf += &fs::read_to_string(path)?; + buf.push('\n'); } } let combined_ftl = Path::new("src/i18n/ftl/template.ftl"); @@ -145,6 +146,7 @@ fn main() -> std::io::Result<()> { let path = entry.path(); println!("cargo:rerun-if-changed={:?}", entry.path()); buf += &fs::read_to_string(path)?; + buf.push('\n'); } langs .entry(lang_name) From beee1f10e03f450e2d044735be3d4e0c96f19a5b Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 25 Mar 2020 09:45:50 +1000 Subject: [PATCH 24/24] possible CI fix --- .github/workflows/checks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 9e78b1537..28c02e04c 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -13,6 +13,8 @@ jobs: python-version: 3.7 - name: Set up protoc uses: ankitects/setup-protoc@master + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Set up node uses: actions/setup-node@v1 with: