zenysis-py77 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zenysis_py77-0.2.1/LICENSE +21 -0
- zenysis_py77-0.2.1/PKG-INFO +63 -0
- zenysis_py77-0.2.1/README.md +43 -0
- zenysis_py77-0.2.1/pylib/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/base/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/base/environment.py +17 -0
- zenysis_py77-0.2.1/pylib/base/exec_utils.py +263 -0
- zenysis_py77-0.2.1/pylib/base/flags.py +35 -0
- zenysis_py77-0.2.1/pylib/base/term_color.py +129 -0
- zenysis_py77-0.2.1/pylib/config/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/config/r77_init.py +54 -0
- zenysis_py77-0.2.1/pylib/file/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/file/file_utils.py +446 -0
- zenysis_py77-0.2.1/pylib/file/parse_include_list.py +44 -0
- zenysis_py77-0.2.1/pylib/flash/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/flash/build.py +129 -0
- zenysis_py77-0.2.1/pylib/flash/cc_rules.py +174 -0
- zenysis_py77-0.2.1/pylib/flash/clean.py +73 -0
- zenysis_py77-0.2.1/pylib/flash/cmd_handler.py +140 -0
- zenysis_py77-0.2.1/pylib/flash/dep_graph.py +157 -0
- zenysis_py77-0.2.1/pylib/flash/flash.py +152 -0
- zenysis_py77-0.2.1/pylib/flash/gen_makefile.py +228 -0
- zenysis_py77-0.2.1/pylib/flash/js_rules.py +36 -0
- zenysis_py77-0.2.1/pylib/flash/make_rules.py +156 -0
- zenysis_py77-0.2.1/pylib/flash/ng_rules.py +35 -0
- zenysis_py77-0.2.1/pylib/flash/nge2e_rules.py +113 -0
- zenysis_py77-0.2.1/pylib/flash/pkg_rules.py +74 -0
- zenysis_py77-0.2.1/pylib/flash/proto_rules.py +91 -0
- zenysis_py77-0.2.1/pylib/flash/py_rules.py +91 -0
- zenysis_py77-0.2.1/pylib/flash/rules.py +576 -0
- zenysis_py77-0.2.1/pylib/flash/run.py +108 -0
- zenysis_py77-0.2.1/pylib/flash/swig_rules.py +132 -0
- zenysis_py77-0.2.1/pylib/flash/test.py +37 -0
- zenysis_py77-0.2.1/pylib/flash/url_rules_base.py +127 -0
- zenysis_py77-0.2.1/pylib/flash/utils.py +135 -0
- zenysis_py77-0.2.1/pylib/monitor/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/monitor/haproxy/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/monitor/haproxy/conditions.py +48 -0
- zenysis_py77-0.2.1/pylib/monitor/haproxy/haproxy_cluster_monitor_group.py +133 -0
- zenysis_py77-0.2.1/pylib/monitor/haproxy/haproxy_cluster_monitor_group_test.py +59 -0
- zenysis_py77-0.2.1/pylib/monitor/haproxy/haproxy_monitor.py +186 -0
- zenysis_py77-0.2.1/pylib/monitor/haproxy/haproxy_monitor_test.py +48 -0
- zenysis_py77-0.2.1/pylib/monitor/monitor_server.py +91 -0
- zenysis_py77-0.2.1/pylib/mps/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/mps/cluster/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/mps/cluster/cluster.py +591 -0
- zenysis_py77-0.2.1/pylib/mps/cluster/lazy.py +127 -0
- zenysis_py77-0.2.1/pylib/mps/cluster/multiplecmd.py +88 -0
- zenysis_py77-0.2.1/pylib/mps/cluster/packages.py +328 -0
- zenysis_py77-0.2.1/pylib/mps/packager/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/mps/packager/packager.py +95 -0
- zenysis_py77-0.2.1/pylib/mps/packager/packager_util.py +58 -0
- zenysis_py77-0.2.1/pylib/mps/packager/pkg_bin_rules.py +80 -0
- zenysis_py77-0.2.1/pylib/mps/packager/pkg_ctrl.py +33 -0
- zenysis_py77-0.2.1/pylib/mps/packager/pkg_rules.py +96 -0
- zenysis_py77-0.2.1/pylib/mps/packager/pkg_rules_interface.py +19 -0
- zenysis_py77-0.2.1/pylib/mps/packager/pkg_sys_rules.py +105 -0
- zenysis_py77-0.2.1/pylib/mps/packager/pkg_utils.py +27 -0
- zenysis_py77-0.2.1/pylib/mps/packager/shared/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/mps/packager/shared/control_base.py +188 -0
- zenysis_py77-0.2.1/pylib/mps/packager/shared/copy_shared.py +23 -0
- zenysis_py77-0.2.1/pylib/mps/update_packages.py +101 -0
- zenysis_py77-0.2.1/pylib/mps/util/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/mps/util/push_util.py +23 -0
- zenysis_py77-0.2.1/pylib/mps/util/queue_cluster_config_updates.py +83 -0
- zenysis_py77-0.2.1/pylib/net/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/net/mailer.py +48 -0
- zenysis_py77-0.2.1/pylib/net/server.py +262 -0
- zenysis_py77-0.2.1/pylib/net/util.py +153 -0
- zenysis_py77-0.2.1/pylib/net/util_test.py +23 -0
- zenysis_py77-0.2.1/pylib/pager/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/pager/pager.py +254 -0
- zenysis_py77-0.2.1/pylib/playback/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/playback/play.py +69 -0
- zenysis_py77-0.2.1/pylib/playback/record.py +62 -0
- zenysis_py77-0.2.1/pylib/prod/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/prod/cluster/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/prod/cluster/cluster.py +591 -0
- zenysis_py77-0.2.1/pylib/prod/cluster/lazy.py +127 -0
- zenysis_py77-0.2.1/pylib/prod/cluster/multiplecmd.py +88 -0
- zenysis_py77-0.2.1/pylib/prod/cluster/packages.py +328 -0
- zenysis_py77-0.2.1/pylib/prod/packager/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/prod/packager/packager.py +95 -0
- zenysis_py77-0.2.1/pylib/prod/packager/packager_util.py +58 -0
- zenysis_py77-0.2.1/pylib/prod/packager/pkg_bin_rules.py +80 -0
- zenysis_py77-0.2.1/pylib/prod/packager/pkg_ctrl.py +33 -0
- zenysis_py77-0.2.1/pylib/prod/packager/pkg_rules.py +96 -0
- zenysis_py77-0.2.1/pylib/prod/packager/pkg_rules_interface.py +19 -0
- zenysis_py77-0.2.1/pylib/prod/packager/pkg_sys_rules.py +105 -0
- zenysis_py77-0.2.1/pylib/prod/packager/pkg_utils.py +27 -0
- zenysis_py77-0.2.1/pylib/prod/packager/shared/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/prod/packager/shared/control_base.py +188 -0
- zenysis_py77-0.2.1/pylib/prod/packager/shared/copy_shared.py +23 -0
- zenysis_py77-0.2.1/pylib/prod/update_packages.py +101 -0
- zenysis_py77-0.2.1/pylib/prod/util/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/prod/util/push_util.py +23 -0
- zenysis_py77-0.2.1/pylib/prod/util/queue_cluster_config_updates.py +83 -0
- zenysis_py77-0.2.1/pylib/pyinstaller/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/pyinstaller/hooks/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/pyinstaller/hooks/hook-flask.py +1 -0
- zenysis_py77-0.2.1/pylib/pyinstaller/hooks/hook-gunicorn.py +3 -0
- zenysis_py77-0.2.1/pylib/pyinstaller/hooks/hook-pylib.mail.template.py +1 -0
- zenysis_py77-0.2.1/pylib/pyinstaller/hooks/hook-pylib.mail.template.templates.py +9 -0
- zenysis_py77-0.2.1/pylib/pyinstaller/hooks/hook_utils.py +3 -0
- zenysis_py77-0.2.1/pylib/template/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/template/template_manager.py +58 -0
- zenysis_py77-0.2.1/pylib/template/template_manager_test.py +48 -0
- zenysis_py77-0.2.1/pylib/util/__init__.py +1 -0
- zenysis_py77-0.2.1/pylib/util/algorithm.py +78 -0
- zenysis_py77-0.2.1/pylib/util/credentials.py +45 -0
- zenysis_py77-0.2.1/pylib/util/date_time.py +131 -0
- zenysis_py77-0.2.1/pylib/util/date_time_test.py +75 -0
- zenysis_py77-0.2.1/pylib/util/decorators/__init__.py +1 -0
- zenysis_py77-0.2.1/pylib/util/decorators/decorations.py +12 -0
- zenysis_py77-0.2.1/pylib/util/decorators/decorations_test.py +30 -0
- zenysis_py77-0.2.1/pylib/util/decorators/thread.py +36 -0
- zenysis_py77-0.2.1/pylib/util/descriptor.py +25 -0
- zenysis_py77-0.2.1/pylib/util/descriptor_test.py +76 -0
- zenysis_py77-0.2.1/pylib/util/dev.py +16 -0
- zenysis_py77-0.2.1/pylib/util/dictionary.py +83 -0
- zenysis_py77-0.2.1/pylib/util/dictionary_test.py +32 -0
- zenysis_py77-0.2.1/pylib/util/generator.py +15 -0
- zenysis_py77-0.2.1/pylib/util/git_util.py +195 -0
- zenysis_py77-0.2.1/pylib/util/iter_util.py +25 -0
- zenysis_py77-0.2.1/pylib/util/mail/__init__.py +1 -0
- zenysis_py77-0.2.1/pylib/util/mail/mailer.py +129 -0
- zenysis_py77-0.2.1/pylib/util/math/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/util/math/errors.py +25 -0
- zenysis_py77-0.2.1/pylib/util/math/list_ops.py +70 -0
- zenysis_py77-0.2.1/pylib/util/math/list_ops_test.py +50 -0
- zenysis_py77-0.2.1/pylib/util/singleton.py +80 -0
- zenysis_py77-0.2.1/pylib/util/singleton_test.py +104 -0
- zenysis_py77-0.2.1/pylib/util/stop_words.py +673 -0
- zenysis_py77-0.2.1/pylib/util/string_util.py +85 -0
- zenysis_py77-0.2.1/pylib/util/time_decay.py +55 -0
- zenysis_py77-0.2.1/pylib/util/time_decay_test.py +40 -0
- zenysis_py77-0.2.1/pylib/zeus/__init__.py +0 -0
- zenysis_py77-0.2.1/pylib/zeus/cleaner.py +87 -0
- zenysis_py77-0.2.1/pylib/zeus/continuer.py +71 -0
- zenysis_py77-0.2.1/pylib/zeus/exporter.py +146 -0
- zenysis_py77-0.2.1/pylib/zeus/importer.py +132 -0
- zenysis_py77-0.2.1/pylib/zeus/pipeline_cmd_base.py +177 -0
- zenysis_py77-0.2.1/pylib/zeus/pipeline_config.py +213 -0
- zenysis_py77-0.2.1/pylib/zeus/pipeline_utils.py +232 -0
- zenysis_py77-0.2.1/pylib/zeus/publisher.py +115 -0
- zenysis_py77-0.2.1/pylib/zeus/runner.py +516 -0
- zenysis_py77-0.2.1/pylib/zeus/utils/bash/common.sh +69 -0
- zenysis_py77-0.2.1/pylib/zeus/zeus.py +208 -0
- zenysis_py77-0.2.1/setup.cfg +4 -0
- zenysis_py77-0.2.1/setup.py +30 -0
- zenysis_py77-0.2.1/zenysis_py77.egg-info/PKG-INFO +63 -0
- zenysis_py77-0.2.1/zenysis_py77.egg-info/SOURCES.txt +153 -0
- zenysis_py77-0.2.1/zenysis_py77.egg-info/dependency_links.txt +1 -0
- zenysis_py77-0.2.1/zenysis_py77.egg-info/entry_points.txt +2 -0
- zenysis_py77-0.2.1/zenysis_py77.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014 Room 77, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zenysis-py77
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Zenysis-maintained fork of the Room 77 Python Libraries
|
|
5
|
+
Home-page: https://github.com/Zenysis/py77
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Source, https://github.com/Zenysis/py77
|
|
8
|
+
Project-URL: Upstream, https://github.com/room77/py77
|
|
9
|
+
Provides: pylib
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Dynamic: description
|
|
13
|
+
Dynamic: description-content-type
|
|
14
|
+
Dynamic: home-page
|
|
15
|
+
Dynamic: license
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
Dynamic: project-url
|
|
18
|
+
Dynamic: provides
|
|
19
|
+
Dynamic: summary
|
|
20
|
+
|
|
21
|
+
# Room 77 Python Libraries
|
|
22
|
+
This is a collection of Python libraries used at Room 77, Inc.
|
|
23
|
+
|
|
24
|
+
This is a fork maintained by Zenysis, since the original
|
|
25
|
+
[room77/py77](https://github.com/room77/py77) is no longer maintained.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
Install from PyPI:
|
|
29
|
+
|
|
30
|
+
pip install zenysis-py77
|
|
31
|
+
|
|
32
|
+
The package is still imported as `pylib` and installs the `zeus` command.
|
|
33
|
+
|
|
34
|
+
Alternatively, clone the repo and include its path in your PYTHONPATH
|
|
35
|
+
|
|
36
|
+
For example:
|
|
37
|
+
|
|
38
|
+
export PYTHONPATH=${PYTHONPATH}:/home/user/src/pylib
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Many of the pylib libraries can be used immediately without installing dependencies. The stable-requirements has not been cleaned and contains more dependencies than are necessary. The recommended approach is to not install the stable-requirements and attempt to use the library as is. Only install the requirements when they are needed.
|
|
42
|
+
|
|
43
|
+
There is one additional dependency not in PyPi: GraphViz. To install the necessary Python bindings run
|
|
44
|
+
|
|
45
|
+
sudo apt-get install libgv-python
|
|
46
|
+
|
|
47
|
+
Or the equivalent command for your operating system. Depending on your environment, it may be necessary to add the installed module to your Python path either by setting the PYTHONPATH environment variable or by creating symlinks to the installed module and shared library. On Debian, by default, `gv.py` and `_gv.so` are installed to `/usr/share/pyshared`.
|
|
48
|
+
|
|
49
|
+
A `setup.py` file has been provided but is in experimental state. It is not recommended to install this way if you want to use `flash`
|
|
50
|
+
|
|
51
|
+
## Components
|
|
52
|
+
|
|
53
|
+
### Flash
|
|
54
|
+
A declarative build system.
|
|
55
|
+
|
|
56
|
+
### Zeus
|
|
57
|
+
A task runner.
|
|
58
|
+
|
|
59
|
+
### Master Packaging System
|
|
60
|
+
A production deployment system.
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
All code is distributed under the MIT license, unless otherwise noted. See LICENSE for details.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Room 77 Python Libraries
|
|
2
|
+
This is a collection of Python libraries used at Room 77, Inc.
|
|
3
|
+
|
|
4
|
+
This is a fork maintained by Zenysis, since the original
|
|
5
|
+
[room77/py77](https://github.com/room77/py77) is no longer maintained.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
Install from PyPI:
|
|
9
|
+
|
|
10
|
+
pip install zenysis-py77
|
|
11
|
+
|
|
12
|
+
The package is still imported as `pylib` and installs the `zeus` command.
|
|
13
|
+
|
|
14
|
+
Alternatively, clone the repo and include its path in your PYTHONPATH
|
|
15
|
+
|
|
16
|
+
For example:
|
|
17
|
+
|
|
18
|
+
export PYTHONPATH=${PYTHONPATH}:/home/user/src/pylib
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Many of the pylib libraries can be used immediately without installing dependencies. The stable-requirements has not been cleaned and contains more dependencies than are necessary. The recommended approach is to not install the stable-requirements and attempt to use the library as is. Only install the requirements when they are needed.
|
|
22
|
+
|
|
23
|
+
There is one additional dependency not in PyPi: GraphViz. To install the necessary Python bindings run
|
|
24
|
+
|
|
25
|
+
sudo apt-get install libgv-python
|
|
26
|
+
|
|
27
|
+
Or the equivalent command for your operating system. Depending on your environment, it may be necessary to add the installed module to your Python path either by setting the PYTHONPATH environment variable or by creating symlinks to the installed module and shared library. On Debian, by default, `gv.py` and `_gv.so` are installed to `/usr/share/pyshared`.
|
|
28
|
+
|
|
29
|
+
A `setup.py` file has been provided but is in experimental state. It is not recommended to install this way if you want to use `flash`
|
|
30
|
+
|
|
31
|
+
## Components
|
|
32
|
+
|
|
33
|
+
### Flash
|
|
34
|
+
A declarative build system.
|
|
35
|
+
|
|
36
|
+
### Zeus
|
|
37
|
+
A task runner.
|
|
38
|
+
|
|
39
|
+
### Master Packaging System
|
|
40
|
+
A production deployment system.
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
All code is distributed under the MIT license, unless otherwise noted. See LICENSE for details.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
module for managing machine environments
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__copyright__ = '2013, Room 77, Inc.'
|
|
6
|
+
__author__ = 'Kyle Konrad'
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
__PRODUCTION_FILE = '/home/config/prod_machine'
|
|
12
|
+
__STAGING_FILE = '/home/config/staging_machine'
|
|
13
|
+
__TEST_FILE = '/localdisk/home/is_r77_test'
|
|
14
|
+
|
|
15
|
+
IN_PRODUCTION = os.path.exists(__PRODUCTION_FILE)
|
|
16
|
+
IN_STAGING = os.path.exists(__STAGING_FILE)
|
|
17
|
+
IN_TEST = os.path.exists(__TEST_FILE)
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"""Utils file for the different build operations."""
|
|
2
|
+
|
|
3
|
+
__author__ = 'pramodg@room77.com (Pramod Gupta)'
|
|
4
|
+
__copyright__ = 'Copyright 2012 Room77, Inc.'
|
|
5
|
+
|
|
6
|
+
from collections import deque
|
|
7
|
+
from queue import Queue
|
|
8
|
+
import multiprocessing
|
|
9
|
+
import os
|
|
10
|
+
import signal
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
import shlex
|
|
14
|
+
from threading import Thread, Timer
|
|
15
|
+
|
|
16
|
+
from pylib.base.term_color import TermColor
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class KeyboardInterruptError(Exception):
|
|
20
|
+
"""Exception to translate keyboard interrupt in child processes."""
|
|
21
|
+
def __init__(self, value="Keyboard Interrupt."):
|
|
22
|
+
self.value = value
|
|
23
|
+
|
|
24
|
+
def __str__(self):
|
|
25
|
+
return repr(self.value)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class PicklableCallback():
|
|
29
|
+
"""Class to use as a picklable callback(e.g. for pools)."""
|
|
30
|
+
|
|
31
|
+
def __call__(self, args):
|
|
32
|
+
"""The default call method for the class. We want to explicitly handle
|
|
33
|
+
KeyboardInterrupt as otherwise this may lead to invalid child task.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
args: tuple: List of args. We expect args to be as follows:
|
|
37
|
+
arg[0]: The class object.
|
|
38
|
+
arg[1]: Method to be called for the class object.
|
|
39
|
+
arg[2:]: All the arguments to be passed to the method.
|
|
40
|
+
|
|
41
|
+
Return:
|
|
42
|
+
Passes on the value from the called method.
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
handler = getattr(args[0], args[1], None)
|
|
46
|
+
method_args = args[2:]
|
|
47
|
+
res = handler(*method_args)
|
|
48
|
+
sys.stdout.flush()
|
|
49
|
+
return res
|
|
50
|
+
except KeyboardInterrupt:
|
|
51
|
+
raise KeyboardInterruptError()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ExecUtils:
|
|
55
|
+
"""Utility class."""
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def ExecuteParallel(args, pool_size=0, callback=PicklableCallback()):
|
|
59
|
+
"""Executes a list of methods in parallel. Uses the PicklableCallback
|
|
60
|
+
as default callback to run individual handlers with the given set of args.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
callback: callable method: A method that can be pickled and called.
|
|
64
|
+
args: list: List of args to pass to PicklableCallback which in turn calls
|
|
65
|
+
the callback handler.
|
|
66
|
+
pool_size: int: The size of the task pool.
|
|
67
|
+
Return:
|
|
68
|
+
list: Returns a list of results passed on by the callback handler.
|
|
69
|
+
"""
|
|
70
|
+
if not args:
|
|
71
|
+
TermColor.Warning('Nothing to execute.')
|
|
72
|
+
return []
|
|
73
|
+
|
|
74
|
+
if not pool_size:
|
|
75
|
+
pool_size = max(multiprocessing.cpu_count(), 1)
|
|
76
|
+
|
|
77
|
+
# NOTE(stephen): Require use of `fork` for multiprocessing instead of `spawn` since
|
|
78
|
+
# there are issues with the reuse of some libraries (like Flags) when `spawn` is
|
|
79
|
+
# used.
|
|
80
|
+
pool = multiprocessing.get_context('fork').Pool(processes=pool_size)
|
|
81
|
+
try:
|
|
82
|
+
res = pool.map(callback, args)
|
|
83
|
+
pool.terminate()
|
|
84
|
+
sys.stdout.flush()
|
|
85
|
+
return res
|
|
86
|
+
except (KeyboardInterrupt, Exception) as e:
|
|
87
|
+
TermColor.Error('%s: %s' % (type(e), e))
|
|
88
|
+
# pool.close()
|
|
89
|
+
pool.terminate()
|
|
90
|
+
# Pass on the keyboard interrupt.
|
|
91
|
+
if type(e) == KeyboardInterrupt: raise e
|
|
92
|
+
|
|
93
|
+
sys.stdout.flush()
|
|
94
|
+
return []
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def ExecuteParallelGenerator(args, pool_size=0, callback=PicklableCallback()):
|
|
99
|
+
"""Executes a list of methods in parallel. Uses the PicklableCallback
|
|
100
|
+
as default callback to run individual handlers with the given set of args.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
callback: callable method: A method that can be pickled and called.
|
|
104
|
+
args: list: List of args to pass to PicklableCallback which in turn calls
|
|
105
|
+
the callback handler.
|
|
106
|
+
pool_size: int: The size of the task pool.
|
|
107
|
+
Return:
|
|
108
|
+
list: Returns a list of results passed on by the callback handler.
|
|
109
|
+
"""
|
|
110
|
+
if not args:
|
|
111
|
+
TermColor.Warning('Nothing to execute.')
|
|
112
|
+
return []
|
|
113
|
+
|
|
114
|
+
if not pool_size:
|
|
115
|
+
pool_size = max(multiprocessing.cpu_count(), 1)
|
|
116
|
+
|
|
117
|
+
in_queue = Queue()
|
|
118
|
+
for job in args:
|
|
119
|
+
in_queue.put(job)
|
|
120
|
+
out_queue = Queue()
|
|
121
|
+
def worker(in_queue, out_queue):
|
|
122
|
+
while (job := in_queue.get()):
|
|
123
|
+
out_queue.put(callback(job))
|
|
124
|
+
|
|
125
|
+
for _ in range(pool_size):
|
|
126
|
+
Thread(target=worker, args=(in_queue, out_queue)).start()
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
while True:
|
|
130
|
+
res = out_queue.get()
|
|
131
|
+
new_work = yield res
|
|
132
|
+
if new_work is None:
|
|
133
|
+
break
|
|
134
|
+
for job in new_work:
|
|
135
|
+
in_queue.put(job)
|
|
136
|
+
sys.stdout.flush()
|
|
137
|
+
except (KeyboardInterrupt, Exception) as e:
|
|
138
|
+
TermColor.Error('%s: %s' % (type(e), e))
|
|
139
|
+
# Pass on the keyboard interrupt.
|
|
140
|
+
if type(e) == KeyboardInterrupt: raise e
|
|
141
|
+
finally:
|
|
142
|
+
for _ in range(pool_size):
|
|
143
|
+
in_queue.put(None)
|
|
144
|
+
sys.stdout.flush()
|
|
145
|
+
yield None
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def ExecuteSequentiallyGenerator(args, pool_size=0, callback=PicklableCallback()):
|
|
149
|
+
"""Executes a list of methods sequentially. Uses the PicklableCallback
|
|
150
|
+
as default callback to run individual handlers with the given set of args.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
callback: callable method: A method that can be pickled and called.
|
|
154
|
+
args: list: List of args to pass to PicklableCallback which in turn calls
|
|
155
|
+
the callback handler.
|
|
156
|
+
pool_size: int: The size of the task pool.
|
|
157
|
+
Return:
|
|
158
|
+
list: Returns a list of results passed on by the callback handler.
|
|
159
|
+
"""
|
|
160
|
+
if not args:
|
|
161
|
+
TermColor.Warning('Nothing to execute.')
|
|
162
|
+
return []
|
|
163
|
+
|
|
164
|
+
queue = deque(args)
|
|
165
|
+
try:
|
|
166
|
+
while queue:
|
|
167
|
+
job = queue.popleft()
|
|
168
|
+
new_jobs = yield callback(job)
|
|
169
|
+
queue.extend(new_jobs or ())
|
|
170
|
+
yield # wait for the final sentinel
|
|
171
|
+
except (KeyboardInterrupt, Exception) as e:
|
|
172
|
+
TermColor.Error('%s: %s' % (type(e), e))
|
|
173
|
+
# Pass on the keyboard interrupt.
|
|
174
|
+
if type(e) == KeyboardInterrupt: raise e
|
|
175
|
+
finally:
|
|
176
|
+
sys.stdout.flush()
|
|
177
|
+
|
|
178
|
+
@staticmethod
|
|
179
|
+
def RunCmd(cmd, timeout_sec=sys.maxsize, piped_output=True, extra_env=None):
|
|
180
|
+
"""Executes a command.
|
|
181
|
+
Args:
|
|
182
|
+
cmd: string: A string specifying the command to execute.
|
|
183
|
+
timeout: float: Timeout for the command in seconds.
|
|
184
|
+
piped_output: bool: Set to true if the output is to be dumped directly
|
|
185
|
+
to termimal.
|
|
186
|
+
extra_env: dict{string, string}: The extra environment variables to pass to the cmd.
|
|
187
|
+
"""
|
|
188
|
+
TermColor.VInfo(2, 'Executing: %s' % cmd)
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
if extra_env:
|
|
192
|
+
cmd_env = os.environ.copy()
|
|
193
|
+
cmd_env.update(extra_env)
|
|
194
|
+
else:
|
|
195
|
+
cmd_env = os.environ
|
|
196
|
+
|
|
197
|
+
timer = None
|
|
198
|
+
proc = None
|
|
199
|
+
|
|
200
|
+
if piped_output:
|
|
201
|
+
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
|
202
|
+
stderr=subprocess.STDOUT, env=cmd_env)
|
|
203
|
+
else:
|
|
204
|
+
proc = subprocess.Popen(cmd, shell=True, env=cmd_env)
|
|
205
|
+
|
|
206
|
+
# Start timeout.
|
|
207
|
+
timer = Timer(timeout_sec, ExecUtils.__ProcessTimedOut,
|
|
208
|
+
[proc, cmd, timeout_sec])
|
|
209
|
+
timer.start()
|
|
210
|
+
(merged_out, unused) = proc.communicate()
|
|
211
|
+
timer.cancel()
|
|
212
|
+
retcode = proc.poll()
|
|
213
|
+
if not merged_out:
|
|
214
|
+
merged_out = ''
|
|
215
|
+
|
|
216
|
+
if retcode:
|
|
217
|
+
TermColor.Error('%s failed.\nErrorcode: %d' % (cmd, retcode))
|
|
218
|
+
TermColor.Info('%s Output: \n%s' % (cmd, merged_out))
|
|
219
|
+
else:
|
|
220
|
+
TermColor.VInfo(4, '%s Output: \n%s' % (cmd, merged_out))
|
|
221
|
+
return (retcode, merged_out)
|
|
222
|
+
except (KeyboardInterrupt, OSError) as e:
|
|
223
|
+
TermColor.Error('Command: %s failed. Error: %s' % (cmd, e))
|
|
224
|
+
if timer: timer.cancel()
|
|
225
|
+
if proc:
|
|
226
|
+
ExecUtils.__KillSubchildren(proc.pid)
|
|
227
|
+
proc.communicate()
|
|
228
|
+
# Pass on the keyboard interrupt.
|
|
229
|
+
if type(e) == KeyboardInterrupt: raise e
|
|
230
|
+
return (301, '')
|
|
231
|
+
|
|
232
|
+
@staticmethod
|
|
233
|
+
def __ProcessTimedOut(proc, cmd, timeout_sec):
|
|
234
|
+
"""Handles timed out process. Kills the process and all its children.
|
|
235
|
+
Args:
|
|
236
|
+
cmd: string: The cmd that launched the proc.
|
|
237
|
+
proc: subprocess.Popen: The proc created for the command.
|
|
238
|
+
timeout_sec: int: The timeout for the process.
|
|
239
|
+
"""
|
|
240
|
+
TermColor.Error('Command: %s Timed Out (%dsec)!' % (cmd, timeout_sec))
|
|
241
|
+
ExecUtils.__KillSubchildren(proc.pid)
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
def __KillSubchildren(root_pid):
|
|
245
|
+
"""Kills the process and all its subchildren specified by the pid.
|
|
246
|
+
Args:
|
|
247
|
+
root_pid: int: The pid of the process to be killed.
|
|
248
|
+
"""
|
|
249
|
+
# Get all child processes.
|
|
250
|
+
p = subprocess.Popen('ps --no-headers -o pid --ppid %d' % root_pid,
|
|
251
|
+
shell=True, stdout=subprocess.PIPE,
|
|
252
|
+
stderr=subprocess.PIPE)
|
|
253
|
+
(stdout, stderr) = p.communicate()
|
|
254
|
+
pids = [int(p) for p in stdout.split()]
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
os.kill(root_pid, signal.SIGKILL)
|
|
258
|
+
except OSError as e:
|
|
259
|
+
TermColor.Warning('Could not kill %d. Error %s' % (root_pid, e))
|
|
260
|
+
|
|
261
|
+
# Kill all subchildren recursively.
|
|
262
|
+
for pid in pids:
|
|
263
|
+
ExecUtils.__KillSubchildren(pid)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Flags."""
|
|
2
|
+
|
|
3
|
+
__author__ = 'pramodg@room77.com (Pramod Gupta)'
|
|
4
|
+
__copyright__ = 'Copyright 2012 Room77, Inc.'
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
|
|
8
|
+
# HACK(stephen): Force add_subparsers to be backwards compatible since this
|
|
9
|
+
# broke in Python 3.
|
|
10
|
+
def build_parser():
|
|
11
|
+
parser = argparse.ArgumentParser(conflict_handler='resolve',
|
|
12
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
13
|
+
|
|
14
|
+
# Workaround based on: https://stackoverflow.com/a/22994500
|
|
15
|
+
_add_subparsers = parser.add_subparsers
|
|
16
|
+
def add_subparsers(*args, **kwargs):
|
|
17
|
+
subparser = _add_subparsers(dest='', *args, **kwargs)
|
|
18
|
+
subparser.required = True
|
|
19
|
+
return subparser
|
|
20
|
+
parser.add_subparsers = add_subparsers
|
|
21
|
+
return parser
|
|
22
|
+
|
|
23
|
+
class Flags:
|
|
24
|
+
"""Class to manage command line flags."""
|
|
25
|
+
ARGS = argparse.Namespace()
|
|
26
|
+
PARSER = build_parser()
|
|
27
|
+
TESTING = False
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def InitArgs(cls):
|
|
31
|
+
cls.ARGS = cls.PARSER.parse_args()
|
|
32
|
+
|
|
33
|
+
# TODO(pramodg): See if we can replace testing above with an argument.
|
|
34
|
+
# Flags.PARSER.add_argument('-t', '--testing', action='store_true', default=False,
|
|
35
|
+
# help='Testing mode.')
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Terminal Logging implementation."""
|
|
2
|
+
|
|
3
|
+
__author__ = 'pramodg@room77.com (Pramod Gupta)'
|
|
4
|
+
__copyright__ = 'Copyright 2012 Room77, Inc.'
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
import traceback
|
|
9
|
+
|
|
10
|
+
from pylib.base.flags import Flags
|
|
11
|
+
|
|
12
|
+
Flags.PARSER.add_argument('-v', '--verbose', type=int, default=0,
|
|
13
|
+
help='Verbosity level.')
|
|
14
|
+
|
|
15
|
+
class TermColor:
|
|
16
|
+
"""Class for manipulating terminal colors."""
|
|
17
|
+
|
|
18
|
+
CODE = {
|
|
19
|
+
'ENDC': 0, # RESET COLOR
|
|
20
|
+
'BOLD': 1,
|
|
21
|
+
'UNDERLINE': 4,
|
|
22
|
+
'BLINK': 5,
|
|
23
|
+
'INVERT': 7,
|
|
24
|
+
'CONCEALD': 8,
|
|
25
|
+
'STRIKE': 9,
|
|
26
|
+
'GREY30': 90,
|
|
27
|
+
'GREY40': 2,
|
|
28
|
+
'GREY65': 37,
|
|
29
|
+
'GREY70': 97,
|
|
30
|
+
'GREY20_BG': 40,
|
|
31
|
+
'GREY33_BG': 100,
|
|
32
|
+
'GREY80_BG': 47,
|
|
33
|
+
'GREY93_BG': 107,
|
|
34
|
+
'DARK_RED': 31,
|
|
35
|
+
'RED': 91,
|
|
36
|
+
'RED_BG': 41,
|
|
37
|
+
'LIGHT_RED_BG': 101,
|
|
38
|
+
'DARK_YELLOW': 33,
|
|
39
|
+
'YELLOW': 93,
|
|
40
|
+
'YELLOW_BG': 43,
|
|
41
|
+
'LIGHT_YELLOW_BG': 103,
|
|
42
|
+
'DARK_BLUE': 34,
|
|
43
|
+
'BLUE': 94,
|
|
44
|
+
'BLUE_BG': 44,
|
|
45
|
+
'LIGHT_BLUE_BG': 104,
|
|
46
|
+
'DARK_MAGENTA': 35,
|
|
47
|
+
'PURPLE': 95,
|
|
48
|
+
'MAGENTA_BG': 45,
|
|
49
|
+
'LIGHT_PURPLE_BG': 105,
|
|
50
|
+
'DARK_CYAN': 36,
|
|
51
|
+
'AUQA': 96,
|
|
52
|
+
'CYAN_BG': 46,
|
|
53
|
+
'LIGHT_AUQA_BG': 106,
|
|
54
|
+
'DARK_GREEN': 32,
|
|
55
|
+
'GREEN': 92,
|
|
56
|
+
'GREEN_BG': 42,
|
|
57
|
+
'LIGHT_GREEN_BG': 102,
|
|
58
|
+
'BLACK': 30,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
def TermCode(num):
|
|
63
|
+
return '\033[%sm' % num
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def ColorStr(s, color):
|
|
67
|
+
return (TermColor.TermCode(TermColor.CODE[color]) + s +
|
|
68
|
+
TermColor.TermCode(TermColor.CODE['ENDC']))
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def PrintStr(s, color, print_trace=True):
|
|
72
|
+
if print_trace:
|
|
73
|
+
caller = traceback.extract_stack()[-3]
|
|
74
|
+
s = (caller[0] + ':' + str(caller[1]) + ': ' + s)
|
|
75
|
+
|
|
76
|
+
if sys.stdout.isatty():
|
|
77
|
+
s = TermColor.ColorStr(s, color)
|
|
78
|
+
|
|
79
|
+
print(s)
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def Fatal(s):
|
|
83
|
+
TermColor.PrintStr('FATAL: ' + s, 'RED_BG')
|
|
84
|
+
traceback.print_stack()
|
|
85
|
+
exit(1)
|
|
86
|
+
|
|
87
|
+
@staticmethod
|
|
88
|
+
def PrintException(s):
|
|
89
|
+
TermColor.PrintStr('Exception: ' + s, 'DARK_RED')
|
|
90
|
+
traceback.print_exc()
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def Error(s, print_stack=False):
|
|
94
|
+
TermColor.PrintStr('ERROR: ' + s, 'DARK_RED')
|
|
95
|
+
if print_stack: traceback.print_stack()
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def Warning(s):
|
|
99
|
+
TermColor.PrintStr('WARNING: ' + s, 'PURPLE')
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
def Notice(s):
|
|
103
|
+
TermColor.PrintStr(s, 'ENDC')
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def Info(s):
|
|
107
|
+
TermColor.PrintStr(s, 'ENDC', False)
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def VInfo(level, s):
|
|
111
|
+
if level > Flags.ARGS.verbose: return
|
|
112
|
+
TermColor.Info(s)
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def VNotice(level, s):
|
|
116
|
+
if level > Flags.ARGS.verbose: return
|
|
117
|
+
TermColor.Notice(s)
|
|
118
|
+
|
|
119
|
+
@staticmethod
|
|
120
|
+
def Debug(s):
|
|
121
|
+
TermColor.PrintStr('DEBUG: ' + s, 'BLUE')
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def Success(s):
|
|
125
|
+
TermColor.PrintStr('SUCCESS: ' + s, 'GREEN', False)
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def Failure(s):
|
|
129
|
+
TermColor.PrintStr('FAILURE: ' + s, 'RED', False)
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Common init to get the source root for files."""
|
|
2
|
+
|
|
3
|
+
__author__ = 'pramodg@room77.com (Pramod Gupta)'
|
|
4
|
+
__copyright__ = 'Copyright 2012 Room77, Inc.'
|
|
5
|
+
|
|
6
|
+
import inspect
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import traceback
|
|
10
|
+
|
|
11
|
+
# This is needed to build binaries due to a bug in pyinstaller.
|
|
12
|
+
# May be removed in future if the bug is fixed.
|
|
13
|
+
import encodings
|
|
14
|
+
|
|
15
|
+
# directory of the file this module is imported from
|
|
16
|
+
_dir = os.path.dirname(os.path.realpath(os.path.abspath(
|
|
17
|
+
traceback.extract_stack()[-2][0])))
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
## NO NOT PRINT ANYTHING IN THIS FILE. Many files
|
|
21
|
+
## include this file, and printing may mess up
|
|
22
|
+
## file generation and other tasks that reply on output
|
|
23
|
+
##
|
|
24
|
+
|
|
25
|
+
def src_root():
|
|
26
|
+
"""Returns the repository root."""
|
|
27
|
+
d = _dir
|
|
28
|
+
while (d and d != '/' and os.path.isdir(d) and not
|
|
29
|
+
os.path.exists(os.path.join(d, '.git'))):
|
|
30
|
+
d = os.path.dirname(d)
|
|
31
|
+
return d
|
|
32
|
+
|
|
33
|
+
def pylib_parent_dir():
|
|
34
|
+
"""Returns the directory containing pylib."""
|
|
35
|
+
d = _dir
|
|
36
|
+
while (d and d != '/' and os.path.isdir(d) and not
|
|
37
|
+
os.path.exists(os.path.join(d, 'pylib'))):
|
|
38
|
+
d = os.path.dirname(d)
|
|
39
|
+
if d is None or d == '/':
|
|
40
|
+
raise ValueError('r77_init must be imported from a file under pylib')
|
|
41
|
+
return d
|
|
42
|
+
|
|
43
|
+
def e_dir():
|
|
44
|
+
"""Returns the dir with generated code corresponding to this dir"""
|
|
45
|
+
return os.path.join(src_root(), 'e')
|
|
46
|
+
|
|
47
|
+
PY_SRC = pylib_parent_dir()
|
|
48
|
+
E = e_dir()
|
|
49
|
+
# print 'SRC: %s' % SRC
|
|
50
|
+
if PY_SRC not in sys.path:
|
|
51
|
+
sys.path.append(PY_SRC)
|
|
52
|
+
if E not in sys.path:
|
|
53
|
+
sys.path.append(E)
|
|
54
|
+
|
|
File without changes
|