FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

attempt to improve import time by samuelcolvin · Pull Request #50 · samuelcolvin/python-devtools · GitHub

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .cfg  (1) .py  (6) .yml  (2) All 3 file types selected
Only manifest files
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
6 changes: 6 additions & 0 deletions .codecov.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
coverage:
precision: 2
range: [95, 100]

comment:
layout: 'header, diff, flags, files, footer'
10 changes: 6 additions & 4 deletions .github/workflows/ci.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ jobs:
make check-dist

- name: test with extras
run: make test
run: |
make test
coverage xml

- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v1.0.7
with:
file: ./coverage.xml
env_vars: EXTRAS,PYTHON,OS
Expand All @@ -58,10 +60,10 @@ jobs:
make test
coverage xml

- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v1.0.7
with:
file: ./coverage.xml
env_vars: DEPS,PYTHON,OS
env_vars: EXTRAS,PYTHON,OS
env:
EXTRAS: no

Expand Down
22 changes: 9 additions & 13 deletions devtools/ansi.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import re
import sys
from enum import IntEnum
from typing import Any

from .utils import isatty

_ansi_template = '\033[{}m'
_ansi_re = re.compile('\033\\[((?:\\d|;)*)([a-zA-Z])')

__all__ = 'sformat', 'sprint'


def isatty(stream=None):
stream = stream or sys.stdout
try:
return stream.isatty()
except Exception:
return False
MYPY = False
if MYPY:
from typing import Any


def strip_ansi(value):
return _ansi_re.sub('', value)
import re

return re.sub('\033\\[((?:\\d|;)*)([a-zA-Z])', '', value)


class Style(IntEnum):
Expand Down Expand Up @@ -68,7 +64,7 @@ class Style(IntEnum):
# this is a meta value used for the "Style" instance which is the "style" function
function = -1

def __call__(self, input: Any, *styles, reset: bool = True, apply: bool = True):
def __call__(self, input: 'Any', *styles: 'Style', reset: bool = True, apply: bool = True) -> str:
"""
Styles text with ANSI styles and returns the new string.

Expand Down
82 changes: 49 additions & 33 deletions devtools/debug.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import ast
import dis
import inspect
import os
import pdb
import sys
from pathlib import Path
from textwrap import dedent, indent
from types import FrameType
from typing import Generator, List, Optional, Tuple

from .ansi import isatty, sformat
from .ansi import sformat
from .prettier import PrettyFormat, env_true
from .timer import Timer
from .utils import isatty

__all__ = 'Debug', 'debug'
CWD = Path('.').resolve()
MYPY = False
if MYPY:
import ast
from types import FrameType
from typing import Generator, List, Optional, Tuple


pformat = PrettyFormat(
Expand Down Expand Up @@ -78,7 +75,7 @@ class DebugOutput:
arg_class = DebugArgument
__slots__ = 'filename', 'lineno', 'frame', 'arguments', 'warning'

def __init__(self, *, filename: str, lineno: int, frame: str, arguments: List[DebugArgument], warning=None):
def __init__(self, *, filename: str, lineno: int, frame: str, arguments: 'List[DebugArgument]', warning=None):
self.filename = filename
self.lineno = lineno
self.frame = frame
Expand Down Expand Up @@ -110,22 +107,9 @@ def __repr__(self) -> str:

class Debug:
output_class = DebugOutput
complex_nodes = (
ast.Call,
ast.Attribute,
ast.Subscript,
ast.IfExp,
ast.BoolOp,
ast.BinOp,
ast.Compare,
ast.DictComp,
ast.ListComp,
ast.SetComp,
ast.GeneratorExp,
)

def __init__(
self, *, warnings: Optional[bool] = None, highlight: Optional[bool] = None, frame_context_length: int = 50
self, *, warnings: 'Optional[bool]' = None, highlight: 'Optional[bool]' = None, frame_context_length: int = 50
):
self._show_warnings = self._env_bool(warnings, 'PY_DEVTOOLS_WARNINGS', True)
self._highlight = self._env_bool(highlight, 'PY_DEVTOOLS_HIGHLIGHT', None)
Expand All @@ -149,6 +133,8 @@ def format(self, *args, **kwargs) -> DebugOutput:
return self._process(args, kwargs, 'format')

def breakpoint(self):
import pdb

pdb.Pdb(skip=['devtools.*']).set_trace()

def timer(self, name=None, *, verbose=True, file=None, dp=3) -> Timer:
Expand All @@ -160,7 +146,7 @@ def _process(self, args, kwargs, func_name: str) -> DebugOutput:
"""
# HELP: any errors other than ValueError from _getframe? If so please submit an issue
try:
call_frame: FrameType = sys._getframe(2)
call_frame: 'FrameType' = sys._getframe(2)
except ValueError:
# "If [ValueError] is deeper than the call stack, ValueError is raised"
return self.output_class(
Expand All @@ -175,15 +161,20 @@ def _process(self, args, kwargs, func_name: str) -> DebugOutput:
function = call_frame.f_code.co_name
if filename.startswith('/'):
# make the path relative
from pathlib import Path

cwd = Path('.').resolve()
try:
filename = str(Path(filename).relative_to(CWD))
filename = str(Path(filename).relative_to(cwd))
except ValueError:
# happens if filename path is not within CWD
pass

lineno = call_frame.f_lineno
warning = None

import inspect

try:
file_lines, _ = inspect.findsource(call_frame)
except OSError:
Expand Down Expand Up @@ -214,7 +205,23 @@ def _args_inspection_failed(self, args, kwargs):
for name, value in kwargs.items():
yield self.output_class.arg_class(value, name=name)

def _process_args(self, func_ast, code_lines, args, kwargs) -> Generator[DebugArgument, None, None]: # noqa: C901
def _process_args(self, func_ast, code_lines, args, kwargs) -> 'Generator[DebugArgument, None, None]': # noqa: C901
import ast

complex_nodes = (
ast.Call,
ast.Attribute,
ast.Subscript,
ast.IfExp,
ast.BoolOp,
ast.BinOp,
ast.Compare,
ast.DictComp,
ast.ListComp,
ast.SetComp,
ast.GeneratorExp,
)

arg_offsets = list(self._get_offsets(func_ast))
for i, arg in enumerate(args):
try:
Expand All @@ -226,7 +233,7 @@ def _process_args(self, func_ast, code_lines, args, kwargs) -> Generator[DebugAr

if isinstance(ast_node, ast.Name):
yield self.output_class.arg_class(arg, name=ast_node.id)
elif isinstance(ast_node, self.complex_nodes):
elif isinstance(ast_node, complex_nodes):
# TODO replace this hack with astor when it get's round to a new release
start_line, start_col = arg_offsets[i]

Expand All @@ -252,12 +259,14 @@ def _process_args(self, func_ast, code_lines, args, kwargs) -> Generator[DebugAr
yield self.output_class.arg_class(value, name=name, variable=kw_arg_names.get(name))

def _parse_code(
self, filename: str, file_lines: List[str], first_line: int, last_line: int
) -> Tuple[ast.AST, List[str]]:
self, filename: str, file_lines: 'List[str]', first_line: int, last_line: int
) -> 'Tuple[ast.AST, List[str]]':
"""
All we're trying to do here is build an AST of the function call statement. However numerous ugly interfaces,
lack on introspection support and changes between python versions make this extremely hard.
"""
from textwrap import dedent
import ast

def get_code(_last_line: int) -> str:
lines = file_lines[first_line - 1 : _last_line]
Expand Down Expand Up @@ -295,10 +304,12 @@ def get_code(_last_line: int) -> str:
return func_ast, code_lines

@staticmethod # noqa: C901
def _statement_range(call_frame: FrameType, func_name: str) -> Tuple[int, int]: # noqa: C901
def _statement_range(call_frame: 'FrameType', func_name: str) -> 'Tuple[int, int]': # noqa: C901
"""
Try to find the start and end of a frame statement.
"""
import dis

# dis.disassemble(call_frame.f_code, call_frame.f_lasti)
# pprint([i for i in dis.get_instructions(call_frame.f_code)])

Expand Down Expand Up @@ -343,15 +354,20 @@ def _statement_range(call_frame: FrameType, func_name: str) -> Tuple[int, int]:
return first_line, last_line

@staticmethod
def _wrap_parse(code, filename):
def _wrap_parse(code: str, filename: str) -> 'ast.Call':
"""
async wrapper is required to avoid await calls raising a SyntaxError
"""
import ast
from textwrap import indent

code = 'async def wrapper():\n' + indent(code, ' ')
return ast.parse(code, filename=filename).body[0].body[0].value

@staticmethod
def _get_offsets(func_ast):
import ast

for arg in func_ast.args:
start_line, start_col = arg.lineno - 2, arg.col_offset - 1

Expand Down
Loading

Back | FazBrowse Home | New Git URL