def prepare_entrypoint_documentation(data): """Place the generated entrypoint doc in the source structure.""" if data['name'] != 'zest.releaser': # We're available everywhere, but we're only intended for # zest.releaser internal usage. return target = os.path.join(data['reporoot'], 'doc', 'source', 'entrypoints.rst') marker = '.. ### AUTOGENERATED FROM HERE ###' result = [] lines, encoding = read_text_file(target) for line in lines.split('\n'): line = line.rstrip() if line == marker: break result.append(line) result.append(marker) result.append('') for name, datadict in ( ('prerelease', prerelease.DATA), ('release', release.DATA), ('postrelease', postrelease.DATA)): heading = '%s data dict items' % name.capitalize() result.append(heading) result.append('-' * len(heading)) result.append('') for key in sorted(datadict.keys()): result.append(key) result.append(' ' + datadict[key]) result.append('') write_text_file(target, '\n'.join(result), encoding) print("Wrote entry point documentation to %s" % target)
def _update_history(self): """Update the history file""" version = self.data['new_version'] history = self.vcs.history_file() if not history: logger.warn("No history file found") return history_lines = read_text_file(history).split('\n') headings = utils.extract_headings_from_history(history_lines) if not len(headings): logger.warn("No detectable existing version headings in the " "history file.") inject_location = 0 underline_char = '-' else: first = headings[0] inject_location = first['line'] underline_line = first['line'] + 1 try: underline_char = history_lines[underline_line][0] except IndexError: logger.debug("No character on line below header.") underline_char = '-' header = '%s (unreleased)' % version inject = [header, underline_char * len(header), '', self.data['nothing_changed_yet'], '', ''] history_lines[inject_location:inject_location] = inject contents = '\n'.join(history_lines) write_text_file(history, contents) logger.info("Injected new section into the history: %r", header)
def _write_history(self): """Write previously-calculated history lines back to the file""" if self.data['history_file'] is None: return contents = '\n'.join(self.data['history_lines']) history = self.data['history_file'] write_text_file(history, contents) logger.info("History file %s updated.", history)
def cleanup_changelog(data): """Cleanup empty headers. We call this twice: in prereleaser.before and prereleaser.middle. In 'before', we are too early and zest.releaser has not looked for the history file yet. But we try 'CHANGES.rst' ourselves. In 'middle' we are a bit too late, as zest.releaser has already complained when it found the NOTHING_CHANGED_YET value in the history. So we call this twice, which should be fine. """ # The history_file is probably not set yet, as we are called too early. # That might change subtly in future zest.releaser versions, so let's check # it anyway. history_file = data.get('history_file') if history_file: contents = '\n'.join(data['history_lines']) encoding = data['history_encoding'] else: # We do not want to copy the logic from zest.releaser that tries to # find the history file, but we can check the most obvious spot. history_file = 'CHANGES.rst' if not os.path.exists(history_file): print('Cannot cleanup history, will try again later.') return contents, encoding = read_text_file(history_file) orig_contents = contents changed = False for header in ALL_HEADERS: if header in contents: contents = contents.replace(header, '') changed = True if not changed: return write_text_file( history_file, contents, encoding=encoding) print("Cleaned up empty headers from history file {}".format(history_file)) # Update the data, otherwise our work may get overwritten. data['history_lines'] = contents.split('\n') if not os.path.isdir('.git'): print('Not a git checkout, cannot commit.') return g = git.Git('.') message = "Cleaned up empty headers from changelog.\n\n[ci skip]" print(g.diff(history_file)) msg = "Commit changes?" if not ask(msg, default=True): # Restore original contents. write_text_file( history_file, orig_contents, encoding=encoding) sys.exit() print("Committing changes.") print(g.add(history_file)) print(g.commit(message=message))
def _write_history(self): """Write previously-calculated history lines back to the file""" if self.data['history_file'] is None: return contents = '\n'.join(self.data['history_lines']) history = self.data['history_file'] write_text_file( history, contents, encoding=self.data['history_encoding']) logger.info("History file %s updated.", history)
def _update_python_file_version(self, version): setup_cfg = pypi.SetupConfig() filename = setup_cfg.python_file_with_version() lines, encoding = utils.read_text_file(filename) lines = lines.split('\n') for index, line in enumerate(lines): match = UNDERSCORED_VERSION_PATTERN.search(line) if match: lines[index] = "__version__ = '%s'" % version contents = '\n'.join(lines) utils.write_text_file(filename, contents, encoding) logger.info("Set __version__ in %s to %r", filename, version)
def _update_python_file_version(self, version): filename = self.setup_cfg.python_file_with_version() lines, encoding = utils.read_text_file( filename, fallback_encoding=self.fallback_encoding, ) for index, line in enumerate(lines): match = UNDERSCORED_VERSION_PATTERN.search(line) if match: lines[index] = "__version__ = '%s'" % version contents = '\n'.join(lines) utils.write_text_file(filename, contents, encoding) logger.info("Set __version__ in %s to '%s'", filename, version)
def _update_version(self, version): """Find out where to change the version and change it. There are three places where the version can be defined. The first one is an explicitly defined Python file with a ``__version__`` attribute. The second one is some version.txt that gets read by setup.py. The third is directly in setup.py. """ if self.get_python_file_version(): self._update_python_file_version(version) return version_filenames = ['version'] version_filenames.extend( ['.'.join(['version', extension]) for extension in TXT_EXTENSIONS]) versionfile = self.filefind(version_filenames) if versionfile: # We have a version.txt file but does it match the setup.py # version (if any)? setup_version = self.get_setup_py_version() if not setup_version or (setup_version == self.get_version_txt_version()): with open(versionfile, 'w') as f: f.write(version + '\n') logger.info("Changed %s to %r", versionfile, version) return good_version = "version = '%s'" % version line_number = 0 setup_lines, encoding = utils.read_text_file('setup.py') setup_lines = setup_lines.split('\n') for line_number, line in enumerate(setup_lines): if VERSION_PATTERN.search(line): logger.debug("Matching version line found: %r", line) if line.startswith(' '): # oh, probably ' version = 1.0,' line. indentation = line.split('version')[0] # Note: no spaces around the '='. good_version = indentation + "version='%s'," % version setup_lines[line_number] = good_version utils.write_text_file('setup.py', '\n'.join(setup_lines), encoding) logger.info("Set setup.py's version to %r", version) return logger.error( "We could read a version from setup.py, but could not write it " "back. See " "http://zestreleaser.readthedocs.io/en/latest/versions.html " "for hints.") raise RuntimeError("Cannot set version")
def fillchangelog(context): default_location = None setup_cfg = pypi.SetupConfig() config = setup_cfg.config if config and config.has_option('zest.releaser', 'history_file'): default_location = config.get('zest.releaser', 'history_file') vcs = zest.releaser.choose.version_control() history_file = vcs.history_file(location=default_location) if history_file: try: found = zest.releaser.utils.get_last_tag(vcs) log_command = vcs.cmd_log_since_tag(found) except SystemExit: log_command = get_all_commits_command(vcs) if log_command: data = execute_command(log_command) pretty_data = prettyfy_logs(data, vcs) print('These are all the commits since the last tag:') print('') print('\n'.join(pretty_data)) if zest.releaser.utils.ask('Do you want to add those commits to the CHANGES file?', True): new_history_lines = [] history_lines, history_encoding = read_text_file(history_file) history_lines = history_lines.split('\n') for line in history_lines: current_position = history_lines.index(line) new_history_lines.append(line) if line.lower().find('unreleased') != -1: # current_position + 1 == ---------------- # current_position + 2 == blank # current_position + 3 == - Nothing changed yet. # current_position + 4 == blank new_history_lines.append(history_lines[current_position + 1]) new_history_lines.append(history_lines[current_position + 2]) new_history_lines.extend(pretty_data) new_history_lines.extend(history_lines[current_position + 4:]) break contents = '\n'.join(new_history_lines) write_text_file(history_file, contents) msg = 'Update changelog' commit_cmd = vcs.cmd_commit(msg) commit = execute_command(commit_cmd) print(commit) else: print('History file not found. Skipping.')
def updateBuildoutChangeLogs(history_lines, history_encoding, headings, changelogs, package, version): inject_location = headings[0]['line'] inject = ['', '- %s %s' % (package, version)] indentchangelogs = [] for changelog in changelogs: if changelog: changelog = ' %s' % changelog indentchangelogs.append(changelog) inject.extend(indentchangelogs) inject.append('') if history_lines[inject_location+3] == '- Nothing changed yet.': del history_lines[inject_location+3:inject_location+6] history_lines[inject_location+2:inject_location+2] = inject contents = u'\n'.join(history_lines) utils.write_text_file(BUILDOUTHISTORYFILE, contents, history_encoding)
def prepare_entrypoint_documentation(data): """Place the generated entrypoint doc in the source structure.""" if data['name'] != 'zest.releaser': # We're available everywhere, but we're only intended for # zest.releaser internal usage. return target = os.path.join(data['reporoot'], 'doc', 'source', 'entrypoints.rst') marker = '.. ### AUTOGENERATED FROM HERE ###' result = [] lines, encoding = read_text_file(target) for line in lines: line = line.rstrip() if line == marker: break result.append(line) result.append(marker) result.append('') for name, datadict in ( ('common', baserelease.DATA), ('prerelease', prerelease.DATA), ('release', release.DATA), ('postrelease', postrelease.DATA), ('addchangelogentry', addchangelogentry.DATA), ('bumpversion', bumpversion.DATA), ): if name == 'common': heading = '%s data dict items' % name.capitalize() else: # quote the command name heading = '``%s`` data dict items' % name result.append(heading) result.append('-' * len(heading)) result.append('') if name == 'common': result.append('These items are shared among all commands.') result.append('') for key in sorted(datadict.keys()): if name != 'common' and datadict[key] == baserelease.DATA.get(key): # The key is already in common data, with the same value. continue result.append(key) result.append(' ' + datadict[key]) result.append('') write_text_file(target, '\n'.join(result), encoding) print("Wrote entry point documentation to %s" % target)
def _update_python_file_version(self, version): filename = self.setup_cfg.python_file_with_version() lines, encoding = utils.read_text_file( filename, fallback_encoding=self.fallback_encoding, ) good_version = "__version__ = '%s'" % version for index, line in enumerate(lines): if UNDERSCORED_VERSION_PATTERN.search(line): lines[index] = ( good_version.replace("'", '"') if '"' in line else good_version ) contents = '\n'.join(lines) utils.write_text_file(filename, contents, encoding) logger.info("Set __version__ in %s to '%s'", filename, version)
def prepare_entrypoint_documentation(data): """Place the generated entrypoint doc in the source structure.""" if data['name'] != 'zest.releaser': # We're available everywhere, but we're only intended for # zest.releaser internal usage. return target = os.path.join(data['reporoot'], 'doc', 'source', 'entrypoints.rst') marker = '.. ### AUTOGENERATED FROM HERE ###' result = [] lines, encoding = read_text_file(target) for line in lines.split('\n'): line = line.rstrip() if line == marker: break result.append(line) result.append(marker) result.append('') for name, datadict in ( ('prerelease', prerelease.DATA), ('release', release.DATA), ('postrelease', postrelease.DATA), ('addchangelogentry', addchangelogentry.DATA), ('bumpversion', bumpversion.DATA), ): heading = '%s data dict items' % name.capitalize() result.append(heading) result.append('-' * len(heading)) result.append('') for key in sorted(datadict.keys()): result.append(key) result.append(' ' + datadict[key]) result.append('') write_text_file(target, '\n'.join(result), encoding) print("Wrote entry point documentation to %s" % target)
def _update_version(self, version): """Find out where to change the version and change it. There are three places where the version can be defined. The first one is an explicitly defined Python file with a ``__version__`` attribute. The second one is some version.txt that gets read by setup.py. The third is directly in setup.py. """ if self.get_python_file_version(): setup_cfg = pypi.SetupConfig() filename = setup_cfg.python_file_with_version() lines, encoding = utils.read_text_file(filename) lines = lines.split('\n') for index, line in enumerate(lines): match = UNDERSCORED_VERSION_PATTERN.search(line) if match: lines[index] = "__version__ = '%s'" % version contents = '\n'.join(lines) utils.write_text_file(filename, contents, encoding) logger.info("Set __version__ in %s to %r", filename, version) return version_filenames = ['version'] for extension in TXT_EXTENSIONS: version_filenames.append('.'.join(['version', extension])) versionfile = self.filefind(version_filenames) if versionfile: # We have a version.txt file but does it match the setup.py # version (if any)? setup_version = self.get_setup_py_version() if not setup_version or (setup_version == self.get_version_txt_version()): open(versionfile, 'w').write(version + '\n') logger.info("Changed %s to %r", versionfile, version) return good_version = "version = '%s'" % version line_number = 0 setup_lines, encoding = utils.read_text_file('setup.py') setup_lines = setup_lines.split('\n') for line_number, line in enumerate(setup_lines): match = VERSION_PATTERN.search(line) if match: logger.debug("Matching version line found: %r", line) if line.startswith(' '): # oh, probably ' version = 1.0,' line. indentation = line.split('version')[0] # Note: no spaces around the '='. good_version = indentation + "version='%s'," % version setup_lines[line_number] = good_version contents = '\n'.join(setup_lines) utils.write_text_file('setup.py', contents, encoding) logger.info("Set setup.py's version to %r", version) return logger.error( "We could read a version from setup.py, but could not write it " + "back. See " + "http://zestreleaser.readthedocs.org/en/latest/versions.html " + "for hints.") raise RuntimeError("Cannot set version")