Compare commits

..

2 Commits

Author SHA1 Message Date
deroshkin 357eceabad Added emdash 0x2014 as a word separator 2021-11-22 21:25:08 +01:00
Dmytro Yeroshkin 1c53c94b9c Add title to the output 2021-11-01 10:01:31 +01:00
8 changed files with 90 additions and 53 deletions

View File

@ -1,12 +1,39 @@
---
kind: pipeline
name: python-3-11-alpine-3-18
name: python-3-6-alpine-3-9
clone:
skip_verify: true
steps:
- name: build
image: alpine:3.18
image: alpine:3.9
pull: always
commands:
- tests/run-ci-tests
---
kind: pipeline
name: python-3-7-alpine-3-10
clone:
skip_verify: true
steps:
- name: build
image: alpine:3.10
pull: always
commands:
- tests/run-ci-tests
---
kind: pipeline
name: python-3-8-alpine-3-13
clone:
skip_verify: true
steps:
- name: build
image: alpine:3.13
pull: always
commands:
- tests/run-ci-tests

View File

@ -57,11 +57,11 @@ total: 946 words
## Installation
Start by cloning the project with git. Then install it with
[pipx](https://pypa.github.io/pipx/). Example:
Start by cloning the project with git. Then install it with Python's `pip`.
Example:
```bash
pipx install /path/to/novel-stats
pip3 install /path/to/novel-stats
```
## Usage
@ -226,9 +226,17 @@ make sure your changes work.
```bash
cd novel-stats/
pipx install --editable .
pip3 install --editable --user .
```
Note that this will typically install the novel-stats commands into
`~/.local/bin`, which may or may not be on your PATH. There are other ways to
install novel-stats editable as well, for instance into the system Python
install (so without `--user`, as root), or even into a
[virtualenv](https://virtualenv.pypa.io/en/stable/). How or where you install
novel-stats is up to you, but generally an editable install makes development
and testing easier.
### Automated tests
@ -237,7 +245,7 @@ you're in the `novel-stats/` working copy, install tox, which is used for
setting up testing environments:
```bash
pipx install tox
pip3 install --user tox
```
Finally, to actually run tests, run:

View File

@ -4,18 +4,21 @@
import argparse
import collections
import tempfile
import re
CHAPTER_MARKER = '## '
STATUS_MARKER = '[status]: # '
ACT_MARKER = '[act]: # '
# Standard markdown comment marker, supported by Pandoc and Calibre's ebook-convert.
COMMENT_MARKER = '[//]: # '
TITLE_MARKER = '# '
WORD_SEPS = [' ','—']
def count_words(line):
count = 0
for word in line.strip().split(' '):
for word in re.split('|'.join(WORD_SEPS), line.strip()):
if not word.strip() or word == '*' or word.startswith('#'):
continue
@ -72,8 +75,9 @@ def main():
word_count_by_chapter = collections.defaultdict(int)
word_count_by_status = collections.defaultdict(int)
word_count_by_act = collections.defaultdict(int)
status_by_chapter = collections.defaultdict(lambda: collections.defaultdict(int))
status_by_chapter = {}
current_status = None
title = None
for line in mdfile.readlines():
if line.startswith(CHAPTER_MARKER):
@ -83,22 +87,24 @@ def main():
chapter_heading = line[len(CHAPTER_MARKER) :].strip('()\n')
# Count the words in chapter heading, because the chapter number and title count as words.
if chapter_heading:
word_count_by_chapter[chapter_heading] = count_words(chapter_heading)
current_status = None
word_count_by_chapter[chapter_heading] = count_words(chapter_heading)
status_by_chapter[chapter_heading] = collections.defaultdict(int)
current_status = None
# Modified to allow multiple statuses in a single chapter, can swap back and forth.
elif line.startswith(STATUS_MARKER):
if current_status is None:
current_status = line[len(STATUS_MARKER) :].strip('()\n')
if chapter_heading:
status_by_chapter[chapter_heading][current_status] = count_words(
chapter_heading
)
status_by_chapter[chapter_heading][current_status] = count_words(chapter_heading)
else:
current_status = line[len(STATUS_MARKER) :].strip('()\n')
elif line.startswith(ACT_MARKER):
act_heading = line[len(ACT_MARKER) :].strip('()\n')
word_count_by_act[act_heading] = count_words(act_heading)
elif line.startswith(TITLE_MARKER):
title = line[len(TITLE_MARKER):].strip()
line_word_count = count_words(line)
word_count_by_chapter[chapter_heading] += line_word_count
elif line.startswith(COMMENT_MARKER): # Don't count the words in a comment.
pass
else:
@ -115,6 +121,9 @@ def main():
word_count_by_act[act_heading] += word_count_by_chapter[chapter_heading]
total_word_count += word_count_by_chapter[chapter_heading]
if title:
print(f'Novel Stats for {title.upper()}')
# -c or --chapter to give a chapter-by-chapter word count summary.
if arguments.chapter:
for chapter_heading, chapter_word_count in word_count_by_chapter.items():

View File

@ -20,15 +20,8 @@ setup(
"Topic :: Text Processing :: Markup",
],
packages=find_packages(exclude=["tests*"]),
entry_points={
"console_scripts": [
"novel-stats = novel_stats.novel_stats:main",
]
},
entry_points={"console_scripts": ["novel-stats = novel_stats.novel_stats:main",]},
install_requires=(),
extras_require={
"multi_file": ["MarkdownPP"],
},
extras_require={"multi_file": ["MarkdownPP"],},
include_package_data=True,
python_requires='>3.7.0',
)

View File

@ -1,18 +1,18 @@
appdirs==1.4.4
attrs==23.1.0
black==23.10.1
click==8.1.7
coverage==7.3.2
flake8==6.1.0
flexmock==0.11.3
isort==5.12.0
mccabe==0.7.0
pluggy==1.3.0
pathspec==0.11.2
py==1.11.0
pycodestyle==2.11.1
pyflakes==3.1.0
pytest==7.4.2
pytest-cov==4.1.0
regex
typed-ast
appdirs==1.4.4; python_version >= '3.8'
attrs==20.3.0; python_version >= '3.8'
black==19.10b0; python_version >= '3.8'
click==7.1.2; python_version >= '3.8'
coverage==5.3
flake8==3.8.4
flexmock==0.10.4
isort==5.9.1
mccabe==0.6.1
pluggy==0.13.1
pathspec==0.8.1; python_version >= '3.8'
py==1.10.0
pycodestyle==2.6.0
pyflakes==2.2.0
pytest==6.1.2
pytest-cov==2.10.1
regex; python_version >= '3.8'
typed-ast==1.4.2; python_version >= '3.8'

View File

View File

@ -9,6 +9,7 @@ set -e
apk add --no-cache python3 py3-pip
# If certain dependencies of black are available in this version of Alpine, install them.
apk add --no-cache py3-typed-ast py3-regex || true
pip3 install tox==4.11.3
python3 -m pip install --upgrade pip==21.3.1 setuptools==58.2.0
pip3 install tox==3.24.4
export COVERAGE_FILE=/tmp/.coverage
tox --workdir /tmp/.tox --sitepackages

17
tox.ini
View File

@ -1,16 +1,16 @@
[tox]
env_list = py38,py39,py310,py311
envlist = py36,py37,py38,py39
skip_missing_interpreters = True
package = editable
minversion = 4.0
skipsdist = True
minversion = 3.14.1
[testenv]
deps =
-r test_requirements.txt
pass_env = COVERAGE_FILE
usedevelop = True
deps = -rtest_requirements.txt
passenv = COVERAGE_FILE
commands =
pytest {posargs}
black --check .
py38,py39: black --check .
isort --check-only --settings-path setup.cfg .
flake8 novel_stats tests
@ -23,7 +23,6 @@ commands =
pytest {posargs}
[testenv:isort]
deps =
{[testenv]deps}
deps = {[testenv]deps}
commands =
isort --settings-path setup.cfg .