Skip to content

Commit

Permalink
Allow setting language by using Language instances.
Browse files Browse the repository at this point in the history
Also add docstrings for `lang` to public API.
  • Loading branch information
pekkaklarck committed Aug 16, 2022
1 parent 7e61ad3 commit 800e7e6
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 23 deletions.
24 changes: 14 additions & 10 deletions src/robot/conf/languages.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import inspect
import os.path

from robot.utils import getdoc, is_string, Importer, normalize
from robot.utils import is_list_like, Importer, normalize


class Languages:
Expand Down Expand Up @@ -48,20 +48,24 @@ def _get_languages(self, languages):
available = self._get_available_languages()
returned = []
for lang in languages:
normalized = normalize(lang, ignore='-')
if normalized in available:
returned.append(available[normalized])
if isinstance(lang, Language):
returned.append(lang)
else:
returned.extend(self._import_languages(lang))
return [subclass() for subclass in returned]
normalized = normalize(lang, ignore='-')
if normalized in available:
returned.append(available[normalized]())
else:
returned.extend(self._import_languages(lang))
return returned

def _resolve_languages(self, languages):
if not languages:
languages = []
if is_string(languages):
elif is_list_like(languages):
languages = list(languages)
else:
languages = [languages]
if 'en' not in languages:
languages.append('en')
languages.append(En())
return languages

def _get_available_languages(self):
Expand All @@ -80,7 +84,7 @@ def is_language(member):
if os.path.exists(lang):
lang = os.path.abspath(lang)
module = Importer('language file').import_module(lang)
return [value for _, value in inspect.getmembers(module, is_language)]
return [value() for _, value in inspect.getmembers(module, is_language)]

def translate_setting(self, name):
return self.settings.get(name, name)
Expand Down
12 changes: 8 additions & 4 deletions src/robot/parsing/lexer/lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from .tokens import EOS, END, Token


# FIXME: Documentation for `lang`.
def get_tokens(source, data_only=False, tokenize_variables=False, lang=None):
"""Parses the given source to tokens.
Expand All @@ -39,6 +38,11 @@ def get_tokens(source, data_only=False, tokenize_variables=False, lang=None):
arguments and elsewhere are tokenized. See the
:meth:`~robot.parsing.lexer.tokens.Token.tokenize_variables`
method for details.
:param lang: Additional languages to be supported during parsing.
Can be a string matching any of the supported language codes or names,
an initialized :class:`~robot.conf.languages.Language` subsclass,
a list containing such strings or instances, or a
:class:`~robot.conf.languages.Languages` instance.
Returns a generator that yields :class:`~robot.parsing.lexer.tokens.Token`
instances.
Expand All @@ -51,7 +55,7 @@ def get_tokens(source, data_only=False, tokenize_variables=False, lang=None):
def get_resource_tokens(source, data_only=False, tokenize_variables=False, lang=None):
"""Parses the given source to resource file tokens.
Otherwise same as :func:`get_tokens` but the source is considered to be
Same as :func:`get_tokens` otherwise, but the source is considered to be
a resource file. This affects, for example, what settings are valid.
"""
lexer = Lexer(ResourceFileContext(lang=lang), data_only, tokenize_variables)
Expand All @@ -62,7 +66,7 @@ def get_resource_tokens(source, data_only=False, tokenize_variables=False, lang=
def get_init_tokens(source, data_only=False, tokenize_variables=False, lang=None):
"""Parses the given source to init file tokens.
Otherwise same as :func:`get_tokens` but the source is considered to be
Same as :func:`get_tokens` otherwise, but the source is considered to be
a suite initialization file. This affects, for example, what settings are
valid.
"""
Expand Down Expand Up @@ -96,7 +100,7 @@ def _read(self, source):
try:
with FileReader(source, accept_text=True) as reader:
return reader.read()
except:
except Exception:
raise DataError(get_error_message())

def get_tokens(self):
Expand Down
7 changes: 5 additions & 2 deletions src/robot/parsing/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ def get_model(source, data_only=False, curdir=None, lang=None):
When not given, the variable is left as-is. Should only be given
only if the model will be executed afterwards. If the model is saved
back to disk, resolving ``${CURDIR}`` is typically not a good idea.
# FIXME: docs
:param lang: Additional languages to be supported during parsing
:param lang: Additional languages to be supported during parsing.
Can be a string matching any of the supported language codes or names,
an initialized :class:`~robot.conf.languages.Language` subsclass,
a list containing such strings or instances, or a
:class:`~robot.conf.languages.Languages` instance.
Use :func:`get_resource_model` or :func:`get_init_model` when parsing
resource or suite initialization files, respectively.
Expand Down
13 changes: 9 additions & 4 deletions src/robot/running/builder/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class TestSuiteBuilder:
- Execute the created suite by using its
:meth:`~robot.running.model.TestSuite.run` method. The suite can be
can be modified before execution if needed.
modified before execution if needed.
- Inspect the suite to see, for example, what tests it has or what tags
tests have. This can be more convenient than using the lower level
Expand All @@ -56,9 +56,14 @@ def __init__(self, included_suites=None, included_extensions=('robot',),
:param included_extensions:
List of extensions of files to parse. Same as `--extension`.
:param rpa: Explicit test execution mode. ``True`` for RPA and
``False`` for test automation. By default mode is got from data file
headers and possible conflicting headers cause an error.
Same as `--rpa` or `--norpa`.
``False`` for test automation. By default, mode is got from data file
headers and possible conflicting headers cause an error.
Same as `--rpa` or `--norpa`.
:param lang: Additional languages to be supported during parsing.
Can be a string matching any of the supported language codes or names,
an initialized :class:`~robot.conf.languages.Language` subsclass,
a list containing such strings or instances, or a
:class:`~robot.conf.languages.Languages` instance.
:param allow_empty_suite:
Specify is it an error if the built suite contains no tests.
Same as `--runemptysuite`.
Expand Down
19 changes: 16 additions & 3 deletions utest/parsing/test_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from io import StringIO
from pathlib import Path

from robot.conf import Languages
from robot.conf import Language, Languages
from robot.utils.asserts import assert_equal
from robot.parsing import get_tokens, get_init_tokens, get_resource_tokens, Token

Expand Down Expand Up @@ -2196,11 +2196,24 @@ def _verify(self, data, expected, test=False):

class TestLanguageConfig(unittest.TestCase):

def test_lang_as_string(self):
def test_lang_as_code(self):
self._test('fi')
self._test('F-I')

def test_lang_as_name(self):
self._test('Finnish')
self._test('FINNISH')

def test_lang_as_Language(self):
self._test(Language.from_name('fi'))

def test_lang_as_list(self):
self._test(['fi'])
self._test(['fi', Language.from_name('de')])
self._test([Language.from_name('fi'), 'de'])

def test_lang_as_tuple(self):
self._test(('f-i', Language.from_name('de')))
self._test((Language.from_name('fi'), 'de'))

def test_lang_as_Languages(self):
self._test(Languages('fi'))
Expand Down

0 comments on commit 800e7e6

Please sign in to comment.