changelog-0.4.2/0000775000175000017500000000000013354475055014545 5ustar classicclassic00000000000000changelog-0.4.2/LICENSE0000664000175000017500000000216213011372263015536 0ustar classicclassic00000000000000This is the MIT license: http://www.opensource.org/licenses/mit-license.php Copyright (C) 2012 by Michael Bayer. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. changelog-0.4.2/MANIFEST.in0000664000175000017500000000010313011372263016260 0ustar classicclassic00000000000000recursive-include changelog *.py *.css include README* LICENSE changelog-0.4.2/PKG-INFO0000664000175000017500000000751013354475055015645 0ustar classicclassic00000000000000Metadata-Version: 1.1 Name: changelog Version: 0.4.2 Summary: Provides simple Sphinx markup to render changelog displays. Home-page: http://bitbucket.org/zzzeek/changelog Author: Mike Bayer Author-email: mike@zzzcomputing.com License: MIT Description: ========== Changelog ========== A `Sphinx `_ extension to generate changelog files. This is an experimental, possibly-not-useful extension that's used by the `SQLAlchemy `_ project and related projects. Configuration ============= A sample configuration in ``conf.py`` looks like this:: extensions = [ # changelog extension 'changelog', # your other sphinx extensions # ... ] # section names - optional changelog_sections = ["general", "rendering", "tests"] # tags to sort on inside of sections - also optional changelog_inner_tag_sort = ["feature", "bug"] # how to render changelog links - these are plain # python string templates, ticket/pullreq/changeset number goes # in "%s" changelog_render_ticket = "http://bitbucket.org/myusername/myproject/issue/%s" changelog_render_pullreq = "http://bitbucket.org/myusername/myproject/pullrequest/%s" changelog_render_changeset = "http://bitbucket.org/myusername/myproject/changeset/%s" Usage ===== Changelog introduces the ``changelog`` and ``change`` directives:: ==================== Changelog for 1.5.6 ==================== .. changelog:: :version: 1.5.6 :released: Sun Oct 12 2008 .. change:: :tags: general :tickets: 27 Improved the frobnozzle. .. change:: :tags: rendering, tests :pullreq: 8 :changeset: a9d7cc0b56c2 Rendering tests now correctly render. With the above markup, the changes above will be rendered into document sections per changelog, then each change within organized into paragraphs, including special markup for tags, tickets mentioned, pull requests, changesets. The entries will be grouped and sorted by tag according to the configuration of the ``changelog_sections`` and ``changelog_inner_tag_sort`` configurations. A "compound tag" can also be used, if the configuration has a section like this:: changelog_sections = ["orm declarative", "orm"] Then change entries which contain both the ``orm`` and ``declarative`` tags will be grouped under a section called ``orm declarative``, followed by the ``orm`` section where change entries that only have ``orm`` will be placed. Other Markup ============ The ``:ticket:`` directive will make use of the ``changelog_render_ticket`` markup to render a ticket link:: :ticket:`456` Keywords: Sphinx Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Documentation changelog-0.4.2/README.rst0000664000175000017500000000475213011372263016227 0ustar classicclassic00000000000000========== Changelog ========== A `Sphinx `_ extension to generate changelog files. This is an experimental, possibly-not-useful extension that's used by the `SQLAlchemy `_ project and related projects. Configuration ============= A sample configuration in ``conf.py`` looks like this:: extensions = [ # changelog extension 'changelog', # your other sphinx extensions # ... ] # section names - optional changelog_sections = ["general", "rendering", "tests"] # tags to sort on inside of sections - also optional changelog_inner_tag_sort = ["feature", "bug"] # how to render changelog links - these are plain # python string templates, ticket/pullreq/changeset number goes # in "%s" changelog_render_ticket = "http://bitbucket.org/myusername/myproject/issue/%s" changelog_render_pullreq = "http://bitbucket.org/myusername/myproject/pullrequest/%s" changelog_render_changeset = "http://bitbucket.org/myusername/myproject/changeset/%s" Usage ===== Changelog introduces the ``changelog`` and ``change`` directives:: ==================== Changelog for 1.5.6 ==================== .. changelog:: :version: 1.5.6 :released: Sun Oct 12 2008 .. change:: :tags: general :tickets: 27 Improved the frobnozzle. .. change:: :tags: rendering, tests :pullreq: 8 :changeset: a9d7cc0b56c2 Rendering tests now correctly render. With the above markup, the changes above will be rendered into document sections per changelog, then each change within organized into paragraphs, including special markup for tags, tickets mentioned, pull requests, changesets. The entries will be grouped and sorted by tag according to the configuration of the ``changelog_sections`` and ``changelog_inner_tag_sort`` configurations. A "compound tag" can also be used, if the configuration has a section like this:: changelog_sections = ["orm declarative", "orm"] Then change entries which contain both the ``orm`` and ``declarative`` tags will be grouped under a section called ``orm declarative``, followed by the ``orm`` section where change entries that only have ``orm`` will be placed. Other Markup ============ The ``:ticket:`` directive will make use of the ``changelog_render_ticket`` markup to render a ticket link:: :ticket:`456` changelog-0.4.2/changelog/0000775000175000017500000000000013354475055016474 5ustar classicclassic00000000000000changelog-0.4.2/changelog/__init__.py0000664000175000017500000000007413354475017020604 0ustar classicclassic00000000000000__version__ = '0.4.2' from .sphinxext import setup # noqa changelog-0.4.2/changelog/changelog.css0000664000175000017500000000014113011372263021114 0ustar classicclassic00000000000000a.changeset-link { visibility: hidden; } li:hover a.changeset-link { visibility: visible; } changelog-0.4.2/changelog/cmd.py0000664000175000017500000000412013241610175017573 0ustar classicclassic00000000000000import re import os import tempfile import shutil import argparse import sys def release_notes_into_changelog_file(target_filename, version, release_date): output = tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') with open(target_filename) as handle: for line in handle: m = re.match(r".*:version: %s" % version, line) if m: output.write(line) output.write(" :released: %s\n" % release_date) continue m = re.match(r".*:include_notes_from: (.+)", line) if m: notes_dir = os.path.join( os.path.dirname(target_filename), m.group(1) ) for fname in os.listdir(notes_dir): if not fname.endswith(".rst"): continue fname_path = os.path.join(notes_dir, fname) output.write("\n") with open(fname_path) as inner: for inner_line in inner: output.write((" " + inner_line).rstrip() + "\n") os.system("git rm %s" % fname_path) else: output.write(line) output.close() shutil.move(output.name, target_filename) def main(argv=None): parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() subparser = subparsers.add_parser( "release-notes", help="Merge notes files into changelog and git rm" ) subparser.add_argument("filename", help="target changelog filename") subparser.add_argument("version", help="version string as it appears in changelog") subparser.add_argument("date", help="full text of datestamp to insert") subparser.set_defaults( cmd=(release_notes_into_changelog_file, ["filename", "version", "date"])) options = parser.parse_args(argv) fn, argnames = options.cmd fn(*[getattr(options, name) for name in argnames]) if __name__ == '__main__': main(sys.argv) changelog-0.4.2/changelog/render.py0000664000175000017500000001600713354475006020325 0ustar classicclassic00000000000000#! coding: utf-8 from docutils import nodes import itertools import collections def render_changelog(changelog_directive): changes = changelog_directive.get_changes_list( changelog_directive.env, changelog_directive.version).values() output = [] id_prefix = "change-%s" % (changelog_directive.version, ) topsection = _run_top(changelog_directive, id_prefix) output.append(topsection) bysection, all_sections = _organize_by_section( changelog_directive, changes) counter = itertools.count() sections_to_render = [ s for s in changelog_directive.sections if s in all_sections] if not sections_to_render: for cat in changelog_directive.inner_tag_sort: append_sec = _append_node(changelog_directive) for rec in bysection[(changelog_directive.default_section, cat)]: rec["id"] = "%s-%s" % (id_prefix, next(counter)) _render_rec(changelog_directive, rec, None, cat, append_sec) if append_sec.children: topsection.append(append_sec) else: for section in sections_to_render + [ changelog_directive.default_section]: sec = nodes.section( '', nodes.title(section, section), ids=["%s-%s" % (id_prefix, section.replace(" ", "-"))] ) append_sec = _append_node(changelog_directive) sec.append(append_sec) for cat in changelog_directive.inner_tag_sort: for rec in bysection[(section, cat)]: rec["id"] = "%s-%s" % (id_prefix, next(counter)) _render_rec( changelog_directive, rec, section, cat, append_sec) if append_sec.children: topsection.append(sec) return output def _organize_by_section(changelog_directive, changes): compound_sections = [ (s, s.split(" ")) for s in changelog_directive.sections if " " in s] bysection = collections.defaultdict(list) all_sections = set() for rec in changes: assert changelog_directive.version == rec['render_for_version'] inner_tag = rec['tags'].intersection( changelog_directive.inner_tag_sort) if inner_tag: inner_tag = inner_tag.pop() else: inner_tag = "" for compound, comp_words in compound_sections: if rec['tags'].issuperset(comp_words): bysection[(compound, inner_tag)].append(rec) all_sections.add(compound) break else: intersect = rec['tags'].intersection(changelog_directive.sections) if intersect: for sec in rec['sorted_tags']: if sec in intersect: bysection[(sec, inner_tag)].append(rec) all_sections.add(sec) break else: bysection[ (changelog_directive.default_section, inner_tag) ].append(rec) return bysection, all_sections def _append_node(changelog_directive): return nodes.bullet_list() def _run_top(changelog_directive, id_prefix): version = changelog_directive._parsed_content.get('version', '') topsection = nodes.section( '', nodes.title(version, version), ids=[id_prefix] ) if changelog_directive._parsed_content.get("released"): topsection.append( nodes.Text("Released: %s" % changelog_directive._parsed_content['released']) ) else: topsection.append(nodes.Text("no release date")) intro_para = nodes.paragraph('', '') len_ = -1 for len_, text in enumerate(changelog_directive._parsed_content['text']): if ".. change::" in text: break # if encountered any text elements that didn't start with # ".. change::", those become the intro if len_ > 0: changelog_directive.state.nested_parse( changelog_directive._parsed_content['text'][0:len_], 0, intro_para) topsection.append(intro_para) return topsection def _render_rec(changelog_directive, rec, section, cat, append_sec): para = rec['node'].deepcopy() targetid = "change-%s" % ( rec['version_to_hash'][changelog_directive.version], ) targetnode = nodes.target('', '', ids=[targetid]) para.insert(0, targetnode) permalink = nodes.reference( '', '', nodes.Text(u"¶", u"¶"), refid=targetid, classes=['changeset-link', 'headerlink'], ) para.append(permalink) if len(rec['versions']) > 1: backported_changes = rec['sorted_versions'][ rec['sorted_versions'].index(changelog_directive.version) + 1:] if backported_changes: backported = nodes.paragraph('') backported.append(nodes.Text("This change is also ", "")) backported.append(nodes.strong("", "backported")) backported.append( nodes.Text(" to: %s" % ", ".join(backported_changes), "")) para.append(backported) insert_ticket = nodes.paragraph('') para.append(insert_ticket) i = 0 for collection, render, prefix in ( (rec['tickets'], changelog_directive.env.config.changelog_render_ticket, "#%s"), (rec['pullreq'], changelog_directive.env.config.changelog_render_pullreq, "pull request %s"), (rec['changeset'], changelog_directive.env.config.changelog_render_changeset, "r%s"), ): for refname in sorted(collection): if i > 0: insert_ticket.append(nodes.Text(", ", ", ")) else: insert_ticket.append(nodes.Text("References: """)) i += 1 if render is not None: if isinstance(render, dict): if ":" in refname: typ, refval = refname.split(":") else: typ = "default" refval = refname refuri = render[typ] % refval else: refuri = render % refname node = nodes.reference( '', '', nodes.Text(prefix % refname, prefix % refname), refuri=refuri ) else: node = nodes.Text(prefix % refname, prefix % refname) insert_ticket.append(node) if rec['tags']: tag_node = nodes.strong( '', " ".join( "[%s]" % t for t in [t1 for t1 in [section, cat] if t1 in rec['tags']] + list(sorted(rec['tags'].difference([section, cat]))) ) + " " ) para.children[0].insert(0, tag_node) append_sec.append( nodes.list_item( '', nodes.target('', '', ids=[rec['id']]), para ) ) changelog-0.4.2/changelog/sphinxext.py0000664000175000017500000003116213353522554021077 0ustar classicclassic00000000000000import collections import copy import hashlib as md5 import os import re import warnings import sys from docutils.parsers.rst import Directive from docutils import nodes from sphinx.util.console import bold from sphinx.util.osutil import copyfile from sphinx.util import status_iterator from sphinx.util import logging from . import render py3k = sys.version_info >= (3, 0) LOG = logging.getLogger(__name__) def _is_html(app): return app.builder.name in ('html', 'readthedocs') def _comma_list(text): return re.split(r"\s*,\s*", text.strip()) def _parse_content(content): d = {} d['text'] = [] idx = 0 for line in content: idx += 1 m = re.match(r' *\:(.+?)\:(?: +(.+))?', line) if m: attrname, value = m.group(1, 2) d[attrname] = value or '' elif idx == 1 and line: # accomodate a unique value on the edge of .. change:: continue else: break d["text"] = content[idx:] return d class EnvDirective(object): @property def env(self): return self.state.document.settings.env @classmethod def get_changes_list(cls, env, hash_on_version): key = ('ChangeLogDirective_changes', hash_on_version) if key not in env.temp_data: env.temp_data[key] = collections.OrderedDict() return env.temp_data[key] class ChangeLogDirective(EnvDirective, Directive): """Implement the ``.. changelog::`` directive. """ has_content = True default_section = 'misc' def run(self): self._parse() if not ChangeLogImportDirective.in_include_directive(self.env): return render.render_changelog(self) else: return [] def _parse(self): # 1. pull in global configuration from conf.py self.sections = self.env.config.changelog_sections self.inner_tag_sort = self.env.config.changelog_inner_tag_sort + [""] # 2. examine top level directives inside the .. changelog:: # directive. version, release date self._parsed_content = parsed = _parse_content(self.content) self.version = version = parsed.get('version', '') self.release_date = parsed.get('released', None) self.is_released = bool(self.release_date) self.env.temp_data['ChangeLogDirective'] = self content = self.content # 3. read extra per-file included notes if 'include_notes_from' in parsed: if content.items and content.items[0]: source = content.items[0][0] # seems we are now getting strings like: # changelog/changelog_11.rst source = source.split(' ')[0] path = os.path.join( os.path.dirname(source), parsed['include_notes_from']) else: path = parsed['include_notes_from'] if not os.path.exists(path): raise Exception("included nodes path %s does not exist" % path) content = copy.deepcopy(content) files = [ fname for fname in os.listdir(path) if fname.endswith(".rst") ] for fname in status_iterator( files, "reading changelog note files (version %s)..." % version, "purple", length=len(files), verbosity=self.env.app.verbosity ): fpath = os.path.join(path, fname) with open(fpath) as handle: content.append("", path, 0) for num, line in enumerate(handle): if not py3k: line = line.decode('utf-8') if "\t" in line: warnings.warn( "file %s has a tab in it! please " "convert to spaces." % fname) line = line.replace("\t", " ") line = line.rstrip() content.append( line, path, num ) # 4. parse the content of the .. changelog:: directive. This # is where we parse individual .. change:: directives and construct # a list of items, stored in the env via self.get_changes_list(env) p = nodes.paragraph('', '',) self.state.nested_parse(content[1:], 0, p) class ChangeLogImportDirective(EnvDirective, Directive): """Implement the ``.. changelog_imports::`` directive. Here, we typically load in other changelog.rst files which may feature elements that also apply to our current changelog.rst file, when they specify the ``:version:`` modifier. """ has_content = True @classmethod def in_include_directive(cls, env): return 'ChangeLogDirective_includes' in env.temp_data def run(self): # tell ChangeLogDirective we're here, also prevent # nested .. include calls if not self.in_include_directive(self.env): self.env.temp_data['ChangeLogDirective_includes'] = True p = nodes.paragraph('', '',) self.state.nested_parse(self.content, 0, p) del self.env.temp_data['ChangeLogDirective_includes'] return [] class ChangeDirective(EnvDirective, Directive): """Implement the ``.. change::`` directive. """ has_content = True def run(self): # don't do anything if we're not inside of a version if 'ChangeLogDirective' not in self.env.temp_data: return [] content = _parse_content(self.content) body_paragraph = nodes.paragraph('', '',) sorted_tags = _comma_list(content.get('tags', '')) changelog_directive = self.env.temp_data['ChangeLogDirective'] declared_version = changelog_directive.version versions = set( _comma_list(content.get("versions", ""))).difference(['']).\ union([declared_version]) # if we don't refer to any other versions and we're in an include, # skip if len(versions) == 1 and \ ChangeLogImportDirective.in_include_directive(self.env): return [] self.state.nested_parse(content['text'], 0, body_paragraph) raw_text = _text_rawsource_from_node(body_paragraph) tickets = set(_comma_list(content.get('tickets', ''))).difference(['']) pullreq = set(_comma_list(content.get('pullreq', ''))).difference(['']) tags = set(sorted_tags).difference(['']) for hash_on_version in versions: issue_hash = _get_robust_version_hash( raw_text, hash_on_version, tickets, tags) rec = ChangeLogDirective.get_changes_list( changelog_directive.env, hash_on_version).setdefault( issue_hash, {}) if not rec: rec.update({ 'hash': issue_hash, "render_for_version": hash_on_version, 'tags': tags, 'tickets': tickets, 'pullreq': pullreq, 'changeset': set( _comma_list(content.get('changeset', '')) ).difference(['']), 'node': body_paragraph, 'raw_text': raw_text, 'type': "change", "title": content.get("title", None), 'sorted_tags': sorted_tags, "versions": versions, "version_to_hash": { version: _get_legacy_version_hash(raw_text, version) for version in versions }, "source_versions": [declared_version], "sorted_versions": list( reversed(sorted(versions, key=_str_version_as_tuple))) }) else: # This seems to occur repeated times for each included # changelog, not clear if sphinx has changed the scope # of self.env to lead to this occurring more often LOG.debug( "Merging changelog record '%s' from version(s) %s " "with that of version %s", _quick_rec_str(rec), ", ".join(rec['source_versions']), declared_version ) rec["source_versions"].append(declared_version) assert rec['raw_text'] == raw_text assert rec['tags'] == tags assert rec["render_for_version"] == hash_on_version rec['tickets'].update(tickets) rec['pullreq'].update(pullreq) rec['changeset'].update( set( _comma_list(content.get('changeset', ''))). difference(['']) ) rec['versions'].update(versions) rec['version_to_hash'].update( { version: _get_legacy_version_hash(raw_text, version) for version in versions } ) rec["sorted_versions"] = list( reversed( sorted(rec['versions'], key=_str_version_as_tuple))) return [] def _quick_rec_str(rec): """try to print an identifiable description of a record""" if rec['tickets']: return "[tickets: %s]" % ", ".join(rec["tickets"]) else: return "%s..." % rec["raw_text"][0:25] def _get_legacy_version_hash(raw_text, version): # this needs to stay like this for link compatibility # with thousands of already-published changelogs to_hash = "%s %s" % (version, raw_text[0:100]) return md5.md5(to_hash.encode('ascii', 'ignore')).hexdigest() def _get_robust_version_hash(raw_text, version, tickets, tags): # this needs to stay like this for link compatibility # with thousands of already-published changelogs to_hash = "%s %s %s %s" % ( version, ", ".join(tickets), ", ".join(tags), raw_text) return md5.md5(to_hash.encode('ascii', 'ignore')).hexdigest() def _text_rawsource_from_node(node): src = [] stack = [node] while stack: n = stack.pop(0) if isinstance(n, nodes.Text): src.append(n.rawsource) stack.extend(n.children) return "".join(src) _VERSION_IDS = {} def _str_version_as_tuple(ver): if ver in _VERSION_IDS: return _VERSION_IDS[ver] out = [] for dig in ver.split("."): try: out.append(int(dig)) except ValueError: out.append(dig) _VERSION_IDS[ver] = result = tuple(out) return result def make_ticket_link( name, rawtext, text, lineno, inliner, options={}, content=[]): env = inliner.document.settings.env render_ticket = env.config.changelog_render_ticket or "%s" prefix = "#%s" if render_ticket: ref = render_ticket % text node = nodes.reference(rawtext, prefix % text, refuri=ref, **options) else: node = nodes.Text(prefix % text, prefix % text) return [node], [] def add_stylesheet(app): app.add_stylesheet('changelog.css') def copy_stylesheet(app, exception): LOG.info( bold('The name of the builder is: %s' % app.builder.name), nonl=True) if not _is_html(app) or exception: return LOG.info(bold('Copying sphinx_paramlinks stylesheet... '), nonl=True) source = os.path.abspath(os.path.dirname(__file__)) # the '_static' directory name is hardcoded in # sphinx.builders.html.StandaloneHTMLBuilder.copy_static_files. # would be nice if Sphinx could improve the API here so that we just # give it the path to a .css file and it does the right thing. dest = os.path.join(app.builder.outdir, '_static', 'changelog.css') copyfile(os.path.join(source, "changelog.css"), dest) LOG.info('done') def setup(app): app.add_directive('changelog', ChangeLogDirective) app.add_directive('change', ChangeDirective) app.add_directive('changelog_imports', ChangeLogImportDirective) app.add_config_value("changelog_sections", [], 'env') app.add_config_value("changelog_inner_tag_sort", [], 'env') app.add_config_value("changelog_render_ticket", None, 'env') app.add_config_value("changelog_render_pullreq", None, 'env') app.add_config_value("changelog_render_changeset", None, 'env') app.connect('builder-inited', add_stylesheet) app.connect('build-finished', copy_stylesheet) app.add_role('ticket', make_ticket_link) changelog-0.4.2/changelog.egg-info/0000775000175000017500000000000013354475055020166 5ustar classicclassic00000000000000changelog-0.4.2/changelog.egg-info/PKG-INFO0000664000175000017500000000751013354475054021265 0ustar classicclassic00000000000000Metadata-Version: 1.1 Name: changelog Version: 0.4.2 Summary: Provides simple Sphinx markup to render changelog displays. Home-page: http://bitbucket.org/zzzeek/changelog Author: Mike Bayer Author-email: mike@zzzcomputing.com License: MIT Description: ========== Changelog ========== A `Sphinx `_ extension to generate changelog files. This is an experimental, possibly-not-useful extension that's used by the `SQLAlchemy `_ project and related projects. Configuration ============= A sample configuration in ``conf.py`` looks like this:: extensions = [ # changelog extension 'changelog', # your other sphinx extensions # ... ] # section names - optional changelog_sections = ["general", "rendering", "tests"] # tags to sort on inside of sections - also optional changelog_inner_tag_sort = ["feature", "bug"] # how to render changelog links - these are plain # python string templates, ticket/pullreq/changeset number goes # in "%s" changelog_render_ticket = "http://bitbucket.org/myusername/myproject/issue/%s" changelog_render_pullreq = "http://bitbucket.org/myusername/myproject/pullrequest/%s" changelog_render_changeset = "http://bitbucket.org/myusername/myproject/changeset/%s" Usage ===== Changelog introduces the ``changelog`` and ``change`` directives:: ==================== Changelog for 1.5.6 ==================== .. changelog:: :version: 1.5.6 :released: Sun Oct 12 2008 .. change:: :tags: general :tickets: 27 Improved the frobnozzle. .. change:: :tags: rendering, tests :pullreq: 8 :changeset: a9d7cc0b56c2 Rendering tests now correctly render. With the above markup, the changes above will be rendered into document sections per changelog, then each change within organized into paragraphs, including special markup for tags, tickets mentioned, pull requests, changesets. The entries will be grouped and sorted by tag according to the configuration of the ``changelog_sections`` and ``changelog_inner_tag_sort`` configurations. A "compound tag" can also be used, if the configuration has a section like this:: changelog_sections = ["orm declarative", "orm"] Then change entries which contain both the ``orm`` and ``declarative`` tags will be grouped under a section called ``orm declarative``, followed by the ``orm`` section where change entries that only have ``orm`` will be placed. Other Markup ============ The ``:ticket:`` directive will make use of the ``changelog_render_ticket`` markup to render a ticket link:: :ticket:`456` Keywords: Sphinx Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Documentation changelog-0.4.2/changelog.egg-info/SOURCES.txt0000664000175000017500000000053113354475055022051 0ustar classicclassic00000000000000LICENSE MANIFEST.in README.rst setup.py changelog/__init__.py changelog/changelog.css changelog/cmd.py changelog/render.py changelog/sphinxext.py changelog.egg-info/PKG-INFO changelog.egg-info/SOURCES.txt changelog.egg-info/dependency_links.txt changelog.egg-info/entry_points.txt changelog.egg-info/not-zip-safe changelog.egg-info/top_level.txtchangelog-0.4.2/changelog.egg-info/dependency_links.txt0000664000175000017500000000000113354475054024233 0ustar classicclassic00000000000000 changelog-0.4.2/changelog.egg-info/entry_points.txt0000664000175000017500000000006213354475055023462 0ustar classicclassic00000000000000[console_scripts] changelog = changelog.cmd:main changelog-0.4.2/changelog.egg-info/not-zip-safe0000664000175000017500000000000113011374666022410 0ustar classicclassic00000000000000 changelog-0.4.2/changelog.egg-info/top_level.txt0000664000175000017500000000001213354475055022711 0ustar classicclassic00000000000000changelog changelog-0.4.2/setup.cfg0000664000175000017500000000004613354475055016366 0ustar classicclassic00000000000000[egg_info] tag_build = tag_date = 0 changelog-0.4.2/setup.py0000664000175000017500000000226113134737626016261 0ustar classicclassic00000000000000from setuptools import setup import os import re v = open(os.path.join(os.path.dirname(__file__), 'changelog', '__init__.py')) VERSION = re.compile(r".*__version__ = '(.*?)'", re.S).match(v.read()).group(1) v.close() readme = os.path.join(os.path.dirname(__file__), 'README.rst') setup(name='changelog', version=VERSION, description="Provides simple Sphinx markup to render changelog displays.", long_description=open(readme).read(), classifiers=[ 'Development Status :: 3 - Alpha', 'Environment :: Console', 'Intended Audience :: Developers', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Documentation', ], keywords='Sphinx', author='Mike Bayer', author_email='mike@zzzcomputing.com', url='http://bitbucket.org/zzzeek/changelog', license='MIT', packages=['changelog'], include_package_data=True, zip_safe=False, entry_points={ 'console_scripts': ['changelog = changelog.cmd:main'], } )