Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit 2319f3da282a3d4d8f9d113053fa79d7cbb09290
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Nov 18 15:07:49 2015 +0100
[python][WIP] documentation for ClientV2: mainly done with Project
---------------------------------------------------------------
python/copr/client_v2/client.py | 2 +-
python/copr/client_v2/handlers.py | 20 ++++-
python/copr/client_v2/resources.py | 102 +++++++++++++++++---
python/docs/ClientV2.rst | 12 ++-
python/docs/client_v2/handlers.rst | 3 +-
python/docs/client_v2/resource_info/build.rst | 6 +
.../docs/client_v2/resource_info/mock_chroot.rst | 6 +
.../docs/client_v2/{ => resource_info}/project.rst | 71 ++++++++++----
.../client_v2/resource_info/project_chroot.rst | 9 ++
python/docs/client_v2/resources.rst | 27 +++++-
python/docs/client_v2/resources_usage.rst | 4 +-
python/docs/conf.py | 8 +-
python/docs/index.rst | 12 ++-
13 files changed, 233 insertions(+), 49 deletions(-)
diff --git a/python/copr/client_v2/client.py b/python/copr/client_v2/client.py
index 95ff21c..db92133 100644
--- a/python/copr/client_v2/client.py
+++ b/python/copr/client_v2/client.py
@@ -216,7 +216,7 @@ class CoprClient(UnicodeMixin, HandlersProvider):
return client
def post_init(self):
- """ Finalizes client initialization be querying API root info
+ """ Finalizes client initialization by querying API root info
"""
log.debug("Getting root resources")
diff --git a/python/copr/client_v2/handlers.py b/python/copr/client_v2/handlers.py
index 9978ace..d52653c 100644
--- a/python/copr/client_v2/handlers.py
+++ b/python/copr/client_v2/handlers.py
@@ -5,7 +5,7 @@ import os
from copr.client_v2.net_client import RequestError, MultiPartTuple
from .entities import ProjectChrootEntity
-from .resources import Project, OperationResult, ProjectsList, ProjectChroot,
ProjectChrootList, Build, BuildList, \
+from .resources import Project, OperationResult, ProjectList, ProjectChroot,
ProjectChrootList, Build, BuildList, \
MockChroot, MockChrootList
@@ -103,6 +103,19 @@ class BuildHandle(AbstractHandle):
def create_from_url(self, project_id, srpm_url,
chroots=None, enable_net=True):
+ """
+ Creates new build using public url to the srpm file
+
+ :param int project_id:
+ :param str srpm_url:
+ :param str file_name:
+ :param list chroots:
+ :param bool enable_net:
+ :return: created build
+ :rtype: Build
+ """
+
+
chroots = map(str, chroots or list())
content = {
"project_id": int(project_id),
@@ -181,13 +194,14 @@ class ProjectHandle(AbstractHandle):
def get_list(self, search_query=None, owner=None, name=None, limit=None,
offset=None):
""" Retrieves projects object according to the given parameters
+
:param str search_query: search projects with such string
:param str owner: owner username
:param str name: project name
:param int limit: limit number of projects
:param int offset: number of projects to skip
- :rtype: :py:class:`~.resources.ProjectsList`
+ :rtype: :py:class:`~.resources.ProjectList`
"""
options = {
"search_query": search_query,
@@ -198,7 +212,7 @@ class ProjectHandle(AbstractHandle):
}
response = self.nc.request(self.get_base_url(), query_params=options)
- return ProjectsList.from_response(self, response, options)
+ return ProjectList.from_response(self, response, options)
def get_one(self, project_id):
# todo: implement: , show_builds=False, show_chroots=False):
diff --git a/python/copr/client_v2/resources.py b/python/copr/client_v2/resources.py
index 2bbd963..b006a39 100644
--- a/python/copr/client_v2/resources.py
+++ b/python/copr/client_v2/resources.py
@@ -50,8 +50,6 @@ class IndividualResource(with_metaclass(EntityFieldsMetaClass,
UnicodeMixin)):
:type links: (dict of (str, Link)) or None
"""
_schema = EmptySchema(strict=True)
- # PY2 compatibility
- #__metaclass__ = EntityFieldsMetaClass
def __init__(self, entity, handle=None, response=None, links=None, embedded=None,
options=None):
@@ -67,7 +65,8 @@ class IndividualResource(with_metaclass(EntityFieldsMetaClass,
UnicodeMixin)):
dir(self.__class__) + list(self.__dict__.keys())
))
if self._entity:
- res.extend([x for x in dir(self._entity) if not
x.startswith("_")])
+ # res.extend([x for x in dir(self._entity) if not
x.startswith("_")])
+ res.extend(self._schema.fields.keys())
return res
def __unicode__(self):
@@ -88,7 +87,7 @@ class Root(IndividualResource):
def get_resource_base_url(self, resource_name):
"""
- :type entity_type: client_v2.common.EntityTypes
+ :param str resource_name:
"""
return "{}{}".format(self.root_url,
self.get_href_by_name(resource_name))
@@ -141,7 +140,7 @@ class Project(IndividualResource):
def __init__(self, entity, handle, **kwargs):
super(Project, self).__init__(entity=entity, handle=handle, **kwargs)
- # import ipdb; ipdb.set_trace()
+
self._entity = entity
self._handle = handle
@@ -162,32 +161,64 @@ class Project(IndividualResource):
return self._handle.delete(self.id)
def get_self(self):
+ """ Retrieves fresh project object from the service
+
+ :rtype: :py:class:`~copr.client_v2.resources.Project`
+ """
return self._handle.get_one(self.id)
+ def get_builds(self, **query_options):
+ """ Get builds owned by this project
+
+ :param query_options: see :py:meth:`.handlers.BuildHandle.get_list`
+ :rtype: :py:class:`~.BuildsList`
+ """
+ handle = self._handle.get_builds_handle()
+ return handle.get_list(project_id=self.id, **query_options)
+
def get_project_chroot(self, name):
+ """ Retrieves project chroot object by the given name
+
+ :param str name: mock chroot name
+ :rtype: :py:class:`~copr.client_v2.resources.ProjectChroot`
+ """
handle = self._handle.get_project_chroots_handle()
return handle.get_one(self, name)
def get_project_chroot_list(self):
+ """ Retrieves project chroots list
+
+ :rtype: :py:class:`~copr.client_v2.resources.ProjectChrootList`
+ """
handle = self._handle.get_project_chroots_handle()
return handle.get_list(self)
def enable_project_chroot(self, name):
"""
+ Enables given chroot for this project
+
:param str name: mock chroot name
:rtype: :py:class:`~copr.client_v2.resources.OperationResult`
"""
handle = self._handle.get_project_chroots_handle()
return handle.enable(self, name)
- # TODO: remove proxy methods on the handle classes
def create_build_from_file(self, *args, **kwargs):
"""
- See additional options `:py:method:BuildHandle.create_from_file:`
+ Shortcut for :py:meth:`.BuildHandle.create_from_file`
+ (here you don't need to specify project_id)
"""
builds = self._handle.get_builds_handle()
return builds.create_from_file(self.id, *args, **kwargs)
+ def create_build_from_url(self, *args, **kwargs):
+ """
+ Shortcut for :py:meth:`.BuildHandle.create_from_file`
+ (here you don't need to specify project_id)
+ """
+ builds = self._handle.get_builds_handle()
+ return builds.create_from_url(self.id, *args, **kwargs)
+
@classmethod
def from_response(cls, handle, data_dict, response=None, options=None):
links = Link.from_dict(data_dict["_links"])
@@ -248,15 +279,22 @@ class MockChroot(IndividualResource):
class OperationResult(IndividualResource):
+ """ Fake resource to represent results of the requested operation
- # TODO: app param expected_status=200 and method is_successful() which would compare
- # obtained status with expected one
+ """
def __init__(self, handle, response=None, entity=None, options=None,
expected_status=200):
super(OperationResult, self).__init__(handle=handle, response=response,
entity=entity, options=options)
self._expected_status = expected_status
@property
def new_location(self):
+ """ Contains an url to the new location produced by an operation
+ If operation doesn't produce a new location would contain None
+
+ :rtype: str
+ """
+ # todo: Create sub-class for results which contains `new_location`
+
if self._response and \
self._response.headers and \
"location" in self._response.headers:
@@ -265,6 +303,11 @@ class OperationResult(IndividualResource):
return None
def is_successful(self):
+ """ Performs check if status code is equal to the expected value
+ of particular request.
+
+ :rtype: bool
+ """
if self._response and self._response.status_code == self._expected_status:
return True
else:
@@ -317,22 +360,40 @@ class CollectionResource(Iterable, UnicodeMixin):
"""
return iter(self._individuals)
+ def __len__(self):
+ if self._individuals is None:
+ raise RuntimeError(u"Collection resource is missing
self._individuals")
+
+ return len(self._individuals)
+
+ def __getitem__(self, item):
+ if self._individuals is None:
+ raise RuntimeError(u"Collection resource is missing
self._individuals")
+
+ return self._individuals[item]
+
@classmethod
def from_response(cls, handle, response, options):
raise NotImplementedError
- # todo: add classmethod from response
-
-class ProjectsList(CollectionResource):
+class ProjectList(CollectionResource):
"""
:type handle: copr.client_v2.handlers.ProjectHandle
"""
def __init__(self, handle, **kwargs):
- super(ProjectsList, self).__init__(**kwargs)
+ super(ProjectList, self).__init__(**kwargs)
self._handle = handle
+ def next_page(self):
+ """
+ Retrieves next chunk of the Project list for the same query options
+
+ :rtype: :py:class:`.ProjectList`
+ """
+ return super(ProjectList, self).next_page()
+
@property
def projects(self):
""" :rtype: list of :py:class:`~.resources.Project`
"""
@@ -341,7 +402,7 @@ class ProjectsList(CollectionResource):
@classmethod
def from_response(cls, handle, response, options):
data_dict = response.json
- result = ProjectsList(
+ result = ProjectList(
handle,
response=response,
links=Link.from_dict(data_dict["_links"]),
@@ -390,6 +451,8 @@ class BuildList(CollectionResource):
class ProjectChrootList(CollectionResource):
"""
+ List of the :class:`~.ProjectChroot` in the one Project.
+
:type handle: copr.client_v2.handlers.ProjectChrootHandle
"""
@@ -400,9 +463,17 @@ class ProjectChrootList(CollectionResource):
@property
def chroots(self):
+ """
+ :rtype: list of :py:class:`~.resources.ProjectChroot`
+ """
return self._individuals
def enable(self, name):
+ """
+ Enables mock chroot for the current project
+
+ :rtype: :py:class:`~.OperationResult`
+ """
return self._handle.enable(self._project, name)
@classmethod
@@ -426,6 +497,8 @@ class ProjectChrootList(CollectionResource):
class MockChrootList(CollectionResource):
"""
+ List of the mock chroots supported by the service
+
:type handle: copr.client_v2.handlers.MockChrootHandle
"""
@@ -435,6 +508,7 @@ class MockChrootList(CollectionResource):
@property
def chroots(self):
+
return self._individuals
@classmethod
diff --git a/python/docs/ClientV2.rst b/python/docs/ClientV2.rst
index 8925854..413a070 100644
--- a/python/docs/ClientV2.rst
+++ b/python/docs/ClientV2.rst
@@ -18,7 +18,17 @@ of retrieved objects.
client_v2/initialization.rst
client_v2/resources_usage.rst
client_v2/errors.rst
- client_v2/project.rst
+
+Resources info
+--------------
+
+.. toctree::
+ :maxdepth: 1
+
+ client_v2/resource_info/project.rst
+ client_v2/resource_info/project_chroot.rst
+ client_v2/resource_info/build.rst
+ client_v2/resource_info/mock_chroot.rst
Autodoc
diff --git a/python/docs/client_v2/handlers.rst b/python/docs/client_v2/handlers.rst
index e830dc1..4df33c0 100644
--- a/python/docs/client_v2/handlers.rst
+++ b/python/docs/client_v2/handlers.rst
@@ -11,8 +11,7 @@ Handlers
.. autoclass:: copr.client_v2.handlers.BuildHandle
- :members: get_list, get_one
- :undoc-members:
+ :members:
.. autoclass:: copr.client_v2.handlers.MockChrootHandle
:members: get_list, get_one
diff --git a/python/docs/client_v2/resource_info/build.rst
b/python/docs/client_v2/resource_info/build.rst
new file mode 100644
index 0000000..924dc66
--- /dev/null
+++ b/python/docs/client_v2/resource_info/build.rst
@@ -0,0 +1,6 @@
+.. _build-info:
+
+Build
+=====
+
+pass
diff --git a/python/docs/client_v2/resource_info/mock_chroot.rst
b/python/docs/client_v2/resource_info/mock_chroot.rst
new file mode 100644
index 0000000..f7194da
--- /dev/null
+++ b/python/docs/client_v2/resource_info/mock_chroot.rst
@@ -0,0 +1,6 @@
+.. _`mock-chroot-info`:
+
+Mock chroot
+===========
+
+
diff --git a/python/docs/client_v2/project.rst
b/python/docs/client_v2/resource_info/project.rst
similarity index 54%
rename from python/docs/client_v2/project.rst
rename to python/docs/client_v2/resource_info/project.rst
index 9d3cb48..2758c08 100644
--- a/python/docs/client_v2/project.rst
+++ b/python/docs/client_v2/resource_info/project.rst
@@ -2,7 +2,9 @@ Project
=======
Access to project resources is done through
:py:meth:`~copr.client_v2.client.CoprClient.projects`.
-property of initialized :py:class:`~copr.client_v2.client.CoprClient`.
+property of initialized :py:class:`~copr.client_v2.client.CoprClient`. That property is
an instance of
+:py:class:`~copr.client_v2.handlers.ProjectHandle`. Projects are represented by
+:py:class:`~copr.client_v2.resources.Project` class.
Individual Attributes
---------------------
@@ -23,50 +25,85 @@ instructions string yes installation
instructions
homepage string(URL) yes project homepage URL
contact string(URL or email) yes contact with the project maintainer
disable_createrepo bool yes disables automatic repository metadata
generation
-build_enable_net bool yes set default value for new builds
option `enable_net`
+build_enable_net bool yes set default value for new builds
option ``enable_net``
repos list of string yes list of additional repositories to be
enabled during the build
================== ==================== =========
=================================================================================
-.. note:: all following examples assume that we use `cl` as an instance of
:py:class:`.client_v2.client.CoprClient`
+.. note::
+ all following examples assume that we use ``cl``
+ as an instance of :py:class:`.client_v2.client.CoprClient`
Get one project
---------------
- .. sourcecode:: python
+.. sourcecode:: python
- >>> p = cl.projects.get_one(1835)
+ >>> p = cl.projects.get_one(1835)
Modify project parameters
-------------------------
- .. sourcecode:: python
+.. sourcecode:: python
- >>> p.description = "Nothing"
- >>> p.update()
+ >>> p.description = "Nothing"
+ >>> p.update()
Delete project
--------------
- .. sourcecode:: python
+.. sourcecode:: python
- >>> p.delete()
+ >>> p.delete()
Create new project
------------------
- .. todo:: Not Implemented yet
+.. note:: Not Implemented yet
Fetch projects
--------------
- .. sourcecode:: python
+.. sourcecode:: python
- >>> plist_1 = cl.project.get_list(limit=10)
- # filter by name
- >>> plist_2 = cl.project.get_list(name="copr")
- # search by string
- >>> plist_2 = cl.project.get_list(name="copr")
+ >>> plist_1 = cl.project.get_list(limit=10)
+ # filter by name
+ >>> plist_2 = cl.project.get_list(name="copr")
+ # search by string
+ >>> plist_2 = cl.project.get_list(name="copr")
+Access project chroots
+----------------------
+.. note::
+ see also :ref:`project-chroot-info`
+
+
+.. sourcecode:: python
+
+ # get all lists
+ >>> chroots = p.get_project_chroot_list()
+ >>> print("\n".join(map(str, chroots)))
+ <Project chroot: fedora-21-x86_64, additional packages: [], comps size if any:
0>
+ <Project chroot: fedora-21-i386, additional packages: [], comps size if any:
0>
+ # get one chroot
+ >>> chroot_1 = p.get_project_chroot("fedora-22-i386")
+ # enable chroot for project
+ >>> p.enable_project_chroot("fedora-22-x86_64)
+
+Access project builds
+---------------------
+.. note::
+ see also :ref:`build-info`
+
+.. sourcecode:: python
+
+ >>> p.get_builds(limit=5)
+ >>> pbuilds = p.get_builds(limit=5)
+ >>> print(pbuilds[3])
+ <Build #138414 state: failed>
+
+ # submit new builds
+ >>>
p.create_build_from_url(srpm_url="http://example.com/my.src.rpm")
+ >>> p.create_build_from_file(file_path="/tmp/my.src.rpm")
diff --git a/python/docs/client_v2/resource_info/project_chroot.rst
b/python/docs/client_v2/resource_info/project_chroot.rst
new file mode 100644
index 0000000..8920b02
--- /dev/null
+++ b/python/docs/client_v2/resource_info/project_chroot.rst
@@ -0,0 +1,9 @@
+
+.. _project-chroot-info:
+
+Project chroot
+==============
+
+foobar
+
+
diff --git a/python/docs/client_v2/resources.rst b/python/docs/client_v2/resources.rst
index 3693426..f19c5fc 100644
--- a/python/docs/client_v2/resources.rst
+++ b/python/docs/client_v2/resources.rst
@@ -2,8 +2,29 @@ Resources
=========
.. autoclass:: copr.client_v2.resources.Project
- :members: update, delete
- :undoc-members:
+ :members:
+
+.. autoclass:: copr.client_v2.resources.ProjectList
+ :members:
+
+.. autoclass:: copr.client_v2.resources.ProjectChroot
+ :members:
+
+
+.. autoclass:: copr.client_v2.resources.ProjectChrootList
+ :members:
+
-.. autoclass:: copr.client_v2.resources.ProjectsList
+.. autoclass:: copr.client_v2.resources.MockChroot
:members:
+
+
+.. autoclass:: copr.client_v2.resources.MockChrootList
+ :members:
+
+
+.. autoclass:: copr.client_v2.resources.OperationResult
+ :members:
+
+
+
diff --git a/python/docs/client_v2/resources_usage.rst
b/python/docs/client_v2/resources_usage.rst
index dc95fa2..c48cf03 100644
--- a/python/docs/client_v2/resources_usage.rst
+++ b/python/docs/client_v2/resources_usage.rst
@@ -2,7 +2,7 @@ Resources
~~~~~~~~~
Client represents API with two kinds of resources: Individuals and Collections. For
example when we request
-all projects with name `copr` we would receive collection ProjectsList_ resource:
+all projects with name `copr` we would receive collection
:py:class:`~copr.client_v2.resources.ProjectList` resource:
.. sourcecode:: python
@@ -31,7 +31,7 @@ retrieved in the one request, collections has method `next_page()` to
retrieve m
-If we already knew project id we could get an individual Project_ resource:
+If we already knew project id we could get an individual
:py:class:`~copr.client_v2.resources.Project` resource:
.. sourcecode:: python
diff --git a/python/docs/conf.py b/python/docs/conf.py
index ff2001e..115f114 100644
--- a/python/docs/conf.py
+++ b/python/docs/conf.py
@@ -69,7 +69,7 @@ release = '1.52'
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
+default_role = "any"
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
@@ -93,7 +93,9 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'default'
+# html_theme = 'classic'
+#html_theme = 'alabaster'
+
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -243,4 +245,4 @@ texinfo_documents = [
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
-#autodoc_member_order = 'bysource'
+autodoc_member_order = 'bysource'
diff --git a/python/docs/index.rst b/python/docs/index.rst
index d23535d..8e75b14 100644
--- a/python/docs/index.rst
+++ b/python/docs/index.rst
@@ -12,7 +12,10 @@ through its `API <
http://copr.fedoraproject.org/api>`_.
Python-copr right now is in alpha stage, so expect lot of changes. Now it targets python
2.6+
and python3.3+.
-.. include:: installation.rst
+.. toctree::
+ :maxdepth: 1
+
+ installation.rst
Contact
=======
@@ -31,8 +34,11 @@ Usage
Recently Copr started to offer an alternative REST-like APIv2_.
New API is provided by mostly independent `client_v2` package.
-.. include:: ClientV1.rst
-.. include:: ClientV2.rst
+.. toctree::
+ :maxdepth: 1
+
+ ClientV1.rst
+ ClientV2.rst
Indices and tables