Unused import A module is imported (using the import statement) but that module is never used. This creates a dependency that does not need to exist and makes the code more difficult to read. Recommendation Delete the import statement.

This commit is contained in:
2026-01-17 17:21:10 -06:00
parent 1fdf8ba2d0
commit f70b702b76
4 changed files with 789 additions and 793 deletions

View File

@@ -40,11 +40,10 @@ from typing import Dict
sys.path.insert(0, str(Path(__file__).parent.parent / "lib"))
try:
import common
import joomla_manifest
import common
except ImportError:
print("ERROR: Cannot import required libraries", file=sys.stderr)
sys.exit(1)
print("ERROR: Cannot import required libraries", file=sys.stderr)
sys.exit(1)
# ============================================================================
@@ -52,73 +51,73 @@ except ImportError:
# ============================================================================
def get_component_structure(name: str, description: str, author: str) -> Dict[str, str]:
"""Get directory structure and files for a component."""
safe_name = name.lower().replace(" ", "_")
com_name = f"com_{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
"""Get directory structure and files for a component."""
safe_name = name.lower().replace(" ", "_")
com_name = f"com_{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="4.0" method="upgrade">
<name>{name}</name>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<name>{name}</name>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<files folder="site">
<folder>src</folder>
</files>
<files folder="site">
<folder>src</folder>
</files>
<administration>
<menu>{name}</menu>
<files folder="admin">
<folder>services</folder>
<folder>sql</folder>
<folder>src</folder>
</files>
</administration>
<administration>
<menu>{name}</menu>
<files folder="admin">
<folder>services</folder>
<folder>sql</folder>
<folder>src</folder>
</files>
</administration>
</extension>
"""
return {
f"{com_name}.xml": manifest,
"site/src/.gitkeep": "",
"admin/services/provider.php": f"<?php\n// Service provider for {name}\n",
"admin/sql/install.mysql.utf8.sql": "-- Installation SQL\n",
"admin/sql/uninstall.mysql.utf8.sql": "-- Uninstallation SQL\n",
"admin/src/.gitkeep": "",
}
return {
f"{com_name}.xml": manifest,
"site/src/.gitkeep": "",
"admin/services/provider.php": f"<?php\n// Service provider for {name}\n",
"admin/sql/install.mysql.utf8.sql": "-- Installation SQL\n",
"admin/sql/uninstall.mysql.utf8.sql": "-- Uninstallation SQL\n",
"admin/src/.gitkeep": "",
}
def get_module_structure(name: str, description: str, author: str, client: str = "site") -> Dict[str, str]:
"""Get directory structure and files for a module."""
safe_name = name.lower().replace(" ", "_")
mod_name = f"mod_{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
"""Get directory structure and files for a module."""
safe_name = name.lower().replace(" ", "_")
mod_name = f"mod_{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="{client}" method="upgrade">
<name>{name}</name>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<name>{name}</name>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<files>
<filename module="{mod_name}">{mod_name}.php</filename>
<filename>{mod_name}.xml</filename>
<folder>tmpl</folder>
</files>
<files>
<filename module="{mod_name}">{mod_name}.php</filename>
<filename>{mod_name}.xml</filename>
<folder>tmpl</folder>
</files>
</extension>
"""
module_php = f"""<?php
module_php = f"""<?php
/**
* @package {name}
* @copyright Copyright (C) {datetime.now().year} {author}
@@ -130,8 +129,8 @@ defined('_JEXEC') or die;
// Module logic here
require JModuleHelper::getLayoutPath('mod_{safe_name}', $params->get('layout', 'default'));
"""
default_tmpl = f"""<?php
default_tmpl = f"""<?php
/**
* @package {name}
* @copyright Copyright (C) {datetime.now().year} {author}
@@ -141,41 +140,41 @@ require JModuleHelper::getLayoutPath('mod_{safe_name}', $params->get('layout', '
defined('_JEXEC') or die;
?>
<div class="{mod_name}">
<p><?php echo JText::_('MOD_{safe_name.upper()}_DESCRIPTION'); ?></p>
<p><?php echo JText::_('MOD_{safe_name.upper()}_DESCRIPTION'); ?></p>
</div>
"""
return {
f"{mod_name}.xml": manifest,
f"{mod_name}.php": module_php,
"tmpl/default.php": default_tmpl,
}
return {
f"{mod_name}.xml": manifest,
f"{mod_name}.php": module_php,
"tmpl/default.php": default_tmpl,
}
def get_plugin_structure(name: str, description: str, author: str, group: str = "system") -> Dict[str, str]:
"""Get directory structure and files for a plugin."""
safe_name = name.lower().replace(" ", "_")
plg_name = f"{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
"""Get directory structure and files for a plugin."""
safe_name = name.lower().replace(" ", "_")
plg_name = f"{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
<extension type="plugin" version="4.0" group="{group}" method="upgrade">
<name>plg_{group}_{safe_name}</name>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<name>plg_{group}_{safe_name}</name>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<files>
<filename plugin="{plg_name}">{plg_name}.php</filename>
</files>
<files>
<filename plugin="{plg_name}">{plg_name}.php</filename>
</files>
</extension>
"""
plugin_php = f"""<?php
plugin_php = f"""<?php
/**
* @package {name}
* @copyright Copyright (C) {datetime.now().year} {author}
@@ -188,54 +187,54 @@ use Joomla\\CMS\\Plugin\\CMSPlugin;
class Plg{group.capitalize()}{plg_name.capitalize()} extends CMSPlugin
{{
protected $autoloadLanguage = true;
protected $autoloadLanguage = true;
public function onContentPrepare($context, &$article, &$params, $limitstart = 0)
{{
// Plugin logic here
}}
public function onContentPrepare($context, &$article, &$params, $limitstart = 0)
{{
// Plugin logic here
}}
}}
"""
return {
f"plg_{group}_{safe_name}.xml": manifest,
f"{plg_name}.php": plugin_php,
}
return {
f"plg_{group}_{safe_name}.xml": manifest,
f"{plg_name}.php": plugin_php,
}
def get_template_structure(name: str, description: str, author: str) -> Dict[str, str]:
"""Get directory structure and files for a template."""
safe_name = name.lower().replace(" ", "_")
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
"""Get directory structure and files for a template."""
safe_name = name.lower().replace(" ", "_")
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
<extension type="template" version="4.0" client="site" method="upgrade">
<name>{safe_name}</name>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<author>{author}</author>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<version>1.0.0</version>
<description>{description}</description>
<name>{safe_name}</name>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<author>{author}</author>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<version>1.0.0</version>
<description>{description}</description>
<files>
<filename>index.php</filename>
<filename>templateDetails.xml</filename>
<folder>css</folder>
<folder>js</folder>
<folder>images</folder>
</files>
<files>
<filename>index.php</filename>
<filename>templateDetails.xml</filename>
<folder>css</folder>
<folder>js</folder>
<folder>images</folder>
</files>
<positions>
<position>header</position>
<position>main</position>
<position>footer</position>
</positions>
<positions>
<position>header</position>
<position>main</position>
<position>footer</position>
</positions>
</extension>
"""
index_php = f"""<?php
index_php = f"""<?php
/**
* @package {name}
* @copyright Copyright (C) {datetime.now().year} {author}
@@ -257,61 +256,61 @@ $wa->useStyle('template.{safe_name}')->useScript('template.{safe_name}');
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
<jdoc:include type="metas" />
<jdoc:include type="styles" />
<jdoc:include type="scripts" />
<jdoc:include type="metas" />
<jdoc:include type="styles" />
<jdoc:include type="scripts" />
</head>
<body>
<header>
<jdoc:include type="modules" name="header" style="html5" />
</header>
<main>
<jdoc:include type="component" />
</main>
<footer>
<jdoc:include type="modules" name="footer" style="html5" />
</footer>
<header>
<jdoc:include type="modules" name="header" style="html5" />
</header>
<main>
<jdoc:include type="component" />
</main>
<footer>
<jdoc:include type="modules" name="footer" style="html5" />
</footer>
</body>
</html>
"""
return {
"templateDetails.xml": manifest,
"index.php": index_php,
"css/template.css": "/* Template styles */\n",
"js/template.js": "// Template JavaScript\n",
"images/.gitkeep": "",
}
return {
"templateDetails.xml": manifest,
"index.php": index_php,
"css/template.css": "/* Template styles */\n",
"js/template.js": "// Template JavaScript\n",
"images/.gitkeep": "",
}
def get_package_structure(name: str, description: str, author: str) -> Dict[str, str]:
"""Get directory structure and files for a package."""
safe_name = name.lower().replace(" ", "_")
pkg_name = f"pkg_{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
"""Get directory structure and files for a package."""
safe_name = name.lower().replace(" ", "_")
pkg_name = f"pkg_{safe_name}"
manifest = f"""<?xml version="1.0" encoding="utf-8"?>
<extension type="package" version="4.0" method="upgrade">
<name>{name}</name>
<packagename>{safe_name}</packagename>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<name>{name}</name>
<packagename>{safe_name}</packagename>
<author>{author}</author>
<creationDate>{datetime.now().strftime("%Y-%m-%d")}</creationDate>
<copyright>Copyright (C) {datetime.now().year} {author}</copyright>
<license>GPL-3.0-or-later</license>
<authorEmail>hello@example.com</authorEmail>
<authorUrl>https://example.com</authorUrl>
<version>1.0.0</version>
<description>{description}</description>
<files folder="packages">
<!-- Add extension packages here -->
</files>
<files folder="packages">
<!-- Add extension packages here -->
</files>
</extension>
"""
return {
f"{pkg_name}.xml": manifest,
"packages/.gitkeep": "",
}
return {
f"{pkg_name}.xml": manifest,
"packages/.gitkeep": "",
}
# ============================================================================
@@ -319,59 +318,59 @@ def get_package_structure(name: str, description: str, author: str) -> Dict[str,
# ============================================================================
def create_extension(
ext_type: str,
name: str,
description: str,
author: str,
output_dir: str = "src",
**kwargs
ext_type: str,
name: str,
description: str,
author: str,
output_dir: str = "src",
**kwargs
) -> None:
"""
Create extension scaffolding.
Args:
ext_type: Extension type (component, module, plugin, template, package)
name: Extension name
description: Extension description
author: Author name
output_dir: Output directory
**kwargs: Additional type-specific options
"""
output_path = Path(output_dir)
# Get structure based on type
if ext_type == "component":
structure = get_component_structure(name, description, author)
elif ext_type == "module":
client = kwargs.get("client", "site")
structure = get_module_structure(name, description, author, client)
elif ext_type == "plugin":
group = kwargs.get("group", "system")
structure = get_plugin_structure(name, description, author, group)
elif ext_type == "template":
structure = get_template_structure(name, description, author)
elif ext_type == "package":
structure = get_package_structure(name, description, author)
else:
common.die(f"Unknown extension type: {ext_type}")
# Create files
common.log_section(f"Creating {ext_type}: {name}")
for file_path, content in structure.items():
full_path = output_path / file_path
# Create parent directories
full_path.parent.mkdir(parents=True, exist_ok=True)
# Write file
full_path.write_text(content, encoding="utf-8")
common.log_success(f"Created: {file_path}")
common.log_section("Scaffolding Complete")
common.log_info(f"Extension files created in: {output_path}")
common.log_info(f"Extension type: {ext_type}")
common.log_info(f"Extension name: {name}")
"""
Create extension scaffolding.
Args:
ext_type: Extension type (component, module, plugin, template, package)
name: Extension name
description: Extension description
author: Author name
output_dir: Output directory
**kwargs: Additional type-specific options
"""
output_path = Path(output_dir)
# Get structure based on type
if ext_type == "component":
structure = get_component_structure(name, description, author)
elif ext_type == "module":
client = kwargs.get("client", "site")
structure = get_module_structure(name, description, author, client)
elif ext_type == "plugin":
group = kwargs.get("group", "system")
structure = get_plugin_structure(name, description, author, group)
elif ext_type == "template":
structure = get_template_structure(name, description, author)
elif ext_type == "package":
structure = get_package_structure(name, description, author)
else:
common.die(f"Unknown extension type: {ext_type}")
# Create files
common.log_section(f"Creating {ext_type}: {name}")
for file_path, content in structure.items():
full_path = output_path / file_path
# Create parent directories
full_path.parent.mkdir(parents=True, exist_ok=True)
# Write file
full_path.write_text(content, encoding="utf-8")
common.log_success(f"Created: {file_path}")
common.log_section("Scaffolding Complete")
common.log_info(f"Extension files created in: {output_path}")
common.log_info(f"Extension type: {ext_type}")
common.log_info(f"Extension name: {name}")
# ============================================================================
@@ -379,11 +378,11 @@ def create_extension(
# ============================================================================
def main() -> None:
"""Main entry point."""
parser = argparse.ArgumentParser(
description="Create Joomla extension scaffolding",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
"""Main entry point."""
parser = argparse.ArgumentParser(
description="Create Joomla extension scaffolding",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
# Create a component
%(prog)s component MyComponent "My Component Description" "John Doe"
@@ -400,49 +399,49 @@ Examples:
# Create a package
%(prog)s package mypackage "My Package Description" "John Doe"
"""
)
parser.add_argument(
"type",
choices=["component", "module", "plugin", "template", "package"],
help="Extension type to create"
)
parser.add_argument("name", help="Extension name")
parser.add_argument("description", help="Extension description")
parser.add_argument("author", help="Author name")
parser.add_argument(
"-o", "--output",
default="src",
help="Output directory (default: src)"
)
parser.add_argument(
"--client",
choices=["site", "administrator"],
default="site",
help="Module client (site or administrator)"
)
parser.add_argument(
"--group",
default="system",
help="Plugin group (system, content, user, etc.)"
)
args = parser.parse_args()
try:
create_extension(
ext_type=args.type,
name=args.name,
description=args.description,
author=args.author,
output_dir=args.output,
client=args.client,
group=args.group
)
except Exception as e:
common.log_error(f"Failed to create extension: {e}")
sys.exit(1)
)
parser.add_argument(
"type",
choices=["component", "module", "plugin", "template", "package"],
help="Extension type to create"
)
parser.add_argument("name", help="Extension name")
parser.add_argument("description", help="Extension description")
parser.add_argument("author", help="Author name")
parser.add_argument(
"-o", "--output",
default="src",
help="Output directory (default: src)"
)
parser.add_argument(
"--client",
choices=["site", "administrator"],
default="site",
help="Module client (site or administrator)"
)
parser.add_argument(
"--group",
default="system",
help="Plugin group (system, content, user, etc.)"
)
args = parser.parse_args()
try:
create_extension(
ext_type=args.type,
name=args.name,
description=args.description,
author=args.author,
output_dir=args.output,
client=args.client,
group=args.group
)
except Exception as e:
common.log_error(f"Failed to create extension: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
main()

View File

@@ -33,149 +33,149 @@ BRIEF: Run all validation scripts
import subprocess
import sys
from pathlib import Path
from typing import List, Tuple
from typing import Tuple
# Add lib directory to path
sys.path.insert(0, str(Path(__file__).parent.parent / "lib"))
try:
import common
import common
except ImportError:
print("ERROR: Cannot import required libraries", file=sys.stderr)
sys.exit(1)
print("ERROR: Cannot import required libraries", file=sys.stderr)
sys.exit(1)
# Required validation scripts (must pass)
REQUIRED_SCRIPTS = [
"scripts/validate/manifest.py",
"scripts/validate/xml_wellformed.py",
"scripts/validate/workflows.py",
"scripts/validate/manifest.py",
"scripts/validate/xml_wellformed.py",
"scripts/validate/workflows.py",
]
# Optional validation scripts (failures are warnings)
OPTIONAL_SCRIPTS = [
"scripts/validate/changelog.py",
"scripts/validate/language_structure.py",
"scripts/validate/license_headers.py",
"scripts/validate/no_secrets.py",
"scripts/validate/paths.py",
"scripts/validate/php_syntax.py",
"scripts/validate/tabs.py",
"scripts/validate/version_alignment.py",
"scripts/validate/version_hierarchy.py",
"scripts/validate/changelog.py",
"scripts/validate/language_structure.py",
"scripts/validate/license_headers.py",
"scripts/validate/no_secrets.py",
"scripts/validate/paths.py",
"scripts/validate/php_syntax.py",
"scripts/validate/tabs.py",
"scripts/validate/version_alignment.py",
"scripts/validate/version_hierarchy.py",
]
def run_validation_script(script_path: str) -> Tuple[bool, str]:
"""
Run a validation script.
Args:
script_path: Path to script
Returns:
Tuple of (success, output)
"""
script = Path(script_path)
if not script.exists():
return (False, f"Script not found: {script_path}")
try:
result = subprocess.run(
["python3", str(script)],
capture_output=True,
text=True,
check=False
)
output = result.stdout + result.stderr
success = result.returncode == 0
return (success, output)
except Exception as e:
return (False, f"Error running script: {e}")
"""
Run a validation script.
Args:
script_path: Path to script
Returns:
Tuple of (success, output)
"""
script = Path(script_path)
if not script.exists():
return (False, f"Script not found: {script_path}")
try:
result = subprocess.run(
["python3", str(script)],
capture_output=True,
text=True,
check=False
)
output = result.stdout + result.stderr
success = result.returncode == 0
return (success, output)
except Exception as e:
return (False, f"Error running script: {e}")
def main() -> int:
"""Main entry point."""
common.log_section("Running All Validations")
print()
total_passed = 0
total_failed = 0
total_skipped = 0
# Run required scripts
common.log_info("=== Required Validations ===")
print()
for script in REQUIRED_SCRIPTS:
script_name = Path(script).name
common.log_info(f"Running {script_name}...")
success, output = run_validation_script(script)
if success:
common.log_success(f"{script_name} passed")
total_passed += 1
else:
common.log_error(f"{script_name} FAILED")
if output:
print(output)
total_failed += 1
print()
# Run optional scripts
common.log_info("=== Optional Validations ===")
print()
for script in OPTIONAL_SCRIPTS:
script_name = Path(script).name
if not Path(script).exists():
common.log_warn(f"{script_name} not found (skipped)")
total_skipped += 1
continue
common.log_info(f"Running {script_name}...")
success, output = run_validation_script(script)
if success:
common.log_success(f"{script_name} passed")
total_passed += 1
else:
common.log_warn(f"{script_name} failed (optional)")
if output:
print(output[:500]) # Limit output
total_failed += 1
print()
# Summary
common.log_section("Validation Summary")
common.log_kv("Total Passed", str(total_passed))
common.log_kv("Total Failed", str(total_failed))
common.log_kv("Total Skipped", str(total_skipped))
print()
# Check if any required validations failed
required_failed = sum(
1 for script in REQUIRED_SCRIPTS
if Path(script).exists() and not run_validation_script(script)[0]
)
if required_failed > 0:
common.log_error(f"{required_failed} required validation(s) failed")
return 1
common.log_success("All required validations passed!")
if total_failed > 0:
common.log_warn(f"{total_failed} optional validation(s) failed")
return 0
"""Main entry point."""
common.log_section("Running All Validations")
print()
total_passed = 0
total_failed = 0
total_skipped = 0
# Run required scripts
common.log_info("=== Required Validations ===")
print()
for script in REQUIRED_SCRIPTS:
script_name = Path(script).name
common.log_info(f"Running {script_name}...")
success, output = run_validation_script(script)
if success:
common.log_success(f"{script_name} passed")
total_passed += 1
else:
common.log_error(f"{script_name} FAILED")
if output:
print(output)
total_failed += 1
print()
# Run optional scripts
common.log_info("=== Optional Validations ===")
print()
for script in OPTIONAL_SCRIPTS:
script_name = Path(script).name
if not Path(script).exists():
common.log_warn(f"{script_name} not found (skipped)")
total_skipped += 1
continue
common.log_info(f"Running {script_name}...")
success, output = run_validation_script(script)
if success:
common.log_success(f"{script_name} passed")
total_passed += 1
else:
common.log_warn(f"{script_name} failed (optional)")
if output:
print(output[:500]) # Limit output
total_failed += 1
print()
# Summary
common.log_section("Validation Summary")
common.log_kv("Total Passed", str(total_passed))
common.log_kv("Total Failed", str(total_failed))
common.log_kv("Total Skipped", str(total_skipped))
print()
# Check if any required validations failed
required_failed = sum(
1 for script in REQUIRED_SCRIPTS
if Path(script).exists() and not run_validation_script(script)[0]
)
if required_failed > 0:
common.log_error(f"{required_failed} required validation(s) failed")
return 1
common.log_success("All required validations passed!")
if total_failed > 0:
common.log_warn(f"{total_failed} optional validation(s) failed")
return 0
if __name__ == "__main__":
sys.exit(main())
sys.exit(main())