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
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 01, 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 01, 2023
Sixpack is a language-agnostic a/b-testing framework

Sixpack Sixpack is a framework to enable A/B testing across multiple programming languages. It does this by exposing a simple API for client libraries

1.7k Dec 24, 2022
Automatically mock your HTTP interactions to simplify and speed up testing

VCR.py 📼 This is a Python version of Ruby's VCR library. Source code https://github.com/kevin1024/vcrpy Documentation https://vcrpy.readthedocs.io/ R

Kevin McCarthy 2.3k Jan 01, 2023
create custom test databases that are populated with fake data

About Generate fake but valid data filled databases for test purposes using most popular patterns(AFAIK). Current support is sqlite, mysql, postgresql

Emir Ozer 2.2k Jan 06, 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
A screamingly fast Python 2/3 WSGI server written in C.

bjoern: Fast And Ultra-Lightweight HTTP/1.1 WSGI Server A screamingly fast, ultra-lightweight WSGI server for CPython 2 and CPython 3, written in C us

Jonas Haag 2.9k Dec 21, 2022
The successor to nose, based on unittest2

Welcome to nose2 nose2 is the successor to nose. It's unittest with plugins. nose2 is a new project and does not support all of the features of nose.

738 Jan 09, 2023
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
livereload server in python (MAINTAINERS NEEDED)

LiveReload Reload webpages on changes, without hitting refresh in your browser. Installation python-livereload is for web developers who know Python,

Hsiaoming Yang 977 Dec 14, 2022
A drop-in replacement for Django's runserver.

About A drop in replacement for Django's built-in runserver command. Features include: An extendable interface for handling things such as real-time l

David Cramer 1.3k Dec 15, 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 01, 2023
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
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 01, 2023
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
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
a socket mock framework - for all kinds of socket animals, web-clients included

mocket /mɔˈkɛt/ A socket mock framework for all kinds of socket animals, web-clients included - with gevent/asyncio/SSL support ...and then MicroPytho

Giorgio Salluzzo 249 Dec 14, 2022
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
No longer maintained, please migrate to model_bakery

Model Mommy: Smart fixtures for better tests IMPORTANT: Model Mommy is no longer maintained and was replaced by Model Bakery. Please, consider migrati

Bernardo Fontes 917 Oct 04, 2022
FastWSGI - An ultra fast WSGI server for Python 3

FastWSGI - An ultra fast WSGI server for Python 3

James Roberts 343 Dec 22, 2022