From 76d267ee8552de8211e804c6b5194a62b3db3ac4 Mon Sep 17 00:00:00 2001 From: Joseph Lewis III Date: Thu, 31 Oct 2024 22:23:37 -0700 Subject: [PATCH] Added CSV support in --slug --- CHANGELOG.md | 1 + src/devdocs2zim/generator.py | 21 +++++++++--- tests/test_generator.py | 63 ++++++++++++++++++++++++++++++------ 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7744925..96d5ef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Page navigation is now dynamically rendered reducing file sizes. (#24, #31) +- The `--slug` flag now supports comma delimited values. (#28) ## [0.1.0] - 2024-09-27 diff --git a/src/devdocs2zim/generator.py b/src/devdocs2zim/generator.py index b0aed74..76f568d 100644 --- a/src/devdocs2zim/generator.py +++ b/src/devdocs2zim/generator.py @@ -211,8 +211,8 @@ class DocFilter(BaseModel): all: bool | None # If > 0 and not None, allow the first N of each slug without version. first: int | None - # If specified, only the given slugs are allowed. - slugs: list[str] | None + # If specified, only the given slugs are allowed. Each entry may be comma delimited. + csv_slugs: list[str] | None # If specified, slugs matching the regex are skipped. skip_slug_regex: str | None @@ -234,9 +234,10 @@ def add_flags(parser: argparse.ArgumentParser): help="Fetch the provided Devdocs resource. " "Slugs are the first path entry in the Devdocs URL. " "For example, the slug for: `https://devdocs.io/gcc~12/` is `gcc~12`. " - "Use --slug several times to fetch multiple docs.", + "Use --slug several times or with values separated by a comma to " + "fetch multiple docs.", action="append", - dest="slugs", + dest="csv_slugs", metavar="SLUG", ) doc_selection.add_argument( @@ -257,6 +258,18 @@ def of(namespace: argparse.Namespace) -> "DocFilter": """Parses a namespace to create a new DocFilter.""" return DocFilter.model_validate(namespace, from_attributes=True) + @property + def slugs(self) -> list[str] | None: + """Returns the parsed list of user supplied slugs, if specified.""" + if self.csv_slugs is None: + return None + + out: list[str] = [] + for slug in self.csv_slugs: + out.extend(slug.split(",")) + + return out + def filter(self, docs: list[DevdocsMetadata]) -> list[DevdocsMetadata]: """Filters docs based on the user's choices.""" diff --git a/tests/test_generator.py b/tests/test_generator.py index 5f1a2c4..5d976a5 100644 --- a/tests/test_generator.py +++ b/tests/test_generator.py @@ -157,7 +157,7 @@ def test_flags_all(self): DocFilter( all=True, first=None, - slugs=None, + csv_slugs=None, skip_slug_regex=None, ), got, @@ -175,11 +175,35 @@ def test_flags_slug(self): DocFilter( all=False, first=None, - slugs=["first", "second"], + csv_slugs=["first", "second"], skip_slug_regex=None, ), got, ) + self.assertEqual( + ["first", "second"], + got.slugs, + ) + + def test_flags_slug_csv(self): + parser = argparse.ArgumentParser() + DocFilter.add_flags(parser) + + got = DocFilter.of(parser.parse_args(args=["--slug", "first,second"])) + + self.assertEqual( + DocFilter( + all=False, + first=None, + csv_slugs=["first,second"], + skip_slug_regex=None, + ), + got, + ) + self.assertEqual( + ["first", "second"], + got.slugs, + ) def test_flags_first(self): parser = argparse.ArgumentParser() @@ -191,7 +215,7 @@ def test_flags_first(self): DocFilter( all=False, first=3, - slugs=None, + csv_slugs=None, skip_slug_regex=None, ), got, @@ -213,14 +237,16 @@ def test_flags_regex(self): DocFilter( all=True, first=None, - slugs=None, + csv_slugs=None, skip_slug_regex="^$", ), got, ) def test_filter_all(self): - doc_filter = DocFilter(all=True, first=None, slugs=None, skip_slug_regex=None) + doc_filter = DocFilter( + all=True, first=None, csv_slugs=None, skip_slug_regex=None + ) got = doc_filter.filter( [ @@ -234,7 +260,22 @@ def test_filter_all(self): def test_filter_slugs(self): doc_filter = DocFilter( - all=False, first=None, slugs=["foo", "bazz"], skip_slug_regex=None + all=False, first=None, csv_slugs=["foo", "bazz"], skip_slug_regex=None + ) + + got = doc_filter.filter( + [ + DevdocsMetadata(name="foo", slug="foo"), + DevdocsMetadata(name="bar", slug="bar"), + DevdocsMetadata(name="bazz", slug="bazz"), + ] + ) + + self.assertEqual(2, len(got)) + + def test_filter_slugs_csvs(self): + doc_filter = DocFilter( + all=False, first=None, csv_slugs=["foo,bazz"], skip_slug_regex=None ) got = doc_filter.filter( @@ -248,7 +289,9 @@ def test_filter_slugs(self): self.assertEqual(2, len(got)) def test_filter_all_regex(self): - doc_filter = DocFilter(all=True, first=None, slugs=None, skip_slug_regex="^b") + doc_filter = DocFilter( + all=True, first=None, csv_slugs=None, skip_slug_regex="^b" + ) got = doc_filter.filter( [ @@ -262,13 +305,13 @@ def test_filter_all_regex(self): def test_filter_slugs_missing(self): doc_filter = DocFilter( - all=False, first=None, slugs=["does_not_exist"], skip_slug_regex=None + all=False, first=None, csv_slugs=["does_not_exist"], skip_slug_regex=None ) self.assertRaises(MissingDocumentError, doc_filter.filter, []) def test_filter_first(self): - doc_filter = DocFilter(all=False, first=2, slugs=None, skip_slug_regex=None) + doc_filter = DocFilter(all=False, first=2, csv_slugs=None, skip_slug_regex=None) got = doc_filter.filter( [ @@ -303,7 +346,7 @@ def setUp(self): self.generator = Generator( devdocs_client=self.mock_client, doc_filter=DocFilter( - all=True, first=None, slugs=None, skip_slug_regex=None + all=True, first=None, csv_slugs=None, skip_slug_regex=None ), output_folder=output_folder, zim_config=zim_defaults(),