rel-eng/packages/spacecmd | 2
spacecmd/spacecmd.spec | 7 ++-
spacecmd/src/lib/api.py | 95 +++++++++++++++++++++++++++++++++++++++++++
spacecmd/src/lib/shell.py | 2
spacecmd/src/lib/utils.py | 101 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 204 insertions(+), 3 deletions(-)
New commits:
commit 71ebdded59d86aeacd56fd7ac5e7a0e8bcebf8dd
Author: Aron Parsons <aparsons(a)redhat.com>
Date: Thu Aug 4 17:58:14 2011 -0400
Automatic commit of package [spacecmd] release [1.6.2-1].
diff --git a/rel-eng/packages/spacecmd b/rel-eng/packages/spacecmd
index 754cc38..c8593e3 100644
--- a/rel-eng/packages/spacecmd
+++ b/rel-eng/packages/spacecmd
@@ -1 +1 @@
-1.6.1-1 spacecmd/
+1.6.2-1 spacecmd/
diff --git a/spacecmd/spacecmd.spec b/spacecmd/spacecmd.spec
index 84bb3b8..26e26e0 100644
--- a/spacecmd/spacecmd.spec
+++ b/spacecmd/spacecmd.spec
@@ -4,7 +4,7 @@
%endif
Name: spacecmd
-Version: 1.6.1
+Version: 1.6.2
Release: 1%{?dist}
Summary: Command-line interface to Spacewalk and Satellite servers
@@ -61,6 +61,11 @@ touch %{buildroot}/%{python_sitelib}/spacecmd/__init__.py
%doc %{_mandir}/man1/spacecmd.1.gz
%changelog
+* Thu Aug 04 2011 Aron Parsons <aparsons(a)redhat.com> 1.6.2-1
+- Enable new 'api' module (satoru.satoh(a)gmail.com)
+- add utility routines for new 'api' module (satoru.satoh(a)gmail.com)
+- add api module to spacecmd (satoru.satoh(a)gmail.com)
+
* Fri Jul 22 2011 Jan Pazdziora 1.6.1-1
- We only support version 14 and newer of Fedora, removing conditions for old
versions.
commit 54d2ca9555e706656779bf2ff6cfc077ae376435
Author: Satoru SATOH <satoru.satoh(a)gmail.com>
Date: Fri Jul 29 18:33:48 2011 +0900
Enable new 'api' module
This is the last one to enable new 'api' module in spacecmd.
Signed-Off-By: Satoru SATOH <ssato(a)redhat.com>
diff --git a/spacecmd/src/lib/shell.py b/spacecmd/src/lib/shell.py
index 08d0898..1025048 100644
--- a/spacecmd/src/lib/shell.py
+++ b/spacecmd/src/lib/shell.py
@@ -29,7 +29,7 @@ class SpacewalkShell(Cmd):
'custominfo', 'distribution', 'errata',
'filepreservation', 'group', 'kickstart',
'misc', 'org', 'package', 'repo',
'report', 'schedule',
- 'snippet', 'softwarechannel', 'ssm',
+ 'snippet', 'softwarechannel', 'ssm',
'api',
'system', 'user', 'utils' ]
# a SyntaxError is thrown if we don't wrap this in an 'exec'
commit 5c80e1a30082b2e2e2a6f61ada670f4c91c19955
Author: Satoru SATOH <satoru.satoh(a)gmail.com>
Date: Fri Jul 29 18:28:33 2011 +0900
add utility routines for new 'api' module
This patch adds some utility routines needed for new 'api' module in
spacecmd.
Its all doctests look OK as far as I tested. Here is a test log:
$ PYTHONPATH=spacecmd/src/lib nosetests --with-doctest -vv \
spacecmd/src/lib/utils.py
Doctest: utils.parse_api_args ...
ok
Doctest: utils.parse_list_str ... ok
Doctest: utils.parse_str ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.020s
OK
$
Signed-Off-By: Satoru SATOH <ssato(a)redhat.com>
diff --git a/spacecmd/src/lib/utils.py b/spacecmd/src/lib/utils.py
index 3768647..a8fd5ee 100644
--- a/spacecmd/src/lib/utils.py
+++ b/spacecmd/src/lib/utils.py
@@ -26,6 +26,12 @@ from optparse import OptionParser
from tempfile import mkstemp
from textwrap import wrap
+try:
+ import json
+except ImportError:
+ import simplejson as json # python < 2.6
+
+
__EDITORS = ['vim', 'vi', 'nano', 'emacs']
def parse_arguments(args, options = []):
@@ -462,4 +468,99 @@ def read_file(filename):
return contents
+
+def parse_str(s, type_to=None):
+ """
+ Similar to 'read :: Read a => String -> a' in Haskell.
+
+ >>> parse_str('1234567', int)
+ 1234567
+ >>> parse_str('1234567')
+ 1234567
+ >>> parse_str('abcXYZ012')
+ 'abcXYZ012'
+ >>> d = dict(channelLabel="foo-i386-5")
+ >>> d = parse_str('{"channelLabel":
"foo-i386-5"}')
+ >>> assert d["channelLabel"] == 'foo-i386-5'
+
+ """
+ try:
+ if type_to is not None and isinstance(type_to, type):
+ return type_to(s)
+
+ elif re.match(r'[1-9]\d*', s):
+ return int(s)
+
+ elif re.match(r'{.*}', s):
+ return json.loads(s) # retry with json module
+
+ else:
+ return str(s)
+
+ except ValueError:
+ return str(s)
+
+
+def parse_list_str(list_s, sep=","):
+ """
+ simple parser for a list of items separated with "," (comma) or given
+ separator chars.
+
+ >>> assert parse_list_str("") == []
+ >>> assert parse_list_str("a,b") == ["a",
"b"]
+ >>> assert parse_list_str("a,b,") == ["a",
"b"]
+ >>> assert parse_list_str("a:b:", ":") ==
["a", "b"]
+ """
+ return [p for p in list_s.split(sep) if p]
+
+
+def parse_api_args(args, sep=','):
+ """
+ Simple JSON-like expression parser.
+
+ :param args: a list of strings may be separated with sep, and each
+ string represents parameters passed to API later.
+ :type args: `str`
+
+ :param sep: A char to separate paramters in `args`
+ :type sep: `str`
+
+ :rtype: rpc arg objects, [arg] :: [string]
+
+ >>> parse_api_args('')
+ []
+ >>> parse_api_args('1234567')
+ [1234567]
+ >>> parse_api_args('abcXYZ012')
+ ['abcXYZ012']
+
+ >>> assert parse_api_args('{"channelLabel":
"foo-i386-5"}')[0]["channelLabel"] == "foo-i386-5"
+
+ >>> (i, s, d) =
parse_api_args('1234567,abcXYZ012,{"channelLabel":
"foo-i386-5"}')
+ >>> assert i == 1234567
+ >>> assert s == "abcXYZ012"
+ >>> assert d["channelLabel"] == "foo-i386-5"
+
+ >>> (i, s, d) =
parse_api_args('[1234567,"abcXYZ012",{"channelLabel":
"foo-i386-5"}]')
+ >>> assert i == 1234567
+ >>> assert s == "abcXYZ012"
+ >>> assert d["channelLabel"] == "foo-i386-5"
+ """
+ if not args:
+ return []
+
+ try:
+ x = json.loads(args)
+ ret = isinstance(x, list) and x or [x]
+
+ except ValueError:
+ ret = [parse_str(a) for a in parse_list_str(args, sep)]
+
+ return ret
+
+
+def json_dump(obj, fp, indent=2, **kwargs):
+ json.dump(obj, fp, ensure_ascii=False, indent=indent, **kwargs)
+
+
# vim:ts=4:expandtab:
commit 05ba31a7e3b4aec724316d8ce70725e977a10b3f
Author: Satoru SATOH <satoru.satoh(a)gmail.com>
Date: Fri Jul 29 18:20:04 2011 +0900
add api module to spacecmd
This patch adds 'api' module into spacecmd.
Signed-Off-By: Satoru SATOH <ssato(a)redhat.com>
diff --git a/spacecmd/src/lib/api.py b/spacecmd/src/lib/api.py
new file mode 100644
index 0000000..0c1d05c
--- /dev/null
+++ b/spacecmd/src/lib/api.py
@@ -0,0 +1,95 @@
+#
+# Licensed under the GNU General Public License Version 3
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright 2011 Satoru SATOH <ssato(a)redhat.com>
+#
+
+from optparse import Option
+from spacecmd.utils import *
+
+import sys
+import logging
+
+
+def help_api(self):
+ print 'api: call RHN API with arguements directly'
+ print '''usage: api [options] API_STRING
+
+options:
+ -A, --args Arguments for the API other than session id in comma separated
+ strings or JSON expression
+ -F, --format Output format
+ -o, --output Output file
+
+examples:
+ api api.getApiCallList
+ api --args "sysgroup_A" systemgroup.listSystems
+ api -A "rhel-i386-server-5,2011-04-01,2011-05-01" -F "%(name)s" \\
+ channel.software.listAllPackages
+'''
+
+
+def do_api(self, args):
+ options = [ Option('-A', '--args', default=''),
+ Option('-F', '--format', default=''),
+ Option('-o', '--output', default='') ]
+
+ (args, options) = parse_arguments(args, options)
+
+ if not args:
+ self.help_api()
+ return
+
+ api_name = args[0]
+ api_args = parse_api_args(options.args)
+
+ if options.output:
+ try:
+ output = open(options.output, "w")
+ except IOError:
+ logging.warn("Could not open to write: " + options.output)
+ logging.info("Fallback output to stdout")
+
+ output = sys.stdout
+ else:
+ output = sys.stdout
+
+ api = getattr(self.client, api_name, None)
+
+ if not callable(api):
+ logging.warn("No such API: " + api_name)
+ return
+
+ try:
+ res = api(self.session, *api_args)
+
+ if not isinstance(res, list):
+ res = [res]
+
+ if options.format:
+ for r in res:
+ output.write(options.format % r + "\n")
+ else:
+ json_dump(res, output, indent=2)
+
+ output == sys.stdout or output.close()
+
+ except:
+ output == sys.stdout or output.close()
+
+
+# vim:ts=4:expandtab: