From 4781fd7e4c3d9d5b343f0c1b0597a8a535d6bdbf Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 9 Jan 2016 19:22:54 +0100 Subject: [PATCH] Improve the API documentation. --- docs/api/gitlab.rst | 29 +++++- docs/api/modules.rst | 4 +- docs/index.rst | 2 +- gitlab/__init__.py | 181 +++++++++++++++++++++++++++++++--- gitlab/objects.py | 226 +++++++++++++++++++++++++++++++++++-------- 5 files changed, 382 insertions(+), 60 deletions(-) diff --git a/docs/api/gitlab.rst b/docs/api/gitlab.rst index 296a1e3bd..da2719e4f 100644 --- a/docs/api/gitlab.rst +++ b/docs/api/gitlab.rst @@ -1,8 +1,31 @@ -############################ -``gitlab`` API documentation -############################ +gitlab package +============== + +Module contents +--------------- .. automodule:: gitlab :members: :undoc-members: :show-inheritance: + :exclude-members: Hook, Project, UserProject, Group, Issue, Team, User, + all_projects, owned_projects, search_projects + +gitlab.exceptions module +------------------------ + +.. automodule:: gitlab.exceptions + :members: + :undoc-members: + :show-inheritance: + +gitlab.objects module +--------------------- + +.. automodule:: gitlab.objects + :members: + :undoc-members: + :show-inheritance: + :exclude-members: Branch, Commit, Content, Event, File, Hook, Issue, Key, + Label, Member, MergeRequest, Milestone, Note, Project, + Snippet, Tag diff --git a/docs/api/modules.rst b/docs/api/modules.rst index 22089d84e..7b09ae1b6 100644 --- a/docs/api/modules.rst +++ b/docs/api/modules.rst @@ -1,5 +1,5 @@ -. -= +gitlab +====== .. toctree:: :maxdepth: 4 diff --git a/docs/index.rst b/docs/index.rst index c952a2114..0d09a780d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,7 +15,7 @@ Contents: cli api-usage upgrade-from-0.10 - api/gitlab + api/modules Indices and tables diff --git a/gitlab/__init__.py b/gitlab/__init__.py index b70d0a89d..e50a2a78a 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -14,7 +14,8 @@ # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . -"""Package for interfacing with GitLab-api """ +"""Wrapper for the GitLab API.""" + from __future__ import print_function from __future__ import division from __future__ import absolute_import @@ -50,16 +51,59 @@ def _sanitize_dict(src): class Gitlab(object): - """Represents a GitLab server connection + """Represents a GitLab server connection. Args: - url (str): the URL of the Gitlab server - private_token (str): the user private token - email (str): the user email/login - password (str): the user password (associated with email) - ssl_verify (bool): (Passed to requests-library) - timeout (float or tuple(float,float)): (Passed to - requests-library). Timeout to use for requests to gitlab server + url (str): The URL of the GitLab server. + private_token (str): The user private token + email (str): The user email or login. + password (str): The user password (associated with email). + ssl_verify (bool): Whether SSL certificates should be validated. + timeout (float or tuple(float,float)): Timeout to use for requests to + the GitLab server. + + Attributes: + user_keys (UserKeyManager): Manager for GitLab users' SSH keys. + users (UserManager): Manager for GitLab users + group_members (GroupMemberManager): Manager for GitLab group members + groups (GroupManager): Manager for GitLab members + hooks (HookManager): Manager for GitLab hooks + issues (IssueManager): Manager for GitLab issues + project_branches (ProjectBranchManager): Manager for GitLab projects + branches + project_commits (ProjectCommitManager): Manager for GitLab projects + commits + project_keys (ProjectKeyManager): Manager for GitLab projects keys + project_events (ProjectEventManager): Manager for GitLab projects + events + project_forks (ProjectForkManager): Manager for GitLab projects forks + project_hooks (ProjectHookManager): Manager for GitLab projects hooks + project_issue_notes (ProjectIssueNoteManager): Manager for GitLab notes + on issues + project_issues (ProjectIssueManager): Manager for GitLab projects + issues + project_members (ProjectMemberManager): Manager for GitLab projects + members + project_notes (ProjectNoteManager): Manager for GitLab projects notes + project_tags (ProjectTagManager): Manager for GitLab projects tags + project_mergerequest_notes (ProjectMergeRequestNoteManager): Manager + for GitLab notes on merge requests + project_mergerequests (ProjectMergeRequestManager): Manager for GitLab + projects merge requests + project_milestones (ProjectMilestoneManager): Manager for GitLab + projects milestones + project_labels (ProjectLabelManager): Manager for GitLab projects + labels + project_files (ProjectFileManager): Manager for GitLab projects files + project_snippet_notes (ProjectSnippetNoteManager): Manager for GitLab + note on snippets + project_snippets (ProjectSnippetManager): Manager for GitLab projects + snippets + user_projects (UserProjectManager): Manager for GitLab projects users + projects (ProjectManager): Manager for GitLab projects + team_members (TeamMemberManager): Manager for GitLab teams members + team_projects (TeamProjectManager): Manager for GitLab teams projects + teams (TeamManager): Manager for GitLab teams """ def __init__(self, url, private_token=None, @@ -71,11 +115,11 @@ def __init__(self, url, private_token=None, #: Headers that will be used in request to GitLab self.headers = {} self.set_token(private_token) - #: the user email + #: The user email self.email = email - #: the user password (associated with email) + #: The user password (associated with email) self.password = password - #: (Passed to requests-library) + #: Whether SSL certificates should be validated self.ssl_verify = ssl_verify self.user_keys = UserKeyManager(self) @@ -110,6 +154,18 @@ def __init__(self, url, private_token=None, @staticmethod def from_config(gitlab_id=None, config_files=None): + """Create a Gitlab connection from configuration files. + + Args: + gitlab_id (str): ID of the configuration section. + config_files list[str]: List of paths to configuration files. + + Returns: + (gitlab.Gitlab): A Gitlab connection. + + Raises: + gitlab.config.GitlabDataError: If the configuration is not correct. + """ config = gitlab.config.GitlabConfigParser(gitlab_id=gitlab_id, config_files=config_files) return Gitlab(config.url, private_token=config.token, @@ -120,7 +176,8 @@ def auth(self): Uses either the private token, or the email/password pair. - The user attribute will hold a CurrentUser object on success. + The `user` attribute will hold a `gitlab.objects.CurrentUser` object on + success. """ if self.private_token: self.token_auth() @@ -128,6 +185,7 @@ def auth(self): self.credentials_auth() def credentials_auth(self): + """Performs an authentication using email/password.""" if not self.email or not self.password: raise GitlabAuthenticationError("Missing email/password") @@ -135,13 +193,21 @@ def credentials_auth(self): r = self._raw_post('/session', data, content_type='application/json') raise_error_from_response(r, GitlabAuthenticationError, 201) self.user = CurrentUser(self, r.json()) + """(gitlab.objects.CurrentUser): Object representing the user currently + logged. + """ self.set_token(self.user.private_token) def token_auth(self): + """Performs an authentication using the private token.""" self.user = CurrentUser(self) def set_url(self, url): - """Updates the gitlab URL.""" + """Updates the GitLab URL. + + Args: + url (str): Base URL of the GitLab server. + """ self._url = '%s/api/v3' % url def _construct_url(self, id_, obj, parameters): @@ -167,7 +233,11 @@ def _create_headers(self, content_type=None, headers={}): return request_headers def set_token(self, token): - """Sets the private token for authentication.""" + """Sets the private token for authentication. + + Args: + token (str): The private token. + """ self.private_token = token if token else None if token: self.headers["PRIVATE-TOKEN"] = token @@ -175,7 +245,12 @@ def set_token(self, token): del self.headers["PRIVATE-TOKEN"] def set_credentials(self, email, password): - """Sets the email/login and password for authentication.""" + """Sets the email/login and password for authentication. + + Args: + email (str): The user email or login. + password (str): The user password. + """ self.email = email self.password = password @@ -233,6 +308,19 @@ def _raw_delete(self, path, content_type=None, **kwargs): "Can't connect to GitLab server (%s)" % self._url) def list(self, obj_class, **kwargs): + """Request the listing of GitLab resources. + + Args: + obj_class (object): The class of resource to request. + **kwargs: Additional arguments to send to GitLab. + + Returns: + list(obj_class): A list of objects of class `obj_class`. + + Raises: + GitlabConnectionError: If the server cannot be reached. + GitlabListError: If the server fails to perform the request. + """ missing = [] for k in itertools.chain(obj_class.requiredUrlAttrs, obj_class.requiredListAttrs): @@ -288,6 +376,20 @@ def list(self, obj_class, **kwargs): return results def get(self, obj_class, id=None, **kwargs): + """Request a GitLab resources. + + Args: + obj_class (object): The class of resource to request. + id: The object ID. + **kwargs: Additional arguments to send to GitLab. + + Returns: + obj_class: An object of class `obj_class`. + + Raises: + GitlabConnectionError: If the server cannot be reached. + GitlabGetError: If the server fails to perform the request. + """ missing = [] for k in itertools.chain(obj_class.requiredUrlAttrs, obj_class.requiredGetAttrs): @@ -319,6 +421,19 @@ def get(self, obj_class, id=None, **kwargs): return r.json() def delete(self, obj, **kwargs): + """Delete an object on the GitLab server. + + Args: + obj (object): The object to delete. + **kwargs: Additional arguments to send to GitLab. + + Returns: + bool: True if the operation succeeds. + + Raises: + GitlabConnectionError: If the server cannot be reached. + GitlabDeleteError: If the server fails to perform the request. + """ params = obj.__dict__.copy() params.update(kwargs) missing = [] @@ -353,6 +468,23 @@ def delete(self, obj, **kwargs): return True def create(self, obj, **kwargs): + """Create an object on the GitLab server. + + The object class and attributes define the request to be made on the + GitLab server. + + Args: + obj (object): The object to create. + **kwargs: Additional arguments to send to GitLab. + + Returns: + str: A json representation of the object as returned by the GitLab + server + + Raises: + GitlabConnectionError: If the server cannot be reached. + GitlabCreateError: If the server fails to perform the request. + """ params = obj.__dict__.copy() params.update(kwargs) missing = [] @@ -383,6 +515,23 @@ def create(self, obj, **kwargs): return r.json() def update(self, obj, **kwargs): + """Update an object on the GitLab server. + + The object class and attributes define the request to be made on the + GitLab server. + + Args: + obj (object): The object to create. + **kwargs: Additional arguments to send to GitLab. + + Returns: + str: A json representation of the object as returned by the GitLab + server + + Raises: + GitlabConnectionError: If the server cannot be reached. + GitlabUpdateError: If the server fails to perform the request. + """ params = obj.__dict__.copy() params.update(kwargs) missing = [] diff --git a/gitlab/objects.py b/gitlab/objects.py index b430795a6..628b41ff5 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -38,9 +38,31 @@ def default(self, obj): class BaseManager(object): + """Base manager class for API operations. + + Managers provide method to manage GitLab API objects, such as retrieval, + listing, creation. + + Inherited class must define the ``obj_cls`` attribute. + + Attributes: + obj_cls (class): class of objects wrapped by this manager. + """ + obj_cls = None def __init__(self, gl, parent=None, args=[]): + """Constructs a manager. + + Args: + gl (gitlab.Gitlab): Gitlab object referencing the GitLab server. + parent (Optional[Manager]): A parent manager. + args (list): A list of tuples defining a link between the + parent/child attributes. + + Raises: + AttributeError: If `obj_cls` is None. + """ self.gitlab = gl self.args = args self.parent = parent @@ -54,18 +76,59 @@ def _set_parent_args(self, **kwargs): kwargs.setdefault(attr, getattr(self.parent, parent_attr)) def get(self, id, **kwargs): + """Get a GitLab object. + + Args: + id: ID of the object to retrieve. + **kwargs: Additional arguments to send to GitLab. + + Returns: + object: An object of class `obj_cls`. + + Raises: + NotImplementedError: If objects cannot be retrieved. + GitlabGetError: If the server fails to perform the request. + """ self._set_parent_args(**kwargs) if not self.obj_cls.canGet: raise NotImplementedError return self.obj_cls.get(self.gitlab, id, **kwargs) def list(self, **kwargs): + """Get a list of GitLab objects. + + Args: + **kwargs: Additional arguments to send to GitLab. + + Returns: + list[object]: A list of `obj_cls` objects. + + Raises: + NotImplementedError: If objects cannot be listed. + GitlabListError: If the server fails to perform the request. + """ self._set_parent_args(**kwargs) if not self.obj_cls.canList: raise NotImplementedError return self.obj_cls.list(self.gitlab, **kwargs) def create(self, data, **kwargs): + """Create a new object of class `obj_cls`. + + Args: + data (dict): The parameters to send to the GitLab server to create + the object. Required and optional arguments are defined in the + `requiredCreateAttrs` and `optionalCreateAttrs` of the + `obj_cls` class. + **kwargs: Additional arguments to send to GitLab. + + Returns: + object: A newly create `obj_cls` object. + + Raises: + NotImplementedError: If objects cannot be created. + GitlabCreateError: If the server fails to perform the request. + """ self._set_parent_args(**kwargs) if not self.obj_cls.canCreate: raise NotImplementedError @@ -85,15 +148,7 @@ def _custom_list(self, url, cls, **kwargs): class GitlabObject(object): - """Base class for all classes that interface with GitLab - - Args: - gl (gitlab.Gitlab): GitLab server connection - data: If data is integer or string type, get object from GitLab - data: If data is dictionary, create new object locally. To save object - in GitLab, call save-method - kwargs: Arbitrary keyword arguments - """ + """Base class for all classes that interface with GitLab.""" #: Url to use in GitLab for this object _url = None # Some objects (e.g. merge requests) have different urls for singular and @@ -104,38 +159,39 @@ class GitlabObject(object): #: Whether _get_list_or_object should return list or object when id is None getListWhenNoId = True - #: Tells if GitLab-api allows retrieving single objects + #: Tells if GitLab-api allows retrieving single objects. canGet = True - #: Tells if GitLab-api allows listing of objects + #: Tells if GitLab-api allows listing of objects. canList = True - #: Tells if GitLab-api allows creation of new objects + #: Tells if GitLab-api allows creation of new objects. canCreate = True - #: Tells if GitLab-api allows updating object + #: Tells if GitLab-api allows updating object. canUpdate = True - #: Tells if GitLab-api allows deleting object + #: Tells if GitLab-api allows deleting object. canDelete = True - #: Attributes that are required for constructing url + #: Attributes that are required for constructing url. requiredUrlAttrs = [] - #: Attributes that are required when retrieving list of objects + #: Attributes that are required when retrieving list of objects. requiredListAttrs = [] - #: Attributes that are required when retrieving single object + #: Attributes that are required when retrieving single object. requiredGetAttrs = [] - #: Attributes that are required when deleting object + #: Attributes that are required when deleting object. requiredDeleteAttrs = [] - #: Attributes that are required when creating a new object + #: Attributes that are required when creating a new object. requiredCreateAttrs = [] - #: Attributes that are optional when creating a new object + #: Attributes that are optional when creating a new object. optionalCreateAttrs = [] - #: Attributes that are required when updating an object + #: Attributes that are required when updating an object. requiredUpdateAttrs = None - #: Attributes that are optional when updating an object + #: Attributes that are optional when updating an object. optionalUpdateAttrs = None - #: Whether the object ID is required in the GET url + #: Whether the object ID is required in the GET url. getRequiresId = True - #: List of managers to create + #: List of managers to create. managers = [] - + #: Name of the identifier of an object. idAttr = 'id' + #: Attribute to use as ID when displaying the object. shortPrintAttr = None def _data_for_gitlab(self, extra_parameters={}): @@ -151,6 +207,20 @@ def _data_for_gitlab(self, extra_parameters={}): @classmethod def list(cls, gl, **kwargs): + """Retrieve a list of objects from GitLab. + + Args: + gl (gitlab.Gitlab): Gitlab object referencing the GitLab server. + per_page (int): Maximum number of items to return. + page (int): ID of the page to return when using pagination. + + Returns: + list[object]: A list of objects. + + Raises: + NotImplementedError: If objects can't be listed. + GitlabListError: If the server cannot perform the request. + """ if not cls.canList: raise NotImplementedError @@ -161,6 +231,20 @@ def list(cls, gl, **kwargs): @classmethod def get(cls, gl, id, **kwargs): + """Retrieve a single object. + + Args: + gl (gitlab.Gitlab): Gitlab object referencing the GitLab server. + id (int or str): ID of the object to retrieve. + + Returns: + object: The found GitLab object. + + Raises: + NotImplementedError: If objects can't be retrieved. + GitlabGetError: If the server cannot perform the request. + """ + if cls.canGet is False: raise NotImplementedError elif cls.canGet is True: @@ -229,6 +313,19 @@ def delete(self, **kwargs): @classmethod def create(cls, gl, data, **kwargs): + """Create an object. + + Args: + gl (gitlab.Gitlab): Gitlab object referencing the GitLab server. + data (dict): The data used to define the object. + + Returns: + object: The new object. + + Raises: + NotImplementedError: If objects can't be created. + GitlabCreateError: If the server cannot perform the request. + """ if not cls.canCreate: raise NotImplementedError @@ -238,7 +335,20 @@ def create(cls, gl, data, **kwargs): return obj def __init__(self, gl, data=None, **kwargs): + """Constructs a new object. + + Do not use this method. Use the `get` or `create` class methods + instead. + + Args: + gl (gitlab.Gitlab): Gitlab object referencing the GitLab server. + data: If `data` is a dict, create a new object using the + information. If it is an int or a string, get a GitLab object + from an API request. + **kwargs: Additional arguments to send to GitLab. + """ self._from_api = False + #: (gitlab.Gitlab): Gitlab connection. self.gitlab = gl if (data is None or isinstance(data, six.integer_types) or @@ -276,6 +386,11 @@ def display(self, pretty): self.short_print() def short_print(self, depth=0): + """Print the object on the standard output (verbose). + + Args: + depth (int): Used internaly for recursive call. + """ id = self.__dict__[self.idAttr] print("%s%s: %s" % (" " * depth * 2, self.idAttr, id)) if self.shortPrintAttr: @@ -303,6 +418,11 @@ def _obj_to_str(obj): return str(obj) def pretty_print(self, depth=0): + """Print the object on the standard output (verbose). + + Args: + depth (int): Used internaly for recursive call. + """ id = self.__dict__[self.idAttr] print("%s%s: %s" % (" " * depth * 2, self.idAttr, id)) for k in sorted(self.__dict__.keys()): @@ -330,6 +450,11 @@ def pretty_print(self, depth=0): print("%s%s: %s" % (" " * depth * 2, pretty_k, v)) def json(self): + """Dump the object as json. + + Returns: + str: The json string. + """ return json.dumps(self.__dict__, cls=jsonEncoder) @@ -961,15 +1086,15 @@ def create_file(self, path, branch, content, message, **kwargs): """Creates file in project repository Args: - path (str): Full path to new file - branch (str): The name of branch - content (str): Content of the file - message (str): Commit message - kwargs: Arbitrary keyword arguments + path (str): Full path to new file. + branch (str): The name of branch. + content (str): Content of the file. + message (str): Commit message. + **kwargs: Arbitrary keyword arguments. Raises: - GitlabCreateError: Operation failed - GitlabConnectionError: Connection to GitLab-server failed + GitlabConnectionError: If the server cannot be reached. + GitlabCreateError: If the server fails to perform the request. """ url = "/projects/%s/repository/files" % self.id url += ("?file_path=%s&branch_name=%s&content=%s&commit_message=%s" % @@ -998,14 +1123,20 @@ def create_fork_relation(self, forked_from_id): forked_from_id (int): The ID of the project that was forked from Raises: - GitlabCreateError: Operation failed - GitlabConnectionError: Connection to GitLab-server failed + GitlabConnectionError: If the server cannot be reached. + GitlabCreateError: If the server fails to perform the request. """ url = "/projects/%s/fork/%s" % (self.id, forked_from_id) r = self.gitlab._raw_post(url) raise_error_from_response(r, GitlabCreateError, 201) def delete_fork_relation(self): + """Delete a forked relation between existing projects. + + Raises: + GitlabConnectionError: If the server cannot be reached. + GitlabDeleteError: If the server fails to perform the request. + """ url = "/projects/%s/fork" % self.id r = self.gitlab._raw_delete(url) raise_error_from_response(r, GitlabDeleteError) @@ -1038,19 +1169,38 @@ class ProjectManager(BaseManager): obj_cls = Project def search(self, query, **kwargs): - """Searches projects by name. + """Search projects by name. + + Args: + query (str): The query string to send to GitLab for the search. + **kwargs: Additional arguments to send to GitLab. - Returns a list of matching projects. + Returns: + list(Project): A list of matching projects. """ return self._custom_list("/projects/search/" + query, Project, **kwargs) def all(self, **kwargs): - """Lists all the projects (need admin rights).""" + """List all the projects (need admin rights). + + Args: + **kwargs: Additional arguments to send to GitLab. + + Returns: + list(Project): The list of projects. + """ return self._custom_list("/projects/all", Project, **kwargs) def owned(self, **kwargs): - """Lists owned projects.""" + """List owned projects. + + Args: + **kwargs: Additional arguments to send to GitLab. + + Returns: + list(Project): The list of owned projects. + """ return self._custom_list("/projects/owned", Project, **kwargs)