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
include requirements.txt
include main.py
include pyproject.toml
include aisbf.sh
include cli.py
recursive-include config *.json
recursive-include config *.md
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"
[project]
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"
readme = "README.md"
license = "GPL-3.0-or-later"
......@@ -49,6 +49,7 @@ Documentation = "https://git.nexlab.net/nexlab/aisbf.git"
[tool.setuptools]
packages = ["aisbf"]
py-modules = ["cli"]
[tool.setuptools.package-data]
aisbf = ["*.json"]
\ No newline at end of file
......@@ -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!
"""
from setuptools import setup, find_packages, Command
from setuptools import setup, find_packages
from setuptools.command.install import install as _install
from pathlib import Path
import os
......@@ -38,7 +38,7 @@ if (this_directory / "requirements.txt").exists():
requirements = [line.strip() for line in f if line.strip() and not line.startswith("#")]
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):
_install.initialize_options(self)
......@@ -47,43 +47,9 @@ class InstallCommand(_install):
print("Installing as non-root user. Adding --user flag for user-local installation.")
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(
name="aisbf",
version="0.2.0",
version="0.2.2",
author="AISBF Contributors",
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",
......@@ -111,7 +77,7 @@ setup(
"aisbf": ["*.json"],
},
data_files=[
# Install to /usr/share/aisbf (system-wide)
# Install to /usr/local/share/aisbf (system-wide)
('share/aisbf', [
'main.py',
'requirements.txt',
......@@ -132,7 +98,7 @@ setup(
],
entry_points={
"console_scripts": [
"aisbf=main:main",
"aisbf=cli:main",
],
},
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