Skip to content

Commit 8954166

Browse files
Ned Batcheldernedbat
authored andcommitted
Create API classes
The scriv.scriv module has Scriv, Changelog, and Fragment classes.
1 parent 2560e73 commit 8954166

File tree

6 files changed

+298
-205
lines changed

6 files changed

+298
-205
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Added
2+
.....
3+
4+
- A new poorly documented API is available. See the Scriv, Changelog, and
5+
Fragment classes in the scriv.scriv module.

src/scriv/collect.py

Lines changed: 16 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,17 @@
11
"""Collecting fragments."""
22

3-
import collections
4-
import datetime
5-
import itertools
63
import logging
7-
from pathlib import Path
8-
from typing import Dict, Iterable, List, Optional, Sequence, Tuple, TypeVar
4+
from typing import Optional
95

106
import click
117
import click_log
12-
import jinja2
138

14-
from .config import Config
15-
from .format import SectionDict, get_format_tools
169
from .gitinfo import git_add, git_config_bool, git_edit, git_rm
10+
from .scriv import Scriv
1711

1812
logger = logging.getLogger()
1913

2014

21-
def files_to_combine(config: Config) -> List[Path]:
22-
"""
23-
Find all the files to be combined.
24-
25-
The files are returned in the order they should be processed.
26-
27-
"""
28-
return sorted(
29-
itertools.chain.from_iterable(
30-
[
31-
Path(config.fragment_directory).glob(pattern)
32-
for pattern in ["*.rst", "*.md"]
33-
]
34-
)
35-
)
36-
37-
38-
def sections_from_file(config: Config, filename: Path) -> SectionDict:
39-
"""
40-
Collect the sections from a file.
41-
"""
42-
format_tools = get_format_tools(filename.suffix.lstrip("."), config)
43-
text = filename.read_text().rstrip()
44-
file_sections = format_tools.parse_text(text)
45-
return file_sections
46-
47-
48-
def combine_sections(config: Config, files: Iterable[Path]) -> SectionDict:
49-
"""
50-
Read files, and produce a combined SectionDict of their contents.
51-
"""
52-
sections = collections.defaultdict(list) # type: SectionDict
53-
for file in files:
54-
file_sections = sections_from_file(config, file)
55-
for section, paragraphs in file_sections.items():
56-
sections[section].extend(paragraphs)
57-
return sections
58-
59-
60-
T = TypeVar("T")
61-
K = TypeVar("K")
62-
63-
64-
def order_dict(
65-
d: Dict[Optional[K], T], keys: Sequence[Optional[K]]
66-
) -> Dict[Optional[K], T]:
67-
"""
68-
Produce an OrderedDict of `d`, but with the keys in `keys` order.
69-
"""
70-
with_order = collections.OrderedDict()
71-
to_insert = set(d)
72-
for k in keys:
73-
if k not in to_insert:
74-
continue
75-
with_order[k] = d[k]
76-
to_insert.remove(k)
77-
78-
for k in to_insert:
79-
with_order[k] = d[k]
80-
81-
return with_order
82-
83-
84-
def cut_at_line(text: str, marker: str) -> Tuple[str, str]:
85-
"""
86-
Split text into two parts: up to the line with marker, and lines after.
87-
88-
If `marker` isn't in the text, return ("", text)
89-
"""
90-
lines = text.splitlines(keepends=True)
91-
for i, line in enumerate(lines):
92-
if marker in line:
93-
return "".join(lines[: i + 1]), "".join(lines[i + 1 :])
94-
return ("", text)
95-
96-
9715
@click.command()
9816
@click.option(
9917
"--add/--no-add", default=None, help="'git add' the updated changelog file."
@@ -121,55 +39,27 @@ def collect(
12139
if edit is None:
12240
edit = git_config_bool("scriv.collect.edit")
12341

124-
config = Config.read()
125-
logger.info("Collecting from {}".format(config.fragment_directory))
126-
files = files_to_combine(config)
127-
sections = combine_sections(config, files)
128-
sections = order_dict(sections, [None] + config.categories)
42+
scriv = Scriv()
43+
logger.info("Collecting from {}".format(scriv.config.fragment_directory))
44+
frags = scriv.fragments_to_combine()
12945

130-
changelog = Path(config.output_file)
131-
newline = ""
132-
if changelog.exists():
133-
with changelog.open("r") as f:
134-
changelog_text = f.read()
135-
if f.newlines: # .newlines may be None, str, or tuple
136-
if isinstance(f.newlines, str):
137-
newline = f.newlines
138-
else:
139-
newline = f.newlines[0]
140-
text_before, text_after = cut_at_line(
141-
changelog_text, config.insert_marker
142-
)
143-
else:
144-
text_before = ""
145-
text_after = ""
46+
changelog = scriv.changelog()
47+
changelog.read()
14648

147-
format_tools = get_format_tools(config.format, config)
148-
title_data = {
149-
"date": datetime.datetime.now(),
150-
"version": version or config.version,
151-
}
152-
new_title = jinja2.Template(config.entry_title_template).render(
153-
config=config, **title_data
154-
)
155-
if new_title.strip():
156-
new_header = format_tools.format_header(new_title)
157-
else:
158-
new_header = ""
159-
new_text = format_tools.format_sections(sections)
160-
with changelog.open("w", newline=newline or None) as f:
161-
f.write(text_before + new_header + new_text + text_after)
49+
new_header = changelog.entry_header(version=version)
50+
new_text = changelog.entry_text(scriv.combine_fragments(frags))
51+
changelog.write(new_header, new_text)
16252

16353
if edit:
164-
git_edit(changelog)
54+
git_edit(changelog.path)
16555

16656
if add:
167-
git_add(changelog)
57+
git_add(changelog.path)
16858

16959
if not keep:
170-
for file in files:
171-
logger.info("Deleting fragment file {}".format(file))
60+
for frag in frags:
61+
logger.info("Deleting fragment file {!r}".format(str(frag.path)))
17262
if add:
173-
git_rm(file)
63+
git_rm(frag.path)
17464
else:
175-
file.unlink()
65+
frag.path.unlink()

src/scriv/create.py

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,18 @@
11
"""Creating fragments."""
22

3-
import datetime
43
import logging
5-
import re
64
import sys
7-
import textwrap
8-
from pathlib import Path
95
from typing import Optional
106

117
import click
128
import click_log
13-
import jinja2
149

15-
from .collect import sections_from_file
16-
from .config import Config
17-
from .gitinfo import (
18-
current_branch_name,
19-
git_add,
20-
git_config_bool,
21-
git_edit,
22-
user_nick,
23-
)
10+
from .gitinfo import git_add, git_config_bool, git_edit
11+
from .scriv import Scriv
2412

2513
logger = logging.getLogger()
2614

2715

28-
def new_fragment_path(config: Config) -> Path:
29-
"""
30-
Return the file path for a new fragment.
31-
"""
32-
file_name = "{:%Y%m%d_%H%M%S}_{}".format(
33-
datetime.datetime.now(), user_nick()
34-
)
35-
branch_name = current_branch_name()
36-
if branch_name and branch_name not in config.main_branches:
37-
branch_name = branch_name.rpartition("/")[-1]
38-
branch_name = re.sub(r"[^a-zA-Z0-9_]", "_", branch_name)
39-
file_name += "_{}".format(branch_name)
40-
file_name += ".{}".format(config.format)
41-
file_path = Path(config.fragment_directory) / file_name
42-
return file_path
43-
44-
45-
def new_fragment_contents(config: Config) -> str:
46-
"""Produce the initial contents of a scriv fragment."""
47-
return jinja2.Template(
48-
textwrap.dedent(config.new_fragment_template)
49-
).render(config=config)
50-
51-
5216
@click.command()
5317
@click.option(
5418
"--add/--no-add", default=None, help="'git add' the created file."
@@ -68,24 +32,25 @@ def create(add: Optional[bool], edit: Optional[bool]) -> None:
6832
if edit is None:
6933
edit = git_config_bool("scriv.create.edit")
7034

71-
config = Config.read()
72-
if not Path(config.fragment_directory).exists():
35+
scriv = Scriv()
36+
frag = scriv.new_fragment()
37+
file_path = frag.path
38+
if not file_path.parent.exists():
7339
sys.exit(
7440
"Output directory {!r} doesn't exist, please create it.".format(
75-
config.fragment_directory
41+
str(file_path.parent)
7642
)
7743
)
7844

79-
file_path = new_fragment_path(config)
8045
if file_path.exists():
8146
sys.exit("File {} already exists, not overwriting".format(file_path))
8247

8348
logger.info("Creating {}".format(file_path))
84-
file_path.write_text(new_fragment_contents(config))
49+
frag.write()
8550

8651
if edit:
8752
git_edit(file_path)
88-
sections = sections_from_file(config, file_path)
53+
sections = scriv.sections_from_fragment(frag)
8954
if not sections:
9055
logger.info("Empty fragment, aborting...")
9156
file_path.unlink()

0 commit comments

Comments
 (0)