Skip to content
This repository has been archived by the owner on Jan 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1 from jezdez/master
Browse files Browse the repository at this point in the history
A visit from the packaging fairy.
  • Loading branch information
idan committed Jun 7, 2011
2 parents da88f55 + d4eb8a5 commit 5541a97
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 53 deletions.
3 changes: 2 additions & 1 deletion .gitignore
@@ -1 +1,2 @@
*.pyc
*.pyc
*.egg-info
2 changes: 2 additions & 0 deletions MANIFEST.in
@@ -0,0 +1,2 @@
include README.rst
recursive-include fuzzydt/static/fuzzydt *.js *.css
1 change: 0 additions & 1 deletion README.rst
Expand Up @@ -48,7 +48,6 @@ Release History
TODO
----

* Packaging
* Making it easy to use the included media.
* Document what external media is used (also that this project requires a customized version of labelify.)
* css examples
Expand Down
12 changes: 7 additions & 5 deletions fuzzydt/fields.py
@@ -1,8 +1,10 @@
import datetime

from django import forms
from django.utils.translation import ugettext_lazy as _
from fuzzydt.widgets import *

from parsedatetime.parsedatetime import Calendar
import datetime

# These values, if given to to_python(), will trigger the self.required check.
EMPTY_VALUES = (None, '')
Expand All @@ -17,7 +19,7 @@ def __init__(self, url, *args, **kwargs):
self.url = url
self.widget = FuzzyDateInput(url=url)
super(FuzzyDateField, self).__init__(*args, **kwargs)

def clean(self, value):
"""
Validates that the input can be converted to a date. Returns a Python
Expand Down Expand Up @@ -58,7 +60,7 @@ def clean(self, value):
return None
if isinstance(value, datetime.time):
return value

c = Calendar()
parsed = c.parse(value)
if parsed[1] == 2:
Expand All @@ -75,7 +77,7 @@ def __init__(self, url, *args, **kwargs):
self.url = url
self.widget = FuzzyDateTimeInput(url=url)
super(FuzzyDateTimeField, self).__init__(*args, **kwargs)

def clean(self, value):
"""
Validates that the input can be converted to a datetime. Returns a
Expand All @@ -94,7 +96,7 @@ def clean(self, value):
if len(value) != 2:
raise ValidationError(self.error_messages['invalid'])
value = '%s %s' % tuple(value)

c = Calendar()
parsed = c.parse(value)
if parsed[1] == 3:
Expand Down
File renamed without changes.
37 changes: 19 additions & 18 deletions fuzzydt/views.py
@@ -1,78 +1,79 @@
from django.http import HttpResponse, HttpResponseBadRequest
from parsedatetime.parsedatetime import Calendar
import datetime
from parsedatetime.parsedatetime import Calendar

from django.http import HttpResponse, HttpResponseBadRequest
from django.utils import simplejson as json
from django.utils.dateformat import format

def fuzzydtparse(request):
"""
Attempts to parse a natural-language date/time string and return a
formatted representation of the parsed date/time.
The returned representations are formatted using django's php-style
datetime formatting facilities. See
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#now for a
full specification
GET/POST arguments:
dtstring *(required)*
The natural-language date and/or time string to parse.
dateformat (optional)
A format specifier string used to format the returned representation
if it is determined to be a date instance. The default format is
'l, F jS Y', which produces values like 'Thursday, October 1st 2009'.
timeformat (optional)
A format specifier string used to format the returned representation
if it is determined to be a time instance. The default format is
'P', which produces values like '6:26 p.m.'.
dtformat (optional)
A format specifier string used to format the returned representation
if it is determined to be a datetime instance. The default format is
'l, F jS Y, P', which produces values like
'Thursday, October 1st 2009, 6:26 p.m.'.
require (optional)
One of 'date', 'time', 'datetime'. If the parsed value is not of the
specified type, the view will return 400/Bad Request
callback (optional)
JSONP callback.
Returns a json dictionary containing two values:
type
An string indicating the kind of representation returned.
One of 'date', 'time', or 'datetime'
parsed
A string representation of the parsed datetime.
Invalid / unparsable datetimes will return 400/Bad Request.
"""
try:
dtstring = request.REQUEST['dtstring']
except KeyError:
return HttpResponseBadRequest()


kind = {
'date': 1,
'time': 2,
'datetime': 3
}

dateformat = request.REQUEST.get('dateformat', 'l, F jS Y' )
timeformat = request.REQUEST.get('timeformat', 'P')
dtformat = request.REQUEST.get('dtformat', 'l, F jS Y, P')
require = request.REQUEST.get('require', None)
callback = request.REQUEST.get('callback', None)

if require and require not in kind:
return HttpResponseBadRequest()

c = Calendar()

# TODO: possible security hole?
Expand All @@ -98,7 +99,7 @@ def fuzzydtparse(request):
return HttpResponseBadRequest()
except:
return HttpResponseBadRequest()

if callback:
resp = "%s(%s)" % (callback, json.dumps(response_dict))
else:
Expand Down
55 changes: 27 additions & 28 deletions fuzzydt/widgets.py
@@ -1,9 +1,8 @@
from django import forms
import datetime

from django.forms.widgets import Input, MultiWidget
from django.utils.safestring import mark_safe
from django.utils.dateformat import format, time_format
from parsedatetime.parsedatetime import Calendar
import datetime

fuzzy_dtinput_template = u'''<div id="parsed_%(name)s" class="fuzzy_dtinput_parsed">%(tip)s</div><br clear="all">
<script type="text/javascript">
Expand Down Expand Up @@ -34,7 +33,7 @@
$('#id_%(name)s').addClass('annotated')
$("#parsed_%(name)s").text(json.parsed).attr('class', 'fuzzy_dtinput_ok');
}
});
});
}
}
// validate the initial contents of the field before labelify
Expand Down Expand Up @@ -62,13 +61,13 @@ class FuzzyDateInput(Input):
format = 'M jS Y' # 'Oct 31st 2009'
previewformat = 'l, F jS Y' # 'Tuesday, October 31st 2009'
tip = 'A date, like "Jan 1st 2010" or "next friday".'

class Media:
css = {
'all': ('css/fuzzydt.css',),
}
js = ('js/jquery.debounce.js', 'js/jquery.labelify.js')

def __init__(self, url, attrs=None, format=None, previewformat=None, tip=None):
if not attrs:
attrs = {'class': 'natural_dtinput'}
Expand All @@ -85,27 +84,27 @@ def __init__(self, url, attrs=None, format=None, previewformat=None, tip=None):
self.previewformat = previewformat
if tip:
self.tip = tip

self.attrs['title'] = 'Date'

def _format_value(self, value):
if value is None:
return ''
elif not isinstance(value, datetime.date):
return value
else:
return format(value, self.format)

def render(self, name, value, attrs=None):
value = self._format_value(value)
rendered = super(FuzzyDateInput, self).render(name, value, attrs)
return rendered + mark_safe(fuzzy_dtinput_template % {
'name': name,
'url': self.url,
'name': name,
'url': self.url,
'previewformat': self.previewformat,
'require': 'date',
'tip': self.tip })

def _has_changed(self, initial, data):
return super(FuzzyDateInput, self)._has_changed(self._format_value(initial), data)

Expand All @@ -114,13 +113,13 @@ class FuzzyTimeInput(Input):
format = 'g:i A' # '11:59 PM'
previewformat = 'g:i A' # '11:59 PM'
tip = 'a time, like "noon", "10a", or "6:23pm".'

class Media:
css = {
'all': ('css/fuzzydt.css',),
}
js = ('js/jquery.debounce.js', 'js/jquery.labelify.js')

def __init__(self, url, attrs=None, format=None, previewformat=None, tip=None):
if not attrs:
attrs = {'class': 'natural_dtinput'}
Expand All @@ -129,7 +128,7 @@ def __init__(self, url, attrs=None, format=None, previewformat=None, tip=None):
attrs['class'] += ' natural_dtinput'
else:
attrs['class'] = 'natural_dtinput'

super(FuzzyTimeInput, self).__init__(attrs)
self.url = url
if format:
Expand All @@ -138,18 +137,18 @@ def __init__(self, url, attrs=None, format=None, previewformat=None, tip=None):
self.previewformat = previewformat
if tip:
self.tip = tip

self.attrs['title'] = 'Time'


def _format_value(self, value):
if value is None:
return ''
elif not isinstance(value, datetime.time):
return value
else:
return time_format(value, self.format)

def render(self, name, value, attrs=None):
value = self._format_value(value)
rendered = super(FuzzyTimeInput, self).render(name, value, attrs)
Expand All @@ -159,7 +158,7 @@ def render(self, name, value, attrs=None):
'previewformat': self.previewformat,
'require': 'time',
'tip': self.tip })

def _has_changed(self, initial, data):
return super(FuzzyTimeInput, self)._has_changed(self._format_value(initial), data)

Expand All @@ -173,7 +172,7 @@ class Media:
'all': ('css/fuzzydt.css',),
}
js = ('js/jquery.debounce.js', 'js/jquery.labelify.js')

def __init__(self, url, attrs=None, format=None, previewformat=None, tip=None):
if not attrs:
attrs = {'class': 'natural_dtinput'}
Expand All @@ -190,25 +189,25 @@ def __init__(self, url, attrs=None, format=None, previewformat=None, tip=None):
self.previewformat = previewformat
if tip:
self.tip = tip

self.attrs['title'] = 'Date and Time'

def _format_value(self, value):
if value is None:
return ''
else:
return format(value, self.format)

def render(self, name, value, attrs=None):
value = self._format_value(value)
rendered = super(FuzzyDateTimeInput, self).render(name, value, attrs)
return rendered + mark_safe(fuzzy_dtinput_template % {
'name': name,
'url': self.url,
'name': name,
'url': self.url,
'previewformat': self.previewformat,
'require': 'datetime',
'tip': self.tip })

def _has_changed(self, initial, data):
return super(FuzzyDateTimeInput, self)._has_changed(self._format_value(initial), data)

Expand All @@ -232,7 +231,7 @@ def __init__(self, url, attrs=None, date_format=None, date_previewformat=None,
self.time_format = time_format
if time_previewformat:
self.time_previewformat = time_previewformat

widgets = (
FuzzyDateInput(url,
attrs=attrs,
Expand Down
35 changes: 35 additions & 0 deletions setup.py
@@ -0,0 +1,35 @@
import os
import codecs
from setuptools import setup

def read(fname):
return codecs.open(
os.path.join(os.path.dirname(__file__), fname), encoding='utf-8').read()

README = read('README.rst')

setup(
name = "django-fuzzydt",
version = "0.1a1",
url = 'https://github.com/idangazit/django-fuzzydt',
license = 'BSD',
description = '"Fuzzy" datetime parsing app for django including form fields/widgets',
long_description = README,
author = 'Idan Gazit',
author_email = 'idan@pixane.com',
packages = ['fuzzydt'],
package_data = {
'fuzzydt': ['static/fuzzydt/*/*'],
},
install_requires=['parsedatetime'],
classifiers = [
'Development Status :: 4 - Beta',
'Framework :: Django',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Topic :: Internet :: WWW/HTTP',
],
zip_safe = False,
)

0 comments on commit 5541a97

Please sign in to comment.