Revision 6ab72614
Corrections suite à l'analyse de Pylint.
git-svn-id: https://vigilo-dev.si.c-s.fr/svn@1803 b22e2e97-25c9-44ff-b637-2e5ceca36478
vigiboard/config/__init__.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 |
|
|
2 |
""" Fichiers de configuration spécifiques à Vigiboard """ |
vigiboard/controllers/root.py | ||
---|---|---|
14 | 14 |
from pylons.i18n import ugettext as _ |
15 | 15 |
from pylons.i18n import lazy_ugettext as l_ |
16 | 16 |
from pylons.controllers.util import abort |
17 |
from sqlalchemy import not_, and_, or_, asc |
|
18 |
from sqlalchemy.orm import aliased |
|
17 |
from sqlalchemy import asc |
|
19 | 18 |
from sqlalchemy.sql import func |
20 |
from sqlalchemy.sql.expression import union |
|
21 | 19 |
from repoze.what.predicates import Any, not_anonymous |
22 | 20 |
|
23 | 21 |
from vigilo.models.session import DBSession |
24 | 22 |
from vigilo.models import Event, EventHistory, CorrEvent, SupItem, \ |
25 |
Host, HostGroup, ServiceGroup, \ |
|
26 |
StateName, User, LowLevelService |
|
23 |
HostGroup, ServiceGroup, StateName, User |
|
27 | 24 |
from vigilo.models.functions import sql_escape_like |
28 |
from vigilo.models.secondary_tables import HOST_GROUP_TABLE, \ |
|
29 |
SERVICE_GROUP_TABLE |
|
30 | 25 |
|
31 | 26 |
from vigilo.turbogears.controllers.autocomplete import AutoCompleteController |
32 | 27 |
from vigiboard.controllers.vigiboardrequest import VigiboardRequest |
... | ... | |
122 | 117 |
servicegroup = sql_escape_like(servicegroup) |
123 | 118 |
aggregates.add_join((ServiceGroup, ServiceGroup.idgroup == \ |
124 | 119 |
aggregates.items.c.idservicegroup)) |
125 |
aggregates.add_filter(ServiceGroup.name.ilike('%%%s%%' % servicegroup)) |
|
120 |
aggregates.add_filter( |
|
121 |
ServiceGroup.name.ilike('%%%s%%' % servicegroup)) |
|
126 | 122 |
|
127 | 123 |
if host: |
128 | 124 |
search['host'] = host |
... | ... | |
333 | 329 |
'host': validators.NotEmpty(), |
334 | 330 |
# 'service': validators.NotEmpty() |
335 | 331 |
}, |
336 |
error_handler=process_form_errors)
|
|
332 |
error_handler = process_form_errors)
|
|
337 | 333 |
@expose('vigiboard.html') |
338 | 334 |
@require(Any(not_anonymous(), msg=l_("You need to be authenticated"))) |
339 | 335 |
def host_service(self, host, service=None): |
... | ... | |
536 | 532 |
@validate(validators={ |
537 | 533 |
"fontsize": validators.Regex( |
538 | 534 |
r'[0-9]+(pt|px|em|%)', |
539 |
regexOps=('I',)
|
|
535 |
regexOps = ('I',)
|
|
540 | 536 |
)}, error_handler = process_form_errors) |
541 | 537 |
@expose('json') |
542 | 538 |
def set_fontsize(self, fontsize): |
vigiboard/controllers/vigiboard_controller.py | ||
---|---|---|
4 | 4 |
Controller for authentification |
5 | 5 |
""" |
6 | 6 |
|
7 |
from tg import expose, flash, require, url, request, redirect
|
|
7 |
from tg import expose, flash, url, request, redirect |
|
8 | 8 |
|
9 |
from pylons.i18n import ugettext as _, lazy_ugettext as l_ |
|
10 |
from repoze.what import predicates |
|
9 |
from pylons.i18n import ugettext as _ |
|
11 | 10 |
|
12 |
from vigilo.models.session import DBSession |
|
13 | 11 |
from vigilo.models import ApplicationLog |
14 | 12 |
|
15 | 13 |
from vigiboard.lib.base import BaseController |
vigiboard/controllers/vigiboard_plugin/shn.py | ||
---|---|---|
6 | 6 |
|
7 | 7 |
from pylons.i18n import gettext as _ |
8 | 8 |
from tg import url |
9 |
from sqlalchemy.sql import functions |
|
10 | 9 |
|
11 | 10 |
from vigiboard.controllers.vigiboard_plugin import VigiboardRequestPlugin |
12 | 11 |
from vigilo.models.session import DBSession |
13 | 12 |
from vigilo.models import HighLevelService, \ |
14 |
CorrEvent, Event, SupItem, \ |
|
15 |
ImpactedHLS, ImpactedPath |
|
16 |
from vigilo.models.secondary_tables import EVENTSAGGREGATE_TABLE |
|
13 |
CorrEvent, Event, SupItem |
|
17 | 14 |
|
18 | 15 |
class PluginSHN(VigiboardRequestPlugin): |
19 | 16 |
|
... | ... | |
63 | 60 |
|
64 | 61 |
def controller(self, idcorrevent, *argv, **krgv): |
65 | 62 |
"""Ajout de fonctionnalités au contrôleur""" |
66 |
supitem = DBSession.query(SupItem).join( |
|
67 |
(Event, Event.idsupitem == SupItem.idsupitem), |
|
68 |
(CorrEvent, CorrEvent.idcause == Event.idevent), |
|
69 |
).filter(CorrEvent.idcorrevent == idcorrevent).first() |
|
63 |
supitem = self.get_correvent_supitem(idcorrevent) |
|
70 | 64 |
|
71 | 65 |
if not supitem: |
72 | 66 |
# XXX On devrait afficher une erreur (avec tg.flash()). |
... | ... | |
80 | 74 |
|
81 | 75 |
return dict(services=[service.servicename for service in services]) |
82 | 76 |
|
77 |
def get_correvent_supitem(self, idcorrevent): |
|
78 |
""" |
|
79 |
Retourne le supitem ayant causé l'évènement |
|
80 |
corrélé dont l'identifiant est passé en paramètre. |
|
81 |
""" |
|
82 |
# On récupère l'item recherché dans la BDD |
|
83 |
supitem = DBSession.query(SupItem |
|
84 |
).join( |
|
85 |
(Event, Event.idsupitem == SupItem.idsupitem), |
|
86 |
(CorrEvent, CorrEvent.idcause == Event.idevent), |
|
87 |
).filter(CorrEvent.idcorrevent == idcorrevent).first() |
|
88 |
|
|
89 |
# # On détermine l'identité de l'utilisateur |
|
90 |
# username = request.environ['repoze.who.identity']['repoze.who.userid'] |
|
91 |
# user = User.by_user_name(username) |
|
92 |
# |
|
93 |
# # On liste les permissions dont dispose l'utilisateur |
|
94 |
# user_permissions = [] |
|
95 |
# for group in user.usergroups: |
|
96 |
# for permission in group.permissions: |
|
97 |
# user_permissions.append(permission) |
|
98 |
# |
|
99 |
# # On liste les permissions possibles pour l'item |
|
100 |
# supitem_permissions = [] |
|
101 |
# for group in supitem.groups: |
|
102 |
# for permission in group.permissions: |
|
103 |
# supitem_permissions.append(permission) |
|
104 |
# |
|
105 |
# # On vérifie que l'utilisateur dispose bien des |
|
106 |
# # permissions sur l'item en question avant de le retourner. |
|
107 |
# for user_permission in user_permissions : |
|
108 |
# for supitem_permission in supitem_permissions : |
|
109 |
# if user_permission.idpermission == \ |
|
110 |
# supitem_permission.idpermission: |
|
111 |
# return supitem |
|
112 |
# |
|
113 |
# # Dans le cas contraire on retourne None |
|
114 |
# return None |
|
115 |
|
|
116 |
return supitem |
|
117 |
|
vigiboard/controllers/vigiboardrequest.py | ||
---|---|---|
8 | 8 |
from tg import url, config, tmpl_context |
9 | 9 |
from tg.i18n import get_lang |
10 | 10 |
from pylons.i18n import ugettext as _ |
11 |
from sqlalchemy import not_, and_, asc, desc, sql
|
|
11 |
from sqlalchemy import not_, and_, asc, desc |
|
12 | 12 |
from sqlalchemy.sql.expression import or_, null as expr_null, union |
13 |
from sqlalchemy.orm import aliased |
|
14 | 13 |
|
15 | 14 |
from vigilo.models.session import DBSession |
16 |
from vigilo.models import SupItem, Event, CorrEvent, EventHistory, \ |
|
17 |
Host, HostGroup, LowLevelService, ServiceGroup, \ |
|
18 |
StateName |
|
15 |
from vigilo.models import Event, CorrEvent, EventHistory, \ |
|
16 |
Host, LowLevelService, StateName |
|
19 | 17 |
from vigilo.models.secondary_tables import HOST_GROUP_TABLE, \ |
20 | 18 |
SERVICE_GROUP_TABLE |
21 | 19 |
from vigiboard.widgets.edit_event import EditEventForm |
... | ... | |
67 | 65 |
).join( |
68 | 66 |
(Host, Host.idhost == LowLevelService.idhost), |
69 | 67 |
).outerjoin( |
70 |
(HOST_GROUP_TABLE, HOST_GROUP_TABLE.c.idhost == LowLevelService.idhost), |
|
71 |
(SERVICE_GROUP_TABLE, SERVICE_GROUP_TABLE.c.idservice == LowLevelService.idservice), |
|
68 |
(HOST_GROUP_TABLE, |
|
69 |
HOST_GROUP_TABLE.c.idhost == LowLevelService.idhost), |
|
70 |
(SERVICE_GROUP_TABLE, |
|
71 |
SERVICE_GROUP_TABLE.c.idservice == LowLevelService.idservice), |
|
72 | 72 |
).filter( |
73 | 73 |
or_( |
74 | 74 |
HOST_GROUP_TABLE.c.idgroup.in_(self.user_groups), |
... | ... | |
83 | 83 |
expr_null().label("idservicegroup"), |
84 | 84 |
HOST_GROUP_TABLE.c.idgroup.label('idhostgroup'), |
85 | 85 |
).join((HOST_GROUP_TABLE, HOST_GROUP_TABLE.c.idhost == Host.idhost) |
86 |
).filter(HOST_GROUP_TABLE.c.idgroup.label('idhostgroup').in_(self.user_groups), |
|
86 |
).filter(HOST_GROUP_TABLE.c.idgroup.label('idhostgroup' |
|
87 |
).in_(self.user_groups), |
|
87 | 88 |
) |
88 | 89 |
|
89 | 90 |
# Object Selectable renvoyant des informations sur un supitem |
vigiboard/tests/functional/test_event_table.py | ||
---|---|---|
6 | 6 |
|
7 | 7 |
from nose.tools import assert_true, assert_equal |
8 | 8 |
from datetime import datetime |
9 |
import tg |
|
10 | 9 |
import transaction |
11 | 10 |
|
12 | 11 |
from vigilo.models.session import DBSession |
13 |
from vigilo.models import Event, EventHistory, CorrEvent, \
|
|
14 |
Permission, User, StateName, \
|
|
15 |
Host, HostGroup, LowLevelService, ServiceGroup
|
|
12 |
from vigilo.models import Event, CorrEvent, \ |
|
13 |
Permission, StateName, \ |
|
14 |
Host, HostGroup, LowLevelService |
|
16 | 15 |
from vigiboard.tests import TestController |
17 |
from vigiboard.controllers.vigiboardrequest import VigiboardRequest |
|
18 |
from vigiboard.controllers.vigiboard_plugin.tests import MonPlugin |
|
19 | 16 |
|
20 | 17 |
def populate_DB(): |
21 | 18 |
""" Peuple la base de données. """ |
vigiboard/tests/functional/test_history_form.py | ||
---|---|---|
153 | 153 |
DBSession.flush() |
154 | 154 |
transaction.commit() |
155 | 155 |
|
156 |
response = self.app.post('/history_dialog',
|
|
156 |
self.app.post('/history_dialog', |
|
157 | 157 |
{'idcorrevent': idcorrevent}, |
158 | 158 |
extra_environ={'REMOTE_USER': 'manager'}, |
159 | 159 |
status=302) |
... | ... | |
164 | 164 |
DBSession.flush() |
165 | 165 |
transaction.commit() |
166 | 166 |
|
167 |
response = self.app.post('/history_dialog',
|
|
167 |
self.app.post('/history_dialog', |
|
168 | 168 |
{'idcorrevent': idcorrevent}, |
169 | 169 |
extra_environ={'REMOTE_USER': 'manager'}, |
170 | 170 |
status=302) |
vigiboard/tests/functional/test_history_tables.py | ||
---|---|---|
6 | 6 |
|
7 | 7 |
from nose.tools import assert_true, assert_equal |
8 | 8 |
from datetime import datetime |
9 |
import tg |
|
10 | 9 |
import transaction |
11 | 10 |
|
12 | 11 |
from vigilo.models.session import DBSession |
13 | 12 |
from vigilo.models import Event, EventHistory, CorrEvent, \ |
14 |
Permission, User, StateName, \
|
|
13 |
Permission, StateName, \ |
|
15 | 14 |
Host, HostGroup, LowLevelService, ServiceGroup |
16 | 15 |
from vigiboard.tests import TestController |
17 |
from vigiboard.controllers.vigiboardrequest import VigiboardRequest |
|
18 |
from vigiboard.controllers.vigiboard_plugin.tests import MonPlugin |
|
19 | 16 |
|
20 | 17 |
def populate_DB(): |
21 | 18 |
""" Peuple la base de données. """ |
... | ... | |
221 | 218 |
|
222 | 219 |
# On ajoute deux évènements corrélés causés par l'hôte : |
223 | 220 |
# le premier encore ouvert, le second clos par un utilisateur. |
224 |
aggregate_id1 = add_correvent_caused_by(managerhost) |
|
225 |
aggregate_id2 = add_correvent_caused_by(managerhost, u"AAClosed", |
|
226 |
u"OK") |
|
221 |
add_correvent_caused_by(managerhost) |
|
222 |
add_correvent_caused_by(managerhost, u"AAClosed", u"OK") |
|
227 | 223 |
|
228 | 224 |
transaction.commit() |
229 | 225 |
DBSession.add(managerhost) |
... | ... | |
277 | 273 |
|
278 | 274 |
# On ajoute deux évènements corrélés causés par le service : |
279 | 275 |
# le premier encore ouvert, le second clos par un utilisateur. |
280 |
aggregate_id1 = add_correvent_caused_by(managerservice) |
|
281 |
aggregate_id2 = add_correvent_caused_by(managerservice, u"AAClosed", |
|
282 |
u"OK") |
|
276 |
add_correvent_caused_by(managerservice) |
|
277 |
add_correvent_caused_by(managerservice, u"AAClosed", u"OK") |
|
283 | 278 |
|
284 | 279 |
transaction.commit() |
285 | 280 |
DBSession.add(managerhost) |
vigiboard/tests/functional/test_host_vigiboardrequest.py | ||
---|---|---|
12 | 12 |
from vigilo.models.session import DBSession |
13 | 13 |
from vigilo.models import Event, EventHistory, CorrEvent, \ |
14 | 14 |
Permission, User, StateName, \ |
15 |
Host, HostGroup, LowLevelService, ServiceGroup
|
|
15 |
Host, HostGroup |
|
16 | 16 |
from vigiboard.tests import TestController |
17 | 17 |
from vigiboard.controllers.vigiboardrequest import VigiboardRequest |
18 | 18 |
from vigiboard.controllers.vigiboard_plugin.tests import MonPlugin |
19 | 19 |
|
20 | 20 |
|
21 | 21 |
class TestHostVigiboardRequest(TestController): |
22 |
""" |
|
23 |
Test de la classe Vigiboard Request pour des requêtes concernant les hôtes |
|
24 |
""" |
|
22 |
""" Préparation de la base de données en vue des tests. """ |
|
25 | 23 |
|
26 | 24 |
def setUp(self): |
27 | 25 |
super(TestHostVigiboardRequest, self).setUp() |
... | ... | |
37 | 35 |
# On ajoute les groupes et leurs dépendances |
38 | 36 |
self.hosteditors = HostGroup(name=u'editorsgroup') |
39 | 37 |
DBSession.add(self.hosteditors) |
40 |
self.hostmanagers = HostGroup(name=u'managersgroup', parent=self.hosteditors) |
|
38 |
self.hostmanagers = HostGroup(name=u'managersgroup', |
|
39 |
parent=self.hosteditors) |
|
41 | 40 |
DBSession.add(self.hostmanagers) |
42 | 41 |
DBSession.flush() |
43 | 42 |
|
... | ... | |
109 | 108 |
transaction.commit() |
110 | 109 |
|
111 | 110 |
def tearDown(self): |
112 |
# This operation is only necessary for DBMS which are |
|
113 |
# really strict about table locks, such as PostgreSQL. |
|
114 |
# For our tests, we use an (in-memory) SQLite database, |
|
115 |
# so we're unaffected. This is done only for completeness. |
|
111 |
""" Nettoyage de la base de données après les tests. """ |
|
116 | 112 |
TestController.tearDown(self) |
117 | 113 |
|
118 | 114 |
|
vigiboard/tests/functional/test_root.py | ||
---|---|---|
16 | 16 |
|
17 | 17 |
|
18 | 18 |
class TestRootController(TestController): |
19 |
""" Classe de test du root controller """ |
|
19 | 20 |
def test_index(self): |
20 | 21 |
"""Test that access to the root webpage is restricted.""" |
21 | 22 |
|
vigiboard/tests/functional/test_search_form_host.py | ||
---|---|---|
4 | 4 |
""" |
5 | 5 |
from nose.tools import assert_true, assert_equal |
6 | 6 |
from datetime import datetime |
7 |
from lxml import etree |
|
8 | 7 |
import transaction |
9 | 8 |
|
10 | 9 |
from vigiboard.tests import TestController |
vigiboard/tests/functional/test_search_form_hostgroup.py | ||
---|---|---|
9 | 9 |
from vigiboard.tests import TestController |
10 | 10 |
from vigilo.models.session import DBSession |
11 | 11 |
from vigilo.models import HostGroup, Host, Permission, \ |
12 |
LowLevelService, Event, CorrEvent, StateName
|
|
12 |
Event, CorrEvent, StateName |
|
13 | 13 |
|
14 | 14 |
def insert_deps(): |
15 | 15 |
"""Insère les dépendances nécessaires aux tests.""" |
vigiboard/tests/functional/test_search_form_servicegroup.py | ||
---|---|---|
89 | 89 |
DBSession.flush() |
90 | 90 |
transaction.commit() |
91 | 91 |
|
92 |
# On envoie une requête avec recherche sur le groupe de services créé,
|
|
93 |
# on s'attend à recevoir 1 résultat. |
|
92 |
# On envoie une requête avec recherche sur le groupe |
|
93 |
# de services créé, on s'attend à recevoir 1 résultat.
|
|
94 | 94 |
response = self.app.get('/?servicegroup=foo', |
95 | 95 |
extra_environ={'REMOTE_USER': 'manager'}) |
96 | 96 |
|
... | ... | |
132 | 132 |
insert_deps() |
133 | 133 |
transaction.commit() |
134 | 134 |
|
135 |
# On envoie une requête avec recherche sur le groupe de services créé,
|
|
136 |
# mais avec un utilisateur ne disposant pas des permissions adéquates.
|
|
137 |
# On s'attend à n'obtenir aucun résultat. |
|
135 |
# On envoie une requête avec recherche sur le groupe de services |
|
136 |
# services créé, mais avec un utilisateur ne disposant pas des
|
|
137 |
# permissions adéquates. On s'attend à n'obtenir aucun résultat.
|
|
138 | 138 |
response = self.app.get('/?servicegroup=foo', |
139 | 139 |
extra_environ={'REMOTE_USER': 'manager'}) |
140 | 140 |
|
vigiboard/tests/functional/test_userutils.py | ||
---|---|---|
3 | 3 |
""" |
4 | 4 |
Teste l'héritage des permissions sur les groupes d'hôtes/services. |
5 | 5 |
""" |
6 |
import tg |
|
7 | 6 |
import transaction |
8 | 7 |
from nose.tools import assert_true |
9 | 8 |
|
vigiboard/tests/functional/vigiboard_plugin/test_plugin_hls.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 |
""" |
|
3 |
Integration tests for the autocompletion controller. |
|
4 |
""" |
|
2 |
""" Test du plugin listant les services de haut niveau impactés. """ |
|
5 | 3 |
|
6 | 4 |
from datetime import datetime |
7 | 5 |
import transaction |
8 | 6 |
from vigiboard.tests import TestController |
9 |
from nose.tools import assert_true, assert_equal
|
|
7 |
from nose.tools import assert_equal |
|
10 | 8 |
from vigilo.models import Permission, StateName, \ |
11 |
HostGroup, Host, \ |
|
12 |
LowLevelService, HighLevelService, ServiceGroup, \ |
|
13 |
Event, CorrEvent, \ |
|
14 |
ImpactedPath, ImpactedHLS |
|
9 |
HostGroup, Host, HighLevelService, \ |
|
10 |
Event, CorrEvent, ImpactedPath, ImpactedHLS |
|
15 | 11 |
from vigilo.models.session import DBSession |
16 | 12 |
|
17 | 13 |
|
... | ... | |
72 | 68 |
|
73 | 69 |
return aggregate |
74 | 70 |
|
75 |
def add_paths(path_number, path_length, idsupitem, |
|
76 |
different_path_lengths = None): |
|
71 |
def add_paths(path_number, path_length, idsupitem): |
|
77 | 72 |
""" |
78 | 73 |
Ajoute path_number chemins de services de haut niveau impactés |
79 | 74 |
dans la base de donnée. Leur longeur sera égale à path_length. |
vigiboard/websetup.py | ||
---|---|---|
3 | 3 |
|
4 | 4 |
import logging |
5 | 5 |
|
6 |
import transaction |
|
7 |
from tg import config |
|
8 |
|
|
9 | 6 |
from vigiboard.config.environment import load_environment |
10 | 7 |
from vigilo.turbogears import populate_db |
11 | 8 |
|
vigiboard/widgets/edit_event.py | ||
---|---|---|
5 | 5 |
from pylons.i18n import lazy_ugettext as l_ |
6 | 6 |
from tw.forms import TableForm, SingleSelectField, TextField, \ |
7 | 7 |
HiddenField, SubmitButton |
8 |
from tw.api import WidgetsList |
|
9 | 8 |
|
10 | 9 |
__all__ = ('EditEventForm', 'edit_event_status_options') |
11 | 10 |
|
... | ... | |
33 | 32 |
] |
34 | 33 |
|
35 | 34 |
def __init__(self, id, last_modification, *args, **kwargs): |
36 |
super(TableForm, self).__init__(id, *args, **kwargs)
|
|
35 |
TableForm.__init__(self, id, *args, **kwargs)
|
|
37 | 36 |
|
38 | 37 |
self.children.append(HiddenField('last_modification', |
39 | 38 |
attrs={'value': last_modification})) |
vigiboard/widgets/search_form.py | ||
---|---|---|
4 | 4 |
|
5 | 5 |
from pylons.i18n import lazy_ugettext as l_ |
6 | 6 |
from tw.forms import TableForm, TextField, CalendarDateTimePicker, SubmitButton |
7 |
from tw.api import WidgetsList |
|
8 |
from tg import url |
|
9 | 7 |
|
10 | 8 |
__all__ = ('SearchForm', ) |
11 | 9 |
|
... | ... | |
22 | 20 |
submit_text = None |
23 | 21 |
action = './' |
24 | 22 |
fields = [ |
25 |
TextField('hostgroup', label_text=l_('Host group')),
|
|
26 |
TextField('servicegroup', label_text=l_('Service group')),
|
|
27 |
TextField('host', label_text=l_('Host')),
|
|
28 |
TextField('service', label_text=l_('Service')),
|
|
29 |
TextField('output', label_text=l_('Output')),
|
|
30 |
TextField('trouble_ticket', label_text=l_('Trouble Ticket'))
|
|
23 |
TextField('hostgroup', label_text = l_('Host group')),
|
|
24 |
TextField('servicegroup', label_text = l_('Service group')),
|
|
25 |
TextField('host', label_text = l_('Host')),
|
|
26 |
TextField('service', label_text = l_('Service')),
|
|
27 |
TextField('output', label_text = l_('Output')),
|
|
28 |
TextField('trouble_ticket', label_text = l_('Trouble Ticket'))
|
|
31 | 29 |
] |
32 | 30 |
|
33 | 31 |
def __init__(self, id, lang, date_format='%Y-%m-%d %I:%M:%S %P', |
34 | 32 |
*args, **kwargs): |
35 |
super(SearchForm, self).__init__(id, *args, **kwargs)
|
|
33 |
TableForm.__init__(self, id, *args, **kwargs)
|
|
36 | 34 |
|
37 | 35 |
self.children.append(CalendarDateTimePicker(id + '_from_date', |
38 | 36 |
name = 'from_date', |
Also available in: Unified diff