Contents:¶
gerritssh¶




Python package wrapping the Gerrit command line API.
This is very much a work in progress, and intended to be the basis for building more sophisticated scripts and applications, for example automating complex work flows in large projects.
Rationale¶
This project was started as a test-bed for me to explore the wider world of Python, such as:
- Unit testing
- Continuous Integration
- Sphinx rst documentation
- tox, flake8, etc.
- Supporting multiple versions of Python.
- Pythonic style
Basically, everything that goes into making an industrial-strength Python library or application. So you are going to see novice mistakes and code which is not idiomatic.
All contributions and suggestions are welcome, and indeed that’s the logic behind making this open source. I want to learn from the experience of those who’ve been there before me.
Features¶
- Handles the low-level details of the gerrit SSH command line syntax.
- Makes the results of those commands available to the programmer in a format which is more natural for Python programmers to manipulate.
- Is aware of which combinations of commands and versions are supported for versions of Gerrit from 2.4 through 2.8.
- Supports Python 2.6, 2.7, 3.3, and 3.4
Planned Features¶
- Support a broad range of commands including the latest commands for Gerrit v2.8 (such as ls-members)
- Add a module to operate on sets of Review objects to perform more complex searches, such as building dependency graphs of open reviews.
- Add support for the administrators gsql command
- Implement queries such as examining the audit trail on group membership
- Wrapping generation of properly quoted SQL statements
- Extract the SCHEMA information with a \d command and dynamically clone the database into a memory-resident sqlite database.
- Implement support for the stream-events command, serving up events using an observer-pattern approach to allow many threads to consume events.
Feedback¶
If you have any suggestions or questions about gerritssh feel free to email me at kderrick_public@att.net.
If you encounter any errors or problems with gerritssh, please let me know! Open an Issue at the GitHub http://github.com/kdopen/gerritssh main repository.
Installation¶
At the command line either via easy_install or pip:
$ easy_install gerritssh
$ pip install gerritssh
Or, if you have virtualenvwrapper installed:
$ mkvirtualenv gerritssh
$ pip install gerritssh
Usage¶
To use gerritssh in a project:
import gerritssh
The script, gsshcli, will be installed as part of the pip install command. It is not really meant to be used for real work, but does provide an example of how to use the library.
For help, use the --help option, specifying the sub-command for more detailed help:
$ gsshcli.py --help
usage: gsshcli.py [-h] [-v] [-V] {projects,query,version} ...
Simple CLI script to use gerritssh to talk to a site
positional arguments:
{projects,query,version}
projects List the projects
query Search for reviews
version Show the Gerrit version
optional arguments:
-h, --help show this help message and exit
-v, --verbose set verbosity level [default: None]
-V, --version show program's version number and exit
$ gsshcli.py query -h
usage: gsshcli.py query [-h] [-s {open,merged,abandoned}] [-b BRANCH]
[-l MAXRESULTS] [-p PROJECT]
site ...
positional arguments:
site The Gerrit instance to connect to, e.g
review.openstack,org
QUERY
optional arguments:
-h, --help show this help message and exit
-s {open,merged,abandoned}, --status {open,merged,abandoned}
Find all reviews with he given status
-b BRANCH, --branch BRANCH
Restrict search to a given branch
-l MAXRESULTS, --limit MAXRESULTS
Limit the number of results
-p PROJECT, --project PROJECT
Project for which reviews are required
$ gsshcli.py projects --help
usage: gsshcli.py projects [-h] [-a] site
positional arguments:
site The Gerrit instance to connect to, e.g review.openstack,org
optional arguments:
-h, --help show this help message and exit
-a, --all List all project types
$ gsshcli.py version --help
usage: gsshcli.py version [-h] site
positional arguments:
site The Gerrit instance to connect to, e.g review.openstack,org
optional arguments:
-h, --help show this help message and exit
Sample commands:
$ gsshcli.py version review.openstack.org
review.openstack.org is running version 2.4.4 of Gerrit
$ gsshcli.py projects review.openstack.org
...
$ gsshicli.py query review.openstack.org --project openstack-infra/gerritlib --status open
...
Contributing¶
Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
You can contribute in many ways:
Types of Contributions¶
Report Bugs¶
Report bugs at https://github.com/kdopen/gerritssh/issues.
If you are reporting a bug, please include:
- Your operating system name and version.
- Any details about your local setup that might be helpful in troubleshooting.
- Detailed steps to reproduce the bug.
Fix Bugs¶
Look through the GitHub issues for bugs. Anything tagged with “bug” is open to whoever wants to implement it.
Implement Features¶
Look through the GitHub issues for features. Anything tagged with “feature” is open to whoever wants to implement it. Or look at the Planned Features section of the README file.
Write Documentation¶
gerritssh could always use more documentation, whether as part of the official gerritssh docs, in docstrings, or even on the web in blog posts, articles, and such.
Submit Feedback¶
The best way to send feedback is to file an issue at https://github.com/kdopen/gerritssh/issues.
If you are proposing a feature:
- Explain in detail how it would work.
- Keep the scope as narrow as possible, to make it easier to implement.
- Remember that this is a volunteer-driven project, and that contributions are welcome :)
Get Started!¶
Ready to contribute? Here’s how to set up gerritssh for local development.
Fork the gerritssh repo on GitHub.
Create a virtual-environment (you are using vitualenv, aren’t you?)
Clone your fork locally and install the basic requirements:
$ git clone git@github.com:your_name_here/gerritssh.git $ cd gerritssh $ pip install -r requirements.txt
Create a branch for local development:
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
When you’re done making changes, check that your changes pass style and unit tests, including testing other Python versions with tox:
$ tox
To get tox and the other test-related tools, just:
$ pip install -r test-requirements.txt
Note
tox is configured to apply style checks using flake8, including pep8-naming. Line length limits are set to trigger at 79 characters, which will explain some of the seemingly strange layouts of strings and expressions.
Commit your changes and push your branch to GitHub:
$ git add . $ git commit -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature
Don’t expect to get 100% coverage (via make coverage), as there are code sections which only activate on specific versions of Python (a cost of cross-version support).
Submit a pull request through the GitHub website.
Pull Request Guidelines¶
Before you submit a pull request, check that it meets these guidelines:
- The pull request should include tests.
- If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst.
- The pull request should work for Python 2.6, 2.7, 3.3, and 3.4. Check https://travis-ci.org/kdopen/gerritssh under pull requests for active pull requests or run the tox command and make sure that the tests pass for all supported Python versions.
Note
gerritssh uses the git-flow branching model. Please request that your pull-request be merged to the develop branch, and ensure your changes are based on the develop branch.
Testing¶
To run a subset of tests:
$ py.test test/test_<module>.py
where <module> is the name of the actual submodule you wish to test.
To run tests on all Python versions:
$ make test-all
or
$ tox
To ensure that you have not introduced any errors which would only show up when actually communicating with a real Gerrit instance, there are a set of tests which perform no mocking, and actually ‘reach out’ to a live instance. If you have an account with review.openstack.org - and have added your public key - simply run:
$ make test-all-online
or
$ make test-online
If you have an account on a different Gerrit instance, you can test against it instead:
$ GSSH_TEST_INSTANCE='gerrit.mysite.com' tox
or
$ GSSH_TEST_INSTANCE-'gerrit.mysite.com' py.test
Credits¶
Development Lead¶
- Keith Derrick <kderrick_public@att.net>
Indirect Contributors¶
- Eduardo Felipe for his backport of subprocess.check_output to python 2.6. Available at https://gist.github.com/edufelipe/1027906. This was used in the initial development, before switching to paramiko.
- David Pursehouse and the people at Sony Xperia Developer World for their excellent pygerrit repository at https://github.com/sonyxperiadev/pygerrit from which I have taken the core of the ssh.py module to avoid reinventing the wheel in gerritsite.py.
- Scott K Maxwell for providing a cross-version branch of Paramiko. This is available at https://github.com/scottkmaxwell/paramiko/tree/py3-support-without-py25. This has now been merged to master in the main paramiko repository and was included in v1.14 of paramiko.
Direct Contributors¶
None yet. Why not be the first?
Other Implementations¶
Any quick perusal of pypi will show a large collection of existing Python libraries and packages which provide similar features and capabilities. This raises the obvious question, “Why yet another library?”. The answer to that question is many-fold.
- First, see the Rationale above. I needed something to act as a vehicle for this learning exercise. I could hardly take over someone else’s project and experiment with all the things I wanted to try. Gerrit, and its SSH API is something I currently deal with on a daily basis, so this has the small chance of being useful to me.
- The nature of the Open Source community is somewhat darwinian. In almost any area, there are multiple choices and implementations. Eventually, the best ones become widely adopted and over time de-facto standards evolve. I don’t seriously expect this library to reach that level of acceptance, but you never know.
- None of the others worked quite the way I wanted, and I’m not sure my own vision would match that of their owners. And producing my own clone, or wrapping their version would be almost as much work as writing one from scratch.
That’s not to say there are not features and/or ideas in those projects which are not inspiring. I have borrowed shamelessly when it makes sense. See the Indirect Contributors section under Contributing for the appropriate credits.
The following subsections indicate the issues I was concerned with in each implementation.
Openstack’s gerritlib¶
ssh://review.openstack.org/openstack-infra/gerritlib
The underlying implementation has the following shortcomings from my point of view:
- The query and bulk_query operations are broken if a query generates more than 500 results. The actual number is a configuration option for the Gerrit instance but this is typical. If the limit is reached, Gerrit returns a subset of results and provides a sortkey which can be used to fetch the next set. Gerritlib ignores this.
- Every SSH command creates a new session, with the full overhead of logging in. This seems to defeat the value of creating a connection once and then using it for a sequence of commands. My hope was to avoid this overhead once I switched to Paramiko.
- The list of commands is embedded in the main class, making it difficult for library clients to add support for new commands.
It does, however, provide a useful reference in understanding how to use some of Paramiko’s features.
gerrit-cli¶
git@github.com:FlaPer87/gerrit-cli.git
This is basically a command line interface to for python-gerrit.
gerritrestclient¶
git@github.com:lann/gerritrestclient.git
The name says it all. I’m interested in the command line API, not the REST one. Though I may eventually use REST to implement more advanced features.
pygerrit¶
git@github.com:sonyxperiadev/pygerrit.git
This one has many interesting ideas and is pretty close to what I had in mind. Had I been pressed for time, I may well have forked this and bent it to my will. But, as previously mentioned, I really wanted to develop something from scratch.
It still fails with really large result sets, but does reuse the same SSH connection for sequences of commands.
I have borrowed large parts of the ssh module from this library.
python-gerrit¶
git@github.com:FlaPer87/python-gerrit.git
This is a partial implementation, with numerous performance issues. It is also focused on the gerrit review command, which is not particularly of interest to me.
However, the ‘filters’ module (and its representation of AND and OR terms) is simple and elegant. I intend to leverage that in a future version.
Release Notes¶
0.1.3 (2014-06-04)¶
Fixes #4 - Unit tests are not sufficient
Added a baseline set of unit tests which perform end-to-end validation against a live Gerrit instance if GSSH_TEST_INSTANCE is set in the environment.
Corrects a bug found in the ssh client disconnect function by the new tests.
Adds new and extended make targets to better clean and test the package.
Updated documentation accordingly, including expanded testing information.
Removed pypi from the list of environments used on travis-ci.
The tests all run fine under pypi locally, but something in travis’s pypi environment seems to be broken since they started supporting Python 3.4.
0.1.2 (2014-06-03)¶
Fixes #1 - gsshcli.py requires __version__ attribute
Moved VERSION.py to inside the package so the metadata is avaialable to the package and its clients, then modified setup.py and conf.py to use execfile to read the data for their own purposes.
Fixes #2 - gsshcli.py query command fails when –limit option used
The demo script now reconstitues all option arguments as strings.
Fixes #3 - Query command throws TypeError under Python2.7
The JSON responses from the query command are correctly converted to strings in Python 2.x.
Initiates unit-test coverage reporting via coveralls.io
0.1.1 (2014-05-23)¶
- Minor tweak for pip install
0.1.0 (2014-05-23)¶
- First release on PyPI.
gerritssh¶
gerritssh package¶
Subpackages¶
gerritssh.borrowed package¶
Submodules¶
gerritssh.borrowed.ssh module¶
Gerrit SSH Client.
A thin wrapper/extension of Paramiko’s SSHClient class, adding logic to parse the standard configuration file from ~/.ssh.
It also provides lightweight threading protection to allow a single connection to be used by multiple threads.
- class gerritssh.borrowed.ssh.GerritSSHClient(hostname, username=None, port=None, keyfile_name=None)[source]¶
Bases: paramiko.client.SSHClient
Gerrit SSH Client, extending the paramiko SSH Client.
Parameters: - hostname – The host to connect to
- username – The optional user name to use on connection
- port – The optional port to use
- keyfile_name – The optional key file to use
- class gerritssh.borrowed.ssh.SSHCommandResult(command, stdin, stdout, stderr)[source]¶
Bases: object
Represents the results of a command run over SSH.
The three attributes are channels representing the three standard streams.
Parameters: - stdin – The channel’s input channel
- stdout – Standard output channel
- stderr – The error output channel
Module contents¶
gerritssh.internal package¶
Submodules¶
gerritssh.internal.cmdoptions module¶
A set of cooperating classes which allow command implementations to specify and parse the various options which Gerrit supports.
In addition, every option can be assigned a semantic-version compatible specification which identifies the Gerrit versions on which the option is supported. Thus, a command implementation can not only parse its option list with ease, but also identify combinations which are not supported by the site they are being sent to.
Implementing a versioned command has the following requirements (see the ProjectList command for a full implementation).
- Create an OptionSet instance, specify all the supported options. This is best done as a class attribute, as the information is constant for all instances.
- Pass the OptionSet, and list of options to be parsed, to the constructor for the abstract SiteCommand class.
- When the execute_on method is invoked, call check_support_for() in the base class, which will verify all options (and the command itself) are supported in the Gerrit version for the given site.
A complete framework for a command implementation, supported on Gerrit versions 2.7 and above, might look like:
class SomeCommand(SiteCommand):
__options = OptionSet(
Option.flag(...),
Option.choice(...),
Option.valued(...),
Option.flag('needed'))
def __init__(self, options_string):
super(SomeCommand,self).__init__('>=2.7',
SomeCommand.__options,
options_string)
def execute_on(self, site):
# We always need to specify --needed for some reason
self.__parsed.needed = True
# Check the support *after* overriding options
self.check_support_for(site)
return site.execute(' '.join(['some-command',
self.__parsed]).strip())
- class gerritssh.internal.cmdoptions.OptionSet(*args)[source]¶
Bases: object
A set of options supported by a command.
Basically this is currently a wrapper around a tuple that allows for a natural form of creation. It also allows the representation to be changed later without producing widespread changes.
All arguments to the constructor need to be created by calls to the static methods of the Option class:
options = OptionSet(Option.flag(...), Option.choice(...), Option.valud(...), ...)
Raises: TypeError if other types of arguments are created. - options_supported_in(version)[source]¶
Return a subset of the OptionSet containing only those options supported by the provided version.
Parameters: version – A Version object from the semantic_version package. Returns: A filtered OptionSet Raises: TypeError if version is not a semantic_version.Version object
- class gerritssh.internal.cmdoptions.Option[source]¶
Bases: object
This class provides a namespace for static methods that create Option objects for inclusion in an Optionset.
Typically, these are used in initializing an OptionSet as follows:
OptionSet(Option.flag(...), Option.choices(...), Option.values(...))
flags, choices, and valued option definitions each take the following parameters:
Parameters: - long_name – A string providing the long name for the option (without the leading ‘–’)
- short – A string providing the short name for the option (withoutthe leading ‘-‘). This defaults to None.
- repeatable – A boolean keyword argument, defaulting to False. If True, the option can be specified more than once (for example, ‘-vv’ to increase the level of verbosity twice)
- spec – A semantic_version compatible specification, defining which versions support this option. Defaults to ‘all versions’
The specific behavior of each is documented in the option creation methods.
- static choice(long_name, short='', choices=, []**kwargs)[source]¶
Define an option which requires a seleciton from a list of values.
Parameters: choices – A keyword argument providing the list of acceptable values. The selected value is stored as an array if repeatable is True.
Example:
Option.choice('format', 'f', choices=['json', 'text', 'html'])
- static flag(long_name, short='', **kwargs)[source]¶
Create a simple flag option.
Flag options are either boolean, or repeatable.
If repeatable is True, the flags value will represent a count of how often it was found.
Examples:
# An option, '--long' or '-l', which is only supported in version # 2.0.0 or better. Option.flag('long', 'l', spec='>=2.0.0') # An option '--verbose'or '-v' which can specified many times Option.flag('--verbose','-v', repeatable=True)
- class gerritssh.internal.cmdoptions.CmdOptionParser(option_set)[source]¶
Bases: object
A parser configured for a given OptionSet
Parameters: option_set – An initialized OptionSet instance Raises: TypeError if option_set is not an OptionSet
Module contents¶
Submodules¶
gerritssh.bancommit module¶
Implements the ban-commit command
- class gerritssh.bancommit.BanCommit(project, commit, option_str='')[source]¶
Bases: gerritssh.gerritsite.SiteCommand
Obtain a list of all(visible) groups on a site
Parameters: - project – The repository name containingg the commit
- commit – The SHA-1 for the commit to be banned
- option_str – List of options to pass to the command
gerritssh.gerritsite module¶
Representations of a Gerrit site, and the abstract base class for all executable commands.
All sessions with a Gerrit instance begin by creating a Site object and establishing a connection:
import gerritssh as gssh
mysite = gssh.Site('gerrit.exmaple.com').connect()
Commands are executed by creating an instance of a SiteCommand concrete class, and then executing them against the Site object. The following snippet will connect to a site, and then print out a list of all open reviews by project:
import gerritssh as gssh
mysite = gssh.Site('gerrit.example.org').connect()
lsprojects = gssh.ProjectList()
lsprojects.execute_on(mysite)
for p in lsprojects:
openp = gssh.open_reviews(project=p).execute_on(mysite)
if not openp:
continue
print('\n{0}\n{1}\n'.format(p, '=' * len(p)))
for r in openp:
print('{0}\t{1}\n'.format(r.ref, r.summary))
This example also shows both ways of iterating over the results from executing a command. The line for p in lsprojects iterates directly over the ProjectList object, while the line for r in openp: iterates over the list of results returned by calling execute_on
Note
This module was original called simply ‘site’, but that clashed with the built in site module which is automatically imported during initialization. This lead to strange failures during runs of tox that took a little while to debug.
- class gerritssh.gerritsite.Site(sitename, username=None, port=None, keyfile=None)[source]¶
Bases: object
An individual Gerrit site.
An object of this class manages all access, execution of commands, etc.
Parameters: - sitename (str) – The top level URL for the site, e.g. ‘gerrit.example.com’
- username – The optional user to log in as
- port – The optional port to connect on
- keyfile – The optional file containing the SSH key to use
Raises: TypeError if sitename is not a string
Usage:
import gerritssh try: mysite = gerritssh.Site('gerrit.example.com').connect() msg = 'Connected to {}, running Gerrit version {}' print(msg.format(mysite.site, mysite.version) except gerritssh.SSHConnectionError: print('Failed to connect to site '+mysite.site)
- connect()[source]¶
Establish an SSH connection to the site
Returns: self to allow chaining Raises: SSHConnectionError if it is not possible to connect to the site
- copy()[source]¶
Construct an unconnected copy of this Site.
This can be used to create additional Site instances from one which has already been initialized. An obvious use would be to open multiple connections to the same site, from a point in the code which is not aware of the initial values used to identify the Gerrit instance.
for example:
# In the command line parsing module site = gerritssh.Site(sitename, username, port).connect() ... # In another module: def new_connection(asite): return asite.copy().connect()
This method is aliased by __copy__ and __deepcopy__ and allows Site objects to be safely used with copy.copy() and copy.deepCopy()
- execute(cmd)[source]¶
Execute a command and return the results
Parameters: cmd – The command to execute as either a SiteComand object, or a string. If a SiteCommand object is passed in, double-dispatch is used to evaluate the command. Otherwise, the string is treated as a valid command string and executed directly. Returns [str]: A list of stripped strings containing the output of the command. Raises: InvalidCommandError if the cmd object does not report a valid command Raises: SSHConnectionError if there is no current connection to the site Raises: CalledProcessError if the command returns an error
- site[source]¶
The original site name provided to the constructor
This needs to be an immutable attribute of the instance once it is created,hence the definition of a ‘read-only’ property.
- version[source]¶
After connection, provides the version of Gerrit running on the site.
Returns: A semantic_version Version object containing the values extracted from the response to a ‘gerrit version’ command. Before connecting, or if a valid version number can not be found in the response from Gerrit, it has the value ‘0.0.0’.
This needs to be an immutable attribute of the instance once it is created,hence the definition of a ‘read-only’ property.
- version_in(constraint)[source]¶
Does the site’s version match a constraint specifier.
Client’s are free to roll their own tests, but this method makes it unnecessary for them to actually import the semantic_version module directly.
Parameters: constraint (str) – A requirement specification conforming to the Semantic Version package’s documentation at
http://pythonhosted.org/semantic_version/#requirement-specification
Returns: True if the site’s version satisfies the requirement. Raises: SSHConnectionError if there is no active connection - Usage::
- s=Site(‘example.gerrit.com’).connect() # Check that the site is running Gerrit 2.5 or later s.version_in(‘>=2.5’) # Check that the site is running 2.6, 2.7, or 2.8 s.version_in(‘>=2.6,<2.9’)
- exception gerritssh.gerritsite.SSHConnectionError[source]¶
Bases: gerritssh.GerritsshException
Raised when a Site object fails to connect via SSH, or when a method is called on an unconnected site which requires a connection.
- exception gerritssh.gerritsite.InvalidCommandError[source]¶
Bases: gerritssh.GerritsshException
Raised when an attempt is made to execute a BaseCommand object.
- class gerritssh.gerritsite.SiteCommand(cmd_supported_in, option_set, option_str)[source]¶
Bases: abc.newbase
Base class for a command to be executed against a Site
This is not meant to be used directly by clients. Instead is allows for duck-typing of sub-classes representing the various Command Line tools supported by Gerrit. Clients can use this to support commands which are missing from the release version of gerritssh or to create macro commands.
The key method to override is execute_on() which uses the provided Site object to actually implement the command. The method returns its results, usually as an iterable. The parameters for the command are meant to be provided to the constructor of the concrete class.
On completion, the execute_on method should store its results in self._results as an iterable object, to allow iteration over the object.
The constructor creates a parser and parses the provided options string, storing the results in self._parsed_options.
For example, a minimal class to represent the ls-projects command, with the response in JSON format (on a site which supports it) might declare the method as follows:
class JSONProjects(SiteCommand): def __init__(self): super(JSONProjects,self).__init__() def execute_on(self, site): self._results = site.execute('ls-projects') return self._results
and be used thus:
site=Site('gerrit.example.com').connect() cmd=JSONProjects() projects = cmd.execute_on(site)
or, the command object can be passed to the site (useful in building macro operations):
site=Site('gerrit.example.com').connect() cmd=JSONProjects() projects = site.execute(cmd)
Either way, providing the SiteCommand class sets _results properly, the caller can then iterate over the results in two ways. By directly iterating over the returned value:
projects = site.execute(cmd) for p in projects: pass
or, by iterating over the command object itself:
site.execute(cmd) # or cmd.execute_on(site) for p in cmd: pass
Parameters: - cmd_supported_in –
The semantic-version compliant version specification defining which Gerrit versions support the command.
If not specified, or specified as None, defaults to ‘>=2.4’
- option_set –
An OptionSet instance defining the options supported by the command
If not specfied, or given as None, no options will be parsed. You can not provide an option_str argument without an OptionSet.
- option_str –
The options to be parsed and passed to the Gerrit site.
Defaults to ‘’ if omitted or given as None.
Raises: TypeError if option_set is not an OptionSet instance
Raises: ValueError if option_str is specified without an option_set
Raises: SystemExit if the option_str fails to parse
- check_support_for(site)[source]¶
Validate that the provided site supports the command and all provided options.
Parameters: site – A connected Site instance Raises: NotImplementedError If the command or one of the options are unsupported on the site.
- execute_on(the_site)[source]¶
Execute the command on the given site
This method must be overridden in concrete classes, and thus the base class implementation is guaranteed to raise an exception.
Raises: TypeError
- static text_to_json(text_or_list)[source]¶
Convert one or more JSON strings to a list of dictionaries.
Every string is split and stripped (via text_to_list()) before decoding. All empty strings (or substrings) are ignored.
Parameters: text_or_list – Either a single string, or a list of strings to be interpreted as JSON. Returns [dict]: A list of dictionaries, one per string, produced by interpreting each string JSON. Raises: TypeError if text_or_list` is not one or more strings or if one of the strings can’t be decoded as valid JSON.
- static text_to_list(text_or_list, nonempty=False)[source]¶
Split a single string containing embedded newlines into a list of trimmed strings
Useful for cleaning up multi-line output from commands. Note that a list of strings (perhaps the output from multiple commands) will be flattened to a single list.
Parameters: - text_or_list (str) – Either a string with embedded newlines, or a list or tuple of strings with embedded newlines.
- nonempty (bool) – If true, all empty lines will be removed from the output.
Returns [str]: List of stripped strings, one string per embedded line.
Raises: TypeError if text_or_list contains anything other than strings.
- Usage::
>>> SiteCommand.text_to_list('a\n \nb') ['a', '', 'b'] >>> SiteCommand.text_to_list('a\n \nb\n', True) ['a', 'b'] >>> SiteCommand.text_to_list(['a\nb','c\nd']) ['a','b','c','d']
- cmd_supported_in –
gerritssh.lsgroups module¶
Implements the ls-groups command
- class gerritssh.lsgroups.ListGroups(option_str='')[source]¶
Bases: gerritssh.gerritsite.SiteCommand
Obtain a list of all(visible) groups on a site
Parameters: option_str – List of options to pass to the command
gerritssh.lsmembers module¶
Implements the ls-groups command
- class gerritssh.lsmembers.ListMembers(group, option_str='')[source]¶
Bases: gerritssh.gerritsite.SiteCommand
Obtain a list of all members of a given group
Parameters: - group – The group name
- option_str – List of options to pass to the command
Raises: SystemExit if the option string fails to parse.
Raises: ValueError if the group is not provided
Raises: AttributeError if the group is not a string
- execute_on(the_site)[source]¶
Parameters: the_site – A Site representing the site to search Returns: A list of dictionaries, one per member, with the keys id, username, fullname, and email. Raises: NotImplementedError If the site does not support the command, or a specified option Raises: InvalidGroupError if the command returns an error line
- exception gerritssh.lsmembers.InvalidGroupError[source]¶
Bases: gerritssh.GerritsshException
gerritssh.lsprojects module¶
Miscellaneous SiteCommand classes for simple commands
- class gerritssh.lsprojects.ProjectList(option_str='')[source]¶
Bases: gerritssh.gerritsite.SiteCommand
Obtain a list of all(visible) projects on a site
Parameters: option_str – List of options to pass to the command
gerritssh.query module¶
Commands for querying code review objects on a Gerrit Site
Specifically, the Query command encapsulates the ‘query’ command line utility.
Some common queries are provided in the form of functions which return a prepared Query object. For example, open_reviews reviews a Query prepared to return a complete list of all open code reviews, optionally restricted to a single project:
import gerritssh
s = gerritssh.Site('gerrit.example.com').connect()
r = gerritssh.open_reviews('myproject').execute_on(s)
Following the PEP8 naming conventions, methods which return prepared Query objects will have names in all lowercase. Classes which represent more complex queries will have CamelCase names.
The ‘more complex’ distinction may be necessary if, for example, variants of a command are supported only in specific versions of Gerrit.
- class gerritssh.query.Query(option_str='', query='', max_results=0)[source]¶
Bases: gerritssh.gerritsite.SiteCommand
Command to execute queries on reviews
Parameters: - option_str –
One or more supported options to be passed to the command
note: In order to ensure that the necessary information is returned to allow creation of the Review objects, many of the options will be overridden by execute_on. The following will always be sent: - –current-patch-set
- –patch-sets
- –all-approvals
- –dependencies
- –commit-message
- –format JSON
- query – arguments to the query commands, e.g. ‘status:abandoned owner:self’
- max_results – limit the result set to the first ‘n’. If not given, all results are returned. This may require multiple commands being sent to the Gerrit site, as Gerrit instances often have a built-in limit to the number of results it returns (often around 500).
- option_str –
- gerritssh.query.open_reviews(project=None, branch=None, max_results=0)[source]¶
Query for all open reviews on a site, optionally restricted to a single project and/or branch.
Parameters: - project – If specified, limits the search to a specific project
- branch – If specified, limits the search to a specific branch
- max_results – Limit the result set to the first ‘n’. A value of zero (the default) results in all possible results being returned,
Returns: A list of Review objects
- gerritssh.query.merged_reviews(project=None, branch=None, max_results=0)[source]¶
Query for all merged reviews on a site, optionally restricted to a single project and/or branch.
Parameters: - project – If specified, limits the search to a specific project
- branch – If specified, limits the search to a specific branch
- max_results – Limit the result set to the first ‘n’. A value of zero (the default) results in all possible results being returned,
Returns: A list of Review objects
- gerritssh.query.abandoned_reviews(project=None, branch=None, max_results=0)[source]¶
Query for all abandoned reviews on a site, optionally restricted to a single project and/or branch.
Parameters: - project – If specified, limits the search to a specific project
- branch – If specified, limits the search to a specific branch
- max_results – Limit the result set to the first ‘n’. A value of zero (the default) results in all possible results being returned,
Returns: A list of Review objects
gerritssh.review module¶
Classes to represent a Gerrit code review and its patch sets
Typically, objects of these classes are created by executing Query operations. There is little obvious use for a bare Review or Patchset object.
Both classes override __getattr__ to provide acees to the underling raw JSON. Thus, instead of:
ref = somepatchset.raw['ref']
one can simply do:
ref = somepatchset.ref
It also obviates the need to declare many properties that simply return a field, without needing any manipulation.
However, some properties such as the patchset number, are defined as explicit properties to allow conversion to a more natural type.
As a note for contributors, it might seem to make sense to move these classes into the query module. But it is not difficult to envisage other modules which operate solely on collections of Review or Patchset objects, and do not themselves need to be coupled to the gerritsite or query modules.
Safe for: from review import *
- class gerritssh.review.Review(raw)[source]¶
Bases: object
A single code review, containing all patchsets
Parameters: raw – A dict() representing the raw JSON response from Gerrit Raises: TypeError if raw is not a dictionary Other than in initialization, this class is meant to be read-only so all instance variables are declared with double leading underscores and provided as properties with getters only
Author of the review.
- class gerritssh.review.Patchset(review, raw)[source]¶
Bases: object
A single patch set within a GerritReview
Parameters: - review – The enclosing Review object
- raw – The raw JSON extracted from the Review details
Raises: TypeError if review is not a Review object, or if raw is not a dictionary.
Other than in initialization, this class is meant to be read-only so all instance variables are declared with double leading underscores and provided as properties with getters only.
A library user is not expected to create instances of this class directly. They are created as part of a Review object when processing a response from Gerrit.
Author of the Patchset
Returns: (str) The uploader’s name if available, else their user name.