Commit Graph

5707 Commits

Author SHA1 Message Date
Will McGugan
55fc89cf14 changelog v0.13.0 2023-03-02 14:51:59 +00:00
Will McGugan
2bf3ed1fea version bump (#1923) 2023-03-02 14:50:21 +00:00
Will McGugan
41003e356c Fix content width (#1910)
* fix calculation for scrollbars

* added snapshot

* fix for name change

* snapshot

* fix for textual colors

* remove logs

* scrollbar logic

* scroll logic

* remove dead code

* snapshot tests

* scrollbar mechanism

* tidy

* demo tweak

* preset window size

* no need for repaint

* Restore repaint

* wait for idle on pause

* colors tweak

* remove wait for idle

* snapshot

* small sleep

* change stabilizer

* debug tweaks

* remove debug

* remove debug

* snapshot test

* docstring

* changelog

* add pause
2023-03-02 14:39:31 +00:00
Dave Pearson
88a0349cb6 Merge pull request #1917 from davep/button-docs-widget-redux
Tidy up some Button documentation
2023-03-02 13:29:49 +00:00
Dave Pearson
0df17fc8f0 Tidy up some Button documentation
Adds missing documentation for disabled to each of the button variant
constructors, and also pulls in a couple more public-visible Button-related
types into the docs.
2023-03-01 16:46:47 +00:00
Dave Pearson
086c7d6688 Merge pull request #1909 from davep/widget-doc-sweep
Widget documentation sweep
2023-03-01 16:43:09 +00:00
Dave Pearson
d9ab2ac69c Remove omit a unnecessary word
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-01 16:21:58 +00:00
Dave Pearson
5cfa998fe4 Improved wording
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-01 16:20:52 +00:00
Dave Pearson
88fcf4f070 Improved wording
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-01 16:18:47 +00:00
Dave Pearson
b3fe97e8b4 Improved wording
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-01 16:17:12 +00:00
Dave Pearson
b1c6da2169 Improved wording
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-01 16:16:56 +00:00
Dave Pearson
348fbe2cfa Improved wording
Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com>
2023-03-01 16:16:41 +00:00
Dave Pearson
768d4ae864 Code tidy
Tidying up after an on-forge merge conflict resolution that of course ended
up bypassing black.
2023-03-01 16:11:54 +00:00
Dave Pearson
847e2ccc1a Merge branch 'main' into widget-doc-sweep 2023-03-01 16:07:36 +00:00
Dave Pearson
f439fa90c4 Merge pull request #1915 from davep/interdoc
Interlink the docs with the Python and Rich manuals
2023-03-01 16:05:47 +00:00
Rodrigo Girão Serrão
ed28a7019c Make mypy happy (#1831)
* Helper file for error progress tracking.

* Fix typing of Keys.???.value.

* Assert that we have frame information.

@willmcgugan I went with the asserts because the tone of the code tells me that we are kind of certain that the current and previous frames always exist. Should the function be refactored to handle None for the previous frame (or the current & previous frames) by writing to the buffer without caller information, for example?

* Use inspect.Traceback instead of inspect.FrameInfo.

Looks like the two shared a lot of attributes, so we were trying to use FrameInfo but inspect.getframeinfo returns a Traceback, so that felt like the correct type to use.

* Update after installing msgpack-types.

* Assert we have frame info.

Same fix as in b709219.

* Fix MapGeometry order information typing.

There was another alternative solution, which was to just flatten everything entirely, so that the code actually obeyed the comments.
After all, the comments for the attribute `order` in the definition of `MapGeometry` said that `order` was a tuple of integers defining the painting order, which was not true because the very first widget was having its order defined as `order = ((0,),)` instead of `order = (0,)`.
Thus, another possible solution would be to retype `order` as `tuple[int, ...]` and make everything flat, but I opted for the “tuple of tuples” approach because the sub-tuples will highlight the nested structure of the DOM hierarchy.

* Fix import and typing for fromkeys.

* Assert app is not None.

[skip cli]

* Import missing type.

* Use CallbackType for event Callback.

* Remove variable name clash.

* Ensure ScalarAnimation only receives widgets.

Two other alternatives would be:
 - leave typing of 'widget: DOMNode' and then assert 'widget' is actually of type 'Widget', which works just fine but looks weird in the sense that we type a parameter in one way but then only manage to do any work if it is of another type;
 - type it as 'widget: DOMNode | Widget' and set 'size' to something other than 'widget.outer_size' if 'widget' is a 'DOMNode'.

* Count spacing values as 1 for int instance.

Adding an 'assert not isinstance(spacing, int)' before raising the error sounds reasonable, because 'Spacing.unpack' seems to be able to handle a lone integer just fine, but I decided against it because I would not like to raise an assertion error from within an exception handling inside Textual.
So, to keep it on the safer side, I went with the conditional expression that checks if we have an integer or a tuple.

* Use correct default.

The obvious fix would be to do 'default_factory=RulesMap' but mypy will infer that the type of 'RulesMap' is 'type[RulesMap]' and will not see it as a 'Callable[[], RulesMap]'. That could be fixed by using 'cast'. I decided to use 'RulesMap.__call__'.

[skip ci]

* Use correct abstract methods.

We fix the LSP violation by using the abstract methods that the ABC already provides... Which is a shame, because I thought I was about to write my first Protocol.

* Add missing annotation.

* Fix type inference.

* Check token is not None.

* Revert "Check token is not None."

This reverts commit 0ae463366e.
Upon closer look, this is not the correct fix.

* Check that token is not None.

Checking if the token is not 'None' brings us a tiny step closer to fixing #1849, which still needs to ensure the variable definition is complete and valid, even if empty.

* Type DOMQuery instantiation correctly.

After some fiddling, some crying, and talking to Dave and Will, we got to a partial solution.
I cried a bit more and came up with the fix that entailed lifting 'ExpectType' to outside of 'DOMNode'.
Then, I realised 'ExpectType' and 'QueryType' from 'query.py' were essentially the same thing so I decided to only make use of 'QueryType'.

* Infer correct type while walking.

* Cast to remove doubt about None.

mypy can't infer that if after is None, then before won't.

* Explicitly type variable.

* Cast to console renderable.

@willmcgugan did I understand correctly that this 'cast' is exactly what renderable being possibly a 'RichCast' asks me to do..? To be honest, I was not 100% sure after reading rich's documentation for 'RichCast' and after reading the source of 'rich_cast'.

* Type variable to remove literal ambiguity.

mypy was inferring the type of the empty string as a literal and thus was not type checking the fact that 'render' would either be a string or Text.

* Assert scrollbars always have parents.

* Make scrollbar scroll actions synchronous.

The scrollbars were posting the messages and awaiting for them but that's not what Widget does, which handles scrolling synchronously. Thus, I made them synchronous methods by using 'post_message_no_wait'.

* Use link only when available.

* Update errors.

* Relax type inference.

* Ignore missing imports for uvloop.

'uvloop' is completely optional and this code only exists to cater for the case where the user _already_ has uvloop installed.
With that in mind, it makes sense to silence errors about uvloop not being available because we don't need to know about that.
We only care if uvloop happens to be installed.

* Enable variable reuse.

* Fix type issues in easing.py.

* Fix typing issues in demo.

Fixing the typing issues here involved making use of the messaging features to replace a method (wasn't exactly wrong, but this is more in line with the Textual way of doing things, which should be prevalent in the demo of the framework).
We also dealt with a typing issue in DarkSwitch.on_dark_change by deleting an unnecessary parameter, but the underlying problem is unsolved and was logged as issue #1865.

Related issues: #1865.

* Fix typing issues in _doc.py.

* Type actions with a type alias.

* Make return values optional.

As per discussion with @darrenburns.

* Make StringKey idempotent.

This set up is so that we can easily make sure that a variable of the type str | SK (where SK is a subclass of StringKey) becomes of the type SK.
Instead of having to write a conditional expression to only convert in case of a string, we make SK idempotent so that we can just call it on the value that may still be a string.

* Make sorting type safe.

* Fix typing of StringKey.__new__.

This is needed to ensure the type checkers know the exact type of the instances returned when instantiating subclasses of StringKey.

* Add explicit type variables.

* Type-safe line rendering.

* Type safe _render_line_in_row.

* Type safe _render_cell.

* Type safe ordered_rows property.

* Type safe ordered_columns property.

* Simplify handling of Nones in TwoWayDict.

In the beginning of the work on this PR, mypy flagged two issues in the implementation of TwoWayDict, which would return None when the keys/values were not available but the signatures of get/get_key did not have the missing '| None'.
When I added the '| None' to the return values of TwoWayDict.get and TwoWayDict.get_key, many new errors popped up because the implementation of DataTable assumes, in many different places, that those methods return the exact thing that we asked for, and not None.

To fix this, I started going over the call sites for get/get_key and started adding checks for 'None' and raising the appropriate RowDoesNotExist/ColumnDoesNotExist error.

At some point, I realised that went a little bit against the semantics of the code, which pretty much assumes those accesses WILL work.

So, I subclassed TwoWayDict to specialise it even further to this use case.
The subclass is meant to work with RowKey/ColumnKey as the underlying keys and it will automatically raise an error if the access fails.

CC: @darrenburns.

* Make use of idempotency of StringKey subclasses.

* Make message aware of type of sender.

* Only select when possible.

* Fix typing of reactive attribute.

* Reset cursor upon moving action if needed.

* Assure mypy we have ListItems.

This could be improved (as in, cast wouldn't be needed) if #1871 is resolved favourably.

* Add explicit return.

* Ignore argument types to watch.

Related issues: #1865.

* Type safe App._register.

* Redirect output to void.

* Remove helper file.

* Fix Python compat. issues.

* Button can only accept str/Text as label.

Fixes: #1870.

* Add runtime type check for list items.

This change follows from a discussion in issue #1871.

* Address review comments.

* Revert "Fix typing issues in demo."

This reverts commit f366783920.

* Address review comments.

Related comments: https://github.com/Textualize/textual/pull/1831\#discussion_r1118155296

* Add clarifying comment.

See: https://github.com/Textualize/textual/pull/1831\#discussion_r1118154777

* Revert changes to data table.
2023-03-01 15:50:15 +00:00
Dave Pearson
9fa10ecc18 Interlink the docs with the Python and Rich manuals
All through our docs there are mentions of Python types and also Rich types.
This change will make the vast majority of mentions of them into actual
links that people can follow. So now, for example, when someone sees a
method that returns a `Style`, they can click on it and see what a `Style`
actually is.
2023-03-01 15:42:38 +00:00
Dave Pearson
aa96b54263 Final back-read, typo squishing and markup-fixing
Delivering on a promise made in #1920.
2023-03-01 14:59:36 +00:00
Dave Pearson
24fa963241 Tidy up the docstring of Widget.scroll_to_region
Delivering on a promise made in #1920.
2023-03-01 14:54:28 +00:00
Dave Pearson
53b0e54e9d Tidy up the docstring of Widget.scroll_to_widget
Delivering on a promise made in #1920.
2023-03-01 14:53:59 +00:00
Dave Pearson
5afbf48ef4 Tidy up the docstring of Widget.scroll_page_right
Delivering on a promise made in #1920.
2023-03-01 14:49:45 +00:00
Dave Pearson
ce016d57e2 Tidy up the docstring of Widget.scroll_page_left
Delivering on a promise made in #1920.
2023-03-01 14:49:15 +00:00
Dave Pearson
ab963d2eb6 Tidy up the docstring of Widget.scroll_page_down
Delivering on a promise made in #1920.
2023-03-01 14:48:35 +00:00
Dave Pearson
3122748303 Tidy up the docstring of Widget.scroll_page_up
Delivering on a promise made in #1920.
2023-03-01 14:47:56 +00:00
Dave Pearson
b617d67f3d Tidy up the docstring of Widget._scroll_up_for_pointer
Delivering on a promise made in #1920.
2023-03-01 14:46:25 +00:00
Dave Pearson
ca1abcff5c Tidy up the docstring of Widget.scroll_up
Delivering on a promise made in #1920.
2023-03-01 14:45:47 +00:00
Dave Pearson
f8167ac35e Add some missing markup 2023-03-01 14:44:36 +00:00
Dave Pearson
0992b3650d Tidy up the docstring of Widget._scroll_down_for_pointer
Delivering on a promise made in #1920.
2023-03-01 14:43:55 +00:00
Dave Pearson
2deb90eb8d Tidy up the docstring of Widget.scroll_down
Delivering on a promise made in #1920.
2023-03-01 14:43:14 +00:00
Dave Pearson
e8537c6c65 Tidy up the docstring of Widget._scroll_right_for_pointer
Delivering on a promise made in #1920.
2023-03-01 14:41:07 +00:00
Dave Pearson
acaec3435f Tidy up the docstring of Widget.scroll_right
Delivering on a promise made in #1920.
2023-03-01 14:40:24 +00:00
Dave Pearson
ef29a77315 Remove another default value from Widget.scroll_left
Delivering on a promise made in #1920.
2023-03-01 14:39:14 +00:00
Dave Pearson
30d894314b Tidy up the docstring of Widget._scroll_left_for_pointer
Delivering on a promise made in #1920.
2023-03-01 14:38:52 +00:00
Dave Pearson
ee126a9427 Tidy up the docstring of Widget.scroll_left
Delivering on a promise made in #1920.
2023-03-01 14:37:30 +00:00
Dave Pearson
88f771b4e1 Tidy the wording of a docstring 2023-03-01 14:36:31 +00:00
Dave Pearson
52b69d50d0 Tidy up the docstring of Widget.scroll_to
Delivering on a promise made in #1920.
2023-03-01 14:35:38 +00:00
Dave Pearson
2fce894b90 Tidy up the docstring of Widget._scroll_to
Delivering on a promise made in #1920.
2023-03-01 14:34:11 +00:00
Dave Pearson
cf34e5e7fa Merge branch 'main' into widget-doc-sweep 2023-03-01 14:32:47 +00:00
Dave Pearson
af6d56cf8e Tidy up the docstring of Widget.scroll_end
Delivering on a promise made in #1920.
2023-03-01 14:25:03 +00:00
Dave Pearson
48dd54c481 Tidy up the docstring of Widget.scroll_home
Delivering on a promise made in #1920.
2023-03-01 14:23:38 +00:00
Dave Pearson
22b0b5b047 Tidy up the docstring of Widget.scroll_relative
Delivering on a promise made in #1920.
2023-03-01 14:22:34 +00:00
Dave Pearson
21e7cfb9ca Tidy up the docstring of Widget.scroll_to
Delivering on a promise made in #1920.
2023-03-01 14:17:01 +00:00
Dave Pearson
abdcf2fea8 Add a docstring for EventTreeDataType 2023-03-01 14:10:45 +00:00
Dave Pearson
b73cd781be Improve the docstring of Tree.validate_guide_depth 2023-03-01 14:08:03 +00:00
Dave Pearson
fb5a10a835 Improve the docstring of Tree.validate_cursor_line 2023-03-01 14:07:22 +00:00
Dave Pearson
3850070fd9 Improve the docstring of Tree.process_label
Also give it a return type hint to match the docs.
2023-03-01 14:05:11 +00:00
Dave Pearson
8917bb6da2 Document Tree.root 2023-03-01 13:50:08 +00:00
Dave Pearson
40b41a1b93 Add a docstring to Tree.__init__ 2023-03-01 13:48:58 +00:00
Dave Pearson
80fd76f1f2 Document TreeDataType 2023-03-01 13:45:32 +00:00
Dave Pearson
fa1f699161 Reorder the declaration of the Tree COMPONENT_CLASSES
The only benefit here (which is a good benefit) being that the order will
match the docstring below so it'll be easier to keep track of if everything
is in the docstring or not.
2023-03-01 13:41:32 +00:00