Python's strftime dislikes years before 1900

>>> birthday = datetime.datetime(year=1879, month=3, day=19)
>>> birthday.strftime("%y/%m/%d")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: year=979 is before 1900; the datetime strftime() methods require year >= 1900

困りました。ValueError を例外処理するしかないのかな・・・

関連情報:

Python で無限大を得る方法

最近知ったのでメモ。

float の引数に文字列で "inf" を渡すと inf オブジェクトが返ってきます。

>>> float("inf")
inf

inf に何を足しても inf です。

>>> inf = float("inf")
>>> inf + 1
inf
>>> inf + 1 == inf
True

inf から inf を引いたり、 inf に 0 を掛けると、結果は nan (不定) になります

>>> inf - inf
nan
>>> inf * 0
nan

nan は自分自身と等しくないので、これを利用して nan かどうか調べることができます。
(Python 2.6 からは math モジュールに isnan というそのものズバリな関数が用意されています)

>>> nan = float("nan")
>>> nan == nan
False
>>> nan != nan
True

最後の nan の判定方法は PythonでNaNやinfを調べる で知りました。

By id:knzm

RHEL 4 への qdbm-1..8.77 インストールではまった

コンパイルはできるのだが、

$ make check

でテストに失敗する。2〜3時間格闘したが、結局原因は NFS だった。
ローカルディスクで "make check" すると成功。
Cent OS 5 では NFS でもテストに失敗しなかったので、RHEL 4 の NFS 特有の問題か。
RHEL 4 の場合、NFS で qdbm を使っちゃダメかもしれない。

id:junya_hayashi

virtualenv 下で sitecustomize.py が機能しない

virtualenv 下で sitecusotomize.py が機能しないと思ったら、Hardy のせいでした。

Hardy では /usr/lib/python2.x/sitecustomize.py が置かれているため、 virtualenv 側で lib/python2.x/site-packages/sitecustomize.py を置いても読み込んでくれません。

このことに気がつくまで、えらい時間がかかってしまった・・・

posted by id:junya_hayashi

Dynamic inheritance

Mako で、条件によって継承テンプレートを変えたかったので、

<%inherit file="/${ c.flg and 'foo' or 'bar' }/index.tpl" />

としたら怒られた。inherit の中では、種々の変数はcontext 変数から取得しないといけないらしい。(参考
正しくは

<%inherit file="/${ context.get('c').flg and 'foo' or 'bar' }/index.tpl" />

となる。

Jinja2 Buffet Plugin

Pylons 0.9.6.2 から Jinja2 を利用するための Buffet Plugin を記述しました。
なお、最新の Pylons 0.9.7 はデフォルトで Jinja2 に対応しています。

# -*- coding: utf-8 -*-

from jinja2 import Environment
from jinja2 import FileSystemLoader, PackageLoader, FunctionLoader
from jinja2.sandbox import SandboxedEnvironment

class Jinja2TemplatePlugin(object):
    """ Implements the Jina2 buffet plugin

    This module is made referring to Jinja1's BuffetPlugin.

    .. seealso::

      `Template plugins (for developers) - Pylons Cookbook
      <http://docs.pythonweb.org/display/pylonscookbook/Template+plugins+(for+developers)>`_
    """

    def __init__(self, extra_vars_func=None, options=None):
        """ Store the two arguments (normally dicts of strings), and do any
        other initialization required.

        .. Note::

           Jinja2 uses URI notation for template name.
           If options['jinja2.extension'] is not provided, the module will
           take given tempate name as URI.
        """

        if 'jinja2.environment' in options:
            self.env = options['jinja2.environment']
        else:
            opt = {}
            for key, value in options.iteritems():
                if key.startswith('jinja2.') and key != 'jinja2.extension':
                    opt[key[7:]] = value
            loader_func = opt.pop('loader_func', None)
            if 'searchpath' in opt:
                opt['loader'] = FileSystemLoader(opt.pop('searchpath'))
            elif 'package' in opt:
                opt['loader'] = PackageLoader(opt.pop('package'),
                                              opt.pop('package_path', ''))
            elif loader_func is not None:
                opt['loader'] = FunctionLoader(loader_func)

            sandboxed = opt.pop('sandboxed', None)
            if sandboxed:
                self.env = SandboxedEnvironment(**opt)
            else:
                self.env = Environment(**opt)

        self.extra_vars_func = extra_vars_func
        self.extension = options.pop('jinja2.extension', None)

    def render(self, info, format="html", fragment=False, template=None):
        """ Return a rendered version of the template.

        'info' is a dict of context variables (string : anything).
        'format' is the desired output format.  This is engine-specific.
        'fragment' is true if the template should be rendered "standalone";
            i.e., bypassing any inherited templates or wrapper templates that
            would normally be applied.  The plugin may ignore this argument if
            the engine does not support this.
        'template' is the template name (string).  Buffet requires dotted
            notation (see below), while Pylons allows URI notation.

        The method should call the 'extra_vars_funcs' function given to the
        constructor, and merge those variables in with 'info'.
        """
        if isinstance(template, basestring):
            template = self.load_template(template)
        if self.extra_vars_func:
            info.update(self.extra_vars_func())
        return template.render(info)

    def load_template(self, templatename, template_string=None):
        """ Optional: not called by Pylons. Called by TurboGears in special
         circumstances; see Buffet interface for details.
        """
        if template_string is not None:
            return self.env.from_string(template_string)
        # Translate TG dot notation to normal / template path
        if self.extension is not None:
            templatename = templatename.replace('.', '/') + '.' + self.extension
        return self.env.get_template(templatename)

    # def transform(self, info, template):
    #     """ Optional: not called by Pylons.  Called by TurboGears to render the
    #     template as a tree of ElementTree nodes rather than as a string.  Kid
    #     is the only known engine that supports this.
    #     """
    #     pass

posted by id:junya_hayashi