Merge pull request #6124 from johnnoone/strftime-formatter

Strftime formatter
This commit is contained in:
Thomas S Hatch 2013-07-16 17:11:46 -07:00
commit b8f26dad8d
5 changed files with 131 additions and 0 deletions

View File

@ -173,6 +173,29 @@ breaks, using `whitespace control`_.
.. _`macro`: http://jinja.pocoo.org/docs/templates/#macros .. _`macro`: http://jinja.pocoo.org/docs/templates/#macros
.. _`whitespace control`: http://jinja.pocoo.org/docs/templates/#whitespace-control .. _`whitespace control`: http://jinja.pocoo.org/docs/templates/#whitespace-control
Filters
=======
Saltstack extends `builtin filters`_ with his custom filters:
strftime
Converts any time related object into a time based string. It requires a
valid `strftime directives`_. An `exhaustive list`_ can be found in the
official Python documentation. Fuzzy dates are parsed by `timelib`_ python
module. Some exemples are available on this pages.
.. code-block:: yaml
{{ "2002/12/25"|strftime("%y") }}
{{ "1040814000"|strftime("%Y-%m-%d") }}
{{ datetime|strftime("%u") }}
{{ "now"|strftime }}
.. _`builtin filters`: http://jinja.pocoo.org/docs/templates/##builtin-filters
.. _`strftime directives`: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior
.. _`exhaustive list`: http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior
.. _`timelib`: https://github.com/pediapress/timelib/
Jinja in Files Jinja in Files
============== ==============

View File

@ -4,3 +4,4 @@ msgpack-python
pycrypto pycrypto
PyYAML PyYAML
pyzmq >= 2.1.9 pyzmq >= 2.1.9
timelib >= 0.2.4

View File

@ -26,6 +26,20 @@ import types
import warnings import warnings
from calendar import month_abbr as months from calendar import month_abbr as months
try:
import timelib
HAS_TIMELIB = True
except ImportError:
HAS_TIMELIB = False
try:
import parsedatetime
HAS_PARSEDATETIME = True
except ImportError:
HAS_PARSEDATETIME = False
try: try:
import fcntl import fcntl
HAS_FNCTL = True HAS_FNCTL = True
@ -1249,3 +1263,66 @@ def _win_console_event_handler(event):
def enable_ctrl_logoff_handler(): def enable_ctrl_logoff_handler():
if HAS_WIN32API: if HAS_WIN32API:
win32api.SetConsoleCtrlHandler(_win_console_event_handler, 1) win32api.SetConsoleCtrlHandler(_win_console_event_handler, 1)
def date_cast(date):
'''
Casts any object into a datetime.datetime object
date
any datetime, time string representation...
'''
if date is None:
return datetime.now()
elif isinstance(date, datetime.datetime):
return date
# fuzzy date
try:
if isinstance(date, salt._compat.string_types):
try:
if HAS_TIMELIB:
return timelib.strtodatetime(date)
except ValueError:
pass
# not parsed yet, obviously a timestamp?
if date.isdigit():
date = int(date)
else:
date = float(date)
return datetime.datetime.fromtimestamp(date)
except Exception as e:
if HAS_TIMELIB:
raise ValueError('Unable to parse {0}'.format(date))
raise RuntimeError('Unable to parse {0}.'
' Consider to install timelib'.format(date))
def date_format(date=None, format="%Y-%m-%d"):
'''
Converts date into a timebased string
date
any datetime, time string representation...
format
:ref:`strftime<http://docs.python.org/2/library/datetime.html#datetime.datetime.strftime>` format
>>> import datetime
>>> src = datetime.datetime(2002, 12, 25, 12, 00, 00, 00)
>>> date_format(src)
'Dec 25, 2002'
>>> src = '2002/12/25'
>>> date_format(src)
'Dec 25, 2002'
>>> src = 1040814000
>>> date_format(src)
'Dec 25, 2002'
>>> src = '1040814000'
>>> date_format(src)
'Dec 25, 2002'
'''
return date_cast(date).strftime(format)

View File

@ -115,6 +115,7 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None):
else: else:
jinja_env = jinja2.Environment( jinja_env = jinja2.Environment(
undefined=jinja2.StrictUndefined, **env_args) undefined=jinja2.StrictUndefined, **env_args)
jinja_env.filters['strftime'] = salt.utils.date_format
unicode_context = {} unicode_context = {}
for key, value in context.iteritems(): for key, value in context.iteritems():

View File

@ -4,6 +4,7 @@
import os import os
import tempfile import tempfile
import json import json
import datetime
# Import Salt Testing libs # Import Salt Testing libs
from salttesting import TestCase from salttesting import TestCase
@ -175,6 +176,33 @@ class TestGetTemplate(TestCase):
self.assertEqual(fc.requests[0]['path'], 'salt://macro') self.assertEqual(fc.requests[0]['path'], 'salt://macro')
SaltCacheLoader.file_client = _fc SaltCacheLoader.file_client = _fc
def test_strftime(self):
response = render_jinja_tmpl('{{ "2002/12/25"|strftime }}',
dict(opts=self.local_opts, env='other'))
self.assertEqual(response, '2002-12-25')
objects = (
datetime.datetime(2002, 12, 25, 12, 00, 00, 00),
'2002/12/25',
1040814000,
'1040814000'
)
for object in objects:
response = render_jinja_tmpl('{{ object|strftime }}',
dict(object=object, opts=self.local_opts, env='other'))
self.assertEqual(response, '2002-12-25')
response = render_jinja_tmpl('{{ object|strftime("%b %d, %Y") }}',
dict(object=object, opts=self.local_opts, env='other'))
self.assertEqual(response, 'Dec 25, 2002')
response = render_jinja_tmpl('{{ object|strftime("%y") }}',
dict(object=object, opts=self.local_opts, env='other'))
self.assertEqual(response, '02')
class TestCustomExtensions(TestCase): class TestCustomExtensions(TestCase):
def test_serialize(self): def test_serialize(self):
dataset = { dataset = {
@ -190,6 +218,7 @@ class TestCustomExtensions(TestCase):
rendered = env.from_string('{{ dataset|json }}').render(dataset=dataset) rendered = env.from_string('{{ dataset|json }}').render(dataset=dataset)
self.assertEquals(dataset, json.loads(rendered)) self.assertEquals(dataset, json.loads(rendered))
if __name__ == '__main__': if __name__ == '__main__':
from integration import run_tests from integration import run_tests
run_tests([TestSaltCacheLoader, TestGetTemplate, TestCustomExtensions], needs_daemon=False) run_tests([TestSaltCacheLoader, TestGetTemplate, TestCustomExtensions], needs_daemon=False)