diff --git a/combidata/classes/case.py b/combidata/classes/case.py index c714fce..3c93ea1 100644 --- a/combidata/classes/case.py +++ b/combidata/classes/case.py @@ -60,7 +60,8 @@ def __init__(self, case: dict, field_name: str, field_mode: str): self.additional_fields = self.form_additional_fields(case) - + def __repr__(self): + return str(vars(self)) def hand_requirements(self, requirements): if isinstance(requirements, dict): diff --git a/combidata/classes/combination.py b/combidata/classes/combination.py index c0c439a..41b2440 100644 --- a/combidata/classes/combination.py +++ b/combidata/classes/combination.py @@ -2,14 +2,24 @@ import traceback -def step_not_done(current_step_name, combi): - if isinstance(combi, list): - for combination in combi: - if combination.step_done != current_step_name and combination.step_done != "STOP": - return True +def current_workflow(workflow, is_all_steps=False): + from combidata import Process + if isinstance(workflow[0], Process): + for process in workflow: + yield process + elif is_all_steps: + for stage in workflow: + for process in stage: + yield process else: - if combi.step_done != current_step_name and combi.step_done != "STOP": - return True + for process in workflow[0]: + yield process + workflow.pop(0) + + +def step_not_done(current_step_name, combi): + if combi.step_done != current_step_name and not isinstance(combi.step_done, Exception): + return True return False @@ -36,7 +46,7 @@ class Combination: step_done = None # last passed step - def __init__(self, case, workflow, init_lib, template, tools, logger, generator_id): + def __init__(self, case, workflow, init_lib, template, tools, logger, generator_id, types_for_generation): self.init_lib = copy.deepcopy(init_lib) self.main_case = case self.template = template @@ -49,14 +59,12 @@ def __init__(self, case, workflow, init_lib, template, tools, logger, generator_ self.cache = {} - self.workflow = workflow + self.workflow = copy.deepcopy(workflow) - self.init_lib[self.main_case.field_name] = {self.main_case.field_mode: self.main_case} + self.types_for_generation = types_for_generation def run(self): - self.workflow = list(self.workflow) if isinstance(self.workflow, list) else self.workflow # todo beautify - workflow = self.workflow.pop(0) if isinstance(self.workflow, list) else self.workflow - for current_step in workflow: + for current_step in current_workflow(self.workflow): while step_not_done(current_step.name, self): if self.step_done != current_step.name: if self.logger: @@ -64,7 +72,7 @@ def run(self): try: current_step.activate(self) except Exception as e: - self.step_done = "STOP" + self.step_done = e if self.logger: temp_exep = f"An exception occurred: {type(e).__name__}. " temp_exep += f"Error message: {str(e)}. " @@ -75,9 +83,6 @@ def run(self): line_number = last_traceback.lineno temp_exep += f"Occurred at: {file_name}:{line_number}. " self.logger.end_step(self.generator_id, temp_exep) - else: - raise e else: if self.logger: self.logger.end_step(self.generator_id) - diff --git a/combidata/classes/data_generator.py b/combidata/classes/data_generator.py index b168354..9e29462 100644 --- a/combidata/classes/data_generator.py +++ b/combidata/classes/data_generator.py @@ -1,41 +1,10 @@ import copy import random -import traceback -from pprint import pprint from combidata.classes.case import Case -from combidata.classes.combination import Combination, step_not_done - - -def crop_types(current_dict, poss_types): - for unit, modes in current_dict.items(): - for mode in list(modes.keys()): - if current_dict[unit][mode].type_of_case not in poss_types: - del current_dict[unit][mode] - - -def can_combine(neutral_lib, case): - for field, modes in neutral_lib.items(): - for mode in modes.values(): - if (case.field_name in mode.requirements and case.field_mode in mode.requirements[ - case.field_name]) or mode.field_name == case.field_name: - break - else: - return False - return True - - -def form_template(lib): - template = {} - for field, modes in lib.items(): - template[field] = {} - for mode in modes: - template[field][mode] = copy.deepcopy( - lib[field][mode]) # TODO fix_it copy.deepcopy(lib[field][mode]) is tooo dum - for seed_field, seed_modes in lib.items(): - if seed_field != field: - template[field][mode].requirements[seed_field] = set(seed_modes) - return template +from combidata.classes.combination import Combination, current_workflow +from combidata.classes.mul_dim_graph import MDG +from combidata.funcs.exeptions import CombinatoricsError def check_all_names(init_lib): @@ -43,34 +12,7 @@ def check_all_names(init_lib): for cases in init_lib["cases"].values(): for case in cases.values(): assert case["name"] not in name_set, case["name"] + " - is not unique" - name_set.update(set(case["name"])) - - -def extend_dict(input_dict, final_key_count): - output_dict = {} - dict_keys = list(input_dict.keys()) - key_count = len(dict_keys) - - i = 0 - added_key_count = 0 - shuffle_point = 0 if key_count > final_key_count else (final_key_count // key_count) * key_count - - while added_key_count < final_key_count: - if i % key_count == 0 and i == shuffle_point: - random.shuffle(dict_keys) - key = dict_keys[i % key_count] - value = input_dict[key] - - if i < key_count: - output_dict[key] = copy.deepcopy(value) - else: - extended_key = f"{key}[{i // key_count}]" - output_dict[extended_key] = copy.deepcopy(value) - - i += 1 - added_key_count += 1 - - return output_dict + name_set.add(case["name"]) class DataGenerator: @@ -111,6 +53,7 @@ def __init__(self, library: dict, logger=None, generator_id: str = None): + self.combinations = None assert amount is None or (isinstance(amount, int) and amount > 0), "amount must be integer > 0" assert banned_fields is None or isinstance(banned_fields, list), "banned_fields must be list instance" assert possible_fields is None or isinstance(possible_fields, list), "possible_fields must be list instance" @@ -120,80 +63,111 @@ def __init__(self, library: dict, self.modes_for_gen = self.form_modes_for_gen(possible_modes) self.init_lib = self.form_init_lib(library) self.dell_fields(possible_fields, banned_fields) - self.template = library["template"] + self.template = library.get("template") self.tools = library.get("tools") self.logger = logger self.generator_id = generator_id assert (logger and generator_id) or logger is None, "You must use logger and generator_id" + self.type_of_cases = type_of_cases if type_of_cases else "standard" self.workflow = self.get_workflow(library["workflow"], type_of_cases) - type_of_cases = type_of_cases if type_of_cases else "standard" if types_for_generation is None: types_for_generation = ["standard"] if not isinstance(types_for_generation, list): types_for_generation = [types_for_generation] - neutral_lib = self.form_neutral_lib(self.init_lib) - self.spread_requirements(neutral_lib) - crop_types(neutral_lib, types_for_generation) + self.types_for_generation = types_for_generation - self.combinations = self.find_combinations(neutral_lib, type_of_cases) + self.form_combinations() - assert self.combinations, "No combinations for tests" #TODO deep logging needed + assert self.combinations, "No combinations for tests" # TODO deep logging needed if amount is not None: - self.combinations = extend_dict(self.combinations, amount) - def spread_requirements(self, neutral_lib): - for field, modes in neutral_lib.items(): - for mode, case in modes.items(): - self.init_lib[field][mode].requirements = case.requirements - - def find_combinations(self, neutral_lib, type_of_cases): - all_combinations = {} + self.extend_cases(amount) + + def extend_cases(self, amount): + + workflow = copy.deepcopy(self.workflow) + if "ST_COMBINE" in [process.name for process in current_workflow(workflow, True)]: + combi_graph = MDG(self.init_lib, self.types_for_generation) + combinations = list(self.combinations.keys()) + random.shuffle(combinations) + for combination_name in combinations: + if not combi_graph.can_combine(self.combinations[combination_name].main_case): + del self.combinations[combination_name] + + dict_keys = list(self.combinations.keys()) + random.shuffle(dict_keys) + key_count = len(dict_keys) + + if key_count == amount: + return + elif key_count > amount: + for i in range(key_count - amount): + del self.combinations[dict_keys[i]] + return + + i = 0 + added_key_count = 0 + shuffle_point = (amount // key_count) * key_count + + while added_key_count < amount: + if i % key_count == 0 and i == shuffle_point: + random.shuffle(dict_keys) + key = dict_keys[i % key_count] + value = self.combinations[key] + + if i < key_count: + self.combinations[key] = copy.deepcopy(value) + else: + extended_key = f"{key}[{i // key_count}]" + self.combinations[extended_key] = copy.deepcopy(value) + + i += 1 + added_key_count += 1 + + def form_combinations(self): + self.combinations = {} for field_name, cases in self.init_lib.items(): for field_mode, case in cases.items(): - if case.type_of_case == type_of_cases and can_combine(neutral_lib, case): - current_combination = Combination(case, self.workflow, neutral_lib, - self.template, self.tools, self.logger, self.generator_id) - all_combinations.update({case.case_name: current_combination}) - return all_combinations + if case.type_of_case == self.type_of_cases: + current_combination = Combination(case, self.workflow, self.init_lib, + self.template, self.tools, self.logger, self.generator_id, + self.types_for_generation) + self.combinations.update({case.case_name: current_combination}) def run(self): - workflow = self.workflow.pop(0) if isinstance(self.workflow, list) else self.workflow - combinations = list(self.combinations.values()) - - for current_step in workflow: - while step_not_done(current_step.name, combinations): - for combination in combinations: - if combination.step_done != current_step.name: - if self.logger: - self.logger.start_step(self.generator_id, current_step.name) - try: - current_step.activate(combination) - except Exception as e: - combination.step_done = "STOP" - if self.logger: - temp_exep = f"An exception occurred: {type(e).__name__}. " - temp_exep += f"Error message: {str(e)}. " - traceback_list = traceback.extract_tb(e.__traceback__) - if traceback_list: - last_traceback = traceback_list[-1] - file_name = last_traceback.filename - line_number = last_traceback.lineno - temp_exep += f"Occurred at: {file_name}:{line_number}. " - self.logger.end_step(self.generator_id, temp_exep) - else: - raise e - else: - if self.logger: - self.logger.end_step(self.generator_id) - + combinations_names = list(self.combinations.keys()) + for combination_name in combinations_names: + self.combinations[combination_name].run() + if isinstance(self.combinations[combination_name].step_done, type(CombinatoricsError())): + del self.combinations[combination_name] + + def run_one(self): + combinations = list(self.combinations.keys()) + random.shuffle(combinations) + for combination_name in combinations: + combinations[combination_name].run() + if combinations[combination_name].step_done != CombinatoricsError(): + return combinations[combination_name] def get_one(self): - return self.combinations[random.choice(list(self.combinations.keys()))] + workflow = copy.deepcopy(self.workflow) + if "ST_COMBINE" in [process.name for process in current_workflow(workflow, True)]: + combi_graph = MDG(self.init_lib, self.types_for_generation) + combinations = list(self.combinations.keys()) + random.shuffle(combinations) + for combination in combinations: + if combi_graph.can_combine(self.combinations[combination].main_case): + return self.combinations[combination] + else: + combinations = list(self.combinations.keys()) + return self.combinations[random.choice(combinations)] - def form_modes_for_gen(self, possible_modes): + # todo def any_passed + @staticmethod + def form_modes_for_gen(possible_modes): modes_for_gen = copy.deepcopy(possible_modes) if modes_for_gen is not None: @@ -213,12 +187,6 @@ def form_init_lib(self, library): if self.modes_for_gen is not None: if field_name in self.modes_for_gen.keys() and field_mode not in self.modes_for_gen[field_name]: init_lib[field_name][field_mode].type_of_case = "OFF" - elif requirements := init_lib[field_name][field_mode].requirements: - for rec_field, rec_modes in requirements.items(): - if rec_field in self.modes_for_gen.keys() and not rec_modes & set( - self.modes_for_gen[rec_field]): - init_lib[field_name][field_mode].type_of_case = "OFF" - break return init_lib def get_workflow(self, workflow, type_of_cases): @@ -237,32 +205,3 @@ def dell_fields(self, possible_fields, banned_fields): for field in banned_fields: del self.init_lib[field] - def form_neutral_lib(self, init_lib): - neutral_lib = form_template(init_lib) - - for field, modes in init_lib.items(): - for mode in modes: - if init_lib[field][mode].requirements: - for req_unit, req_modes in init_lib[field][mode].requirements.items(): - if req_unit in neutral_lib.keys() and mode in neutral_lib[field].keys(): - neutral_lib[field][mode].requirements[req_unit] = req_modes & \ - neutral_lib[field][mode].requirements[ - req_unit] - if not neutral_lib[field][mode].requirements[req_unit]: - del neutral_lib[field][mode] - if self.logger: - self.logger.add_log(self.generator_id, - f"Mode: {mode} in field: {field}: Was deleted because will never use in generation") - modes_for_hunt = set(neutral_lib[req_unit].keys()) - req_modes - for target_mode in modes_for_hunt: - neutral_lib[req_unit][target_mode].requirements[field] = \ - neutral_lib[req_unit][target_mode].requirements[field] - set(mode) - if not neutral_lib[req_unit][target_mode].requirements[field]: - del neutral_lib[req_unit][target_mode] - if self.logger: - self.logger.add_log(self.generator_id, - f"Mode: {target_mode} in field: {req_unit}: Was deleted because will never use in generation") - - - - return neutral_lib diff --git a/combidata/classes/mul_dim_graph.py b/combidata/classes/mul_dim_graph.py new file mode 100644 index 0000000..ac16a25 --- /dev/null +++ b/combidata/classes/mul_dim_graph.py @@ -0,0 +1,62 @@ +import copy + +from combidata.funcs.exeptions import CombinatoricsError +from combidata.funcs.form_and_combine import form_template, can_combine + + +def should_keep(x): + return len(x) > 1 + + +def form_seed(gen_lib): + return {field: list(modes.keys())[0] for field, modes in gen_lib.items()} + + +class MDG: + def __init__(self, init_lib, types_for_generation=None, logger=None, generator_id=None): + + self.init_lib = copy.deepcopy(init_lib) + self.types_for_generation = types_for_generation + self.logger = logger + self.generator_id = generator_id + self.neutral_lib = self.form_neutral_lib() + + def seed(self, main_case): + if result := can_combine(self.neutral_lib, main_case, self.types_for_generation): + return form_seed(result) + else: + raise CombinatoricsError() + + def can_combine(self, main_case): + if can_combine(self.neutral_lib, main_case, self.types_for_generation): + return True + else: + return False + + def form_neutral_lib(self): + template = form_template(self.init_lib) + + for field, modes in self.init_lib.items(): + for mode in modes: + if self.init_lib[field][mode].requirements: + for req_unit, req_modes in self.init_lib[field][mode].requirements.items(): + if req_unit in template.keys() and mode in template[field].keys(): + template[field][mode].requirements[req_unit] = req_modes & \ + template[field][mode].requirements[ + req_unit] + if not template[field][mode].requirements[req_unit]: + del template[field][mode] + if self.logger: + self.logger.add_log(self.generator_id, + f"Mode: {mode} in field: {field}: Was deleted because will never use in generation") + modes_for_hunt = set(template[req_unit].keys()) - req_modes + for target_mode in modes_for_hunt: + template[req_unit][target_mode].requirements[field] = \ + template[req_unit][target_mode].requirements[field] - set(mode) + if not template[req_unit][target_mode].requirements[field]: + del template[req_unit][target_mode] + if self.logger: + self.logger.add_log(self.generator_id, + f"Mode: {target_mode} in field: {req_unit}: Was deleted because will never use in generation") + + return template diff --git a/combidata/funcs/exeptions.py b/combidata/funcs/exeptions.py new file mode 100644 index 0000000..88c24bf --- /dev/null +++ b/combidata/funcs/exeptions.py @@ -0,0 +1,6 @@ +class CombinatoricsError(Exception): + """Bad combinatorics.""" + + def __init__(self, message="You can't combine that case"): + self.message = message + super().__init__(self.message) \ No newline at end of file diff --git a/combidata/funcs/form_and_combine.py b/combidata/funcs/form_and_combine.py new file mode 100644 index 0000000..d688e3a --- /dev/null +++ b/combidata/funcs/form_and_combine.py @@ -0,0 +1,59 @@ +import copy +import random + + +def should_keep(x): + return len(x) > 1 + + +def form_template(lib): + template = {} + for field, modes in lib.items(): + template[field] = {} + for mode in modes: + template[field][mode] = copy.deepcopy( + lib[field][mode]) # TODO fix_it copy.deepcopy(lib[field][mode]) is to dum + for seed_field, seed_modes in lib.items(): + if seed_field != field: + template[field][mode].requirements[seed_field] = set(seed_modes) + return template + + +def can_combine(neutral_lib, current_case, types_for_generation): + case = copy.deepcopy(current_case) + case.requirements = neutral_lib[case.field_name][case.field_mode].requirements + copied_lib = copy.deepcopy(neutral_lib) + + for mode in neutral_lib[case.field_name].keys(): + if mode != case.field_mode: + del copied_lib[case.field_name][mode] + + for field, modes in neutral_lib.items(): + if field != case.field_name: + for mode in neutral_lib[field].keys(): + if mode not in case.requirements[field]: + del copied_lib[field][mode] + + modes_count = 0 + + for modes in copied_lib.values(): + if not modes: + return False + modes_count += len(modes) + + if modes_count == len(copied_lib.keys()): + for field, modes in copied_lib.items(): + for case in modes.values(): + for case_field, case_modes in case.requirements.items(): + if not list(copied_lib[case_field].keys())[0] in case_modes: + return False + return copied_lib + else: + fields = [list(mode.values()) for mode in copied_lib.values()] + random.shuffle(fields) + fields = list(filter(should_keep, fields)) + for case in fields[0]: + if case.type_of_case in types_for_generation and (result := can_combine(copied_lib, case, types_for_generation)): + return result + else: + return False diff --git a/combidata/processes/combine.py b/combidata/processes/combine.py index 898645e..2de965e 100644 --- a/combidata/processes/combine.py +++ b/combidata/processes/combine.py @@ -1,89 +1,20 @@ -import copy -import random - - -def crop_types(current_dict, poss_types): - for unit, modes in current_dict.items(): - for mode in list(modes.keys()): - if current_dict[unit][mode].type_of_case not in poss_types: - del current_dict[unit][mode] - - -def form_template(lib): - template = {} - for field, modes in lib.items(): - template[field] = {} - for mode in modes: - template[field][mode] = copy.deepcopy( - lib[field][mode]) # TODO fix_it copy.deepcopy(lib[field][mode]) is tooo dum - for seed_field, seed_modes in lib.items(): - if seed_field != field: - template[field][mode].requirements[seed_field] = set(seed_modes) - return template - - -def form_poss(init_lib, neutral_types=None): - neutral_lib = form_template(init_lib) - - for field, modes in init_lib.items(): - for mode in modes: - if init_lib[field][mode].requirements: - for req_unit, req_modes in init_lib[field][mode].requirements.items(): - if req_unit in neutral_lib.keys() and mode in neutral_lib[field].keys(): - neutral_lib[field][mode].requirements[req_unit] = req_modes & \ - neutral_lib[field][mode].requirements[ - req_unit] - if not neutral_lib[field][mode].requirements[req_unit]: - del neutral_lib[field][mode] - modes_for_hunt = set(neutral_lib[req_unit].keys()) - req_modes - for target_mode in modes_for_hunt: - neutral_lib[req_unit][target_mode].requirements[field] = \ - neutral_lib[req_unit][target_mode].requirements[field] - set(mode) - if not neutral_lib[req_unit][target_mode].requirements[field]: - del neutral_lib[req_unit][target_mode] - - if neutral_types is not None: - crop_types(neutral_lib, neutral_types) - - return neutral_lib - - -def process_mode(seed, poss_di, chosen_case): - for pos_unit, pos_modes in chosen_case.requirements.items(): - if poss_di.get(pos_unit): - modes_for_del = set(poss_di[pos_unit].keys()) - set(pos_modes) - for mode_for_del in modes_for_del: - del poss_di[pos_unit][mode_for_del] - seed[chosen_case.field_name] = chosen_case.field_mode - del poss_di[chosen_case.field_name] - return form_poss(poss_di) - - -def generate_seed(di, main_case): - poss_di = copy.deepcopy(di) - seed = {} - - poss_di = process_mode(seed, poss_di, main_case) - - while poss_di: - chosen_unit = random.choice(list(poss_di.keys())) - chosen_mode = random.choice(list(poss_di[chosen_unit].keys())) - poss_di = process_mode(seed, poss_di, poss_di[chosen_unit][chosen_mode]) - - return seed +from combidata.classes.mul_dim_graph import MDG def combine(combination): neutral_lib = combination.init_lib + + combi_graph = MDG(neutral_lib, combination.types_for_generation, combination.logger, combination.generator_id) + main_case = combination.main_case - combination.test_seed = generate_seed(neutral_lib, main_case) + combination.test_seed = combi_graph.seed(main_case) combination.other_cases = {field: combination.init_lib[field][mode] for field, mode in combination.test_seed.items() if field != combination.main_case.field_name} if combination.logger: combination.logger.add_log(combination.generator_id, - f"Generated seed: {str(combination.test_seed)}") + f"Generated seed: {str(combination.test_seed)}") return True diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md new file mode 100644 index 0000000..b79c81c --- /dev/null +++ b/docs/ReleaseNotes.md @@ -0,0 +1,17 @@ +--- +hide: + - navigation +--- + +# Release Notes: Version 0.2.3 + +## Enhancements: +1. **Multidimensional Graph Overhaul:** The multidimensional graph has been reworked for improved performance and efficiency. +2. **Initial Generation Function Rework:** The function for initial data generation has been redesigned. Now, combinations are calculated dynamically during runtime, rather than pre-computed before launch. This change enhances the flexibility and responsiveness of the system. +3. **New Class Methods - Run1 and Extend Cases:** For scenarios where pre-calculation of combinations is required, new class methods 'Run1' and 'Extend Cases' have been introduced. These methods provide additional control and customization options for data generation and processing. + +## Bug Fixes: +1. **Multidimensional Combinatorial Graph Bugs Addressed:** Several bugs in the multidimensional combinatorial graph have been identified and fixed, ensuring more stable and reliable operations. + +## Functionality Improvements: +1. **Enhanced Functions:** Various functions have been refined for better performance and user experience, contributing to the overall robustness of the application. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 599deeb..3acf606 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -10,6 +10,7 @@ nav: - Combination: Combination.md - DataGenerator: DataGenerator.md - Quick Start Guide: QSG.md + - Release Notes: ReleaseNotes.md theme: name: material logo: assets/logo.svg diff --git a/pyproject.toml b/pyproject.toml index 5f3d39e..f13297b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,4 +17,4 @@ keywords = [ urls = {Homepage = "https://github.com/Warrfie/combidata"} authors = [{name = "MaximKuklikov(Warrfie)", email = "warrfie@gmail.com"}] requires-python = ">=3.10" -version="0.2.2.4" +version="0.2.3" diff --git a/setup.py b/setup.py index 30aa997..4f98062 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name="combidata", - version="0.2.2.4", + version="0.2.3", description="Package for random data generation and combination different cases", long_description=long_description, url="https://github.com/Warrfie/combidata", diff --git a/tests/test_generator.py b/tests/test_generator.py index 2b32a5c..abfba69 100644 --- a/tests/test_generator.py +++ b/tests/test_generator.py @@ -9,6 +9,8 @@ from combidata import ST_COMBINE, ST_GENERATE, ST_FORM, DataGenerator, Process from re_generate import re_generate +from combidata.funcs.exeptions import CombinatoricsError + def code_generator(combination, example_token): # just for test @@ -17,6 +19,7 @@ def code_generator(combination, example_token): def gen_comb(combination: Combination): new_comb = DataGenerator(library, amount=1).get_one() + new_comb.run() return new_comb.generated_data @@ -36,7 +39,9 @@ def gen_value(value): "template": { "NAME": "NAME", "code": "CODE", - "inc": "SAVES" + "inc": "SAVES", + "obj1": "OBJ1", + "obj2": "OBJ2", } } library["cases"]["NAME"] = { @@ -56,6 +61,40 @@ def gen_value(value): "is_presented": False, "name": "Check NAME for not necessary field" }} +library["cases"]["OBJ1"] = { + "1": { + "gen_func": re_generate, + "value": r"[a-zA-Z]{50}", + "requirements": {"CODE": "NT"}, + "name": "1Standart NAME check" + }, + "2": { + "value": "12345", + "requirements": {"CODE": "NT"}, + "name": "1Check NAME with error" + }, + "3": { + "value": None, + "requirements": {"OBJ2": ["1", "2"]}, + "is_presented": False, + "name": "1Check NAME for not necessary field" + }} +library["cases"]["OBJ2"] = { + "1": { + "gen_func": re_generate, + "value": r"[a-zA-Z]{50}", + "name": "2Standart NAME check" + }, + "2": { + "value": "12345", + "name": "2Check NAME with error" + }, + "3": { + "value": None, + "requirements": {"CODE": "T"}, + "is_presented": False, + "name": "2Check NAME for not necessary field" + }} library["cases"]["CODE"] = { "TNNN": { "gen_func": code_generator, @@ -100,10 +139,39 @@ def gen_value(value): }, } -generator = DataGenerator(library, amount=100) +generator = DataGenerator(library) + + generator.run() +@pytest.mark.parametrize("combination_name", generator.combinations.keys()) +def test_smoke(combination_name): + combination = generator.combinations[combination_name] + combination.run() + if isinstance(combination.step_done, Exception): + raise combination.step_done + print() + print(combination.test_seed) + print() + pprint(combination.formed_data) + + +@pytest.mark.parametrize("combination_name", generator.combinations.keys()) +def test_smoke(combination_name): + combination = generator.combinations[combination_name] + combination.run() + if isinstance(combination.step_done, CombinatoricsError): + pytest.skip() + elif isinstance(combination.step_done, Exception): + raise combination.step_done + print() + print(combination.test_seed) + print() + pprint(combination.formed_data) + assert combination.test_seed.get("OBJ2", True) != "3" + + @pytest.mark.parametrize("combination_name", generator.combinations.keys()) def test(combination_name): combination = generator.combinations[combination_name] @@ -125,6 +193,7 @@ def test2(combination_name): gen_seed = gen_seed.test_seed assert seed == gen_seed + @pytest.mark.parametrize("combination_name", generator.combinations.keys()) def test3(combination_name): combination = generator.combinations[combination_name] @@ -134,4 +203,3 @@ def test3(combination_name): print(seed) semi_gen = DataGenerator(library, possible_modes=seed, amount=100) semi_gen.run() -