diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 1772620e98..b0fb210989 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -21,6 +21,17 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + + # Python 3.9 is on macos-13 but not macos-latest (macos-14-arm64) + # https://github.com/actions/setup-python/issues/696#issuecomment-1637587760 + exclude: + - { python-version: "3.8", os: "macos-latest" } + - { python-version: "3.9", os: "macos-latest" } + - { python-version: "3.11", os: "macos-latest" } + include: + - { python-version: "3.8", os: "macos-13" } + - { python-version: "3.9", os: "macos-13" } + - { python-version: "3.11", os: "macos-13" } defaults: run: shell: bash @@ -32,18 +43,18 @@ jobs: uses: actions/setup-python@v4.7.1 with: python-version: ${{ matrix.python-version }} - cache: 'poetry' + cache: "poetry" - name: Install dependencies run: poetry install --no-interaction --extras syntax if: ${{ matrix.python-version != '3.12' }} - - name: Install dependencies for 3.12 # https://github.com/Textualize/textual/issues/3491#issuecomment-1854156476 + - name: Install dependencies for 3.12 # https://github.com/Textualize/textual/issues/3491#issuecomment-1854156476 run: poetry install --no-interaction if: ${{ matrix.python-version == '3.12' }} - name: Test with pytest run: | poetry run pytest tests -v --cov=./src/textual --cov-report=xml:./coverage.xml --cov-report term-missing if: ${{ matrix.python-version != '3.12' }} - - name: Test with pytest for 3.12 # https://github.com/Textualize/textual/issues/3491#issuecomment-1854156476 + - name: Test with pytest for 3.12 # https://github.com/Textualize/textual/issues/3491#issuecomment-1854156476 run: | poetry run pytest tests -v --cov=./src/textual --cov-report=xml:./coverage.xml --cov-report term-missing -m 'not syntax' if: ${{ matrix.python-version == '3.12' }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc0b80d2a..7decf03774 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fixed `TextArea` to end mouse selection only if currently selecting https://github.com/Textualize/textual/pull/4436 +- Fixed issue with margins https://github.com/Textualize/textual/pull/4441 ### Changed diff --git a/src/textual/layouts/horizontal.py b/src/textual/layouts/horizontal.py index 02672ae879..e4581f5734 100644 --- a/src/textual/layouts/horizontal.py +++ b/src/textual/layouts/horizontal.py @@ -38,7 +38,7 @@ def arrange( ] ) + (box_margins[0].left + box_margins[-1].right), - min( + max( [ margin_top + margin_bottom for margin_top, _, margin_bottom, _ in box_margins diff --git a/src/textual/layouts/vertical.py b/src/textual/layouts/vertical.py index 995b135439..a81518f1d2 100644 --- a/src/textual/layouts/vertical.py +++ b/src/textual/layouts/vertical.py @@ -29,7 +29,7 @@ def arrange( ] if box_margins: resolve_margin = Size( - min( + max( [ margin_right + margin_left for _, margin_right, _, margin_left in box_margins diff --git a/src/textual/widget.py b/src/textual/widget.py index e334c18ecf..1c77c1581b 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -1233,9 +1233,11 @@ def get_content_width(self, container: Size, viewport: Size) -> int: Returns: The optimal width of the content. """ + if self.is_container: assert self._layout is not None - return self._layout.get_content_width(self, container, viewport) + width = self._layout.get_content_width(self, container, viewport) + return width cache_key = container.width if self._content_width_cache[0] == cache_key: diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 5941436dd7..5b7e08df7c 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -24615,6 +24615,164 @@ ''' # --- +# name: test_margin_multiple + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MyApp + + + + + + + + + + ═══ + foo + ═══ + + + ──────────────────────────── + + + ──────────────────────────── + + ═══ + bar + ══════ + bar + ═══ + + + + ──────────────────────────────────────────────────────── + + + + + + + + + + ''' +# --- # name: test_markdown_component_classes_reloading ''' diff --git a/tests/snapshot_tests/snapshot_apps/margin_multiple.py b/tests/snapshot_tests/snapshot_apps/margin_multiple.py new file mode 100644 index 0000000000..81eb017bff --- /dev/null +++ b/tests/snapshot_tests/snapshot_apps/margin_multiple.py @@ -0,0 +1,43 @@ +from textual.app import App, ComposeResult +from textual.containers import Container, ScrollableContainer, Horizontal +from textual.widgets import Label + + +class CompoundWidget(ScrollableContainer): + DEFAULT_CSS = """ + #inner { + width: 1fr; + background: $panel; + align: center middle; + margin: 5; + border: green; + + } + + Label { + border: double yellow; + } + """ + + def compose(self) -> ComposeResult: + yield Label("foo") + with Container(id="inner"): + yield Label("bar") + + +class MyApp(App): + CSS = """ + #widget2 > Label { + display: none; + } + + """ + + def compose(self) -> ComposeResult: + with Horizontal(): + yield CompoundWidget(id="widget1") + yield CompoundWidget(id="widget2") + + +if __name__ == "__main__": + MyApp().run() diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 77e9855578..f9650a016f 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -1236,7 +1236,7 @@ def test_example_pride(snap_compare): """Test the pride example.""" assert snap_compare(EXAMPLES_DIR / "pride.py") - + def test_button_with_console_markup(snap_compare): """Regression test for https://github.com/Textualize/textual/issues/4328""" assert snap_compare(SNAPSHOT_APPS_DIR / "button_markup.py") @@ -1249,3 +1249,7 @@ def test_width_100(snap_compare): def test_button_with_multiline_label(snap_compare): assert snap_compare(SNAPSHOT_APPS_DIR / "button_multiline_label.py") + + +def test_margin_multiple(snap_compare): + assert snap_compare(SNAPSHOT_APPS_DIR / "margin_multiple.py")