Lazydog¶
Python module monitoring user-level file system events like Creation, Modification, Move, Copy, and Deletion of files and folders. Lazydog tries to aggregate low-level events between them in order to emit a minimum number of high-level events (actually one event per user action). Lazydog uses python Watchdog API to detect low-level events.
Getting Started¶
How to use it¶
Where the watchdog module would throw dozen of events after each user event, lazydog only throws one. For example, ask lazidog to watch any existing directory:
$ lazydog /the/directory/you/want/to/watch
And just move a file in the watched directory (here from
/watched/directory/move_test.txt
to
/watched/directory/move_test_2.txt
), and wait 2 seconds. You will
get something like this in the console:
INFO -
INFO - LIST OF THE LAST EVENTS:
INFO - moved: '/move_test.txt' to '/move_test_2.txt' mtime[1512151173.0] size[5]
INFO -
Try to copy the same file, and you will get somthiing like this:
INFO -
INFO - LIST OF THE LAST EVENTS:
INFO - copied: '/move_test_2.txt' to '/move_test_2 - Copie.txt' mtime[1512151173.0] size[5]
INFO -
Only one event per user action. You can try it with other type of action (Deletion, Creation, Modification), and also with directories.
How to use in in third-part apps¶
Below is an example on how to rapidly initialize the high-level lazydog
event handler, and log every new event in the console (using logging
module). The watched directory is the current one (using
os.getcwd()
).
Please note that once installed, using the $ lazydog
command in the
console does just the same.
import logging
import os
from lazydog.handlers import HighlevelEventHandler
# LOG
# create logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# create console handler with a higher log level
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
# add the handlers to the logger
logger.addHandler(console_handler)
# INITIALIZE
# get dir in parameter else current dir
watched_dir = directory if len(directory) > 1 else os.getcwd()
# initializing a new HighlevelEventHandler
highlevel_handler = HighlevelEventHandler.get_instance(watched_dir)
# starting it (since it is a thread)
highlevel_handler.start()
# log first message
logging.info('LISTENING EVENTS IN DIR: \'%s\'' % watched_dir)
# OPERATING
try:
while True:
# The following loop check every 1 second if any new event.
time.sleep(1)
local_events = highlevel_handler.get_available_events()
# If any, it logs it directly in the console.
for e in local_events:
logging.info(e)
# Keyboard <CTRL+C> interrupts the loop
except KeyboardInterrupt:
highlevel_handler.stop()
Getting further¶
Please find full code documentation in an HTML format on ReadTheDocs.org: http://lazydog.readthedocs.io/
Miscellaneous…¶
Watchdog uses inotify by default on Linux to monitor directories for changes. It’s not uncommon to encounter a system limit on the number of files you can monitor (for example 8192 directories). You can get your current inotify file watch limit by executing:
$ cat /proc/sys/fs/inotify/max_user_watches
8192
When this limit is not enough to monitor all files inside a directory, the limit must be increased for Lazydog to work properly. You can set a new limit temporary with:
$ sudo sysctl fs.inotify.max_user_watches=524288
$ sudo sysctl -p
If you like to make your limit permanent, use:
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p
Get it installed, the contributor way¶
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
Prerequisites¶
Main dependency of lazydog, is the python watchdog API. You can install it using the following command:
$ pip3 install watchdog
Please read the official documentation for any question about this project: https://pypi.org/project/watchdog/
Installing development environment¶
Just clone the repository in your local working directory (or fork it).
$ git clone https://github.com/warniiiz/Lazydog
In order to contribute, you will need pytest for testing purpose (or refer to the pytest documentation ).
$ pip3 install pytest
You will also need Sphinx package for documentation purpose (or refer to the Sphinx documentation ).
$ apt-get install python-sphinx
Tests¶
Module testing¶
The different python module are in the /lazydog
directory. Each of
them has attached test functions, that are in the /lazydog/test
directory. You can launch tests unitary like this (for example for
testing the events module):
$ pytest lazydog/test/test_events.py
Kind of results:
================================= test session starts =================================
platform linux -- Python 3.4.2, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
rootdir: /media/maxtor/media/Python/Lazydog, inifile:
plugins: cov-2.5.1
collected 16 items
lazydog/test/test_events.py ................ [100%]
============================== 16 passed in 0.51 seconds ==============================
You can also test the whole package (assuming you are in the developpement directory):
$ pytest
Test coverage¶
Check the test coverage:
$ py.test --cov lazydog
Test coverage is > 90%. The metric is not very relevant about the test quality, but at least you will be reasssured there are some tests ;)
========================== test session starts ===========================
platform linux -- Python 3.4.2, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
rootdir: /media/maxtor/media/Python/Lazydog, inifile:
plugins: cov-2.5.1
collected 58 items
lazydog/test/test_events.py ................ [ 27%]
lazydog/test/test_handlers.py ...................... [ 65%]
lazydog/test/test_queues.py .. [ 68%]
lazydog/test/test_states.py .................. [100%]
----------- coverage: platform linux, python 3.4.2-final-0 -----------
Name Stmts Miss Cover
--------------------------------------------------------------------------
lazydog/__init__.py 0 0 100%
lazydog/dropbox_content_hasher.py 66 14 79%
lazydog/events.py 249 7 97%
lazydog/handlers.py 214 29 86%
lazydog/lazydog.py 39 39 0%
lazydog/queues.py 18 0 100%
lazydog/revised_watchdog/__init__.py 0 0 100%
lazydog/revised_watchdog/events.py 31 1 97%
lazydog/revised_watchdog/observers/__init__.py 0 0 100%
lazydog/revised_watchdog/observers/inotify.py 49 6 88%
lazydog/revised_watchdog/observers/inotify_buffer.py 12 0 100%
lazydog/revised_watchdog/observers/inotify_c.py 72 22 69%
lazydog/states.py 109 1 99%
lazydog/test/test_events.py 261 2 99%
lazydog/test/test_handlers.py 355 3 99%
lazydog/test/test_queues.py 31 0 100%
lazydog/test/test_states.py 172 0 100%
--------------------------------------------------------------------------
TOTAL 1678 124 93%
====================== 58 passed in 30.15 seconds ========================
Documentation¶
Full code documentation¶
Please find full code documentation in an HTML format on ReadTheDocs.org: http://lazydog.readthedocs.io/
This documentation is automatically updated each time an update is made no GitHub.
Maintaining documentation up-to-date¶
Please document each change. If you want to check the result before publishing, you can run the following after each documentation modification:
$ cd docs # first go in the /docs subdirectory.
$ make html # recompute the sphinx documentation
The resulted documentation is then in the local relative folder
/docs/_build/html/index.html
.
Note that if you did not modify local file from /docs
subdirectory,
the changes will not be taken… you can use the following command to
force recomputing all the changes:
$ touch autodoc.rst; make html
Last thing. If you modified the main README.md
, and you want the
changes to appear in the documentation (and not only on github), you
have to convert the .md file to a .rst one. You can use the pandoc app
to do thiss conversion, using the following command (after installing
Pandoc, please refer to Pandoc
documentation for more
information):
pandoc --from=markdown --to=rst --output=README.rst ../README.md # Assuming you are in the /docs subdirectory.
Then don’t forget to run the previous command again to recompute the whole documentation.
Contributing¶
For lazydog to be a truly great project, third-party code contributions are important. If you want to enhance lazydog, spot bugs or fix them, or just ask for new enhancements, you are so much welcome! Below is a list of things that might help you in contributing to lazydog.
Check the current issues¶
The list of the current bugs, issues, new enhancement proposals, etc. are all grouped on GitHub Issues’ tab:
For more information about GitHub, please check the followings:
Getting Started¶
To get involved in code enhancement:
- Make sure you have a GitHub account
- Get the latest version, by either way cloning of forking this repository (depending on what you want to do)
- Install the requirements via pip:
pip install -r requirements.txt
- Submit an issue directly on GitHub:
- For bugs, clearly describe the issue including steps to reproduce
- For enhancement proposals, be sure to indicate if you’re willing to work on implementing the enhancement
If you do not have GitHub account and you just want to notify for a new bug, please report me by e-mail.
Making Changes¶
lazydog
does not use any git Workflow until now. This will remains until the volume of changes and contribution needs a clearer workflow.- Make commits of logical units.
- Check for unnecessary whitespace with
git diff --check
before committing. - Make sure you have added the necessary tests for your changes.
- Run
python setup.py test
to make sure your tests pass - Run
coverage run --source=lazydog setup.py test
if you have thecoverage
package installed to generate coverage data - Check your coverage by running
coverage report
- Please correctly document the code you wrote, and ensure it is readable once HTML generated
- Update main documentation files (README.md, etc.) when necessary.
Submitting Changes¶
- Push your changes to the feature branch in your fork of the repository.
- Submit a pull request to the main repository
Versioning and release notes¶
We use SemVer for versioning. Please read RELEASE-NOTES.md for details about each releases.
License¶
This project is licensed under the Apache License Version 2.0. Please see the LICENSE.md file for details.
Special thanks¶
Thanks to Jeff Knupp for this general guidelines for open sourcing a python project (which helped me a lot since it is my first open source project I deliver):