Update upstream source from tag 'upstream/2.6.3'
Update to upstream version '2.6.3'
with Debian dir c9638a728d82f50d1ea027ece5d35c41384d9617
Pierre-Elliott Bécue
3 years ago
0 | # These are supported funding model platforms | |
1 | ||
2 | github: [lepture] | |
3 | patreon: lepture | |
4 | tidelift: pypi/livereload | |
5 | custom: https://lepture.com/donate |
1 | 1 | ========= |
2 | 2 | |
3 | 3 | The full list of changes between each Python LiveReload release. |
4 | ||
5 | Version 2.6.3 | |
6 | ------------- | |
7 | ||
8 | Released on August 22, 2020 | |
9 | ||
10 | 1. Support for custom default filenames. | |
11 | ||
12 | ||
13 | Version 2.6.2 | |
14 | ------------- | |
15 | ||
16 | Released on June 6, 2020 | |
17 | ||
18 | 1. Support for Python 2.8 | |
19 | 2. Enable adding custom headers to response. | |
20 | 3. Updates for Python 2.7 support. | |
21 | 4. Support for use with a reverse proxy. | |
22 | 5. Other bug fixes. | |
23 | ||
4 | 24 | |
5 | 25 | Version 2.6.1 |
6 | 26 | ------------- |
106 | 106 | # delay 2 seconds for reloading |
107 | 107 | server.watch('path/to/file', delay=2) |
108 | 108 | |
109 | server.setHeader | |
110 | ~~~~~~~~~~~~~~~~ | |
111 | ||
112 | ```server.setHeader``` can be used to add one or more headers to the HTTP | |
113 | response:: | |
114 | ||
115 | server.setHeader('Access-Control-Allow-Origin', '*') | |
116 | server.setHeader('Access-Control-Allow-Methods', '*') | |
117 | ||
109 | 118 | |
110 | 119 | server.serve |
111 | 120 | ~~~~~~~~~~~~ |
124 | 133 | |
125 | 134 | # open the web browser on startup, based on $BROWSER environment variable |
126 | 135 | server.serve(open_url_delay=5, debug=False) |
136 | ||
137 | # set a custom default file to open | |
138 | server.serve(default_filename='example.html') | |
127 | 139 | |
128 | 140 | |
129 | 141 | shell |
195 | 207 | server = Server(app) |
196 | 208 | # server.watch |
197 | 209 | server.serve() |
210 | ||
211 | Security Report | |
212 | --------------- | |
213 | ||
214 | To report a security vulnerability, please use the | |
215 | `Tidelift security contact <https://tidelift.com/security>`_. | |
216 | Tidelift will coordinate the fix and disclosure. |
7 | 7 | :license: BSD, see LICENSE for more details. |
8 | 8 | """ |
9 | 9 | |
10 | __version__ = '2.6.1' | |
10 | __version__ = '2.6.3' | |
11 | 11 | __author__ = 'Hsiaoming Yang <me@lepture.com>' |
12 | 12 | __homepage__ = 'https://github.com/lepture/python-livereload' |
13 | 13 |
28 | 28 | from .watcher import get_watcher_class |
29 | 29 | from six import string_types, PY3 |
30 | 30 | |
31 | import sys | |
32 | ||
33 | if sys.version_info >= (3, 7) or sys.version_info.major == 2: | |
34 | import errno | |
35 | else: | |
36 | from os import errno | |
37 | ||
38 | if sys.version_info >= (3, 8) and sys.platform == 'win32': | |
39 | import asyncio | |
40 | asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) | |
41 | ||
31 | 42 | logger = logging.getLogger('livereload') |
32 | 43 | |
33 | 44 | HEAD_END = b'</head>' |
45 | ||
46 | ||
47 | def set_header(fn, name, value): | |
48 | """Helper Function to Add HTTP headers to the server""" | |
49 | def set_default_headers(self, *args, **kwargs): | |
50 | fn(self, *args, **kwargs) | |
51 | self.set_header(name, value) | |
52 | return set_default_headers | |
34 | 53 | |
35 | 54 | |
36 | 55 | def shell(cmd, output=None, mode='w', cwd=None, shell=False): |
66 | 85 | shell=shell) |
67 | 86 | except OSError as e: |
68 | 87 | logger.error(e) |
69 | if e.errno == os.errno.ENOENT: # file (command) not found | |
88 | if e.errno == errno.ENOENT: # file (command) not found | |
70 | 89 | logger.error("maybe you haven't installed %s", cmd[0]) |
71 | 90 | return e |
72 | 91 | stdout, stderr = p.communicate() |
176 | 195 | watcher_cls = get_watcher_class() |
177 | 196 | watcher = watcher_cls() |
178 | 197 | self.watcher = watcher |
198 | self.SFH = StaticFileHandler | |
199 | ||
200 | def setHeader(self, name, value): | |
201 | """Add or override HTTP headers at the at the beginning of the | |
202 | request. | |
203 | ||
204 | Once you have intialized a server, you can add one or more | |
205 | headers before starting the server:: | |
206 | ||
207 | server.setHeader('Access-Control-Allow-Origin', '*') | |
208 | server.setHeader('Access-Control-Allow-Methods', '*') | |
209 | server.serve() | |
210 | ||
211 | :param name: The name of the header field to be defined. | |
212 | :param value: The value of the header field to be defined. | |
213 | """ | |
214 | StaticFileHandler.set_default_headers = set_header( | |
215 | StaticFileHandler.set_default_headers, name, value) | |
216 | self.SFH = StaticFileHandler | |
179 | 217 | |
180 | 218 | def watch(self, filepath, func=None, delay=None, ignore=None): |
181 | 219 | """Add the given filepath for watcher list. |
235 | 273 | if liveport: |
236 | 274 | live_script = escape.utf8(live_script % liveport) |
237 | 275 | else: |
238 | live_script = escape.utf8(live_script % 'window.location.port') | |
276 | live_script = escape.utf8(live_script % "(window.location.port || (window.location.protocol == 'https:' ? 443: 80))") | |
239 | 277 | |
240 | 278 | web_handlers = self.get_web_handlers(live_script) |
241 | 279 | |
265 | 303 | fallback = LiveScriptContainer(self.app, script) |
266 | 304 | return [(r'.*', web.FallbackHandler, {'fallback': fallback})] |
267 | 305 | return [ |
268 | (r'/(.*)', StaticFileHandler, { | |
306 | (r'/(.*)', self.SFH, { | |
269 | 307 | 'path': self.root or '.', |
270 | 'default_filename': 'index.html', | |
308 | 'default_filename': self.default_filename, | |
271 | 309 | }), |
272 | 310 | ] |
273 | 311 | |
274 | 312 | def serve(self, port=5500, liveport=None, host=None, root=None, debug=None, |
275 | 313 | open_url=False, restart_delay=2, open_url_delay=None, |
276 | live_css=True): | |
314 | live_css=True, default_filename='index.html'): | |
277 | 315 | """Start serve the server with the given port. |
278 | 316 | |
279 | 317 | :param port: serve on this port, default is 5500 |
286 | 324 | :param open_url_delay: open webbrowser after the delay seconds |
287 | 325 | :param live_css: whether to use live css or force reload on css. |
288 | 326 | Defaults to True |
327 | :param default_filename: launch this file from the selected root on startup | |
289 | 328 | """ |
290 | 329 | host = host or '127.0.0.1' |
291 | 330 | if root is not None: |
294 | 333 | self._setup_logging() |
295 | 334 | logger.info('Serving on http://%s:%s' % (host, port)) |
296 | 335 | |
336 | self.default_filename = default_filename | |
337 | ||
297 | 338 | self.application( |
298 | 339 | port, host, liveport=liveport, debug=debug, live_css=live_css) |
299 | 340 | |
300 | 341 | # Async open web browser after 5 sec timeout |
301 | if open_url or open_url_delay: | |
302 | if open_url: | |
303 | logger.warn('Use `open_url_delay` instead of `open_url`') | |
304 | sleep = open_url_delay or 5 | |
342 | if open_url: | |
343 | logger.error('Use `open_url_delay` instead of `open_url`') | |
344 | if open_url_delay is not None: | |
305 | 345 | |
306 | 346 | def opener(): |
307 | time.sleep(sleep) | |
347 | time.sleep(open_url_delay) | |
308 | 348 | webbrowser.open('http://%s:%s' % (host, port)) |
309 | 349 | threading.Thread(target=opener).start() |
310 | 350 |
12 | 12 | import logging |
13 | 13 | import os |
14 | 14 | import time |
15 | import sys | |
16 | ||
17 | if sys.version_info.major < 3: | |
18 | import inspect | |
19 | else: | |
20 | from inspect import signature | |
15 | 21 | |
16 | 22 | try: |
17 | 23 | import pyinotify |
90 | 96 | for path in self._tasks: |
91 | 97 | item = self._tasks[path] |
92 | 98 | self._task_mtimes = item['mtimes'] |
93 | if self.is_changed(path, item['ignore']): | |
99 | changed = self.is_changed(path, item['ignore']) | |
100 | if changed: | |
94 | 101 | func = item['func'] |
95 | 102 | delay = item['delay'] |
96 | 103 | if delay and isinstance(delay, float): |
101 | 108 | name = getattr(func, '__name__', 'anonymous') |
102 | 109 | logger.info( |
103 | 110 | "Running task: {} (delay: {})".format(name, delay)) |
104 | func() | |
111 | if sys.version_info.major < 3: | |
112 | sig_len = len(inspect.getargspec(func)[0]) | |
113 | else: | |
114 | sig_len = len(signature(func).parameters) | |
115 | if sig_len > 0 and isinstance(changed, list): | |
116 | func(changed) | |
117 | else: | |
118 | func() | |
105 | 119 | |
106 | 120 | if delays: |
107 | 121 | delay = max(delays) |
122 | 136 | elif os.path.isdir(path): |
123 | 137 | changed = self.is_folder_changed(path, ignore) |
124 | 138 | else: |
125 | changed = self.is_glob_changed(path, ignore) | |
139 | changed = self.get_changed_glob_files(path, ignore) | |
126 | 140 | |
127 | 141 | if not changed: |
128 | 142 | changed = self.is_file_removed() |
189 | 203 | return True |
190 | 204 | return False |
191 | 205 | |
192 | def is_glob_changed(self, path, ignore=None): | |
206 | def get_changed_glob_files(self, path, ignore=None): | |
193 | 207 | """Check if glob path has any changed filepaths.""" |
194 | for f in glob.glob(path): | |
195 | if self.is_file_changed(f, ignore): | |
196 | return True | |
197 | return False | |
208 | if sys.version_info[0] >=3 and sys.version_info[1] >=5: | |
209 | files = glob.glob(path, recursive=True) | |
210 | else: | |
211 | files = glob.glob(path) | |
212 | changed_files = [f for f in files if self.is_file_changed(f, ignore)] | |
213 | return changed_files | |
198 | 214 | |
199 | 215 | |
200 | 216 | class INotifyWatcher(Watcher): |
24 | 24 | url='https://github.com/lepture/python-livereload', |
25 | 25 | packages=['livereload', 'livereload.management.commands'], |
26 | 26 | description='Python LiveReload is an awesome tool for web developers', |
27 | long_description_content_type='text/x-rst', | |
27 | 28 | long_description=fread('README.rst'), |
28 | 29 | entry_points={ |
29 | 30 | 'console_scripts': [ |
31 | 32 | ] |
32 | 33 | }, |
33 | 34 | install_requires=[ |
34 | 'tornado', | |
35 | 'tornado;python_version>"2.7"', | |
36 | 'tornado<6;python_version=="2.7"', | |
35 | 37 | 'six', |
36 | 38 | ], |
37 | 39 | license='BSD', |
52 | 54 | 'Programming Language :: Python :: 3.5', |
53 | 55 | 'Programming Language :: Python :: 3.6', |
54 | 56 | 'Programming Language :: Python :: 3.7', |
57 | 'Programming Language :: Python :: 3.8', | |
55 | 58 | 'Programming Language :: Python :: Implementation :: CPython', |
56 | 59 | 'Programming Language :: Python :: Implementation :: PyPy', |
57 | 60 | 'Topic :: Software Development :: Build Tools', |