Skip to content

Commit

Permalink
walk back last change slightly
Browse files Browse the repository at this point in the history
preamble now contains the title, to allow for representing Jekyll front matter or any other information above the title
  • Loading branch information
drewcassidy committed May 7, 2021
1 parent a230968 commit a925a4e
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 56 deletions.
27 changes: 17 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ All notable changes to this project will be documented in this file

### Changed

- API changes:
- `header` attribute renamed to `preamble` to avoid confusion.
- improved version header parsing to be more robust and handle multi-word version names.
- improved version number incrementing in `release`.
- can now handle other text surrounding a pep440-compliant version number, which will not be modified
- can now handle pre-releases correctly. The version to increment is the most recent version in the log with a valid pep440 version number in it. Release increment and prerelease increments can be mixed, allowing e.g: `yaclog release -mr` to create a release candidate with in incremented minor version number.
- `header` attribute on the changelog class has been split into `title` and `preamble`
- can now handle pre-releases correctly. The version to increment is the most recent version in the log with a valid pep440 version number in it.
- Release increment and prerelease increments can be mixed, allowing e.g: `yaclog release -mr` to create a release candidate with in incremented minor version number.

### Removed

Expand All @@ -20,6 +22,7 @@ All notable changes to this project will be documented in this file

- Terminal output has color to distinguish version names/headers, sections, and git information


## 0.3.3 - 2021-04-27

### Added
Expand All @@ -34,6 +37,7 @@ All notable changes to this project will be documented in this file
- `release` now resets lesser version values when incrementing
- `release` now works with logs that have only unreleased changes


## 0.3.2 - 2021-04-24

### Added
Expand All @@ -49,17 +53,19 @@ All notable changes to this project will be documented in this file

- `release` and `entry` commands now work using empty changelogs.


## 0.3.1 - 2021-04-24

### Added

- `yaclog` tool for manipulating changelogs from the command line
- `init` command to make a new changelog
- `format` command to reformat the changelog
- `show` command to show changes from the changelog
- `entry` command for manipulating entries in the changelog
- `tag` command for manipulating tags in the changelog
- `release` command for creating releases
- `init` command to make a new changelog
- `format` command to reformat the changelog
- `show` command to show changes from the changelog
- `entry` command for manipulating entries in the changelog
- `tag` command for manipulating tags in the changelog
- `release` command for creating releases


## 0.2.0 - 2021-04-19

Expand All @@ -71,8 +77,9 @@ All notable changes to this project will be documented in this file

- Updated package metadata
- Rewrote parser to use a 2-step method that is more flexible.
- Parser can now handle code blocks.
- Parser can now handle setext-style headers and H2s not conforming to the schema.
- Parser can now handle code blocks.
- Parser can now handle setext-style headers and H2s not conforming to the schema.


## 0.1.0 - 2021-04-16

Expand Down
10 changes: 3 additions & 7 deletions docs/handbook/changelog_files.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@

Yaclog works on markdown changelog files, using a machine-readable format based on what is proposed by [Keep a Changelog](https://keepachangelog.com). Changelog files can be created using the {command}`yaclog init` command.

## Title

The title is the first H1 in the file giving its title, usually `# Changlog`.

## Preamble

The preamble is the text at the top of the file before any version information. It can contain an explanation of the file's purpose, as well as any general machine-readable information you may want to include for use with other tools. Yaclog does not provide any ways to manipulate the front matter from the command line due to its open-ended nature.
The preamble is the text at the top of the file before any version information. It can contain the title, an explanation of the file's purpose, as well as any general machine-readable information you may want to include for use with other tools. Yaclog does not provide any ways to manipulate the front matter from the command line due to its open-ended nature.

## Versions

Expand All @@ -17,9 +13,11 @@ Version information begins with a header, which is an H2 containing the version'
```markdown
## 1.0.0
```

```markdown
## 3.2.0 "Columbia" - 1981-07-20
```

```markdown
## Version 8.0.0rc1 1988-11-15 [PRERELEASE]
```
Expand Down Expand Up @@ -54,7 +52,6 @@ Yanked due to issues with oxygen tanks, currently investigating
- Replaced Ken Mattingly
- Stirred oxygen tanks


## 0.12.0 "Intrepid" - 1969-11-14

### Added
Expand All @@ -71,7 +68,6 @@ Yanked due to issues with oxygen tanks, currently investigating

- Lightning strike during launch: No effect on performance


## 0.11.0 "Eagle" - 1969-07-20

Initial stable release
Expand Down
4 changes: 2 additions & 2 deletions tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
log_text = '\n\n'.join(log_segments)

log = yaclog.Changelog()
log.title = 'Changelog'
log.preamble = ['This changelog is for testing the parser, and has many things in it that might trip it up.']
log.preamble = '# Changelog\n\n' \
'This changelog is for testing the parser, and has many things in it that might trip it up.'
log.links = {'id': 'http://www.koalastothemax.com'}
log.versions = [yaclog.changelog.VersionEntry(), yaclog.changelog.VersionEntry(), yaclog.changelog.VersionEntry()]

Expand Down
10 changes: 3 additions & 7 deletions tests/test_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ def test_path(self):
"""Test the log's path"""
self.assertEqual(self.path, self.log.path)

def test_title(self):
"""Test the title at the top of the file"""
self.assertEqual(log.title, self.log.title)

def test_preamble(self):
"""Test the preamble at the top of the file"""
self.assertEqual(log.preamble, self.log.preamble)
Expand Down Expand Up @@ -56,11 +52,11 @@ def setUpClass(cls):
log.write(cls.path)
with open(cls.path) as fd:
cls.log_text = fd.read()
cls.log_segments = [line for line in cls.log_text.split('\n\n') if line]
cls.log_segments = [line.lstrip('\n') for line in cls.log_text.split('\n\n') if line]

def test_header(self):
def test_preamble(self):
"""Test the header information at the top of the file"""
self.assertEqual(log_segments[1], self.log_segments[1])
self.assertEqual(log_segments[0:2], self.log_segments[0:2])

def test_links(self):
"""Test the links at the end of the file"""
Expand Down
55 changes: 25 additions & 30 deletions yaclog/changelog.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
Contains the `Changelog` class that represents a parsed changelog file that can be read from and written to
disk as markdown, as well as the `VersionEntry` class that represents a single version within that changelog
disk as markdown, as well as the `VersionEntry` class that represents a single version within that changelog.
"""

# yaclog: yet another changelog tool
Expand Down Expand Up @@ -33,7 +33,10 @@


class VersionEntry:
"""Holds a single version entry in a :py:class:`Changelog`"""
"""
A serialized representation of a single version entry in a `Changelog`,
containing the changes made since the previous version
"""

_header_regex = re.compile( # THE LANGUAGE OF THE GODS
r"##\s+(?P<name>.*?)(?:\s+-)?(?:\s+(?P<date>\d{4}-\d{2}-\d{2}))?(?P<tags>(?:\s+\[[^]]*?])*)\s*$")
Expand Down Expand Up @@ -215,32 +218,31 @@ def __str__(self) -> str:


class Changelog:
"""A changelog made up of a header, several versions, and a link table"""
"""
A serialized representation of a Markdown changelog made up of a preamble, multiple versions, and a link table.
"""

def __init__(self, path=None,
title: str = 'Changelog',
preamble: str = "All notable changes to this project will be documented in this file"):
preamble: str = "Changelog\n\nAll notable changes to this project will be documented in this file"):
"""
Contents will be automatically read from disk if the file exists
:param path: The changelog's path on disk
:param str title: The changelog title to use if the file does not exist.
:param path: The changelog's path on disk.
:param str preamble: The changelog preamble to use if the file does not exist.
"""
self.path = os.path.abspath(path) if path else None
"""The path of the changelog's file on disk"""

self.title: str = title
"""The title of the changelog"""

self.preamble: List[str] = preamble
"""Any text at the top of the changelog before any version information as a list of paragraphs"""
self.preamble: str = preamble
"""Any text at the top of the changelog before any version information, including the title.
It can contain the title, an explanation of the file's purpose, as well as any general machine-readable
information for use with other tools."""

self.versions: List[VersionEntry] = []
"""A list of versions in the changelog"""
"""A list of versions in the changelog, with the most recent version first"""

self.links: Dict[str, str] = {}
"""Link IDs at the end of the changelog"""
"""Link definitions at the end of the changelog, as a dictionary of ``{id: url}``"""

if path and os.path.exists(path):
self.read()
Expand All @@ -250,7 +252,7 @@ def read(self, path=None) -> None:
Read a markdown changelog file from disk. The object's contents will be overwritten by the file contents if
reading is successful.
:param path: The changelog's path on disk. By default, :py:attr:`~Changelog.path` is used.
:param path: The changelog's path on disk. By default, :py:attr:`~Changelog.path` is used
"""

if not path:
Expand All @@ -263,8 +265,7 @@ def read(self, path=None) -> None:

section = ''
versions = []
title = None
preamble = []
preamble_segments = []

for token in tokens:
text = '\n'.join(token.lines)
Expand All @@ -276,11 +277,8 @@ def read(self, path=None) -> None:

elif len(versions) == 0:
# we haven't encountered any version headers yet,
# so its best to just add this line to the preamble or title
if token.kind == 'h1' and not title:
title = text.strip('#').strip()
else:
preamble.append(text)
# so its best to just add this line to the preamble
preamble_segments.append(text)

elif token.kind == 'h3':
# start of a version section
Expand All @@ -306,14 +304,13 @@ def read(self, path=None) -> None:
# id-matched link
version.link = links[version.link_id]

self.title = title
self.preamble = preamble
self.preamble = markdown.join(preamble_segments)
self.versions = versions
self.links = links

def write(self, path=None) -> None:
"""
Write a markdown changelog to a file.
Write a changelog to a Markdown file.
:param path: The changelog's path on disk. By default, :py:attr:`~Changelog.path` is used.
"""
Expand All @@ -324,18 +321,16 @@ def write(self, path=None) -> None:

segments = []

if self.title:
segments.append(f'# {self.title}')
if self.preamble:
segments += self.preamble
segments.append(self.preamble)

v_links = {**self.links}

for version in self.versions:
if version.link:
v_links[version.name.lower()] = version.link

segments.append(version.text())
segments.append(version.text() + '\n')

segments += [f'[{link_id}]: {link}' for link_id, link in v_links.items()]

Expand Down Expand Up @@ -386,7 +381,7 @@ def current_version(self, released: Optional[bool] = None, new_version: bool = F

def get_version(self, name: Optional[str] = None) -> VersionEntry:
"""
Get a version from the changelog
Get a version from the changelog by name
:param name: The name of the version to get, or `None` to return the most recent
:return: The first version with the selected name
Expand Down

0 comments on commit a925a4e

Please sign in to comment.