1
1
"""A dialog for viewing the text of a PEP."""
2
2
3
+ ##############################################################################
4
+ # Python imports.
5
+ from pathlib import Path
6
+
3
7
##############################################################################
4
8
# Textual imports.
5
9
from textual import on , work
11
15
##############################################################################
12
16
# Local imports.
13
17
from ...peps import API
14
- from ..data import PEP
18
+ from ..data import PEP , cache_dir
15
19
16
20
17
21
##############################################################################
@@ -57,7 +61,7 @@ class PEPViewer(ModalScreen[None]):
57
61
}
58
62
"""
59
63
60
- BINDINGS = [("escape" , "close" )]
64
+ BINDINGS = [("escape" , "close" ), ( "ctrl+r" , "refresh" ) ]
61
65
62
66
def __init__ (self , pep : PEP ) -> None :
63
67
"""Initialise the dialog.
@@ -75,34 +79,67 @@ def compose(self) -> ComposeResult:
75
79
dialog .border_title = f"PEP{ self ._pep .number } "
76
80
yield VerticalScroll (Static (id = "text" ), id = "viewer" )
77
81
with Horizontal (id = "buttons" ):
78
- yield Button ("Close [dim]\\ [Esc][/]" , variant = "default" )
82
+ yield Button ("Refresh [dim]\\ [^r][/]" , id = "refresh" )
83
+ yield Button ("Close [dim]\\ [Esc][/]" , id = "close" )
84
+
85
+ @property
86
+ def _cache_name (self ) -> Path :
87
+ """The name of the file that is the cached version of the PEP source."""
88
+ return cache_dir () / API .pep_file (self ._pep .number )
79
89
80
90
@work
81
91
async def _download_text (self ) -> None :
82
- """Download the text of the PEP."""
83
- try :
84
- self .query_one ("#text" , Static ).update (
85
- await API ().get_pep (self ._pep .number )
86
- )
87
- except API .RequestError as error :
88
- self .query_one ("#text" , Static ).update ("[error]Error[/]" )
89
- self .notify (
90
- str (error ), title = "Error downloading PEP source" , severity = "error"
91
- )
92
- return
93
- finally :
94
- self .query_one ("#viewer" ).loading = False
92
+ """Download the text of the PEP.
93
+
94
+ Notes:
95
+ Once downloaded a local copy will be saved. Subsequently, when
96
+ attempting to download the PEP, this local copy will be used
97
+ instead.
98
+ """
99
+ pep_source = ""
100
+ if self ._cache_name .exists ():
101
+ try :
102
+ pep_source = self ._cache_name .read_text (encoding = "utf-8" )
103
+ except IOError :
104
+ pass
105
+
106
+ if not pep_source :
107
+ try :
108
+ self ._cache_name .write_text (
109
+ pep_source := await API ().get_pep (self ._pep .number ),
110
+ encoding = "utf-8" ,
111
+ )
112
+ except IOError :
113
+ pass
114
+ except API .RequestError as error :
115
+ pep_source = "Error downloading PEP source"
116
+ self .notify (
117
+ str (error ), title = "Error downloading PEP source" , severity = "error"
118
+ )
119
+
120
+ self .query_one ("#text" , Static ).update (pep_source )
121
+ self .query_one ("#viewer" ).loading = False
95
122
self .set_focus (self .query_one ("#viewer" ))
96
123
97
124
def on_mount (self ) -> None :
98
125
"""Populate the dialog once the"""
99
126
self .query_one ("#viewer" ).loading = True
100
127
self ._download_text ()
101
128
102
- @on (Button .Pressed )
129
+ @on (Button .Pressed , "#close" )
103
130
def action_close (self ) -> None :
104
131
"""Close the dialog."""
105
132
self .dismiss (None )
106
133
134
+ @on (Button .Pressed , "#refresh" )
135
+ def action_refresh (self ) -> None :
136
+ """Refresh the PEP source."""
137
+ try :
138
+ self ._cache_name .unlink (missing_ok = True )
139
+ except IOError :
140
+ pass
141
+ self .query_one ("#viewer" ).loading = True
142
+ self ._download_text ()
143
+
107
144
108
145
### pep_viewer.py ends here
0 commit comments