cengal.code_inspection.line_tracer.versions.v_0.line_tracer

  1#!/usr/bin/env python
  2# coding=utf-8
  3
  4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>
  5# 
  6# Licensed under the Apache License, Version 2.0 (the "License");
  7# you may not use this file except in compliance with the License.
  8# You may obtain a copy of the License at
  9# 
 10#     http://www.apache.org/licenses/LICENSE-2.0
 11# 
 12# Unless required by applicable law or agreed to in writing, software
 13# distributed under the License is distributed on an "AS IS" BASIS,
 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15# See the License for the specific language governing permissions and
 16# limitations under the License.
 17
 18from inspect import getouterframes, currentframe
 19from cengal.web_tools.request_cache import RequestCache
 20from typing import Optional
 21from cengal.introspection.inspect import frame
 22import os
 23
 24"""
 25Module Docstring
 26Docstrings: http://www.python.org/dev/peps/pep-0257/
 27"""
 28
 29__author__ = "ButenkoMS <gtalk@butenkoms.space>"
 30__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>"
 31__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ]
 32__license__ = "Apache License, Version 2.0"
 33__version__ = "4.4.1"
 34__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>"
 35__email__ = "gtalk@butenkoms.space"
 36# __status__ = "Prototype"
 37__status__ = "Development"
 38# __status__ = "Production"
 39
 40
 41class LineTracer:
 42    def __init__(self, print_full_file_name=False, trace_allowed=True):
 43        self.print_full_file_name = print_full_file_name
 44        self.trace_allowed = trace_allowed
 45        self._file_cache = RequestCache(999999)
 46        pass
 47
 48    def _get_file_data(self, path):
 49        file_data = self._file_cache.try_to_get_data_for_request(path)
 50        if not file_data:
 51            with open(path) as file:
 52                file_data = file.readlines()
 53                file_data = [line.rstrip('\n') for line in file_data]
 54                self._file_cache.put_new_request(path, file_data)
 55        return file_data
 56
 57    def _get_file_line(self, path, line_num):
 58        line_num -= 1  # make line numbers start from 0 - not from 1
 59        default_answer = None
 60        if line_num < 0:
 61            return default_answer
 62        
 63        file_data = self._get_file_data(path)
 64        max_line = len(file_data) - 1
 65        if line_num > max_line:
 66            return default_answer
 67
 68        return file_data[line_num]
 69    
 70    def _frame_info(self, depth: Optional[int] = 1):
 71        fr = frame(depth + 1)
 72        filename = fr.f_code.co_filename
 73        line_number = fr.f_lineno
 74        function_name = fr.f_code.co_name
 75        lines = str()
 76        index = fr.f_code.co_firstlineno
 77        return fr, filename, line_number, function_name, lines, index
 78
 79    def trace(self, depth: Optional[int] = 1):
 80        if not self.trace_allowed:
 81            result = (None, None, None, None, None)
 82            return result
 83        
 84        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
 85        previous_line_num = line_number - 1
 86        lines = self._get_file_line(filename, previous_line_num)
 87        if not self.print_full_file_name:
 88            filename = os.path.basename(filename)
 89        
 90        result = (filename, function_name, previous_line_num, lines, index)
 91        return result
 92
 93    def trace_self(self, depth: Optional[int] = 1):
 94        if not self.trace_allowed:
 95            result = (None, None, None, None, None)
 96            return result
 97        
 98        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
 99        current_line_num = line_number
100        lines = self._get_file_line(filename, current_line_num)
101        if not self.print_full_file_name:
102            filename = os.path.basename(filename)
103        
104        result = (filename, function_name, current_line_num, lines, index)
105        return result
106
107    def trace_next(self, depth: Optional[int] = 1):
108        if not self.trace_allowed:
109            result = (None, None, None, None, None)
110            return result
111        
112        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
113        next_line_num = line_number + 1
114        lines = self._get_file_line(filename, next_line_num)
115        if not self.print_full_file_name:
116            filename = os.path.basename(filename)
117        
118        result = (filename, function_name, next_line_num, lines, index)
119        return result
120
121    def trace_exact(self, line_num: int, depth: Optional[int] = 1):
122        if not self.trace_allowed:
123            result = (None, None, None, None, None)
124            return result
125        
126        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
127        exact_line_num = line_num
128        lines = self._get_file_line(filename, exact_line_num)
129        if not self.print_full_file_name:
130            filename = os.path.basename(filename)
131        
132        result = (filename, function_name, exact_line_num, lines, index)
133        return result
134
135    def trace_relative(self, line_num_offset: int, depth: Optional[int] = 1):
136        if not self.trace_allowed:
137            result = (None, None, None, None, None)
138            return result
139        
140        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
141        exact_line_num = line_number + line_num_offset
142        lines = self._get_file_line(filename, exact_line_num)
143        if not self.print_full_file_name:
144            filename = os.path.basename(filename)
145        
146        result = (filename, function_name, exact_line_num, lines, index)
147        return result
148
149    def __call__(self, depth: Optional[int] = 1):
150        if not self.trace_allowed:
151            return
152        
153        print(self.trace(depth=depth))
154
155    def n(self, name: str = '', depth: Optional[int] = 1):
156        if not self.trace_allowed:
157            return
158        
159        if name:
160            print(f'<< {name} >>', self.trace(depth=depth))
161        else:
162            print(self.trace(depth=depth))
163
164
165line_tracer = LineTracer()
166line_tracer_full_file_name = LineTracer(print_full_file_name=True)
167
168
169def previous_line_number(depth: Optional[int] = 1) -> int:
170    return line_tracer.trace(depth + 1)[2]
171
172
173def current_line_number(depth: Optional[int] = 1) -> int:
174    return previous_line_number(depth + 1) + 1
175
176
177def next_line_number(depth: Optional[int] = 1) -> int:
178    return previous_line_number(depth + 1) + 2
179
180
181pln = previous_line_number
182cln = current_line_number
183nln = next_line_number
class LineTracer:
 42class LineTracer:
 43    def __init__(self, print_full_file_name=False, trace_allowed=True):
 44        self.print_full_file_name = print_full_file_name
 45        self.trace_allowed = trace_allowed
 46        self._file_cache = RequestCache(999999)
 47        pass
 48
 49    def _get_file_data(self, path):
 50        file_data = self._file_cache.try_to_get_data_for_request(path)
 51        if not file_data:
 52            with open(path) as file:
 53                file_data = file.readlines()
 54                file_data = [line.rstrip('\n') for line in file_data]
 55                self._file_cache.put_new_request(path, file_data)
 56        return file_data
 57
 58    def _get_file_line(self, path, line_num):
 59        line_num -= 1  # make line numbers start from 0 - not from 1
 60        default_answer = None
 61        if line_num < 0:
 62            return default_answer
 63        
 64        file_data = self._get_file_data(path)
 65        max_line = len(file_data) - 1
 66        if line_num > max_line:
 67            return default_answer
 68
 69        return file_data[line_num]
 70    
 71    def _frame_info(self, depth: Optional[int] = 1):
 72        fr = frame(depth + 1)
 73        filename = fr.f_code.co_filename
 74        line_number = fr.f_lineno
 75        function_name = fr.f_code.co_name
 76        lines = str()
 77        index = fr.f_code.co_firstlineno
 78        return fr, filename, line_number, function_name, lines, index
 79
 80    def trace(self, depth: Optional[int] = 1):
 81        if not self.trace_allowed:
 82            result = (None, None, None, None, None)
 83            return result
 84        
 85        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
 86        previous_line_num = line_number - 1
 87        lines = self._get_file_line(filename, previous_line_num)
 88        if not self.print_full_file_name:
 89            filename = os.path.basename(filename)
 90        
 91        result = (filename, function_name, previous_line_num, lines, index)
 92        return result
 93
 94    def trace_self(self, depth: Optional[int] = 1):
 95        if not self.trace_allowed:
 96            result = (None, None, None, None, None)
 97            return result
 98        
 99        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
100        current_line_num = line_number
101        lines = self._get_file_line(filename, current_line_num)
102        if not self.print_full_file_name:
103            filename = os.path.basename(filename)
104        
105        result = (filename, function_name, current_line_num, lines, index)
106        return result
107
108    def trace_next(self, depth: Optional[int] = 1):
109        if not self.trace_allowed:
110            result = (None, None, None, None, None)
111            return result
112        
113        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
114        next_line_num = line_number + 1
115        lines = self._get_file_line(filename, next_line_num)
116        if not self.print_full_file_name:
117            filename = os.path.basename(filename)
118        
119        result = (filename, function_name, next_line_num, lines, index)
120        return result
121
122    def trace_exact(self, line_num: int, depth: Optional[int] = 1):
123        if not self.trace_allowed:
124            result = (None, None, None, None, None)
125            return result
126        
127        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
128        exact_line_num = line_num
129        lines = self._get_file_line(filename, exact_line_num)
130        if not self.print_full_file_name:
131            filename = os.path.basename(filename)
132        
133        result = (filename, function_name, exact_line_num, lines, index)
134        return result
135
136    def trace_relative(self, line_num_offset: int, depth: Optional[int] = 1):
137        if not self.trace_allowed:
138            result = (None, None, None, None, None)
139            return result
140        
141        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
142        exact_line_num = line_number + line_num_offset
143        lines = self._get_file_line(filename, exact_line_num)
144        if not self.print_full_file_name:
145            filename = os.path.basename(filename)
146        
147        result = (filename, function_name, exact_line_num, lines, index)
148        return result
149
150    def __call__(self, depth: Optional[int] = 1):
151        if not self.trace_allowed:
152            return
153        
154        print(self.trace(depth=depth))
155
156    def n(self, name: str = '', depth: Optional[int] = 1):
157        if not self.trace_allowed:
158            return
159        
160        if name:
161            print(f'<< {name} >>', self.trace(depth=depth))
162        else:
163            print(self.trace(depth=depth))
LineTracer(print_full_file_name=False, trace_allowed=True)
43    def __init__(self, print_full_file_name=False, trace_allowed=True):
44        self.print_full_file_name = print_full_file_name
45        self.trace_allowed = trace_allowed
46        self._file_cache = RequestCache(999999)
47        pass
print_full_file_name
trace_allowed
def trace(self, depth: typing.Union[int, NoneType] = 1):
80    def trace(self, depth: Optional[int] = 1):
81        if not self.trace_allowed:
82            result = (None, None, None, None, None)
83            return result
84        
85        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
86        previous_line_num = line_number - 1
87        lines = self._get_file_line(filename, previous_line_num)
88        if not self.print_full_file_name:
89            filename = os.path.basename(filename)
90        
91        result = (filename, function_name, previous_line_num, lines, index)
92        return result
def trace_self(self, depth: typing.Union[int, NoneType] = 1):
 94    def trace_self(self, depth: Optional[int] = 1):
 95        if not self.trace_allowed:
 96            result = (None, None, None, None, None)
 97            return result
 98        
 99        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
100        current_line_num = line_number
101        lines = self._get_file_line(filename, current_line_num)
102        if not self.print_full_file_name:
103            filename = os.path.basename(filename)
104        
105        result = (filename, function_name, current_line_num, lines, index)
106        return result
def trace_next(self, depth: typing.Union[int, NoneType] = 1):
108    def trace_next(self, depth: Optional[int] = 1):
109        if not self.trace_allowed:
110            result = (None, None, None, None, None)
111            return result
112        
113        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
114        next_line_num = line_number + 1
115        lines = self._get_file_line(filename, next_line_num)
116        if not self.print_full_file_name:
117            filename = os.path.basename(filename)
118        
119        result = (filename, function_name, next_line_num, lines, index)
120        return result
def trace_exact(self, line_num: int, depth: typing.Union[int, NoneType] = 1):
122    def trace_exact(self, line_num: int, depth: Optional[int] = 1):
123        if not self.trace_allowed:
124            result = (None, None, None, None, None)
125            return result
126        
127        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
128        exact_line_num = line_num
129        lines = self._get_file_line(filename, exact_line_num)
130        if not self.print_full_file_name:
131            filename = os.path.basename(filename)
132        
133        result = (filename, function_name, exact_line_num, lines, index)
134        return result
def trace_relative(self, line_num_offset: int, depth: typing.Union[int, NoneType] = 1):
136    def trace_relative(self, line_num_offset: int, depth: Optional[int] = 1):
137        if not self.trace_allowed:
138            result = (None, None, None, None, None)
139            return result
140        
141        frame, filename, line_number, function_name, lines, index = self._frame_info(depth + 1)
142        exact_line_num = line_number + line_num_offset
143        lines = self._get_file_line(filename, exact_line_num)
144        if not self.print_full_file_name:
145            filename = os.path.basename(filename)
146        
147        result = (filename, function_name, exact_line_num, lines, index)
148        return result
def n(self, name: str = '', depth: typing.Union[int, NoneType] = 1):
156    def n(self, name: str = '', depth: Optional[int] = 1):
157        if not self.trace_allowed:
158            return
159        
160        if name:
161            print(f'<< {name} >>', self.trace(depth=depth))
162        else:
163            print(self.trace(depth=depth))
line_tracer = <LineTracer object>
line_tracer_full_file_name = <LineTracer object>
def previous_line_number(depth: typing.Union[int, NoneType] = 1) -> int:
170def previous_line_number(depth: Optional[int] = 1) -> int:
171    return line_tracer.trace(depth + 1)[2]
def current_line_number(depth: typing.Union[int, NoneType] = 1) -> int:
174def current_line_number(depth: Optional[int] = 1) -> int:
175    return previous_line_number(depth + 1) + 1
def next_line_number(depth: typing.Union[int, NoneType] = 1) -> int:
178def next_line_number(depth: Optional[int] = 1) -> int:
179    return previous_line_number(depth + 1) + 2
def pln(depth: typing.Union[int, NoneType] = 1) -> int:
170def previous_line_number(depth: Optional[int] = 1) -> int:
171    return line_tracer.trace(depth + 1)[2]
def cln(depth: typing.Union[int, NoneType] = 1) -> int:
174def current_line_number(depth: Optional[int] = 1) -> int:
175    return previous_line_number(depth + 1) + 1
def nln(depth: typing.Union[int, NoneType] = 1) -> int:
178def next_line_number(depth: Optional[int] = 1) -> int:
179    return previous_line_number(depth + 1) + 2