Fix entry point to avoid importing aisbf package dependencies

- Move cli.py from aisbf/ to root directory to prevent package imports
- Update setup.py entry point from aisbf.cli:main to cli:main
- Update pyproject.toml to include cli.py as a py-module
- Update MANIFEST.in to include cli.py in distribution
- Update cli.py to look for aisbf.sh in /usr/local/share/aisbf/ or ~/.local/share/aisbf/
- Add KeyboardInterrupt handler for graceful Ctrl-C exit
- Update setup.py data_files to install aisbf.sh in correct directory
parent 1a2d14a2
...@@ -3,5 +3,8 @@ include LICENSE.txt ...@@ -3,5 +3,8 @@ include LICENSE.txt
include requirements.txt include requirements.txt
include main.py include main.py
include pyproject.toml include pyproject.toml
include aisbf.sh
include cli.py
recursive-include config *.json recursive-include config *.json
recursive-include config *.md
recursive-include aisbf *.py recursive-include aisbf *.py
\ No newline at end of file
"""
Copyright (C) 2026 Stefy Lanza <stefy@nexlab.net>
AISBF - AI Service Broker Framework || AI Should Be Free
Python CLI wrapper that calls the aisbf.sh shell script.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Why did the programmer quit his job? Because he didn't get arrays!
"""
import os
import sys
import subprocess
from pathlib import Path
def main():
"""Main entry point for the aisbf CLI - calls the aisbf.sh shell script"""
# Determine the correct script path at runtime
# Check for system installation first (/usr/local/share/aisbf/aisbf.sh)
script_path = Path("/usr/local/share/aisbf/aisbf.sh")
if not script_path.exists():
# Fall back to user installation (~/.local/share/aisbf/aisbf.sh)
script_path = Path.home() / ".local" / "share" / "aisbf" / "aisbf.sh"
# Check if the script exists
if not script_path.exists():
print(f"Error: AISBF script not found at {script_path}", file=sys.stderr)
print("Please ensure AISBF is properly installed.", file=sys.stderr)
print(f"Expected locations:", file=sys.stderr)
print(f" - /usr/local/share/aisbf/aisbf.sh (system-wide)", file=sys.stderr)
print(f" - ~/.local/share/aisbf/aisbf.sh (user installation)", file=sys.stderr)
sys.exit(1)
# Execute the shell script with all arguments passed to this Python script
try:
# Use subprocess to run the shell script
result = subprocess.run(
[str(script_path)] + sys.argv[1:],
check=False
)
# Exit with the same exit code as the shell script
sys.exit(result.returncode)
except KeyboardInterrupt:
# Handle Ctrl-C gracefully
sys.exit(130) # Standard exit code for SIGINT (128 + 2)
except Exception as e:
print(f"Error executing AISBF script: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
\ No newline at end of file
...@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" ...@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "aisbf" name = "aisbf"
version = "0.2.0" version = "0.2.2"
description = "AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations" description = "AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations"
readme = "README.md" readme = "README.md"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
...@@ -49,6 +49,7 @@ Documentation = "https://git.nexlab.net/nexlab/aisbf.git" ...@@ -49,6 +49,7 @@ Documentation = "https://git.nexlab.net/nexlab/aisbf.git"
[tool.setuptools] [tool.setuptools]
packages = ["aisbf"] packages = ["aisbf"]
py-modules = ["cli"]
[tool.setuptools.package-data] [tool.setuptools.package-data]
aisbf = ["*.json"] aisbf = ["*.json"]
\ No newline at end of file
...@@ -21,7 +21,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. ...@@ -21,7 +21,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Why did the programmer quit his job? Because he didn't get arrays! Why did the programmer quit his job? Because he didn't get arrays!
""" """
from setuptools import setup, find_packages, Command from setuptools import setup, find_packages
from setuptools.command.install import install as _install from setuptools.command.install import install as _install
from pathlib import Path from pathlib import Path
import os import os
...@@ -38,7 +38,7 @@ if (this_directory / "requirements.txt").exists(): ...@@ -38,7 +38,7 @@ if (this_directory / "requirements.txt").exists():
requirements = [line.strip() for line in f if line.strip() and not line.startswith("#")] requirements = [line.strip() for line in f if line.strip() and not line.startswith("#")]
class InstallCommand(_install): class InstallCommand(_install):
"""Custom install command that also installs the aisbf script and creates venv""" """Custom install command that adds --user flag for non-root users"""
def initialize_options(self): def initialize_options(self):
_install.initialize_options(self) _install.initialize_options(self)
...@@ -47,43 +47,9 @@ class InstallCommand(_install): ...@@ -47,43 +47,9 @@ class InstallCommand(_install):
print("Installing as non-root user. Adding --user flag for user-local installation.") print("Installing as non-root user. Adding --user flag for user-local installation.")
self.user = True self.user = True
def run(self):
# Run the standard install (this will install data_files to share directory)
_install.run(self)
# Install the aisbf script
self._install_aisbf_script()
def _install_aisbf_script(self):
"""Install the aisbf script that uses the venv"""
# Determine the installation directory
if '--user' in sys.argv or os.geteuid() != 0:
# User installation - use ~/.local/bin
bin_dir = Path.home() / '.local' / 'bin'
share_dir = Path.home() / '.local' / 'share' / 'aisbf'
else:
# System installation - use /usr/local/bin
bin_dir = Path('/usr/local/bin')
share_dir = Path('/usr/share/aisbf')
# Create the bin directory if it doesn't exist
bin_dir.mkdir(parents=True, exist_ok=True)
# Copy the aisbf.sh script from the share directory to the bin directory
src = share_dir / 'aisbf.sh'
dst = bin_dir / 'aisbf'
# Copy the script
import shutil
shutil.copy(src, dst)
# Make it executable
os.chmod(dst, 0o755)
print(f"Installed 'aisbf' script to {dst}")
setup( setup(
name="aisbf", name="aisbf",
version="0.2.0", version="0.2.2",
author="AISBF Contributors", author="AISBF Contributors",
author_email="stefy@nexlab.net", author_email="stefy@nexlab.net",
description="AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations", description="AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations",
...@@ -111,7 +77,7 @@ setup( ...@@ -111,7 +77,7 @@ setup(
"aisbf": ["*.json"], "aisbf": ["*.json"],
}, },
data_files=[ data_files=[
# Install to /usr/share/aisbf (system-wide) # Install to /usr/local/share/aisbf (system-wide)
('share/aisbf', [ ('share/aisbf', [
'main.py', 'main.py',
'requirements.txt', 'requirements.txt',
...@@ -132,7 +98,7 @@ setup( ...@@ -132,7 +98,7 @@ setup(
], ],
entry_points={ entry_points={
"console_scripts": [ "console_scripts": [
"aisbf=main:main", "aisbf=cli:main",
], ],
}, },
cmdclass={ cmdclass={
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment