import sys
import urllib2
from optparse import OptionParser
from pprint import pprint

from allura.lib import rest_api


def parse_options():
    optparser = OptionParser(usage=''' %prog --api-key= --secret-key= <JSON dump>

Import project data dump in JSON format into Allura project.''')
    optparser.add_option('-a', '--api-key', dest='api_key', help='API key')
    optparser.add_option('-s', '--secret-key', dest='secret_key', help='Secret key')
    optparser.add_option('-u', '--base-url', dest='base_url', default='https://sourceforge.net', help='Base Allura URL (%default)')
    optparser.add_option('--validate', dest='validate', action='store_true', help='Validate import data')
    options, args = optparser.parse_args()
    if len(args) != 1:
        optparser.error("Wrong number of arguments.")
    if not options.api_key or not options.secret_key:
        optparser.error("Keys are required.")
    return options, args


class RestClient(rest_api.RestClient):

    def call(self, method, url, **params):
        try:
            return self.request(method, url, **params)
        except urllib2.HTTPError, e:
            error_content = e.fp.read()
            e.msg += '. Error response:\n' + error_content
            raise e

    
if __name__ == '__main__':
    options, args = parse_options()
    if options.validate:
        url = '/rest/p/test/bugs/validate_import'
    else:
        url = '/rest/p/test/bugs/perform_import'

    cli = RestClient(base_uri=options.base_url, api_key=options.api_key, secret_key=options.secret_key)
    print cli.call('POST', url, doc=open(args[0]).read())

@@ -17,17 +17,74 @@
 t urllib
-2
+%0Aimport urllib2%0Aimport urlparse%0Aimport hmac%0Aimport hashlib
 %0Afrom op
@@ -140,40 +140,37 @@
 int%0A
-%0A
 from 
-allura.lib import rest_api
+datetime import datetime
 %0A%0A%0Ad
@@ -989,16 +989,22 @@
 %0A%0Aclass 
+Allura
 RestClie
@@ -1010,140 +1010,828 @@
 ent(
-rest_api.RestClient):%0A%0A    def call(self, method, url, **params):%0A        try:%0A            return self.request(method, url, **params
+object):%0A%0A    def __init__(self, base_url, api_key, secret_key):%0A        self.base_url = base_url%0A        self.api_key = api_key%0A        self.secret_key = secret_key%0A        %0A    def sign(self, path, params):%0A        params.append(('api_key', self.api_key))%0A        params.append(('api_timestamp', datetime.utcnow().isoformat()))%0A        message = path + '?' + urllib.urlencode(sorted(params))%0A        digest = hmac.new(self.secret_key, message, hashlib.sha256).hexdigest()%0A        params.append(('api_signature', digest))%0A        return params%0A%0A    def call(self, url, **params):%0A        url = urlparse.urljoin(options.base_url, url)%0A        params = self.sign(urlparse.urlparse(url).path, params.items())%0A%0A        try:%0A            result = urllib2.urlopen(url, urllib.urlencode(params))%0A            return result.read(
 )%0A  
@@ -1899,11 +1899,8 @@
 = e.
-fp.
 read
@@ -2195,16 +2195,22 @@
   cli = 
+Allura
 RestClie
@@ -2216,17 +2216,8 @@
 ent(
-base_uri=
 opti
@@ -2234,16 +2234,8 @@
 rl, 
-api_key=
 opti
@@ -2251,19 +2251,8 @@
 ey, 
-secret_key=
 opti
@@ -2290,16 +2290,8 @@
 all(
-'POST', 
 url,

Add self-contained Allura REST client, based on wiki-post.py