#/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import requests
import argparse

from gevent.pool import Pool
from collections import defaultdict
from sys import exit
from sys import stdout


_methods = 'GET', 'POST'
_stats = defaultdict(list)


# TODO: fix bug AttributeError: 'Greenlet' object has no attribute '_run'
def call(method, url):
    start = time.time()
    res = method(url)
    _stats[res.status_code].append(time.time()-start)


class Overload(object):

    def __init__(self, url, method='GET', concurrency=1, numbers=1, **options):
        self.url = url
        self.method = method
        self.concurrency = concurrency
        self.numbers = numbers
        self.options = options

    @property
    def run(self):
        self.method = getattr(requests, self.method.lower())
        start = time.time()
        pool = Pool(self.concurrency)
        for number in xrange(self.numbers):
            pool.spawn(call, self.method, self.url)
        pool.join()
        self.time_process = time.time() - start

    @property
    def stats(self):
        self.total = sum([len(_stats[key]) for key in _stats.iterkeys()])
        self.total_success = len(_stats[200])
        self.min = min(_stats[200])
        self.max = max(_stats[200])

    @property
    def output(self):
        stdout.write('Concurrency level: {}\n'.format(self.concurrency))
        stdout.write('Number process requests: {}\n'.format(self.total))
        stdout.write('Time taken for tests: {:.2f}\n\n'.format(self.time_process))
        stdout.write('Complete requests: {}\n'.format(self.total_success))
        stdout.write('Failed requests: {}\n\n'.format(self.total-self.total_success))
        stdout.write('Faster request: {:.3f}\n'.format(self.min))
        stdout.write('Slower request: {:.3f}\n'.format(self.max))


if __name__ == '__main__':
    # parser
    parser = argparse.ArgumentParser(description='Overload benchmark')
    parser.add_argument('url', metavar='url', type=str, nargs='+', help='URL you want overload')
    parser.add_argument('-m', dest='method', default='GET', type=str, help='HTTP method')
    parser.add_argument('-c', dest='concurrency', default=1, type=int, help='Number of multiple requests to perform at a time. Default is one request at a time')
    parser.add_argument('-n', dest='numbers', default=1, type=int, help='''Number of requests to perform for the benchmarking session. The default is to just perform a single request which usually leads to non-representative benchmarking results''')
    args = parser.parse_args()

    # arguments
    url = args.url[0]
    method = args.method
    concurrency = args.concurrency
    numbers = args.numbers

    # app
    overload = Overload(url, method=method, concurrency=concurrency, numbers=numbers)
    overload.run
    overload.stats
    overload.output

@@ -39,16 +39,62 @@
 -8 -*-%0A%0A
+from gevent import monkey%0Amonkey.patch_all()%0A%0A
 import t
@@ -295,16 +295,157 @@
 list)%0A%0A%0A
+def progress(func):%0A    def wrapper(*args):%0A        stdout.write('-')%0A        stdout.flush()%0A        return func(*args)%0A    return wrapper%0A%0A%0A
 # TODO: 
@@ -510,16 +510,26 @@
  '_run'%0A
+@progress%0A
 def call
@@ -543,16 +543,29 @@
 , url):%0A
+    try:%0A    
     star
@@ -584,16 +584,20 @@
 e()%0A    
+  
+  
 res = me
@@ -614,26 +614,113 @@
     
-_stats%5Bres.
+    code = res.status_code%0A    except Exception as error:%0A        code = 404%0A    finally:%0A        _
 stat
-us_
+s%5B
 code
@@ -1033,32 +1033,49 @@
  def run(self):%0A
+        try:%0A    
         self.met
@@ -1119,32 +1119,36 @@
 ower())%0A        
+ 
+   
 start = time.tim
@@ -1143,32 +1143,93 @@
 t = time.time()%0A
+            stdout.flush()%0A            stdout.write('%5B')%0A    
         pool = P
@@ -1250,16 +1250,20 @@
 rrency)%0A
+    
         
@@ -1306,24 +1306,28 @@
             
+   
+ 
 pool.spawn(c
@@ -1358,24 +1358,28 @@
 rl)%0A        
+    
 pool.join()%0A
@@ -1378,16 +1378,20 @@
 .join()%0A
+    
         
@@ -1429,16 +1429,200 @@
  - start
+%0A            stdout.flush()%0A            stdout.write('%5D')%0A        except Exception as error:%0A            stdout.write('error during run process (%7B%7D)'.format(error))%0A            exit(1)
 %0A%0A    @p
@@ -1841,16 +1841,73 @@
 ts%5B200%5D)
+%0A        self.moy = sum(_stats%5B200%5D) / self.total_success
 %0A%0A    @p
@@ -1958,16 +1958,18 @@
 .write('
+%5Cn
 Concurre
@@ -2464,35 +2464,103 @@
 x))%0A
-%0A%0Aif __name__ == '__
+        stdout.write('Time per request (only success): %7B:.3f%7D%5Cn'.format(self.moy))%0A%0A%0Adef 
 main
-__'
+()
 :%0A  
@@ -3408,16 +3408,29 @@
   # app%0A
+    try:%0A    
     over
@@ -3507,16 +3507,20 @@
 umbers)%0A
+    
     over
@@ -3528,24 +3528,28 @@
 oad.run%0A    
+  
+  
 overload.sta
@@ -3551,24 +3551,28 @@
 d.stats%0A    
+   
+ 
 overload.out
@@ -3575,8 +3575,119 @@
 .output%0A
+    except KeyboardInterrupt:%0A        pass%0A    finally:%0A        exit(0)%0A%0Aif __name__ == '__main__':%0A    main()%0A

improve the code