Skip to content

Commit

Permalink
Fix: 74 error no active provider set please select a provider for thi…
Browse files Browse the repository at this point in the history
…s project (#85)
  • Loading branch information
jahwag authored Oct 23, 2024
1 parent abe141f commit d150ce3
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 1
timeout-minutes: 2
strategy:
fail-fast: false
matrix:
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "claudesync"
version = "0.6.1"
version = "0.6.2"
authors = [
{name = "Jahziah Wagner", email = "[email protected]"},
]
Expand All @@ -27,7 +27,7 @@ dependencies = [
"crontab>=1.0.1",
"python-crontab>=3.2.0",
"Brotli>=1.1.0",
"anthropic>=0.34.2",
"anthropic>=0.37.1",
"cryptography>=3.4.7",
]
keywords = [
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ claudesync>=0.5.4
crontab>=1.0.1
python-crontab>=3.2.0
Brotli>=1.1.0
anthropic>=0.34.2
anthropic>=0.37.1
cryptography>=3.4.7
75 changes: 66 additions & 9 deletions src/claudesync/cli/project.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import click
import os
import logging

from tqdm import tqdm
from ..provider_factory import get_provider
from ..utils import handle_errors, validate_and_get_provider
from ..exceptions import ProviderError, ConfigurationError
from tqdm import tqdm
from .file import file
from .submodule import submodule
from ..syncmanager import retry_on_403

logger = logging.getLogger(__name__)


@click.group()
def project():
Expand Down Expand Up @@ -69,43 +72,91 @@ def create(ctx, name, description, local_path, provider, organization):
f"Project '{new_project['name']}' (uuid: {new_project['uuid']}) has been created successfully."
)

# Update configuration
config.set("active_provider", provider, local=True)
config.set("active_organization_id", organization, local=True)
config.set("active_project_id", new_project["uuid"], local=True)
config.set("active_project_name", new_project["name"], local=True)
config.set("local_path", local_path, local=True)

# Create .claudesync directory and save config
claudesync_dir = os.path.join(local_path, ".claudesync")
os.makedirs(claudesync_dir, exist_ok=True)
config_file_path = os.path.join(claudesync_dir, "config.local.json")
config._save_local_config()

click.echo(
f"\nProject setup complete. You can now start syncing files with this project. "
f"URL: https://claude.ai/project/{new_project['uuid']}"
)
click.echo("\nProject created:")
click.echo(f" - Project location: {local_path}")
click.echo(f" - Project config location: {config_file_path}")
click.echo(f" - Remote URL: https://claude.ai/project/{new_project['uuid']}")

except (ProviderError, ConfigurationError) as e:
click.echo(f"Failed to create project: {str(e)}")


@project.command()
@click.option(
"-a",
"--all",
"archive_all",
is_flag=True,
help="Archive all active projects",
)
@click.option(
"-y",
"--yes",
is_flag=True,
help="Skip confirmation prompt",
)
@click.pass_obj
@handle_errors
def archive(config):
"""Archive an existing project."""
def archive(config, archive_all, yes):
"""Archive existing projects."""
provider = validate_and_get_provider(config)
active_organization_id = config.get("active_organization_id")
projects = provider.get_projects(active_organization_id, include_archived=False)

if not projects:
click.echo("No active projects found.")
return

if archive_all:
if not yes:
click.echo("The following projects will be archived:")
for project in projects:
click.echo(f" - {project['name']} (ID: {project['id']})")
if not click.confirm("Are you sure you want to archive all projects?"):
click.echo("Operation cancelled.")
return

with click.progressbar(
projects,
label="Archiving projects",
item_show_func=lambda p: p["name"] if p else "",
) as bar:
for project in bar:
try:
provider.archive_project(active_organization_id, project["id"])
except Exception as e:
click.echo(
f"\nFailed to archive project '{project['name']}': {str(e)}"
)

click.echo("\nArchive operation completed.")
return

single_project_archival(projects, yes, provider, active_organization_id)


def single_project_archival(projects, yes, provider, active_organization_id):
click.echo("Available projects to archive:")
for idx, project in enumerate(projects, 1):
click.echo(f" {idx}. {project['name']} (ID: {project['id']})")

selection = click.prompt("Enter the number of the project to archive", type=int)
if 1 <= selection <= len(projects):
selected_project = projects[selection - 1]
if click.confirm(
if yes or click.confirm(
f"Are you sure you want to archive the project '{selected_project['name']}'? "
f"Archived projects cannot be modified but can still be viewed."
):
Expand Down Expand Up @@ -191,7 +242,13 @@ def set(ctx, show_all, provider):

# Create .claudesync directory in the current working directory if it doesn't exist
os.makedirs(".claudesync", exist_ok=True)
click.echo(f"Ensured .claudesync directory exists in {os.getcwd()}")
claudesync_dir = os.path.abspath(".claudesync")
config_file_path = os.path.join(claudesync_dir, "config.local.json")
config._save_local_config()

click.echo("\nProject created:")
click.echo(f" - Project location: {os.getcwd()}")
click.echo(f" - Project config location: {config_file_path}")
else:
click.echo("Invalid selection. Please try again.")

Expand Down
13 changes: 8 additions & 5 deletions src/claudesync/configmanager/file_config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,16 @@ def _find_local_config_dir(self, max_depth=100):
current_dir = Path.cwd()
root_dir = Path(current_dir.root)
home_dir = Path.home()
depth = 0 # Initialize depth counter
depth = 0

while current_dir != root_dir:
claudesync_dir = current_dir / ".claudesync"
if claudesync_dir.is_dir() and claudesync_dir != home_dir / ".claudesync":
return current_dir

current_dir = current_dir.parent
depth += 1 # Increment depth counter
depth += 1

# Sanity check: stop if max_depth is reached
if depth > max_depth:
return None

Expand Down Expand Up @@ -132,9 +131,12 @@ def set(self, key, value, local=False):
local (bool): If True, sets the value in the local configuration. Otherwise, sets it in the global configuration.
"""
if local:
if not self.local_config_dir:
self.local_config_dir = Path.cwd()
# Update local_config_dir when setting local_path
if key == "local_path":
self.local_config_dir = Path(value)
# Create .claudesync directory in the specified path
(self.local_config_dir / ".claudesync").mkdir(exist_ok=True)

self.local_config[key] = value
self._save_local_config()
else:
Expand All @@ -159,6 +161,7 @@ def _save_local_config(self):
local_config_file = (
self.local_config_dir / ".claudesync" / "config.local.json"
)
local_config_file.parent.mkdir(exist_ok=True)
with open(local_config_file, "w") as f:
json.dump(self.local_config, f, indent=2)

Expand Down
20 changes: 10 additions & 10 deletions src/claudesync/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,26 +289,26 @@ def validate_and_get_provider(config, require_org=True, require_project=False):
or if require_project is True and no active project ID is set.
ProviderError: If the session key has expired.
"""
active_provider = config.get_active_provider()
if not active_provider:
if require_org and not config.get("active_organization_id"):
raise ConfigurationError(
"No active provider set. Please select a provider for this project."
"No active organization set. Please select an organization (claudesync organization set)."
)

session_key, session_key_expiry = config.get_session_key(active_provider)
if not session_key:
if require_project and not config.get("active_project_id"):
raise ConfigurationError(
f"No valid session key found for {active_provider}. Please log in again."
"No active project set. Please select or create a project (claudesync project set)."
)

if require_org and not config.get("active_organization_id"):
active_provider = config.get_active_provider()
if not active_provider:
raise ConfigurationError(
"No active organization set. Please select an organization."
"No active provider set. Please select a provider for this project."
)

if require_project and not config.get("active_project_id"):
session_key, session_key_expiry = config.get_session_key(active_provider)
if not session_key:
raise ConfigurationError(
"No active project set. Please select or create a project."
f"No valid session key found for {active_provider}. Please log in again."
)

return get_provider(config, active_provider)
Expand Down
14 changes: 6 additions & 8 deletions tests/test_happy_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ def setUp(self):

@patch("claudesync.utils.get_local_files")
def test_happy_path(self, mock_get_local_files):

# Mock the API calls
mock_get_local_files.return_value = {"test.txt": "content_hash"}

Expand Down Expand Up @@ -58,19 +57,18 @@ def test_happy_path(self, mock_get_local_files):
obj=self.config,
)
self.assertEqual(result.exit_code, 0)

self.assertIn(
"Project 'New Project' (uuid: new_proj) has been created successfully."
"\n\nProject setup complete. You can now start syncing files with this project. "
"URL: https://claude.ai/project/new_proj\n",
"Project 'New Project' (uuid: new_proj) has been created successfully",
result.output,
)
self.assertIn("Project created:", result.output)
self.assertIn("Project location:", result.output)
self.assertIn("Project config location:", result.output)
self.assertIn("Remote URL: https://claude.ai/project/new_proj", result.output)

# Push project
result = self.runner.invoke(cli, ["push"], obj=self.config)
print("Login output:", result.output)
print("Login exit code:", result.exit_code)
if result.exception:
print("Login exception:", result.exception)
self.assertEqual(result.exit_code, 0)
self.assertIn("Main project 'New Project' synced successfully", result.output)

Expand Down

0 comments on commit d150ce3

Please sign in to comment.