diff --git a/.pytest_cache/v/cache/lastfailed b/.pytest_cache/v/cache/lastfailed index b930be7..de719d8 100644 --- a/.pytest_cache/v/cache/lastfailed +++ b/.pytest_cache/v/cache/lastfailed @@ -1,185 +1,6 @@ { - "tests/templates/format/test_base.py::TestJoinMethod::test_if_input_dictionaries_have_no_sections_and_have_only_parameter_lines__it_will_be_processed_correctly": true, - "tests/templates/format/test_base.py::TestJoinMethod::test_if_input_template_dictionary_has_delete_mark_for_parameter__parameter_will_be_deleted": true, - "tests/templates/format/test_base.py::TestJoinMethod::test_if_input_template_dictionary_has_delete_mark_for_section__section_will_be_deleted": true, - "tests/templates/format/test_base.py::TestJoinMethod::test_if_input_template_dictionary_has_replace_mark_for_section__section_will_be_deleted": true, - "tests/templates/format/test_base.py::TestJoinMethod::test_if_inputs_are_dictionaries_with_parameters_with_same_name_in_same_section__parameters_values_in_original_dictionary_changed_to_values_from_template": true, - "tests/templates/format/test_base.py::TestJoinMethod::test_if_inputs_are_dictionaries_with_same_sections_which_contain_different_parameters__a_section_from_the_template_added_to_the_same_section_of_original_dictionary": true, - "tests/templates/format/test_base.py::TestJoinMethod::test_if_inputs_are_dictionaries_with_string_keys_without_any_action_marks__the_dictionaties_just_merged": true, - "tests/templates/format/test_base.py::TestJoinMethod::test_if_inputs_are_dictionaries_with_tuple_keys_without_any_action_marks_as_their_keys__the_dictionaries_just_merged": true, - "tests/templates/format/test_base.py::TestLogicLinesMethod::test_if_input_is_text_document_the_method_returns_list_of_its_lines": true, - "tests/templates/format/test_base.py::TestLogicLinesMethod::test_if_lines_in_document_divided_using_backslash_as_continuation_symbol__method_returns_list_of_full_lines": true, "tests/templates/format/test_bind.py::TestParsingMethods::test_if_comment_parameter_is_set_for_template__format_object_will_parse_comments_with_comment_symbol_from_this_parameter": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_if_input_document_contains_blocks_and_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_values_or_with_empty_block__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_if_input_document_contains_some_block_of_parameters__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_if_input_document_contains_some_blocks_with_similar_names__the_blocks_join_recursively": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_if_parameters_and_blocks_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value_or_with_special_key_in_block_dictionary": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_if_the_IgnoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_bind.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values_and_sections_to_delete__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_if_input_document_contains_sections_with_different_names_but_different_parameters__the_parameters_merged_in_one_section": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_if_input_document_contains_sections_with_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_if_parameter_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_if_the_ignore_comments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_compiz.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_contents.py::TestParsingMethods::test_if_input_document_contains_a_few_lines_with_some_action_symbols__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_contents.py::TestParsingMethods::test_if_input_document_contains_a_few_lines_without_any_action_symbols__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_contents.py::TestParsingMethods::test_if_template_parser_flag_is_set_False__the_initialized_object_contains_correct_dictionary_for_contents_util_module": true, - "tests/templates/format/test_contents.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_diff.py::TestExecuteMethods::test_if_diff_patch_used_for_patching_of_directories__it_changes_files_in_directories_and_adds_ones": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_if_input_document_contains_blocks_and_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_values_or_with_empty_block__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_if_input_document_contains_some_block_of_parameters__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_if_input_document_contains_some_blocks_with_similar_names__the_blocks_join_recursively": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_if_parameters_and_blocks_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value_or_with_special_key_in_block_dictionary": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_if_the_IgnoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_dovecot.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_json.py::TestParsingMethods::test_if_input_document_contains_just_few_parameters_and_parameter_blocks__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_json.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_json.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values_and_sections_to_delete__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_input_document_contains_parameters_with_values_with_unicode_symbols__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_input_document_contains_sections_with_different_names_but_different_parameters__the_parameters_merged_in_one_section": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_input_document_contains_sections_with_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_parameter_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_if_the_IgnoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_kde.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_kernel.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_kernel.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_kernel.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_kernel.py::TestParsingMethods::test_if_input_document_contains_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_kernel.py::TestParsingMethods::test_if_parameter_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value": true, - "tests/templates/format/test_kernel.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_kernel.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_input_doc_contains_some_type_sections_with_plain_directives__object_dictionary_contains_correct_dictionary_with_directives_values_and_comments": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_input_doc_contains_some_type_sections_with_plain_directives_and_action_marks__object_dictionary_contains_correct_dictionary_with_directives_values_and_comments": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_input_document_contains_access_to_directive__the_object_s_dictionary_contains_correct_dictionary_with_list_of_access_to_parameters_and_comments": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_input_document_contains_comments_to_type_sections__the_object_s_dictionary_collect_them": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_input_document_contains_index_directives__the_object_s_dictionary_contains_correct_dictionary_with_index_elements_and_comments": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_input_document_contains_syncrepl_and_access_to_constructions_with_action_marks__object_dictionary_contains_correct_dictionary_with_action_marks": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_input_document_contains_syncrepl_directive__the_object_s_dictionary_contains_correct_dictionary_with_list_of_syncrepl_parameters_and_comments": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_logiclines_method_takes_text_with_lines_that_starts_whit_space_symbols__it_returns_joined_lines": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_if_template_text_contains_some_access_to_constuctions_with_same_what_value_and_without_action_marks_for_whole_constructions__they_join_in_one_access_to_construction": true, - "tests/templates/format/test_ldap.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_if_input_document_contains_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_if_parameter_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_if_the_IgnoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_openrc.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_input_document_contains_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_parameter_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_the_IgnoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_postfix.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_if_input_document_contains_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_if_parameter_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_if_the_IgnoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_procmail.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_input_document_contains_blocks_and_parameters_with_action_marks__the_key_tuples_of_parameters_s_have_it_as_its_first_element_inherited": true, - "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_any_values_the_document_object_contains_dictionary_with_this_items_to_delete": true, - "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_input_document_contains_some_block_of_parameters__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_parameters_and_blocks_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value_or_with_special_key_in_block_dictionary": true, - "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_the_ignoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_proftpd.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values_and_sections_to_delete__the_document_object_contains_dictionary_with_item_to_delete": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_sections_with_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_sections_with_similar_names_but_different_parameters__the_parameters_merged_in_one_section": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_parameters_contains_upper_case_symbols__it_becomes_lower_case": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_joinBefore_flag_is_set__the_document_object_contains_dictionary_with_sections_added_in_the_top_of_it": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_parameter_in_input_document_has_some_comments__the_comments_will_be_collected_in_the_list_of_parameter_value": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_if_the_IgnoreComments_flag_is_set__the_parser_ignores_all_comments": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_samba.py::TestParsingMethods::test_make_template": true, - "tests/templates/format/test_xml_gconf.py::TestParsingMethods::test_if_input_document_is_simple_gconf__the_format_object_contains_correct_dictionary": true, - "tests/templates/format/test_xml_gconf.py::TestParsingMethods::test_if_input_document_is_simple_gconf_tree__the_format_object_contains_correct_dictionary": true, - "tests/templates/format/test_xml_gconf.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/format/test_xml_xfce.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary": true, - "tests/templates/format/test_xml_xfce.py::TestParsingMethods::test_joining_documents_1": true, - "tests/templates/test_directory_processor.py::TestDirectoryProcessor::test_just_for_debug_with_package_value": true, - "tests/templates/test_directory_processor.py::TestDirectoryProcessor::test_just_for_debug_without_package_value": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_initialized_accoding_to_dictionary_of_correct_template_parameters__the_TemplateParameters_object_contains_processed_parameters_as_its_attributes_including_default_values": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_as_dir_parameters_object_using_correct_source_parameter_with_append_link__the_object_will_be_initialized_successfully": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_as_dir_parameters_object_using_source_parameter_but_without_append_link__the_initialization_of_the_object_will_be_failed": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_append_parameter__a_value_of_the_parameter_will_be_checked": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_autoupdate_parameter__a_value_of_the_parameter_will_be_checked": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chmod_parameter__the_object_will_be_initialized_successfully": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chmod_parameter_in_its_digital_form__the_object_will_be_initialized_successfully": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chown_parameter__the_object_will_be_initialized_successfully": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chown_parameter_in_its_digital_form__the_object_will_be_initialized_successfully": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_force_parameter__the_object_will_be_initialized_successfully": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_source_parameter__the_object_will_be_initialized_successfully": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_incorrect_autoupdate_parameter__the_initialization_of_the_object_will_be_failed": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_incorrect_chown_parameter__the_initialization_of_the_object_will_be_failed": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_dictionary_with_incorrect_force_parameter__the_initialization_of_the_object_will_be_failed": true, - "tests/templates/test_parameters_processor.py::TestTemplateParameters::test_if_TemplateParameters_object_is_intialized_using_source_parameter_with_unexisting_file_path__the_initialization_of_the_object_will_be_failed": true, - "tests/templates/test_template_action.py::TestTemplateAction::test_chmod_directory": true, - "tests/templates/test_template_action.py::TestTemplateAction::test_chown_directory": true, - "tests/templates/test_template_action.py::TestTemplateAction::test_create_directory": true, - "tests/templates/test_template_action.py::TestTemplateAction::test_link_directory": true, - "tests/templates/test_template_action.py::TestTemplateAction::test_remove_directory": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_binded_with_datavars_module__variables_available_in_a_template": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_calculate_tag_contains_pkg_function_with_an_existing_package_in_its_argument__the_pkg_function_returns_version_value_of_the_package_from_package_parameter_without_any_exceptions": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_calculate_tag_with_some_parameters__the_template_engine_object_will_collect_its_parameters": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_condition_and_it_is_True__the_template_engine_object_will_be_initialized_without_any_exceptions": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_env_parameter_in_which_module_name_is_assigned__the_variables_from_this_module_can_be_used_in_template_without_determining_of_their_module": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_pkg_function_with_existing_package_as_its_argument__it_works_correctly_and_pkg_function_returns_version_value": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_pkg_function_with_package_that_does_not_exist_in_its_argument__it_works_correctly_and_pkg_function_returns_empty_version_value": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_pkg_function_without_any_arguments_and_without_package_parameter_in_calculate_tag__the_pkg_function_returns_empty_version_value": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_pkg_function_without_any_arguments_but_with_package_parameter_in_calculate_tag__the_pkg_function_returns_version_value_of_the_package_from_package_parameter": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_several_calculate_tags__the_template_engine_will_parse_them_all_and_will_contain_all_parameters_and_result_of_all_conditions": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_several_conditions_and_it_is_False__the_template_engine_raises_ConditionFailed_exception": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_an_input_template_contains_variables_in_its_text__the_rendered_text_will_contain_values_of_this_variables": true, - "tests/templates/test_template_engine.py::TestTemplateEngine::test_if_value_of_variable_is_set_using_save_tag__the_new_value_of_variable_can_be_used_in_template": true, - "tests/utils/test_files.py::TestUtils::test_if_a_pipe_Process_object_uses_for_several_writes__it_successfully_executes_even_after_read": true, - "tests/utils/test_files.py::TestUtils::test_if_a_pipe_Process_object_uses_for_several_writes_without_readings__it_successfully_executes": true, - "tests/utils/test_files.py::TestUtils::test_if_pipe_is_executed_using_Process_object__it_has_successfully_executed": true, - "tests/utils/test_files.py::TestUtils::test_if_single_correct_command_executed_using_Process_object__it_successfully_executes": true, - "tests/utils/test_package.py::TestContents::test_if_PackageContents_object_contains_contents_dictionary__it_renders_CONTENTS_file_correctly": true, - "tests/utils/test_package.py::TestContents::test_if_PackageContents_object_initialized_by_existing_package__it_contains_dictionary_of_items_from_contents_file": true, - "tests/utils/test_package.py::TestContents::test_if_new_directory_is_added_in_contents_file_using_add_dir_method__the_PackageContents_object_renders_the_contents_file_with_new_dir": true, - "tests/utils/test_package.py::TestContents::test_if_new_link_is_added_in_contents_file_using_add_sym_method__the_PackageContents_object_renders_the_contents_file_with_new_sym": true, - "tests/utils/test_package.py::TestContents::test_if_new_object_is_added_in_contents_file_using_add_obj_method__the_PackageContents_object_renders_the_contents_file_with_new_obj": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_parsed_a_correct_package_atom_name_but_without_a_slot_and_use_flags__the_PackageAtom_object_returns_atom_name_of_package": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_parsed_a_correct_package_atom_name_with_a_slot_value__the_PackageAtom_returns_atom_name_of_package_with_this_slot": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_parsed_a_correct_package_atom_name_with_a_uses_value__the_PackageAtom_object_returns_atom_name_of_package_with_this_use_flags": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_parsed_a_correct_package_atom_name_with_an_empty_slot_value__the_PackageAtom_object_returns_atom_name_of_package": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_parses_a_correct_package_atom_name_without_version_value_but_with_slot_value__the_PackageAtom_object_looks_for_package_with_assigned_slot_value": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_parses_a_correct_package_atom_name_without_version_value_but_with_use_flags_value__the_PackageAtom_object_looks_for_package_with_assigned_use_flags": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_tried_to_parse_an_correct_package_atom_name_that_matches_multiple_packages__the_PackageAtom_object_gets_info_for_package_with_older_version": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_tried_to_parse_an_incorrect_package_atom_name__the_PackageAtom_object_throws_the_PackageAtomError_exception": true, - "tests/utils/test_package.py::TestContents::test_if_the_PackageAtom_object_tried_to_parse_an_package_atom_name_with_incorrect_use_flags__the_PackageAtom_object_throws_the_PackageAtomError_exception": true, - "tests/utils/test_package.py::TestContents::test_if_the_get_file_package_method_of_the_PackageAtom_object_is_called_with_a_name_of_a_file_that_belongs_to_any_package__the_PackageAtom_object_contains_dictionary_with_an_owner_package": true, - "tests/utils/test_package.py::TestContents::test_if_the_get_file_package_method_of_the_PackageAtom_object_is_called_with_a_name_of_a_file_that_does_not_belong_to_any_package__the_PackageAtom_object_throws_the_PackageAtomError_exception": true, - "tests/utils/test_package.py::TestContents::test_if_two_Version_objects_compared_using_eq_operation_and_the_left_version_value_is_less_than_or_equal_to_the_right_version__the_result_of_the_comparing_would_be_True": true, - "tests/utils/test_package.py::TestContents::test_if_two_Version_objects_compared_using_ge_operation_and_the_left_version_value_is_less_than_or_equal_to_the_right_version__the_result_of_the_comparing_would_be_True": true, - "tests/utils/test_package.py::TestContents::test_if_two_Version_objects_compared_using_gt_operation_and_the_left_version_value_is_less_than_the_right_version__the_result_of_the_comparing_would_be_True": true, - "tests/utils/test_package.py::TestContents::test_if_two_Version_objects_compared_using_le_operation_and_the_left_version_value_is_less_than_or_equal_to_the_right_version__the_result_of_the_comparing_would_be_True": true, - "tests/utils/test_package.py::TestContents::test_if_two_Version_objects_compared_using_lt_operation_and_the_left_version_value_is_less_than_the_right_version__the_result_of_the_comparing_would_be_True": true, - "tests/utils/test_package.py::TestContents::test_if_two_Version_objects_compared_using_ne_operation_and_the_left_version_value_is_less_than_or_equal_to_the_right_version__the_result_of_the_comparing_would_be_True": true, - "tests/vars/test_namespace.py::TestNamespace::test_init_default_path": true, - "tests/vars/test_namespace.py::TestNamespace::test_init_empty_namespace": true + "tests/templates/format/test_regex.py::TestParsingMethods::test_if_input_patch_document_contains_only_regular_expressions_without_any_regex_flags__it_correctly_patches_input_document": true, + "tests/templates/format/test_regex.py::TestParsingMethods::test_if_input_patch_document_contains_regular_expressions_with_global_regex_flags_and_flags_as_attributes__it_correctly_patches_input_document_using_regex_flags": true, + "tests/templates/test_template_action.py::TestTemplateAction::test_create_directory": true } \ No newline at end of file diff --git a/.pytest_cache/v/cache/nodeids b/.pytest_cache/v/cache/nodeids index 8eb49c8..bcc168e 100644 --- a/.pytest_cache/v/cache/nodeids +++ b/.pytest_cache/v/cache/nodeids @@ -115,8 +115,6 @@ "tests/templates/format/test_openrc.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_assign_symbol_and_any_values__the_document_object_contains_dictionary_with_item_to_delete", "tests/templates/format/test_openrc.py::TestParsingMethods::test_joining_documents_1", "tests/templates/format/test_openrc.py::TestParsingMethods::test_make_template", - "tests/templates/format/test_patch.py::TestParsingMethods::test_if_input_patch_document_contains_only_regular_expressions_without_any_regex_flags__it_correctly_patches_input_document", - "tests/templates/format/test_patch.py::TestParsingMethods::test_if_input_patch_document_contains_regular_expressions_with_global_regex_flags_and_flags_as_attributes__it_correctly_patches_input_document_using_regex_flags", "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary", "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary", "tests/templates/format/test_postfix.py::TestParsingMethods::test_if_input_document_contains_parameters_with_action_marks__the_key_tuples_of_object_s_dictionary_have_it_as_its_first_element", @@ -140,6 +138,8 @@ "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_the_ignoreComments_flag_is_set__the_parser_ignores_all_comments", "tests/templates/format/test_proftpd.py::TestParsingMethods::test_if_input_document_contains_parameters_to_delete_without_any_values_the_document_object_contains_dictionary_with_this_items_to_delete", "tests/templates/format/test_proftpd.py::TestParsingMethods::test_joining_documents_1", + "tests/templates/format/test_regex.py::TestParsingMethods::test_if_input_patch_document_contains_only_regular_expressions_without_any_regex_flags__it_correctly_patches_input_document", + "tests/templates/format/test_regex.py::TestParsingMethods::test_if_input_patch_document_contains_regular_expressions_with_global_regex_flags_and_flags_as_attributes__it_correctly_patches_input_document_using_regex_flags", "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_just_few_parameter_lines__the_initialised_object_contains_correct_dictionary", "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_few_parameter_lines_and_some_empty_lines__the_initialized_object_contains_correct_dictionary", "tests/templates/format/test_samba.py::TestParsingMethods::test_if_input_document_contains_sections_with_similar_names_but_different_parameters__the_parameters_merged_in_one_section", diff --git a/calculate/templates/format/diff_format.py b/calculate/templates/format/diff_format.py deleted file mode 100644 index 83740a5..0000000 --- a/calculate/templates/format/diff_format.py +++ /dev/null @@ -1,84 +0,0 @@ -# vim: fileencoding=utf-8 -# -from .base_format import BaseFormat -from ..template_engine import ParametersContainer -from calculate.utils.files import Process -from calculate.templates.format.base_format import FormatError -from os import path - - -class DiffFormat(BaseFormat): - FORMAT = 'diff' - EXECUTABLE = True - - def __init__(self, document_text: str, - join_before=False, - parameters=ParametersContainer()): - self._patch_text = document_text - self._cwd_path = '/' - self._last_level = 0 - - # Измененные файлы. - self.changed_files = dict() - - def execute_format(self, target_path): - '''Метод для запуска работы формата.''' - self._cwd_path = target_path - if not path.isdir(self._cwd_path): - # Если target_path -- путь к файлу, запускаем все процессы из - # директории, в которой этот файл находится. - self._cwd_path = path.dirname(self._cwd_path) - - if not path.exists(self._cwd_path): - raise FormatError('root path does not exist') - - if self._patch_text: - self._patch_document() - return self.changed_files - else: - raise FormatError('empty patch file') - - def _patch_document(self): - '''Метод, производящий наложение патча путем запуска процесса patch.''' - # Сначала определяем на каком уровне накладываем патч. - # Для этого запускаем утилиту patch с --dry-run и смотрим результат - # выполнения. - for level in range(0, 4): - patch_dry_run = Process('patch', '--dry-run', - '-p{}'.format(level), - cwd=self._cwd_path) - patch_dry_run.write(self._patch_text) - if patch_dry_run.success(): - break - - patch_dry_run = Process('patch', '-R', '--dry-run', - '-p{}'.format(level), - cwd=self._cwd_path) - patch_dry_run.write(self._patch_text) - if patch_dry_run.success(): - return '' - else: - raise FormatError('correction failed') - - self._last_level = level - patch_run = Process('patch', '-p{}'.format(level), - cwd=self._cwd_path) - patch_run.write(self._patch_text) - - if patch_run.success(): - for line in patch_run.read_lines(): - if line.startswith('patching file'): - changed_file_path = path.join(self._cwd_path, - line[13:].strip()) - if path.exists(changed_file_path): - self.changed_files.update({changed_file_path: - 'modify'}) - else: - self.changed_files.update({changed_file_path: - 'remove'}) - print('Changings: ') - for file_path, change_type in self.changed_files.items(): - print('{}: {}'.format(file_path, change_type)) - return patch_run.read() - else: - return '' diff --git a/calculate/templates/format/patch_format.py b/calculate/templates/format/patch_format.py index 7a8e839..de70843 100644 --- a/calculate/templates/format/patch_format.py +++ b/calculate/templates/format/patch_format.py @@ -1,183 +1,84 @@ # vim: fileencoding=utf-8 # -from .base_format import BaseFormat, FormatError +from .base_format import BaseFormat from ..template_engine import ParametersContainer -from collections import OrderedDict -import re -try: - from lxml.etree.ElementTree import fromstring -except ImportError: - from xml.etree.ElementTree import fromstring +from calculate.utils.files import Process +from calculate.templates.format.base_format import FormatError +from os import path class PatchFormat(BaseFormat): FORMAT = 'patch' - EXECUTABLE = False - FORMAT_PARAMETERS = {'multiline', 'dotall', 'comment'} + EXECUTABLE = True def __init__(self, document_text: str, - ignore_comments=False, join_before=False, parameters=ParametersContainer()): - processing_methods = OrderedDict() - super().__init__(processing_methods) + self._patch_text = document_text + self._cwd_path = '/' + self._last_level = 0 + # Измененные файлы. self.changed_files = dict() - self._multiline_flag = parameters.multiline - self._dotall_flag = parameters.dotall - self._parsed_patch = None + def execute_format(self, target_path): + '''Метод для запуска работы формата.''' + self._cwd_path = target_path + if not path.isdir(self._cwd_path): + # Если target_path -- путь к файлу, запускаем все процессы из + # директории, в которой этот файл находится. + self._cwd_path = path.dirname(self._cwd_path) - self._document_text = document_text - self._FLAG_VALUES = {'True': True, - 'False': False, - 'true': True, - 'false': False, - '1': True, - '0': False} + if not path.exists(self._cwd_path): + raise FormatError('root path does not exist') - self._XML_ROOT_LINE = '\ - {0}' - - def _parse_patch(self, patch_text): - '''Метод, составляющий из текста шаблона xml документ и разбирающий его - с помощью lxml.''' - xml_patch = self._XML_ROOT_LINE.format(patch_text.strip()) - try: - self._parsed_patch = fromstring(xml_patch) - except Exception: - raise FormatError('can not parse patch document') - - def join_template(self, template): - tmp_multiline = template._multiline_flag - tmp_dotall = template._dotall_flag - - template._multiline_flag = self._multiline_flag - template._dotall_flag = self._dotall_flag - - self._document_text = template._join(self._document_text) - - template._multiline_flag = tmp_multiline - template._dotall_flag = tmp_dotall - - def _join(self, input_text): - '''Метод для запуска наложения патча.''' - self._parse_patch(self._document_text) - - if not input_text.strip() == '': - self._document_to_patch = input_text + if self._patch_text: + self._patch_document() + return self.changed_files else: - return input_text - - if not self._patch_document(input_text): - raise FormatError('Error: Can not run patch.') + raise FormatError('empty patch file') + + def _patch_document(self): + '''Метод, производящий наложение патча путем запуска процесса patch.''' + # Сначала определяем на каком уровне накладываем патч. + # Для этого запускаем утилиту patch с --dry-run и смотрим результат + # выполнения. + for level in range(0, 4): + patch_dry_run = Process('patch', '--dry-run', + '-p{}'.format(level), + cwd=self._cwd_path) + patch_dry_run.write(self._patch_text) + if patch_dry_run.success(): + break + + patch_dry_run = Process('patch', '-R', '--dry-run', + '-p{}'.format(level), + cwd=self._cwd_path) + patch_dry_run.write(self._patch_text) + if patch_dry_run.success(): + return '' else: - after_patch = self._document_to_patch - self._document_to_patch = '' - - return after_patch - - def _patch_document(self, document_to_patch): - '''Метод, обходящий теги шаблона и использующий указанные в нем - регулярные выражения.''' - patch_iterator = self._parsed_patch.getiterator() - PATCH_DOCUMENT_TAGS = ('reg', 'text') - - patch_element = next(patch_iterator, False) - - if not patch_element or not patch_element.tag == 'patch': - raise FormatError('incorrect text of the template') - - while True: - for patch_tag in PATCH_DOCUMENT_TAGS: - patch_element = next(patch_iterator, None) - - if patch_element is None: - if patch_tag == 'text': - raise FormatError('last Text ' - 'object is missed.') + raise FormatError('correction failed') + + self._last_level = level + patch_run = Process('patch', '-p{}'.format(level), + cwd=self._cwd_path) + patch_run.write(self._patch_text) + + if patch_run.success(): + for line in patch_run.read_lines(): + if line.startswith('patching file'): + changed_file_path = path.join(self._cwd_path, + line[13:].strip()) + if path.exists(changed_file_path): + self.changed_files.update({changed_file_path: + 'modify'}) else: - break - - if patch_element.tag == patch_tag: - if patch_element.text is not None: - element_text = patch_element.text.strip() - if element_text == '': - raise FormatError( - ("Error: Incorrect text of the " - "template: <{0}>%s").format( - patch_tag - )) - else: - raise FormatError("Error: Incorrect text of the " - "template: <{0}>").format( - patch_tag - ) - - if patch_tag == 'reg': - dotall = patch_element.attrib.get('dotall', False) - regex_flags = 0 - - if 'multiline' in patch_element.attrib: - multiline = patch_element.attrib['multiline'] - if multiline not in self._FLAG_VALUES: - raise FormatError('invalid multiline value') - else: - multiline = self._FLAG_VALUES[multiline] - - # Если глобально флаг MULTILINE включен, но в - # атрибутах тэга этот флаг присутствует со - # значением False -- для этого регулярного - # выражения этот флаг также будет False. - multiline_global = self._multiline_flag & multiline - else: - multiline = False - multiline_global = self._multiline_flag - - if multiline_global or multiline: - regex_flags |= re.MULTILINE - - if 'dotall' in patch_element.attrib: - dotall = patch_element.attrib['dotall'] - if dotall not in self._FLAG_VALUES: - raise FormatError('invalid dotall value') - else: - dotall = self._FLAG_VALUES[dotall] - - # Если глобально флаг DOTALL включен, но в - # атрибутах тэга этот флаг присутствует со - # значением False -- для этого регулярного - # выражения этот флаг также будет False. - dotall_global = self._dotall_flag & dotall - else: - dotall = False - dotall_global = self._dotall_flag - - if dotall_global or dotall: - regex_flags |= re.DOTALL - - regex_expression = re.compile(element_text, - regex_flags) - else: - text_for_replace = element_text - else: - if patch_element.tag in PATCH_DOCUMENT_TAGS: - error_message = '<{0}> is expected, <{1}> instead.'.\ - format(patch_tag, - patch_element.tag) - else: - error_message = 'unknown tag: {0}'.format( - patch_element.tag - ) - raise ("incorrect text of the template: {}".format( - error_message)) - else: - self._document_to_patch = re.sub(regex_expression, - text_for_replace, - self._document_to_patch) - continue - return True - - @property - def document_text(self): - return self._document_text + self.changed_files.update({changed_file_path: + 'remove'}) + print('Changings: ') + for file_path, change_type in self.changed_files.items(): + print('{}: {}'.format(file_path, change_type)) + return patch_run.read() + else: + return '' diff --git a/calculate/templates/format/regex_format.py b/calculate/templates/format/regex_format.py new file mode 100644 index 0000000..135ca05 --- /dev/null +++ b/calculate/templates/format/regex_format.py @@ -0,0 +1,183 @@ +# vim: fileencoding=utf-8 +# +from .base_format import BaseFormat, FormatError +from ..template_engine import ParametersContainer +from collections import OrderedDict +import re +try: + from lxml.etree.ElementTree import fromstring +except ImportError: + from xml.etree.ElementTree import fromstring + + +class RegexFormat(BaseFormat): + FORMAT = 'regex' + EXECUTABLE = False + FORMAT_PARAMETERS = {'multiline', 'dotall', 'comment'} + + def __init__(self, document_text: str, + ignore_comments=False, + join_before=False, + parameters=ParametersContainer()): + processing_methods = OrderedDict() + super().__init__(processing_methods) + + self.changed_files = dict() + + self._multiline_flag = parameters.multiline + self._dotall_flag = parameters.dotall + self._parsed_patch = None + + self._document_text = document_text + self._FLAG_VALUES = {'True': True, + 'False': False, + 'true': True, + 'false': False, + '1': True, + '0': False} + + self._XML_ROOT_LINE = '\ + {0}' + + def _parse_patch(self, patch_text): + '''Метод, составляющий из текста шаблона xml документ и разбирающий его + с помощью lxml.''' + xml_patch = self._XML_ROOT_LINE.format(patch_text.strip()) + try: + self._parsed_patch = fromstring(xml_patch) + except Exception: + raise FormatError('can not parse patch document') + + def join_template(self, template): + tmp_multiline = template._multiline_flag + tmp_dotall = template._dotall_flag + + template._multiline_flag = self._multiline_flag + template._dotall_flag = self._dotall_flag + + self._document_text = template._join(self._document_text) + + template._multiline_flag = tmp_multiline + template._dotall_flag = tmp_dotall + + def _join(self, input_text): + '''Метод для запуска наложения патча.''' + self._parse_patch(self._document_text) + + if not input_text.strip() == '': + self._document_to_patch = input_text + else: + return input_text + + if not self._patch_document(input_text): + raise FormatError('Error: Can not run patch.') + else: + after_patch = self._document_to_patch + self._document_to_patch = '' + + return after_patch + + def _patch_document(self, document_to_patch): + '''Метод, обходящий теги шаблона и использующий указанные в нем + регулярные выражения.''' + patch_iterator = self._parsed_patch.getiterator() + PATCH_DOCUMENT_TAGS = ('reg', 'text') + + patch_element = next(patch_iterator, False) + + if not patch_element or not patch_element.tag == 'patch': + raise FormatError('incorrect text of the template') + + while True: + for patch_tag in PATCH_DOCUMENT_TAGS: + patch_element = next(patch_iterator, None) + + if patch_element is None: + if patch_tag == 'text': + raise FormatError('last Text ' + 'object is missed.') + else: + break + + if patch_element.tag == patch_tag: + if patch_element.text is not None: + element_text = patch_element.text.strip() + if element_text == '': + raise FormatError( + ("Error: Incorrect text of the " + "template: <{0}>%s").format( + patch_tag + )) + else: + raise FormatError("Error: Incorrect text of the " + "template: <{0}>").format( + patch_tag + ) + + if patch_tag == 'reg': + dotall = patch_element.attrib.get('dotall', False) + regex_flags = 0 + + if 'multiline' in patch_element.attrib: + multiline = patch_element.attrib['multiline'] + if multiline not in self._FLAG_VALUES: + raise FormatError('invalid multiline value') + else: + multiline = self._FLAG_VALUES[multiline] + + # Если глобально флаг MULTILINE включен, но в + # атрибутах тэга этот флаг присутствует со + # значением False -- для этого регулярного + # выражения этот флаг также будет False. + multiline_global = self._multiline_flag & multiline + else: + multiline = False + multiline_global = self._multiline_flag + + if multiline_global or multiline: + regex_flags |= re.MULTILINE + + if 'dotall' in patch_element.attrib: + dotall = patch_element.attrib['dotall'] + if dotall not in self._FLAG_VALUES: + raise FormatError('invalid dotall value') + else: + dotall = self._FLAG_VALUES[dotall] + + # Если глобально флаг DOTALL включен, но в + # атрибутах тэга этот флаг присутствует со + # значением False -- для этого регулярного + # выражения этот флаг также будет False. + dotall_global = self._dotall_flag & dotall + else: + dotall = False + dotall_global = self._dotall_flag + + if dotall_global or dotall: + regex_flags |= re.DOTALL + + regex_expression = re.compile(element_text, + regex_flags) + else: + text_for_replace = element_text + else: + if patch_element.tag in PATCH_DOCUMENT_TAGS: + error_message = '<{0}> is expected, <{1}> instead.'.\ + format(patch_tag, + patch_element.tag) + else: + error_message = 'unknown tag: {0}'.format( + patch_element.tag + ) + raise ("incorrect text of the template: {}".format( + error_message)) + else: + self._document_to_patch = re.sub(regex_expression, + text_for_replace, + self._document_to_patch) + continue + return True + + @property + def document_text(self): + return self._document_text diff --git a/calculate/templates/template_engine.py b/calculate/templates/template_engine.py index 35ad6e4..8e57526 100644 --- a/calculate/templates/template_engine.py +++ b/calculate/templates/template_engine.py @@ -508,15 +508,19 @@ class ParametersProcessor: """Взять uid из chroot passwd файла.""" passwd_file_path = os.path.join(self.chroot_path, 'etc/passwd') passwd_dictionary = [] + if os.path.exists(passwd_file_path): with open(passwd_file_path, 'r') as passwd_file: for line in passwd_file: if line.startswith('#'): continue + passwd_item = tuple(line.split(':')[0:3:2]) + if (len(passwd_item) > 1 and passwd_item[0] and passwd_item[0]): passwd_dictionary.append(passwd_item) + passwd_dictionary = dict(passwd_dictionary) return int(passwd_dictionary[user_name]) else: @@ -527,15 +531,20 @@ class ParametersProcessor: """Взять gid из chroot group файла.""" group_file_path = os.path.join(self.chroot_path, 'etc/group') group_dictionary = [] + if os.path.exists(group_file_path): with open(group_file_path, 'r') as group_file: for line in group_file: if line.startswith('#'): continue + group_item = tuple(line.split(':')[0:3:2]) + if len(group_item) > 1 and group_item[0] and group_item[1]: group_dictionary.append(group_item) + group_dictionary = dict(group_dictionary) + if group_name in group_dictionary: return int(group_dictionary[group_name]) else: diff --git a/pytest.ini b/pytest.ini index 5ce8ff6..a5a799a 100644 --- a/pytest.ini +++ b/pytest.ini @@ -6,14 +6,14 @@ markers = bind: marker for running tests for bind format. compiz: marker for running tests for compiz format. contents: marker for running tests for contents format. - diff: marker for running test for diff format. + patch: marker for running test for patch format. dovecot: marker for running tests for devecot format. json: marker for running tests for json format. kde: marker for running test for kde format. kernel: marker for running test for kernel format. ldap: marker for running test for ldap format. openrc: marker for running test for openrc format. - patch: marker for running test fot patch format. + regex: marker for running test fot regex format. postfix: marker for running test for postfix format. procmail: marker for running test for procmail format. proftpd: marker for running tests for proftpd format. diff --git a/template_action_draft.py b/template_action_draft.py index c5aa8d9..2aa7b18 100644 --- a/template_action_draft.py +++ b/template_action_draft.py @@ -471,14 +471,30 @@ class TemplateWrapper: if self.template_type == DIR: self.target_package.clear_dir(self.target_path) - def add_to_contents(self, file_md5=None): + def add_to_contents(self, file_md5=None, file_path=None): '''Метод для добавления целевого файла в CONTENTS.''' if self.parameters.append == 'link': - self.target_package.add_sym(target_path, self.parameters.source) + self.target_package.add_sym(self.target_path, + self.parameters.source) elif self.template_type == DIR: - self.target_package.add_dir(target_path) + self.target_package.add_dir(self.target_path) elif self.template_type == FILE: - self.target_package.add_obj(target_path, file_md5) + self.target_package.add_obj(self.target_path, file_md5) + + def update_contents_from_list(self, changed_list: dict): + for file_path, mode in changed_list.items(): + if mode == "modify": + if os.path.islink(file_path): + self.target_package.add_sym(file_path) + elif os.path.isdir(file_path): + self.target_package.add_dir(file_path) + elif os.path.isfile(file_path): + self.target_package.add_obj(file_path) + elif mode == "remove": + if os.path.islink(file_path) or os.path.isfile(file_path): + self.target_package.remove_obj(file_path) + elif os.path.isdir(file_path): + self.target_package.add_dir(file_path) @classmethod def _set_protected(cls): @@ -658,14 +674,32 @@ class TemplateExecutor: if template_object.target_type is not None: self._clear_directory(template_object.target_path) + # Меняем права и владельца очищенной директории, если это + # необходимо. + if template_object.parameters.chmod: + self._chmod_directory(target_path, + template_object.parameters.chmod) + + if template_object.parameters.chown: + self._chown_directory(target_path, + template_object.parameters.chown) + template_object.clear_dir_contents() def _append_link_directory(self, template_object: TemplateWrapper): '''Метод описывающий действия для append = "link", если шаблон -- директория. Создает ссылку на директорию, если она есть.''' - target = template_object.parameters.source - link_path = template_object.target_path - self._link_directory(link_path, target) + self._link_directory(template_object.parameters.source, + template_object.target_path) + + # Меняем права и владельца файла, на который указывает ссылка. + if template_object.parameters.chmod: + self._chmod_directory(template_object.parameters.source, + template_object.parameters.chmod) + + if template_object.parameters.chown: + self._chmod_directory(template_object.parameters.source, + template_object.parameters.chown) template_object.add_to_contents() @@ -687,8 +721,33 @@ class TemplateExecutor: output_path = template_object.output_path template_format = template_object.format_class + print('target_path: ', template_object.target_path) + print('output_path: ', output_path) - if template_object.md5_matching: + # Задаемся значениями chmod и chown в зависимости от наличия или + # отсутствия файла. + try: + chmod = template_parameters.chmod + if not chmod: + chmod = self._get_file_mode(template_object.target_path) + elif template_object.target_type is not None: + chmod = self.directory_default_parameters.get('chmod', + False) + + chown = template_parameters.chown + if not chown: + chown = self._get_file_owner(template_object.target_path) + elif template_object.target_type is not None: + chown = self.directory_default_parameters.get('chown', + False) + except OSError: + raise TemplateExecutorError('No access to the directory: {}'. + format(template_object.target_path)) + print('chmod: ', chmod) + print('chown: ', chown) + + if template_object.format_class.EXECUTABLE or\ + template_object.md5_matching: # Действия при совпадении md5 из CONTENTS и md5 целевого файла. output_paths = [output_path] @@ -719,14 +778,14 @@ class TemplateExecutor: with open(save_path, 'w') as output_file: output_file.write(output_text) - if template_object.parameters.chown: - self.chown_file(save_path, - template_object.parameters.chown, + # Меняем права доступа и владельца всех сохраняемых файлов, + # если это необходимо. + if chown: + self.chown_file(save_path, chown, check_existation=False) - if template_object.parameters.chmod: - self.chmod_file(save_path, - template_object.parameters.chmod, + if chmod: + self.chmod_file(save_path, chmod, check_existation=False) # Убираем все ._cfg файлы. @@ -746,24 +805,30 @@ class TemplateExecutor: template_object.add_to_contents( file_md5=output_text_md5) else: - parsed_template.execute_format( + changed_files = parsed_template.execute_format( input_text=input_text, target_path=template_object.target_path) # Удаляем форматный объект входного файла. del(parsed_template) + # Если исполняемый формат выдал список измененных файлов для + # изменения CONTENTS -- обновляем CONTENTS. + if changed_files: + template_object.update_contents_from_list(changed_files) else: if template_object.target_type is not None and not replace: with open(input_path, 'r') as input_file: input_text = input_file.read() - parsed_input = template_format(input_text) else: input_text = '' + parsed_input = template_format(input_text) parsed_template = template_format(template_object.template_text) + parsed_input.join_template(parsed_template) # Результат наложения шаблона. output_text = parsed_input.document_text + # Удаляем форматный объект входного файла. del(parsed_input) output_text_md5 = hashlib.md5(output_text.encode()).hexdigest() @@ -773,16 +838,18 @@ class TemplateExecutor: with open(output_path, 'w') as output_file: output_file.write(output_text) - if template_object.parameters.chown: - self.chown_file(output_path, - template_object.parameters.chown, + # Меняем права доступа и владельца ._cfg????_ файлов, если + # это необходимо. + if chown: + self.chown_file(output_path, chown, check_existation=False) - if template_object.parameters.chmod: + if chmod: self.chmod_file(output_file, template_object.parameters.chmod, check_existation=False) + # Обновляем CL. self.calculate_config_file.set_files_md5( template_object.target_path, output_text_md5) @@ -794,90 +861,125 @@ class TemplateExecutor: template_object.add_to_contents(file_md5=output_text_md5) def _append_after_file(self, template_object: TemplateWrapper): + '''Метод описывающий действия при append = "after", если шаблон -- + файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся + в конец файла и в конец каждой секции файла.''' self._append_join_file(template_object, join_before=False) def _append_before_file(self, template_object: TemplateWrapper): + '''Метод описывающий действия при append = "after", если шаблон -- + файл. Объединяет шаблон с целевым файлом так, чтобы текст добавлялся + в начало файла и в начало каждой секции файла.''' self._append_join_file(template_object, join_before=True) def _append_skip_file(self, template_object: TemplateWrapper): + '''Метод описывающий действия при append = "skip". Пока никаких + действий.''' pass def _append_replace_file(self, template_object: TemplateWrapper): + '''Метод описывающий действия при append = "replace", если шаблон -- + файл. Очищает файл и затем накладывает на него шаблон.''' self._append_join_file(template_object, replace=True) def _append_remove_file(self, template_object: TemplateWrapper): + '''Метод описывающий действия при append = "remove", если шаблон -- + файл. Удаляет файл.''' if template_object.target_type is not None: self._remove_file(template_object.target_path) template_object.remove_from_contents() def _append_clear_file(self, template_object: TemplateWrapper): + '''Метод описывающий действия при append = "clear", если шаблон -- + файл. Очищает файл.''' if template_object.target_type is not None: self._clear_file(template_object.target_path) - else: - open(template_object.target_path, 'w').close() - template_object.add_to_contents() + # Меняем владельца и права доступа к очищенному файлу, если нужно. + if template_object.chown: + self.chown_file(template_object.target_path, + template_object.parameters.chown) - def _append_link_file(self, template_object: TemplateWrapper): - if template_object.target_type is not None: - self._link_file(template_object.target_path, - template_object.parameters.source) + if template_object.chmod: + self.chmod_file(template_object.target_path, + template_object.parameters.chown) template_object.add_to_contents() + def _append_link_file(self, template_object: TemplateWrapper): + '''Метод описывающий действия при append = "link", если шаблон -- + файл. Создает ссылку на файл, указанный в параметре source.''' + self._link_file(template_object.parameters.source, + template_object.parameters.target_path) + + # Меняем права и владельца файла, на который указывает ссылка. + if template_object.parameters.chmod: + self.chmod_file(template_object.parameters.source, + template_object.parameters.chmod) + + if template_object.parameters.chown: + self.chmod_file(template_object.parameters.source, + template_object.parameters.chown) + + template_object.add_to_contents() + def _create_directory(self, template_object: TemplateWrapper): '''Метод для создания директории и, при необходимости, изменения владельца и доступа все директорий на пути к целевой.''' target_path = template_object.target_path template_parameters = template_object.parameters + # Если файл есть, но указан chmod или chown -- используем их. if os.access(target_path, os.F_OK): if template_parameters.chmod: - self.chmod_directory(target_path) + self._chmod_directory(target_path, template_parameters.chmod) - if self.template_parameters.chown: - self.chown_directory(target_path) + if template_parameters.chown: + self._chown_directory(target_path, template_parameters.chown) return directories_to_create = [target_path] directory_path = os.path.dirname(target_path) + # Составляем список путей к директориям, которые нужно создать. while not os.access(directory_path, os.F_OK) and directory_path: directories_to_create.append(directory_path) directory_path = os.path.dirname(directory_path) + # получаем информацию о владельце и правах доступа ближайшей + # существующей директории. try: - current_mod, current_uid, current_gid = self.get_file_info( - directory_path, - 'all') - current_owner = {'uid': current_uid, 'gid': current_gid} + chmod = template_parameters.chmod + if not chmod: + chmod = self._get_file_mode(directory_path) + else: + chmod = self.directory_default_parameters.get('chmod', False) + + chown = template_parameters.chown + if not chown: + chown = self._get_file_owner(directory_path) + else: + chown = self.directory_default_parameters.get('chown', False) except OSError: - raise TemplateExecutorError('No access to the directory: {}'. - format(directory_path)) + raise TemplateExecutorError('No access to the directory: {}'. + format(directory_path)) directories_to_create.reverse() + # создаем директории. for create_path in directories_to_create: try: os.mkdir(create_path) - if (template_parameters.chmod and - template_parameters.chmod != current_mod): - self.chmod_directory(create_path) - elif 'chmod' in self.directory_default_parameters: - self.chmod_directory( - create_path, - chmod_value=self.directory_default_parameters['chown']) - - if (template_parameters.chown and - template_parameters.chown != current_owner): - self.chown_directory(create_path) - elif 'chown' in self.directory_default_parameters: - self.chown_directory( - create_path, - chown_value=self.directory_default_parameters['chmod']) + # Для каждой созданной директории меняем права и владельца + # если это необходимо. + if chmod: + self._chmod_directory(create_path, chmod) + + if chown: + self._chown_directory(create_path, chown) except OSError as error: raise TemplateExecutorError( @@ -911,11 +1013,13 @@ class TemplateExecutor: '''Метод для очистки содержимого целевой директории.''' if os.path.exists(target_path): if os.path.isdir(target_path): + # Удаляем все содержимое директории. for node in os.scandir(target_path): if node.is_dir(): self._remove_directory(node.path) else: self._remove_file(node.path) + return else: error_message = "target file is not directory" else: @@ -925,7 +1029,7 @@ class TemplateExecutor: " reason: {}").format(target_path, error_message)) - def _link_directory(self, target_path, source): + def _link_directory(self, source, target_path): '''Метод для создания по целевому пути ссылки на директорию расположенную на пути, указанному в source.''' try: @@ -958,7 +1062,7 @@ class TemplateExecutor: raise TemplateExecutorError("failed to clear the file: {}". format(target_path)) - def _link_file(self, target_path, source): + def _link_file(self, source, target_path): '''Метод для создания по целевому пути ссылки на файл расположенный на пути, указанному в source.''' try: @@ -968,52 +1072,6 @@ class TemplateExecutor: "Failed to create symlink to the file: {0} -> {1}". format(target_path, self.source)) - def chown_directory(self, target_path, chown_value={}): - """Метод для смены владельца директории.""" - if not chown_value: - chown_value = self.template_parameters.chown - print('chown value = {}'.format(chown_value)) - try: - os.chown(target_path, chown_value['uid'], chown_value['gid']) - except (OSError, Exception) as error: - # возможно потребуются дополнительные проверки. - raise TemplateExecutorError( - 'Can not chown directory: {0}, reason: {1}'. - format(target_path, str(error))) - - def chmod_directory(self, target_path, chmod_value=False): - '''Метод для смены прав доступа к директории.''' - if not chmod_value: - chmod_value = self.template_parameters.chmod - try: - os.chmod(target_path, chmod_value) - except (OSError, Exception) as error: - # возможно потребуются дополнительные проверки. - self.output.set_error('Can not chmod directory: {0}, reason: {1}'. - format(target_path, str(error))) - - def chown_file(self, target_path, chown_value, check_existation=True): - '''Метод для смены владельца файла.''' - try: - if check_existation and not os.path.exists(target_path): - open(target_path, 'w').close() - os.lchown(target_path, chown_value['uid'], chown_value['gid']) - except (OSError, Exception) as error: - # возможно потребуются дополнительные проверки. - raise TemplateExecutorError('Can not chown file: {0}, reason: {1}'. - format(target_path, str(error))) - - def chmod_file(self, target_path, chmod_value, check_existation=True): - '''Метод для смены прав доступа к директории.''' - try: - if check_existation and not os.path.exists(target_path): - open(target_path, 'w').close() - os.chmod(target_path, chmod_value) - except (OSError, Exception) as error: - # возможно потребуются дополнительные проверки. - raise TemplateExecutorError('Can not chmod file: {0}, reason: {1}'. - format(target_path, str(error))) - def _run_template(self, template_object: TemplateWrapper): '''Метод для сохранения текста шаблонов, который должен быть исполнен интерпретатором указанным в run прямо во время обработки шаблонов.''' @@ -1045,18 +1103,24 @@ class TemplateExecutor: ''' text_to_run = template_object.template_text interpreter = template_object.parameters.exec + + # Получаем путь к директории для хранения файлов .execute. if (self.chroot_path != '/' and not self.exec_files_directory.startswith(self.chroot_path)): exec_files_directory = join_paths(self.chroot_path, '/var/lib/calculate/.execute/') + # Если директория уже существует получаем номер очередного файла для + # exec по номеру последнего. exec_number = 0 if os.path.exists(exec_files_directory): exec_files_list = os.listdir(exec_files_directory) if exec_files_list: exec_number = int(exec_files_list[-1][-4:]) + exec_number = str(exec_number + 1) + # Получаем название нового exec_???? файла. if len(exec_number) < 4: exec_number = '0' * (4 - len(exec_number)) + exec_number exec_file_name = 'exec_{}'.format(exec_number) @@ -1067,63 +1131,119 @@ class TemplateExecutor: exec_file.write(text_to_run) exec_file.close() + # Добавляем новый файл в словарь файлов для дальнейшего исполнения. self.executor_output['exec_file'] = {interpreter: exec_file_name} - def get_file_info(self, path, info='all'): - file_stat = os.stat(path) - if info == 'all': - return stat.S_IMODE(file_stat.st_mode), file_stat.st_uid,\ - file_stat.st_gid - if info == 'mode': - return stat.S_IMODE(file_stat.st_mode) - if info == 'owner': - return file_stat.st_uid, file_stat.st_gid - - def set_uid_gid_error(self, path, uid, gid, template_path=''): + def _chown_directory(self, target_path, chown_value): + """Метод для смены владельца директории.""" + try: + os.chown(target_path, chown_value['uid'], chown_value['gid']) + except (OSError, Exception) as error: + if not self._check_os_error(error, target_path): + raise TemplateExecutorError( + 'Can not chown file: {0} to {1}, reason: {2}'. + format(target_path, self._translate_uid_gid( + target_path, + chown_value['uid'], + chown_value['gid']), + str(error))) + + def _chmod_directory(self, target_path, chmod_value): + '''Метод для смены прав доступа к директории.''' + try: + os.chmod(target_path, chmod_value) + except (OSError, Exception) as error: + if not self._check_os_error(error, target_path): + self.output.set_error( + 'Can not chmod directory: {0}, reason: {1}'. + format(target_path, str(error))) + + def chown_file(self, target_path, chown_value, check_existation=True): + '''Метод для смены владельца файла.''' + try: + if check_existation and not os.path.exists(target_path): + open(target_path, 'w').close() + os.lchown(target_path, chown_value['uid'], chown_value['gid']) + except (OSError, Exception) as error: + if not self._check_os_error(error, target_path): + raise TemplateExecutorError( + 'Can not chown file: {0} to {1}, reason: {2}'. + format(target_path, self._translate_uid_gid( + target_path, + chown_value['uid'], + chown_value['gid']), + str(error))) + + def chmod_file(self, target_path, chmod_value, check_existation=True): + '''Метод для смены прав доступа к директории.''' + try: + if check_existation and not os.path.exists(target_path): + open(target_path, 'w').close() + os.chmod(target_path, chmod_value) + except (OSError, Exception) as error: + if not self._check_os_error(error, target_path): + raise TemplateExecutorError( + 'Can not chmod file: {0}, reason: {1}'. + format(target_path, str(error))) + + def _get_file_mode(self, file_path): + '''Метод для получения прав доступа для указанного файла.''' + file_stat = os.stat(file_path) + return stat.S_IMODE(file_stat.st_mode) + + def _get_file_owner(self, file_path): + '''Метод для получения uid и gid значений для владельца указанного + файла.''' + file_stat = os.stat(file_path) + return {'uid': file_stat.st_uid, 'gid': file_stat.st_gid} + + def _translate_uid_gid(self, target_path, uid, gid): + '''Метод для получения из uid и gid имен пользователя и группы при, + необходимых для выдачи сообщения об ошибке при попытке chown.''' import pwd import grp + try: - user_name = pwd.getpwuid(uid).pw_name + if self.chroot_path == '/': + user_name = pwd.getpwuid(uid).pw_name + else: + user_name = str(uid) except (TypeError, KeyError): user_name = str(uid) + try: - group_name = grp.getgrgid(gid).gr_name + if self.chroot_path == '/': + group_name = grp.getgrgid(gid).gr_name + else: + user_name = str(gid) except (TypeError, KeyError): group_name = str(gid) - owner = '{0}:{1}'.format(user_name, group_name) - if template_path: - self.output.set_error('Failed to process template file {}'. - template_path) - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # !! описать ошибку !! - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - self.output.set_error('error with owner: {}'.format(owner)) - - def check_filesystem(self, target_path): - '''Метод, который предположительно будет использоваться для проверки - файловой системы перед применением шаблона.''' - pass - def is_vfat(self, path): + return '{0}:{1}'.format(user_name, group_name) + + def _check_os_error(self, error, path_to_check): + '''Метод для проверки причины, по которой не удалось изменить владельца + или права доступа файла.''' + if hasattr(error, 'errno') and error.errno == os.errno.EPERM: + if self.is_vfat(path_to_check): + return True + + return hasattr(error, 'errno') and error.errno == os.errno.EACCES and\ + 'var/calculate/remote' in path_to_check + + def _is_vfat(self, path_to_check): '''Метод, проверяющий является ли файловая система vfat. Нужно для того, - чтобы заранее знать о возможности применения chown, chmod и т.д.''' + чтобы знать о возможности применения chown, chmod и т.д.''' + # Инициализируем объект для проверки примонтированных файловых систем. if self.mounts is None: self.mounts = Mounts() - if self.mounts.get_from_fstab(what=self.mounts.TYPE, - where=self.mounts.DIR, - is_in=path) in ('vfat', 'ntfs-3g', - 'ntfs'): - return True - return False - - def check_os_error(self, error, path): - if hasattr(error, 'errno') and error.errno == os.errno.EPERM: - if self.is_vfat(path): - return True - if hasattr(error, 'errno') and error.errno == os.errno.EACCES and\ - 'var/calculate/remote' in path: - return True - return False + + # Проверяем файловую систему на пути. + return self.mounts.get_from_fstab(what=self.mounts.TYPE, + where=self.mounts.DIR, + is_in=path_to_check) in {'vfat', + 'ntfs-3g', + 'ntfs'} # Применение основного шаблона: diff --git a/tests/templates/format/test_diff.py b/tests/templates/format/test_diff.py index 65a3470..7a21a15 100644 --- a/tests/templates/format/test_diff.py +++ b/tests/templates/format/test_diff.py @@ -1,11 +1,11 @@ import pytest -from calculate.templates.format.diff_format import DiffFormat +from calculate.templates.format.patch_format import PatchFormat from calculate.utils.files import Process from os import path import os -@pytest.mark.diff +@pytest.mark.patch class TestExecuteMethods: def test_if_diff_patch_used_for_patching_of_several_files__it_changes_patched_file_correctly(self): test_result = True @@ -13,7 +13,7 @@ class TestExecuteMethods: with open(path.join(cwd_path, 'diff_1.patch')) as patch_file: patch_text = patch_file.read() - diff_patch = DiffFormat(patch_text) + diff_patch = PatchFormat(patch_text) print('Path:', cwd_path) output = diff_patch.execute_format(target_path=cwd_path) print('Output:') @@ -51,14 +51,14 @@ class TestExecuteMethods: def test_if_diff_patch_used_for_patching_of_directories__it_changes_files_in_directories_and_adds_ones(self): test_result = True cwd_path = path.join(os.getcwd(), - 'tests/templates/format/testfiles/a1') + 'tests/templates/format/testfiles/a1') patch_path = path.join(os.getcwd(), 'tests/templates/format/testfiles/diff_2.patch') with open(path.join(patch_path)) as patch_file: patch_text = patch_file.read() - diff_patch = DiffFormat(patch_text) - output = diff_patch.execute_format(target_path=cwd_path) + diff_patch = PatchFormat(patch_text) + diff_patch.execute_format(target_path=cwd_path) for changed_file, change_type in\ diff_patch.changed_files.items(): @@ -73,15 +73,18 @@ class TestExecuteMethods: 'b1', changed_file) with open(other_file_path) as other_file: other_file_text = other_file.read() - test_result = test_result and (other_file_text == patched_file_text) + print('test_result =', test_result) + test_result = test_result and ( + other_file_text == patched_file_text) + print('test_result =', test_result) if not test_result: - # print('Differences:') + print('Differences:') try: diff_process = Process('diff', '-u', file_path, other_file_path) diff_result = diff_process.read() - # print(diff_result) + print(diff_result) except Exception as error: print('diff was not executed.') print('Reason:', str(error)) @@ -90,11 +93,10 @@ class TestExecuteMethods: '-p{}'.format(diff_patch._last_level), cwd=cwd_path) reverse_patch_run.write(patch_text) - output = reverse_patch_run.read() + reverse_patch_run.read() if reverse_patch_run.success(): print('[*] Changes was returned...') else: print('[!] Changes was not returned...') assert test_result - assert False diff --git a/tests/templates/format/test_patch.py b/tests/templates/format/test_regex.py similarity index 89% rename from tests/templates/format/test_patch.py rename to tests/templates/format/test_regex.py index d8faa68..20e1e61 100644 --- a/tests/templates/format/test_patch.py +++ b/tests/templates/format/test_regex.py @@ -1,10 +1,10 @@ import pytest from collections import OrderedDict -from calculate.templates.format.patch_format import PatchFormat +from calculate.templates.format.regex_format import RegexFormat from calculate.templates.template_engine import ParametersContainer -@pytest.mark.patch +@pytest.mark.regex class TestParsingMethods: def test_if_input_patch_document_contains_only_regular_expressions_without_any_regex_flags__it_correctly_patches_input_document(self): input_text = ''' @@ -29,8 +29,8 @@ Another line of endless sadness. ParameterName = NewValue ''' - patch_original = PatchFormat(input_text) - patch_template = PatchFormat(patch_text) + patch_original = RegexFormat(input_text) + patch_template = RegexFormat(patch_text) patch_original.join_template(patch_template) assert patch_original.document_text == output_text @@ -78,8 +78,8 @@ Another line of endless sadness. parameters = ParametersContainer({'multiline': True, 'dotall': True}) - patch_original = PatchFormat(input_text, parameters=parameters) - patch_template = PatchFormat(patch_text, parameters=parameters) + patch_original = RegexFormat(input_text, parameters=parameters) + patch_template = RegexFormat(patch_text, parameters=parameters) patch_original.join_template(patch_template) assert patch_original.document_text == output_text diff --git a/tests/templates/format/testfiles/a1/dir/file1.txt b/tests/templates/format/testfiles/a1/dir/file1.txt index 023bd50..8393bcc 100644 --- a/tests/templates/format/testfiles/a1/dir/file1.txt +++ b/tests/templates/format/testfiles/a1/dir/file1.txt @@ -3,6 +3,7 @@ CONFIG_BUILDTIME_EXTABLE_SORT=y # # General setup # +CONFIG_BUILD_SALT="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_XZ=y diff --git a/tests/templates/format/testfiles/b1/dir/file1.txt b/tests/templates/format/testfiles/b1/dir/file1.txt index 8393bcc..474f6f7 100644 --- a/tests/templates/format/testfiles/b1/dir/file1.txt +++ b/tests/templates/format/testfiles/b1/dir/file1.txt @@ -1,11 +1,17 @@ CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y # # General setup # +CONFIG_INIT_ENV_ARG_LIMIT=16 +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set CONFIG_BUILD_SALT="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y CONFIG_HAVE_KERNEL_LZ4=y diff --git a/tests/templates/format/testfiles/diff_1.patch b/tests/templates/format/testfiles/diff_1.patch index 14edf64..d505f5e 100644 --- a/tests/templates/format/testfiles/diff_1.patch +++ b/tests/templates/format/testfiles/diff_1.patch @@ -1,6 +1,6 @@ diff -urN a/dir/file1.txt b/dir/file1.txt ---- a/dir/file1.txt 2020-01-29 14:38:21.216540100 +0300 -+++ b/dir/file1.txt 2020-01-29 14:40:19.200542500 +0300 +--- a/dir/file1.txt 2020-06-01 11:43:36.661218600 +0300 ++++ b/dir/file1.txt 2020-02-06 12:49:10.941240900 +0300 @@ -1,10 +1,17 @@ CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -20,8 +20,8 @@ diff -urN a/dir/file1.txt b/dir/file1.txt CONFIG_HAVE_KERNEL_LZO=y CONFIG_HAVE_KERNEL_LZ4=y diff -urN a/dir/file2.txt b/dir/file2.txt ---- a/dir/file2.txt 2020-01-29 14:35:45.112536800 +0300 -+++ b/dir/file2.txt 2020-01-29 13:47:05.475437800 +0300 +--- a/dir/file2.txt 2020-06-01 11:43:36.693218600 +0300 ++++ b/dir/file2.txt 2020-02-06 12:49:10.949240900 +0300 @@ -8,3 +8,9 @@ The old familiar sting Try to kill it all away diff --git a/tests/templates/format/testfiles/diff_2.patch b/tests/templates/format/testfiles/diff_2.patch index eecd2c6..4b85fa4 100644 --- a/tests/templates/format/testfiles/diff_2.patch +++ b/tests/templates/format/testfiles/diff_2.patch @@ -1,7 +1,7 @@ -diff -Naru a1/dir/file1.txt b1/dir/file1.txt ---- a1/dir/file1.txt 2020-01-29 16:12:32.179927200 +0300 -+++ b1/dir/file1.txt 2020-01-29 15:54:03.080863300 +0300 -@@ -1,10 +1,17 @@ +diff -Naur a1/dir/file1.txt b1/dir/file1.txt +--- a1/dir/file1.txt 2020-06-01 12:07:06.845725100 +0300 ++++ b1/dir/file1.txt 2020-06-01 12:07:16.085725300 +0300 +@@ -1,11 +1,17 @@ CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y @@ -12,16 +12,16 @@ diff -Naru a1/dir/file1.txt b1/dir/file1.txt +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_BUILD_SALT="" + CONFIG_BUILD_SALT="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y CONFIG_HAVE_KERNEL_LZ4=y -diff -Naru a1/dir/file2.txt b1/dir/file2.txt +diff -Naur a1/dir/file2.txt b1/dir/file2.txt --- a1/dir/file2.txt 1970-01-01 03:00:00.000000000 +0300 -+++ b1/dir/file2.txt 2020-01-29 13:47:05.475437800 +0300 ++++ b1/dir/file2.txt 2020-06-01 11:44:54.825220300 +0300 @@ -0,0 +1,16 @@ +Nine Inch Nails -- Hurt + diff --git a/tests/templates/testfiles/test_root/etc/dir/file.conf b/tests/templates/testfiles/test_root/etc/dir/file.conf deleted file mode 100644 index afd6900..0000000 --- a/tests/templates/testfiles/test_root/etc/dir/file.conf +++ /dev/null @@ -1,5 +0,0 @@ -[section one] - parameter_1 = value - parameter_2 = value_2 -[section two] - other_parameter = other_value diff --git a/tests/templates/testfiles/test_root/var/db/pkg/test-category/test-package-1.0/CONTENTS b/tests/templates/testfiles/test_root/var/db/pkg/test-category/test-package-1.0/CONTENTS index f3222cc..e69de29 100644 --- a/tests/templates/testfiles/test_root/var/db/pkg/test-category/test-package-1.0/CONTENTS +++ b/tests/templates/testfiles/test_root/var/db/pkg/test-category/test-package-1.0/CONTENTS @@ -1,3 +0,0 @@ -dir /etc -dir /etc/dir -obj /etc/dir/file.conf 0b87fea7f5b65cac5012baa2bf647e72 1590764349 diff --git a/tests/templates/testfiles/test_root/var/lib/calculate/config-archive/etc/dir/file.conf b/tests/templates/testfiles/test_root/var/lib/calculate/config-archive/etc/dir/file.conf index afd6900..0bc8d65 100644 --- a/tests/templates/testfiles/test_root/var/lib/calculate/config-archive/etc/dir/file.conf +++ b/tests/templates/testfiles/test_root/var/lib/calculate/config-archive/etc/dir/file.conf @@ -1,5 +1,5 @@ [section one] - parameter_1 = value - parameter_2 = value_2 -[section two] - other_parameter = other_value + parameter_1 = value_1 +# Source file +[section_name] + rare_parameter = eternal_value