Update pip package to create share directory and copy files

- Add data_files to setup.py for installing main.py, requirements.txt, and JSON configs
- Update aisbf script to create venv in share directory if it doesn't exist
- Fix pyproject.toml warnings: add dynamic fields, update license format, remove deprecated classifier
- Update MANIFEST.in to include pyproject.toml
- Remove manual file copying from setup.py (now handled by data_files)
- Remove unused imports (shutil, subprocess)
parent 3cbe1fe0
...@@ -2,5 +2,6 @@ include README.md ...@@ -2,5 +2,6 @@ include README.md
include LICENSE.txt include LICENSE.txt
include requirements.txt include requirements.txt
include main.py include main.py
include pyproject.toml
recursive-include config *.json recursive-include config *.json
recursive-include aisbf *.py recursive-include aisbf *.py
\ No newline at end of file
...@@ -7,7 +7,7 @@ name = "aisbf" ...@@ -7,7 +7,7 @@ name = "aisbf"
version = "0.1.0" version = "0.1.0"
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 = {text = "GPL-3.0-or-later"} license = "GPL-3.0-or-later"
requires-python = ">=3.8" requires-python = ">=3.8"
authors = [ authors = [
{name = "AISBF Contributors"}, {name = "AISBF Contributors"},
...@@ -31,7 +31,6 @@ classifiers = [ ...@@ -31,7 +31,6 @@ classifiers = [
"Development Status :: 3 - Alpha", "Development Status :: 3 - Alpha",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries :: Python Modules",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
...@@ -40,6 +39,7 @@ classifiers = [ ...@@ -40,6 +39,7 @@ classifiers = [
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Operating System :: OS Independent", "Operating System :: OS Independent",
] ]
dynamic = ["dependencies", "scripts"]
[project.urls] [project.urls]
Homepage = "https://git.nexlab.net/nexlab/aisbf.git" Homepage = "https://git.nexlab.net/nexlab/aisbf.git"
......
...@@ -25,9 +25,7 @@ from setuptools import setup, find_packages, Command ...@@ -25,9 +25,7 @@ from setuptools import setup, find_packages, Command
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
import shutil
import sys import sys
import subprocess
# Read the contents of README file # Read the contents of README file
this_directory = Path(__file__).parent this_directory = Path(__file__).parent
...@@ -50,107 +48,22 @@ class InstallCommand(_install): ...@@ -50,107 +48,22 @@ class InstallCommand(_install):
self.user = True self.user = True
def run(self): def run(self):
# Run the standard install # Run the standard install (this will install data_files to share directory)
_install.run(self) _install.run(self)
# Install config files
self._install_config_files()
# Install main.py to share directory
self._install_main_file()
# Create venv and install requirements
self._create_venv_and_install_requirements()
# Install the aisbf script # Install the aisbf script
self._install_aisbf_script() self._install_aisbf_script()
def _create_venv_and_install_requirements(self):
"""Create a virtual environment and install requirements"""
# Determine installation directory
if '--user' in sys.argv or os.geteuid() != 0:
# User installation - use ~/.local
install_dir = Path.home() / '.local'
else:
# System installation - use /usr/local
install_dir = Path('/usr/local')
venv_dir = install_dir / 'aisbf-venv'
# Create venv if it doesn't exist
if not venv_dir.exists():
print(f"Creating virtual environment at {venv_dir}")
subprocess.run([sys.executable, '-m', 'venv', str(venv_dir)], check=True)
else:
print(f"Virtual environment already exists at {venv_dir}")
# Install requirements in the venv
pip_path = venv_dir / 'bin' / 'pip'
requirements_path = this_directory / 'requirements.txt'
if requirements_path.exists():
print(f"Installing requirements from {requirements_path}")
subprocess.run([str(pip_path), 'install', '-r', str(requirements_path)], check=True)
else:
print("No requirements.txt found, skipping dependency installation")
def _install_config_files(self):
"""Install config files to the appropriate share directory"""
# Determine the share directory
if '--user' in sys.argv or os.geteuid() != 0:
# User installation - use ~/.local/share
share_dir = Path.home() / '.local' / 'share' / 'aisbf'
else:
# System installation - use /usr/local/share
share_dir = Path('/usr/local/share/aisbf')
# Create the share directory if it doesn't exist
share_dir.mkdir(parents=True, exist_ok=True)
# Copy config files
config_dir = this_directory / 'config'
if config_dir.exists():
for config_file in config_dir.glob('*.json'):
dst = share_dir / config_file.name
shutil.copy2(config_file, dst)
print(f"Installed config file {config_file.name} to {dst}")
else:
print(f"Warning: Config directory {config_dir} not found")
def _install_main_file(self):
"""Install main.py to the appropriate share directory"""
# Determine the share directory
if '--user' in sys.argv or os.geteuid() != 0:
# User installation - use ~/.local/share
share_dir = Path.home() / '.local' / 'share' / 'aisbf'
else:
# System installation - use /usr/local/share
share_dir = Path('/usr/local/share/aisbf')
# Create the share directory if it doesn't exist
share_dir.mkdir(parents=True, exist_ok=True)
# Copy main.py
main_file = this_directory / 'main.py'
if main_file.exists():
dst = share_dir / 'main.py'
shutil.copy2(main_file, dst)
print(f"Installed main.py to {dst}")
else:
print(f"Warning: main.py not found")
def _install_aisbf_script(self): def _install_aisbf_script(self):
"""Install the aisbf script that uses the venv""" """Install the aisbf script that uses the venv"""
# Determine the installation directory # Determine the installation directory
if '--user' in sys.argv or os.geteuid() != 0: if '--user' in sys.argv or os.geteuid() != 0:
# User installation - use ~/.local/bin # User installation - use ~/.local/bin
bin_dir = Path.home() / '.local' / 'bin' bin_dir = Path.home() / '.local' / 'bin'
venv_dir = Path.home() / '.local' / 'aisbf-venv'
share_dir = Path.home() / '.local' / 'share' / 'aisbf' share_dir = Path.home() / '.local' / 'share' / 'aisbf'
else: else:
# System installation - use /usr/local/bin # System installation - use /usr/local/bin
bin_dir = Path('/usr/local/bin') bin_dir = Path('/usr/local/bin')
venv_dir = Path('/usr/local') / 'aisbf-venv'
share_dir = Path('/usr/local/share/aisbf') share_dir = Path('/usr/local/share/aisbf')
# Create the bin directory if it doesn't exist # Create the bin directory if it doesn't exist
...@@ -162,11 +75,28 @@ class InstallCommand(_install): ...@@ -162,11 +75,28 @@ class InstallCommand(_install):
# This script manages the AISBF server using the installed virtual environment # This script manages the AISBF server using the installed virtual environment
PIDFILE="/tmp/aisbf.pid" PIDFILE="/tmp/aisbf.pid"
VENV_DIR="{venv_dir}"
SHARE_DIR="{share_dir}" SHARE_DIR="{share_dir}"
VENV_DIR="$SHARE_DIR/venv"
# Function to create venv if it doesn't exist
ensure_venv() {{
if [ ! -d "$VENV_DIR" ]; then
echo "Creating virtual environment at $VENV_DIR"
python3 -m venv "$VENV_DIR"
# Install requirements if requirements.txt exists
if [ -f "$SHARE_DIR/requirements.txt" ]; then
echo "Installing requirements from $SHARE_DIR/requirements.txt"
"$VENV_DIR/bin/pip" install -r "$SHARE_DIR/requirements.txt"
fi
fi
}}
# Function to start the server # Function to start the server
start_server() {{ start_server() {{
# Ensure venv exists
ensure_venv
# Activate the virtual environment # Activate the virtual environment
source $VENV_DIR/bin/activate source $VENV_DIR/bin/activate
...@@ -191,6 +121,9 @@ start_daemon() {{ ...@@ -191,6 +121,9 @@ start_daemon() {{
fi fi
fi fi
# Ensure venv exists
ensure_venv
# Start in background with nohup # Start in background with nohup
nohup bash -c "source $VENV_DIR/bin/activate && cd $SHARE_DIR && uvicorn main:app --host 0.0.0.0 --port 8000" > /dev/null 2>&1 & nohup bash -c "source $VENV_DIR/bin/activate && cd $SHARE_DIR && uvicorn main:app --host 0.0.0.0 --port 8000" > /dev/null 2>&1 &
PID=$! PID=$!
...@@ -288,6 +221,15 @@ setup( ...@@ -288,6 +221,15 @@ setup(
package_data={ package_data={
"aisbf": ["*.json"], "aisbf": ["*.json"],
}, },
data_files=[
# Install to /usr/local/share/aisbf (system-wide)
('share/aisbf', [
'main.py',
'requirements.txt',
'config/providers.json',
'config/rotations.json',
]),
],
entry_points={ entry_points={
"console_scripts": [ "console_scripts": [
"aisbf=main:main", "aisbf=main:main",
......
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