1.0.0 Porting Guide

The 0.1 through 1.0.0 releases focused on bringing in functions from yum and python-fedora. This porting guide tells how to port from those APIs to their kitchen replacements.

python-fedora

python-fedora kitchen replacement
fedora.iterutils.isiterable() kitchen.iterutils.isiterable() [1]
fedora.textutils.to_unicode() kitchen.text.converters.to_unicode()
fedora.textutils.to_bytes() kitchen.text.converters.to_bytes()
[1]

isiterable() has changed slightly in kitchen. The include_string attribute has switched its default value from True to False. So you need to change code like:

>>> # Old code
>>> isiterable('abcdef')
True
>>> # New code
>>> isiterable('abcdef', include_string=True)
True

yum

yum kitchen replacement
yum.i18n.dummy_wrapper() kitchen.i18n.DummyTranslations.ugettext() [2]
yum.i18n.dummyP_wrapper() kitchen.i18n.DummyTanslations.ungettext() [2]
yum.i18n.utf8_width() kitchen.text.display.textual_width()
yum.i18n.utf8_width_chop() kitchen.text.display.textual_width_chop() and kitchen.text.display.textual_width() [3] [5]
yum.i18n.utf8_valid() kitchen.text.misc.byte_string_valid_encoding()
yum.i18n.utf8_text_wrap() kitchen.text.display.wrap() [4]
yum.i18n.utf8_text_fill() kitchen.text.display.fill() [4]
yum.i18n.to_unicode() kitchen.text.converters.to_unicode() [6]
yum.i18n.to_unicode_maybe() kitchen.text.converters.to_unicode() [6]
yum.i18n.to_utf8() kitchen.text.converters.to_bytes() [6]
yum.i18n.to_str() kitchen.text.converters.to_unicode() or kitchen.text.converters.to_bytes() [7]
yum.i18n.str_eq() kitchen.text.misc.str_eq()
yum.misc.to_xml() kitchen.text.converters.unicode_to_xml() or kitchen.text.converters.byte_string_to_xml() [8]
yum.i18n._() See: Initializing Yum i18n
yum.i18n.P_() See: Initializing Yum i18n
yum.i18n.exception2msg() kitchen.text.converters.exception_to_unicode() or kitchen.text.converter.exception_to_bytes() [9]
[2](1, 2) These yum methods provided fallback support for gettext functions in case either gaftonmode was set or gettext failed to return an object. In kitchen, we can use the kitchen.i18n.DummyTranslations object to fulfill that role. Please see Initializing Yum i18n for more suggestions on how to do this.
[3]The yum version of these functions returned a byte str. The kitchen version listed here returns a unicode string. If you need a byte str simply call kitchen.text.converters.to_bytes() on the result.
[4](1, 2) The yum version of these functions would return either a byte str or a unicode string depending on what the input value was. The kitchen version always returns unicode strings.
[5]

yum.i18n.utf8_width_chop() performed two functions. It returned the piece of the message that fit in a specified width and the width of that message. In kitchen, you need to call two functions, one for each action:

>>> # Old way
>>> utf8_width_chop(msg, 5)
(5, 'く ku')
>>> # New way
>>> from kitchen.text.display import textual_width, textual_width_chop
>>> (textual_width(msg), textual_width_chop(msg, 5))
(5, u'く ku')
[6](1, 2, 3)

If the yum version of to_unicode() or to_utf8() is given an object that is not a string, it returns the object itself. kitchen.text.converters.to_unicode() and kitchen.text.converters.to_bytes() default to returning the simplerepr of the object instead. If you want the yum behaviour, set the nonstring parameter to passthru:

>>> from kitchen.text.converters import to_unicode
>>> to_unicode(5)
u'5'
>>> to_unicode(5, nonstring='passthru')
5
[7]yum.i18n.to_str() could return either a byte str. or a unicode string In kitchen you can get the same effect but you get to choose whether you want a byte str or a unicode string. Use to_bytes() for str and to_unicode() for unicode.
[8]yum.misc.to_xml() was buggy as written. I think the intention was for you to be able to pass a byte str or unicode string in and get out a byte str that was valid to use in an xml file. The two kitchen functions byte_string_to_xml() and unicode_to_xml() do that for each string type.
[9]

When porting yum.i18n.exception2msg() to use kitchen, you should setup two wrapper functions to aid in your port. They’ll look like this:

from kitchen.text.converters import EXCEPTION_CONVERTERS, \
    BYTE_EXCEPTION_CONVERTERS, exception_to_unicode, \
    exception_to_bytes
def exception2umsg(e):
    '''Return a unicode representation of an exception'''
    c = [lambda e: e.value]
    c.extend(EXCEPTION_CONVERTERS)
    return exception_to_unicode(e, converters=c)
def exception2bmsg(e):
    '''Return a utf8 encoded str representation of an exception'''
    c = [lambda e: e.value]
    c.extend(BYTE_EXCEPTION_CONVERTERS)
    return exception_to_bytes(e, converters=c)

The reason to define this wrapper is that many of the exceptions in yum put the message in the value attribute of the Exception instead of adding it to the args attribute. So the default EXCEPTION_CONVERTERS don’t know where to find the message. The wrapper tells kitchen to check the value attribute for the message. The reason to define two wrappers may be less obvious. yum.i18n.exception2msg() can return a unicode string or a byte str depending on a combination of what attributes are present on the Exception and what locale the function is being run in. By contrast, kitchen.text.converters.exception_to_unicode() only returns unicode strings and kitchen.text.converters.exception_to_bytes() only returns byte str. This is much safer as it keeps code that can only handle unicode or only handle byte str correctly from getting the wrong type when an input changes but it means you need to examine the calling code when porting from yum.i18n.exception2msg() and use the appropriate wrapper.

Initializing Yum i18n

Previously, yum had several pieces of code to initialize i18n. From the toplevel of yum/i18n.py:

try:.
    '''
    Setup the yum translation domain and make _() and P_() translation wrappers
    available.
    using ugettext to make sure translated strings are in Unicode.
    '''
    import gettext
    t = gettext.translation('yum', fallback=True)
    _ = t.ugettext
    P_ = t.ungettext
except:
    '''
    Something went wrong so we make a dummy _() wrapper there is just
    returning the same text
    '''
    _ = dummy_wrapper
    P_ = dummyP_wrapper

With kitchen, this can be changed to this:

from kitchen.i18n import easy_gettext_setup, DummyTranslations
try:
    _, P_ = easy_gettext_setup('yum')
except:
    translations = DummyTranslations()
    _ = translations.ugettext
    P_ = translations.ungettext

Note

In Overcoming frustration: Correctly using unicode in python2, it is mentioned that for some things (like exception messages), using the byte str oriented functions is more appropriate. If this is desired, the setup portion is only a second call to kitchen.i18n.easy_gettext_setup():

b_, bP_ = easy_gettext_setup('yum', use_unicode=False)

The second place where i18n is setup is in yum.YumBase._getConfig() in yum/__init_.py if gaftonmode is in effect:

if startupconf.gaftonmode:
    global _
    _ = yum.i18n.dummy_wrapper

This can be changed to:

if startupconf.gaftonmode:
    global _
    _ = DummyTranslations().ugettext()

Table Of Contents

Previous topic

Exceptions

Next topic

Conventions for contributing to kitchen

This Page