tools: Add tools/shim
//tools is a bit of a mess of various naming schemes:
foo_bar
foo-bar
foo_bar.py
foo-bar.py
foobar
Even just considering the Python scripts. Everything that doesn't end
with .py doesn't get formatted aromatically (which is one problem)
but worse they can't easily share code - which leads to a lot of
duplication.
It would be better if they could live in //python/tools and get those
advantages but some people are used to the naming of the existing
scripts.
The idea is for a tool named /tools/foo-bar you:
- mv it to //python/tools/foo_bar.py
- symlink //tools/foo-bar to //tools/shim
//tools/foo-bar then continues to work as an alias for
//python/tools/foo_bar.py but you get the advantage of formatting
& code sharing.
Change-Id: If7ec4fddb0a613f02ddec1ad59ecddf880e4b428
diff --git a/tools/check_imports b/python/tools/check_imports.py
similarity index 81%
rename from tools/check_imports
rename to python/tools/check_imports.py
index 3233e47..756d99c 100755
--- a/tools/check_imports
+++ b/python/tools/check_imports.py
@@ -12,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
"""
Enforce import rules for https://ui.perfetto.dev.
Directory structure encodes ideas about the expected dependency graph
@@ -34,11 +33,13 @@
import collections
import argparse
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ROOT_DIR = os.path.dirname(
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
UI_SRC_DIR = os.path.join(ROOT_DIR, 'ui', 'src')
class Failure(object):
+
def __init__(self, path, rule):
self.path = path
self.rule = rule
@@ -46,16 +47,17 @@
def __str__(self):
nice_path = ["ui/src" + name + ".ts" for name in self.path]
return ''.join([
- 'Forbidden dependency path:\n\n ',
- '\n -> '.join(nice_path),
- '\n',
- '\n',
- str(self.rule),
- '\n',
+ 'Forbidden dependency path:\n\n ',
+ '\n -> '.join(nice_path),
+ '\n',
+ '\n',
+ str(self.rule),
+ '\n',
])
class NoDirectDep(object):
+
def __init__(self, src, dst, reasoning):
self.src = src
self.dst = dst
@@ -73,6 +75,7 @@
class NoDep(object):
+
def __init__(self, src, dst, reasoning):
self.src = src
self.dst = dst
@@ -94,38 +97,38 @@
# files matching regex 'b' - but they may indirectly depend on them.
# NoDep(a, b) = as above but 'a' may not even transitively import 'b'.
RULES = [
- NoDirectDep(
- r'/plugins/.*',
- r'/core/.*',
- 'instead plugins should depend on the API exposed at ui/src/api.',
- ),
- NoDirectDep(
- r'/tracks/.*',
- r'/core/.*',
- 'instead tracks should depend on the API exposed at ui/src/api.',
- ),
- NoDep(
- r'/core/.*',
- r'/plugins/.*',
- 'otherwise the plugins are no longer optional.',
- ),
- # Fails at the moment due to:
- # ui/src/base/comparison_utils.ts
- # -> ui/src/common/query_result.ts
- # -> ui/src/core/static_initializers.ts
- #NoDep(
- # r'/base/.*',
- # r'/core/.*',
- # 'core should depend on base not the other way round',
- #),
+ NoDirectDep(
+ r'/plugins/.*',
+ r'/core/.*',
+ 'instead plugins should depend on the API exposed at ui/src/api.',
+ ),
+ NoDirectDep(
+ r'/tracks/.*',
+ r'/core/.*',
+ 'instead tracks should depend on the API exposed at ui/src/api.',
+ ),
+ NoDep(
+ r'/core/.*',
+ r'/plugins/.*',
+ 'otherwise the plugins are no longer optional.',
+ ),
+ # Fails at the moment due to:
+ # ui/src/base/comparison_utils.ts
+ # -> ui/src/common/query_result.ts
+ # -> ui/src/core/static_initializers.ts
+ #NoDep(
+ # r'/base/.*',
+ # r'/core/.*',
+ # 'core should depend on base not the other way round',
+ #),
]
def all_source_files():
for root, dirs, files in os.walk(UI_SRC_DIR, followlinks=False):
- for name in files:
- if name.endswith('.ts') and not name.endswith('.d.ts'):
- yield os.path.join(root, name)
+ for name in files:
+ if name.endswith('.ts') and not name.endswith('.d.ts'):
+ yield os.path.join(root, name)
def is_dir(path, cache={}):
@@ -162,7 +165,6 @@
return not path.startswith('/')
-
def bfs(graph, src):
seen = set()
queue = [(src, [])]
@@ -210,6 +212,7 @@
def do_dot(options, graph):
+
def simplify(path):
if is_external_dep(path):
return path
@@ -244,13 +247,17 @@
parser.set_defaults(func=do_check)
subparsers = parser.add_subparsers()
- check_command = subparsers.add_parser('check', help='Check the rules (default)')
+ check_command = subparsers.add_parser(
+ 'check', help='Check the rules (default)')
check_command.set_defaults(func=do_check)
desc_command = subparsers.add_parser('desc', help='Print the rules')
desc_command.set_defaults(func=do_desc)
- dot_command = subparsers.add_parser('dot', help='Output dependency graph in dot format suitble for use in graphviz (e.g. ./tools/check_imports dot | dot -Tpng -ograph.png)')
+ dot_command = subparsers.add_parser(
+ 'dot',
+ help='Output dependency graph in dot format suitble for use in graphviz (e.g. ./tools/check_imports dot | dot -Tpng -ograph.png)'
+ )
dot_command.set_defaults(func=do_dot)
dot_command.add_argument(
'--simplify',
@@ -275,4 +282,3 @@
if __name__ == '__main__':
sys.exit(main())
-
diff --git a/tools/check_imports b/tools/check_imports
new file mode 120000
index 0000000..478ff5c
--- /dev/null
+++ b/tools/check_imports
@@ -0,0 +1 @@
+shim
\ No newline at end of file
diff --git a/tools/shim b/tools/shim
new file mode 100755
index 0000000..fff429e
--- /dev/null
+++ b/tools/shim
@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+# The idea is for a tool named /tools/foo-bar you mv it to
+# /python/tools/foo_bar.py then softlink /tools/shim to /tools/foo-bar.
+# /tools/foo-bar then continues to work as an alias for
+# /python/tools/foo_bar.py but you get the advantage of formatting
+# & code sharing.
+import os
+import sys
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+NAME = os.path.basename(sys.argv[0]).replace('-', '_')
+NAME = NAME if NAME.endswith('.py') else NAME + '.py'
+PATH = os.path.join(ROOT_DIR, 'python', 'tools', NAME)
+assert os.path.isfile(PATH), f'Shim target {PATH} does not exist.'
+os.execv(PATH, sys.argv)