commit
78fb7b01c8
30
README.rst
30
README.rst
|
@ -21,24 +21,24 @@ plone.api
|
|||
* `Continuous Integration @ Travis CI <http://travis-ci.org/plone/plone.api>`_
|
||||
* `Code Coverage @ Coveralls.io <http://coveralls.io/r/plone/plone.api>`_
|
||||
|
||||
The intention of this package is to be transitional. It points out the parts of
|
||||
Plone which are particularly nasty -- we hope they will get fixed so that we
|
||||
can deprecate the ``plone.api`` methods that cover them up, but the
|
||||
documentation can still be useful.
|
||||
The intention of this package is to provide clear API methods for Plone
|
||||
functionality which may be confusing or difficult to access. As the underlying
|
||||
code improves some API methods may be deprecated and the documentation here
|
||||
will be updated to show how to use the improved code (even if it means not
|
||||
using ``plone.api``)
|
||||
|
||||
Some parts of the documentation already are this way: they don't use
|
||||
``plone.api`` methods directly, but simply provide guidance on achieving a task
|
||||
using Plone's internals. Example: usage of the catalog in `Find content`
|
||||
example.
|
||||
Some parts of the documentation do not use *plone.api* methods directly, but
|
||||
simply provide guidance on achieving a task using Plone's internal API. For
|
||||
example, using the portal catalog (see 'Find content objects').
|
||||
|
||||
The intention is to cover 20% of the tasks we do 80% of the time. Keeping
|
||||
everything in one place helps keep the API introspectable and discoverable,
|
||||
which are important aspects of being Pythonic.
|
||||
The intention is to cover 20% of the tasks any Plone developer does 80% of the
|
||||
time. By keeping everything in one place, the API stays introspectable and
|
||||
discoverable, important aspects of being Pythonic.
|
||||
|
||||
.. note::
|
||||
|
||||
This package is still under development, but should be fairly stable and is
|
||||
already being used in production. It's currently a release candidate,
|
||||
meaning that we don't intend to change method signatures, but it may still
|
||||
happen.
|
||||
This package is stable and used in production, but from time to time
|
||||
changes will be made to the API. Additional api methods may be introduced
|
||||
in minor versions (1.1 -> 1.2). Backward-incompatible changes to the API
|
||||
will be restricted to major versions (1.x -> 2.x).
|
||||
|
||||
|
|
111
docs/about.rst
111
docs/about.rst
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/about.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/about.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
=====
|
||||
|
@ -15,14 +15,14 @@ Inspiration
|
|||
We want `plone.api` to be developed with `PEP 20
|
||||
<http://www.python.org/dev/peps/pep-0020/>`_ idioms in mind, in particular:
|
||||
|
||||
| Explicit is better than implicit.
|
||||
| Readability counts.
|
||||
| There should be one -- and preferably only one -- obvious way to do it.
|
||||
| Now is better than never.
|
||||
| If the implementation is hard to explain, it's a bad idea.
|
||||
| If the implementation is easy to explain, it may be a good idea.
|
||||
| Explicit is better than implicit.
|
||||
| Readability counts.
|
||||
| There should be one-- and preferably only one --obvious way to do it.
|
||||
| Now is better than never.
|
||||
| If the implementation is hard to explain, it's a bad idea.
|
||||
| If the implementation is easy to explain, it may be a good idea.
|
||||
|
||||
All contributions to :mod:`plone.api` should keep these important rules in mind.
|
||||
All contributions to `plone.api` should keep these rules in mind.
|
||||
|
||||
Two libraries are especially inspiring:
|
||||
|
||||
|
@ -32,21 +32,18 @@ Two libraries are especially inspiring:
|
|||
designed, is consistent, explicit, and easy to learn.
|
||||
|
||||
`Requests <http://docs.python-requests.org>`_
|
||||
As of this writing, this is still a very new library, but just looking at
|
||||
`a comparison between the urllib2 way and the requests way
|
||||
<https://gist.github.com/973705>`_, as well as the rest of its documentation,
|
||||
one cannot but see a parallel between the way we *have been* and the way we
|
||||
*should be* writing code for Plone (or at least have that option).
|
||||
If you look at the documentation for this library, or make `a comparison
|
||||
between the urllib2 way and the requests way
|
||||
<https://gist.github.com/973705>`_, you cannot but see a parallel between
|
||||
the way we *have been* and the way we *should be* writing code for Plone. At
|
||||
the least, we should have the option to write such clean code.
|
||||
|
||||
The API provides grouped functional access to otherwise dispersed logic
|
||||
in Plone. Plone's original distribution of logic is a result of two things:
|
||||
the historic re-use of CMF- and Zope-methods and reasonable, but
|
||||
at first hard to understand splits like ``acl_users.*`` and
|
||||
``portal_memberdata``.
|
||||
|
||||
That's why we've created a set of useful methods that implement best-practice
|
||||
access to the original dispersed APIs. In this way we also document in code
|
||||
how to use Plone directly.
|
||||
The API provides grouped functional access to otherwise distributed logic in
|
||||
Plone. This distribution is a result of two historical factors: re-use of CMF-
|
||||
and Zope-methods and reasonable but hard to remember splits like `acl_users`
|
||||
and `portal_memberdata`. Methods defined in `plone.api` implement
|
||||
best-practice access to the original distributed APIs. These methods also
|
||||
provide clear documentation of how best to access Plone APIs directly.
|
||||
|
||||
.. note::
|
||||
If you doubt those last sentences: We had five different ways to get the
|
||||
|
@ -54,12 +51,11 @@ how to use Plone directly.
|
|||
an object. With this in mind, it's obvious that even the most simple
|
||||
tasks can't be documented in Plone in a sane way.
|
||||
|
||||
Also, we don't intend to cover all possible use-cases. Only the most common
|
||||
ones. If you need to do something that :mod:`plone.api` does not support,
|
||||
just use the underlying APIs directly. We will cover 20% of tasks that are
|
||||
being done 80% of the time, and not one more. We try to document sensible use
|
||||
cases even when we don't provide them, though.
|
||||
|
||||
We do not intend to cover all possible use-cases, only the most common. We
|
||||
will cover the 20% of possible tasks on which we spend 80% of our time. If you
|
||||
need to do something that `plone.api` does not support, use the underlying
|
||||
APIs directly. We try to document sensible use cases even when we don't
|
||||
provide APIs for them, though.
|
||||
|
||||
Design decisions
|
||||
================
|
||||
|
@ -67,10 +63,10 @@ Design decisions
|
|||
Import and usage style
|
||||
----------------------
|
||||
|
||||
API methods are grouped by their field of usage. For example:
|
||||
:ref:`chapter_portal`, :ref:`chapter_content`, :ref:`chapter_users`
|
||||
and :ref:`chapter_groups`. Hence the importing and usage of API
|
||||
methods look like this:
|
||||
API methods are grouped according to what they affect. For example:
|
||||
:ref:`chapter_portal`, :ref:`chapter_content`, :ref:`chapter_users`,
|
||||
:ref:`chapter_env` and :ref:`chapter_groups`. In general, importing and using
|
||||
an API looks something like this:
|
||||
|
||||
.. invisible-code-block: python
|
||||
|
||||
|
@ -92,31 +88,31 @@ methods look like this:
|
|||
self.assertEqual(catalog.__class__.__name__, 'CatalogTool')
|
||||
self.assertEqual(user.__class__.__name__, 'MemberData')
|
||||
|
||||
In other words, always import the top-level package (``from plone import api``)
|
||||
Always import the top-level package (``from plone import api``)
|
||||
and then use the group namespace to access the method you want
|
||||
(``portal = api.portal.get()``).
|
||||
|
||||
All example code should adhere to this style, so we encourage one and only
|
||||
one preferred way of consuming API methods.
|
||||
All example code should adhere to this style, to encourage one and only one
|
||||
preferred way of consuming API methods.
|
||||
|
||||
|
||||
Prefer keyword arguments
|
||||
------------------------
|
||||
|
||||
For the following reasons the example code in the API (and hence the
|
||||
recommendation to people on how to use it) shall always prefer using keyword
|
||||
instead of positional arguments:
|
||||
We prefer using keyword arguments to positional arguments. Example code in
|
||||
`plone.api` will use this style, and we recommend users to follow this
|
||||
convention. For the curious, here are the reasons:
|
||||
|
||||
#. There will never be a doubt when writing a method on whether an argument
|
||||
should be positional or not. Decision already made.
|
||||
#. There will never be a doubt when using the API on which argument comes
|
||||
first, or which ones are named/positional. All arguments are named.
|
||||
#. When using positional arguments, the method signature is dictated by the
|
||||
underlying implementation. Think required vs. optional arguments. Named
|
||||
arguments are always optional in Python. This allows us to change
|
||||
implementation details and leave the signature unchanged. In other words,
|
||||
the underlying API code can change substantially and the code using it will
|
||||
remain valid.
|
||||
underlying implementation (think required vs. optional arguments). Named
|
||||
arguments are always optional in Python. Using keywords allows
|
||||
implementation details to change while the signature is preserved. In other
|
||||
words, the underlying API code can change substantially but code using it
|
||||
will remain valid.
|
||||
#. The arguments can all be passed as a dictionary.
|
||||
|
||||
|
||||
|
@ -124,13 +120,11 @@ instead of positional arguments:
|
|||
|
||||
# GOOD
|
||||
from plone import api
|
||||
portal = api.portal.get()
|
||||
alice = api.user.get(username='alice@plone.org')
|
||||
|
||||
# BAD
|
||||
from plone.api import portal, user
|
||||
portal = portal.get()
|
||||
alie = user.get('alice@plone.org')
|
||||
from plone.api import user
|
||||
alice = user.get('alice@plone.org')
|
||||
|
||||
|
||||
FAQ
|
||||
|
@ -142,15 +136,14 @@ Why aren't we using wrappers?
|
|||
We could wrap an object (like a user) with an API to make it more usable
|
||||
right now. That would be an alternative to the convenience methods.
|
||||
|
||||
But telling developers that they will get yet another object from the API which
|
||||
isn't the requested object, but an API-wrapped one instead, would be very hard.
|
||||
Also, making this wrap transparent in order to make the returned object
|
||||
directly usable would be nearly impossible, because we'd have to proxy all the
|
||||
:mod:`zope.interface` stuff, annotations and more.
|
||||
Unfortunately a wrapper is not the same as the object it wraps, and answering
|
||||
the inevitable questions about this difference would be confusing. Moreover,
|
||||
functionality provided by :mod:`zope.interface` such as annotations would need
|
||||
to be proxied. This would be extremely difficult, if not impossible.
|
||||
|
||||
Furthermore, we want to avoid people writing code like this in tests or their
|
||||
internal utility code and failing miserably in the future if wrappers would
|
||||
no longer be needed and would therefore be removed::
|
||||
It is also important that developers be able to ensure that their tests
|
||||
continue to work even if wrappers were to be deprecated. Consider the failure
|
||||
lurking behind test code such as this::
|
||||
|
||||
if users['bob'].__class__.__name__ == 'WrappedMemberDataObject':
|
||||
# do something
|
||||
|
@ -160,5 +153,5 @@ Why ``delete`` instead of ``remove``?
|
|||
-------------------------------------
|
||||
|
||||
* The underlying code uses methods that are named more similarly to *delete*
|
||||
rather than to *remove*
|
||||
* ``CRUD`` has *delete*, not *remove*.
|
||||
rather than to *remove*.
|
||||
* The ``CRUD`` verb is *delete*, not *remove*.
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/api/content.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. _plone-api-content:
|
||||
|
||||
plone.api.content
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/api/env.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. _plone-api-env:
|
||||
|
||||
plone.api.env
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/api/exceptions.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. _plone-api-errors:
|
||||
|
||||
plone.api.exc
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/api/group.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. _plone-api-group:
|
||||
|
||||
plone.api.group
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/api.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/api/index.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. currentmodule:: plone
|
||||
|
@ -80,6 +80,9 @@ api.env
|
|||
.. autosummary::
|
||||
|
||||
api.env.adopt_roles
|
||||
api.env.adopt_user
|
||||
api.env.debug_mode
|
||||
api.env.test_mode
|
||||
|
||||
|
||||
Exceptions and errors
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/api/portal.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. _plone-api-portal:
|
||||
|
||||
plone.api.portal
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/api/user.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. _plone-api-user:
|
||||
|
||||
plone.api.user
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/content.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/content.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. module:: plone
|
||||
|
@ -17,16 +17,17 @@ Content
|
|||
Create content
|
||||
--------------
|
||||
|
||||
First get the portal object that we will use as a container for new content:
|
||||
To add an object, you must first have a container in which to put it. Get the
|
||||
portal object, it will serve nicely:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from plone import api
|
||||
portal = api.portal.get()
|
||||
|
||||
If you want to create a new content item, use the :meth:`api.content.create`
|
||||
method. The type attribute will automatically decide which content type
|
||||
(dexterity, archetype, ...) should be created.
|
||||
Create your new content item using the :meth:`api.content.create` method. The
|
||||
type argument will decide which content type will be created. Both Dexterity
|
||||
and Archetypes content types are supported.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -36,7 +37,8 @@ method. The type attribute will automatically decide which content type
|
|||
title='My Content',
|
||||
container=portal)
|
||||
|
||||
The ``id`` of the object gets generated (in a safe way) from its ``title``.
|
||||
The ``id`` of the new object is automatically and safely generated from its
|
||||
``title``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -48,8 +50,8 @@ The ``id`` of the object gets generated (in a safe way) from its ``title``.
|
|||
Get content object
|
||||
------------------
|
||||
|
||||
There are several approaches of getting to your content object. Consider
|
||||
the following portal structure::
|
||||
There are several approaches to getting your content object. Consider the
|
||||
following portal structure::
|
||||
|
||||
plone (portal root)
|
||||
|-- blog
|
||||
|
@ -76,8 +78,8 @@ the following portal structure::
|
|||
api.content.create(container=events, type='Event', id='sprint')
|
||||
|
||||
|
||||
You can do the following operations to get to various content objects in the
|
||||
stucture above, including using :meth:`api.content.get`.
|
||||
The following operations will get objects from the stucture above, including
|
||||
using :meth:`api.content.get`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -98,7 +100,7 @@ stucture above, including using :meth:`api.content.get`.
|
|||
|
||||
# moreover, you can access content by its UID
|
||||
uid = about['team'].UID()
|
||||
conference = api.content.get(UID=uid)
|
||||
team = api.content.get(UID=uid)
|
||||
|
||||
|
||||
.. invisible-code-block: python
|
||||
|
@ -108,12 +110,13 @@ stucture above, including using :meth:`api.content.get`.
|
|||
self.assertTrue(about)
|
||||
self.assertTrue(conference)
|
||||
self.assertTrue(sprint)
|
||||
self.assertTrue(team)
|
||||
|
||||
|
||||
.. _content_find_example:
|
||||
|
||||
Find content object
|
||||
-------------------
|
||||
Find content objects
|
||||
--------------------
|
||||
|
||||
You can use the *catalog* to search for content. Here is a simple example:
|
||||
|
||||
|
@ -127,8 +130,8 @@ You can use the *catalog* to search for content. Here is a simple example:
|
|||
self.assertEqual(catalog.__class__.__name__, 'CatalogTool')
|
||||
self.assertEqual(len(documents), 3)
|
||||
|
||||
More about how to use the catalog and what parameters it supports is written
|
||||
in the `Collective Developer Documentation
|
||||
More information about how to use the catalog may be found in the `Collective
|
||||
Developer Documentation
|
||||
<http://collective-docs.readthedocs.org/en/latest/searching_and_indexing/query.html>`_.
|
||||
Note that the catalog returns *brains* (metadata stored in indexes) and not
|
||||
objects. However, calling ``getObject()`` on brains does in fact give you the
|
||||
|
@ -145,15 +148,15 @@ object.
|
|||
Get content object UUID
|
||||
-----------------------
|
||||
|
||||
An Universally Unique IDentifier (UUID) is a unique, non-human-readable
|
||||
A Universally Unique IDentifier (UUID) is a unique, non-human-readable
|
||||
identifier for a content object which stays on the object even if the object
|
||||
is moved.
|
||||
|
||||
Plone uses UUIDs for storing content-to-content references and for linking by
|
||||
Plone uses UUIDs for storing references between content and for linking by
|
||||
UIDs, enabling persistent links.
|
||||
|
||||
To get a content object UUID use :meth:`api.content.get_uuid`. The following
|
||||
code gets the UUID of the ``contact`` document.
|
||||
To get the UUID of any content object use :meth:`api.content.get_uuid`. The
|
||||
following code gets the UUID of the ``contact`` document.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -172,9 +175,10 @@ code gets the UUID of the ``contact`` document.
|
|||
Move content
|
||||
------------
|
||||
|
||||
To move content around the portal structure defined above use
|
||||
:meth:`api.content.move` The code below moves the ``contact`` item (with all
|
||||
objects that it contains) out of folder ``about`` into the Plone portal root.
|
||||
To move content around the portal structure defined above use the
|
||||
:meth:`api.content.move` method. The code below moves the ``contact`` item
|
||||
(with all it contains) out of the folder ``about`` and into the Plone portal
|
||||
root.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -190,16 +194,16 @@ objects that it contains) out of folder ``about`` into the Plone portal root.
|
|||
self.assertTrue(portal['contact'])
|
||||
|
||||
Actually, ``move`` behaves like a filesystem move. If you pass it an ``id``
|
||||
argument, you can define to what target ID the object will be moved to.
|
||||
Otherwise it will be moved with the same ID that it had.
|
||||
|
||||
argument the object will have that new ID in it's new home. By default it will
|
||||
retain its original ID.
|
||||
|
||||
.. _content_rename_example:
|
||||
|
||||
Rename content
|
||||
--------------
|
||||
|
||||
To rename, use the :meth:`api.content.rename` method.
|
||||
To rename a content object (change its ID), use the :meth:`api.content.rename`
|
||||
method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -218,7 +222,7 @@ To rename, use the :meth:`api.content.rename` method.
|
|||
Copy content
|
||||
------------
|
||||
|
||||
To copy a content object, use the :meth:`api.content.copy`.
|
||||
To copy a content object, use the :meth:`api.content.copy` method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -228,9 +232,9 @@ To copy a content object, use the :meth:`api.content.copy`.
|
|||
|
||||
api.content.copy(source=training, target=portal)
|
||||
|
||||
Note that the new object will have the same id as the old object (if not
|
||||
stated otherwise). This is not a problem, since the new object is in a different
|
||||
container.
|
||||
Note that the new object will have the same ID as the old object (unless
|
||||
otherwise stated). This is not a problem, since the new object is in a
|
||||
different container.
|
||||
|
||||
.. invisible-code-block: python
|
||||
|
||||
|
@ -240,7 +244,7 @@ container.
|
|||
|
||||
You can also set ``target`` to source's container and set ``safe_id=True`` which
|
||||
will duplicate your content object in the same container and assign it a
|
||||
non-conflicting id.
|
||||
new, non-conflicting ID.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -258,8 +262,8 @@ non-conflicting id.
|
|||
Delete content
|
||||
--------------
|
||||
|
||||
Deleting content works by passing the object you want to delete to the
|
||||
:meth:`api.content.delete` method:
|
||||
To delete a content object, pass the object to the :meth:`api.content.delete`
|
||||
method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -278,11 +282,13 @@ Content manipulation with the `safe_id` option
|
|||
----------------------------------------------
|
||||
|
||||
When manipulating content with :meth:`api.content.create`,
|
||||
:meth:`api.content.move` and :meth:`api.content.copy` the `safe_id` flag is
|
||||
disabled by default. This means the id will be enforced, if the id is taken on
|
||||
the target container the API method will raise an error.
|
||||
:meth:`api.content.move` or :meth:`api.content.copy` the `safe_id` flag is
|
||||
disabled by default. This means the uniqueness of IDs will be enforced. If
|
||||
another object with the same ID is already present in the target container
|
||||
these API methods will raise an error.
|
||||
|
||||
However, if the `safe_id` option is enabled, a non-conflicting id will be created.
|
||||
However, if the `safe_id` option is enabled, a non-conflicting id will be
|
||||
generated.
|
||||
|
||||
.. invisible-code-block: python
|
||||
|
||||
|
@ -299,8 +305,8 @@ However, if the `safe_id` option is enabled, a non-conflicting id will be create
|
|||
Get workflow state
|
||||
------------------
|
||||
|
||||
To find out in which workflow state your content is, use
|
||||
:meth:`api.content.get_state`.
|
||||
To find out the current workflow state of your content, use the
|
||||
:meth:`api.content.get_state` method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -318,7 +324,8 @@ To find out in which workflow state your content is, use
|
|||
Transition
|
||||
----------
|
||||
|
||||
To transition your content into a new state, use :meth:`api.content.transition`.
|
||||
To transition your content to a new workflow state, use the
|
||||
:meth:`api.content.transition` method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/contribute/conventions.html so you
|
||||
have working references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/contribute/conventions.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
.. _conventions:
|
||||
|
||||
|
@ -297,7 +297,7 @@ Declaring dependencies
|
|||
All direct dependencies should be declared in ``install_requires`` or
|
||||
``extras_require`` sections in ``setup.py``. Dependencies, which are not needed for
|
||||
a production environment (like "develop" or "test" dependencies) or are
|
||||
optional (like "archetypes" or "dexterity" flavors of the same package) should
|
||||
optional (like "Archetypes" or "Dexterity" flavors of the same package) should
|
||||
go in ``extras_require``. Remember to document how to enable specific features
|
||||
(and think of using ``zcml:condition`` statements, if you have such optional
|
||||
features).
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/contribute/develop.html so you
|
||||
have working references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/contribute/develop.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
=======================
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/about.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/contribute/index.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
==================================
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/contribute/release.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
.. _releasing_a_new_version:
|
||||
|
||||
=======================
|
||||
|
|
11
docs/env.rst
11
docs/env.rst
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/env.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/env.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. module:: plone
|
||||
|
@ -70,6 +70,8 @@ To temporarily override the user which is currently active, use
|
|||
"doc_owner",
|
||||
)
|
||||
|
||||
.. _env_debug_mode_example:
|
||||
|
||||
Debug mode
|
||||
----------
|
||||
|
||||
|
@ -84,6 +86,9 @@ To know if your zope instance is running in debug mode, use
|
|||
if in_debug_mode:
|
||||
print 'Zope is in debug mode'
|
||||
|
||||
|
||||
.. _env_test_mode_example:
|
||||
|
||||
Test mode
|
||||
---------
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/group.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/group.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. module:: plone
|
||||
|
@ -28,7 +28,8 @@ To create a new portal group, use :meth:`api.group.create`.
|
|||
|
||||
self.assertEqual(group.id, 'staff')
|
||||
|
||||
When creating groups ``title``, ``description``, ``roles`` and ``groups`` are optional.
|
||||
When creating groups ``title``, ``description``, ``roles`` and ``groups`` are
|
||||
optional.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -123,9 +124,9 @@ You can also get all groups, by using :meth:`api.group.get_groups`.
|
|||
Get user's groups
|
||||
-----------------
|
||||
|
||||
If you set the ``user`` parameter,
|
||||
then :meth:`api.group.get_groups` will return
|
||||
groups that the user is member of.
|
||||
The groups returned may be filtered by member. By passing the ``username``
|
||||
parameter, :meth:`api.group.get_groups` will return only those groups to which
|
||||
the user belongs.
|
||||
|
||||
.. invisible-code-block: python
|
||||
|
||||
|
@ -145,12 +146,23 @@ groups that the user is member of.
|
|||
self.assertEqual(groups[1].id, 'AuthenticatedUsers')
|
||||
self.assertEqual(groups[2].id, 'staff')
|
||||
|
||||
You may also pass the user directly to :meth:`api.group.get_groups`:
|
||||
|
||||
from plone import api
|
||||
user = api.user.get(username='jane')
|
||||
groups = api.group.get_groups(user=user)
|
||||
|
||||
.. invisible-code-block: python
|
||||
|
||||
self.assertEqual(groups[0].id, 'Reviewers')
|
||||
self.assertEqual(groups[1].id, 'AuthenticatedUsers')
|
||||
self.assertEqual(groups[2].id, 'staff')
|
||||
|
||||
Get group members
|
||||
-----------------
|
||||
|
||||
Remember to use the :meth:`api.user.get_users` method to get all users that are
|
||||
members of a certain group.
|
||||
Use the :meth:`api.user.get_users` method to get all the users that are
|
||||
members of a group.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -168,8 +180,8 @@ members of a certain group.
|
|||
Delete group
|
||||
------------
|
||||
|
||||
To delete a group, use :meth:`api.group.delete` and pass in either the groupname
|
||||
or the group object you want to delete.
|
||||
To delete a group, use :meth:`api.group.delete` and pass in either the
|
||||
groupname or the group object you want to delete.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -196,9 +208,9 @@ or the group object you want to delete.
|
|||
Adding user to group
|
||||
--------------------
|
||||
|
||||
The :meth:`api.group.add_user` method accepts either the groupname or the group
|
||||
object of the target group and the username or the user object you want to add
|
||||
to the group.
|
||||
To add a user to a group, use the :meth:`api.group.add_user` method. This
|
||||
method accepts either the groupname or the group object for the target group
|
||||
and the username or the user object you want to add to the group.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -209,7 +221,9 @@ to the group.
|
|||
|
||||
.. invisible-code-block: python
|
||||
|
||||
self.assertTrue('staff' in [g.id for g in api.group.get_groups(username='bob')])
|
||||
self.assertTrue(
|
||||
'staff' in [g.id for g in api.group.get_groups(username='bob')]
|
||||
)
|
||||
|
||||
|
||||
.. _group_remove_user_example:
|
||||
|
@ -217,9 +231,9 @@ to the group.
|
|||
Removing user from group
|
||||
------------------------
|
||||
|
||||
The :meth:`api.group.remove_user` method accepts either the groupname or the
|
||||
group object of the target group and either the username or the user object you
|
||||
want to remove from the group.
|
||||
To remove a user from a group, use the :meth:`api.group.remove_user` method.
|
||||
This also accepts either the groupname or the group object for the target group
|
||||
and either the username or the user object you want to remove from the group.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -237,8 +251,8 @@ want to remove from the group.
|
|||
Get group roles
|
||||
---------------
|
||||
|
||||
The :meth:`api.group.get_roles` method is used for getting a group's roles.
|
||||
By default it returns site-wide roles.
|
||||
To find the roles assigned to a group, use the :meth:`api.group.get_roles`
|
||||
method. By default it returns site-wide roles.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -251,7 +265,7 @@ By default it returns site-wide roles.
|
|||
self.assertEqual(set(EXPECTED_SITE_ROLES), set(roles))
|
||||
|
||||
|
||||
If you pass in a content object, it will return local roles of the group
|
||||
If you pass in a content object, it will return the local roles of the group
|
||||
in that particular context.
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -276,8 +290,8 @@ in that particular context.
|
|||
Grant roles to group
|
||||
--------------------
|
||||
|
||||
The :meth:`api.group.grant_roles` allows us to grant a list of roles site-wide to the
|
||||
group.
|
||||
To grant roles to a group, use the :meth:`api.group.grant_roles` method. By
|
||||
default, roles are granted site-wide.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -294,7 +308,8 @@ group.
|
|||
self.assertEqual(set(EXPECTED_SITE_ROLES), set(roles))
|
||||
|
||||
|
||||
If you pass in a content object, it will grant these roles in that particular context.
|
||||
If you pass in a content object, roles will be assigned in that particular
|
||||
context.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -317,8 +332,8 @@ If you pass in a content object, it will grant these roles in that particular co
|
|||
Revoke roles from group
|
||||
-----------------------
|
||||
|
||||
The :meth:`api.group.revoke_roles` allows us to revoke a list of roles from the
|
||||
group.
|
||||
To revoke roles already granted to a group, use the
|
||||
:meth:`api.group.revoke_roles` method.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -333,7 +348,8 @@ group.
|
|||
self.assertEqual(set(EXPECTED_SITE_ROLES), set(roles))
|
||||
|
||||
|
||||
If you pass in a content object, it will grant these roles in that particular context.
|
||||
If you pass in a content object, it will revoke roles granted in that
|
||||
particular context.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -352,5 +368,5 @@ If you pass in a content object, it will grant these roles in that particular co
|
|||
Further reading
|
||||
---------------
|
||||
|
||||
For more information on possible flags and usage options please see the full
|
||||
:ref:`plone-api-group` specification.
|
||||
For more information on possible flags and complete options please see the
|
||||
full :ref:`plone-api-group` specification.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/index.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/index.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
===========
|
||||
A Plone API
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/portal.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/portal.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. module:: plone
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.. admonition:: GitHub-only
|
||||
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read it on api.plone.org:
|
||||
http://developer.plone.org/reference_manuals/external/plone.api/user.html so you have working
|
||||
references and proper formatting.
|
||||
WARNING: If you are reading this on GitHub, DON'T! Read the documentation
|
||||
at `api.plone.org <http://developer.plone.org/reference_manuals/external/plone.api/user.html>`_
|
||||
so you have working references and proper formatting.
|
||||
|
||||
|
||||
.. module:: plone
|
||||
|
|
|
@ -163,12 +163,18 @@ class _GlobalRoleOverridingContext(object):
|
|||
|
||||
|
||||
def debug_mode():
|
||||
"""Returns True if your zope instance is running in debug mode."""
|
||||
"""Returns True if your zope instance is running in debug mode.
|
||||
|
||||
:Example: :ref:`env_debug_mode_example`
|
||||
"""
|
||||
return Globals.DevelopmentMode
|
||||
|
||||
|
||||
def test_mode():
|
||||
"""Returns True if you are running the zope test runner."""
|
||||
"""Returns True if you are running the zope test runner.
|
||||
|
||||
:Example: :ref:`env_test_mode_example`
|
||||
"""
|
||||
from plone.api import env
|
||||
|
||||
if env.IS_TEST is None:
|
||||
|
|
Reference in New Issue