# HG changeset patch # User Julien Cristau # Date 1394549765 -3600 # Node ID abaae1496ba4aad0b95b5fd36fa007eb00a900b0 # Parent d5b0e1f4c5c575eecb450e06cd1c393e4b9a6ac5 [book] Update documentation for new repoapi Quite a few things change in 3.19: - repoapi instead of dbapi - ClientConnection / Connection / Session rework - web authentication process - test APIs Closes #3638793 diff -r d5b0e1f4c5c5 -r abaae1496ba4 devtools/testlib.py --- a/devtools/testlib.py Fri Mar 14 11:18:15 2014 +0100 +++ b/devtools/testlib.py Tue Mar 11 15:56:05 2014 +0100 @@ -39,8 +39,9 @@ from logilab.common.deprecation import deprecated, class_deprecated from logilab.common.shellutils import getlogin -from cubicweb import ValidationError, NoSelectableObject, AuthenticationError -from cubicweb import cwconfig, dbapi, devtools, web, server, repoapi +from cubicweb import (ValidationError, NoSelectableObject, AuthenticationError, + ProgrammingError) +from cubicweb import cwconfig, devtools, web, server, repoapi from cubicweb.utils import json from cubicweb.sobjects import notification from cubicweb.web import Redirect, application @@ -156,7 +157,7 @@ class TestCaseConnectionProxy(object): - """thin wrapper around `cubicweb.dbapi.Connection` context-manager + """thin wrapper around `cubicweb.repoapi.ClientConnection` context-manager used in CubicWebTC (cf. `cubicweb.devtools.testlib.CubicWebTC.login` method) It just proxies to the default connection context manager but @@ -260,7 +261,7 @@ * `vreg`, the vregistry * `schema`, self.vreg.schema * `config`, cubicweb configuration - * `cnx`, dbapi connection to the repository using an admin user + * `cnx`, repoapi connection to the repository using an admin user * `session`, server side session associated to `cnx` * `app`, the cubicweb publisher (for web testing) * `repo`, the repository object @@ -436,7 +437,7 @@ def rollback(self): try: self.cnx.rollback() - except dbapi.ProgrammingError: + except ProgrammingError: pass # connection closed finally: self.session.set_cnxset() # ensure cnxset still set after commit @@ -667,14 +668,13 @@ .. sourcecode:: python - rdef = self.schema['CWUser'].rdef('login') with self.temporary_permissions(CWUser={'read': ()}): ... - Usually the former will be prefered to override permissions on a + Usually the former will be preferred to override permissions on a relation definition, while the latter is well suited for entity types. - The allowed keys in the permission dictionary depends on the schema type + The allowed keys in the permission dictionary depend on the schema type (entity type / relation definition). Resulting permissions will be similar to `orig_permissions.update(partial_perms)`. """ diff -r d5b0e1f4c5c5 -r abaae1496ba4 doc/book/en/devrepo/repo/sessions.rst --- a/doc/book/en/devrepo/repo/sessions.rst Fri Mar 14 11:18:15 2014 +0100 +++ b/doc/book/en/devrepo/repo/sessions.rst Tue Mar 11 15:56:05 2014 +0100 @@ -3,50 +3,47 @@ Sessions ======== -Sessions are object carrying the `.execute` method to query the data -sources. +Sessions are objects linked to an authenticated user. The `Session.new_cnx` +method returns a new Connection linked to that session. + +Connections +=========== -Kinds of sessions ------------------ +Connections provide the `.execute` method to query the data sources. -There are two kinds of sessions. +Kinds of connections +-------------------- -* `normal sessions` are the most common: they are related to users and +There are two kinds of connections. + +* `normal connections` are the most common: they are related to users and carry security checks coming with user credentials -* `internal sessions` have all the powers; they are also used in only a +* `internal connections` have all the powers; they are also used in only a few situations where you don't already have an adequate session at hand, like: user authentication, data synchronisation in multi-source contexts -.. note:: - Do not confuse the session type with their connection mode, for - instance : `in memory` or `pyro`. - -Normal sessions are typically named `_cw` in most appobjects or +Normal connections are typically named `_cw` in most appobjects or sometimes just `session`. -Internal sessions are available from the `Repository` object and are +Internal connections are available from the `Repository` object and are to be used like this: .. sourcecode:: python - session = self.repo.internal_session() - try: - do_stuff_with(session) - finally: - session.close() + with self.repo.internal_cnx() as cnx: + do_stuff_with(cnx) + cnx.commit() -.. warning:: - Do not forget to close such a session after use for a session leak - will quickly lead to an application crash. +Connections should always be used as context managers, to avoid leaks. Authentication and management of sessions ----------------------------------------- The authentication process is a ballet involving a few dancers: -* through its `connect` method the top-level application object (the +* through its `get_session` method the top-level application object (the `CubicWebPublisher`) will open a session whenever a web request comes in; it asks the `session manager` to open a session (giving the web request object as context) using `open_session` @@ -88,7 +85,7 @@ ------------------------------ Sometimes CubicWeb's out-of-the-box authentication schemes (cookie and -http) are not sufficient. Nowadays there is a plethore of such schemes +http) are not sufficient. Nowadays there is a plethora of such schemes and the framework cannot provide them all, but as the sequence above shows, it is extensible. @@ -154,7 +151,7 @@ .. sourcecode:: python - class XFooUserRetriever(authentication.LoginPasswordRetreiver): + class XFooUserRetriever(authentication.LoginPasswordRetriever): """ authenticate by the x-foo-user http header or just do normal login/password authentication """ @@ -200,7 +197,8 @@ return 1 return 0 -Full API Session -~~~~~~~~~~~~~~~~~~~~~~~~~~ +Full Session and Connection API +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: cubicweb.server.session.Session +.. autoclass:: cubicweb.server.session.Connection diff -r d5b0e1f4c5c5 -r abaae1496ba4 doc/book/en/devrepo/testing.rst --- a/doc/book/en/devrepo/testing.rst Fri Mar 14 11:18:15 2014 +0100 +++ b/doc/book/en/devrepo/testing.rst Tue Mar 11 15:56:05 2014 +0100 @@ -466,29 +466,26 @@ First, remember to think that some code run on a client side, some other on the repository side. More precisely: -* client side: web interface, raw db-api connection (cubicweb-ctl shell for +* client side: web interface, raw repoapi connection (cubicweb-ctl shell for instance); * repository side: RQL query execution, that may trigger hooks and operation. -The client interact with the repository through a db-api connection. +The client interacts with the repository through a repoapi connection. -A db-api connection is tied to a session in the repository. The connection and +A repoapi connection is tied to a session in the repository. The connection and request objects are unaccessible from repository code / the session object is -unaccessible from client code (theorically at least). +unaccessible from client code (theoretically at least). -The :mod:`cubicweb.dbapi` module provides a base request class. The web interface -provides an extended request class. - - -The `request` object provides access to all cubicweb resources, eg: +The web interface provides a request class. That `request` object provides +access to all cubicweb resources, eg: * the registry (which itself provides access to the schema and the configuration); -* an underlying db-api connection (when using req.execute, you actually call the - db-api); +* an underlying repoapi connection (when using req.execute, you actually call the + repoapi); * other specific resources depending on the client type (url generation according to base url, form parameters, etc.). @@ -510,37 +507,32 @@ The `_cw` attribute ``````````````````` The `_cw` attribute available on every application object provides access to all -cubicweb resources, eg: +cubicweb resources, i.e.: -For code running on the client side (eg web interface view), `_cw` is a request -instance. +- For code running on the client side (eg web interface view), `_cw` is a request + instance. -For code running on the repository side (hooks and operation), `_cw` is a session -instance. +- For code running on the repository side (hooks and operation), `_cw` is a + Connection or Session instance. -Beware some views may be called with a session (eg notifications) or with a -DB-API request. In the later case, see :meth:`use_web_compatible_requests` on -:class:`Connection` instances. +Beware some views may be called with a session (e.g. notifications) or with a +request. Request, session and transaction ```````````````````````````````` -In the web interface, an HTTP request is handle by a single request, which will -be thrown way once the response send. +In the web interface, an HTTP request is handled by a single request, which will +be thrown away once the response is sent. -The web publisher handle the transaction: +The web publisher handles the transaction: * commit / rollback is done automatically * you should not commit / rollback explicitly -When using a raw db-api, you're on your own regarding transaction. - -On the other hand, db-api connection and session live from a user login to its logout. - -Because session lives for a long time, and database connections is a limited -resource, we can't bound a session to its own database connection for all its +Because a session lives for a long time, and database connections are a limited +resource, we can't bind a session to its own database connection for all its lifetime. The repository handles a pool of connections (4 by default), and it's responsible to attribute them as needed. @@ -550,13 +542,13 @@ 2. the repository attributes a database connection to the session -3. the repository's querier execute the query +3. the repository's querier executes the query 4. this query may trigger hooks. Hooks and operation may execute some rql queries through `_cw.execute`. Those queries go directly to the querier, hence don't touch the database connection, they use the one attributed in 2. -5. the repository's get the result of the query in 1. If it was a RQL read query, +5. the repository gets the result of the query in 1. If it was a RQL read query, the database connection is released. If it was a write query, the connection is then tied to the session until the transaction is commited or rollbacked. @@ -567,11 +559,11 @@ * when using a request, or code executed in hooks, this database connection handling is totally transparent -* however, take care when writing test: you are usually faking / testing both the - server and the client side, so you have to decide when to use self.request() / - self.session. Ask yourself "where the code I want to test will be running, - client or repository side ?". The response is usually : use a request :) - However, if you really need using a session: +* however, take care when writing tests: you are usually faking / testing both the + server and the client side, so you have to decide when to use RepoAccess.client_cnx / + RepoAccess.repo_cnx. Ask yourself "where the code I want to test will be running, + client or repository side ?". The response is usually : use a client connection :) + However, if you really need using a server-side object: - commit / rollback will free the database connection (unless explicitly told not to do so). diff -r d5b0e1f4c5c5 -r abaae1496ba4 doc/book/en/devweb/request.rst --- a/doc/book/en/devweb/request.rst Fri Mar 14 11:18:15 2014 +0100 +++ b/doc/book/en/devweb/request.rst Tue Mar 11 15:56:05 2014 +0100 @@ -20,8 +20,6 @@ * `ie_browser`: tells if the browser belong to the Internet Explorer family - * `xhtml_browser`: tells if the browser is able to properly handle - XHTML (at the HTTP content_type level) * `User and identification`: @@ -30,7 +28,8 @@ * `Session data handling` - * `session.data` is the dictionnary of the session data; it can be manipulated like an ordinary Python dictionnary + * `session.data` is the dictionary of the session data; it can be + manipulated like an ordinary Python dictionary * `Edition` (utilities for edition control): @@ -104,8 +103,7 @@ * `get_header(header)`, returns the value associated to an arbitrary header of the HTTP request * `set_header(header, value)`, adds an arbitrary header in the response - * `cursor()` returns a RQL cursor on the session - * `execute(*args, **kwargs)`, shortcut to ``.cursor().execute()`` + * `execute(*args, **kwargs)`, executes an RQL query and return the result set * `property_value(key)`, properties management (`CWProperty`) * dictionary `data` to store data to share informations between components *while a request is executed* @@ -120,14 +118,14 @@ ``` The elements we gave in overview for above are built in three layers, -from ``cubicweb.req.RequestSessionBase``, ``cubicweb.dbapi.DBAPIRequest`` and -``cubicweb.web.CubicWebRequestBase``. +from ``cubicweb.req.RequestSessionBase``, ``cubicweb.repoapi.ClientConnection`` and +``cubicweb.web.ConnectionCubicWebRequestBase``. .. autoclass:: cubicweb.req.RequestSessionBase :members: -.. autoclass:: cubicweb.dbapi.DBAPIRequest +.. autoclass:: cubicweb.repoapi.ClientConnection :members: -.. autoclass:: cubicweb.web.request.CubicWebRequestBase +.. autoclass:: cubicweb.web.request.ConnectionCubicWebRequestBase :members: diff -r d5b0e1f4c5c5 -r abaae1496ba4 doc/book/en/images/request_session.png Binary file doc/book/en/images/request_session.png has changed diff -r d5b0e1f4c5c5 -r abaae1496ba4 doc/book/en/images/request_session.svg --- a/doc/book/en/images/request_session.svg Fri Mar 14 11:18:15 2014 +0100 +++ b/doc/book/en/images/request_session.svg Tue Mar 11 15:56:05 2014 +0100 @@ -13,7 +13,7 @@ height="12.382812" id="svg2" version="1.1" - inkscape:version="0.48.1 r9760" + inkscape:version="0.48.3.1 r9886" sodipodi:docname="request_session.svg"> @@ -48,10 +48,10 @@ fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" - inkscape:window-width="766" - inkscape:window-height="1151" - inkscape:window-x="1152" - inkscape:window-y="24" + inkscape:window-width="958" + inkscape:window-height="1160" + inkscape:window-x="0" + inkscape:window-y="38" inkscape:window-maximized="0" inkscape:snap-global="true" /> image/svg+xml - + @@ -113,7 +113,7 @@ sodipodi:role="line" id="tspan3763" x="262.63968" - y="470.51431">DB API + y="470.51431">REPOAPI