Repository: d0c-s4vage/lookatme
Pull request #162 (2022-10-18 04:38:56)

Update 3.0-dev with latest from main


Patch:
diff --git a/.github/workflows/pypi_publish.yml b/.github/workflows/pypi_publish.yml
new file mode 100644
index 0000000..6d23727
--- /dev/null
+++ b/.github/workflows/pypi_publish.yml
@@ -0,0 +1,35 @@
+name: Publish to PyPI
+on:
+  push:
+    tags:
+      - 'v*.*.*'
+
+jobs:
+  build-and-publish:
+    name: Build and publish to PyPI
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - name: Setup Python 3.10
+        uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
+      - name: Set VERSION number
+        run: |
+          version_num="${{github.ref_name}}"
+          # strip the leading v
+          version_num=${version_num#v}
+          echo "Replacing {{VERSION}} with '$version_num'"
+          echo "Files with {{VERSION}}:"
+          grep -rl '{{VERSION}}' .
+          grep -rl '{{VERSION}}' . | xargs sed -i "s/{{VERSION}}/$version_num/g"
+          echo "Files with {{VERSION}} after replacing:"
+          grep -rl '{{VERSION}}' . || true
+      - name: Install pypa/build
+        run: python -m pip install build --user
+      - name: Build binary wheel + tarball
+        run: python -m build --sdist --wheel --outdir dist/
+      - name: Publish distribution to PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3d18ad..d5dd42d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+- [v2.4.1](#v241)
+- [v2.4.0](#v240)
+- [v2.3.2](#v232)
+- [v2.3.1](#v231)
 - [v2.3.0](#v230)
 - [v2.2.0](#v220)
 - [v2.1.0](#v210)
@@ -17,6 +21,15 @@
 - [v0.2.0](#v020)
 - [v0.1.0](#v010)
 
+## v2.4.1
+
+Bug fix - theme and style override precedence issues. The CLI params `--theme`
+and `--style` and other general style precedence issues are fixed.
+
+| type | PR/ticket                                               | author                                       | description                                                       |
+|-----:|---------------------------------------------------------|----------------------------------------------|-------------------------------------------------------------------|
+|  bug | [#123](https://github.com/d0c-s4vage/lookatme/pull/123) | [@d0c-s4vage](https://github.com/d0c-s4vage) | Fixes CLI `--theme`, `--style`, and general style override issues |
+
 ## v2.4.0
 
 Bug fixes, new features, new CI, getting ready for v3.0.
@@ -28,8 +41,8 @@ Bug fixes, new features, new CI, getting ready for v3.0.
 |     bug | [!133](https://github.com/d0c-s4vage/lookatme/pull/133)   | [@AMDmi3](https://github.com/AMDmi3)         | Excludes tests dir from packages                                 |
 |     bug | [#126](https://github.com/d0c-s4vage/lookatme/issues/126) | [@d0c-s4vage](https://github.com/d0c-s4vage) | Fix unit test failues                                            |
 |     bug | [!141](https://github.com/d0c-s4vage/lookatme/pull/141)   | [@corydodt](https://github.com/corydodt)     | Fix click requirements range                                     |
-| feature | [!150](https://github.com/d0c-s4vage/pull/150             | [@d0c-s4vage](https://github.com/d0c-s4vage) | New CI that uses GitHub actions                                  |
-|     bug | [!151](https://github.com/d0c-s4vage/pull/151             | [@d0c-s4vage](https://github.com/d0c-s4vage) | Fix linter errors                                                |
+| feature | [!150](https://github.com/d0c-s4vage/pull/150)            | [@d0c-s4vage](https://github.com/d0c-s4vage) | New CI that uses GitHub actions                                  |
+|     bug | [!151](https://github.com/d0c-s4vage/pull/151)            | [@d0c-s4vage](https://github.com/d0c-s4vage) | Fix linter errors                                                |
 
 
 ## v2.3.2
diff --git a/lookatme/parser.py b/lookatme/parser.py
index 7359d05..e3c0e68 100644
--- a/lookatme/parser.py
+++ b/lookatme/parser.py
@@ -113,7 +113,7 @@ class Parser(object):
                 pass
 
         elif num_hrules == 0:
-            if meta["title"] in ("", None):
+            if meta.get("title", "") in ["", None]:
                 meta["title"] = hinfo["title"]
 
             def slide_split_check(token):
@@ -271,14 +271,14 @@ class Parser(object):
                 break
 
         if not found_first:
-            return input_data, MetaSchema().load({})
+            return input_data, MetaSchema().load_partial_styles({}, partial=True)
 
         new_input = input_data[skipped_chars:]
         if len(yaml_data) == 0:
-            return new_input, MetaSchema().load({})
+            return new_input, MetaSchema().load_partial_styles({}, partial=True)
 
         yaml_data = "\n".join(yaml_data)
-        data = MetaSchema().loads(yaml_data)
+        data = MetaSchema().loads_partial_styles(yaml_data, partial=True)
         return new_input, data
 
     def _create_slides(self, tokens, number):
diff --git a/lookatme/pres.py b/lookatme/pres.py
index cedb8ad..8e020b5 100644
--- a/lookatme/pres.py
+++ b/lookatme/pres.py
@@ -113,10 +113,12 @@ class Presentation(object):
                 self.ignore_ext_failure,
             )
 
+        # style override order:
+        # 1. theme settings
         self.styles = lookatme.themes.ensure_defaults(self.theme_mod)
+        # 2. inline styles from the presentation
         dict_deep_update(self.styles, self.meta.get("styles", {}))
-
-        # now apply any command-line style overrides
+        # 3. CLI style overrides
         if self.style_override is not None:
             self.styles["style"] = self.style_override  # type: ignore
 
diff --git a/lookatme/schemas.py b/lookatme/schemas.py
index 503a798..60cc773 100644
--- a/lookatme/schemas.py
+++ b/lookatme/schemas.py
@@ -460,6 +460,23 @@ class MetaSchema(Schema):
     )
     extensions = fields.List(fields.Str(), dump_default=[], load_default=[])
 
+    def _ensure_top_level_defaults(self, res: Dict) -> Dict:
+        res.setdefault("title", "")
+        res.setdefault("author", "")
+        res.setdefault("date", datetime.datetime.now().strftime("%Y-%m-%d"))
+        res.setdefault("extensions", [])
+
+        return res
+
+    def loads_partial_styles(self, *args, **kwargs):
+        kwargs["partial"] = True
+        res = super(self.__class__, self).loads(*args, **kwargs)
+        if res is None:
+            raise ValueError("Could not loads")
+
+        res = self._ensure_top_level_defaults(res)
+        return res
+
     def loads(self, *args, **kwargs) -> Dict:
         res = super(self.__class__, self).loads(*args, **kwargs)
         if res is None:
@@ -467,6 +484,15 @@ class MetaSchema(Schema):
 
         return res
 
+    def load_partial_styles(self, *args, **kwargs):
+        kwargs["partial"] = True
+        res = super(self.__class__, self).load(*args, **kwargs)
+        if res is None:
+            raise ValueError("Could not loads")
+
+        res = self._ensure_top_level_defaults(res)
+        return res
+
     def load(self, *args, **kwargs) -> Dict:
         res = super(self.__class__, self).load(*args, **kwargs)
         if res is None:
diff --git a/lookatme/themes/dark.py b/lookatme/themes/dark.py
index 2915f9f..d87bc00 100644
--- a/lookatme/themes/dark.py
+++ b/lookatme/themes/dark.py
@@ -3,4 +3,5 @@ Defines styles that should look good on dark backgrounds
 """
 
 
+# the default settings for lookatme are dark settings
 theme = {}


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 570e56a..a91e3f1 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -3,9 +3,15 @@ Test the main CLI
 """
 
 
+from typing import Optional
+
+import yaml
 from click.testing import CliRunner
 
 import lookatme
+import lookatme.schemas
+import lookatme.themes.dark as dark_theme
+import lookatme.themes.light as light_theme
 import lookatme.tui
 from lookatme.__main__ import main
 
@@ -23,6 +29,90 @@ def test_dump_styles_unicode():
     assert "█" in res.output
 
 
+def _get_dumped_style(
+    tmpdir,
+    theme: Optional[str] = None,
+    md_meta_style: Optional[str] = None,
+    cli_style: Optional[str] = None
+) -> str:
+    cli_args = ["--dump-styles"]
+
+    if theme is not None:
+        cli_args += ["--theme", theme]
+    if md_meta_style is not None:
+        tmpfile = tmpdir.join("test.md")
+        with open(tmpfile, "w") as f:
+            f.write("\n".join([
+                "---",
+                "styles:",
+                "  style: {}".format(md_meta_style),
+                "---",
+            ]))
+        cli_args += [str(tmpfile)]
+    if cli_style is not None:
+        cli_args += ["--style", cli_style]
+
+    res = run_cmd(*cli_args)
+    assert res.exit_code == 0
+
+    yaml_data = yaml.safe_load(res.output)
+    return yaml_data["style"]
+
+
+def test_style_override_precedence_dark(tmpdir):
+    """Test that dump styles works correctly
+    """
+    default_style = _get_dumped_style(tmpdir)
+    themed_style = _get_dumped_style(tmpdir, theme="dark")
+    themed_and_md = _get_dumped_style(
+        tmpdir,
+        theme="dark",
+        md_meta_style="emacs"
+    )
+    themed_and_md_and_cli = _get_dumped_style(
+        tmpdir,
+        theme="dark",
+        md_meta_style="emacs",
+        cli_style="zenburn"
+    )
+
+    default = lookatme.schemas.MetaSchema().dump(None)
+    assert default_style == default["styles"]["style"]
+
+    dark_theme_styles = lookatme.schemas.StyleSchema().dump(dark_theme.theme)
+    assert themed_style == dark_theme_styles["style"]  # type: ignore
+
+    assert themed_and_md == "emacs"
+    assert themed_and_md_and_cli == "zenburn"
+
+
+def test_style_override_precedence_light(tmpdir):
+    """Test that dump styles works correctly
+    """
+    default_style = _get_dumped_style(tmpdir)
+    themed_style = _get_dumped_style(tmpdir, theme="light")
+    themed_and_md = _get_dumped_style(
+        tmpdir,
+        theme="light",
+        md_meta_style="emacs"
+    )
+    themed_and_md_and_cli = _get_dumped_style(
+        tmpdir,
+        theme="light",
+        md_meta_style="emacs",
+        cli_style="zenburn"
+    )
+
+    default = lookatme.schemas.MetaSchema().dump(None)
+    assert default_style == default["styles"]["style"]
+
+    light_theme_styles = lookatme.schemas.StyleSchema().dump(light_theme.theme)
+    assert themed_style == light_theme_styles["style"]  # type: ignore
+
+    assert themed_and_md == "emacs"
+    assert themed_and_md_and_cli == "zenburn"
+
+
 def test_version():
     """Test the version option"""
     res = run_cmd("--version")