1425
by Matt Giuca
doc: Added dev/faq, with some helpful tips on creating certain objects. |
1 |
.. IVLE - Informatics Virtual Learning Environment
|
2 |
Copyright (C) 2007-2009 The University of Melbourne
|
|
3 |
||
4 |
.. This program is free software; you can redistribute it and/or modify
|
|
5 |
it under the terms of the GNU General Public License as published by
|
|
6 |
the Free Software Foundation; either version 2 of the License, or
|
|
7 |
(at your option) any later version.
|
|
8 |
||
9 |
.. This program is distributed in the hope that it will be useful,
|
|
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
GNU General Public License for more details.
|
|
13 |
||
14 |
.. You should have received a copy of the GNU General Public License
|
|
15 |
along with this program; if not, write to the Free Software
|
|
16 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17 |
||
18 |
.. _ref-dev-faq: |
|
19 |
||
20 |
**************************
|
|
21 |
Frequently Asked Questions
|
|
22 |
**************************
|
|
23 |
||
24 |
This is a list of Frequently Asked Questions for IVLE developers. It answers |
|
25 |
questions about common issues encountered when bludgeoning the system into |
|
26 |
behaving. |
|
27 |
||
28 |
.. _ref-dev-faq-how: |
|
29 |
||
30 |
How can I...
|
|
31 |
============
|
|
32 |
||
33 |
.. _ref-dev-faq-config: |
|
34 |
||
35 |
... get data out of the IVLE configuration?
|
|
36 |
-------------------------------------------
|
|
37 |
||
38 |
::
|
|
39 |
||
40 |
from ivle.config import Config
|
|
41 |
config = Config()
|
|
42 |
||
43 |
This makes `config`, a dictionary-tree containing the whole config hierarchy.
|
|
44 |
||
45 |
For example, to get the Subversion repository path, use |
|
46 |
``config['paths']['svn']['repo_path']``.
|
|
47 |
||
48 |
.. note:: |
|
49 |
For code running inside the jail, you will see different configuration |
|
50 |
variables than code running outside. It will be missing a lot of data, and |
|
51 |
will contain some user-specific data. |
|
52 |
||
1496
by David Coles
Docs: Outline on permissions for views and database objects |
53 |
... restrict permission to different views?
|
54 |
-------------------------------------------
|
|
55 |
||
56 |
In all views derived from ``BaseView`` the ``authorize`` function is called to |
|
57 |
check if a user has access to a particular file. Often this is simply a check |
|
58 |
to ensure that the user is logged in (the value of 'user' is not None), but |
|
59 |
may be more complex such as checking if a user has a password hash set (to |
|
60 |
prevent clobbering of external auth) or checking if a user has permission to |
|
61 |
edit an ``Offering`` object.
|
|
62 |
||
1429
by Matt Giuca
dev/faq: Database access tips. |
63 |
Database
|
1431
by Matt Giuca
doc/dev/faq: Slightly better hierarchy. |
64 |
========
|
65 |
||
66 |
How can I...
|
|
67 |
------------
|
|
1429
by Matt Giuca
dev/faq: Database access tips. |
68 |
|
69 |
IVLE exclusively uses the `Storm`_ API for database access. Do not write any
|
|
70 |
SQL code yourself, or make use of low-level database libraries. The only |
|
71 |
exception is in preparing the database schema, which is stored as an SQL file. |
|
72 |
||
73 |
.. _Storm: https://storm.canonical.com/ |
|
74 |
||
75 |
... update the database schema?
|
|
1431
by Matt Giuca
doc/dev/faq: Slightly better hierarchy. |
76 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1429
by Matt Giuca
dev/faq: Database access tips. |
77 |
|
78 |
Modify :file:`userdb/users.sql`. Any changes also need to be made in to a |
|
79 |
migrations file, in :file:`userdb/migrations/`. |
|
80 |
||
81 |
TODO: More detail on migrations. |
|
82 |
||
83 |
.. _ref-dev-faq-read-data: |
|
84 |
||
85 |
... read data from the database?
|
|
1431
by Matt Giuca
doc/dev/faq: Slightly better hierarchy. |
86 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1429
by Matt Giuca
dev/faq: Database access tips. |
87 |
|
88 |
::
|
|
89 |
||
90 |
import ivle.database
|
|
91 |
# Typically, you import all database classes you want here
|
|
92 |
from ivle.database import User
|
|
93 |
||
94 |
You need a `store` object to perform any interactions with the database. If
|
|
95 |
you are inside the web app, get a hold of the `req` (request) object, and use
|
|
96 |
``req.store``. In other code, create a new store as follows (where `config` is |
|
97 |
a :ref:`config <ref-dev-faq-config>` object):: |
|
98 |
||
99 |
store = ivle.database.get_store(config)
|
|
100 |
||
101 |
You can read objects out of the database through the store. For example, to |
|
102 |
get a User object::
|
|
103 |
||
104 |
user = store.find(User, User.login==username).one()
|
|
105 |
||
106 |
(Note that ``store.find(User)`` just returns a sequence of all users.)
|
|
107 |
||
108 |
You can then treat `user` as a normal object, and read from its attributes.
|
|
109 |
All of the classes are defined in ``ivle/database.py``.
|
|
110 |
||
111 |
.. note:: |
|
112 |
The code must be executed outside of the jail. Jail code runs under user |
|
113 |
privileges and cannot access the database. |
|
114 |
||
115 |
.. note:: |
|
116 |
For help with the database API, see the `Storm`_ documentation.
|
|
117 |
||
118 |
... write data to the database?
|
|
1431
by Matt Giuca
doc/dev/faq: Slightly better hierarchy. |
119 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1429
by Matt Giuca
dev/faq: Database access tips. |
120 |
|
121 |
Get an object out of the database, as :ref:`above <ref-dev-faq-read-data>`, |
|
122 |
and simply write to the object's attributes. This updates the *in-memory* copy
|
|
123 |
of the data only. |
|
124 |
||
125 |
To write the changes back to the database, simply use::
|
|
126 |
||
127 |
store.commit()
|
|
128 |
||
129 |
using the same store object as used to retrieve the object in the first place. |
|
130 |
||
131 |
... insert a new object into the database?
|
|
1431
by Matt Giuca
doc/dev/faq: Slightly better hierarchy. |
132 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1429
by Matt Giuca
dev/faq: Database access tips. |
133 |
|
134 |
Create the new object using its constructor, as with any Python object. e.g.::
|
|
135 |
||
136 |
import ivle.database
|
|
137 |
user = ivle.database.User()
|
|
138 |
||
139 |
You can then set the attributes of the object as desired. As with writing, |
|
140 |
this only creates an *in-memory* object.
|
|
141 |
||
142 |
To add the object to the database, get a :ref:`store <ref-dev-faq-read-data>`, |
|
143 |
and use::
|
|
144 |
||
145 |
store.add(user)
|
|
146 |
store.commit()
|
|
147 |
||
1496
by David Coles
Docs: Outline on permissions for views and database objects |
148 |
... modify user capabilities or privileges?
|
149 |
-------------------------------------------
|
|
150 |
||
151 |
User privileges are set by the ``get_permissions`` functions in
|
|
152 |
``ivle/database.py``. Permissions are highly granular and can be set on almost
|
|
153 |
every object in the database. |
|
154 |
||
155 |
Most permissions are set on the ``Offering`` level with ``ProjectSet``, |
|
156 |
``Project`` and ``Worksheet`` simply delegating the check to ``Offering``. |
|
157 |
Since ``Exercise`` may be shared between multiple ``Offerings``, the |
|
158 |
permissions are calculated from the users active enrollments. Other objects |
|
159 |
such as ``User`` may only be modified by the user or an admin. If a user is
|
|
160 |
not logged in (user is None) then they will typically receive no privileges at |
|
161 |
all. |
|
162 |
||
1431
by Matt Giuca
doc/dev/faq: Slightly better hierarchy. |
163 |
Where do I find...
|
164 |
------------------
|
|
165 |
||
166 |
.. This is for finding obscure things in the code.
|
|
167 |
||
168 |
... the class definitions for database objects?
|
|
169 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
170 |
||
171 |
All of the classes are defined in ``ivle/database.py``.
|
|
172 |
||
1432
by Matt Giuca
doc/dev/faq: New Q&A. |
173 |
What does "TypeError: Expected unicode, found <type 'str'>" mean?
|
174 |
-----------------------------------------------------------------
|
|
175 |
||
176 |
All string data going into and out of Storm (i.e., the IVLE database classes) |
|
177 |
must be a Unicode string (type :class:`unicode`), not a regular byte string |
|
178 |
(type :class:`str`). If you have a regular string, convert it to Unicode by |
|
179 |
wrapping it in the :func:`unicode` function. For example:: |
|
180 |
||
181 |
username = unicode(username)
|
|
182 |
||
1425
by Matt Giuca
doc: Added dev/faq, with some helpful tips on creating certain objects. |
183 |
Subversion
|
1431
by Matt Giuca
doc/dev/faq: Slightly better hierarchy. |
184 |
==========
|
185 |
||
186 |
How can I...
|
|
187 |
------------
|
|
1425
by Matt Giuca
doc: Added dev/faq, with some helpful tips on creating certain objects. |
188 |
|
189 |
... get the local file path to a user's Subversion repo?
|
|
190 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
191 |
||
192 |
Get a :ref:`config <ref-dev-faq-config>` object, and use :: |
|
193 |
||
194 |
repopath = os.path.join(config['paths']['svn']['repo_path'],
|
|
195 |
'users', username)
|
|
196 |
||
197 |
(This should probably be abstracted.) |
|
198 |
||
199 |
... get the http:// URL for a user's Subversion repo?
|
|
200 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
201 |
||
202 |
Get a :ref:`config <ref-dev-faq-config>` object, and use :: |
|
203 |
||
204 |
repourl = config['urls']['svn_addr'] + '/users/' + username
|
|
205 |
||
206 |
(This should probably be abstracted.) |
|
207 |
||
208 |
... get a Subversion client from Python?
|
|
209 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
210 |
||
211 |
::
|
|
212 |
||
213 |
import ivle.svn
|
|
214 |
svnclient = ivle.svn.create_auth_svn_client(username, password)
|
|
215 |
||
216 |
If you don't have any auth credentials and you just want to do SVN things |
|
217 |
which don't require auth (though I don't see why this situation would arise), |
|
218 |
you can get an auth-less SVN client, which will raise exceptions if you try to |
|
219 |
do authy things (e.g., commit, update or checkout)::
|
|
220 |
||
221 |
import pysvn
|
|
222 |
svnclient = pysvn.Client()
|
|
223 |
||
224 |
In either case, the client object will raise `pysvn.ClientError` objects, so
|
|
225 |
you should be handling those. |
|
226 |
||
227 |
You may wish to make error messages simpler using this line::
|
|
228 |
||
229 |
svnclient.exception_style = 0
|
|
230 |
||
231 |
A good example of Subversion client code is in |
|
232 |
``ivle/fileservice_lib/action.py``.
|
|
233 |
||
234 |
.. _ref-dev-faq-where: |