Skip to content

Commit 0431030

Browse files
committed
Initial commit
0 parents  commit 0431030

22 files changed

Lines changed: 1087 additions & 0 deletions

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.*
2+
!.editorconfig
3+
!.travis*
4+
!.git*
5+
6+
# Python
7+
/dist
8+
/build
9+
*.pyc
10+
*.pyo
11+
*.egg*

.travis.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
sudo: false
2+
language: python
3+
python:
4+
- '2.7'
5+
install:
6+
- travis_retry pip install -r requirements.txt
7+
- travis_retry pip install -r test-requirements.txt
8+
before_script: pep8 --max-line-length=120
9+
script: python setup.py test --addopts '-vv'
10+
deploy:
11+
provider: pypi
12+
user: bgaifullin
13+
password:
14+
secure: e6aJZA7Bzc45IVwZ0+Lv/Peav3QF4gFmsOW4TeZwRKZ8ElBBFs6nMW+mu7WwyhB/aGIYcaJ/mjY2/xBFy3zn4vGNpeMy7rbVrExIhRTGuYOXU+PLnorSoCj4QZGcza+k6s5a8wdDciCQWRxvxBm9ztDYolqYb+z0SqE1yRjcS1rTh+YjuYGqh2OOG0JnxQoucaJ4kBVaeoU3jvTvCx3pja8IfVN9e0nWnXDbjqpCJaBzgH0q3bbxvExflueX+EtV3/rm7Ak2kDegdy/C6IiQg69LJXPzqifgE4X+Vi12F6CLpUp5oEIawQcUq8woIK9q8Gdm8v0O2Fit1kTNaVya4wKsyYku7AJ85pLVeM12baZXEYQA+2HyHeqEFlRLw7Y2hy8hUFKNGeiKFEk7GzJI7UspQCkeW4QtgB+lyvtUOK6NQYK1RyMGlh8wQiiYlhpnE2sAerE9dh8+0FYCxSkH0wBGjOCMq8+/WkUy/pTrWzVJfM9LISkE9gPkPpQ4LXpQD9b39R55qTNOGpHlwqGY4zr3F0d2oibPLi5xFD8GQpZEiSCcYNiffkqhjb4CAaVc6zowkeIY99qqQ+Ie3KFlbJ1GW8utzxP2GDmW+YJVYI+9qWiGiiboskX05/udbof6wWd4vpaNK1kUKc+oDyTm3Q/bq2YO/Ns9n3TUvZJdvfc=
15+
on:
16+
tags: true
17+
distributions: sdist bdist_wheel
18+
repo: bgaifullin/python-jiractl

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2014 Ryan Leckey
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is furnished
10+
to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MANIFEST.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
include ChangeLog
2+
3+
include README.rst
4+
include *requirements.txt
5+
6+
global-exclude *.pyc

README.rst

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
python-jiractl
2+
==============
3+
4+
.. image:: https://travis-ci.org/bgaifullin/python-jiractl.png?branch=master
5+
:target: https://travis-ci.org/bgaifullin/python-jiractl
6+
.. image:: https://img.shields.io/pypi/v/jiractl.svg
7+
:target: https://pypi.python.org/pypi/jiractl
8+
9+
10+
The command line interface for Jira REST API
11+
12+
******
13+
Usage
14+
******
15+
16+
************
17+
Requirements
18+
************
19+
- jira>=1.0.10
20+
- pbr>=1.6
21+
- cliff>=1.18.0
22+
23+
*******
24+
Install
25+
*******
26+
27+
Automated
28+
---------
29+
1. **jiractl** can be installed through `easy_install` or `pip`.
30+
31+
.. code-block:: bash
32+
33+
pip install jiractrl
34+
35+
36+
Manual
37+
------
38+
39+
1. Clone the **xmlsec** repository to your local computer.
40+
41+
.. code-block:: bash
42+
43+
git clone git://github.com/bgaifullin/python-jiractrl.git
44+
45+
2. Change into the **jiractrl** root directory.
46+
47+
.. code-block:: bash
48+
49+
cd /path/to/jiractrl
50+
51+
52+
3. Install the project and all its dependencies using `pip`.
53+
54+
.. code-block:: bash
55+
56+
pip install .
57+
58+
59+
*******
60+
License
61+
*******
62+
63+
Unless otherwise noted, all files contained within this project are liensed under the MIT opensource license.
64+
See the included file LICENSE or visit `opensource.org <http://opensource.org/licenses/MIT>`_ for more information.

jiractl/__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
This file is part of jiractl
3+
4+
The above copyright notice and this permission notice shall be included in all
5+
copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
13+
SOFTWARE.
14+
"""
15+
16+
import pbr.version
17+
18+
try:
19+
__version__ = pbr.version.VersionInfo(__package__).version_string()
20+
except Exception:
21+
__version__ = "0.0.0"

jiractl/app.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""
2+
This file is part of jiractl
3+
4+
The above copyright notice and this permission notice shall be included in all
5+
copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
13+
SOFTWARE.
14+
"""
15+
16+
from cliff import app
17+
from cliff.commandmanager import CommandManager
18+
import jira
19+
20+
import jiractl
21+
22+
23+
class JiraApp(app.App):
24+
"""Main cliff application class.
25+
26+
Performs initialization of the command manager and
27+
configuration of basic engines.
28+
"""
29+
30+
_jira = None
31+
32+
def build_option_parser(self, description, version, argparse_kwargs=None):
33+
"""Specifies global options."""
34+
parser = super(JiraApp, self).build_option_parser(
35+
description=description, version=version, argparse_kwargs=argparse_kwargs
36+
)
37+
38+
parser.add_argument(
39+
"-s", "--server",
40+
metavar="URL",
41+
help="The Jira URL",
42+
)
43+
parser.add_argument(
44+
"-u", "--user",
45+
metavar="USERNAME",
46+
help="Jira user"
47+
)
48+
parser.add_argument(
49+
"-p", "--password",
50+
metavar="PASSWORD",
51+
help="Jira password"
52+
)
53+
return parser
54+
55+
@property
56+
def jira(self):
57+
if self._jira is None:
58+
self._jira = jira.JIRA(server=self.options.server, basic_auth=(self.options.user, self.options.password))
59+
return self._jira
60+
61+
62+
def run_app(cmd_mgr, argv=None):
63+
"""Runs application."""
64+
return JiraApp(
65+
description="The command line interface for Jira REST API",
66+
version=jiractl.__version__,
67+
command_manager=cmd_mgr,
68+
deferred_help=True
69+
).run(argv)
70+
71+
72+
def main(argv=None):
73+
"""Entry point."""
74+
return run_app(CommandManager(__package__, convert_underscores=True), argv)
75+
76+
77+
def debug(name, cmd_class, argv=None):
78+
"""Helper for debugging single command without package installation."""
79+
import sys
80+
81+
if argv is None:
82+
argv = sys.argv[1:]
83+
84+
argv = [name] + argv + ["-v", "-v", "--debug"]
85+
cmd_mgr = CommandManager(__package__, convert_underscores=True)
86+
cmd_mgr.add_command(name, cmd_class)
87+
88+
return run_app(cmd_mgr, argv)

jiractl/commands/__init__.py

Whitespace-only changes.

jiractl/commands/base.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
This file is part of jiractl
3+
4+
The above copyright notice and this permission notice shall be included in all
5+
copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
13+
SOFTWARE.
14+
"""
15+
16+
from cliff import command
17+
from cliff import lister
18+
from cliff import show
19+
20+
21+
def utf8(text):
22+
"""Converts text to utf8 encoded string"""
23+
return unicode(text, "utf8")
24+
25+
26+
class JiraCommand(command.Command):
27+
"""Executes command."""
28+
29+
30+
class JiraShow(show.ShowOne):
31+
"""Executes command and displays result for one element."""
32+
33+
34+
class JiraList(lister.Lister):
35+
"""Executes command and displays list of elements."""

jiractl/commands/comments.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""
2+
This file is part of jiractl
3+
4+
The above copyright notice and this permission notice shall be included in all
5+
copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
13+
SOFTWARE.
14+
"""
15+
16+
from jiractl.commands import base
17+
18+
19+
class JiraCommentMixin(object):
20+
columns = ("id", "updated", "author", "body")
21+
22+
def get_parser(self, prog_name):
23+
parser = super(JiraCommentMixin, self).get_parser(prog_name)
24+
parser.add_argument("--issue", type=base.utf8, help="Issue ID", required=True)
25+
return parser
26+
27+
@staticmethod
28+
def format_comment(comment):
29+
"""Converts issue comment to tuple."""
30+
return comment.id, comment.updated, comment.author.name, comment.body
31+
32+
33+
class ListComments(JiraCommentMixin, base.JiraList):
34+
"""Gets all comments for issue."""
35+
36+
def take_action(self, parsed_args):
37+
"""Get issue by id."""
38+
return self.columns, [self.format_comment(x) for x in self.app.jira.comments(parsed_args.issue)]
39+
40+
41+
class AddComment(JiraCommentMixin, base.JiraShow):
42+
"""Adds new comment."""
43+
44+
def get_parser(self, prog_name):
45+
parser = super(AddComment, self).get_parser(prog_name)
46+
parser.add_argument("--body", type=base.utf8, help="Comment", required=True)
47+
parser.add_argument(
48+
"--visibility", type=base.utf8, metavar="TYPE:VALUE", help="Visibility of issue. format %(metavar)"
49+
)
50+
return parser
51+
52+
def take_action(self, parsed_args):
53+
"""Adds new comment."""
54+
visibility = None
55+
if parsed_args.visibility:
56+
visibility = dict(zip(("type", "value"), parsed_args.visibility.split(":", 2)))
57+
58+
comment = self.app.jira.add_comment(parsed_args.issue, parsed_args.body, visibility=visibility)
59+
return self.columns, self.format_comment(comment)
60+
61+
62+
class EditComment(JiraCommentMixin, base.JiraCommand):
63+
"""Edit comment."""
64+
65+
def get_parser(self, prog_name):
66+
parser = super(EditComment, self).get_parser(prog_name)
67+
parser.add_argument("--id", type=base.utf8, help="Comment ID", required=True)
68+
parser.add_argument("--body", type=base.utf8, help="Comment", required=True)
69+
parser.add_argument("--visibility", type=base.utf8, help="Visibility in format type:value")
70+
return parser
71+
72+
def take_action(self, parsed_args):
73+
"""Get issue by id."""
74+
visibility = None
75+
if parsed_args.visibility:
76+
visibility = dict(zip(("type", "value"), parsed_args.visibility.split(":", 2)))
77+
78+
comment = self.app.jira.comment(parsed_args.issue, parsed_args.id)
79+
comment.update(body=parsed_args.body, visibility=visibility)
80+
self.app.stdout.write("Done.\n")
81+
82+
83+
class ShowComment(JiraCommentMixin, base.JiraShow):
84+
"""Shows one comment."""
85+
86+
def get_parser(self, prog_name):
87+
parser = super(ShowComment, self).get_parser(prog_name)
88+
parser.add_argument("--id", type=base.utf8, help="Comment ID", required=True)
89+
return parser
90+
91+
def take_action(self, parsed_args):
92+
"""Get issue by id."""
93+
return self.columns, self.format_comment(self.app.jira.comment(parsed_args.issue, parsed_args.id))

0 commit comments

Comments
 (0)