| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -251,3 +251,12 @@ | |||
| 251 | 251 | ||
| 252 | 252 | # How to display URL addresses: 'footnote', 'no', or 'inline'. | |
| 253 | 253 | #texinfo_show_urls = 'footnote' | |
| 254 | + | ||
| 255 | + | ||
| 256 | + # http://stackoverflow.com/a/8415805 | ||
| 257 | + def skip_modules_docstring(app, what, name, obj, options, lines): | ||
| 258 | + if what == 'module': | ||
| 259 | + del lines[:] | ||
| 260 | + | ||
| 261 | + def setup(app): | ||
| 262 | + app.connect('autodoc-process-docstring', skip_modules_docstring) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,9 +13,6 @@ Timetable Utils | |||
| 13 | 13 | ||
| 14 | 14 | .. autofunction:: table | |
| 15 | 15 | ||
| 16 | - .. module:: datetime_utils | ||
| 17 | - :members: | ||
| 18 | - | ||
| 19 | 16 | Options | |
| 20 | 17 | ============ | |
| 21 | 18 | ||
@@ -24,18 +21,18 @@ Options | |||
| 24 | 21 | In an instance of :py:class:`webuntis.session.Session`, a dictionary-like | |
| 25 | 22 | object named ``options`` is created. It accepts the following keys: | |
| 26 | 23 | ||
| 27 | - - *credentials*: A dictionary containing *username* and *password*. Before | ||
| 24 | + - ``credentials``: A dictionary containing ``username`` and ``password``. Before | ||
| 28 | 25 | the session is used, :py:meth:`webuntis.session.JSONRPCSession.login` must | |
| 29 | - be called, in order to add a *jsessionid* key, which will be deleted when | ||
| 26 | + be called, in order to add a ``jsessionid`` key, which will be deleted when | ||
| 30 | 27 | calling :py:meth:`webuntis.session.JSONRPCSession.logout`. | |
| 31 | 28 | ||
| 32 | 29 | In theory, you can obtain the jsessionid yourself and add it to the | |
| 33 | - *credentials* dictionary. In this case, the other two keys are obviously | ||
| 30 | + ``credentials`` dictionary. In this case, the other two keys are obviously | ||
| 34 | 31 | not needed. | |
| 35 | 32 | ||
| 36 | - - *school*: A string containing a valid school name. | ||
| 33 | + - ``school``: A string containing a valid school name. | ||
| 37 | 34 | ||
| 38 | - - *server*: A string containing a host name, a URL, or a URL without path:: | ||
| 35 | + - ``server``: A string containing a host name, a URL, or a URL without path:: | ||
| 39 | 36 | ||
| 40 | 37 | >>> s.options['server'] = 'thalia.webuntis.com' | |
| 41 | 38 | >>> s.options['server'] | |
@@ -50,9 +47,9 @@ object named ``options`` is created. It accepts the following keys: | |||
| 50 | 47 | >>> s.options['server'] | |
| 51 | 48 | 'http://thalia.webuntis.com/' | |
| 52 | 49 | >>> s.options['server'] = '!"$%/WebUntis/jsonrpc.do' | |
| 53 | - ValueError | ||
| 50 | + Traceback blah blah something ValueError | ||
| 54 | 51 | ||
| 55 | - - *useragent*: A string containing a useragent. | ||
| 52 | + - ``useragent``: A string containing a useragent. | ||
| 56 | 53 | ||
| 57 | 54 | Please include useful information, such as an email address, for the server | |
| 58 | 55 | maintainer. Just like you would do with the HTTP useragents of bots. | |
@@ -65,4 +62,14 @@ default. You can set the length with:: | |||
| 65 | 62 | ||
| 66 | 63 | s = webuntis.Session(..., cachelen=40) | |
| 67 | 64 | ||
| 68 | - Setting it to `0` obviously disables the cache. | ||
| 65 | + Setting it to ``0`` obviously disables the cache. | ||
| 66 | + | ||
| 67 | + Errors and Exceptions | ||
| 68 | + ===================== | ||
| 69 | + | ||
| 70 | + `python-webuntis` tries to cover as many error codes recieved by the API as possible. | ||
| 71 | + | ||
| 72 | + .. automodule:: webuntis.errors | ||
| 73 | + :members: | ||
| 74 | + :show-inheritance: | ||
| 75 | + :member-order: bysource | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,90 +7,92 @@ Objects and Models | |||
| 7 | 7 | Base Classes | |
| 8 | 8 | ============ | |
| 9 | 9 | .. autoclass:: Result | |
| 10 | - :members: | ||
| 10 | + :members: | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | .. autoclass:: ListResult | |
| 14 | - :members: | ||
| 14 | + :members: | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | .. autoclass:: ListItem | |
| 18 | - :members: | ||
| 18 | + :members: | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | Departments | |
| 21 | 22 | =========== | |
| 22 | 23 | .. autoclass:: DepartmentList | |
| 23 | - :members: | ||
| 24 | + :members: | ||
| 24 | 25 | ||
| 25 | 26 | .. autoclass:: DepartmentObject | |
| 26 | - :members: | ||
| 27 | + :members: | ||
| 27 | 28 | ||
| 28 | 29 | Holidays | |
| 29 | 30 | ======== | |
| 30 | 31 | .. autoclass:: HolidayList | |
| 31 | - :members: | ||
| 32 | + :members: | ||
| 32 | 33 | ||
| 33 | 34 | .. autoclass:: HolidayObject | |
| 34 | - :members: | ||
| 35 | + :members: | ||
| 35 | 36 | ||
| 36 | 37 | Klassen | |
| 37 | 38 | ======= | |
| 38 | 39 | .. autoclass:: KlassenList | |
| 39 | 40 | ||
| 40 | 41 | .. autoclass:: KlassenObject | |
| 41 | - :members: | ||
| 42 | + :members: | ||
| 42 | 43 | ||
| 43 | 44 | Timetables and Periods | |
| 44 | 45 | ====================== | |
| 45 | 46 | .. autoclass:: PeriodList | |
| 46 | - :members: | ||
| 47 | + :members: | ||
| 47 | 48 | ||
| 48 | 49 | .. autoclass:: PeriodObject | |
| 49 | - :members: | ||
| 50 | + :members: | ||
| 50 | 51 | ||
| 51 | 52 | Rooms | |
| 52 | 53 | ===== | |
| 53 | 54 | .. autoclass:: RoomList | |
| 54 | - :members: | ||
| 55 | + :members: | ||
| 55 | 56 | ||
| 56 | 57 | .. autoclass:: RoomObject | |
| 57 | - :members: | ||
| 58 | + :members: | ||
| 58 | 59 | ||
| 59 | 60 | Schoolyears | |
| 60 | 61 | =========== | |
| 61 | 62 | .. autoclass:: SchoolyearList | |
| 62 | - :members: | ||
| 63 | + :members: | ||
| 63 | 64 | ||
| 64 | 65 | .. autoclass:: SchoolyearObject | |
| 65 | - :members: | ||
| 66 | + :members: | ||
| 66 | 67 | ||
| 67 | 68 | Subjects | |
| 68 | 69 | ======== | |
| 69 | 70 | .. autoclass:: SubjectList | |
| 70 | - :members: | ||
| 71 | + :members: | ||
| 71 | 72 | ||
| 72 | 73 | .. autoclass:: SubjectObject | |
| 73 | - :members: | ||
| 74 | + :members: | ||
| 74 | 75 | ||
| 75 | 76 | Teachers | |
| 76 | 77 | ======== | |
| 77 | 78 | .. autoclass:: TeacherList | |
| 79 | + :members: | ||
| 78 | 80 | ||
| 79 | 81 | .. autoclass:: TeacherObject | |
| 80 | - :members: | ||
| 82 | + :members: | ||
| 81 | 83 | ||
| 82 | 84 | Timegrid and Timeunits | |
| 83 | 85 | ====================== | |
| 84 | 86 | .. autoclass:: TimeunitList | |
| 85 | - :members: | ||
| 87 | + :members: | ||
| 86 | 88 | ||
| 87 | 89 | .. autoclass:: TimeunitObject | |
| 88 | - :members: | ||
| 90 | + :members: | ||
| 89 | 91 | ||
| 90 | 92 | Lesson Types and Period Codes | |
| 91 | 93 | ============================== | |
| 92 | 94 | .. autoclass:: StatusData | |
| 93 | - :members: | ||
| 95 | + :members: | ||
| 94 | 96 | ||
| 95 | 97 | .. autoclass:: ColorInfo | |
| 96 | - :members: | ||
| 98 | + :members: | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,13 +4,10 @@ Session | |||
| 4 | 4 | ||
| 5 | 5 | .. module:: webuntis.session | |
| 6 | 6 | ||
| 7 | - .. autoclass:: JSONRPCSession | ||
| 8 | - :members: | ||
| 9 | - | ||
| 10 | 7 | .. autoclass:: Session | |
| 8 | + :members: | ||
| 9 | + :inherited-members: | ||
| 11 | 10 | ||
| 12 | - You never should use :py:class:`JSONRPCSession` directly unless you know what | ||
| 13 | - you're doing. Rather use :py:class:`Session`, which actually provides more | ||
| 14 | - than a JSON-RPC session library. | ||
| 11 | + .. note:: | ||
| 15 | 12 | ||
| 16 | - For a list of API methods of :py:class:`Session` see :doc:`objects`. | ||
| 13 | + For a list of API methods of :py:class:`Session` see :doc:`objects`. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,12 +9,35 @@ | |||
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | 11 | class Error(Exception): | |
| 12 | - pass | ||
| 12 | + '''Superclass for all `python-webuntis`-specific errors, never gets raised | ||
| 13 | + directly. Positional arguments get joined with ``", "`` and get dumped into | ||
| 14 | + ``self.msg``''' | ||
| 15 | + | ||
| 16 | + def __init__(self, *args): | ||
| 17 | + Exception.__init__(self, *args) | ||
| 18 | + self.msg = ', '.join(args) | ||
| 13 | 19 | ||
| 14 | 20 | ||
| 15 | 21 | class RemoteError(Error, IOError): | |
| 22 | + '''There was some kind of error while interacting with the server.''' | ||
| 23 | + pass | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + class MethodNotFoundError(RemoteError): | ||
| 27 | + '''The JSON-RPC method was not found. This really should not occur.''' | ||
| 16 | 28 | pass | |
| 17 | 29 | ||
| 18 | 30 | ||
| 19 | 31 | class AuthError(RemoteError): | |
| 32 | + '''Usually missing credentials, but also other problems while logging in | ||
| 33 | + are covered with this.''' | ||
| 20 | 34 | pass | |
| 35 | + | ||
| 36 | + | ||
| 37 | + class BadCredentialsError(AuthError): | ||
| 38 | + '''Invalid username or password''' | ||
| 39 | + pass | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + class NotLoggedInError(AuthError): | ||
| 43 | + '''The session expired or we never logged in.''' | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -218,10 +218,11 @@ class KlassenList(ListResult): | |||
| 218 | 218 | id of it. | |
| 219 | 219 | ||
| 220 | 220 | :: | |
| 221 | - >>> s.klassen() | ||
| 222 | - >>> | ||
| 223 | - >>> year = s.schoolyears().filter(id=2) | ||
| 224 | - >>> s.klassen(schoolyear=year) | ||
| 221 | + | ||
| 222 | + s.klassen() | ||
| 223 | + | ||
| 224 | + year = s.schoolyears().filter(id=2) | ||
| 225 | + s.klassen(schoolyear=year) | ||
| 225 | 226 | ||
| 226 | 227 | ''' | |
| 227 | 228 | _itemclass = KlassenObject | |
@@ -327,6 +328,8 @@ class PeriodList(ListResult): | |||
| 327 | 328 | s.timetable(klasse=schoolclass) # which is the same as... | |
| 328 | 329 | s.periods(klasse=schoolclass) | |
| 329 | 330 | ||
| 331 | + :raises: :py:class:`builtins.ValueError` -- if something was wrong with the | ||
| 332 | + arguments supplied. | ||
| 330 | 333 | ''' | |
| 331 | 334 | _itemclass = PeriodObject | |
| 332 | 335 | _jsonrpc_method = 'getTimetable' | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,10 +26,19 @@ | |||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | 28 | class JSONRPCSession(object): | |
| 29 | - '''Contains the functions for not much more than a simple JSON-RPC Session. | ||
| 30 | - Can be used as a context-handler. | ||
| 31 | - ''' | ||
| 29 | + '''Lower-level version of :py:class:`Session`. Do not use this.''' | ||
| 30 | + | ||
| 32 | 31 | options = None | |
| 32 | + '''Contains a options dict upon initialization. See | ||
| 33 | + :py:class:`webuntis.utils.option_utils` for more information.''' | ||
| 34 | + | ||
| 35 | + _errorcodes = { | ||
| 36 | + -32601: errors.MethodNotFoundError, | ||
| 37 | + -8504: errors.BadCredentialsError, | ||
| 38 | + -8520: errors.NotLoggedInError | ||
| 39 | + } | ||
| 40 | + '''This lists the API-errorcodes python-webuntis is able to interpret, | ||
| 41 | + together with the exception that will be thrown.''' | ||
| 33 | 42 | ||
| 34 | 43 | def __init__(self, **kwargs): | |
| 35 | 44 | # The OptionStore is an extended dictionary, associating validators | |
@@ -72,17 +81,21 @@ def logout(self, suppress_errors=False): | |||
| 72 | 81 | ''' | |
| 73 | 82 | Log out of session | |
| 74 | 83 | ||
| 75 | - :param suppress_errors: boolean, whether to not raise an error if we | ||
| 84 | + :param suppress_errors: boolean, whether to suppress errors if we | ||
| 76 | 85 | already were logged out. | |
| 86 | + | ||
| 87 | + :raises: :py:class:`webuntis.errors.NotLoggedInError` | ||
| 77 | 88 | ''' | |
| 78 | 89 | # Send a JSON-RPC 'logout' method without parameters to log out | |
| 79 | 90 | try: | |
| 80 | - self.options['credentials']['jsessionid'] # aborts if we don't have creds | ||
| 91 | + # aborts if we don't have creds | ||
| 92 | + self.options['credentials']['jsessionid'] | ||
| 93 | + | ||
| 81 | 94 | self._make_request('logout') | |
| 82 | 95 | del self.options['credentials']['jsessionid'] | |
| 83 | 96 | except KeyError as e: | |
| 84 | 97 | if not suppress_errors: | |
| 85 | - raise e | ||
| 98 | + raise errors.NotLoggedInError('We already were logged out.') | ||
| 86 | 99 | ||
| 87 | 100 | def login(self): | |
| 88 | 101 | '''Initializes an authentication, provided we have the credentials for | |
@@ -92,6 +105,9 @@ def login(self): | |||
| 92 | 105 | chaining:: | |
| 93 | 106 | ||
| 94 | 107 | s = webuntis.Session(...).login() | |
| 108 | + | ||
| 109 | + :raises: :py:class:`webuntis.errors.BadCredentialsError` | ||
| 110 | + :raises: :py:class:`webuntis.errors.AuthError` | ||
| 95 | 111 | ''' | |
| 96 | 112 | ||
| 97 | 113 | if 'username' not in self.options['credentials'] \ | |
@@ -114,7 +130,10 @@ def login(self): | |||
| 114 | 130 | self.options['credentials']['jsessionid'] = res['sessionId'] | |
| 115 | 131 | logging.debug(self.options['credentials']['jsessionid']) | |
| 116 | 132 | else: | |
| 117 | - raise errors.AuthError('Something went wrong while authenticating', res) | ||
| 133 | + raise errors.AuthError( | ||
| 134 | + 'Something went wrong while authenticating', | ||
| 135 | + res | ||
| 136 | + ) | ||
| 118 | 137 | ||
| 119 | 138 | return self | |
| 120 | 139 | ||
@@ -126,15 +145,32 @@ def _request(self, method, params=None): | |||
| 126 | 145 | self._cache[key] = self._make_request(method, params) | |
| 127 | 146 | return self._cache[key] | |
| 128 | 147 | ||
| 148 | + def _handle_json_error(self, req_data, res_data): | ||
| 149 | + '''Given the request and response objects, this raises the appropriate | ||
| 150 | + exceptions.''' | ||
| 151 | + logging.error(res_data) | ||
| 152 | + try: | ||
| 153 | + error = res_data['error'] | ||
| 154 | + your_weapon = self._errorcodes[error['code']](error['message']) | ||
| 155 | + except KeyError: | ||
| 156 | + your_weapon = errors.RemoteError( | ||
| 157 | + 'Some JSON-RPC-ish error happened. Please report this to the \ | ||
| 158 | + developer so he can implement a proper handling.', | ||
| 159 | + str(res_data), | ||
| 160 | + str(req_data) | ||
| 161 | + ) | ||
| 162 | + | ||
| 163 | + raise your_weapon | ||
| 164 | + | ||
| 129 | 165 | def _make_request(self, method, params=None): | |
| 130 | 166 | ''' | |
| 131 | 167 | A method for sending a JSON-RPC request. | |
| 132 | 168 | ||
| 133 | 169 | :param method: The JSON-RPC method to be executed | |
| 134 | 170 | :type method: str | |
| 135 | 171 | ||
| 136 | - :param params: JSON-RPC parameters to the method \ | ||
| 137 | - (should be JSON serializable) | ||
| 172 | + :param params: JSON-RPC parameters to the method (should be JSON | ||
| 173 | + serializable) | ||
| 138 | 174 | :type params: dict | |
| 139 | 175 | ''' | |
| 140 | 176 | ||
@@ -194,17 +230,12 @@ def _make_request(self, method, params=None): | |||
| 194 | 230 | elif 'result' in res_data: | |
| 195 | 231 | return res_data['result'] | |
| 196 | 232 | else: | |
| 197 | - logging.error(res_data) | ||
| 198 | - raise errors.RemoteError( | ||
| 199 | - 'Some JSON-RPC-ish error happened', | ||
| 200 | - str(res_data), | ||
| 201 | - str(req_data) | ||
| 202 | - ) | ||
| 233 | + self._handle_json_error(req_data, res_data) | ||
| 203 | 234 | ||
| 204 | 235 | ||
| 205 | 236 | class Session(JSONRPCSession): | |
| 206 | - '''Provides an abstraction layer above the JSON-RPC Instance. | ||
| 207 | - ''' | ||
| 237 | + '''The origin of everything you want to do with the WebUntis API. Can be | ||
| 238 | + used as a context-handler.''' | ||
| 208 | 239 | ||
| 209 | 240 | def __getattr__(self, name): | |
| 210 | 241 | '''Returns a callable which creates an instance (or reuses an old one) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments