Skip to content

Commit 237e871

Browse files
committed
Merge branch 'release/version1.0'
2 parents 077b944 + d088772 commit 237e871

287 files changed

Lines changed: 44676 additions & 10199 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ vendor
1515
tmp/*
1616
*~
1717
*.mo
18+
settings/local*
19+
*.js.old
20+
TODO
21+
cover/
22+
sample_data.py

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "vendor"]
22
path = vendor
33
url = git://github.com/mozilla/playdoh-lib.git
4+
[submodule "vendor-local/src/python-dateutil"]
5+
path = vendor-local/src/python-dateutil
6+
url = git://github.com/cozi/python-dateutil.git

README.md

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,19 @@
1-
PTO Planner
2-
===========
1+
PTO
2+
===
33

4-
No more confusing math! This is a small web app (with a dumb name) to help
5-
you figure out how much PTO you'll have available on a given future date.
4+
Takes care of PTO management for Mozilla!
65

76
Install
87
=======
98

10-
To install, run:
9+
to be continued...
1110

12-
pip install -r requirements/compiled.txt -r requirements/dev.txt
13-
cp settings_local.py-dist settings_local.py
14-
mysql -u root -e "create database pto_planner"
15-
16-
Edit settings_local.py with the database credentials:
17-
18-
'NAME': 'pto_planner',
19-
'USER': 'root',
20-
'PASSWORD': '',
21-
...
22-
23-
Then start the web server:
24-
25-
python manage.py runserver
26-
27-
Begin Slacking Off
28-
==================
29-
30-
Open http://localhost:8000/ and start planning your next vacation.
31-
32-
Playdoh
33-
=======
34-
35-
This site is built with Mozilla's Playdoh, a web application template
36-
based on [Django][django].
37-
38-
Full [documentation][docs] for Playdoh is available.
39-
40-
[django]: http://www.djangoproject.com/
41-
[gh-playdoh]: https://github.com/mozilla/playdoh
42-
[docs]: http://playdoh.rtfd.org/
4311

4412

4513
License
4614
-------
47-
This software is licensed under the [New BSD License][BSD]. For more
15+
This software is licensed under the [Mozilla Public License Version 1.1][MPL]. For more
4816
information, read the file ``LICENSE``.
4917

50-
[BSD]: http://creativecommons.org/licenses/BSD/
18+
[MPL]: http://www.mozilla.org/MPL/
5119

apps/autocomplete/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#

apps/autocomplete/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# hey! I'm an app!

apps/autocomplete/tests.py

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# ***** BEGIN LICENSE BLOCK *****
2+
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
3+
#
4+
# The contents of this file are subject to the Mozilla Public License Version
5+
# 1.1 (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
# http://www.mozilla.org/MPL/
8+
#
9+
# Software distributed under the License is distributed on an "AS IS" basis,
10+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11+
# for the specific language governing rights and limitations under the
12+
# License.
13+
#
14+
# The Original Code is Mozilla Sheriff Duty.
15+
#
16+
# The Initial Developer of the Original Code is Mozilla Corporation.
17+
# Portions created by the Initial Developer are Copyright (C) 2011
18+
# the Initial Developer. All Rights Reserved.
19+
#
20+
# Contributor(s):
21+
# Peter Bengtsson, <peterbe@mozilla.com>
22+
#
23+
# Alternatively, the contents of this file may be used under the terms of
24+
# either the GNU General Public License Version 2 or later (the "GPL"), or
25+
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26+
# in which case the provisions of the GPL or the LGPL are applicable instead
27+
# of those above. If you wish to allow use of your version of this file only
28+
# under the terms of either the GPL or the LGPL, and not to allow others to
29+
# use your version of this file under the terms of the MPL, indicate your
30+
# decision by deleting the provisions above and replace them with the notice
31+
# and other provisions required by the GPL or the LGPL. If you do not delete
32+
# the provisions above, a recipient may use your version of this file under
33+
# the terms of any one of the MPL, the GPL or the LGPL.
34+
#
35+
# ***** END LICENSE BLOCK *****
36+
37+
import ldap
38+
from django.conf import settings
39+
from django.core.urlresolvers import reverse
40+
from django.contrib.auth.models import User
41+
from django.utils import simplejson as json
42+
from users.utils.ldap_mock import MockLDAP
43+
from mock import Mock
44+
from nose.tools import eq_, ok_
45+
from test_utils import TestCase
46+
47+
48+
class CitiesTest(TestCase):
49+
50+
def test_cities(self):
51+
url = reverse('autocomplete.cities')
52+
response = self.client.get(url)
53+
eq_(response.status_code, 403)
54+
55+
mortal = User.objects.create(username='mortal')
56+
mortal.set_password('secret')
57+
mortal.save()
58+
assert self.client.login(username='mortal', password='secret')
59+
60+
response = self.client.get(url)
61+
eq_(response.status_code, 200)
62+
ok_(response['content-type'].startswith('application/json'))
63+
struct = json.loads(response.content)
64+
eq_(struct, [])
65+
66+
profile = mortal.get_profile()
67+
profile.city = 'London'
68+
profile.save()
69+
70+
response = self.client.get(url)
71+
eq_(response.status_code, 200)
72+
struct = json.loads(response.content)
73+
eq_(struct, ['London'])
74+
75+
bob = User.objects.create(username='bob')
76+
profile = bob.get_profile()
77+
profile.city = 'Aberdeen'
78+
profile.save()
79+
80+
response = self.client.get(url)
81+
eq_(response.status_code, 200)
82+
struct = json.loads(response.content)
83+
eq_(struct, ['Aberdeen', 'London'])
84+
85+
response = self.client.get(url, {'term': 'LON'})
86+
eq_(response.status_code, 200)
87+
struct = json.loads(response.content)
88+
eq_(struct, ['London'])
89+
90+
91+
class UsersTest(TestCase):
92+
93+
def setUp(self):
94+
super(UsersTest, self).setUp()
95+
96+
ldap.open = Mock('ldap.open')
97+
ldap.open.mock_returns = Mock('ldap_connection')
98+
ldap.set_option = Mock(return_value=None)
99+
100+
def test_users(self):
101+
results = [
102+
('mail=peter@mozilla.com,o=com,dc=mozilla',
103+
{'cn': ['Peter Bengtsson'],
104+
'givenName': ['Pet\xc3\xa3r'], # utf-8 encoded
105+
'mail': ['peterbe@mozilla.com'],
106+
'sn': ['Bengtss\xc2\xa2n'],
107+
'uid': ['pbengtsson']
108+
})
109+
]
110+
111+
ldap.initialize = Mock(return_value=MockLDAP({
112+
'(&(objectClass=inetOrgPerson)(mail=*)(|(mail=peter*)(givenName=peter*)(sn=peter*)))': results
113+
}))
114+
115+
url = reverse('autocomplete.users')
116+
response = self.client.get(url, {'term': ' i '})
117+
eq_(response.status_code, 403)
118+
119+
mortal = User.objects.create(
120+
username='mortal',
121+
first_name='Mortal',
122+
last_name='Joe'
123+
)
124+
mortal.set_password('secret')
125+
mortal.save()
126+
assert self.client.login(username='mortal', password='secret')
127+
128+
response = self.client.get(url, {'term': ' i '})
129+
eq_(response.status_code, 200)
130+
ok_(response['content-type'].startswith('application/json'))
131+
132+
response = self.client.get(url, {'term': 'peter'})
133+
eq_(response.status_code, 200)
134+
ok_(response['content-type'].startswith('application/json'))
135+
struct = json.loads(response.content)
136+
ok_(isinstance(struct, list))
137+
first_item = struct[0]
138+
139+
label = '%s %s <%s>' % (u'Pet\xe3r',
140+
u'Bengtss\xa2n',
141+
'peterbe@mozilla.com')
142+
value = label
143+
eq_(first_item, {
144+
'id': 'pbengtsson',
145+
'label': label,
146+
'value': value,
147+
})
148+
149+
def test_users_knownonly(self):
150+
results = [
151+
('mail=peter@mozilla.com,o=com,dc=mozilla',
152+
{'cn': ['Peter Bengtsson'],
153+
'givenName': ['Pet\xc3\xa3r'], # utf-8 encoded
154+
'mail': ['peterbe@mozilla.com'],
155+
'sn': ['Bengtss\xc2\xa2n'],
156+
'uid': ['pbengtsson']
157+
}),
158+
('mail=peterino@mozilla.com,o=com,dc=mozilla',
159+
{'cn': ['Peterino Gaudy'],
160+
'givenName': ['Pet\xc3\xa3rino'], # utf-8 encoded
161+
'mail': ['peterino@mozilla.com'],
162+
'sn': ['Gaudi'],
163+
'uid': ['peterino']
164+
}),
165+
]
166+
167+
ldap.initialize = Mock(return_value=MockLDAP({
168+
'(&(objectClass=inetOrgPerson)(mail=*)(|(mail=peter*)(givenName=peter*)(sn=peter*)))': results
169+
}))
170+
171+
url = reverse('autocomplete.users_known_only')
172+
173+
mortal = User.objects.create(
174+
username='mortal',
175+
first_name='Mortal',
176+
last_name='Joe'
177+
)
178+
mortal.set_password('secret')
179+
mortal.save()
180+
assert self.client.login(username='mortal', password='secret')
181+
182+
response = self.client.get(url, {'term': 'peter'})
183+
eq_(response.status_code, 200)
184+
ok_(response['content-type'].startswith('application/json'))
185+
struct = json.loads(response.content)
186+
ok_(isinstance(struct, list))
187+
eq_(len(struct), 0)
188+
189+
User.objects.create(
190+
username=results[0][1]['uid'],
191+
email=results[0][1]['mail'].upper(),
192+
first_name=results[0][1]['givenName'],
193+
last_name=results[0][1]['sn'],
194+
)
195+
response = self.client.get(url, {'term': 'peter'})
196+
eq_(response.status_code, 200)
197+
struct = json.loads(response.content)
198+
eq_(len(struct), 1)
199+
200+
first_item = struct[0]
201+
202+
label = '%s %s <%s>' % (u'Pet\xe3r',
203+
u'Bengtss\xa2n',
204+
'peterbe@mozilla.com')
205+
value = label
206+
eq_(first_item, {
207+
'id': 'pbengtsson',
208+
'label': label,
209+
'value': value,
210+
})

apps/autocomplete/urls.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# ***** BEGIN LICENSE BLOCK *****
2+
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
3+
#
4+
# The contents of this file are subject to the Mozilla Public License Version
5+
# 1.1 (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
# http://www.mozilla.org/MPL/
8+
#
9+
# Software distributed under the License is distributed on an "AS IS" basis,
10+
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11+
# for the specific language governing rights and limitations under the
12+
# License.
13+
#
14+
# The Original Code is Mozilla Sheriff Duty.
15+
#
16+
# The Initial Developer of the Original Code is Mozilla Corporation.
17+
# Portions created by the Initial Developer are Copyright (C) 2011
18+
# the Initial Developer. All Rights Reserved.
19+
#
20+
# Contributor(s):
21+
# Peter Bengtsson, <peterbe@mozilla.com>
22+
#
23+
# Alternatively, the contents of this file may be used under the terms of
24+
# either the GNU General Public License Version 2 or later (the "GPL"), or
25+
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26+
# in which case the provisions of the GPL or the LGPL are applicable instead
27+
# of those above. If you wish to allow use of your version of this file only
28+
# under the terms of either the GPL or the LGPL, and not to allow others to
29+
# use your version of this file under the terms of the MPL, indicate your
30+
# decision by deleting the provisions above and replace them with the notice
31+
# and other provisions required by the GPL or the LGPL. If you do not delete
32+
# the provisions above, a recipient may use your version of this file under
33+
# the terms of any one of the MPL, the GPL or the LGPL.
34+
#
35+
# ***** END LICENSE BLOCK *****
36+
37+
from django.conf.urls.defaults import patterns, url
38+
import views
39+
40+
urlpatterns = patterns('',
41+
url(r'^cities/$', views.cities, name='autocomplete.cities'),
42+
url(r'^users/$', views.users, name='autocomplete.users'),
43+
url(r'^users/knownonly/$', views.users,
44+
{'known_only': True},
45+
name='autocomplete.users_known_only'),
46+
)

0 commit comments

Comments
 (0)