symbex 0.2__tar.gz → 0.2.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: symbex
3
- Version: 0.2
3
+ Version: 0.2.1
4
4
  Summary: Find the Python code for specified symbols
5
5
  Home-page: https://github.com/simonw/symbex
6
6
  Author: Simon Willison
@@ -54,6 +54,14 @@ To search within a specific directory and all of its subdirectories, use the `-d
54
54
  ```bash
55
55
  symbex Database -d ~/projects/datasette
56
56
  ```
57
+ If `symbex` encounters any Python code that it cannot parse, it will print a warning message and continue searching:
58
+ ```
59
+ # Syntax error in path/badcode.py: expected ':' (<unknown>, line 1)
60
+ ```
61
+ Pass `--silent` to suppress these warnings:
62
+ ```bash
63
+ symbex MyClass --silent
64
+ ```
57
65
 
58
66
  ## Example output
59
67
 
@@ -39,6 +39,14 @@ To search within a specific directory and all of its subdirectories, use the `-d
39
39
  ```bash
40
40
  symbex Database -d ~/projects/datasette
41
41
  ```
42
+ If `symbex` encounters any Python code that it cannot parse, it will print a warning message and continue searching:
43
+ ```
44
+ # Syntax error in path/badcode.py: expected ':' (<unknown>, line 1)
45
+ ```
46
+ Pass `--silent` to suppress these warnings:
47
+ ```bash
48
+ symbex MyClass --silent
49
+ ```
42
50
 
43
51
  ## Example output
44
52
 
@@ -1,7 +1,7 @@
1
1
  from setuptools import setup
2
2
  import os
3
3
 
4
- VERSION = "0.2"
4
+ VERSION = "0.2.1"
5
5
 
6
6
 
7
7
  def get_long_description():
@@ -8,7 +8,12 @@ from .lib import code_for_node, find_symbol_nodes
8
8
  @click.version_option()
9
9
  @click.argument("symbols", nargs=-1)
10
10
  @click.option(
11
- "files", "-f", "--file", type=click.File("r"), multiple=True, help="Files to search"
11
+ "files",
12
+ "-f",
13
+ "--file",
14
+ type=click.Path(file_okay=True, dir_okay=False),
15
+ multiple=True,
16
+ help="Files to search",
12
17
  )
13
18
  @click.option(
14
19
  "directories",
@@ -18,7 +23,12 @@ from .lib import code_for_node, find_symbol_nodes
18
23
  multiple=True,
19
24
  help="Directories to search",
20
25
  )
21
- def cli(symbols, files, directories):
26
+ @click.option(
27
+ "--silent",
28
+ is_flag=True,
29
+ help="Silently ignore Python files with parse errors",
30
+ )
31
+ def cli(symbols, files, directories, silent):
22
32
  """
23
33
  Find symbols in Python code and print the code for them.
24
34
 
@@ -40,13 +50,18 @@ def cli(symbols, files, directories):
40
50
  """
41
51
  if not files and not directories:
42
52
  directories = ["."]
43
- files = list(files)
53
+ files = [pathlib.Path(f) for f in files]
44
54
  for directory in directories:
45
55
  files.extend(pathlib.Path(directory).rglob("*.py"))
46
56
  pwd = pathlib.Path(".").resolve()
47
57
  for file in files:
48
58
  code = file.read_text("utf-8") if hasattr(file, "read_text") else file.read()
49
- nodes = find_symbol_nodes(code, symbols)
59
+ try:
60
+ nodes = find_symbol_nodes(code, symbols)
61
+ except SyntaxError as ex:
62
+ if not silent:
63
+ click.secho(f"# Syntax error in {file}: {ex}", err=True, fg="yellow")
64
+ continue
50
65
  for node in nodes:
51
66
  # If file is within pwd, print relative path
52
67
  # else print absolute path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: symbex
3
- Version: 0.2
3
+ Version: 0.2.1
4
4
  Summary: Find the Python code for specified symbols
5
5
  Home-page: https://github.com/simonw/symbex
6
6
  Author: Simon Willison
@@ -54,6 +54,14 @@ To search within a specific directory and all of its subdirectories, use the `-d
54
54
  ```bash
55
55
  symbex Database -d ~/projects/datasette
56
56
  ```
57
+ If `symbex` encounters any Python code that it cannot parse, it will print a warning message and continue searching:
58
+ ```
59
+ # Syntax error in path/badcode.py: expected ':' (<unknown>, line 1)
60
+ ```
61
+ Pass `--silent` to suppress these warnings:
62
+ ```bash
63
+ symbex MyClass --silent
64
+ ```
57
65
 
58
66
  ## Example output
59
67
 
@@ -0,0 +1,68 @@
1
+ import pathlib
2
+ import pytest
3
+ from click.testing import CliRunner
4
+
5
+ from symbex.cli import cli
6
+
7
+
8
+ @pytest.fixture
9
+ def directory_full_of_code(tmpdir):
10
+ for path, content in (
11
+ ("foo.py", "def foo1():\n pass\n\n@decorated\ndef foo2():\n pass\n\n"),
12
+ ("bar.py", "class BarClass:\n pass\n\n"),
13
+ ("nested/baz.py", "def baz():\n pass\n\n"),
14
+ ("nested/error.py", "def baz_error()" + "bug:\n pass\n\n"),
15
+ ):
16
+ p = pathlib.Path(tmpdir / path)
17
+ p.parent.mkdir(parents=True, exist_ok=True)
18
+ p.write_text(content, "utf-8")
19
+ return tmpdir
20
+
21
+
22
+ @pytest.mark.parametrize(
23
+ "args,expected",
24
+ (
25
+ (["foo1", "--silent"], "# File: foo.py Line: 1\ndef foo1():\n pass\n\n"),
26
+ (
27
+ ["foo*", "--silent"],
28
+ "# File: foo.py Line: 1\ndef foo1():\n pass\n\n# File: foo.py Line: 4\n@decorated\ndef foo2():\n pass\n\n",
29
+ ),
30
+ (
31
+ ["BarClass", "--silent"],
32
+ "# File: bar.py Line: 1\nclass BarClass:\n pass\n\n",
33
+ ),
34
+ (
35
+ ["baz", "--silent"],
36
+ "# File: nested/baz.py Line: 1\ndef baz():\n pass\n\n",
37
+ ),
38
+ # The -f option
39
+ (
40
+ ["baz", "-f", "nested/baz.py", "--silent"],
41
+ "# File: nested/baz.py Line: 1\ndef baz():\n pass\n\n",
42
+ ),
43
+ # The -d option
44
+ (
45
+ ["baz", "-d", "nested", "--silent"],
46
+ "# File: nested/baz.py Line: 1\ndef baz():\n pass\n\n",
47
+ ),
48
+ ),
49
+ )
50
+ def test_fixture(directory_full_of_code, args, expected, monkeypatch):
51
+ runner = CliRunner()
52
+ monkeypatch.chdir(directory_full_of_code)
53
+ result = runner.invoke(cli, args, catch_exceptions=False)
54
+ assert result.exit_code == 0
55
+ assert result.stdout == expected
56
+
57
+
58
+ def test_errors(directory_full_of_code, monkeypatch):
59
+ # Test without --silent to see errors
60
+ runner = CliRunner(mix_stderr=False)
61
+ monkeypatch.chdir(directory_full_of_code)
62
+ result = runner.invoke(cli, ["baz"], catch_exceptions=False)
63
+ assert result.exit_code == 0
64
+ assert result.stdout == (
65
+ "# File: nested/baz.py Line: 1\n" "def baz():\n" " pass\n\n"
66
+ )
67
+ # This differs between different Python versions
68
+ assert result.stderr.startswith("# Syntax error in nested/error.py:")
@@ -1,38 +0,0 @@
1
- import pathlib
2
- import pytest
3
- from click.testing import CliRunner
4
-
5
- from symbex.cli import cli
6
-
7
-
8
- @pytest.fixture
9
- def directory_full_of_code(tmpdir):
10
- for path, content in (
11
- ("foo.py", "def foo1():\n pass\n\n@decorated\ndef foo2():\n pass\n\n"),
12
- ("bar.py", "class BarClass:\n pass\n\n"),
13
- ("nested/baz.py", "def baz():\n pass\n\n"),
14
- ):
15
- p = pathlib.Path(tmpdir / path)
16
- p.parent.mkdir(parents=True, exist_ok=True)
17
- p.write_text(content, "utf-8")
18
- return tmpdir
19
-
20
-
21
- @pytest.mark.parametrize(
22
- "args,expected",
23
- (
24
- (["foo1"], "# File: foo.py Line: 1\ndef foo1():\n pass\n\n"),
25
- (
26
- ["foo*"],
27
- "# File: foo.py Line: 1\ndef foo1():\n pass\n\n# File: foo.py Line: 4\n@decorated\ndef foo2():\n pass\n\n",
28
- ),
29
- (["BarClass"], "# File: bar.py Line: 1\nclass BarClass:\n pass\n\n"),
30
- (["baz"], "# File: nested/baz.py Line: 1\ndef baz():\n pass\n\n"),
31
- ),
32
- )
33
- def test_fixture(directory_full_of_code, args, expected, monkeypatch):
34
- runner = CliRunner()
35
- monkeypatch.chdir(directory_full_of_code)
36
- result = runner.invoke(cli, args, catch_exceptions=False)
37
- assert result.exit_code == 0
38
- assert result.stdout == expected
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes