imports-logger 2.0.0__py2.py3-none-any.whl

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.
@@ -0,0 +1,132 @@
1
+ from __future__ import print_function
2
+
3
+ # released under the MIT license https://opensource.org/licenses/MIT
4
+ __VERSION__ = "2.0.0"
5
+
6
+
7
+ def setup_logger(log_vsize=False):
8
+ print("===> installing imports_logger_override")
9
+ import os
10
+ import psutil
11
+
12
+ # import pdb
13
+ # import pprint
14
+ # import logging
15
+ import sys
16
+
17
+ from six.moves import builtins
18
+
19
+ # setup the memory vars
20
+ # the call is different on other versions of psutil.
21
+ # i've seen these 2, hopefully this will work in your case
22
+ _this_process = psutil.Process(os.getpid())
23
+ try:
24
+ _this_process.memory_info()
25
+ _f_memory = _this_process.memory_info
26
+ except:
27
+ _this_process.get_memory_info()
28
+ _f_memory = _this_process.get_memory_info
29
+ GET_MEMORY_R = lambda: _f_memory()[0]
30
+ GET_MEMORY_V = lambda: _f_memory()[1]
31
+
32
+ # set up the dirs
33
+ # we'll lot go `{CWD}/__imports_logger/runs/{VERSION}` in which `VERSION` is 001, 002, etc
34
+ REPORTS_DIR_BASE = os.path.join("__imports_logger", "runs")
35
+ if not os.path.exists(REPORTS_DIR_BASE):
36
+ os.makedirs(REPORTS_DIR_BASE)
37
+ dirs = [
38
+ i
39
+ for i in os.listdir(REPORTS_DIR_BASE)
40
+ if os.path.isdir(os.path.join(REPORTS_DIR_BASE, i))
41
+ ]
42
+ max_dirs = len(dirs)
43
+ REPORTS_DIR_RUN = os.path.join(REPORTS_DIR_BASE, "%03d" % max_dirs)
44
+ print("===- Logging to `%s`" % REPORTS_DIR_RUN)
45
+ os.makedirs(REPORTS_DIR_RUN)
46
+ writer_success = open(os.path.join(REPORTS_DIR_RUN, "imports.txt"), "a")
47
+ writer_error = open(os.path.join(REPORTS_DIR_RUN, "errors.txt"), "a")
48
+
49
+ # we need this still
50
+ # PY3 - __import__(name, globals=None, locals=None, fromlist=(), level=0) -> module
51
+ # PY2 - __import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module
52
+ realimport = builtins.__import__
53
+
54
+ # our override
55
+ def imports_logger_override(name, *args, **kwargs):
56
+ _mem_start = GET_MEMORY_R()
57
+ _mem_startv = GET_MEMORY_V()
58
+ _package_name = name
59
+ if len(args) == 4:
60
+ _package_name = "%s.%s" % (name, str(args[2]).replace(",", "|"))
61
+ # use sys._getframe, because the `inspect` module leaves a circular reference that won't clean up (even with an explicit delete)
62
+ _frame = sys._getframe(1)
63
+ try:
64
+ _caller_file = _frame.f_locals["__file__"]
65
+ except:
66
+ _caller_file = "<>"
67
+ try:
68
+ try:
69
+ _imported = realimport(name, *args, **kwargs)
70
+ except (ImportError, AttributeError) as exc:
71
+ raise ImportError(str(exc))
72
+ _mem_finish = GET_MEMORY_R()
73
+ _mem_growth = _mem_finish - _mem_start
74
+ if log_vsize:
75
+ _mem_finishv = GET_MEMORY_V()
76
+ _mem_growthv = _mem_finishv - _mem_startv
77
+ _line = "import|%s,%s,%s,%s,%s,%s,%s,%s\n" % (
78
+ _package_name,
79
+ _caller_file,
80
+ _mem_growth,
81
+ _mem_start,
82
+ _mem_finish,
83
+ _mem_growthv,
84
+ _mem_startv,
85
+ _mem_finishv,
86
+ )
87
+ else:
88
+ _line = "import|%s,%s,%s,%s,%s\n" % (
89
+ _package_name,
90
+ _caller_file,
91
+ _mem_growth,
92
+ _mem_start,
93
+ _mem_finish,
94
+ )
95
+ writer_success.write(_line)
96
+ return _imported
97
+ except Exception as e:
98
+ _message = e.args[0]
99
+ if isinstance(e, ImportError) and _message.startswith("No module named"):
100
+ # print("ImportError: %s | via <%s> in <%s>" % (e, _package_name, _caller_file))
101
+ _mem_finish = GET_MEMORY_R()
102
+ _mem_growth = _mem_finish - _mem_start
103
+ if log_vsize:
104
+ _mem_finishv = GET_MEMORY_V()
105
+ _mem_growthv = _mem_finishv - _mem_startv
106
+ _line = "import|%s,%s,%s,%s,%s,%s,%s,%s\n" % (
107
+ _package_name,
108
+ _caller_file,
109
+ _mem_growth,
110
+ _mem_start,
111
+ _mem_finish,
112
+ _mem_growthv,
113
+ _mem_startv,
114
+ _mem_finishv,
115
+ )
116
+ else:
117
+ _line = "import|%s,%s,%s,%s,%s\n" % (
118
+ _package_name,
119
+ _caller_file,
120
+ _mem_growth,
121
+ _mem_start,
122
+ _mem_finish,
123
+ )
124
+ writer_error.write(_line)
125
+ raise
126
+ finally:
127
+ del _caller_file
128
+ del _frame
129
+
130
+ # install the override
131
+ builtins.__import__ = imports_logger_override
132
+ print("<=== imports_logger_override installed")
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: imports_logger
3
+ Version: 2.0.0
4
+ Summary: Quick tool to log import statements
5
+ Home-page: https://github.com/jvanasco/imports_logger
6
+ Author: Jonathan Vanasco
7
+ Author-email: jvanasco@2xlp.com
8
+ License: MIT
9
+ Keywords: import,logging,memory
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 2.7
12
+ Classifier: Programming Language :: Python :: 3.5
13
+ Classifier: Programming Language :: Python :: 3.6
14
+ Classifier: Programming Language :: Python :: 3.7
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
23
+ Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE.txt
26
+ Requires-Dist: psutil
27
+ Requires-Dist: six
28
+ Provides-Extra: testing
29
+ Requires-Dist: pytest; extra == "testing"
30
+ Requires-Dist: coverage; extra == "testing"
31
+ Dynamic: license-file
32
+
33
+ ![Python package](https://github.com/jvanasco/imports_logger/workflows/Python%20package/badge.svg)
34
+
35
+ Import Logger
36
+ =============
37
+
38
+ This was a terrible, quickly slapped together, package designed as a quick debugging tool.
39
+
40
+ Over the past few years, it has proved to be incredibly useful.
41
+
42
+ ## what this does
43
+
44
+ This package is used to override calls to `import`, wrapping every import with
45
+ a call to `psutil` which measures memory.
46
+
47
+ The outputs are written to a versioned file as `csv` compatible text files --
48
+ one for "successful" imports, another for "failures"".
49
+
50
+ The output files are written to an `__imports_logged` directory and stored under
51
+ an incremental `__imports_logged/runs` subfolder.
52
+
53
+ This is rough and can be customized. This should NEVER NEVER NEVER be used on
54
+ production code. This is a quick debugging tool.
55
+
56
+ ### DANGER DANGER DANGER
57
+
58
+ DO NOT RUN THIS IN PRODUCTION
59
+
60
+ ### DANGER DANGER DANGER
61
+
62
+ SERIOUSLY, DO NOT RUN THIS IN PRODUCTION
63
+
64
+ Why not? This library saves the loaded information in a versioned format - so
65
+ every time you start/restart your applications, more disk space will be consumed.
66
+
67
+
68
+ ## so why would I use this?
69
+
70
+ There are two main use-cases:
71
+
72
+ 1. The outputs can be processed and analyzed (even imported to Excel!) to
73
+ determine where the biggest imports are, and what causes them.
74
+
75
+ 2. Knowing import errors is useful in two situations: refactoring your own code,
76
+ and finding what libraries are conditionally importing other 3rd party tools.
77
+
78
+ ## requirements
79
+
80
+ * `psutil`
81
+
82
+ ## usage
83
+
84
+ try running the demo.py script
85
+
86
+ it is just...
87
+
88
+ # at the top of your script
89
+ import imports_logger
90
+ imports_logger.setup_logger()
91
+
92
+ # your code here
93
+ import re
94
+
95
+ # this should have created a folder named `__imports_logged/runs/001`
96
+
97
+ the text in runs 001 should look like
98
+
99
+ import|re.None,demo.py,0,12664832,12664832
@@ -0,0 +1,6 @@
1
+ imports_logger/__init__.py,sha256=kDxKvIaUPOLWmrfkJNLhYbwcmtcl3PHJ8vqG0LVsLsg,4899
2
+ imports_logger-2.0.0.dist-info/licenses/LICENSE.txt,sha256=HGwQg0OCAkR5EPZnIxnj4aFfG2Yen_jn6Dami5OiJOc,1083
3
+ imports_logger-2.0.0.dist-info/METADATA,sha256=7277u6Xja1-_GpkVqOfcAJdvoCg12ZTG-goJIke3J28,3054
4
+ imports_logger-2.0.0.dist-info/WHEEL,sha256=Uvlg2aNlEKdilsyFSJt1QX5me0eEbCjQzR3nZeFkvy4,109
5
+ imports_logger-2.0.0.dist-info/top_level.txt,sha256=uwlADt14EuamFFm-BUe5VSxUjal_gOg1WIMSq4MiITw,15
6
+ imports_logger-2.0.0.dist-info/RECORD,,
@@ -0,0 +1,6 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py2-none-any
5
+ Tag: py3-none-any
6
+
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2016 Jonathan Vanasco
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+
@@ -0,0 +1 @@
1
+ imports_logger