livereload server in python (MAINTAINERS NEEDED)

Overview

LiveReload

Reload webpages on changes, without hitting refresh in your browser.

Installation

python-livereload is for web developers who know Python, and is available on PyPI.

$ pip install livereload

Command Line Interface

python-livereload provides a command line utility, livereload, for starting a server in a directory.

By default, it will listen to port 35729, the common port for LiveReload browser extensions.

$ livereload --help
usage: livereload [-h] [-p PORT] [-w WAIT] [directory]

Start a `livereload` server

positional arguments:
  directory             Directory to watch for changes

optional arguments:
  -h, --help            show this help message and exit
  -p PORT, --port PORT  Port to run `livereload` server on
  -w WAIT, --wait WAIT  Time delay before reloading

Older versions of python-livereload used a Guardfile to describe optional additional rules for files to watch and build commands to run on changes. This conflicted with other tools that used the same file for their configuration and is no longer supported since python-livereload 2.0.0. Instead of a Guardfile you can now write a Python script using very similar syntax and run it instead of the command line application.

Developer Guide

The new livereload server is designed for developers. It can power a wsgi application now:

from livereload import Server, shell

server = Server(wsgi_app)

# run a shell command
server.watch('static/*.stylus', 'make static')

# run a function
def alert():
    print('foo')
server.watch('foo.txt', alert)

# output stdout into a file
server.watch('style.less', shell('lessc style.less', output='style.css'))

server.serve()

The Server class accepts parameters:

  • app: a wsgi application
  • watcher: a watcher instance, you don't have to create one

server.watch

server.watch can watch a filepath, a directory and a glob pattern:

server.watch('path/to/file.txt')
server.watch('directory/path/')
server.watch('glob/*.pattern')

You can also use other library (for example: formic) for more powerful file adding:

for filepath in formic.FileSet(include="**.css"):
    server.watch(filepath, 'make css')

You can delay a certain seconds to send the reload signal:

# delay 2 seconds for reloading
server.watch('path/to/file', delay=2)

server.setHeader

`server.setHeader` can be used to add one or more headers to the HTTP response:

server.setHeader('Access-Control-Allow-Origin', '*')
server.setHeader('Access-Control-Allow-Methods', '*')

server.serve

Setup a server with server.serve method. It can create a static server and a livereload server:

# use default settings
server.serve()

# livereload on another port
server.serve(liveport=35729)

# use custom host and port
server.serve(port=8080, host='localhost')

# open the web browser on startup, based on $BROWSER environment variable
server.serve(open_url_delay=5, debug=False)

# set a custom default file to open
server.serve(default_filename='example.html')

shell

The powerful shell function will help you to execute shell commands. You can use it with server.watch:

# you can redirect command output to a file
server.watch('style.less', shell('lessc style.less', output='style.css'))

# commands can be a list
server.watch('style.less', shell(['lessc', 'style.less'], output='style.css'))

# working with Makefile
server.watch('assets/*.styl', shell('make assets', cwd='assets'))

Frameworks Integration

Livereload can work seamlessly with your favorite framework.

Django

For Django there is a management command included.

To use simply

  • add 'livereload' to your INSTALLED_APPS and
  • then run ./manage.py livereload.

For available options like host and ports please refer to ./manage.py livereload -h.

To automagically serve static files like the native runserver command you have to use dj-static. (follow the simple instructions there).

Flask

Wrap Flask with livereload is much simpler:

# app is a Flask object
app = create_app()

# remember to use DEBUG mode for templates auto reload
# https://github.com/lepture/python-livereload/issues/144
app.debug = True

server = Server(app.wsgi_app)
# server.watch
server.serve()

Bottle

Wrap the Bottle app with livereload server:

# Without this line templates won't auto reload because of caching.
# http://bottlepy.org/docs/dev/tutorial.html#templates
bottle.debug(True)

app = Bottle()
server = Server(app)
# server.watch
server.serve()

Security Report

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

Comments
  • version 2.4

    version 2.4

    A new release:

    1. [x] wsgi app works
    2. [x] bugfix https://github.com/lepture/python-livereload/issues/102
    3. [x] clever watcher https://github.com/lepture/python-livereload/issues/98
    4. [x] add a filter for directory watching https://github.com/lepture/python-livereload/issues/97
    5. [x] unicode issue: https://github.com/lepture/python-livereload/pull/79
    6. [x] watch without browser open: https://github.com/lepture/python-livereload/issues/109
    opened by lepture 28
  • Want another maintainer? Add me. :)

    Want another maintainer? Add me. :)

    Ahoy @lepture! I see an all-caps "MAINTAINERS NEEDED" on this repository.

    I'd be happy to take over maintainership of this project. Would you be willing to add me as an admin/transfer this project over to me so that I could take it forward? Notably, I'm interested in this project coming from sphinx-autobuild (a downstream user of this package) and plan to put this project under jazzband in the long run.

    opened by pradyunsg 12
  • FakeWaiter: trigger tasks always

    FakeWaiter: trigger tasks always

    I am using python-livereload for a make watch task, and would like to trigger the make scss task always, without some browser having connected before.

    This can be done by attaching some fake-Waiter like this:

    class FakeWaiter:
        "A no-op waiter to trigger scss re-building always."
        def write_message(*args, **kwargs):
            pass
    
    LiveReloadHandler.waiters.add(FakeWaiter)
    

    I think this should be supported by default (by some option), or a Waiter like this should be provided by python-livereload (in case the implementation changes).

    opened by blueyed 9
  • add sphinx compiler

    add sphinx compiler

    I've added new compiler to build html documents based on Sphinx. Does it help you?

    Example Guardfile is:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from livereload.task import Task
    from livereload.compiler import sphinx
    
    Task.add('*.rst', sphinx())
    
    opened by skitazaki 9
  • Upload wheels to PyPI

    Upload wheels to PyPI

    Wheels (.whl) for this package are currently missing from PyPI. Could wheels be uploaded for the current and future releases?

    Read more about the advantages of wheels to understand why generating wheel distributions are important.

    To create a wheel along with source distribution:

    (venv) $ pip install --upgrade pip setuptools wheel
    (venv) $ python setup.py sdist bdist_wheel
    
    # See dist/*.whl
    

    To upload wheels:

    (venv) $ pip install twine
    (venv) $ twine upload dist/*
    
    opened by johnthagen 8
  • livereload does nothing if no browser is watching

    livereload does nothing if no browser is watching

    We use livereload in http://getnikola.com to monitor site changes and trigger rebuilds.

    When using nikola auto -b which calls livereload with open_url=True everything works normally. However, when not using that, rebuilds are never triggered.

    opened by ralsina 8
  • Broken browser caching?

    Broken browser caching?

    I used livereload 2.3.2 on my Sphinx documentation successfully. Then I pip installed git master. Now reloading doesn't work:

    1. I load a page in the browser, http://localhost:5500/foo.html
    2. I edit foo.rst
    3. I see the browser page reload
    4. I still see the old content
    5. I verify that the HTML file on disk has new content
    6. I hit Ctrl-R to reload the browser tab manually
    7. I still see the old content

    I used Chromium's developer tools to look at the HTTP requests: livereload is responding with a 304 Not Modified to the request, which includes If-Modified-Since and If-None-Match headers.

    I can see the new content if I use Ctrl+Shift+R to reload. I see HTTP responses with Server: TornadoServer/4.0.2 and Etag: "586cf5820eb5f1633c93a490820935b6" which doesn't change, even when the HTML file changes.

    type: bug 
    opened by mgedmin 8
  • pyinotify does not work if the file inode changes (i.e. when the original file is deleted and moved over)

    pyinotify does not work if the file inode changes (i.e. when the original file is deleted and moved over)

    When creating a Guardfile I have noted that if I add a task like this:

    Task.add('my_directory')

    everything works fine, but if I add a task like this:

    Task.add('my_file.html')

    when I modify the my_file.html file the livereload event does not trigger.

    When looking for a solution I have tried to force the HAS_PYINOTIFY variable to False in the task.py file, and when disabling pyinotify everything works correctly, which means the problem lies somewhere either in the pyinotify integration, or in pyinotify itself, or I have some settings that prevent inotify to notify changes to single files.

    I am using Fedora 19 x86_64 with kernel 3.10.10-200.fc19.x86_64 and pyinotify version 0.9.4

    opened by bugnano 8
  • Asyncio NotImplemented Error with Python 3.8 and Windows

    Asyncio NotImplemented Error with Python 3.8 and Windows

    As explained in tornadoweb/tornado#2608, the default behavior in Python 3.8 has changed and we get an error on Windows only:

    >livereload site
    [I 191026 22:40:22 server:296] Serving on http://127.0.0.1:35729
    Traceback (most recent call last):
      File "c:\program files\python38\lib\runpy.py", line 192, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "c:\program files\python38\lib\runpy.py", line 85, in _run_code
        exec(code, run_globals)
      File "C:\Program Files\Python38\Scripts\livereload.exe\__main__.py", line 7, in <module>
      File "c:\program files\python38\lib\site-packages\livereload\cli.py", line 60, in main
        server.serve(host=args.host, port=args.port, root=args.directory,
      File "c:\program files\python38\lib\site-packages\livereload\server.py", line 298, in serve
        self.application(
      File "c:\program files\python38\lib\site-packages\livereload\server.py", line 253, in application
        app.listen(port, address=host)
      File "c:\program files\python38\lib\site-packages\tornado\web.py", line 2112, in listen
        server.listen(port, address)
      File "c:\program files\python38\lib\site-packages\tornado\tcpserver.py", line 152, in listen
        self.add_sockets(sockets)
      File "c:\program files\python38\lib\site-packages\tornado\tcpserver.py", line 165, in add_sockets
        self._handlers[sock.fileno()] = add_accept_handler(
      File "c:\program files\python38\lib\site-packages\tornado\netutil.py", line 279, in add_accept_handler
        io_loop.add_handler(sock, accept_handler, IOLoop.READ)
      File "c:\program files\python38\lib\site-packages\tornado\platform\asyncio.py", line 99, in add_handler
        self.asyncio_loop.add_reader(fd, self._handle_events, fd, IOLoop.READ)
      File "c:\program files\python38\lib\asyncio\events.py", line 501, in add_reader
        raise NotImplementedError
    NotImplementedError
    

    It appears that Tornado is not going to override the default themselves, but instead expect applications using Tornado to override the default. In other words, Tornado expects Python-Livereload to set this itself.

    Of course users of Python-Livereload who are calling the lib programmatically through Python code can just do the override themselves. However, anyone using the command line tool will need Python-Livereload to address this for them. Therefore, my question is: will Python-Livereload be addressing this for all users or only the command line tool?

    opened by waylan 7
  • Added `bin/livereload`

    Added `bin/livereload`

    As discussed in #54, I have added an executable script which was previously removed in 2.0.0. In this PR:

    • Added bin/livereload to setup.py's scripts
    • Added argparse based script that starts a livereload server
      • Defaults port to standard 35729 and watching local directory

    Fixes #54

    /cc @lepture

    opened by twolfson 7
  • Could not connect to LiveReload server.

    Could not connect to LiveReload server.

    I got on one terminal :

     ~/Bureau $ livereload
    Serving path . on 127.0.0.1:35729
    [I 130831 09:32:15 web:1359] 200 GET /livereload.js?ext=Firefox&extver=2.0.8 (127.0.0.1) 2.95ms
    [I 130831 09:32:16 web:1359] 304 GET /livereload.js?ext=Firefox&extver=2.0.8 (127.0.0.1) 2.36ms
    

    On another :

    ~/Bureau $ serve
    Serving HTTP on 0.0.0.0 port 8000 ...
    localhost - - [31/Aug/2013 09:32:15] "GET /test.html HTTP/1.1" 200 -
    localhost - - [31/Aug/2013 09:32:15] "GET /style.css HTTP/1.1" 200 -
    localhost - - [31/Aug/2013 09:32:16] "GET /test.html HTTP/1.1" 200 -
    localhost - - [31/Aug/2013 09:32:16] "GET /style.css HTTP/1.1" 200 -
    localhost - - [31/Aug/2013 09:32:20] "GET /test.html HTTP/1.1" 200 -
    localhost - - [31/Aug/2013 09:32:20] "GET /style.css HTTP/1.1" 200 -
    localhost - - [31/Aug/2013 09:32:21] "GET /test.html HTTP/1.1" 200 -
    localhost - - [31/Aug/2013 09:32:21] "GET /style.css HTTP/1.1" 200 -
    

    And an extension installed firefox 23.0 / Ubuntu 12.04. from here :

    http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-

    If I click on the LiveReload extension button, I get the following message :

    Could not connect to LiveReload server. Please make sure that a compatible LiveReload server is running. (We recommand guard-livereload, until LiveReload 2 comes to your platform.)

    Editing the CSS file does not reflect changes. Reload the page does, of course.

    opened by sametmax 7
  • Watcher: always pass 'paths' argument to callback func

    Watcher: always pass 'paths' argument to callback func

    This is a follow-up of #204 This PR makes the behaviour more consistent: file paths are always provided to the callback function, not only when a glob pattern is used (which is currently the case)

    opened by Lucas-C 0
  • ignores implicitly for no good reason.

    ignores implicitly for no good reason.

    I've tried to set it up with Flask and get it going for a really basic scenario. Apart from crashing anytime I edit any of the .py files, it ignores the html file I'm interested in, disregarding what I add to server.watch().

    Here's the minimal setup:

    from flask import Flask, render_template
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        return render_template('index.html')
    
    if __name__ == '__main__':
        from livereload import Server
        server = Server(app.wsgi_app)
        server.watch('./templates/*.html')
        server.serve(debug=True)
    

    folder structure:

    app.py
    templates/index.html
    

    Example stacktrace:

    [I 221121 18:13:30 server:335] Serving on http://127.0.0.1:5500
    [I 221121 18:13:30 handlers:62] Start watching changes
    [I 221121 18:13:30 handlers:64] Start detecting changes
    [I 221121 18:13:31 handlers:135] Browser Connected: http://127.0.0.1:5500/
    [I 221121 18:13:31 handlers:135] Browser Connected: http://127.0.0.1:5500/
    [I 221121 18:13:32 handlers:82] Ignore: ./templates\index.html
    [I 221121 18:13:33 handlers:92] Reload 2 waiters: None
    [I 221121 18:13:34 handlers:135] Browser Connected: http://127.0.0.1:5500/
    
    opened by Zenahr 0
  • Tests failing

    Tests failing

    Hey, when packaging this for Arch Linux I noticed this failing test, I am not sure what it is happening here. Does anyone have any pointers?

    ============================= test session starts ==============================
    platform linux -- Python 3.9.9, pytest-6.2.5, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python
    cachedir: .pytest_cache
    rootdir: /build/python-livereload/src/python-livereload-2.6.3
    collecting ... collected 5 items
    
    tests/test_watcher.py::TestWatcher::test_watch_dir PASSED                [ 20%]
    tests/test_watcher.py::TestWatcher::test_watch_file PASSED               [ 40%]
    tests/test_watcher.py::TestWatcher::test_watch_glob PASSED               [ 60%]
    tests/test_watcher.py::TestWatcher::test_watch_ignore PASSED             [ 80%]
    tests/test_watcher.py::TestWatcher::test_watch_multiple_dirs FAILED      [100%]
    
    =================================== FAILURES ===================================
    _____________________ TestWatcher.test_watch_multiple_dirs _____________________
    
    self = <tests.test_watcher.TestWatcher testMethod=test_watch_multiple_dirs>
    
        def test_watch_multiple_dirs(self):
            first_dir = os.path.join(tmpdir, 'first')
            second_dir = os.path.join(tmpdir, 'second')
    
            watcher = Watcher()
    
            os.mkdir(first_dir)
            watcher.watch(first_dir)
            assert watcher.examine() == (None, None)
    
            first_path = os.path.join(first_dir, 'foo')
            with open(first_path, 'w') as f:
                f.write('')
            assert watcher.examine() == (first_path, None)
            assert watcher.examine() == (None, None)
    
            os.mkdir(second_dir)
            watcher.watch(second_dir)
            assert watcher.examine() == (None, None)
    
            second_path = os.path.join(second_dir, 'bar')
            with open(second_path, 'w') as f:
                f.write('')
            assert watcher.examine() == (second_path, None)
            assert watcher.examine() == (None, None)
    
            with open(first_path, 'a') as f:
                f.write('foo')
    >       assert watcher.examine() == (first_path, None)
    E       AssertionError: assert (None, None) == ('/build/python-livereload/src/python-livereload-2.6.3/tests/tmp/first/foo',\n None)
    E         At index 0 diff: None != '/build/python-livereload/src/python-livereload-2.6.3/tests/tmp/first/foo'
    E         Full diff:
    E           (
    E         -  '/build/python-livereload/src/python-livereload-2.6.3/tests/tmp/first/foo',
    E         +  None,
    E            None,
    E           )
    
    tests/test_watcher.py:147: AssertionError
    =========================== short test summary info ============================
    FAILED tests/test_watcher.py::TestWatcher::test_watch_multiple_dirs - Asserti...
    ========================= 1 failed, 4 passed in 3.16s ==========================
    
    opened by FFY00 1
  • add option to open specific files in the browser

    add option to open specific files in the browser

    context, i'm using live-reload to auto-update views on reveal.js presentations in markdown files

    so i have a directory tree like

    repo:
    -  assets: 
          | git submodule pointing to reveal.js
    -  mytalk:
       - mytalk.html
       - mytalk.md
    - my-othertalk: 
        ...
    - tox.ini
    

    where tox.ini just spells something like

    [tox]
    skipsdist=true
    envlist=live
    [testenv:live]
    skip_install=true
    deps =
       livereload
    commands =
     	livereload {{posargs}}
    

    i would like to be able to invoke something like tox -- --open-in-browser mytalk/mytalk.html

    to have live-reload open $hostname:$randomport/mytalk/mytalk.html instead of going to the server and adding the path there

    opened by RonnyPfannschmidt 0
Releases(2.6.3)
Owner
Hsiaoming Yang
This guy is too lazy to introduce himself.
Hsiaoming Yang
Waitress - A WSGI server for Python 2 and 3

Waitress Waitress is a production-quality pure-Python WSGI server with very acceptable performance. It has no dependencies except ones which live in t

Pylons Project 1.2k Dec 30, 2022
Python HTTP Server

Python HTTP Server Preview Languange and Code Editor: How to run? Download the zip first. Open the http.py and wait 1-2 seconds. You will see __pycach

SonLyte 16 Oct 21, 2021
Robyn is an async Python backend server with a runtime written in Rust, btw.

Robyn is an async Python backend server with a runtime written in Rust, btw. Python server running on top of of Rust Async RunTime. Installation

Sanskar Jethi 1.8k Dec 30, 2022
gunicorn 'Green Unicorn' is a WSGI HTTP Server for UNIX, fast clients and sleepy applications.

Gunicorn Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork worker model ported from Ruby's Unicorn project. The Gunicorn

Benoit Chesneau 8.7k Jan 1, 2023
The lightning-fast ASGI server. 🦄

The lightning-fast ASGI server. Documentation: https://www.uvicorn.org Community: https://discuss.encode.io/c/uvicorn Requirements: Python 3.6+ (For P

Encode 6k Jan 3, 2023
Meinheld is a high performance asynchronous WSGI Web Server (based on picoev)

What's this This is a high performance python wsgi web server. And Meinheld is a WSGI compliant web server. (PEP333 and PEP3333 supported) You can als

Yutaka Matsubara 1.4k Jan 1, 2023
An HTTP server to easily download and upload files.

httpsweet An HTTP server to easily download and upload files. It was created with flexibility in mind, allowing be used in many different situations,

Eloy 17 Dec 23, 2022
Green is a clean, colorful, fast python test runner.

Green -- A clean, colorful, fast python test runner. Features Clean - Low redundancy in output. Result statistics for each test is vertically aligned.

Nathan Stocks 756 Dec 22, 2022
Scalable user load testing tool written in Python

Locust Locust is an easy to use, scriptable and scalable performance testing tool. You define the behaviour of your users in regular Python code, inst

Locust.io 20.4k Jan 8, 2023
A cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.

PyAutoGUI PyAutoGUI is a cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard. pip inst

Al Sweigart 7.6k Jan 1, 2023
splinter - python test framework for web applications

splinter - python tool for testing web applications splinter is an open source tool for testing web applications using Python. It lets you automate br

Cobra Team 2.6k Dec 27, 2022
Let your Python tests travel through time

FreezeGun: Let your Python tests travel through time FreezeGun is a library that allows your Python tests to travel through time by mocking the dateti

Steve Pulec 3.5k Jan 9, 2023
HTTP client mocking tool for Python - inspired by Fakeweb for Ruby

HTTPretty 1.0.5 HTTP Client mocking tool for Python created by Gabriel Falcão . It provides a full fake TCP socket module. Inspired by FakeWeb Github

Gabriel Falcão 2k Jan 6, 2023
A utility for mocking out the Python Requests library.

Responses A utility library for mocking out the requests Python library. Note Responses requires Python 2.7 or newer, and requests >= 2.0 Installing p

Sentry 3.8k Jan 2, 2023
A test fixtures replacement for Python

factory_boy factory_boy is a fixtures replacement based on thoughtbot's factory_bot. As a fixtures replacement tool, it aims to replace static, hard t

FactoryBoy project 3k Jan 5, 2023
Mixer -- Is a fixtures replacement. Supported Django, Flask, SqlAlchemy and custom python objects.

The Mixer is a helper to generate instances of Django or SQLAlchemy models. It's useful for testing and fixture replacement. Fast and convenient test-

Kirill Klenov 871 Dec 25, 2022
Faker is a Python package that generates fake data for you.

Faker is a Python package that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in yo

Daniele Faraglia 15.2k Jan 1, 2023
Mimesis is a high-performance fake data generator for Python, which provides data for a variety of purposes in a variety of languages.

Mimesis - Fake Data Generator Description Mimesis is a high-performance fake data generator for Python, which provides data for a variety of purposes

Isaak Uchakaev 3.8k Jan 1, 2023
Coroutine-based concurrency library for Python

gevent Read the documentation online at http://www.gevent.org. Post issues on the bug tracker, discuss and ask open ended questions on the mailing lis

gevent 5.9k Dec 28, 2022