[fedocal] master: Fix typos (f05c5a4)
by Johan Cwiklinski
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit f05c5a4a09d2a639191699e0629c095999d4f7a7
Author: Johan Cwiklinski <johan(a)x-tnd.be>
Date: Mon Nov 26 16:21:04 2012 +0100
Fix typos
>---------------------------------------------------------------
README.rst | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/README.rst b/README.rst
index 3895891..b930358 100644
--- a/README.rst
+++ b/README.rst
@@ -158,7 +158,7 @@ is not up to date, then you will have to run::
alembic upgrade head
.. note:: If this is the first time you are running ``alembic``, you will
- need to copy file ``elembic.ini.smaple`` to ``alembic.ini`` and setup
+ need to copy file ``alembic.ini.sample`` to ``alembic.ini`` and setup
the ``sqlalchemy.url`` variable in the latest
11 years, 5 months
[fedocal] master: Work on the cron job (1b3b686)
by Pierre-YvesChibon
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit 1b3b686455be06f25c7359e8a0b982bb40c3d33d
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Nov 25 22:49:28 2012 +0100
Work on the cron job
Change the retrieve_meeting_to_remind function to cover a time-range instead a given
specific time. This is useful now that we consider more than just the full hour.
Fix the unit-tests accordingly.
>---------------------------------------------------------------
fedocal/fedocallib/__init__.py | 16 +++++++++-------
fedocal/fedocallib/model.py | 9 +++++----
fedocal/tests/test_fedocallib.py | 4 ++--
fedocal/tests/test_meeting.py | 11 +++++++----
4 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/fedocal/fedocallib/__init__.py b/fedocal/fedocallib/__init__.py
index 3aa5f55..16f197f 100644
--- a/fedocal/fedocallib/__init__.py
+++ b/fedocal/fedocallib/__init__.py
@@ -495,31 +495,33 @@ def _generate_date_rounded_to_the_hour(meetingdate, offset):
"""
delta = timedelta(hours=offset)
new_date = meetingdate + delta
- new_date = new_date - timedelta(minutes=new_date.minute,
- seconds=new_date.second,
+ new_date = new_date - timedelta(seconds=new_date.second,
microseconds=new_date.microsecond)
return new_date
-def retrieve_meeting_to_remind(session):
+def retrieve_meeting_to_remind(session, offset=30):
""" Retrieve all the meetings for which we have to send a reminder.
:arg session: the database session to use.
+ :kwarg offset: the frequency at which the cron job is ran in order
+ to avoid sending twice the same reminder.
"""
today = datetime.utcnow()
# Retrieve meeting planned in less than 12h
new_date = _generate_date_rounded_to_the_hour(today, 12)
+ end_date = new_date + timedelta(minutes=offset)
meetings = Meeting.get_meeting_with_reminder(session,
- new_date.date(), new_date.time(), 'H-12')
+ new_date.date(), new_date.time(), end_date.time(), 'H-12')
new_date = _generate_date_rounded_to_the_hour(today, 24)
meetings.extend(Meeting.get_meeting_with_reminder(session,
- new_date.date(), new_date.time(), 'H-24'))
+ new_date.date(), new_date.time(), end_date.time(), 'H-24'))
new_date = _generate_date_rounded_to_the_hour(today, 48)
meetings.extend(Meeting.get_meeting_with_reminder(session,
- new_date.date(), new_date.time(), 'H-48'))
+ new_date.date(), new_date.time(), end_date.time(), 'H-48'))
new_date = _generate_date_rounded_to_the_hour(today, 168)
meetings.extend(Meeting.get_meeting_with_reminder(session,
- new_date.date(), new_date.time(), 'H-168'))
+ new_date.date(), new_date.time(), end_date.time(), 'H-168'))
return meetings
diff --git a/fedocal/fedocallib/model.py b/fedocal/fedocallib/model.py
index 4ee0b4a..12f3e9c 100644
--- a/fedocal/fedocallib/model.py
+++ b/fedocal/fedocallib/model.py
@@ -305,13 +305,13 @@ class Meeting(BASE):
def get_by_time(cls, session, calendar, meetingdate, start_time,
stop_time):
""" Retrieve the list of meetings for a given date and between
- two times.
+ two times for a specific calendar.
"""
return session.query(cls).filter(and_
(Meeting.calendar == calendar),
(Meeting.meeting_date == meetingdate),
(Meeting.meeting_time_start >= start_time),
- (Meeting.meeting_time_stop <= stop_time)).all()
+ (Meeting.meeting_time_stop < stop_time)).all()
@classmethod
def at_time(cls, session, calendar, meetingdate, t_time):
@@ -363,7 +363,7 @@ class Meeting(BASE):
@classmethod
def get_meeting_with_reminder(cls, session, start_date,
- start_time, offset):
+ start_time, stop_time, offset):
""" Retrieve the list of meetings with a reminder set in
<offset> hours for the given day and at the specified hour.
"""
@@ -374,7 +374,8 @@ class Meeting(BASE):
return []
return session.query(cls).filter(and_
(Meeting.meeting_date == start_date),
- (Meeting.meeting_time_start == start_time),
+ (Meeting.meeting_time_start >= start_time),
+ (Meeting.meeting_time_start < stop_time),
(Meeting.reminder_id.in_(reminders))).all()
diff --git a/fedocal/tests/test_fedocallib.py b/fedocal/tests/test_fedocallib.py
index e70af93..0dc3bff 100644
--- a/fedocal/tests/test_fedocallib.py
+++ b/fedocal/tests/test_fedocallib.py
@@ -470,8 +470,8 @@ class Fedocallibtests(Modeltests):
meeting_manager='pingou',
meeting_date=time_start.date(),
meeting_date_end=time_start.date(),
- meeting_time_start=time(time_start.hour, 00),
- meeting_time_stop=time(time_end.hour, 00),
+ meeting_time_start=time_start.time(),
+ meeting_time_stop=time_end.time(),
meeting_information='This is a test meeting with reminder',
calendar_name='test_calendar',
reminder_id=remobj.reminder_id)
diff --git a/fedocal/tests/test_meeting.py b/fedocal/tests/test_meeting.py
index f3ee5ec..52763b9 100644
--- a/fedocal/tests/test_meeting.py
+++ b/fedocal/tests/test_meeting.py
@@ -544,7 +544,8 @@ class Meetingtests(Modeltests):
""" Test the Meeting get_meeting_with_reminder function. """
self.test_init_meeting()
meetings = model.Meeting.get_meeting_with_reminder(self.session,
- TODAY + timedelta(days=11), time(11, 00), 'H-12')
+ TODAY + timedelta(days=11), time(11, 00), time(11, 30),
+ 'H-12')
self.assertNotEqual(meetings, None)
self.assertEqual(len(meetings), 1)
self.assertEqual(meetings[0].meeting_name,
@@ -557,19 +558,21 @@ class Meetingtests(Modeltests):
"""
self.test_init_meeting()
meetings = model.Meeting.get_meeting_with_reminder(self.session,
- TODAY + timedelta(days=11), time(11, 00), 'H-96')
+ TODAY + timedelta(days=11), time(11, 00), time(11, 30),
+ 'H-96')
self.assertNotEqual(meetings, None)
self.assertEqual(len(meetings), 0)
self.assertEqual(meetings, [])
meetings = model.Meeting.get_meeting_with_reminder(self.session,
- TODAY + timedelta(days=11), time(9, 00), 'H-12')
+ TODAY + timedelta(days=11), time(9, 00), time(9, 30), 'H-12')
self.assertNotEqual(meetings, None)
self.assertEqual(len(meetings), 0)
self.assertEqual(meetings, [])
meetings = model.Meeting.get_meeting_with_reminder(self.session,
- TODAY + timedelta(days=100), time(11, 00), 'H-12')
+ TODAY + timedelta(days=100), time(11, 00), time(11, 30),
+ 'H-12')
self.assertNotEqual(meetings, None)
self.assertEqual(len(meetings), 0)
self.assertEqual(meetings, [])
11 years, 5 months
[fedocal] master: Update Usage documentation for meeting edition and deletion (97b3d33)
by pingou@fedorahosted.org
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit 97b3d335f1570243d05ea01b426e81704333c1f7
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Nov 25 15:34:17 2012 +0100
Update Usage documentation for meeting edition and deletion
Update a little the documentation on where to find the 'manage my meetings' page where
you edit or delete your meetings.
>---------------------------------------------------------------
doc/usage.rst | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/doc/usage.rst b/doc/usage.rst
index ddf3011..75d397f 100644
--- a/doc/usage.rst
+++ b/doc/usage.rst
@@ -170,9 +170,9 @@ One can only edit a meeting if he is one of the manager of the meeting or if
he is an administrator of fedocal.
-In these cases, once logged-in, go to the page ``Manage your meetings`` and
-there is presented a list of the meetings for which you are a manager and that
-you can edit.
+In these cases, once logged-in, go to the ``User`` section in the main
+menu and select ``Manage your meetings``. This page will present a list
+of the meetings for which you are a manager and that you can edit.
When editing a meeting you will have the same field as when creating one,
@@ -188,9 +188,9 @@ One can only delete a meeting if he is one of the manager of the meeting or if
he is an administrator of fedocal.
-In these cases, once logged-in, go to the page ``Manage your meetings`` and
-there is presented a list of the meetings for which you are a manager and that
-you can delete.
+In these cases, once logged-in, go to the ``User`` section in the main
+menu and select ``Manage your meetings``. This page will present a list
+of the meetings for which you are a manager and that you can delete.
You will be asked to confirm the deletion of the meeting and for recursive
11 years, 5 months
[fedocal] master: Update Usage documentation (506618a)
by Pierre-YvesChibon
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit 506618a70b89ec01a3fb36fc6f549ff057696d4d
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Nov 25 15:30:23 2012 +0100
Update Usage documentation
Update a little the formating and add some documentation on how to delete a calendar.
>---------------------------------------------------------------
doc/usage.rst | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/doc/usage.rst b/doc/usage.rst
index b9bfc83..ddf3011 100644
--- a/doc/usage.rst
+++ b/doc/usage.rst
@@ -29,6 +29,7 @@ belong to at least one more group than the ``fedora_cla`` group which
every contributor should sign to contribute to Fedora.
+
Create calendar
---------------
@@ -74,6 +75,26 @@ The form to will ask for:
Note that this can also be used to filter meetings retrieved via the API.
+
+Delete a calendar
+-----------------
+
+One can always delete a calendar if she/he is an administrator as defined
+above.
+
+To delete a calendar, select the calendar to delete in the main menu by
+clicking on its name. Then go to the ``Admin`` entry of the main menu and
+select ``Delete calendar``.
+
+You will see a confirmation page where you will have to select the checkbox
+to confirm the deletion of the Calendar.
+
+.. note:: Deletion of calendar is a permanent operation which will also
+ destroy all meetings of the calendar. You will thus loose all the
+ history of the calendar without possibility to undo it.
+
+
+
Create meeting
--------------
@@ -159,6 +180,7 @@ plus when the meeting is recursive an option to update all the future meetings
or just this one (default).
+
Delete meeting
--------------
@@ -179,6 +201,7 @@ or just this one (default).
For archives purposes, you can never delete meetings from the past.
+
iCal feed
---------
@@ -190,6 +213,7 @@ This iCal is read-only and can be found at::
http://<url to fedocal>/ical/<calendar name>/
+
.. _reminders:
Reminders
11 years, 5 months
[fedocal] master: pep8 run on test_flask_api, line was too long (6f94c6a)
by Pierre-YvesChibon
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit 6f94c6af76804df73964170a110eb3600014d803
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Nov 25 15:23:24 2012 +0100
pep8 run on test_flask_api, line was too long
>---------------------------------------------------------------
fedocal/tests/test_flask_api.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fedocal/tests/test_flask_api.py b/fedocal/tests/test_flask_api.py
index 5ac90dc..1e5b1a9 100644
--- a/fedocal/tests/test_flask_api.py
+++ b/fedocal/tests/test_flask_api.py
@@ -236,8 +236,8 @@ class FlaskApitests(Modeltests):
self.assertTrue('"error": "Date format invalid"' in \
output.data)
- output = self.app.get('/api/place/EMEA/test_calendar4/%s/2012-12-ws/' % (
- TODAY))
+ output = self.app.get('/api/place/EMEA/test_calendar4/%s/'\
+ '2012-12-ws/' % (TODAY))
self.assertEqual(output.status_code, 200)
self.assertTrue('"error": "Date format invalid:' in \
output.data)
11 years, 5 months
[fedocal] master: Add code to delete a Calendar if you are an admin (44c4882)
by Pierre-YvesChibon
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit 44c48824cebdb4e0db2fa0bd19755c1d35486370
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Nov 25 15:20:18 2012 +0100
Add code to delete a Calendar if you are an admin
You can only delete a Calendar if you are an admin and you delete the calendar which is
in the current view. So change your calendar in the main menu then go to:
admin > delete calendar.
Adjust the unit-tests accordingly so that the deletion is also tested.
>---------------------------------------------------------------
fedocal/__init__.py | 27 ++++++++++++++++++++++++++
fedocal/forms.py | 5 ++++
fedocal/templates/delete_calendar.html | 33 ++++++++++++++++++++++++++++++++
fedocal/templates/master.html | 8 ++++++-
fedocal/tests/test_calendar.py | 19 ++++++++++++++++++
5 files changed, 91 insertions(+), 1 deletions(-)
diff --git a/fedocal/__init__.py b/fedocal/__init__.py
index 470b338..c3406f6 100644
--- a/fedocal/__init__.py
+++ b/fedocal/__init__.py
@@ -461,6 +461,33 @@ def delete_meeting(meeting_id):
title=meeting.meeting_name)
+(a)APP.route('/calendar/delete/<calendar_name>/', methods=('GET', 'POST'))
+@cla_plus_one_required
+def delete_calendar(calendar_name):
+ """ Delete a specific meeting given its identifier.
+
+ :arg meeting_id: the identifier of the meeting to delete.
+ """
+ if not flask.g.fas_user or not is_admin():
+ return flask.redirect(flask.url_for('index'))
+ calendarobj = Calendar.by_id(SESSION, calendar_name)
+ deleteform = forms.DeleteCalendarForm()
+ # pylint: disable=E1101
+ if deleteform.validate_on_submit():
+ if deleteform.confirm_delete.data:
+ calendarobj.delete(SESSION)
+ try:
+ SESSION.commit()
+ # pylint: disable=W0703
+ except Exception, err:
+ print 'delete_calendar:', err
+ flask.flash('Could not delete this calendar.')
+ flask.flash('Calendar deleted')
+ return flask.redirect(flask.url_for('index'))
+ return flask.render_template('delete_calendar.html',
+ form=deleteform, calendarobj=calendarobj)
+
+
if __name__ == '__main__': # pragma: no cover
APP.debug = True
APP.run()
diff --git a/fedocal/forms.py b/fedocal/forms.py
index 3b7f13f..e79cc65 100644
--- a/fedocal/forms.py
+++ b/fedocal/forms.py
@@ -150,6 +150,11 @@ class DeleteMeetingForm(wtf.Form):
'Yes, I want to delete all futher meetings.')
+class DeleteCalendarForm(wtf.Form):
+ """ Form used to delete a calendar. """
+ confirm_delete = wtf.BooleanField('Yes I want to delete this calendar')
+
+
class LoginForm(wtf.Form):
""" Form to log in the application. """
username = wtf.TextField('Username', [wtf.validators.Required()])
diff --git a/fedocal/templates/delete_calendar.html b/fedocal/templates/delete_calendar.html
new file mode 100644
index 0000000..dad6825
--- /dev/null
+++ b/fedocal/templates/delete_calendar.html
@@ -0,0 +1,33 @@
+{% extends "master.html" %}
+
+{% block title %} {{ calendarobj.calendar_name }} {% endblock %}
+
+{% set title_extent = 'delete calendar' %}
+
+{% block content %}
+
+<h4> Calendar: {{ calendarobj.calendar_name}}</h4>
+
+<ul>
+ <li>Contact: {{ calendarobj.calendar_contact }} </li>
+ <li>Description: {{ calendarobj.calendar_description }} </li>
+ <li>Manager group: {{ calendarobj.calendar_manager_group }} </li>
+ <li>Multiple meetings: {{ calendarobj.calendar_multiple_meetings }} </li>
+ <li>Regional meeting: {{ calendarobj.calendar_regional_meetings }} </li>
+</ul>
+
+
+<p>
+ Are you positively sure that's what you want to do?
+</p>
+
+<form action="" method="post">
+{{ render_field_invert(form.confirm_delete) }}
+<p class="buttons indent">
+ <input type="submit" class="submit positive button" value="Delete">
+ <input type="button" value="Cancel" class="button" onclick="history.back();">
+</p>
+{{ form.csrf_token }}
+</form>
+
+{% endblock %}
diff --git a/fedocal/templates/master.html b/fedocal/templates/master.html
index b4a5e12..fb21e36 100644
--- a/fedocal/templates/master.html
+++ b/fedocal/templates/master.html
@@ -98,8 +98,14 @@
<h4> Admin </h4>
<ul>
<li>
- <a href="{{ url_for('add_calendar') }}"> Add a calendar </a>
+ <a href="{{ url_for('add_calendar') }}"> Add a calendar </a>
</li>
+ {% if calendar %}
+ <li>
+ <a href="{{ url_for('delete_calendar',
+ calendar_name=calendar.calendar_name) }}"> Delete calendar </a>
+ </li>
+ {% endif %}
</ul>
{% endif %}
</div>
diff --git a/fedocal/tests/test_calendar.py b/fedocal/tests/test_calendar.py
index eee73ed..f3ea640 100644
--- a/fedocal/tests/test_calendar.py
+++ b/fedocal/tests/test_calendar.py
@@ -144,6 +144,25 @@ class Calendartests(Modeltests):
self.assertEqual(len(obj), 0)
self.assertEqual(obj, [])
+ def test_delete(self):
+ """ Test the Calendar.delete method. """
+ self.test_init_calendar()
+ obj = model.Calendar.get_all(self.session)
+ self.assertNotEqual(obj, None)
+ self.assertEqual(len(obj), 4)
+ obj = model.Calendar.by_id(self.session, 'test_calendar')
+ self.assertNotEqual(obj, None)
+
+ obj.delete(self.session)
+ self.session.commit()
+
+ obj = model.Calendar.get_all(self.session)
+ self.assertNotEqual(obj, None)
+ self.assertEqual(len(obj), 3)
+ obj = model.Calendar.by_id(self.session, 'test_calendar')
+ self.assertEqual(obj, None)
+
+
if __name__ == '__main__':
SUITE = unittest.TestLoader().loadTestsFromTestCase(Calendartests)
unittest.TextTestRunner(verbosity=2).run(SUITE)
11 years, 5 months
[fedocal] master: Add a delete method to the Calendar object (5e8e108)
by Pierre-YvesChibon
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit 5e8e108d1e6230ce9b9b74e0b2d1118168ff5c8b
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Nov 25 15:12:29 2012 +0100
Add a delete method to the Calendar object
>---------------------------------------------------------------
fedocal/fedocallib/model.py | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/fedocal/fedocallib/model.py b/fedocal/fedocallib/model.py
index 36a4b3a..4ee0b4a 100644
--- a/fedocal/fedocallib/model.py
+++ b/fedocal/fedocallib/model.py
@@ -93,6 +93,10 @@ class Calendar(BASE):
""" Save the object into the database. """
session.add(self)
+ def delete(self, session):
+ """ Remove the object into the database. """
+ session.delete(self)
+
@classmethod
def by_id(cls, session, identifier):
""" Retrieve a Calendar object from the database based on its
11 years, 5 months
[fedocal] master: Move the API from the main controller to its own. (bbecc0b)
by pingou@fedorahosted.org
Repository : http://git.fedorahosted.org/cgit/fedocal.git
On branch : master
>---------------------------------------------------------------
commit bbecc0bfd3114c83527138bf7d371c67cd3fe463
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Nov 25 14:52:26 2012 +0100
Move the API from the main controller to its own.
The controller of the API is moved to its own file instead of being in the main controller.
Fix the tests accordingly, this meant fixing the test configuration file as well as the
__init__ method.
Adding as well a new meeting (#11) in order to keep the coverage of the API at 100%.
In the meanwhile, change the setUp function for all tests to use scoped_session as in
the application.
>---------------------------------------------------------------
fedocal/__init__.py | 168 +---------------------------------
fedocal/api.py | 192 +++++++++++++++++++++++++++++++++++++++
fedocal/tests/__init__.py | 9 ++-
fedocal/tests/fedocal_test.cfg | 4 +-
fedocal/tests/test_flask_api.py | 49 +++++++---
fedocal/tests/test_meeting.py | 14 +++
6 files changed, 257 insertions(+), 179 deletions(-)
diff --git a/fedocal/__init__.py b/fedocal/__init__.py
index 4991e49..470b338 100644
--- a/fedocal/__init__.py
+++ b/fedocal/__init__.py
@@ -40,10 +40,10 @@ import flask
from flask_fas import FAS, cla_plus_one_required
import forms as forms
-import fedocallib as fedocallib
+import fedocal.fedocallib as fedocallib
import fedocallib.dbaction
-from fedocallib.exceptions import FedocalException
-from fedocallib.model import (Calendar, Meeting, Reminder)
+from fedocal.fedocallib.exceptions import FedocalException
+from fedocal.fedocallib.model import (Calendar, Meeting, Reminder)
# Create the application.
APP = flask.Flask(__name__)
@@ -54,6 +54,9 @@ APP.config.from_envvar('FEDOCAL_CONFIG')
SESSION = fedocallib.create_session(APP.config['DB_URL'])
+import fedocal.api
+
+
@APP.context_processor
def inject_calendars():
""" With this decorator we add the list of all the calendars
@@ -458,165 +461,6 @@ def delete_meeting(meeting_id):
title=meeting.meeting_name)
-### API
-
-(a)APP.route('/api/')
-def api():
- """ Display the api information page. """
- auth_form = forms.LoginForm()
- admin = is_admin()
- return flask.render_template('api.html',
- auth_form=auth_form,
- admin=admin)
-
-
-(a)APP.route('/api/date/<calendar_name>/')
-def api_date_default(calendar_name):
- """ Returns all the meetings for the specified calendar for the
- time frame between today - 30 days to today + 180 days.
-
- :arg calendar_name: the name of the calendar to retrieve information
- from.
- """
- startd = datetime.date.today() - datetime.timedelta(days=30)
- endd = datetime.date.today() + datetime.timedelta(days=180)
- meetings = fedocallib.get_meetings_by_date(SESSION, calendar_name,
- startd, endd)
- if not meetings:
- output = '{ "retrieval": "notok", "meeting": []}'
- else:
- output = '{ "retrieval": "ok", "meeting": [\n'
- cnt = 0
- for meeting in meetings:
- output = output + meeting.to_json()
- cnt = cnt + 1
- if cnt != len(meetings):
- output = output + ','
- output = output + '\n]}'
- return flask.Response(output)
-
-
-(a)APP.route('/api/date/<calendar_name>/<start_date>/<end_date>/')
-def api_date(calendar_name, start_date, end_date):
- """ Returns all the meetings for the specified calendar for the
- specified time frame.
-
- :arg calendar_name: the name of the calendar to retrieve information
- from.
- :arg start_date: the start date of the time frame for which one
- would like to retrieve the meetings.
- :arg end_date: the end date of the time frame for which one would
- like to retrieve the meetings.
- """
- start_date = start_date.split('-')
- end_date = end_date.split('-')
- if len(start_date) != 3 or len(end_date) != 3:
- output = '{ "retrieval": "notok", "meeting": [], "error": '\
- '"Date format invalid"}'
- return flask.Response(output)
- try:
- start_date = [int(item) for item in start_date]
- end_date = [int(item) for item in end_date]
- startd = datetime.date(start_date[0], start_date[1],
- start_date[2])
- endd = datetime.date(end_date[0], end_date[1], end_date[2])
- except ValueError, error:
- output = '{ "retrieval": "notok", "meeting": [], "error": '\
- '"Date format invalid: %s"}' % error
- return flask.Response(output)
-
- meetings = fedocallib.get_meetings_by_date(SESSION, calendar_name,
- startd, endd)
- if not meetings:
- output = '{ "retrieval": "notok", "meeting": []}'
- else:
- output = '{ "retrieval": "ok", "meeting": [\n'
- cnt = 0
- for meeting in meetings:
- output = output + meeting.to_json()
- cnt = cnt + 1
- if cnt != len(meetings):
- output = output + ','
- output = output + '\n]}'
- return flask.Response(output)
-
-
-(a)APP.route('/api/place/<region>/<calendar_name>/')
-def api_place_default(region, calendar_name):
- """ Return all the meetings from an agenda in a specified region.
- The meetings are in the time range from today - 30 days to
- today + 180 days.
-
- :arg region: the name of the region in which the meetings will
- occur.
- :arg calendar_name: the name of the calendar to retrieve information
- from.
- """
- startd = datetime.date.today() - datetime.timedelta(days=30)
- endd = datetime.date.today() + datetime.timedelta(days=180)
- meetings = fedocallib.get_meetings_by_date_and_region(SESSION,
- calendar_name, startd, endd, region)
- if not meetings:
- output = '{ "retrieval": "notok", "meeting": []}'
- else:
- output = '{ "retrieval": "ok", "meeting": [\n'
- cnt = 0
- for meeting in meetings:
- output = output + meeting.to_json()
- cnt = cnt + 1
- if cnt != len(meetings):
- output = output + ','
- output = output + '\n]}'
- return flask.Response(output)
-
-
-(a)APP.route('/api/place/<region>/<calendar_name>/<start_date>/<end_date>/')
-def api_place(region, calendar_name, start_date, end_date):
- """ Returns all the meetings occuring in a region from an agenda
- and for the specified time frame.
-
- :arg region: the name of the region in which the meetings will
- occur.
- :arg calendar_name: the name of the calendar to retrieve information
- from.
- :arg start_date: the start date of the time frame for which one
- would like to retrieve the meetings.
- :arg end_date: the end date of the time frame for which one would
- like to retrieve the meetings.
- """
- start_date = start_date.split('-')
- end_date = end_date.split('-')
- if len(start_date) != 3 or len(end_date) != 3:
- output = '{ "retrieval": "notok", "meeting": [], "error": '\
- '"Date format invalid"}'
- return flask.Response(output)
- try:
- start_date = [int(item) for item in start_date]
- end_date = [int(item) for item in end_date]
- startd = datetime.date(start_date[0], start_date[1],
- start_date[2])
- endd = datetime.date(end_date[0], end_date[1], end_date[2])
- except ValueError, error:
- output = '{ "retrieval": "notok", "meeting": [], "error": '\
- '"Date format invalid: %s"}' % error
- return flask.Response(output)
-
- meetings = fedocallib.get_meetings_by_date_and_region(SESSION,
- calendar_name, startd, endd, region)
- if not meetings:
- output = '{ "retrieval": "notok", "meeting": []}'
- else:
- output = '{ "retrieval": "ok", "meeting": [\n'
- cnt = 0
- for meeting in meetings:
- output = output + meeting.to_json()
- cnt = cnt + 1
- if cnt != len(meetings):
- output = output + ','
- output = output + '\n]}'
- return flask.Response(output)
-
-
if __name__ == '__main__': # pragma: no cover
APP.debug = True
APP.run()
diff --git a/fedocal/api.py b/fedocal/api.py
new file mode 100644
index 0000000..a9dba39
--- /dev/null
+++ b/fedocal/api.py
@@ -0,0 +1,192 @@
+#!/usr/bin/python
+#-*- coding: UTF-8 -*-
+
+"""
+ (c) 2012 - Copyright Pierre-Yves Chibon <pingou(a)pingoured.fr>
+
+ Distributed under License GPLv3 or later
+ You can find a copy of this license on the website
+ http://www.gnu.org/licenses/gpl.html
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA.
+"""
+
+
+import datetime
+import flask
+
+import fedocal.fedocallib as fedocallib
+import fedocal.forms as forms
+
+from fedocal import APP, SESSION
+import fedocal
+
+
+### API
+(a)APP.route('/api/')
+def api():
+ """ Display the api information page. """
+ auth_form = forms.LoginForm()
+ admin = fedocal.is_admin()
+ return flask.render_template('api.html', auth_form=auth_form,
+ admin=admin)
+
+
+(a)APP.route('/api/date/<calendar_name>/')
+def api_date_default(calendar_name):
+ """ Returns all the meetings for the specified calendar for the
+ time frame between today - 30 days to today + 180 days.
+
+ :arg calendar_name: the name of the calendar to retrieve information
+ from.
+ """
+ startd = datetime.date.today() - datetime.timedelta(days=30)
+ endd = datetime.date.today() + datetime.timedelta(days=180)
+ meetings = fedocallib.get_meetings_by_date(SESSION, calendar_name,
+ startd, endd)
+ if not meetings:
+ output = '{ "retrieval": "notok", "meeting": []}'
+ else:
+ output = '{ "retrieval": "ok", "meeting": [\n'
+ cnt = 0
+ for meeting in meetings:
+ output = output + meeting.to_json()
+ cnt = cnt + 1
+ if cnt != len(meetings):
+ output = output + ','
+ output = output + '\n]}'
+ return flask.Response(output)
+
+
+(a)APP.route('/api/date/<calendar_name>/<start_date>/<end_date>/')
+def api_date(calendar_name, start_date, end_date):
+ """ Returns all the meetings for the specified calendar for the
+ specified time frame.
+
+ :arg calendar_name: the name of the calendar to retrieve information
+ from.
+ :arg start_date: the start date of the time frame for which one
+ would like to retrieve the meetings.
+ :arg end_date: the end date of the time frame for which one would
+ like to retrieve the meetings.
+ """
+ start_date = start_date.split('-')
+ end_date = end_date.split('-')
+ if len(start_date) != 3 or len(end_date) != 3:
+ output = '{ "retrieval": "notok", "meeting": [], "error": '\
+ '"Date format invalid"}'
+ return flask.Response(output)
+ try:
+ start_date = [int(item) for item in start_date]
+ end_date = [int(item) for item in end_date]
+ startd = datetime.date(start_date[0], start_date[1],
+ start_date[2])
+ endd = datetime.date(end_date[0], end_date[1], end_date[2])
+ except ValueError, error:
+ output = '{ "retrieval": "notok", "meeting": [], "error": '\
+ '"Date format invalid: %s"}' % error
+ return flask.Response(output)
+
+ meetings = fedocallib.get_meetings_by_date(SESSION, calendar_name,
+ startd, endd)
+ if not meetings:
+ output = '{ "retrieval": "notok", "meeting": []}'
+ else:
+ output = '{ "retrieval": "ok", "meeting": [\n'
+ cnt = 0
+ for meeting in meetings:
+ output = output + meeting.to_json()
+ cnt = cnt + 1
+ if cnt != len(meetings):
+ output = output + ','
+ output = output + '\n]}'
+ return flask.Response(output)
+
+
+(a)APP.route('/api/place/<region>/<calendar_name>/')
+def api_place_default(region, calendar_name):
+ """ Return all the meetings from an agenda in a specified region.
+ The meetings are in the time range from today - 30 days to
+ today + 180 days.
+
+ :arg region: the name of the region in which the meetings will
+ occur.
+ :arg calendar_name: the name of the calendar to retrieve information
+ from.
+ """
+ startd = datetime.date.today() - datetime.timedelta(days=30)
+ endd = datetime.date.today() + datetime.timedelta(days=180)
+ meetings = fedocallib.get_meetings_by_date_and_region(SESSION,
+ calendar_name, startd, endd, region)
+ if not meetings:
+ output = '{ "retrieval": "notok", "meeting": []}'
+ else:
+ output = '{ "retrieval": "ok", "meeting": [\n'
+ cnt = 0
+ for meeting in meetings:
+ output = output + meeting.to_json()
+ cnt = cnt + 1
+ if cnt != len(meetings):
+ output = output + ','
+ output = output + '\n]}'
+ return flask.Response(output)
+
+
+(a)APP.route('/api/place/<region>/<calendar_name>/<start_date>/<end_date>/')
+def api_place(region, calendar_name, start_date, end_date):
+ """ Returns all the meetings occuring in a region from an agenda
+ and for the specified time frame.
+
+ :arg region: the name of the region in which the meetings will
+ occur.
+ :arg calendar_name: the name of the calendar to retrieve information
+ from.
+ :arg start_date: the start date of the time frame for which one
+ would like to retrieve the meetings.
+ :arg end_date: the end date of the time frame for which one would
+ like to retrieve the meetings.
+ """
+ start_date = start_date.split('-')
+ end_date = end_date.split('-')
+ if len(start_date) != 3 or len(end_date) != 3:
+ output = '{ "retrieval": "notok", "meeting": [], "error": '\
+ '"Date format invalid"}'
+ return flask.Response(output)
+ try:
+ start_date = [int(item) for item in start_date]
+ end_date = [int(item) for item in end_date]
+ startd = datetime.date(start_date[0], start_date[1],
+ start_date[2])
+ endd = datetime.date(end_date[0], end_date[1], end_date[2])
+ except ValueError, error:
+ output = '{ "retrieval": "notok", "meeting": [], "error": '\
+ '"Date format invalid: %s"}' % error
+ return flask.Response(output)
+
+ meetings = fedocallib.get_meetings_by_date_and_region(SESSION,
+ calendar_name, startd, endd, region)
+ if not meetings:
+ output = '{ "retrieval": "notok", "meeting": []}'
+ else:
+ output = '{ "retrieval": "ok", "meeting": [\n'
+ cnt = 0
+ for meeting in meetings:
+ output = output + meeting.to_json()
+ cnt = cnt + 1
+ if cnt != len(meetings):
+ output = output + ','
+ output = output + '\n]}'
+ return flask.Response(output)
diff --git a/fedocal/tests/__init__.py b/fedocal/tests/__init__.py
index a95652a..b3b31b9 100644
--- a/fedocal/tests/__init__.py
+++ b/fedocal/tests/__init__.py
@@ -38,6 +38,10 @@ from datetime import date
from datetime import time
from datetime import timedelta
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import scoped_session
+
sys.path.insert(0, os.path.join(os.path.dirname(
os.path.abspath(__file__)), '..'))
@@ -61,7 +65,10 @@ class Modeltests(unittest.TestCase):
# pylint: disable=C0103
def setUp(self):
""" Set up the environnment, ran before every tests. """
- self.session = model.create_tables('sqlite:///%s' % DB_PATH)
+ model.create_tables('sqlite:///%s' % DB_PATH)
+ engine = create_engine('sqlite:///%s' % DB_PATH)
+ scopedsession = scoped_session(sessionmaker(bind=engine))
+ self.session = scopedsession
# pylint: disable=C0103
def tearDown(self):
diff --git a/fedocal/tests/fedocal_test.cfg b/fedocal/tests/fedocal_test.cfg
index 7a8406d..d6d8b22 100644
--- a/fedocal/tests/fedocal_test.cfg
+++ b/fedocal/tests/fedocal_test.cfg
@@ -2,7 +2,9 @@
SECRET_KEY='<The web application secret key>'
### url to the database server:
-DB_URL='sqlite:////tmp/fedocal_dev.sqlite'
+import os
+DB_URL = 'sqlite:///%s/test.db' % (os.path.dirname(os.path.abspath(__file__)))
+#DB_URL='sqlite:////tmp/fedocal_dev.sqlite'
### The FAS group in which the admin of fedocal are
ADMIN_GROUP='packager'
diff --git a/fedocal/tests/test_flask_api.py b/fedocal/tests/test_flask_api.py
index 3849214..5ac90dc 100644
--- a/fedocal/tests/test_flask_api.py
+++ b/fedocal/tests/test_flask_api.py
@@ -61,8 +61,8 @@ class FlaskApitests(Modeltests):
super(FlaskApitests, self).setUp()
fedocal.APP.config['TESTING'] = True
- fedocal.SESSION = fedocallib.create_session(
- 'sqlite:///%s' % DB_PATH)
+ fedocal.APP.config['DB_URL'] = DB_PATH
+ fedocal.SESSION = self.session
self.app = fedocal.APP.test_client()
def test_api(self):
@@ -102,7 +102,7 @@ class FlaskApitests(Modeltests):
output = self.app.get('/api/date/test_calendar4/')
self.assertEqual(output.status_code, 200)
self.assertTrue('"retrieval": "ok"' in output.data)
- self.assertEqual(output.data.count('meeting_name'), 2)
+ self.assertEqual(output.data.count('meeting_name'), 3)
def test_api_date(self):
""" Test the api_date function. """
@@ -134,6 +134,24 @@ class FlaskApitests(Modeltests):
self.assertTrue('"retrieval": "ok"' in output.data)
self.assertEqual(output.data.count('meeting_name'), 2)
+ def test_api_date_error(self):
+ """ Test the api_date function with wrong input. """
+ self.__setup_db()
+
+ output = self.app.get('/api/date/test_calendar/%s/2012-09-aw/' %
+ (TODAY))
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue('"retrieval": "notok"' in output.data)
+ self.assertTrue('"error": "Date format invalid:' in \
+ output.data)
+
+ output = self.app.get('/api/date/test_calendar/%s/2012-09/' %
+ (TODAY))
+ self.assertEqual(output.status_code, 200)
+ self.assertTrue('"retrieval": "notok"' in output.data)
+ self.assertTrue('"error": "Date format invalid"' in \
+ output.data)
+
def test_api_place_default(self):
""" Test the api_place_default function. """
output = self.app.get('/api/place/EMEA/foobar')
@@ -159,7 +177,7 @@ class FlaskApitests(Modeltests):
output = self.app.get('/api/place/EMEA/test_calendar4/')
self.assertEqual(output.status_code, 200)
self.assertTrue('"retrieval": "ok"' in output.data)
- self.assertEqual(output.data.count('meeting_name'), 1)
+ self.assertEqual(output.data.count('meeting_name'), 2)
def test_api_place(self):
""" Test the api_place function. """
@@ -208,20 +226,21 @@ class FlaskApitests(Modeltests):
self.assertEqual(output.data,
'{ "retrieval": "notok", "meeting": []}')
- def test_api_date_place_error(self):
- """ Test the api_date and api_place functions with wrongly
- formated input. """
- output = self.app.get('/api/date/foobar/2000-01/2000-02/')
+ def test_api_place_error(self):
+ """ Test the api_date function with wrong input. """
+ self.__setup_db()
+
+ output = self.app.get('/api/place/EMEA/test_calendar4/%s/2012-12/' % (
+ TODAY))
self.assertEqual(output.status_code, 200)
- self.assertEqual(output.data,
- '{ "retrieval": "notok", "meeting": [], "error": '\
- '"Date format invalid"}')
+ self.assertTrue('"error": "Date format invalid"' in \
+ output.data)
- output = self.app.get('/api/place/EMEA/foobar/2000-01/2000-02/')
+ output = self.app.get('/api/place/EMEA/test_calendar4/%s/2012-12-ws/' % (
+ TODAY))
self.assertEqual(output.status_code, 200)
- self.assertEqual(output.data,
- '{ "retrieval": "notok", "meeting": [], "error": '\
- '"Date format invalid"}')
+ self.assertTrue('"error": "Date format invalid:' in \
+ output.data)
if __name__ == '__main__':
diff --git a/fedocal/tests/test_meeting.py b/fedocal/tests/test_meeting.py
index 5bd4496..f3ee5ec 100644
--- a/fedocal/tests/test_meeting.py
+++ b/fedocal/tests/test_meeting.py
@@ -211,6 +211,20 @@ class Meetingtests(Modeltests):
self.session.commit()
self.assertNotEqual(obj, None)
+ obj = model.Meeting( # id:11
+ meeting_name='test-meeting-11',
+ meeting_manager='test,',
+ meeting_date=TODAY + timedelta(days=20),
+ meeting_date_end=TODAY + timedelta(days=20),
+ meeting_time_start=time(17, 00),
+ meeting_time_stop=time(18, 00),
+ meeting_information='This is a second test meeting in EMEA',
+ calendar_name='test_calendar4',
+ meeting_region='EMEA')
+ obj.save(self.session)
+ self.session.commit()
+ self.assertNotEqual(obj, None)
+
def test_repr_meeting(self):
""" Test the Meeting string representation function. """
self.test_init_meeting()
11 years, 5 months