Browse Source

INI-File, Standard-Products and many other changes

Bernhard Buhl 5 years ago
parent
commit
f2690b0bcc

+ 131 - 26
API_Calls.py

@@ -26,14 +26,15 @@ def args_read(l_search_parameter):
     l_args = sys.argv[1:]
 
     try:
-        opts, args = getopt.getopt(l_args,"u:p:s:l:m:",["users=",
+        opts, args = getopt.getopt(l_args,"u:p:s:l:m:U;",["users=",
                                                     "products=", 
                                                     "server=", 
                                                     "ll=",
                                                     "mode=", 
                                                     "csv=",
                                                     "domass=",
-                                                    "noimage=",
+                                                    "noimage=",                                                
+                                                    "ini_file=",
                                                     ])
     except getopt.GetoptError as err_det:
         print ("Error in reading parameters:" + str(err_det))
@@ -43,7 +44,10 @@ def args_read(l_search_parameter):
         for opt, arg in opts:
             if l_search_parameter == opt: #in ("-u", "--usage"):
                 return arg
-    return None
+    # maybe there is something in ini-file:
+    if not l_search_parameter == "--ini_file":
+        return g_api_ini.get_parameter(l_search_parameter)
+    #return None
 
 def print_args():
     print("""
@@ -67,6 +71,8 @@ Call: python api_calls.py --parameters
                       When this is set, it will be between 1 and 3 recycling entries
        --noimage=yes : If set to "yes" and mode=allnew, no images will be uploaded. Otherwise
                        test2.jpg will be uploaded for each new product
+       --ini_file= Path and name of INI-File to use (other command line arguments will overwrite
+                       the settings from INI-File.
       
  Suggested for standard use:
    python api_calls.py --users=50 --products=1000
@@ -163,11 +169,24 @@ def g_check_status(resp):
         return True
     
 def g_get_header(i=9999999):
+    import time
     
     l_token_key = g_users.get_user_and_login(i)
     if not l_token_key:
-        logger.critical("Token for user not recevied: " + str(i))
-        raise SystemExit()
+        # Problem on 22.6. - Token_key would take ages until we can login with it.
+        for n in range(1,10):
+            logger.warn("Login not successfull - waiting 3 seconds " + str(i))
+            time.sleep( 3 )
+            for x in range(1,20):
+                l_token_key = g_users.get_user_and_login(i)
+                if l_token_key:
+                    break
+            if l_token_key:
+                break
+                
+        if not l_token_key:
+            logger.critical("Token for user not received: " + str(i))
+            raise SystemExit()
     
     headers={'x-geolocation-header': "1:1",
          "authorization": "Token " + l_token_key,
@@ -176,12 +195,50 @@ def g_get_header(i=9999999):
     
     return headers
 
+class ini_contents:
+    def __init__(self, l_file=None):
+        #print ("Init im ini_contents aufgetreten. Usage ist:" + usage)
+        #traceback.print_stack()
+        if l_file is None:
+            self.__file = "init.ini" #"prod" or "test"
+        else:
+            self.__file = l_file
+        self.__attribs = {}
+        self.__open_ini()
+#        self.__util = util()
+#        self.__util.traceback()
+    def __open_ini(self):
+        self.__attribs["INI_FILE"] = self.__file
+        l_filename = self.__file
+
+        with (open(os.path.join(os.getcwd(), l_filename), "r")) as l_file:
+            for l_line in l_file.readlines():
+                # Kommentare ignorieren:
+                if len(l_line.strip()) == 0:
+                    continue
+                if l_line[0] != "#":
+                    l_line = l_line.strip()
+                    self.__attribs[l_line.split("=")[0]] = l_line.split("=")[1]
+            if "ll" in self.__attribs:
+                self.__attribs["ll"] = get_proper_loglevel(self.__attribs["ll"])
+            else:
+                self.__attribs["ll"] = get_proper_loglevel("INFO")
+          
+    def get_value(self, key_for_value):
+        if key_for_value[0:2] == "--":
+            key_for_value = key_for_value[2:]
+        if key_for_value in self.__attribs.keys():
+            return (self.__attribs[key_for_value])
+        else:
+            return None
 class api_init:
-    def __init__(self, min_number, iteration):
+    def __init__(self):
+        # Read the ini-file
+        self.ini_file = ini_contents(l_file=args_read("--ini_file"))
+    def set_default(self, min_number, iteration):
         self.min_number = min_number
         self.max_number = min_number + iteration
         # BaseURL for API-Calls 
-        # Muss spaeter noch ersetzt werden - irgendwie aus INI-File ziehen oda so.
         self.base_url = args_read("--server")
         if not self.base_url:
             self.base_url = "https://app-test.earthsquad.global/api" 
@@ -190,6 +247,7 @@ class api_init:
         l_datetime = datetime.now()
         self.base = str(l_datetime.month + l_datetime.day) + str(l_datetime.hour + l_datetime.minute) + str(l_datetime.second)
         logger.debug("Base-String: " + self.base)
+        
     def set_base_url(self, base_url):
         self.base_url = base_url
     def get_min_number(self):
@@ -200,6 +258,8 @@ class api_init:
         return self.base_url
     def get_base(self):
         return self.base
+    def get_parameter(self, l_search_term):
+        return self.ini_file.get_value(l_search_term)
     def get_g_mode(self):
         l_gmode = args_read("--mode")
         if not l_gmode:
@@ -266,7 +326,7 @@ class api_user:
             self.l_counter = 1
             self.l_token_key = self._login_(l_i)
             return self.l_token_key
-        elif self.l_counter > 50:
+        elif self.l_counter > 20:
             self.l_counter = 0
             return self.l_token_key
         else:
@@ -315,9 +375,10 @@ class api_user:
             l_reader = csv.reader(l_csvfile)
             for l_row in l_reader:
                 # Testusers call start with a number and E-Mail @test.com
-                if "test.com" in l_row[0] and l_row[0][0:1].isdigit():
-                    self.l_users.append([l_row[0].split("@test.com")[0], ""])
-                    l_i += 1
+                if len(l_row) >= 1:
+                    if "test.com" in l_row[0] and l_row[0][0:1].isdigit():
+                        self.l_users.append([l_row[0].split("@test.com")[0], ""])
+                        l_i += 1
         logger.info("File with Users Imported")
         logger.info("Imported: " + str(l_i) + " users from CSV-File " + l_csv)
         # If there were more users selected in the start-parameters (or automatically)
@@ -326,6 +387,21 @@ class api_user:
             self.l_max_number = self.l_min_number + l_i
         return l_i
 
+def g_recyclemat_random():
+    l_random = 0
+    l_rand_str_list = g_api_ini.get_parameter("recycle_producttypes")
+    if l_rand_str_list:
+        logger.debug("Using List for recycling material: " + l_rand_str_list)
+        l_rand_list = l_rand_str_list.split(";")
+        l_rand_pos = g_random(0,len(l_rand_list)-1)
+        logger.debug("Took position " + str(l_rand_pos) + " of list for this BOM or Bulk-Recycling-Item")
+        return l_rand_list[l_rand_pos]
+    else:
+        logger.debug("Not using standard product type")
+        l_random = g_random(3,17)
+    
+    return l_random
+
 class api_product_full:
     def __init__(self, l_number, api_init):
         # uses the EAN-Code and the product API
@@ -346,13 +422,18 @@ class api_product_full:
         l_product = api_product(self.number, api_init=self.api_init)
         self.product_id  = l_product.create(self.ean_id)
         
+        # If product, that was created is not using a default producttype, create a BOM
+        if l_product.get_is_default() == 0:
         # Create 1 to 4 BOM-Items for this product
-        for l_bom in range(0, g_random(1,4)):
-            # chose a random packaging material type
-            api_bom(self.api_init, self.product_id, g_random(3,17), g_random(10,1000))
+            for l_bom in range(0, g_random(1,4)):
+                # chose a random packaging material type
+                api_bom(self.api_init, self.product_id, g_recyclemat_random(), g_random(10,1000))
             
         # Upload Image_
-        f_image_upload("test.jpg", self.product_id)
+        l_image = g_api_ini.get_parameter("image")
+        if not l_image:
+            l_image = "test2.jpg"
+        f_image_upload(l_image, self.product_id, l_image)
  
     def read_server(self, id):
         # Checks with this ID, whether a product exists @ server
@@ -462,8 +543,27 @@ class api_product:
         self.number = l_number
         self.l_api_init = api_init
         self.l_base_url = self.l_api_init.get_base_url()
-        self.l_base = self.l_api_init.get_base()        
+        self.l_base = self.l_api_init.get_base()       
+        self.l_uses_default_product = 0 
     def create(self, l_barcode_id):
+        
+        # Randomly create products with and without default product_type
+        l_use_def_product = g_random(0,1)
+        if l_use_def_product == 1:
+            # Find the products, we're supposed to use from INI-File
+            l_def_products_in = g_api_ini.get_parameter("default_products")
+            if l_def_products_in:
+                # Identifiy the Standard product types we can use.
+                l_def_products = l_def_products_in.split(";")
+                # Get a random number within the array
+                l_use_product_position = g_random(0, len(l_def_products)-1)
+                # get the ID of this random number:
+                l_use_product = l_def_products[l_use_product_position]
+                self.l_uses_default_product = 1
+                logger.info("Using default product_type: " + str(l_use_product) + " for product " + self.l_base + str(self.number))
+        else:
+            l_use_product = 1
+        
         g_timeit.start("products")
         url = self.l_base_url + "/scanapp/en-us/products/"
         product_data = {
@@ -475,7 +575,7 @@ class api_product:
           "height": 0,
           "is_generic": "false",
           "deleted": "false",
-          "product_type": 1,
+          "product_type": l_use_product,
           "weight_unit": 2
           }
         resp = g_post(url, headers=g_get_header(), json=product_data)
@@ -485,7 +585,9 @@ class api_product:
             l_answer = resp.json()
             logger.debug("Product: " + str(self.number) + " " + str(l_answer))  
             #x_result[i].append(l_answer["id"])
-            return l_answer["id"]     
+            return l_answer["id"]
+    def get_is_default(self):
+        return self.l_uses_default_product
             
 def g_random(l_min, l_max):
     return randint(l_min, l_max)
@@ -698,14 +800,13 @@ def f_daily_recycle():
     while l_found_mat <= l_count_materials:
         # Brute-force getting material-IDs from database
 
-        
         l_iterator = l_iterator + g_random(1, l_base_random)
         l_product = api_product_full(l_iterator, g_api_ini)
         l_ok_product = l_product.read_server(l_iterator)
-        if l_endless_loop_counter >= 5:
+        if l_endless_loop_counter >= 25:
             logger.error("Endless loop when trying to find materials. Exiting")
             raise SystemExit()
-        if l_not_found_counter >= 5:
+        if l_not_found_counter >= 7:
             # If we didn't find a product after 5 tries
             # we should reset the iterator.
             l_iterator = 1
@@ -734,7 +835,7 @@ def f_daily_recycle():
             l_product.recycle()
             logger.info("Recycled " + str(l_product.get_id()) + " for user " + str(i))    
 
-def f_image_upload(img_file, l_id):
+def f_image_upload(img_file, l_id, l_img_name="testimage"):
     if args_read("--noimage") == "yes":
         return None
     
@@ -750,7 +851,7 @@ def f_image_upload(img_file, l_id):
         
     l_upload = {
         "product" : str(l_id), 
-        "name" : "test2.jpg"
+        "name" : l_img_name
          }
     #g_timeit.end()
     
@@ -776,7 +877,7 @@ def f_bulk_recycling():
             logger.info("Bulk recycling - items: " + str(i))
             g_api_statistics.get_statistics(g_random(1,2), g_random(1,3))  
         g_timeit.start("bulk_recycling")
-        recycle_data = {"product_type" : g_random(3,17), "weight" : g_random(100,1000), "weight_unit" : g_random(1,2)}
+        recycle_data = {"product_type" : g_recyclemat_random(), "weight" : g_random(100,1000), "weight_unit" : g_random(1,2)}
         resp = g_post(url, headers=g_get_header(), json=recycle_data)
     
         if g_check_status(resp):
@@ -800,10 +901,13 @@ def f_products_import():
     
 print_args() #Prints the instructions how to start the program
 
+g_api_ini = api_init() #initizalize API
+
 logger = g_logging_init()
 
 l_iteration = f_products_import() #from command line parameter or default value
-g_api_ini = api_init(min_number=1000, iteration=l_iteration) #initizalize API
+g_api_ini.set_default(min_number=1000, iteration=l_iteration)
+
 g_mode = g_api_ini.get_g_mode() #from command line parameter or default value
 l_users = g_api_ini.get_l_users() #from command line parameter or default value
 g_timeit = gc_timeit(g_api_ini) #Instanziate timer class
@@ -830,4 +934,5 @@ f_bulk_recycling()
     
 g_timeit.printreport()
 #g_perf_trace.perf_trace_end()    
-print("\nall done - Thanks")
+print("\nall done - Thanks")
+

BIN
API_Calls_test_for_kseniia.zip


+ 5 - 0
auth_user_loc.csv

@@ -0,0 +1,5 @@
+email
+2761241000@test.com
+2761241001@test.com
+276321000@test.com
+276321001@test.com

File diff suppressed because it is too large
+ 86 - 132948
auth_user_mysql.csv


File diff suppressed because it is too large
+ 132949 - 0
auth_user_mysql_old.csv


BIN
dist/CMD_call for Kseniia.zip


+ 1 - 1
dist/_mysql_recycle.cmd

@@ -1 +1 @@
-api_calls.exe --users=100 --products=1000 --server=https://app-test.earthsquad.global/api --mode=recycling --csv="auth_user_dev_mysql.csv"
+api_calls.exe --users=100 --products=1000 --server=https://app-test.earthsquad.global/api --mode=recycling --csv="auth_user_mysql.csv"

+ 1 - 1
dist/_mysql_short.cmd

@@ -1 +1 @@
-api_calls.exe --users=10 --products=100 --server=https://app-test.earthsquad.global/api
+api_calls.exe --users=2 --products=50 --server=https://app-test.earthsquad.global/api

+ 1 - 1
dist/_mysql_short_recycle.cmd

@@ -1 +1 @@
-api_calls.exe --users=10 --products=50 --server=https://app-test.earthsquad.global/api --mode=recycling --csv="auth_user_dev_mysql.csv"
+api_calls.exe --users=10 --products=10 --server=https://app-test.earthsquad.global/api --mode=recycling --csv="auth_user_mysql.csv"

BIN
dist/api_calls.exe


dist/auth_user_dev_mysql.csv → dist/auth_user_dev_mysql_old.csv


+ 87 - 0
dist/auth_user_mysql.csv

@@ -0,0 +1,87 @@
+"admin@earthsquad.global"
+"283551000@test.com"
+"283551001@test.com"
+"283551002@test.com"
+"283551003@test.com"
+"283551004@test.com"
+"283551005@test.com"
+"283551006@test.com"
+"283551007@test.com"
+"283551008@test.com"
+"283551009@test.com"
+"2836281000@test.com"
+"2836281001@test.com"
+"2836281002@test.com"
+"2836281003@test.com"
+"2836281004@test.com"
+"2836281005@test.com"
+"2836281006@test.com"
+"2836281007@test.com"
+"2836281008@test.com"
+"2836281009@test.com"
+"2837271000@test.com"
+"2837271001@test.com"
+"2837271002@test.com"
+"2837271003@test.com"
+"2837271004@test.com"
+"2837271005@test.com"
+"2837271006@test.com"
+"2837271007@test.com"
+"2837271008@test.com"
+"2837271009@test.com"
+"2838561000@test.com"
+"2838561001@test.com"
+"2838561002@test.com"
+"2838561003@test.com"
+"2838561004@test.com"
+"2838561005@test.com"
+"2838561006@test.com"
+"2838561007@test.com"
+"2838561008@test.com"
+"2838561009@test.com"
+"2868141000@test.com"
+"2868141001@test.com"
+"2872221000@test.com"
+"2872221001@test.com"
+"2872221002@test.com"
+"2872221003@test.com"
+"2872221004@test.com"
+"2830111000@test.com"
+"2830111001@test.com"
+"2830111002@test.com"
+"2830111003@test.com"
+"2830111004@test.com"
+"2832101000@test.com"
+"2832101001@test.com"
+"2832101002@test.com"
+"2832101003@test.com"
+"2832101004@test.com"
+"2841381000@test.com"
+"2841381001@test.com"
+"2841381002@test.com"
+"2841381003@test.com"
+"2841381004@test.com"
+"2855411000@test.com"
+"2855411001@test.com"
+"2856341000@test.com"
+"2856341001@test.com"
+"2860321000@test.com"
+"2860321001@test.com"
+"2863131000@test.com"
+"2863131001@test.com"
+"2873201000@test.com"
+"2873201001@test.com"
+"287461000@test.com"
+"287461001@test.com"
+"2818281000@test.com"
+"2818281001@test.com"
+"2818281002@test.com"
+"2818281003@test.com"
+"2818281004@test.com"
+"2818281005@test.com"
+"2818281006@test.com"
+"2818281007@test.com"
+"2818281008@test.com"
+"2818281009@test.com"
+"2819531000@test.com"
+"2819531001@test.com"

BIN
dist/fuer den muecke.zip


+ 37 - 0
dist/init.ini

@@ -0,0 +1,37 @@
+# IDs of producttypes with direct BOMs (e.g. "PET 0,5l")
+default_products=22;25;30;35;36;39;42
+
+# IDs of recycling material product types (=product_types that 
+# are in the hierarchy below ID=2 (=Recycling Material)
+recycle_producttypes=3;4;5;6;7;8;9;12;13;14;15;17
+
+# Server
+server=https://app-test.earthsquad.global/api
+
+# Loglevel
+ll=2
+
+# mode: either "recycling" for simulating daily recycling of users or "allnew"
+#mode=recycling
+mode=allnew
+
+# Location of database dump of "select username from auth_users" as CSV (for mode=Recycling)
+csv=auth_user_mysql.csv
+
+# Switch weather to upload images during product creation (no_image = yes will not upload image)
+no_image=No
+
+# Image file name and location (image2.jpg is currently a small image. image.jpg is 3MB)
+image=test2.jpg
+
+# Number of products to be created (mode=allnew) or search for in CSV-File (mode=recycling)
+products=5
+
+# Number of users to be created (mode=allnew) or chosen for daily recycling (mode=recycling)
+users=5
+
+#Shall the recycling-count be rather high (=yes) or quite low (=no) per User per Day?
+#do_mass=yes
+do_mass=no
+
+

BIN
dist/test.jpg


BIN
dist/test2.jpg


+ 37 - 0
init.ini

@@ -0,0 +1,37 @@
+# IDs of producttypes with direct BOMs (e.g. "PET 0,5l")
+default_products=22;25;30;35;36;39;42
+
+# IDs of recycling material product types (=product_types that 
+# are in the hierarchy below ID=2 (=Recycling Material)
+recycle_producttypes=3;4;5;6;7;8;9;12;13;14;15;17
+
+# Server
+server=https://app-test.earthsquad.global/api
+
+# Loglevel
+ll=2
+
+# mode: either "recycling" for simulating daily recycling of users or "allnew"
+#mode=recycling
+mode=allnew
+
+# Location of database dump of "select username from auth_users" as CSV (for mode=Recycling)
+csv=auth_user_mysql.csv
+
+# Switch weather to upload images during product creation (no_image = yes will not upload image)
+no_image=No
+
+# Image file name and location (image2.jpg is currently a small image. image.jpg is 3MB)
+image=test2.jpg
+
+# Number of products to be created (mode=allnew) or search for in CSV-File (mode=recycling)
+products=5
+
+# Number of users to be created (mode=allnew) or chosen for daily recycling (mode=recycling)
+users=5
+
+#Shall the recycling-count be rather high (=yes) or quite low (=no) per User per Day?
+#do_mass=yes
+do_mass=no
+
+

+ 30 - 0
init_dev.ini

@@ -0,0 +1,30 @@
+# IDs of producttypes with direct BOMs (e.g. "PET 0,5l")
+default_products=22;25;30;35;36;39;42;44
+
+# IDs of recycling material product types (=product_types that 
+# are in the hierarchy below ID=2 (=Recycling Material)
+recycle_producttypes=3;4;5;6;7;8;9;12;13;14;15;17
+
+# Server
+server=http://localhost:8000/api
+
+# Loglevel
+ll=4
+
+# mode: either "recycling" for simulating daily recycling of users or "allnew"
+mode=recycling
+#mode=allnew
+
+# Location of database dump of "select username from auth_users" as CSV (for mode=Recycling)
+csv=auth_user_loc.csv
+
+# Switch weather to upload images during product creation (no_image = yes will not upload image)
+no_image=No
+
+# Image file name and location
+#image=test.jpg
+# Number of products to be created (mode=allnew) or search for in CSV-File (mode=recycling)
+products=5
+
+# Number of users to be created (mode=allnew) or chosen for daily recycling (mode=recycling)
+users=1

BIN
test.jpg


BIN
test2.jpg