Review fixes

This commit is contained in:
Michal Siedlaczek 2017-10-03 19:54:54 -04:00
parent b840b8066b
commit 932e7a9ab9
14 changed files with 281 additions and 317 deletions

View File

@ -18,7 +18,6 @@ include tox.ini
include qutebrowser.py include qutebrowser.py
include misc/cheatsheet.svg include misc/cheatsheet.svg
include qutebrowser/config/configdata.yml include qutebrowser/config/configdata.yml
include qutebrowser/browser/webengine/langs.tsv
prune www prune www
prune scripts/dev prune scripts/dev

View File

@ -1,9 +1,9 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py # This file is automatically generated by scripts/dev/recompile_requirements.py
certifi==2017.4.17 certifi==2017.7.27.1
chardet==3.0.4 chardet==3.0.4
codecov==2.0.9 codecov==2.0.9
coverage==4.4.1 coverage==4.4.1
idna==2.5 idna==2.6
requests==2.18.1 requests==2.18.4
urllib3==1.21.1 urllib3==1.22

View File

@ -1,42 +0,0 @@
af-ZA Afrikaans (South Africa) af-ZA-3-0.bdic
bg-BG Bulgarian (Bulgaria) bg-BG-3-0.bdic
ca-ES Catalan (Spain) ca-ES-3-0.bdic
cs-CZ Czech (Czech Republic) cs-CZ-3-0.bdic
da-DK Danish (Denmark) da-DK-3-0.bdic
de-DE German (Germany) de-DE-3-0.bdic
el-GR Greek (Greece) el-GR-3-0.bdic
en-CA English (Canada) en-CA-7-1.bdic
en-GB English (United Kingdom) en-GB-7-1.bdic
en-US English (United States) en-US-7-1.bdic
es-ES Spanish (Spain) es-ES-3-0.bdic
et-EE Estonian (Estonia) et-EE-3-0.bdic
fa-IR Farsi (Iran) fa-IR-7-0.bdic
fo-FO Faroese (Faroe Islands) fo-FO-3-0.bdic
fr-FR French (France) fr-FR-3-0.bdic
he-IL Hebrew (Israel) he-IL-3-0.bdic
hi-IN Hindi (India) hi-IN-3-0.bdic
hr-HR Croatian (Croatia) hr-HR-3-0.bdic
hu-HU Hungarian (Hungary) hu-HU-3-0.bdic
id-ID Indonesian (Indonesia) id-ID-3-0.bdic
it-IT Italian (Italy) it-IT-3-0.bdic
ko Korean ko-3-0.bdic
lt-LT Lithuanian (Lithuania) lt-LT-3-0.bdic
lv-LV Latvian (Latvia) lv-LV-3-0.bdic
nb-NO Norwegian (Norway) nb-NO-3-0.bdic
nl-NL Dutch (Netherlands) nl-NL-3-0.bdic
pl-PL Polish (Poland) pl-PL-3-0.bdic
pt-BR Portuguese (Brazil) pt-BR-3-0.bdic
pt-PT Portuguese (Portugal) pt-PT-3-0.bdic
ro-RO Romanian (Romania) ro-RO-3-0.bdic
ru-RU Russian (Russia) ru-RU-3-0.bdic
sh Serbo-Croatian sh-3-0.bdic
sk-SK Slovak (Slovakia) sk-SK-3-0.bdic
sl-SI Slovenian (Slovenia) sl-SI-3-0.bdic
sq Albanian sq-3-0.bdic
sr Serbian sr-3-0.bdic
sv-SE Swedish (Sweden) sv-SE-3-0.bdic
ta-IN Tamil (India) ta-IN-3-0.bdic
tg-TG Tajik (Tajikistan) tg-TG-5-0.bdic
tr-TR Turkish (Turkey) tr-TR-4-0.bdic
uk-UA Ukrainian (Ukraine) uk-UA-3-0.bdic
vi-VN Vietnamese (Viet Nam) vi-VN-3-0.bdic
1 af-ZA Afrikaans (South Africa) af-ZA-3-0.bdic
2 bg-BG Bulgarian (Bulgaria) bg-BG-3-0.bdic
3 ca-ES Catalan (Spain) ca-ES-3-0.bdic
4 cs-CZ Czech (Czech Republic) cs-CZ-3-0.bdic
5 da-DK Danish (Denmark) da-DK-3-0.bdic
6 de-DE German (Germany) de-DE-3-0.bdic
7 el-GR Greek (Greece) el-GR-3-0.bdic
8 en-CA English (Canada) en-CA-7-1.bdic
9 en-GB English (United Kingdom) en-GB-7-1.bdic
10 en-US English (United States) en-US-7-1.bdic
11 es-ES Spanish (Spain) es-ES-3-0.bdic
12 et-EE Estonian (Estonia) et-EE-3-0.bdic
13 fa-IR Farsi (Iran) fa-IR-7-0.bdic
14 fo-FO Faroese (Faroe Islands) fo-FO-3-0.bdic
15 fr-FR French (France) fr-FR-3-0.bdic
16 he-IL Hebrew (Israel) he-IL-3-0.bdic
17 hi-IN Hindi (India) hi-IN-3-0.bdic
18 hr-HR Croatian (Croatia) hr-HR-3-0.bdic
19 hu-HU Hungarian (Hungary) hu-HU-3-0.bdic
20 id-ID Indonesian (Indonesia) id-ID-3-0.bdic
21 it-IT Italian (Italy) it-IT-3-0.bdic
22 ko Korean ko-3-0.bdic
23 lt-LT Lithuanian (Lithuania) lt-LT-3-0.bdic
24 lv-LV Latvian (Latvia) lv-LV-3-0.bdic
25 nb-NO Norwegian (Norway) nb-NO-3-0.bdic
26 nl-NL Dutch (Netherlands) nl-NL-3-0.bdic
27 pl-PL Polish (Poland) pl-PL-3-0.bdic
28 pt-BR Portuguese (Brazil) pt-BR-3-0.bdic
29 pt-PT Portuguese (Portugal) pt-PT-3-0.bdic
30 ro-RO Romanian (Romania) ro-RO-3-0.bdic
31 ru-RU Russian (Russia) ru-RU-3-0.bdic
32 sh Serbo-Croatian sh-3-0.bdic
33 sk-SK Slovak (Slovakia) sk-SK-3-0.bdic
34 sl-SI Slovenian (Slovenia) sl-SI-3-0.bdic
35 sq Albanian sq-3-0.bdic
36 sr Serbian sr-3-0.bdic
37 sv-SE Swedish (Sweden) sv-SE-3-0.bdic
38 ta-IN Tamil (India) ta-IN-3-0.bdic
39 tg-TG Tajik (Tajikistan) tg-TG-5-0.bdic
40 tr-TR Turkish (Turkey) tr-TR-4-0.bdic
41 uk-UA Ukrainian (Ukraine) uk-UA-3-0.bdic
42 vi-VN Vietnamese (Viet Nam) vi-VN-3-0.bdic

View File

@ -19,132 +19,29 @@
"""Installing and configuring spell-checking for QtWebEngine.""" """Installing and configuring spell-checking for QtWebEngine."""
import glob
import os import os
from urllib.parse import urljoin
from urllib.request import urlretrieve
from PyQt5.QtCore import QLibraryInfo from PyQt5.QtCore import QLibraryInfo
repository_url = 'https://redirector.gvt1.com/edgedl/chrome/dict/'
def dictionary_dir():
"""Return the path (str) to the QtWebEngine's dictionaries directory."""
datapath = QLibraryInfo.location(QLibraryInfo.DataPath)
return os.path.join(datapath, 'qtwebengine_dictionaries')
class Language: def installed_file(code):
"""Return the installed dictionary for the given code.
"""Dictionary language specs.""" Return the filename of the installed dictionary or None
if the dictionary is not installed.
def __init__(self, code, name, file):
self.code = code
self.name = name
self.file = file
@staticmethod
def from_array(lang_array):
"""Create Language object from an array.
Args:
lang_array: an array of strings containing
the specs of the language in the following format:
[code, name, file]
"""
return Language.from_tuple(tuple(lang_array))
@staticmethod
def from_tuple(lang_tuple):
"""Create Language object from a tuple.
Args:
lang_tuple: a tuple of strings containing
the specs of the language in the following format:
(code, name, file)
"""
code, name, file = lang_tuple
return Language(code, name, file)
@staticmethod
def from_tsv_string(tsv_string):
"""Create Language object from a string in tab-separated values format.
Args:
tsv_string: a string containing
the specs of the language in the following format:
"code name file"
"""
lang_array = tsv_string.split('\t')
return Language.from_array(lang_array)
def __repr__(self):
return 'Language({}, {}, {})'.format(self.code, self.name, self.file)
def get_dictionary_dir():
"""Return the path to the QtWebEngine's dictionaries directory."""
return os.path.join(QLibraryInfo.location(QLibraryInfo.DataPath),
'qtwebengine_dictionaries')
def get_language_list_file():
"""Return the path to the file with the list of all available languages."""
package_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(package_dir, 'langs.tsv')
def get_available_languages():
"""Return a list of Language objects of all available languages."""
with open(get_language_list_file(), 'r', encoding='UTF-8') as file:
return [Language.from_tsv_string(line[:-1]) for line in file]
def get_installed_languages():
"""Return a list of Language objects of all installed languages."""
if not os.path.isdir(get_dictionary_dir()):
return []
installed_files = [os.path.basename(file)
for file in os.listdir(get_dictionary_dir())]
all_languages = get_available_languages()
return filter_languages(all_languages, installed_files,
by=lambda lang: lang.file,
fail_on_unknown=False)
def filter_languages(languages, selected, by=lambda lang: lang.code,
fail_on_unknown=True):
"""Filter a list of languages based on an inclusion list.
Args:
languages: a list of languages to filter
selected: a list of keys to select
by: a function returning the selection key (code by default)
fail_on_unknown: whether to raise an error if there is an unknown
key in selected
""" """
filtered_languages = [] pathname = os.path.join(dictionary_dir(), '{}*.bdic'.format(code))
for language in languages: print(pathname)
if by(language) in selected: matching_dicts = glob.glob(pathname)
filtered_languages.append(language) if matching_dicts:
selected.remove(by(language)) with_extension = os.path.basename(matching_dicts[0])
if fail_on_unknown and selected: return os.path.splitext(with_extension)[0]
unknown = ', '.join(selected) else:
raise ValueError('unknown languages found: {}'.format(unknown)) return None
return filtered_languages
def download_dictionary(url, dest):
urlretrieve(url, dest)
def install(languages):
"""Install languages."""
for lang in languages:
try:
print('Installing {}: {}'.format(lang.code, lang.name))
lang_url = urljoin(repository_url, lang.file)
if not os.path.isdir(get_dictionary_dir()):
print('WARN: {} does not exist, creating the directory'.format(
get_dictionary_dir()))
os.makedirs(get_dictionary_dir())
print('Downloading {}'.format(lang_url))
download_dictionary(lang_url, os.path.join(get_dictionary_dir(),
lang.file))
print('Done.')
except PermissionError as e:
print(e)

View File

@ -36,7 +36,7 @@ from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
QWebEngineScript) QWebEngineScript)
from qutebrowser.browser import shared from qutebrowser.browser import shared
from qutebrowser.browser.webengine.spell import get_installed_languages from qutebrowser.browser.webengine import spell
from qutebrowser.config import config, websettings from qutebrowser.config import config, websettings
from qutebrowser.utils import utils, standarddir, javascript, qtutils, message from qutebrowser.utils import utils, standarddir, javascript, qtutils, message
@ -134,20 +134,18 @@ class DictionaryLanguageSetter(DefaultProfileSetter):
def __init__(self): def __init__(self):
super().__init__('setSpellCheckLanguages', default=[]) super().__init__('setSpellCheckLanguages', default=[])
def _find_installed(self, code):
installed_file = spell.installed_file(code)
if not installed_file:
message.warning('Language {} is not installed.'.format(code))
return installed_file
def _set(self, value, settings=None): def _set(self, value, settings=None):
if settings is not None: if settings is not None:
raise ValueError("'settings' may not be set with " raise ValueError("'settings' may not be set with "
"DictionaryLanguageSetter!") "DictionaryLanguageSetter!")
installed_langs = dict([(lang.code, lang.file) filenames = [self._find_installed(code) for code in value]
for lang in get_installed_languages()]) super()._set([f for f in filenames if f], settings)
lang_files = []
for lang_code in value:
if lang_code in installed_langs:
lang_files.append(installed_langs[lang_code][:-5])
else:
message.warning('Language {} is not installed.'
.format(lang_code))
super()._set(lang_files, settings)
def _init_stylesheet(profile): def _init_stylesheet(profile):
@ -322,7 +320,6 @@ MAPPINGS = {
'scrolling.smooth': 'scrolling.smooth':
Attribute(QWebEngineSettings.ScrollAnimatorEnabled), Attribute(QWebEngineSettings.ScrollAnimatorEnabled),
} }
try: try:
@ -334,8 +331,9 @@ except AttributeError:
if qtutils.version_check('5.8'): if qtutils.version_check('5.8'):
MAPPINGS['spell'] = DefaultProfileSetter('setSpellCheckEnabled') spellcheck_setter = DefaultProfileSetter('setSpellCheckEnabled')
MAPPINGS['spell_languages'] = DictionaryLanguageSetter() MAPPINGS['spellcheck.enabled'] = spellcheck_setter
MAPPINGS['spellcheck.languages'] = DictionaryLanguageSetter()
if qtutils.version_check('5.9'): if qtutils.version_check('5.9'):

View File

@ -977,7 +977,7 @@ scrolling.smooth:
## spell ## spell
spell: spellcheck.enabled:
type: Bool type: Bool
default: true default: true
desc: Enable spell checking. desc: Enable spell checking.
@ -985,7 +985,7 @@ spell:
QtWebKit: false QtWebKit: false
QtWebEngine: Qt 5.8 QtWebEngine: Qt 5.8
spell_languages: spellcheck.languages:
type: type:
name: List name: List
valtype: valtype:
@ -1035,7 +1035,11 @@ spell_languages:
- vi-VN: Vietnamese (Viet Nam) - vi-VN: Vietnamese (Viet Nam)
none_ok: true none_ok: true
default: default:
desc: Spell checking languages. desc: >-
Spell checking languages.
You can check for available languages and install dictionaries using
scripts/install_dict.py. Run the script with -h/--help for instructions.
backend: backend:
QtWebKit: false QtWebKit: false
QtWebEngine: Qt 5.8 QtWebEngine: Qt 5.8

View File

@ -33,7 +33,6 @@ import sip
from PyQt5.QtCore import QUrl from PyQt5.QtCore import QUrl
# so it's available for :debug-pyeval # so it's available for :debug-pyeval
from PyQt5.QtWidgets import QApplication # pylint: disable=unused-import from PyQt5.QtWidgets import QApplication # pylint: disable=unused-import
from PyQt5.QtWebEngineWidgets import QWebEngineProfile # pylint: disable=unused-import
from qutebrowser.browser import qutescheme from qutebrowser.browser import qutescheme
from qutebrowser.utils import log, objreg, usertypes, message, debug, utils from qutebrowser.utils import log, objreg, usertypes, message, debug, utils

View File

@ -27,6 +27,7 @@ import urllib.error
import shutil import shutil
import json import json
import os import os
import sys
def get_latest_pdfjs_url(): def get_latest_pdfjs_url():
@ -110,7 +111,25 @@ def update_ace():
urllib.request.urlcleanup() urllib.request.urlcleanup()
def run(ace=False, pdfjs=True, fancy_dmg=False, pdfjs_version=None): def test_dicts():
"""Test available dictionaries."""
sys.path.insert(0, os.curdir)
from scripts import install_dict
from qutebrowser.config import configdata
configdata.init()
for lang in install_dict.available_languages():
sys.stdout.write('Testing dictionary {}... '.format(lang.code))
lang_url = urllib.parse.urljoin(install_dict.API_URL, lang.file_path)
request = urllib.request.Request(lang_url, method='HEAD')
response = urllib.request.urlopen(request)
if response.status == 200:
print('OK')
else:
print('ERROR: {}'.format(response.status))
def run(ace=False, pdfjs=True, fancy_dmg=False, pdfjs_version=None,
dicts=None):
"""Update components based on the given arguments.""" """Update components based on the given arguments."""
if pdfjs: if pdfjs:
update_pdfjs(pdfjs_version) update_pdfjs(pdfjs_version)
@ -118,6 +137,8 @@ def run(ace=False, pdfjs=True, fancy_dmg=False, pdfjs_version=None):
update_ace() update_ace()
if fancy_dmg: if fancy_dmg:
update_dmg_makefile() update_dmg_makefile()
if dicts:
test_dicts()
def main(): def main():
@ -129,9 +150,14 @@ def main():
required=False, metavar='VERSION') required=False, metavar='VERSION')
parser.add_argument('--fancy-dmg', help="Update fancy-dmg Makefile", parser.add_argument('--fancy-dmg', help="Update fancy-dmg Makefile",
action='store_true') action='store_true')
parser.add_argument(
'--dicts', '-d',
help='Test whether all available dictionaries '
'can be reached at the remote repository.',
required=False, action='store_true')
args = parser.parse_args() args = parser.parse_args()
run(ace=True, pdfjs=True, fancy_dmg=args.fancy_dmg, run(ace=True, pdfjs=True, fancy_dmg=args.fancy_dmg,
pdfjs_version=args.pdfjs) pdfjs_version=args.pdfjs, dicts=args.dicts)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -24,9 +24,34 @@ Use: python -m scripts.install_dict [--list] [lang [lang [...]]]
""" """
import argparse import argparse
import base64
import json
import os
import sys import sys
import re
import urllib.parse
import urllib.request
import attr
from qutebrowser.browser.webengine import spell from qutebrowser.browser.webengine import spell
from qutebrowser.config import configdata
API_URL = 'https://chromium.googlesource.com/chromium/deps/hunspell_dictionaries.git/+/master/'
@attr.s
class Language:
"""Dictionary language specs."""
code = attr.ib(None)
name = attr.ib(None)
file_basename = attr.ib(None)
file_extension = attr.ib('bdic')
@property
def file_path(self):
return '.'.join([self.file_basename, self.file_extension])
def get_argparser(): def get_argparser():
@ -46,18 +71,105 @@ def print_list(languages):
print('{1}\t{0}'.format(lang.name, lang.code)) print('{1}\t{0}'.format(lang.name, lang.code))
def valid_languages():
"""Return a mapping from valid language codes to their names."""
option = configdata.DATA['spellcheck.languages']
return option.typ.valtype.valid_values.descriptions
def language_list_from_api():
"""Return a JSON with a list of available languages from Google API."""
listurl = urllib.parse.urljoin(API_URL, '?format=JSON')
response = urllib.request.urlopen(listurl)
# TODO: what's up with the first 4 characters?
entries = json.loads(response.read().decode('utf-8')[4:])['entries']
return entries
def available_languages():
"""Return a list of Language objects of all available languages."""
lang_map = valid_languages()
api_list = language_list_from_api()
dict_re = re.compile(r"""
(?P<filename>(?P<dict>[a-z]{2}(-[A-Z]{2})?).*)\.bdic
""", re.VERBOSE)
code2file = {}
for lang in api_list:
match = dict_re.match(lang['name'])
if match is not None:
code2file[match.group('dict')] = match.group('filename')
return [
Language(code, name, code2file[code])
for code, name in lang_map.items()
]
def download_dictionary(url, dest):
"""Download a decoded dictionary file."""
response = urllib.request.urlopen(url)
decoded = base64.decodebytes(response.read())
with open(dest, 'bw') as dict_file:
dict_file.write(decoded)
def filter_languages(languages, selected):
"""Filter a list of languages based on an inclusion list.
Args:
languages: a list of languages to filter
selected: a list of keys to select
by: a function returning the selection key (code by default)
fail_on_unknown: whether to raise an error if there is an unknown
key in selected
"""
filtered_languages = []
for language in languages:
if language.code in selected:
filtered_languages.append(language)
selected.remove(language.code)
if selected:
unknown = ', '.join(selected)
raise ValueError('unknown languages found: {}'.format(unknown))
return filtered_languages
def install_lang(lang):
"""Install a single lang given by the argument."""
print('Installing {}: {}'.format(lang.code, lang.name))
lang_url = urllib.parse.urljoin(API_URL, lang.file_path, '?format=TEXT')
if not os.path.isdir(spell.dictionary_dir()):
warn_msg = 'WARN: {} does not exist, creating the directory'
print(warn_msg.format(spell.dictionary_dir()))
os.makedirs(spell.dictionary_dir())
print('Downloading {}'.format(lang_url))
dest = os.path.join(spell.dictionary_dir(), lang.file_path)
download_dictionary(lang_url, dest)
print('Done.')
def install(languages):
"""Install languages."""
for lang in languages:
try:
install_lang(lang)
except PermissionError as e:
print(e)
def main(): def main():
if configdata.DATA is None:
configdata.init()
parser = get_argparser() parser = get_argparser()
argv = sys.argv[1:] argv = sys.argv[1:]
args = parser.parse_args(argv) args = parser.parse_args(argv)
languages = spell.get_available_languages() languages = available_languages()
if args.list: if args.list:
print_list(languages) print_list(languages)
elif not args.languages: elif not args.languages:
parser.print_usage() parser.print_usage()
else: else:
try: try:
spell.install(spell.filter_languages(languages, args.languages)) install(filter_languages(languages, args.languages))
except ValueError as e: except ValueError as e:
print(e) print(e)

View File

@ -29,7 +29,7 @@ import pstats
import os.path import os.path
import operator import operator
from qutebrowser.browser.webengine.spell import get_installed_languages from qutebrowser.browser.webengine import spell
import pytest import pytest
from PyQt5.QtCore import PYQT_VERSION from PyQt5.QtCore import PYQT_VERSION
@ -120,18 +120,17 @@ def _get_backend_tag(tag):
def _get_dictionary_tag(tag): def _get_dictionary_tag(tag):
"""Handle tags like must_have_dict=en-US for BDD tests.""" """Handle tags like must_have_dict=en-US for BDD tests."""
version_re = re.compile(r""" dict_re = re.compile(r"""
(?P<event>must_have_dict|cannot_have_dict)=(?P<dict>[a-z]{2}-[A-Z]{2}) (?P<event>must_have_dict|cannot_have_dict)=(?P<dict>[a-z]{2}-[A-Z]{2})
""", re.VERBOSE) """, re.VERBOSE)
match = version_re.match(tag) match = dict_re.match(tag)
if not match: if not match:
#return pytest.mark.skip
return None return None
event = match.group('event') event = match.group('event')
dictionary = match.group('dict') dictionary = match.group('dict')
has_dict = dictionary in [lang.code for lang in get_installed_languages()] has_dict = spell.installed_file(dictionary) is not None
if event == 'must_have_dict': if event == 'must_have_dict':
return pytest.mark.skipif(not has_dict, reason=tag) return pytest.mark.skipif(not has_dict, reason=tag)
elif event == 'cannot_have_dict': elif event == 'cannot_have_dict':

View File

@ -2,37 +2,29 @@
Feature: Setting spell checking for QtWebEngine Feature: Setting spell checking for QtWebEngine
Background:
Given spell check languages are []
@qtwebkit_skip @qt>=5.8 @qtwebkit_skip @qt>=5.8
Scenario: Turn spell check on Scenario: Turn spell check on
Given spell check is off Given I set spellcheck.enabled to false
When I run :set spell true When I run :set spellcheck.enabled true
Then the option spell should be set to true Then the option spellcheck.enabled should be set to true
Then spell check is on
@qtwebkit_skip @qt>=5.8 @qtwebkit_skip @qt>=5.8
Scenario: Turn spell check off Scenario: Turn spell check off
Given spell check is on Given I set spellcheck.enabled to true
When I run :set spell false When I run :set spellcheck.enabled false
Then the option spell should be set to false Then the option spellcheck.enabled should be set to false
Then spell check is off
@qtwebkit_skip @qt>=5.8 @qtwebkit_skip @qt>=5.8
Scenario: Set an invalid language Scenario: Set an invalid language
When I run :set spell_languages ['invalid-language'] (invalid command) When I run :set spellcheck.languages ['invalid-language'] (invalid command)
Then the error "set: Invalid value 'invalid-language' *" should be shown Then the error "set: Invalid value 'invalid-language' *" should be shown
Then actual spell check languages are []
@qtwebkit_skip @qt>=5.8 @cannot_have_dict=af-ZA @qtwebkit_skip @qt>=5.8 @cannot_have_dict=af-ZA
Scenario: Set valid but not installed language Scenario: Set valid but not installed language
When I run :set spell_languages ['af-ZA'] When I run :set spellcheck.languages ['af-ZA']
Then the warning "Language af-ZA is not installed." should be shown Then the warning "Language af-ZA is not installed." should be shown
Then actual spell check languages are []
@qtwebkit_skip @qt>=5.8 @must_have_dict=en-US @qtwebkit_skip @qt>=5.8 @must_have_dict=en-US
Scenario: Set valid and installed language Scenario: Set valid and installed language
When I run :set spell_languages ["en-US"] When I run :set spellcheck.languages ["en-US"]
Then the option spell_languages should be set to ["en-US"] Then the option spellcheck.languages should be set to ["en-US"]
Then actual spell check languages are ['en-US-7-1']

View File

@ -20,39 +20,3 @@
import pytest_bdd as bdd import pytest_bdd as bdd
bdd.scenarios('spell.feature') bdd.scenarios('spell.feature')
@bdd.given(bdd.parsers.parse("spell check is {val}"))
def spellcheck_enabled_given(quteproc, val):
enabled = val == 'on'
quteproc.send_cmd(':debug-pyeval QWebEngineProfile.defaultProfile()' +
'.setSpellCheckEnabled({})'.format(enabled))
quteproc.wait_for_load_finished('qute://pyeval')
@bdd.given(bdd.parsers.parse("spell check languages are {langs}"))
def spellcheck_langs_given(quteproc, langs):
quteproc.send_cmd(':debug-pyeval QWebEngineProfile.defaultProfile()' +
'.setSpellCheckLanguages({})'.format(langs))
quteproc.wait_for_load_finished('qute://pyeval')
@bdd.then(bdd.parsers.parse("spell check is {val}"))
def spellcheck_enabled_then(quteproc, val):
quteproc.send_cmd(':debug-pyeval QWebEngineProfile.defaultProfile()' +
'.isSpellCheckEnabled()')
quteproc.wait_for_load_finished('qute://pyeval')
content = quteproc.get_content().strip()
if val == 'on':
assert content == 'True'
else:
assert content == 'False'
@bdd.then(bdd.parsers.parse("actual spell check languages are {langs}"))
def spellcheck_langs_then(quteproc, langs):
quteproc.send_cmd(':debug-pyeval QWebEngineProfile.defaultProfile()' +
'.spellCheckLanguages()')
quteproc.wait_for_load_finished('qute://pyeval')
actual_langs = quteproc.get_content().strip()
assert actual_langs == langs

View File

@ -18,78 +18,23 @@
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>. # along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
from os.path import basename, join
import pytest
from qutebrowser.browser.webengine import spell from qutebrowser.browser.webengine import spell
AFRIKAANS = spell.Language('af-ZA',
'Afrikaans (South Africa)',
'af-ZA-3-0.bdic')
ENGLISH = spell.Language('en-US',
'English (United States)',
'en-US-7-1.bdic')
POLISH = spell.Language('pl-PL',
'Polish (Poland)',
'pl-PL-3-0.bdic')
LANGUAGE_LIST = [AFRIKAANS, ENGLISH, POLISH] def test_installed_file_dictionary_does_not_exist(tmpdir, monkeypatch):
monkeypatch.setattr(
spell, 'dictionary_dir', lambda: '/some-non-existing-dir')
assert not spell.installed_file('en-US')
def test_get_installed_languages_empty(tmpdir, mocker): def test_installed_file_dictionary_not_installed(tmpdir, monkeypatch):
mocker.patch('qutebrowser.browser.webengine.spell.get_dictionary_dir', monkeypatch.setattr(spell, 'dictionary_dir', lambda: str(tmpdir))
lambda: '/some-non-existing-dir') assert not spell.installed_file('en-US')
assert spell.get_installed_languages() == []
def test_get_installed_languages_non_empty(tmpdir, mocker): def test_installed_file_dictionary_installed(tmpdir, monkeypatch):
mocker.patch('qutebrowser.browser.webengine.spell.get_dictionary_dir', monkeypatch.setattr(spell, 'dictionary_dir', lambda: str(tmpdir))
lambda: str(tmpdir)) for lang_file in ['en-US-7-1.bdic', 'pl-PL-3-0.bdic']:
for lang in LANGUAGE_LIST: (tmpdir / lang_file).ensure()
open(join(str(tmpdir), lang.file), 'w', encoding='UTF-8').close() assert spell.installed_file('en-US') == 'en-US-7-1'
for actual, expected in zip(spell.get_installed_languages(), assert spell.installed_file('pl-PL') == 'pl-PL-3-0'
LANGUAGE_LIST):
assert (actual.code, actual.name, actual.file) ==\
(expected.code, expected.name, expected.file)
def test_get_available_languages():
language_list = spell.get_available_languages()
assert len(language_list) == 42
first_lang = language_list[0]
assert (first_lang.code, first_lang.name, first_lang.file) ==\
(AFRIKAANS.code, AFRIKAANS.name, AFRIKAANS.file)
def test_filter_languages():
filtered_languages = spell.filter_languages(LANGUAGE_LIST, ['af-ZA'])
assert filtered_languages == [AFRIKAANS]
filtered_languages = spell.filter_languages(LANGUAGE_LIST,
['pl-PL', 'en-US'])
assert filtered_languages == [ENGLISH, POLISH]
with pytest.raises(ValueError):
spell.filter_languages(LANGUAGE_LIST, ['pl-PL', 'en-GB'])
filtered_languages = spell.filter_languages(LANGUAGE_LIST,
['pl-PL-3-0.bdic'],
by=lambda lang: lang.file)
assert filtered_languages == [POLISH]
def test_install(tmpdir, mocker):
mocker.patch('qutebrowser.browser.webengine.spell.get_dictionary_dir',
lambda: str(tmpdir))
mocker.patch('qutebrowser.browser.webengine.spell.download_dictionary',
lambda url, dest: open(dest, 'w', encoding='UTF-8').close())
spell.install(LANGUAGE_LIST)
installed_files = [basename(str(file)) for file in tmpdir.listdir()]
expected_files = [lang.file for lang in LANGUAGE_LIST]
assert sorted(installed_files) == sorted(expected_files)
# TODO: move somewhere to be checked before a release
#def test_available_langs():
# for lang in spell.get_available_languages():
# lang_url = urljoin(spell.repository_url, lang.file)
# response = head(lang_url)
# assert response.status_code == 302

View File

@ -0,0 +1,71 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2017 Michal Siedlaczek <michal.siedlaczek@gmail.com>
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
import py.path # pylint: disable=no-name-in-module
import pytest
from qutebrowser.browser.webengine import spell
from scripts import install_dict
from qutebrowser.config import configdata
AFRIKAANS = install_dict.Language(
'af-ZA',
'Afrikaans (South Africa)',
'af-ZA-3-0')
ENGLISH = install_dict.Language(
'en-US',
'English (United States)',
'en-US-7-1')
POLISH = install_dict.Language(
'pl-PL',
'Polish (Poland)',
'pl-PL-3-0')
LANGUAGE_LIST = [AFRIKAANS, ENGLISH, POLISH]
@pytest.fixture(autouse=True)
def configdata_init():
"""Initialize configdata if needed."""
if configdata.DATA is None:
configdata.init()
def test_filter_languages():
filtered_langs = install_dict.filter_languages(LANGUAGE_LIST, ['af-ZA'])
assert filtered_langs == [AFRIKAANS]
filtered_langs = install_dict.filter_languages(
LANGUAGE_LIST, ['pl-PL', 'en-US'])
assert filtered_langs == [ENGLISH, POLISH]
with pytest.raises(ValueError):
install_dict.filter_languages(LANGUAGE_LIST, ['pl-PL', 'en-GB'])
def test_install(tmpdir, monkeypatch):
monkeypatch.setattr(spell, 'dictionary_dir', lambda: str(tmpdir))
monkeypatch.setattr(
install_dict, 'download_dictionary',
lambda _url, dest: py.path.local(dest).ensure()) # pylint: disable=no-member
install_dict.install(LANGUAGE_LIST)
installed_files = [f.basename for f in tmpdir.listdir()]
expected_files = [lang.file_path for lang in LANGUAGE_LIST]
assert sorted(installed_files) == sorted(expected_files)