How to avoid flake8's "F821 undefined name '_'" when _ has been installed by gettext?
Asked Answered
P

1

19

Problem overview:

In my project's main script, gettext installs the function _() that is used in other modules for translations (like in print(_('Something to translate'))).

As stated by the doc:

the _() function [is] installed in Python’s builtins namespace, so it is easily accessible in all modules of your application.

So, everything runs fine.

Only problem: flake8 shows errors (actually returned by PyFlakes):

$ flake8 *.py
lib.py:2:12: F821 undefined name '_'
main_script.py:8:7: F821 undefined name '_'

This is normal, as _ is indeed not defined in main_script.py nor lib.py.

Simple structure that reproduces the problem:

.
├── lib.py
├── locale
│   └── de
│       └── LC_MESSAGES
│           ├── myapp.mo
│           └── myapp.po
└── main_script.py

Where lib.py contains this:

def fct(sentence):
    return _(sentence)

and main_script.py this:

#!/usr/bin/env python3

import gettext

import lib

gettext.translation('myapp', 'locale', ['de']).install()
print(_('A sentence'))
print(lib.fct('A sentence'))

and myapp.po contains:

msgid ""
msgstr ""
"Project-Id-Version: myapp\n"

msgid "A sentence"
msgstr "Ein Satz"

(was compiled by poedit to produce the mo file).

As stated above, the main script does work:

$ ./main_script.py 
Ein Satz
Ein Satz

Important note: I'm looking for a solution working both for the script where gettext.install() is called and all other modules that do not need to call gettext.install(). Otherwise, the structure could be even more simple, because calling _() from main_script.py is enough to trigger F821.

Solutions to solve the situation that look bad (or worse):

  • add a # noqa comment at the end of each line using _()
  • --ignore F821 (don't want to do that because this is useful in other situations)
Perbunan answered 15/6, 2016 at 15:47 Comment(4)
If you don't mind arguments, you can specify --builtins="_" which is more specific than --ignore F821.Nedi
Well, yes this solves the problem efficiently. You could post this as an answer.Perbunan
Classic well researched question, getting a concise and effective answer (which was directly relevant to my needs).Omidyar
@Omidyar I must precise that after having experienced weird issues at other places (pytest and doctests), directly caused by this use of _ as a translation shortcut, I finally decided to abandon this. I replaced _ by tr and import it anytime necessary as I do for any other module.Perbunan
N
35

You could specify the --builtins="_" which is more specific than --ignore F821.

You should be able to specify this in a configuration file as well if you don't like command line arguments.

Nedi answered 15/6, 2016 at 16:19 Comment(2)
Many thanks for this precision about the configuration file! For atom linter-flake8 plugin, there's no setting yet, but it's indeed possible to add the line builtins = _ in the flake8 config file used for the project (what overrides the settings defined in atom).Perbunan
I must precise that after having experienced weird issues at other places (pytest and doctests), directly caused by this use of _ as a translation shortcut, I finally decided to abandon this. I replaced _ by tr and import it anytime necessary as I do for any other module.Perbunan

© 2022 - 2024 — McMap. All rights reserved.