Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 26f3eed
Showing
5 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,4 @@ | ||
*.pyc | ||
MANIFEST | ||
build | ||
dist |
This file contains 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,27 @@ | ||
Ever tried to refactor some python code and trying to find out where you're | ||
code is used? | ||
|
||
find . -name \*.py | xargs grep foo.bar | ||
|
||
is kinda nice, but it'll find imports, comments, and whatnot. | ||
|
||
Meet pygrep, it allows you to find all references to your code, | ||
|
||
pygrep foo.bar some/dir other/stuff.py | ||
|
||
That will show you some output like | ||
|
||
file.py(Class.function):lineno foo.bar.full.identifier | ||
|
||
In `file.py`, there's a reference to `foo.bar.full.identifier` in the method | ||
`function` in class `Class`. | ||
|
||
Supported | ||
--------- | ||
At this point, pygrep resolves | ||
|
||
from foo import bar | ||
|
||
and | ||
|
||
from foo import bar as baz |
This file contains 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,78 @@ | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
# You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
|
||
import ast | ||
from collections import deque | ||
from os import walk | ||
import os.path | ||
|
||
|
||
class IdentVisitor(ast.NodeVisitor): | ||
def __init__(self, path, ident): | ||
super(IdentVisitor, self).__init__() | ||
self.path = path | ||
self.ident = ident.split('.') | ||
self.attrs = deque() | ||
self.context = deque() | ||
self.importMap = {} | ||
|
||
def visit_ImportFrom(self, node): | ||
if node.level != 0: | ||
# relative imports not supported | ||
return | ||
mods = tuple(node.module.split('.')) | ||
for l, r in zip(mods, self.ident): | ||
if l != r: | ||
return | ||
subident = self.ident[len(mods):] | ||
for alias in node.names: | ||
for l, r in zip(alias.name.split('.'), subident): | ||
if l != r: | ||
continue | ||
lname = alias.asname is not None and alias.asname or alias.name | ||
self.importMap[lname] = mods + (alias.name, ) | ||
|
||
def context_visit(self, node): | ||
self.context.append((node.name, node.lineno)) | ||
self.generic_visit(node) | ||
self.context.pop() | ||
visit_FunctionDef = visit_ClassDef = context_visit | ||
|
||
def visit_Name(self, node): | ||
ident = tuple(self.attrs) + (node.id,) | ||
self.attrs.clear() | ||
if ident[0] in self.importMap: | ||
ident = self.importMap[ident[0]] + ident[1:] | ||
if len(ident) < len(self.ident): | ||
return | ||
for l, r in zip(ident, self.ident): | ||
if l != r: | ||
return | ||
fd = '' | ||
if self.context: | ||
fd = '(%s)' % '.'.join(map(lambda t: t[0], self.context)) | ||
print '%s%s:%s\t%s' % (self.path, fd, node.lineno, '.'.join(ident)) | ||
def visit_Attribute(self, node): | ||
self.attrs.appendleft(node.attr) | ||
self.generic_visit(node) | ||
|
||
|
||
class handleIdent: | ||
def __init__(self, ident, files_or_dirs): | ||
self.ident = ident | ||
for fd in files_or_dirs: | ||
if os.path.isdir(fd): | ||
for dirpath, dirnames, filenames in walk(fd): | ||
for fn in filenames: | ||
if fn.endswith('.py'): | ||
self.handleFile(os.path.join(dirpath, fn)) | ||
else: | ||
self.handleFile(fd) | ||
def handleFile(self, path): | ||
m = ast.parse(open(path).read(), path) | ||
iv = IdentVisitor(path, self.ident) | ||
iv.visit(m) | ||
|
||
|
This file contains 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,14 @@ | ||
#!/usr/bin/env python | ||
# This Source Code Form is subject to the terms of the Mozilla Public | ||
# License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
# You can obtain one at http://mozilla.org/MPL/2.0/. | ||
|
||
import pygrep | ||
from optparse import OptionParser | ||
|
||
|
||
parser = OptionParser() | ||
(options, args) = parser.parse_args() | ||
ident = args[0] | ||
files_or_dirs = args[1:] | ||
pygrep.handleIdent(ident, files_or_dirs) |
This file contains 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,13 @@ | ||
#!/usr/bin/env python | ||
|
||
from distutils.core import setup | ||
|
||
setup(name='pygrep', | ||
version='0.1', | ||
description='Find python identifiers', | ||
author='Axel Hecht', | ||
author_email='axel@pike.org', | ||
url='http://github.com/Pike/pygrep', | ||
packages=['pygrep'], | ||
scripts=['scripts/pygrep'], | ||
) |