From 26b3924f156f80268e84edc42a0a6ecd3975f336 Mon Sep 17 00:00:00 2001 From: BigTreei <970633424@qq.com> Date: Tue, 7 Jul 2020 11:11:28 +0800 Subject: [PATCH 01/10] update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 9b88081..2010788 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,5 +2,5 @@ ## Telegram * get `token` from `@BotFather` by sending `/newbot` -* send `/start` to your chatbot to start charting. +* send `/start` to your chatbot to start chatting. * Get `chat_id` from `@myidbot` by sending `/getid` From 43948444738b7e2bea329ca6e8cd138d87bfa4a7 Mon Sep 17 00:00:00 2001 From: Young Date: Tue, 7 Jul 2020 12:37:56 +0000 Subject: [PATCH 02/10] add debug mode --- README.md | 27 +++++++++++++++++++++++++++ wan/__init__.py | 48 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a3d52b0..5c6636e 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,30 @@ This package is under development. We will release it soon in the future. # Installation [fzf](https://github.com/junegunn/fzf) is required + +## config + +Please config your [notifiers](https://github.com/liiight/notifiers). +`wan` will read the setting in ` ~/.dotfiles/.notifers.yaml` as the arguments for notifiers. + +Here is a config example of telegram +```yaml +provider: telegram +kwargs: + chat_id: + token: +``` + +Other configs: +```yaml +log_level: DEBUG # the default level is INFO +``` + + +# Usage + +## Use in python code +```python + +from wan import ntf; ntf('Finished') +``` diff --git a/wan/__init__.py b/wan/__init__.py index 90b82a1..4223e44 100644 --- a/wan/__init__.py +++ b/wan/__init__.py @@ -7,6 +7,7 @@ from .utils import get_pid_via_fzf import psutil import time +import sys class Notifier: @@ -34,39 +35,54 @@ def __init__(self, config_path: str = '~/.dotfiles/.notifers.yaml'): else: with path.open() as f: self.config = yaml.load(f, Loader=yaml.FullLoader) + logger.remove() + log_level = self.config.get('log_level', 'INFO') + logger.add(sys.stderr, level=log_level) + logger.debug(f"log level: {log_level}") self._provider = get_notifier(self.config['provider']) kwargs = self.config['kwargs'] self._ntf = partial(self._provider.notify, **kwargs) def ntf(self, message): + logger.debug("Sending message: {}".format(message)) self._ntf(message=message) - def wait(self, pid=None, message=None, idle=False, patience=20): + @staticmethod + def _get_process_info(pid): + process_info = ":" + try: + p = psutil.Process(pid) + except psutil.NoSuchProcess: + process_info = "" + else: + process_info = ":" + ' '.join(p.cmdline()) + return process_info + + def wait(self, pid=None, message=None, idle=False, patience=20, sleep=3): """wait. - wati the proces to stop or idle Parameters ---------- pid : pid + message : + message idle : will it notify me if the process become idle + patience : + How many idle status is ignored before reguard the process as stopped + sleep : + sleep """ logger.debug(f"Idle: {idle}") - process_info = ":" if pid is None: pid = get_pid_via_fzf() if pid is None: logger.info('No process selected') return - try: - p = psutil.Process(pid) - except psutil.NoSuchProcess: - process_info = "" - else: - process_info = ":" + ' '.join(p.cmdline()) + process_info = self._get_process_info(pid) logger.info(f'Process[{pid}{process_info}] selected') @@ -75,24 +91,30 @@ def wait(self, pid=None, message=None, idle=False, patience=20): try: p = psutil.Process(pid) except psutil.NoSuchProcess: - logger.debug(f'The process[PID] has ended') + logger.info(f'The process[PID] has ended') break else: - # TODO: get the information of subprocess + # TODO: get the information of subprocesses p_status = p.status() + logger.debug(f'status: {p_status}, patience: {cp}') if idle and p_status not in {psutil.STATUS_RUNNING, psutil.STATUS_DISK_SLEEP}: cp += 1 if cp > patience: - logger.debug(f'The process is not running, status: {p_status}') + logger.info(f'The process is not running, status: {p_status}') break else: cp = 0 - time.sleep(2) + time.sleep(sleep) if message is None: message = f'The Process[{pid}{process_info}] has stopped or become idle now.' self.ntf(message) +def ntf(message): + # notify with the call stack + Notifier().ntf(message) + + def run(): fire.Fire(Notifier) From ca9d82c74522eff1d06cfdaeb785234d8bd4bf0a Mon Sep 17 00:00:00 2001 From: Young Date: Tue, 7 Jul 2020 13:02:57 +0000 Subject: [PATCH 03/10] RoadMap --- docs/RoadMap.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/RoadMap.md diff --git a/docs/RoadMap.md b/docs/RoadMap.md new file mode 100644 index 0000000..14bd555 --- /dev/null +++ b/docs/RoadMap.md @@ -0,0 +1,21 @@ +# Plan + + + +## Development +- [ ] Start command after another process ends or become idle +- [ ] Draw the workflow. +- [ ] auto find my running process +- [ ] Run and wait the command +- [ ] documents(rst??) +- [ ] travies - CI + + +## Release +- [ ] pip release +- [ ] readthedocs??? + + + +## Promotion +- [ ] stackover flow From 09aa7bb236e954feb8e95e3d086735b6c95827ca Mon Sep 17 00:00:00 2001 From: you-n-g Date: Tue, 7 Jul 2020 21:08:08 +0800 Subject: [PATCH 04/10] Update RoadMap.md --- docs/RoadMap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RoadMap.md b/docs/RoadMap.md index 14bd555..902d939 100644 --- a/docs/RoadMap.md +++ b/docs/RoadMap.md @@ -9,7 +9,7 @@ - [ ] Run and wait the command - [ ] documents(rst??) - [ ] travies - CI - +- [ ] wait until system become idle ## Release - [ ] pip release From 59af544e90146d93b61c918fbd8999f001426a68 Mon Sep 17 00:00:00 2001 From: Gazh Date: Tue, 7 Jul 2020 21:15:24 +0800 Subject: [PATCH 05/10] add Promotion --- docs/RoadMap.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/RoadMap.md b/docs/RoadMap.md index 902d939..be06a29 100644 --- a/docs/RoadMap.md +++ b/docs/RoadMap.md @@ -19,3 +19,4 @@ ## Promotion - [ ] stackover flow +- [ ] zhihu From 8d1c76ab1e3d56156494e46165d59bc8108f542d Mon Sep 17 00:00:00 2001 From: you-n-g Date: Wed, 8 Jul 2020 08:05:53 +0800 Subject: [PATCH 06/10] Update RoadMap.md --- docs/RoadMap.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/RoadMap.md b/docs/RoadMap.md index be06a29..25b8c5e 100644 --- a/docs/RoadMap.md +++ b/docs/RoadMap.md @@ -11,6 +11,9 @@ - [ ] travies - CI - [ ] wait until system become idle +### optional +- [ ] Can we make fzf installed automatically? + ## Release - [ ] pip release - [ ] readthedocs??? From a94cee67a8d0e56fa915f2cda852368d991fda3c Mon Sep 17 00:00:00 2001 From: you-n-g Date: Wed, 8 Jul 2020 08:06:21 +0800 Subject: [PATCH 07/10] Update RoadMap.md --- docs/RoadMap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/RoadMap.md b/docs/RoadMap.md index 25b8c5e..7a5d86a 100644 --- a/docs/RoadMap.md +++ b/docs/RoadMap.md @@ -21,5 +21,5 @@ ## Promotion -- [ ] stackover flow +- [ ] stackoverflow - [ ] zhihu From 3a42c7d4250962311241b92c7f3184e14b29c270 Mon Sep 17 00:00:00 2001 From: Young Date: Wed, 15 Jul 2020 12:17:18 +0000 Subject: [PATCH 08/10] normal update --- README.md | 8 ++++++++ docs/RoadMap.md | 4 ++-- wan/__init__.py | 3 ++- wan/utils.py | 1 - 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5c6636e..6f5bbd3 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,15 @@ log_level: DEBUG # the default level is INFO # Usage ## Use in python code + +* Call the function in python code directly. ```python from wan import ntf; ntf('Finished') ``` + +* Call the function in shell directly +```shell +> sleep 10 ; wan ntf sleep finished +``` + diff --git a/docs/RoadMap.md b/docs/RoadMap.md index 14bd555..049ae04 100644 --- a/docs/RoadMap.md +++ b/docs/RoadMap.md @@ -1,13 +1,13 @@ # Plan - - ## Development - [ ] Start command after another process ends or become idle - [ ] Draw the workflow. - [ ] auto find my running process - [ ] Run and wait the command +- [ ] GIF to demonstrate the usage of WAN - [ ] documents(rst??) +- [ ] Opensource Licence? - [ ] travies - CI diff --git a/wan/__init__.py b/wan/__init__.py index 4223e44..c93d8df 100644 --- a/wan/__init__.py +++ b/wan/__init__.py @@ -43,7 +43,8 @@ def __init__(self, config_path: str = '~/.dotfiles/.notifers.yaml'): kwargs = self.config['kwargs'] self._ntf = partial(self._provider.notify, **kwargs) - def ntf(self, message): + def ntf(self, *messages): + message = " ".join(messages) logger.debug("Sending message: {}".format(message)) self._ntf(message=message) diff --git a/wan/utils.py b/wan/utils.py index 6d4209d..43e4477 100644 --- a/wan/utils.py +++ b/wan/utils.py @@ -14,7 +14,6 @@ def get_pid_from_line(line): def get_pid_via_fzf(exact=True): - # TODO: make it can be selected with full match return get_pid_from_line(iterfzf(iter_ps(), multi=False, exact=exact)) From 0eb6f36f9b473afec4769226a0c1443c842c1060 Mon Sep 17 00:00:00 2001 From: Young Date: Tue, 21 Jul 2020 11:29:43 +0800 Subject: [PATCH 09/10] make errors more friendly --- README.md | 5 ++++- wan/__init__.py | 2 +- wan/utils.py | 8 +++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6f5bbd3..be2a1a7 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,10 @@ This package is under development. We will release it soon in the future. # Installation -[fzf](https://github.com/junegunn/fzf) is required + +```shell +pip install wan # TODO: upload this to pip source +``` ## config diff --git a/wan/__init__.py b/wan/__init__.py index c93d8df..1ddedcf 100644 --- a/wan/__init__.py +++ b/wan/__init__.py @@ -80,7 +80,7 @@ def wait(self, pid=None, message=None, idle=False, patience=20, sleep=3): if pid is None: pid = get_pid_via_fzf() if pid is None: - logger.info('No process selected') + logger.info('No process selected, You can used --pid to specify the process') return process_info = self._get_process_info(pid) diff --git a/wan/utils.py b/wan/utils.py index 43e4477..1c4bc35 100644 --- a/wan/utils.py +++ b/wan/utils.py @@ -1,5 +1,6 @@ import subprocess from iterfzf import iterfzf +from loguru import logger def iter_ps(): @@ -14,7 +15,12 @@ def get_pid_from_line(line): def get_pid_via_fzf(exact=True): - return get_pid_from_line(iterfzf(iter_ps(), multi=False, exact=exact)) + try: + selected_line = iterfzf(iter_ps(), multi=False, exact=exact) + except PermissionError as e: + logger.error(f'Please make {e.filename} executable(e.g `chmod a+x {e.filename}`).') + return None + return get_pid_from_line(selected_line) if __name__ == "__main__": From 78ff2e0b5b88f19963863eadee36a998517bb119 Mon Sep 17 00:00:00 2001 From: Young Date: Tue, 11 Aug 2020 12:52:41 +0000 Subject: [PATCH 10/10] Add proxy based on env and fix iterfzf error --- wan/__init__.py | 25 ++++++++++++++++++++++++- wan/utils.py | 12 ++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/wan/__init__.py b/wan/__init__.py index 1ddedcf..371eed9 100644 --- a/wan/__init__.py +++ b/wan/__init__.py @@ -8,10 +8,11 @@ import psutil import time import sys +import os class Notifier: - def __init__(self, config_path: str = '~/.dotfiles/.notifers.yaml'): + def __init__(self, config_path: str = '~/.dotfiles/.notifiers.yaml'): """__init__. Parameters @@ -25,6 +26,15 @@ def __init__(self, config_path: str = '~/.dotfiles/.notifers.yaml'): chat_id: token: ``` + + If you need proxy for your provider, please use the config below. + The env will be updated when running `ntf` method + [This solution](https://github.com/liiight/notifiers/issues/236) is proposed by notifiers + ``` + env: + HTTP_PROXY: 'http://IP:PORT' + HTTPS_PROXY: 'http://IP:PORT' + ``` """ # TODO: DEBUG mode path = Path(config_path).expanduser() @@ -43,10 +53,23 @@ def __init__(self, config_path: str = '~/.dotfiles/.notifers.yaml'): kwargs = self.config['kwargs'] self._ntf = partial(self._provider.notify, **kwargs) + self.env = self.config.get('env', {}) + def ntf(self, *messages): message = " ".join(messages) logger.debug("Sending message: {}".format(message)) + if len(message) == 0: + logger.warning("Blank message.") + + # set proxy if needed + env_back = os.environ.copy() + os.environ.update(self.env) self._ntf(message=message) + for k, v in self.env.items(): + if k not in env_back: + del os.environ[k] + else: + os.environ[k] = env_back[k] @staticmethod def _get_process_info(pid): diff --git a/wan/utils.py b/wan/utils.py index 1c4bc35..1505526 100644 --- a/wan/utils.py +++ b/wan/utils.py @@ -1,6 +1,8 @@ import subprocess from iterfzf import iterfzf from loguru import logger +import os +import stat def iter_ps(): @@ -16,10 +18,16 @@ def get_pid_from_line(line): def get_pid_via_fzf(exact=True): try: + # FIXME: This is a bug from iterfzf. The fzf may not be executable selected_line = iterfzf(iter_ps(), multi=False, exact=exact) except PermissionError as e: - logger.error(f'Please make {e.filename} executable(e.g `chmod a+x {e.filename}`).') - return None + try: + os.chmod(e.filename, os.stat(e.filename).st_mode | stat.S_IEXEC) + except PermissionError: + logger.error(f'Please make {e.filename} executable(e.g `chmod a+x {e.filename}`).') + return None + else: + selected_line = iterfzf(iter_ps(), multi=False, exact=exact) return get_pid_from_line(selected_line)