|
|
|
|
@@ -0,0 +1,667 @@
|
|
|
|
|
{
|
|
|
|
|
"cells": [
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 1,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"import ast\n",
|
|
|
|
|
"import importlib\n",
|
|
|
|
|
"import sys\n",
|
|
|
|
|
"from pathlib import Path\n",
|
|
|
|
|
"from types import ModuleType\n",
|
|
|
|
|
"from typing import Dict, Iterable, Iterator, Mapping, Set, Tuple\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"from rich import print"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 2,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"from appdaemon.dependency import (\n",
|
|
|
|
|
" Graph,\n",
|
|
|
|
|
" find_all_dependents,\n",
|
|
|
|
|
" get_all_nodes,\n",
|
|
|
|
|
" get_dependency_graph,\n",
|
|
|
|
|
" get_file_deps,\n",
|
|
|
|
|
" get_full_module_name,\n",
|
|
|
|
|
" resolve_relative_import,\n",
|
|
|
|
|
" reverse_graph,\n",
|
|
|
|
|
" topo_sort,\n",
|
|
|
|
|
")\n",
|
|
|
|
|
"from appdaemon.models.internal.file_check import FileCheck"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"source": [
|
|
|
|
|
"## Logging"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 3,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"import logging.config\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"from rich.console import Console\n",
|
|
|
|
|
"from rich.highlighter import NullHighlighter\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"console = Console()\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"logging.config.dictConfig(\n",
|
|
|
|
|
" {\n",
|
|
|
|
|
" 'version': 1,\n",
|
|
|
|
|
" 'disable_existing_loggers': False,\n",
|
|
|
|
|
" 'formatters': {'basic': {'style': '{', 'format': '{message}'}},\n",
|
|
|
|
|
" 'handlers': {\n",
|
|
|
|
|
" 'rich': {\n",
|
|
|
|
|
" '()': 'rich.logging.RichHandler',\n",
|
|
|
|
|
" 'formatter': 'basic',\n",
|
|
|
|
|
" 'console': console,\n",
|
|
|
|
|
" 'highlighter': NullHighlighter(),\n",
|
|
|
|
|
" 'markup': True\n",
|
|
|
|
|
" }\n",
|
|
|
|
|
" },\n",
|
|
|
|
|
" 'root': {'level': 'DEBUG', 'handlers': ['rich']},\n",
|
|
|
|
|
" }\n",
|
|
|
|
|
")\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"logger = logging.getLogger()"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"source": [
|
|
|
|
|
"## App Load Example\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"Example of using importlib to (re)load an app class from a module."
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 4,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"name": "stdout",
|
|
|
|
|
"output_type": "stream",
|
|
|
|
|
"text": [
|
|
|
|
|
"change\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"><</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold\">class</span><span style=\"color: #000000; text-decoration-color: #000000\"> </span><span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.deep_pkg.deep_mod.Deep'</span><span style=\"font-weight: bold\">></span>\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"\u001b[1m<\u001b[0m\u001b[1;95mclass\u001b[0m\u001b[39m \u001b[0m\u001b[32m'my_pkg.my_sub_pkg.deep_pkg.deep_mod.Deep'\u001b[0m\u001b[1m>\u001b[0m\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"# apps_path = '/home/john/conf/apps'\n",
|
|
|
|
|
"# module_name = 'app2'\n",
|
|
|
|
|
"# class_name = 'NormalApp'\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"apps_path = '/home/john/conf/apps/my_repo/src'\n",
|
|
|
|
|
"module_name = 'my_pkg.my_sub_pkg.deep_pkg'\n",
|
|
|
|
|
"class_name = 'Deep'\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"if apps_path not in sys.path:\n",
|
|
|
|
|
" sys.path.insert(0, apps_path)\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"if mod := sys.modules.get(module_name):\n",
|
|
|
|
|
" importlib.reload(mod)\n",
|
|
|
|
|
"else:\n",
|
|
|
|
|
" mod = importlib.import_module(module_name)\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"class_def = getattr(mod, class_name)\n",
|
|
|
|
|
"print(class_def)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 5,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"['my_pkg',\n",
|
|
|
|
|
" 'my_pkg.foo',\n",
|
|
|
|
|
" 'my_pkg.my_sub_pkg',\n",
|
|
|
|
|
" 'my_pkg.my_sub_pkg.bar',\n",
|
|
|
|
|
" 'my_pkg.my_sub_pkg.deep_pkg',\n",
|
|
|
|
|
" 'my_pkg.my_sub_pkg.deep_pkg.deep_mod']"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"execution_count": 5,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "execute_result"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"pkgs = sorted(name for name in sys.modules.keys() if name.startswith('my'))\n",
|
|
|
|
|
"pkgs"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"source": [
|
|
|
|
|
"## File Mapping\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"Mapping each file to the package string it will be imported from, so it can be retrieved from `sys.modules`\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"Flow\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"- List of changed files\n",
|
|
|
|
|
"- Package associated with each file\n",
|
|
|
|
|
"- Packages that each file depends on"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 6,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"app_dir = Path('/home/john/conf/apps')\n",
|
|
|
|
|
"# files_to_modules = paths_to_modules(app_dir)\n",
|
|
|
|
|
"# print(files_to_modules)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"source": [
|
|
|
|
|
"## Dependencies\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"Find which modules each module depends on.\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"```python\n",
|
|
|
|
|
"deps = {\n",
|
|
|
|
|
" 'A': {'B', 'C'},\n",
|
|
|
|
|
" 'B': {'C'},\n",
|
|
|
|
|
" 'C': {'D'},\n",
|
|
|
|
|
" 'D': set()\n",
|
|
|
|
|
"}\n",
|
|
|
|
|
"```\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"`A` depends on `B` and `C`.\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"If `D` needs to get reloaded, what else does too?"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 7,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #00ff00; text-decoration-color: #00ff00; font-style: italic\">True</span>\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"\u001b[3;92mTrue\u001b[0m\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"{'C': {'A', 'B'}, 'D': {'C'}, 'B': {'A'}, 'A': set()}"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"execution_count": 7,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "execute_result"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"deps = {'A': {'B', 'C'}, 'B': {'C'}, 'C': {'D'}, 'D': set()}\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"reversable = deps == reverse_graph(reverse_graph(deps))\n",
|
|
|
|
|
"print(reversable)\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"reverse_graph(deps)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 8,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span>\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'hello'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'pathlib'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'logging.config'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adapi'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'logging'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'globals'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">set</span><span style=\"font-weight: bold\">()</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.foo'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.bar'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.foo'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'pathlib'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adbase'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.bar'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'pathlib'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adbase'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.bar'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.baz'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'pathlib'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adbase'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.deep_pkg.deep_mod'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'pathlib'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adbase'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.deep_pkg'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.foo'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.deep_pkg.deep_mod'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.bar'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'app1.notification'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adapi'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'app1'</span>: <span style=\"color: #800080; text-decoration-color: #800080; font-weight: bold\">set</span><span style=\"font-weight: bold\">()</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'app1.database'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adapi'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'foo'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adapi'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'test'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'app1.notification'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adbase'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'app2'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'app2.database'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon'</span><span style=\"font-weight: bold\">}</span>,\n",
|
|
|
|
|
" <span style=\"color: #008000; text-decoration-color: #008000\">'app2.database'</span>: <span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'appdaemon.adapi'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'app1.subdir.foo'</span><span style=\"font-weight: bold\">}</span>\n",
|
|
|
|
|
"<span style=\"font-weight: bold\">}</span>\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"\u001b[1m{\u001b[0m\n",
|
|
|
|
|
" \u001b[32m'hello'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'pathlib'\u001b[0m, \u001b[32m'logging.config'\u001b[0m, \u001b[32m'appdaemon.adapi'\u001b[0m, \u001b[32m'logging'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'globals'\u001b[0m: \u001b[1;35mset\u001b[0m\u001b[1m(\u001b[0m\u001b[1m)\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'my_pkg'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'my_pkg.foo'\u001b[0m, \u001b[32m'my_pkg.my_sub_pkg.bar'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'my_pkg.foo'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'pathlib'\u001b[0m, \u001b[32m'appdaemon.adbase'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'my_pkg.my_sub_pkg.bar'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'pathlib'\u001b[0m, \u001b[32m'appdaemon.adbase'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'my_pkg.my_sub_pkg'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'my_pkg.my_sub_pkg.bar'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'my_pkg.my_sub_pkg.baz'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'pathlib'\u001b[0m, \u001b[32m'appdaemon.adbase'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'my_pkg.my_sub_pkg.deep_pkg.deep_mod'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'pathlib'\u001b[0m, \u001b[32m'appdaemon.adbase'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'my_pkg.my_sub_pkg.deep_pkg'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'my_pkg.foo'\u001b[0m, \u001b[32m'my_pkg.my_sub_pkg.deep_pkg.deep_mod'\u001b[0m, \u001b[32m'my_pkg.my_sub_pkg.bar'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'app1.notification'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'appdaemon.adapi'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'app1'\u001b[0m: \u001b[1;35mset\u001b[0m\u001b[1m(\u001b[0m\u001b[1m)\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'app1.database'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'appdaemon.adapi'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'foo'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'appdaemon.adapi'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'test'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'app1.notification'\u001b[0m, \u001b[32m'appdaemon.adbase'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'app2'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'app2.database'\u001b[0m, \u001b[32m'appdaemon'\u001b[0m\u001b[1m}\u001b[0m,\n",
|
|
|
|
|
" \u001b[32m'app2.database'\u001b[0m: \u001b[1m{\u001b[0m\u001b[32m'appdaemon.adapi'\u001b[0m, \u001b[32m'app1.subdir.foo'\u001b[0m\u001b[1m}\u001b[0m\n",
|
|
|
|
|
"\u001b[1m}\u001b[0m\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"module_dependencies = get_dependency_graph(app_dir.rglob('*.py'))\n",
|
|
|
|
|
"print(module_dependencies)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 9,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">{</span><span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.deep_pkg.deep_mod'</span>, <span style=\"color: #008000; text-decoration-color: #008000\">'my_pkg.my_sub_pkg.deep_pkg'</span><span style=\"font-weight: bold\">}</span>\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"\u001b[1m{\u001b[0m\u001b[32m'my_pkg.my_sub_pkg.deep_pkg.deep_mod'\u001b[0m, \u001b[32m'my_pkg.my_sub_pkg.deep_pkg'\u001b[0m\u001b[1m}\u001b[0m\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"files = [\n",
|
|
|
|
|
" Path('/home/john/conf/apps/my_repo/src/my_pkg/my_sub_pkg/deep_pkg/__init__.py'),\n",
|
|
|
|
|
" Path('/home/john/conf/apps/my_repo/src/my_pkg/my_sub_pkg/deep_pkg/deep_mod.py'),\n",
|
|
|
|
|
"]\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"changed_pkg = set(get_full_module_name(f) for f in files)\n",
|
|
|
|
|
"reversed_deps = reverse_graph(module_dependencies)\n",
|
|
|
|
|
"dependents = find_all_dependents(changed_pkg, reversed_deps)\n",
|
|
|
|
|
"to_load = changed_pkg | dependents\n",
|
|
|
|
|
"print(to_load)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": 11,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--------------------------------------------------\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"--------------------------------------------------\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">from <span style=\"color: #808000; text-decoration-color: #808000\">...</span>foo import Foo\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"from \u001b[33m...\u001b[0mfoo import Foo\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">my_pkg.foo\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"my_pkg.foo\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--------------------------------------------------\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"--------------------------------------------------\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">from ..bar import Bar\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"from ..bar import Bar\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">my_pkg.my_sub_pkg.bar\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"my_pkg.my_sub_pkg.bar\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--------------------------------------------------\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"--------------------------------------------------\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">from . import deep_mod\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"from . import deep_mod\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">my_pkg.my_sub_pkg.deep_pkg\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"my_pkg.my_sub_pkg.deep_pkg\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--------------------------------------------------\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"--------------------------------------------------\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">from .. import bar\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"from .. import bar\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">my_pkg.my_sub_pkg\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"my_pkg.my_sub_pkg\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">--------------------------------------------------\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"--------------------------------------------------\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">from .deep_mod import Deep\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"from .deep_mod import Deep\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"text/html": [
|
|
|
|
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">my_pkg.my_sub_pkg.deep_pkg.deep_mod\n",
|
|
|
|
|
"</pre>\n"
|
|
|
|
|
],
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"my_pkg.my_sub_pkg.deep_pkg.deep_mod\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"source": [
|
|
|
|
|
"def test_rel_imports(file: Path):\n",
|
|
|
|
|
" with file.open('r') as f:\n",
|
|
|
|
|
" file_content = f.read()\n",
|
|
|
|
|
" \n",
|
|
|
|
|
" lines = file_content.splitlines()\n",
|
|
|
|
|
"\n",
|
|
|
|
|
" tree = ast.parse(file_content, filename=file)\n",
|
|
|
|
|
" for node in ast.walk(tree):\n",
|
|
|
|
|
" if isinstance(node, ast.ImportFrom):\n",
|
|
|
|
|
" abs_module = resolve_relative_import(node, file)\n",
|
|
|
|
|
" print('-' * 50)\n",
|
|
|
|
|
" print(lines[node.lineno-1])\n",
|
|
|
|
|
" print(abs_module)\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"test_rel_imports(files[0])"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"source": [
|
|
|
|
|
"### Partial Dependency Graph\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"This is an example of generating the dependency graph using an iterable of file Paths."
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": null,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"p = Path('/home/john/conf/apps/my_repo/src/my_pkg/my_sub_pkg')\n",
|
|
|
|
|
"files = p.rglob('*.py')\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"dep_graph = {get_full_module_name(f): get_file_deps(f) for f in files} \n",
|
|
|
|
|
"dep_graph"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": null,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"reload_deps = {m: module_dependencies[m] for m in to_load}\n",
|
|
|
|
|
"print(reload_deps)\n",
|
|
|
|
|
"topo_sort(reload_deps)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": null,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"files = [\n",
|
|
|
|
|
" Path('/home/john/conf/apps/my_repo/src/my_pkg/my_sub_pkg/deep_pkg/__init__.py'),\n",
|
|
|
|
|
" Path('/home/john/conf/apps/my_repo/src/my_pkg/my_sub_pkg/deep_pkg/deep_mod.py'),\n",
|
|
|
|
|
"]\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"for f in files:\n",
|
|
|
|
|
" mod_name = get_file_deps(f)\n",
|
|
|
|
|
" print(mod_name)\n",
|
|
|
|
|
" break\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"with f.open(\"r\") as file:\n",
|
|
|
|
|
" file_content = file.read()\n",
|
|
|
|
|
"tree = ast.parse(file_content, filename=f)\n",
|
|
|
|
|
"for node in ast.walk(tree):\n",
|
|
|
|
|
" if isinstance(node, ast.ImportFrom):\n",
|
|
|
|
|
" print(node.level, node.module)\n",
|
|
|
|
|
" if node.level:\n",
|
|
|
|
|
" abs_module = resolve_relative_import(node, f)\n",
|
|
|
|
|
" if not node.module:\n",
|
|
|
|
|
" abs_module += f'.{node.names[0].name}'\n",
|
|
|
|
|
" print(abs_module)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"source": [
|
|
|
|
|
"## File Checking"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": null,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"files = app_dir.rglob('*.py')\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"fc = FileCheck.from_paths(files)\n",
|
|
|
|
|
"print('\\n'.join(f'{f.relative_to(app_dir.parent)}' for f in fc.new))"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": null,
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": []
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"metadata": {
|
|
|
|
|
"kernelspec": {
|
|
|
|
|
"display_name": "appdaemon",
|
|
|
|
|
"language": "python",
|
|
|
|
|
"name": "python3"
|
|
|
|
|
},
|
|
|
|
|
"language_info": {
|
|
|
|
|
"codemirror_mode": {
|
|
|
|
|
"name": "ipython",
|
|
|
|
|
"version": 3
|
|
|
|
|
},
|
|
|
|
|
"file_extension": ".py",
|
|
|
|
|
"mimetype": "text/x-python",
|
|
|
|
|
"name": "python",
|
|
|
|
|
"nbconvert_exporter": "python",
|
|
|
|
|
"pygments_lexer": "ipython3",
|
|
|
|
|
"version": "3.11.8"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"nbformat": 4,
|
|
|
|
|
"nbformat_minor": 2
|
|
|
|
|
}
|