Compare commits

...

5 Commits

Author SHA1 Message Date
6d0ac475ba update stereotype 2025-10-21 20:09:51 +08:00
faaa8bb357 add .pbignore function 2025-09-05 12:50:28 +08:00
d209c1abe9 change to pyboot 2025-09-05 11:13:01 +08:00
f0b6a5c6fe update staticmethod to Log 2025-09-04 14:14:49 +08:00
1e07749716 Add .gitignore and remove __pycache__ files from tracking 2025-09-04 14:14:25 +08:00
106 changed files with 2257 additions and 194 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
__pycache__/

View File

@@ -1,5 +1,5 @@
"""
PyApp - A Python application framework
pyboot - A Python application framework
"""
__version__ = "0.1"

View File

@@ -1,11 +1,11 @@
from pyapp.utils.log import Log
from pyboot.utils.log import Log
application_class = {}
def PyApplication(arg=None):
def PybootApplication(arg=None):
if callable(arg):
cls = arg
if "default" in application_class:
Log.error("Multiple classes annotated with default @PyApplication, require a 'name' parameter.", True)
Log.error("Multiple classes annotated with default @PybootApplication, require a 'name' parameter.", True)
application_class["default"] = cls
return cls
@@ -13,9 +13,9 @@ def PyApplication(arg=None):
name = arg
def decorator(cls):
if name is None:
raise Log.error("The 'name' parameter is required when using @PyApplication with arguments.", True)
raise Log.error("The 'name' parameter is required when using @PybootApplication with arguments.", True)
if name in application_class:
raise Log.error(f"Multiple classes annotated with @PyApplication with the same name '{name}' found.", True)
raise Log.error(f"Multiple classes annotated with @PybootApplication with the same name '{name}' found.", True)
application_class[name] = cls
return cls
return decorator

View File

@@ -1,14 +1,14 @@
import os
import sys
from pyapp.application import application_class
from pyapp.stereotype import get_all_component_classes, get_all_component_comments
from pyapp.utils.log import Log
from pyapp.utils.timer import Timer
from pyapp.utils.project import Project
from pyapp.templates.application import template as app_template
from pyapp.templates.config import template as config_template
from pyapp.ui.server.app import app
from pyboot.application import application_class
from pyboot.stereotype import get_all_component_classes, get_all_component_comments
from pyboot.utils.log import Log
from pyboot.utils.timer import Timer
from pyboot.utils.project import Project
from pyboot.templates.application import template as app_template
from pyboot.templates.config import template as config_template
from pyboot.ui.server.app import app
def run():
@@ -17,19 +17,19 @@ def run():
app_name = "default"
if len(application_class) == 0:
Log.error("No class annotated with @PyApplication found.", True)
Log.error("No class annotated with @PybootApplication found.", True)
if len(sys.argv) < 3 and "default" not in application_class:
Log.error("No default @PyApplication found. Please specify the 'name' parameter.", True)
Log.error("No default @PybootApplication found. Please specify the 'name' parameter.", True)
if len(sys.argv) == 3:
app_name = sys.argv[2]
app_cls = application_class.get(app_name)
if app_cls is None:
Log.error(f"No class annotated with @PyApplication found with the name '{app_name}'.", True)
Log.error(f"No class annotated with @PybootApplication found with the name '{app_name}'.", True)
if not hasattr(app_cls, "start"):
Log.error("The class annotated with @PyApplication should have a 'start' method.", True)
Log.error("The class annotated with @PybootApplication should have a 'start' method.", True)
Log.info(f"Application '{app_cls.__name__}' started.")
timer = Timer(f"Application({app_name})")
@@ -42,7 +42,7 @@ def run():
def init():
Log.info("Initializing Pyapp project.")
Log.info("Initializing Pyboot project.")
root_path = os.getcwd()
if len(os.listdir(root_path)) > 0:
Log.error("Current directory is not empty. Please provide an empty directory.")
@@ -52,7 +52,7 @@ def init():
with open(os.path.join(root_path, "config.yaml"), "w") as file:
file.write(config_template)
Log.success("Pyapp project initialized.")
Log.success("Pyboot project initialized.")
Log.info("Now you can create your components and run the application.")
def scan():
@@ -80,16 +80,16 @@ def ui():
port = 5000
if len(sys.argv) == 3:
port = int(sys.argv[2])
Log.success(f"Pyapp UI server started at http://localhost:{port}")
Log.success(f"Pyboot UI server started at http://localhost:{port}")
app.run(port=port, host="0.0.0.0")
def help():
Log.info("Pyapp commands:")
Log.info(" init: Initialize a new Pyapp project in the current directory.")
Log.info(" run [name]: Run the Pyapp application with the specified name. If no name is provided, the default application will be run.")
Log.info(" scan: Scan the project for Pyapp components.")
Log.info(" ui [port]: Start the Pyapp UI server. If no port is provided, the default port 5000 will be used.")
Log.info("Pyboot commands:")
Log.info(" init: Initialize a new Pyboot project in the current directory.")
Log.info(" run [name]: Run the Pyboot application with the specified name. If no name is provided, the default application will be run.")
Log.info(" scan: Scan the project for Pyboot components.")
Log.info(" ui [port]: Start the Pyboot UI server. If no port is provided, the default port 5000 will be used.")
Log.info(" help: Display this help message.")
def main():
@@ -105,6 +105,6 @@ def main():
elif sys.argv[1] == "help":
help()
else:
Log.error("Invalid command: " + sys.argv[1] + ". Use 'pyapp help' for help.")
Log.error("Invalid command: " + sys.argv[1] + ". Use 'pyboot help' for help.")
else:
Log.error("Please provide a command to run the application.")

View File

@@ -1,4 +1,4 @@
from pyapp.utils.log import Log
from pyboot.utils.log import Log
class Component:
TYPE: str

View File

@@ -1,7 +1,7 @@
from pyapp.component import Component
from pyapp.stereotype import *
from pyapp.utils.log import Log
from pyapp.config import ConfigManager
from pyboot.component import Component
from pyboot.stereotype import *
from pyboot.utils.log import Log
from pyboot.config import ConfigManager
class ComponentFactory:
@staticmethod

View File

@@ -2,7 +2,7 @@ import argparse
import os.path
import shutil
import yaml
from pyapp.utils.log import Log
from pyboot.utils.log import Log
class ConfigManager:
config = None

View File

@@ -2,8 +2,8 @@ import os
import time
from abc import abstractmethod, ABC
from pyapp.config import ConfigManager
from pyapp.utils.log import Log
from pyboot.config import ConfigManager
from pyboot.utils.log import Log
class Runner(ABC):

View File

@@ -1,7 +1,7 @@
import inspect
from pyapp.component import Component
from pyapp.utils.log import Log
from pyboot.component import Component
from pyboot.utils.log import Log
def ensure_component_subclass(cls, type_name, name):
@@ -24,9 +24,9 @@ def ensure_component_subclass(cls, type_name, name):
all_component_classes = {}
all_component_comments = {}
def register_component_type(component_type, comment=None):
def register_component_type(component_type):
all_component_classes[component_type] = {}
all_component_comments[component_type] = comment
all_component_comments[component_type] = {}
# --- Classes --- #
@@ -34,49 +34,47 @@ def component(component_type, component_name, comment=None):
def decorator(cls):
cls = ensure_component_subclass(cls, "COMPONENT", component_name)
if component_type not in all_component_classes:
register_component_type(component_type, comment)
register_component_type(component_type)
all_component_classes[component_type][component_name] = cls
all_component_comments[component_type][component_name] = comment
return cls
return decorator
runner_classes = {}
runner_comments = {}
def runner(runner_name, comment=None):
def decorator(cls):
if not hasattr(cls, 'run') or not callable(getattr(cls, 'run')):
Log.error(f"runner <{cls.__name__}> must implement a 'run' method", True)
cls = ensure_component_subclass(cls, "RUNNER", runner_name)
runner_classes[runner_name] = cls
runner_comments[runner_name] = comment
if "runner" not in all_component_classes:
register_component_type("runner")
all_component_classes["runner"][runner_name] = cls
all_component_comments["runner"][runner_name] = comment
return cls
return decorator
factory_classes = {}
factory_comments = {}
def factory(factory_name, comment=None):
def decorator(cls):
if not hasattr(cls, 'create') or not callable(getattr(cls, 'create')):
Log.error(f"factory <{cls.__name__}> must implement a 'create' method", True)
cls = ensure_component_subclass(cls, "FACTORY", factory_name)
factory_classes[factory_name] = cls
factory_comments[factory_name] = comment
if "factory" not in all_component_classes:
register_component_type("factory")
all_component_classes["factory"][factory_name] = cls
all_component_comments["factory"][factory_name] = comment
return cls
return decorator
client_classes = {}
client_comments = {}
def client(client_name, comment=None):
def decorator(cls):
cls = ensure_component_subclass(cls, "CLIENT", client_name)
client_classes[client_name] = cls
client_comments[client_name] = comment
if "client" not in all_component_classes:
register_component_type("client")
all_component_classes["client"][client_name] = cls
all_component_comments["client"][client_name] = comment
return cls
return decorator
server_classes = {}
server_comments = {}
def server(server_name, comment=None):
def decorator(cls):
cls = ensure_component_subclass(cls, "SERVER", server_name)
@@ -84,18 +82,15 @@ def server(server_name, comment=None):
Log.error(f"server <{cls.__name__}> must implement 'host' and 'port' attributes", True)
if not hasattr(cls, 'serve') or not callable(getattr(cls, 'serve')):
Log.error(f"server <{cls.__name__}> must implement a 'serve' method", True)
server_classes[server_name] = cls
server_comments[server_name] = comment
if "server" not in all_component_classes:
register_component_type("server")
all_component_classes["server"][server_name] = cls
all_component_comments["server"][server_name] = comment
return cls
return decorator
# --- Utils --- #
register_component_type("RUNNER", "Runner")
register_component_type("FACTORY", "Factory")
register_component_type("CLIENT", "Client")
register_component_type("SERVER", "Server")
def get_all_component_classes():
return all_component_classes

View File

@@ -1,3 +1,3 @@
"""
Utility modules for PyApp
Template modules for pyboot
"""

View File

@@ -1,13 +1,13 @@
template = """from pyapp.application import PyappApplication
template = """from pyboot.application import PybootApplication
from runners import YourCustomRunner
@PyappApplication("your_application_name")
@PybootApplication("your_application_name")
class Application:
@staticmethod
def start():
'''
call default or your custom runners here, code will be executed
automatically when type "pyapp run" in terminal
automatically when type "pyboot run" or "pb run" in terminal
example:
YourCustomRunner("path_to_your_config").run()

View File

@@ -0,0 +1,3 @@
"""
UI modules for pyboot
"""

View File

@@ -0,0 +1,3 @@
"""
Client-side UI components for Pyboot
"""

View File

@@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pyboot Project</title><link href=/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.9f7b4785a30f0533ee08.js></script><script type=text/javascript src=/static/js/app.d8ab046c4c34bfc5bd54.js></script></body></html>

View File

Before

Width:  |  Height:  |  Size: 542 KiB

After

Width:  |  Height:  |  Size: 542 KiB

View File

@@ -0,0 +1,3 @@
"""
Server-side UI components for Pyboot
"""

View File

@@ -8,12 +8,12 @@ import platform
from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
from pyapp.utils.project import Project
from pyapp.stereotype import get_all_component_classes, get_all_component_comments
from pyapp.application import application_class
from pyapp.status import status_manager
from pyapp.utils.log import Log
from pyapp.utils.timer import Timer
from pyboot.utils.project import Project
from pyboot.stereotype import get_all_component_classes, get_all_component_comments
from pyboot.application import application_class
from pyboot.status import status_manager
from pyboot.utils.log import Log
from pyboot.utils.timer import Timer
app = Flask(__name__, static_folder="../client")
app.logger.setLevel("WARNING")
@@ -66,7 +66,7 @@ def run_application():
if app_cls is None:
Log.error(
f"No class annotated with @PyApplication found with the name '{app_name}'.",
f"No class annotated with @Pybootlication found with the name '{app_name}'.",
True,
)
return jsonify(
@@ -78,7 +78,7 @@ def run_application():
if not hasattr(app_cls, "start"):
Log.error(
"The class annotated with @PyApplication should have a 'start' method.",
"The class annotated with @Pybootlication should have a 'start' method.",
True,
)
return jsonify(

View File

@@ -0,0 +1,3 @@
"""
Utility modules for
"""

View File

@@ -1,7 +1,7 @@
import time
import json
from pyapp.status import status_manager
from pyapp.namespace import LogType
from pyboot.status import status_manager
from pyboot.namespace import LogType
class Log:
MAX_TITLE_LENGTH:int = 7
TYPE_COLOR_MAP = {
@@ -13,22 +13,28 @@ class Log:
LogType.TERMINATE: "\033[96m"
}
@staticmethod
def get_time():
return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
@staticmethod
def blue(message):
# blue
print(f"\033[94m{message}\033[0m")
@staticmethod
def red(message):
# red
print(f"\033[91m{message}\033[0m")
@staticmethod
def yellow(message):
# yellow
print(f"\033[93m{message}\033[0m")
@staticmethod
def green(message):
# green
print(f"\033[92m{message}\033[0m")
@staticmethod
def log(message, log_type: str):
time_str = Log.get_time()
space = ""
@@ -42,28 +48,36 @@ class Log:
print (f"\033[1m\033[4m({time_str})\033[0m \033[1m{Log.TYPE_COLOR_MAP[log_type]}[{log_type.capitalize()}]\033[0m{space} {Log.TYPE_COLOR_MAP[log_type]}{formatted_message}\033[0m")
status_manager.add_log(time_str, log_type, formatted_message)
@staticmethod
def bold(message):
print(f"\033[1m{message}\033[0m")
@staticmethod
def underline(message):
print(f"\033[4m{message}\033[0m")
@staticmethod
def info(message):
Log.log(message, LogType.INFO)
@staticmethod
def error(message, terminate=False):
Log.log(message, LogType.ERROR)
if terminate:
Log.terminate("Application Terminated.")
@staticmethod
def warning(message):
Log.log(message, LogType.WARNING)
@staticmethod
def success(message):
Log.log(message, LogType.SUCCESS)
@staticmethod
def debug(message):
Log.log(message, LogType.DEBUG)
@staticmethod
def terminate(message):
Log.log(message, LogType.TERMINATE)
exit(1)

View File

@@ -0,0 +1,116 @@
import os
import sys
import yaml
import importlib
import fnmatch
class Project:
@staticmethod
def _load_pbignore(root_path):
"""Load .pbignore file and return list of ignore patterns"""
pbignore_path = os.path.join(root_path, '.pbignore')
ignore_patterns = []
if os.path.exists(pbignore_path):
try:
with open(pbignore_path, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
# Skip empty lines and comments
if line and not line.startswith('#'):
ignore_patterns.append(line)
except Exception as e:
print(f"Warning: Could not read .pbignore file: {e}")
return ignore_patterns
@staticmethod
def _should_ignore(path, ignore_patterns, root_path):
"""Check if a path should be ignored based on .pbignore patterns"""
if not ignore_patterns:
return False
# Get relative path from root
try:
rel_path = os.path.relpath(path, root_path)
except ValueError:
# If path is not relative to root, don't ignore
return False
# Normalize path separators
rel_path = rel_path.replace(os.sep, '/')
for pattern in ignore_patterns:
# Handle directory patterns (ending with /)
if pattern.endswith('/'):
pattern = pattern[:-1]
if fnmatch.fnmatch(rel_path, pattern) or fnmatch.fnmatch(rel_path, pattern + '/*'):
return True
else:
# Handle file/directory patterns
if fnmatch.fnmatch(rel_path, pattern) or fnmatch.fnmatch(os.path.basename(rel_path), pattern):
return True
return False
@staticmethod
def scan_project(root_path):
sys.path.append(root_path)
if not os.path.exists(root_path) or not os.path.isdir(root_path):
raise ValueError(f"The provided root_path '{root_path}' is not a valid directory.")
parent_dir = os.path.dirname(root_path)
sys.path.insert(0, parent_dir)
# Load .pbignore patterns
ignore_patterns = Project._load_pbignore(root_path)
def import_all_modules(path, package_name):
for root, dirs, files in os.walk(path):
# Check if current directory should be ignored
if Project._should_ignore(root, ignore_patterns, root_path):
dirs[:] = [] # Don't traverse into ignored directories
continue
relative_path = os.path.relpath(root, root_path)
if relative_path == '.':
module_package = package_name
else:
module_package = f"{package_name}.{relative_path.replace(os.sep, '.')}"
for file in files:
if file.endswith(".py") and file != "__init__.py":
file_path = os.path.join(root, file)
# Check if file should be ignored
if Project._should_ignore(file_path, ignore_patterns, root_path):
continue
module_name = file[:-3]
full_module_name = f"{module_package}.{module_name}"
if full_module_name not in sys.modules:
importlib.import_module(full_module_name)
# Filter out ignored directories from further traversal
dirs[:] = [d for d in dirs if not d.startswith('.') and
not Project._should_ignore(os.path.join(root, d), ignore_patterns, root_path)]
package_name = os.path.basename(root_path)
import_all_modules(root_path, package_name)
@staticmethod
def scan_configs(root_path):
configs = {}
for root, dirs, files in os.walk(root_path):
for file in files:
if file.endswith(('.yaml', '.yml')):
if file.startswith('__'):
continue
file_path = os.path.join(root, file)
with open(file_path, 'r', encoding='utf-8') as f:
try:
content = yaml.safe_load(f)
configs[os.path.splitext(file)[0]] = content
except yaml.YAMLError as e:
print(f"Error reading {file_path}: {e}")
return configs

View File

@@ -1,9 +1,9 @@
Metadata-Version: 2.1
Name: pyapp
Metadata-Version: 2.4
Name: pyboot
Version: 0.1
Summary: UNKNOWN
License: UNKNOWN
Platform: UNKNOWN
UNKNOWN
Requires-Dist: pyyaml
Requires-Dist: psutil
Requires-Dist: GPUtil
Requires-Dist: flask
Requires-Dist: flask_cors
Dynamic: requires-dist

View File

@@ -1,41 +1,42 @@
README.md
setup.py
pyapp/__init__.py
pyapp/application.py
pyapp/boot.py
pyapp/component.py
pyapp/component_factory.py
pyapp/config.py
pyapp/namespace.py
pyapp/runner.py
pyapp/status.py
pyapp/stereotype.py
pyapp.egg-info/PKG-INFO
pyapp.egg-info/SOURCES.txt
pyapp.egg-info/dependency_links.txt
pyapp.egg-info/entry_points.txt
pyapp.egg-info/requires.txt
pyapp.egg-info/top_level.txt
pyapp/templates/__init__.py
pyapp/templates/application.py
pyapp/templates/config.py
pyapp/ui/__init__.py
pyapp/ui/client/__init__.py
pyapp/ui/client/index.html
pyapp/ui/client/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css
pyapp/ui/client/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css.map
pyapp/ui/client/static/fonts/ionicons.143146f.woff2
pyapp/ui/client/static/fonts/ionicons.99ac330.woff
pyapp/ui/client/static/fonts/ionicons.d535a25.ttf
pyapp/ui/client/static/img/ionicons.a2c4a26.svg
pyapp/ui/client/static/js/app.d8ab046c4c34bfc5bd54.js
pyapp/ui/client/static/js/app.d8ab046c4c34bfc5bd54.js.map
pyapp/ui/client/static/js/manifest.2ae2e69a05c33dfc65f8.js
pyapp/ui/client/static/js/manifest.2ae2e69a05c33dfc65f8.js.map
pyapp/ui/client/static/js/vendor.9f7b4785a30f0533ee08.js
pyapp/ui/client/static/js/vendor.9f7b4785a30f0533ee08.js.map
pyapp/ui/server/__init__.py
pyapp/ui/server/app.py
pyapp/utils/__init__.py
pyapp/utils/log.py
pyapp/utils/project.py
pyapp/utils/timer.py
/__init__.py
/application.py
/boot.py
/component.py
/component_factory.py
/config.py
/namespace.py
/runner.py
/status.py
/stereotype.py
.egg-info/PKG-INFO
.egg-info/SOURCES.txt
.egg-info/dependency_links.txt
.egg-info/entry_points.txt
.egg-info/requires.txt
.egg-info/top_level.txt
/templates/__init__.py
/templates/application.py
/templates/config.py
/ui/__init__.py
/ui/client/__init__.py
/ui/client/index.html
/ui/client/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css
/ui/client/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css.map
/ui/client/static/fonts/ionicons.143146f.woff2
/ui/client/static/fonts/ionicons.99ac330.woff
/ui/client/static/fonts/ionicons.d535a25.ttf
/ui/client/static/img/ionicons.a2c4a26.svg
/ui/client/static/js/app.d8ab046c4c34bfc5bd54.js
/ui/client/static/js/app.d8ab046c4c34bfc5bd54.js.map
/ui/client/static/js/manifest.2ae2e69a05c33dfc65f8.js
/ui/client/static/js/manifest.2ae2e69a05c33dfc65f8.js.map
/ui/client/static/js/vendor.9f7b4785a30f0533ee08.js
/ui/client/static/js/vendor.9f7b4785a30f0533ee08.js.map
/ui/server/__init__.py
/ui/server/app.py
/utils/__init__.py
/utils/log.py
/utils/project.py
/utils/timer.py

View File

@@ -1,2 +1,2 @@
[console_scripts]
pa = pyapp.boot:main
pa = pyboot.boot:main

View File

@@ -1 +1 @@
pyapp
pyboot

View File

@@ -1,3 +0,0 @@
"""
Template modules for PyApp
"""

View File

@@ -1,3 +0,0 @@
"""
UI modules for PyApp
"""

View File

@@ -1,3 +0,0 @@
"""
Client-side UI components for PyApp
"""

View File

@@ -1 +0,0 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>PyApp Project</title><link href=/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.9f7b4785a30f0533ee08.js></script><script type=text/javascript src=/static/js/app.d8ab046c4c34bfc5bd54.js></script></body></html>

View File

@@ -1,3 +0,0 @@
"""
Server-side UI components for PyApp
"""

View File

@@ -1,50 +0,0 @@
import os
import sys
import yaml
import importlib
class Project:
@staticmethod
def scan_project(root_path):
sys.path.append(root_path)
if not os.path.exists(root_path) or not os.path.isdir(root_path):
raise ValueError(f"The provided root_path '{root_path}' is not a valid directory.")
parent_dir = os.path.dirname(root_path)
sys.path.insert(0, parent_dir)
def import_all_modules(path, package_name):
for root, dirs, files in os.walk(path):
relative_path = os.path.relpath(root, root_path)
if relative_path == '.':
module_package = package_name
else:
module_package = f"{package_name}.{relative_path.replace(os.sep, '.')}"
for file in files:
if file.endswith(".py") and file != "__init__.py":
module_name = file[:-3]
full_module_name = f"{module_package}.{module_name}"
if full_module_name not in sys.modules:
importlib.import_module(full_module_name)
dirs[:] = [d for d in dirs if not d.startswith('.')]
package_name = os.path.basename(root_path)
import_all_modules(root_path, package_name)
@staticmethod
def scan_configs(root_path):
configs = {}
for root, dirs, files in os.walk(root_path):
for file in files:
if file.endswith(('.yaml', '.yml')):
if file.startswith('__'):
continue
file_path = os.path.join(root, file)
with open(file_path, 'r', encoding='utf-8') as f:
try:
content = yaml.safe_load(f)
configs[os.path.splitext(file)[0]] = content
except yaml.YAMLError as e:
print(f"Error reading {file_path}: {e}")
return configs

9
pyboot.egg-info/PKG-INFO Normal file
View File

@@ -0,0 +1,9 @@
Metadata-Version: 2.4
Name: pyboot
Version: 0.2
Requires-Dist: pyyaml
Requires-Dist: psutil
Requires-Dist: GPUtil
Requires-Dist: flask
Requires-Dist: flask_cors
Dynamic: requires-dist

View File

@@ -0,0 +1,50 @@
.gitignore
README.md
setup.py
__pycache__/setup.cpython-39.pyc
pyapp.egg-info/PKG-INFO
pyapp.egg-info/SOURCES.txt
pyapp.egg-info/dependency_links.txt
pyapp.egg-info/entry_points.txt
pyapp.egg-info/requires.txt
pyapp.egg-info/top_level.txt
pyboot/__init__.py
pyboot/application.py
pyboot/boot.py
pyboot/component.py
pyboot/component_factory.py
pyboot/config.py
pyboot/namespace.py
pyboot/runner.py
pyboot/status.py
pyboot/stereotype.py
pyboot.egg-info/PKG-INFO
pyboot.egg-info/SOURCES.txt
pyboot.egg-info/dependency_links.txt
pyboot.egg-info/entry_points.txt
pyboot.egg-info/requires.txt
pyboot.egg-info/top_level.txt
pyboot/templates/__init__.py
pyboot/templates/application.py
pyboot/templates/config.py
pyboot/ui/__init__.py
pyboot/ui/client/__init__.py
pyboot/ui/client/index.html
pyboot/ui/client/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css
pyboot/ui/client/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css.map
pyboot/ui/client/static/fonts/ionicons.143146f.woff2
pyboot/ui/client/static/fonts/ionicons.99ac330.woff
pyboot/ui/client/static/fonts/ionicons.d535a25.ttf
pyboot/ui/client/static/img/ionicons.a2c4a26.svg
pyboot/ui/client/static/js/app.d8ab046c4c34bfc5bd54.js
pyboot/ui/client/static/js/app.d8ab046c4c34bfc5bd54.js.map
pyboot/ui/client/static/js/manifest.2ae2e69a05c33dfc65f8.js
pyboot/ui/client/static/js/manifest.2ae2e69a05c33dfc65f8.js.map
pyboot/ui/client/static/js/vendor.9f7b4785a30f0533ee08.js
pyboot/ui/client/static/js/vendor.9f7b4785a30f0533ee08.js.map
pyboot/ui/server/__init__.py
pyboot/ui/server/app.py
pyboot/utils/__init__.py
pyboot/utils/log.py
pyboot/utils/project.py
pyboot/utils/timer.py

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,3 @@
[console_scripts]
pb = pyboot.boot:main
pyboot = pyboot.boot:main

View File

@@ -0,0 +1,5 @@
pyyaml
psutil
GPUtil
flask
flask_cors

View File

@@ -0,0 +1 @@
pyboot

6
pyboot/__init__.py Normal file
View File

@@ -0,0 +1,6 @@
"""
pyboot - A Python application framework
"""
__version__ = "0.1"
__author__ = "Hofee"

21
pyboot/application.py Normal file
View File

@@ -0,0 +1,21 @@
from pyboot.utils.log import Log
application_class = {}
def PybootApplication(arg=None):
if callable(arg):
cls = arg
if "default" in application_class:
Log.error("Multiple classes annotated with default @PybootApplication, require a 'name' parameter.", True)
application_class["default"] = cls
return cls
else:
name = arg
def decorator(cls):
if name is None:
raise Log.error("The 'name' parameter is required when using @PybootApplication with arguments.", True)
if name in application_class:
raise Log.error(f"Multiple classes annotated with @PybootApplication with the same name '{name}' found.", True)
application_class[name] = cls
return cls
return decorator

110
pyboot/boot.py Normal file
View File

@@ -0,0 +1,110 @@
import os
import sys
from pyboot.application import application_class
from pyboot.stereotype import get_all_component_classes, get_all_component_comments
from pyboot.utils.log import Log
from pyboot.utils.timer import Timer
from pyboot.utils.project import Project
from pyboot.templates.application import template as app_template
from pyboot.templates.config import template as config_template
from pyboot.ui.server.app import app
def run():
root_path = os.getcwd()
Project.scan_project(root_path)
app_name = "default"
if len(application_class) == 0:
Log.error("No class annotated with @PybootApplication found.", True)
if len(sys.argv) < 3 and "default" not in application_class:
Log.error("No default @PybootApplication found. Please specify the 'name' parameter.", True)
if len(sys.argv) == 3:
app_name = sys.argv[2]
app_cls = application_class.get(app_name)
if app_cls is None:
Log.error(f"No class annotated with @PybootApplication found with the name '{app_name}'.", True)
if not hasattr(app_cls, "start"):
Log.error("The class annotated with @PybootApplication should have a 'start' method.", True)
Log.info(f"Application '{app_cls.__name__}' started.")
timer = Timer(f"Application({app_name})")
timer.start()
app_cls.start()
timer.stop()
Log.info(timer.get_elasped_time_str(Timer.HOURS))
Log.success("Application finished.")
def init():
Log.info("Initializing Pyboot project.")
root_path = os.getcwd()
if len(os.listdir(root_path)) > 0:
Log.error("Current directory is not empty. Please provide an empty directory.")
else:
with open(os.path.join(root_path, "application.py"), "w") as file:
file.write(app_template)
with open(os.path.join(root_path, "config.yaml"), "w") as file:
file.write(config_template)
Log.success("Pyboot project initialized.")
Log.info("Now you can create your components and run the application.")
def scan():
root_path = os.getcwd()
Project.scan_project(root_path)
comments = get_all_component_comments()
Log.info("Components detected in the project:")
for stereotype, classes in get_all_component_classes().items():
if len(classes) == 0:
continue
Log.info(f" {stereotype}:")
for name, cls in classes.items():
comment = comments[stereotype].get(name)
if comment is not None:
Log.warning(f" - {name}: {cls.__module__}.{cls.__name__} ({comment})")
else:
Log.success(f" - {name}: {cls.__module__}.{cls.__name__}")
Log.info("Applications detected in the project:")
for app_name, app_cls in application_class.items():
Log.success(f" - {app_name}: {app_cls.__module__}.{app_cls.__name__}")
Log.success("Scan completed.")
def ui():
port = 5000
if len(sys.argv) == 3:
port = int(sys.argv[2])
Log.success(f"Pyboot UI server started at http://localhost:{port}")
app.run(port=port, host="0.0.0.0")
def help():
Log.info("Pyboot commands:")
Log.info(" init: Initialize a new Pyboot project in the current directory.")
Log.info(" run [name]: Run the Pyboot application with the specified name. If no name is provided, the default application will be run.")
Log.info(" scan: Scan the project for Pyboot components.")
Log.info(" ui [port]: Start the Pyboot UI server. If no port is provided, the default port 5000 will be used.")
Log.info(" help: Display this help message.")
def main():
if len(sys.argv) > 1:
if sys.argv[1] == "init":
init()
elif sys.argv[1] == "run":
run()
elif sys.argv[1] == "scan":
scan()
elif sys.argv[1] == "ui":
ui()
elif sys.argv[1] == "help":
help()
else:
Log.error("Invalid command: " + sys.argv[1] + ". Use 'pyboot help' for help.")
else:
Log.error("Please provide a command to run the application.")

21
pyboot/component.py Normal file
View File

@@ -0,0 +1,21 @@
from pyboot.utils.log import Log
class Component:
TYPE: str
NAME: str
def get_name(self):
return self.NAME
def get_type(self):
return self.TYPE
def get_config(self):
return self.config
def print(self):
Log.blue("Component Information")
Log.blue(f"- Type: {self.TYPE}")
Log.blue(f"- Name: {self.NAME}")
Log.blue(f"- Config: \n\t{self.config}")

View File

@@ -0,0 +1,27 @@
from pyboot.component import Component
from pyboot.stereotype import *
from pyboot.utils.log import Log
from pyboot.config import ConfigManager
class ComponentFactory:
@staticmethod
def create(component_type: str, name: str) -> Component:
component_classes = get_component_classes(component_type=component_type)
if component_classes is None:
Log.error(f"Unsupported component type: {component_type}", True)
if component_type == "COMPONENT":
config = ConfigManager.get(component_type, name)
cls = component_classes[config["source"]]
component_obj = cls(config)
component_obj.NAME = name
component_obj.TYPE = component_type
return component_obj
if name not in component_classes:
Log.error(f"Unsupported component name: {name}", True)
cls = component_classes[name]
config = ConfigManager.get(component_type, name)
return cls(config)

59
pyboot/config.py Normal file
View File

@@ -0,0 +1,59 @@
import argparse
import os.path
import shutil
import yaml
from pyboot.utils.log import Log
class ConfigManager:
config = None
config_path = None
@staticmethod
def get(*args):
result = ConfigManager.config
for arg in args:
result = result[arg]
return result
@staticmethod
def load_config_with(config_file_path):
ConfigManager.config_path = config_file_path
if not os.path.exists(ConfigManager.config_path):
raise ValueError(f"Config file <{config_file_path}> does not exist")
with open(config_file_path, 'r') as file:
ConfigManager.config = yaml.safe_load(file)
@staticmethod
def backup_config_to(target_config_dir, file_name, prefix="config"):
file_name = f"__{prefix}_{file_name}.yaml"
target_config_file_path = str(os.path.join(target_config_dir, file_name))
shutil.copy(ConfigManager.config_path, target_config_file_path)
@staticmethod
def load_config():
parser = argparse.ArgumentParser()
parser.add_argument('--config', type=str, default='', help='config file path')
args = parser.parse_args()
if args.config:
ConfigManager.load_config_with(args.config)
@staticmethod
def print_config(key: str = None, group: dict = None, level=0):
table_size = 80
if key and group:
value = group[key]
if type(value) is dict:
Log.blue("\t" * level + f"+-{key}:")
for k in value:
ConfigManager.print_config(k, value, level=level + 1)
else:
Log.blue("\t" * level + f"| {key}: {value}")
elif key:
ConfigManager.print_config(key, ConfigManager.config, level=level)
else:
Log.blue("+" + "-" * table_size + "+")
Log.blue(f"| Configurations in <{ConfigManager.config_path}>:")
Log.blue("+" + "-" * table_size + "+")
for key in ConfigManager.config:
ConfigManager.print_config(key, level=level + 1)
Log.blue("+" + "-" * table_size + "+")

15
pyboot/namespace.py Normal file
View File

@@ -0,0 +1,15 @@
class Stereotype:
APPLICATION:str = "application"
RUNNER:str = "runner"
FACTORY:str = "factory"
SERVER:str = "server"
CLIENT:str = "client"
class LogType:
INFO:str = "info"
ERROR:str = "error"
WARNING:str = "warning"
SUCCESS:str = "success"
DEBUG:str = "debug"
TERMINATE:str = "terminate"

51
pyboot/runner.py Normal file
View File

@@ -0,0 +1,51 @@
import os
import time
from abc import abstractmethod, ABC
from pyboot.config import ConfigManager
from pyboot.utils.log import Log
class Runner(ABC):
@abstractmethod
def __init__(self, config_path):
ConfigManager.load_config_with(config_path)
ConfigManager.print_config()
self.config = ConfigManager.get("runner")
self.workspace_config = self.config["workspace"]
self.workspace_path = os.path.join(self.workspace_config["root_dir"], self.workspace_config["name"])
lt = time.localtime()
self.file_name = f"{lt.tm_year}_{lt.tm_mon}_{lt.tm_mday}_{lt.tm_hour}h{lt.tm_min}m{lt.tm_sec}s"
self.load_workspace()
@abstractmethod
def run(self):
pass
def load_workspace(self, backup_name=None):
if not os.path.exists(self.workspace_path):
Log.info(f"workspace {self.workspace_config['name']} does not exists.")
self.create_workspace(backup_name)
else:
Log.info(f"workspace {self.workspace_config['name']}")
backup_config_dir = os.path.join(str(self.workspace_path), "configs")
if not os.path.exists(backup_config_dir):
os.makedirs(backup_config_dir)
ConfigManager.backup_config_to(backup_config_dir, self.file_name, backup_name)
def create_workspace(self, backup_name=None):
Log.info("creating workspace: " + self.workspace_config["name"])
os.makedirs(self.workspace_path)
backup_config_dir = os.path.join(str(self.workspace_path), "configs")
os.makedirs(backup_config_dir)
ConfigManager.backup_config_to(backup_config_dir, self.file_name, backup_name)
log_dir = os.path.join(str(self.workspace_path), "logs")
os.makedirs(log_dir)
cache_dir = os.path.join(str(self.workspace_path), "cache")
os.makedirs(cache_dir)
def print_info(self):
table_size = 80
Log.blue("+" + "-" * table_size + "+")
Log.blue(f"| Workspace <{self.workspace_config['name']}>")
Log.blue("+" + "-" * table_size + "+")

56
pyboot/status.py Normal file
View File

@@ -0,0 +1,56 @@
class StatusManager:
def __init__(self):
self.running_app = {}
self.last_status = {}
self.curr_status = {}
self.progress = {}
self.log = []
def is_running(self):
return len(self.running_app) > 0
def run_app(self, app_name, app):
self.running_app[app_name] = app
def end_app(self, app_name):
self.running_app.pop(app_name)
def set_status(self, app_name, runner_name, key, value):
self.last_status = self.curr_status
if app_name not in self.curr_status:
self.curr_status[app_name] = {}
if runner_name not in self.curr_status[app_name]:
self.curr_status[app_name][runner_name] = {}
self.curr_status[app_name][runner_name][key] = value
def set_progress(self, app_name, runner_name, key, curr_value, max_value):
if app_name not in self.progress:
self.progress[app_name] = {}
if runner_name not in self.progress[app_name]:
self.progress[app_name][runner_name] = {}
self.progress[app_name][runner_name][key] = (curr_value, max_value)
def get_status(self):
return self.curr_status
def get_progress(self):
return self.progress
def add_log(self, time_str, log_type, message):
self.log.append((time_str, log_type, message))
def get_log(self):
return self.log
def get_running_apps(self):
return list(self.running_app.keys())
def get_last_status(self):
return self.last_status
def reset_status(self):
self.last_status = {}
self.curr_status = {}
status_manager = StatusManager()

101
pyboot/stereotype.py Normal file
View File

@@ -0,0 +1,101 @@
import inspect
from pyboot.component import Component
from pyboot.utils.log import Log
def ensure_component_subclass(cls, type_name, name):
if not issubclass(cls, Component):
new_cls = type(cls.__name__, (Component, cls), {
**cls.__dict__,
"TYPE": type_name,
"NAME": name
})
new_cls.__original_class__ = cls
else:
new_cls = cls
for method_name, method in inspect.getmembers(cls, predicate=inspect.isfunction):
if getattr(method, "__isabstractmethod__", False):
Log.error(f"Component <{name}> contains abstract method <{method_name}>.", True)
return cls
all_component_classes = {}
all_component_comments = {}
def register_component_type(component_type):
all_component_classes[component_type] = {}
all_component_comments[component_type] = {}
# --- Classes --- #
def component(component_type, component_name, comment=None):
def decorator(cls):
cls = ensure_component_subclass(cls, "COMPONENT", component_name)
if component_type not in all_component_classes:
register_component_type(component_type)
all_component_classes[component_type][component_name] = cls
all_component_comments[component_type][component_name] = comment
return cls
return decorator
def runner(runner_name, comment=None):
def decorator(cls):
if not hasattr(cls, 'run') or not callable(getattr(cls, 'run')):
Log.error(f"runner <{cls.__name__}> must implement a 'run' method", True)
cls = ensure_component_subclass(cls, "RUNNER", runner_name)
if "runner" not in all_component_classes:
register_component_type("runner")
all_component_classes["runner"][runner_name] = cls
all_component_comments["runner"][runner_name] = comment
return cls
return decorator
def factory(factory_name, comment=None):
def decorator(cls):
if not hasattr(cls, 'create') or not callable(getattr(cls, 'create')):
Log.error(f"factory <{cls.__name__}> must implement a 'create' method", True)
cls = ensure_component_subclass(cls, "FACTORY", factory_name)
if "factory" not in all_component_classes:
register_component_type("factory")
all_component_classes["factory"][factory_name] = cls
all_component_comments["factory"][factory_name] = comment
return cls
return decorator
def client(client_name, comment=None):
def decorator(cls):
cls = ensure_component_subclass(cls, "CLIENT", client_name)
if "client" not in all_component_classes:
register_component_type("client")
all_component_classes["client"][client_name] = cls
all_component_comments["client"][client_name] = comment
return cls
return decorator
def server(server_name, comment=None):
def decorator(cls):
cls = ensure_component_subclass(cls, "SERVER", server_name)
if not hasattr(cls, 'host') or not hasattr(cls, 'port'):
Log.error(f"server <{cls.__name__}> must implement 'host' and 'port' attributes", True)
if not hasattr(cls, 'serve') or not callable(getattr(cls, 'serve')):
Log.error(f"server <{cls.__name__}> must implement a 'serve' method", True)
if "server" not in all_component_classes:
register_component_type("server")
all_component_classes["server"][server_name] = cls
all_component_comments["server"][server_name] = comment
return cls
return decorator
# --- Utils --- #
def get_all_component_classes():
return all_component_classes
def get_all_component_comments():
return all_component_comments
def get_component_classes(component_type):
return all_component_classes.get(component_type, None)

View File

@@ -0,0 +1,3 @@
"""
Template modules for pyboot
"""

View File

@@ -0,0 +1,15 @@
template = """from pyboot.application import PybootApplication
from runners import YourCustomRunner
@PybootApplication("your_application_name")
class Application:
@staticmethod
def start():
'''
call default or your custom runners here, code will be executed
automatically when type "pyboot run" or "pb run" in terminal
example:
YourCustomRunner("path_to_your_config").run()
'''
"""

View File

@@ -0,0 +1,9 @@
template = """
runner:
general:
workspace:
name: workspace_name
root_dir: "workspaces"
"""

3
pyboot/ui/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
"""
UI modules for pyboot
"""

View File

@@ -0,0 +1,3 @@
"""
Client-side UI components for Pyboot
"""

View File

@@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pyboot Project</title><link href=/static/css/app.f0ad959581daf87e4158e4f8da1285ba.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.9f7b4785a30f0533ee08.js></script><script type=text/javascript src=/static/js/app.d8ab046c4c34bfc5bd54.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 542 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={2:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,"a",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p="/",t.oe=function(r){throw console.error(r),r}}([]);
//# sourceMappingURL=manifest.2ae2e69a05c33dfc65f8.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap 43a1e13c45f80b089c40"],"names":["parentJsonpFunction","window","chunkIds","moreModules","executeModules","moduleId","chunkId","result","i","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","call","modules","shift","__webpack_require__","s","installedModules","2","exports","module","l","m","c","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","p","oe","err","console","error"],"mappings":"aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,IAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA","file":"static/js/manifest.2ae2e69a05c33dfc65f8.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t2: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 43a1e13c45f80b089c40"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
"""
Server-side UI components for Pyboot
"""

Some files were not shown because too many files have changed in this diff Show More