Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No Unicode in `__all__` for a package's `__init__`?

Are Unicode literals not allowed in __all__ in Python 2.7.5? I've got an __init__.py file with from __future__ import unicode_literals at the top, along with coding utf-8. (There are also some unicode strings in it, hence the future import.)

To ensure that only some of the modules are visible when imported using from mypackage import *, I've added my class to __all__. But I get TypeError: Item in ``from list'' not a string. Why is that? Bug?

However, when I cast the class name to str in __all__, it works just fine.
[ It also works when I specify from mypackage import SomeClass in run.py below...since the items in __all__ are not processed. ]


mypackage/somemodule.py:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

class SomeClass(object):
    pass

mypackage/ __init__.py

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from .somemodule import SomeClass

__all__ = ['SomeClass']

run.py:

# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import unicode_literals
from mypackage import *

print('yay')

To avoid the error, I change the 'all' declaration to:

__all__ = [str('SomeClass')] #pylint: disable=invalid-all-object

which, of course, pylint complains about.

My other option is to not import unicode_literals and explicitly cast all the strings in init to unicode with u'uni string'.

like image 299
aneroid Avatar asked Nov 11 '13 18:11

aneroid


1 Answers

No, unicode values are not allowed in __all__, because in Python 2 names are strings, not unicode values.

Your indeed have to encode all strings in __all__ or not use unicode literals. You could do so as a separate step:

__all__ = ['SomeClass']
__all__ = [n.encode('ascii') for n in __all__]

In Python 3, variable names are unicode values too, so there __all__ is expected to have unicode strings.

like image 74
Martijn Pieters Avatar answered Nov 30 '22 07:11

Martijn Pieters