add .pbignore function

This commit is contained in:
2025-09-05 12:50:28 +08:00
parent d209c1abe9
commit faaa8bb357
7 changed files with 159 additions and 25 deletions

View File

@@ -24,9 +24,9 @@ def ensure_component_subclass(cls, type_name, name):
all_component_classes = {} all_component_classes = {}
all_component_comments = {} all_component_comments = {}
def register_component_type(component_type, comment=None): def register_component_type(component_type):
all_component_classes[component_type] = {} all_component_classes[component_type] = {}
all_component_comments[component_type] = comment all_component_comments[component_type] = {}
# --- Classes --- # # --- Classes --- #
@@ -34,7 +34,7 @@ def component(component_type, component_name, comment=None):
def decorator(cls): def decorator(cls):
cls = ensure_component_subclass(cls, "COMPONENT", component_name) cls = ensure_component_subclass(cls, "COMPONENT", component_name)
if component_type not in all_component_classes: 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_classes[component_type][component_name] = cls
all_component_comments[component_type][component_name] = comment all_component_comments[component_type][component_name] = comment
return cls return cls
@@ -91,10 +91,10 @@ def server(server_name, comment=None):
# --- Utils --- # # --- Utils --- #
register_component_type("RUNNER", "Runner") register_component_type("RUNNER")
register_component_type("FACTORY", "Factory") register_component_type("FACTORY")
register_component_type("CLIENT", "Client") register_component_type("CLIENT")
register_component_type("SERVER", "Server") register_component_type("SERVER")
def get_all_component_classes(): def get_all_component_classes():
return all_component_classes return all_component_classes

View File

@@ -2,8 +2,57 @@ import os
import sys import sys
import yaml import yaml
import importlib import importlib
import fnmatch
class Project: 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 @staticmethod
def scan_project(root_path): def scan_project(root_path):
sys.path.append(root_path) sys.path.append(root_path)
@@ -13,20 +62,37 @@ class Project:
parent_dir = os.path.dirname(root_path) parent_dir = os.path.dirname(root_path)
sys.path.insert(0, parent_dir) sys.path.insert(0, parent_dir)
# Load .pbignore patterns
ignore_patterns = Project._load_pbignore(root_path)
def import_all_modules(path, package_name): def import_all_modules(path, package_name):
for root, dirs, files in os.walk(path): 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) relative_path = os.path.relpath(root, root_path)
if relative_path == '.': if relative_path == '.':
module_package = package_name module_package = package_name
else: else:
module_package = f"{package_name}.{relative_path.replace(os.sep, '.')}" module_package = f"{package_name}.{relative_path.replace(os.sep, '.')}"
for file in files: for file in files:
if file.endswith(".py") and file != "__init__.py": 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] module_name = file[:-3]
full_module_name = f"{module_package}.{module_name}" full_module_name = f"{module_package}.{module_name}"
if full_module_name not in sys.modules: if full_module_name not in sys.modules:
importlib.import_module(full_module_name) importlib.import_module(full_module_name)
dirs[:] = [d for d in dirs if not d.startswith('.')]
# 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) package_name = os.path.basename(root_path)
import_all_modules(root_path, package_name) import_all_modules(root_path, package_name)

View File

@@ -1,9 +1,10 @@
Metadata-Version: 2.4 Metadata-Version: 1.0
Name: pyboot Name: pyboot
Version: 0.1 Version: 0.2
Requires-Dist: pyyaml Summary: UNKNOWN
Requires-Dist: psutil Home-page: UNKNOWN
Requires-Dist: GPUtil Author: UNKNOWN
Requires-Dist: flask Author-email: UNKNOWN
Requires-Dist: flask_cors License: UNKNOWN
Dynamic: requires-dist Description: UNKNOWN
Platform: UNKNOWN

View File

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

View File

@@ -24,9 +24,9 @@ def ensure_component_subclass(cls, type_name, name):
all_component_classes = {} all_component_classes = {}
all_component_comments = {} all_component_comments = {}
def register_component_type(component_type, comment=None): def register_component_type(component_type):
all_component_classes[component_type] = {} all_component_classes[component_type] = {}
all_component_comments[component_type] = comment all_component_comments[component_type] = {}
# --- Classes --- # # --- Classes --- #
@@ -34,7 +34,7 @@ def component(component_type, component_name, comment=None):
def decorator(cls): def decorator(cls):
cls = ensure_component_subclass(cls, "COMPONENT", component_name) cls = ensure_component_subclass(cls, "COMPONENT", component_name)
if component_type not in all_component_classes: 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_classes[component_type][component_name] = cls
all_component_comments[component_type][component_name] = comment all_component_comments[component_type][component_name] = comment
return cls return cls
@@ -91,10 +91,10 @@ def server(server_name, comment=None):
# --- Utils --- # # --- Utils --- #
register_component_type("RUNNER", "Runner") register_component_type("RUNNER")
register_component_type("FACTORY", "Factory") register_component_type("FACTORY")
register_component_type("CLIENT", "Client") register_component_type("CLIENT")
register_component_type("SERVER", "Server") register_component_type("SERVER")
def get_all_component_classes(): def get_all_component_classes():
return all_component_classes return all_component_classes

View File

@@ -2,8 +2,57 @@ import os
import sys import sys
import yaml import yaml
import importlib import importlib
import fnmatch
class Project: 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 @staticmethod
def scan_project(root_path): def scan_project(root_path):
sys.path.append(root_path) sys.path.append(root_path)
@@ -13,20 +62,37 @@ class Project:
parent_dir = os.path.dirname(root_path) parent_dir = os.path.dirname(root_path)
sys.path.insert(0, parent_dir) sys.path.insert(0, parent_dir)
# Load .pbignore patterns
ignore_patterns = Project._load_pbignore(root_path)
def import_all_modules(path, package_name): def import_all_modules(path, package_name):
for root, dirs, files in os.walk(path): 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) relative_path = os.path.relpath(root, root_path)
if relative_path == '.': if relative_path == '.':
module_package = package_name module_package = package_name
else: else:
module_package = f"{package_name}.{relative_path.replace(os.sep, '.')}" module_package = f"{package_name}.{relative_path.replace(os.sep, '.')}"
for file in files: for file in files:
if file.endswith(".py") and file != "__init__.py": 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] module_name = file[:-3]
full_module_name = f"{module_package}.{module_name}" full_module_name = f"{module_package}.{module_name}"
if full_module_name not in sys.modules: if full_module_name not in sys.modules:
importlib.import_module(full_module_name) importlib.import_module(full_module_name)
dirs[:] = [d for d in dirs if not d.startswith('.')]
# 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) package_name = os.path.basename(root_path)
import_all_modules(root_path, package_name) import_all_modules(root_path, package_name)

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup( setup(
name="pyboot", name="pyboot",
version="0.1", version="0.2",
packages=find_packages(), packages=find_packages(),
package_data={ package_data={
'pyboot': ['templates/*.py',"ui/server/*.py", "ui/client/*", 'pyboot': ['templates/*.py',"ui/server/*.py", "ui/client/*",