{"action":"created","issue":{"url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/881","labels_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/881/labels{/name}","comments_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/881/comments","events_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/881/events","html_url":"https://github.com/mitmproxy/mitmproxy/pull/881","id":126199222,"number":881,"title":"Fix #846","user":{"login":"MatthewShao","id":9366279,"avatar_url":"https://avatars.githubusercontent.com/u/9366279?v=3","gravatar_id":"","url":"https://api.github.com/users/MatthewShao","html_url":"https://github.com/MatthewShao","followers_url":"https://api.github.com/users/MatthewShao/followers","following_url":"https://api.github.com/users/MatthewShao/following{/other_user}","gists_url":"https://api.github.com/users/MatthewShao/gists{/gist_id}","starred_url":"https://api.github.com/users/MatthewShao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MatthewShao/subscriptions","organizations_url":"https://api.github.com/users/MatthewShao/orgs","repos_url":"https://api.github.com/users/MatthewShao/repos","events_url":"https://api.github.com/users/MatthewShao/events{/privacy}","received_events_url":"https://api.github.com/users/MatthewShao/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2016-01-12T15:05:46Z","updated_at":"2016-01-13T00:52:23Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/mitmproxy/mitmproxy/pulls/881","html_url":"https://github.com/mitmproxy/mitmproxy/pull/881","diff_url":"https://github.com/mitmproxy/mitmproxy/pull/881.diff","patch_url":"https://github.com/mitmproxy/mitmproxy/pull/881.patch"},"body":"Finally the script reloader works on both Linux and OS X!:tada:\r\n1. I found that the reloader will crash if we load two scripts in same directory. Because we simply use `PatternMatchingEventHandler` to watch the all `*.py` file, when, say, two observer were set in the same, even the modification on the second script will hit the first observer. Then, the first observer will callback to reload the first script. So I pass the `filename` to `_ScriptModificationHandler` to make sure the modification will hit the corresponding observer.\r\n2. The `Observer()` is kind of tricky. \r\n+ On OS X, `event.src_path` will only prints the path to the folder containing the file, not the path to the file itself. So I added some code to find out the script's real path. See: [Watchdog library in Python on OS X — not showing full event path](http://stackoverflow.com/questions/17537291/watchdog-library-in-python-on-os-x-not-showing-full-event-path)\r\n+ For some reasons, multiple observers seem not work on OS X, typically will throw an exception when we stop them. So it need to be changed to `watchdog.observers.polling.PollingObserver()`, which will work on any platform.\r\n+ On Linux, however, the `PollingObserver()` behave a little bit different than `Observer()`, it recognize all `modify` events as `creat` events. Therefore a `on_created` method need to be added to the `_ScriptModificationHandler`.\r\n\r\nAlready tested this on my Ubuntu 14.04 as well as OS X 10.10."},"comment":{"url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/comments/171114437","html_url":"https://github.com/mitmproxy/mitmproxy/pull/881#issuecomment-171114437","issue_url":"https://api.github.com/repos/mitmproxy/mitmproxy/issues/881","id":171114437,"user":{"login":"MatthewShao","id":9366279,"avatar_url":"https://avatars.githubusercontent.com/u/9366279?v=3","gravatar_id":"","url":"https://api.github.com/users/MatthewShao","html_url":"https://github.com/MatthewShao","followers_url":"https://api.github.com/users/MatthewShao/followers","following_url":"https://api.github.com/users/MatthewShao/following{/other_user}","gists_url":"https://api.github.com/users/MatthewShao/gists{/gist_id}","starred_url":"https://api.github.com/users/MatthewShao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MatthewShao/subscriptions","organizations_url":"https://api.github.com/users/MatthewShao/orgs","repos_url":"https://api.github.com/users/MatthewShao/repos","events_url":"https://api.github.com/users/MatthewShao/events{/privacy}","received_events_url":"https://api.github.com/users/MatthewShao/received_events","type":"User","site_admin":false},"created_at":"2016-01-13T00:52:23Z","updated_at":"2016-01-13T00:52:23Z","body":"> This is fixed by using the PollingObserver, right?\r\n\r\nYes! PollingObserver works fine on OS X! I also have considered to only use PollingObsever on OS X, which need to judge the system first, but I haven't done this before, any suggestion? If we use native observer on Linux, we don't need to consider `on_created` case any more.\r\n\r\n> the problem is, as you say, the double-reloads.\r\n\r\nI use `os.path.basename()` to extract the filename and use `fnmatch.fnmatsh` to judge if it is the script file correspond  to the observer. For the time being, most of scripts were written in single `.py` file, and I think most of users will store them in same directory, just like the `mitmproxy/examples` directory. So if any modification on `*.py` in the same directory will hit the observer, it will be unreasonable.\r\nIf we want to detect the changes in imported modules, I can't find any way other than parse the script file and add a observer to the imported modules. But it sounds tricky, right?\r\n"}}