def test_read_files(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert len(cf.files) == 2 assert [fc.path for fc in cf.files] == ['pkg/__init__.py', 'version.txt']
def test_read_plain_variables(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert cf.__config_version__ == 1
def test_read_config_missing_vcs(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert cf.vcs is None
def test_read_release_notes_not_present(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert cf.release_notes == []
def test_read_global_variables_without_globals( temp_empty_dir, config_file_content_without_globals, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content_without_globals, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert cf.globals == {}
def test_read_illegal_config_file(temp_empty_dir, illegal_config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, illegal_config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) with pytest.raises(pc.ConfigurationVersionError) as exc: pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert str(exc.value) == "Unsupported configuration file version 2"
def test_read_empty_actions(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert 'punch:increase' in cf.actions assert 'punch:set' in cf.actions
def test_read_version_missing_version( temp_empty_dir, config_file_content_without_globals_without_version, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content_without_globals_without_version, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) with pytest.raises(ValueError): pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name))
def test_read_empty_actions(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) expected_value = {} assert cf.actions == expected_value
def test_read_global_variables(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) expected_dict = {'serializer': '{{major}}.{{minor}}.{{patch}}'} assert cf.globals == expected_dict
def test_read_empty_config_file(temp_empty_dir, empty_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, empty_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) with pytest.raises(ValueError) as exc: pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert str(exc.value) == \ "Given config file is invalid: missing '__config_version__' variable"
def test_read_vcs_missing_name(temp_empty_dir, config_file_content_with_wrong_vcs, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content_with_wrong_vcs, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) with pytest.raises(ValueError) as exc: pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) assert str(exc.value) == "Missing key 'name' in VCS configuration"
def test_read_release_notes(temp_empty_dir, config_file_content_with_release_notes, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content_with_release_notes, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) expected = [('HISTORY.rst', '^{{version}} (')] assert cf.release_notes == expected
def test_read_actions(temp_empty_dir, config_file_content_with_actions, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content_with_actions, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) expected_value = { 'mbuild': { 'type': 'refresh', 'refresh_fields': ['year', 'month'], 'fallback_field': 'build' } } assert cf.actions == expected_value
def test_read_vcs(temp_empty_dir, config_file_content_with_vcs, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content_with_vcs, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) expected_dict = { 'name': 'git', 'commit_message': "Version updated to {{ new_version }}", 'options': { 'make_release_branch': False, 'annotate_tags': False, 'annotation_message': '', } } assert cf.vcs == expected_dict
def test_read_version(temp_empty_dir, config_file_content, config_file_name, version_file_content, version_file_name): clean_previous_imports() write_file(temp_empty_dir, config_file_content, config_file_name) write_file(temp_empty_dir, version_file_content, version_file_name) cf = pc.PunchConfig(os.path.join(temp_empty_dir, config_file_name)) expected_value = [{ 'name': 'major', 'type': 'integer' }, { 'name': 'minor', 'type': 'integer' }, { 'name': 'patch', 'type': 'integer' }] assert cf.version == expected_value
def args_check_options(args): if not any([args.part, args.set_part, args.action]): fatal_error("You must specify one of --part, --set-part, or --action") set_options = [ i is not None for i in [args.part, args.set_part, args.action] ] if sum(set_options) > 1: fatal_error( "You can only specify one of --part, --set-part, or --action") if args.set_part and args.reset_on_set: set_parts = args.set_part.split(',') if len(set_parts) > 1: fatal_error( "If you specify --reset-on-set you may set only one value") try: config = cfr.PunchConfig(args.config_file) except (cfr.ConfigurationVersionError, ValueError) as exc: fatal_error("An error occurred while reading the configuration file.", exc) if len(config.files) == 0: fatal_error("You didn't configure any file") if args.part: args.action = "punch:increase" args.action_options = "part={}".format(args.part) elif args.set_part: args.action = "punch:set" args.action_options = args.set_part if args.action and args.action not in config.actions: fatal_error("The requested action {} is not defined.".format( args.action)) return config
def main(original_args=None): parser = argparse.ArgumentParser( description="Manages file content with versions.") parser.add_argument('-c', '--config-file', action='store', help="Config file", default=default_config_file_name) parser.add_argument('-v', '--version-file', action='store', help="Version file", default=default_version_file_name) parser.add_argument('-p', '--part', action='store') parser.add_argument('--set-part', action='store') parser.add_argument('--reset-on-set', action='store_true') parser.add_argument('--verbose', action='store_true', help="Be verbose") parser.add_argument('--version', action='store_true', help="Print the Punch version and project information") parser.add_argument( '--init', action='store_true', help= "Writes default initialization files (does not overwrite existing ones)" ) parser.add_argument( '-s', '--simulate', action='store_true', help= "Simulates the version increment and prints a summary of the relevant data" ) args = parser.parse_args() # These are here just to avoid "can be not defined messages" by linters config = None repo = None if args.version is True: print("Punch version {}".format(punch.__version__)) print("Copyright (C) 2016 Leonardo Giordani") print("This is free software, see the LICENSE file.") print("Source: https://github.com/lgiordani/punch") print("Documentation: http://punch.readthedocs.io/en/latest/") sys.exit(0) if args.init is True: if not os.path.exists(default_config_file_name): with open(default_config_file_name, 'w') as f: f.write(default_config_file_content) if not os.path.exists(default_version_file_name): with open(default_version_file_name, 'w') as f: f.write(default_version_file_content) sys.exit(0) if args.part is None and args.set_part is None: fatal_error("You must either specify --part or --set-part") if args.set_part and args.reset_on_set: set_parts = args.set_part.split(',') if len(set_parts) > 1: fatal_error( "If you specify --reset-on-set you may set only one value") if args.verbose: print("## Punch version {}".format(punch.__version__)) try: config = cfr.PunchConfig(args.config_file) except (cfr.ConfigurationVersionError, ValueError) as exc: fatal_error("An error occurred while reading the configuration file.", exc) if not args.simulate: if len(config.files) == 0: fatal_error("You didn't configure any file") current_version = ver.Version.from_file(args.version_file, config.version) new_version = current_version.copy() if args.part: new_version.inc(args.part) if args.set_part: if args.reset_on_set: part, value = args.set_part.split('=') new_version.set_and_reset(part, value) else: set_dict = dict(i.split('=') for i in args.set_part.split(',')) new_version.set(set_dict) global_replacer = rep.Replacer(config.globals['serializer']) current_version_string, new_version_string = global_replacer.run_main_serializer( current_version.as_dict(), new_version.as_dict()) if config.vcs is not None: special_variables = { 'current_version': current_version_string, 'new_version': new_version_string } vcs_configuration = vcsc.VCSConfiguration.from_dict( config.vcs, config.globals, special_variables) else: vcs_configuration = None if args.simulate: print("* Current version") show_version_parts(current_version.values) print("\n* New version") show_version_parts(new_version.values) changes = global_replacer.run_all_serializers( current_version.as_dict(), new_version.as_dict()) print("\n* Global version updates") show_version_updates(changes) print("\nConfigured files") for file_configuration in config.files: updater = fu.FileUpdater(file_configuration) print("* {}: ".format(file_configuration.path)) changes = updater.get_summary(current_version.as_dict(), new_version.as_dict()) show_version_updates(changes) if vcs_configuration is not None: print("\nVersion control configuration") print("Name:", vcs_configuration.name) print("Commit message", vcs_configuration.commit_message) print("Options:", vcs_configuration.options) else: if vcs_configuration is not None: if vcs_configuration.name == 'git': repo_class = gr.GitRepo elif vcs_configuration.name == 'git-flow': repo_class = gfr.GitFlowRepo else: fatal_error( "The requested version control system {} is not supported." .format(vcs_configuration.name)) try: repo = repo_class(os.getcwd(), vcs_configuration) except rex.RepositorySystemError as exc: fatal_error( "An error occurred while initializing the version control repository", exc) else: repo = None if vcs_configuration is not None: # TODO: Create a fake UseCase to allow running this without a repo and outside this nasty if uc = ruc.VCSReleaseUseCase(repo) uc.pre_start_release() uc.start_release() for file_configuration in config.files: if args.verbose: print("* Updating file {}".format(file_configuration.path)) updater = fu.FileUpdater(file_configuration) updater.update(current_version.as_dict(), new_version.as_dict()) with open(args.version_file, 'w') as f: if args.verbose: print("* Updating version file") for i in new_version.keys: f.write('{name} = {value}\n'.format( name=new_version.parts[i].name, value=new_version.parts[i].value)) if vcs_configuration is not None: uc.finish_release() uc.post_finish_release()
def main(original_args=None): parser = argparse.ArgumentParser( description="Manages file content with versions.") parser.add_argument('-c', '--config-file', action='store', help="Config file", default=default_config_file_name) parser.add_argument('-v', '--version-file', action='store', help="Version file", default=default_version_file_name) parser.add_argument('-p', '--part', action='store') parser.add_argument('--set-part', action='store') parser.add_argument('-a', '--action', action='store') parser.add_argument('--action-options', action='store') parser.add_argument('--action-flags', action='store') parser.add_argument('--reset-on-set', action='store_true') parser.add_argument('--verbose', action='store_true', help="Be verbose") parser.add_argument('--version', action='store_true', help="Print the Punch version and project information") parser.add_argument('--init', action='store_true', help="Writes default initialization files" + " (does not overwrite existing ones)") parser.add_argument( '-s', '--simulate', action='store_true', help="Simulates the version increment and" + " prints a summary of the relevant data (implies --verbose)") args = parser.parse_args() # These are here just to avoid "can be not defined" messages by linters config = None repo = None if args.version is True: print("Punch version {}".format(punch.__version__)) print("Copyright (C) 2016 Leonardo Giordani") print("This is free software, see the LICENSE file.") print("Source: https://github.com/lgiordani/punch") print("Documentation: http://punch.readthedocs.io/en/latest/") sys.exit(0) if args.simulate: args.verbose = True if args.init is True: if not os.path.exists(default_config_file_name): with open(default_config_file_name, 'w') as f: f.write(default_config_file_content) if not os.path.exists(default_version_file_name): with open(default_version_file_name, 'w') as f: f.write(default_version_file_content) sys.exit(0) if not any([args.part, args.set_part, args.action]): fatal_error("You must specify one of --part, --set-part, or --action") if args.set_part and args.reset_on_set: set_parts = args.set_part.split(',') if len(set_parts) > 1: fatal_error( "If you specify --reset-on-set you may set only one value") if args.verbose: print("## Punch version {}".format(punch.__version__)) try: config = cfr.PunchConfig(args.config_file) except (cfr.ConfigurationVersionError, ValueError) as exc: fatal_error("An error occurred while reading the configuration file.", exc) if not args.simulate: if len(config.files) == 0: fatal_error("You didn't configure any file") current_version = ver.Version.from_file(args.version_file, config.version) new_version = current_version.copy() if args.part: args.action = "punch:increase" args.action_options = "part={}".format(args.part) if args.set_part: args.action = "punch:set" args.action_options = args.set_part if args.action: try: action_dict = config.actions[args.action] except KeyError: print("The requested action {} is not defined.".format( args.action)) sys.exit(0) try: action_name = action_dict.pop('type') except KeyError: print("The action configuration is missing the 'type' field.") sys.exit(0) if args.action_options: action_dict.update(hlp.optstr2dict(args.action_options)) action_class = ar.ActionRegister.get(action_name) action = action_class(action_dict) new_version = action.process_version(new_version) global_replacer = rep.Replacer(config.globals['serializer']) current_version_string, new_version_string = \ global_replacer.run_main_serializer( current_version.as_dict(), new_version.as_dict() ) if config.vcs is not None: special_variables = { 'current_version': current_version_string, 'new_version': new_version_string } vcs_configuration = vcsc.VCSConfiguration.from_dict( config.vcs, config.globals, special_variables) else: vcs_configuration = None if args.verbose: print("\n* Current version") show_version_parts(current_version.values) print("\n* New version") show_version_parts(new_version.values) changes = global_replacer.run_all_serializers( current_version.as_dict(), new_version.as_dict()) print("\n* Global version updates") show_version_updates(changes) print("\nConfigured files") for file_configuration in config.files: updater = fu.FileUpdater(file_configuration) print("* {}:".format(file_configuration.path)) changes = updater.get_summary(current_version.as_dict(), new_version.as_dict()) show_version_updates(changes) if vcs_configuration is not None: print("\nVersion control configuration") print("Name:", vcs_configuration.name) print("Commit message", vcs_configuration.commit_message) print("Options:", vcs_configuration.options) if not args.simulate: files_to_commit = [f.path for f in config.files] files_to_commit.append(args.config_file) files_to_commit.append(args.version_file) if vcs_configuration is not None: if vcs_configuration.name == 'git': repo_class = gr.GitRepo elif vcs_configuration.name == 'git-flow': repo_class = gfr.GitFlowRepo else: fatal_error("The requested version control" + " system {} is not supported.".format( vcs_configuration.name)) try: repo = repo_class(os.getcwd(), vcs_configuration, files_to_commit) except rex.RepositorySystemError as exc: fatal_error( "An error occurred while initializing" + " the version control repository", exc) else: repo = None if vcs_configuration is not None: # TODO: Create a fake UseCase to allow running this # without a repo and outside this nasty if uc = ruc.VCSReleaseUseCase(repo) uc.pre_start_release() uc.start_release() for file_configuration in config.files: updater = fu.FileUpdater(file_configuration) try: updater.update(current_version.as_dict(), new_version.as_dict()) except ValueError as e: print("Warning:", e) # Write the updated version info to the version file. new_version.to_file(args.version_file) if vcs_configuration is not None: uc.finish_release() uc.post_finish_release()
def main(original_args=None): parser = argparse.ArgumentParser( description="Manages file content with versions." ) parser.add_argument('-c', '--config-file', action='store', help="Config file", default=default_config_file_name) parser.add_argument('-v', '--version-file', action='store', help="Version file", default=default_version_file_name) parser.add_argument('-p', '--part', action='store') parser.add_argument('--set-part', action='store') parser.add_argument('-a', '--action', action='store') parser.add_argument('--action-options', action='store') parser.add_argument('--action-flags', action='store') parser.add_argument('--reset-on-set', action='store_true') parser.add_argument('-q', '--quiet', action='store_true', help='Ignore warnings') parser.add_argument('--verbose', action='store_true', help="Be verbose") parser.add_argument('--version', action='store_true', help="Print the Punch version and project information") parser.add_argument( '--init', action='store_true', help="Writes default initialization files" + " (does not overwrite existing ones)" ) parser.add_argument( '-s', '--simulate', action='store_true', help="Simulates the version increment and" + " prints a summary of the relevant data (implies --verbose)" ) args = parser.parse_args() # These are here just to avoid "can be not defined" messages by linters config = None repo = None if args.version is True: print("Punch version {}".format(punch.__version__)) print("Copyright (C) 2016 Leonardo Giordani") print("This is free software, see the LICENSE file.") print("Source: https://github.com/lgiordani/punch") print("Documentation: http://punch.readthedocs.io/en/latest/") sys.exit(0) if args.init is True: init_config_files() sys.exit(0) if args.simulate: args.verbose = True if not any([args.part, args.set_part, args.action]): fatal_error("You must specify one of --part, --set-part, or --action") set_options = [ i is not None for i in [args.part, args.set_part, args.action] ] if sum(set_options) > 1: fatal_error( "You can only specify one of --part, --set-part, or --action") if args.set_part and args.reset_on_set: set_parts = args.set_part.split(',') if len(set_parts) > 1: fatal_error( "If you specify --reset-on-set you may set only one value" ) try: config = cfr.PunchConfig(args.config_file) except (cfr.ConfigurationVersionError, ValueError) as exc: fatal_error( "An error occurred while reading the configuration file.", exc ) if len(config.files) == 0: fatal_error("You didn't configure any file") if args.part: args.action = "punch:increase" args.action_options = "part={}".format(args.part) elif args.set_part: args.action = "punch:set" args.action_options = args.set_part if args.action and args.action not in config.actions: fatal_error("The requested action {} is not defined.".format( args.action ) ) if args.verbose: print("## Punch version {}".format(punch.__version__)) action_dict = config.actions[args.action] try: action_name = action_dict.pop('type') except KeyError: fatal_error("The action configuration is missing the 'type' field.") if args.action_options: action_dict.update(hlp.optstr2dict(args.action_options)) action_class = ar.ActionRegister.get(action_name) action = action_class(action_dict) current_version = ver.Version.from_file(args.version_file, config.version) new_version = action.process_version(current_version.copy()) global_replacer = rep.Replacer(config.globals['serializer']) current_version_string, new_version_string = \ global_replacer.run_main_serializer( current_version.as_dict(), new_version.as_dict() ) if config.vcs is not None: vcs_configuration = vcsc.VCSConfiguration.from_dict( config.vcs, config.globals, { 'current_version': current_version_string, 'new_version': new_version_string } ) else: vcs_configuration = None # Prepare the files that have been changed by Punch # Including the config and version file of Punch itself files_to_commit = [f.path for f in config.files] files_to_commit.append(args.config_file) files_to_commit.append(args.version_file) # Prepare the VCS repository repo_class = select_vcs_repo_class(vcs_configuration) # Initialise the VCS reposity class try: repo = repo_class(os.getcwd(), vcs_configuration, files_to_commit) except rex.RepositorySystemError as exc: fatal_error( "An error occurred while initialising" + " the version control repository", exc ) if args.verbose: print("\n# Current version") show_version_parts(current_version.values) print("\n# New version") show_version_parts(new_version.values) changes = global_replacer.run_all_serializers( current_version.as_dict(), new_version.as_dict() ) print("\n# Global version updates") show_version_updates(changes) print("\n# Configured files") for file_configuration in config.files: updater = fu.FileUpdater(file_configuration) print("+ {}:".format(file_configuration.path)) changes = updater.get_summary( current_version.as_dict(), new_version.as_dict() ) show_version_updates(changes) # TODO: this should come form the repo vcs_info = repo.get_info() if len(vcs_info) != 0: print("\n# VCS") for key, value in repo.get_info(): print('+ {}: {}'.format(key, value)) if args.simulate: sys.exit(0) uc = vsruc.VCSStartReleaseUseCase(repo) uc.execute() for file_configuration in config.files: updater = fu.FileUpdater(file_configuration) try: updater.update( current_version.as_dict(), new_version.as_dict() ) except ValueError as e: if not args.quiet: print("Warning:", e) # Write the updated version info to the version file. new_version.to_file(args.version_file) uc = vfruc.VCSFinishReleaseUseCase(repo) uc.execute()