feat: v0.2.0 — Joplin import, ChatGPT Projects, --project filter
Core features: - Add `joplin` command: syncs exported Markdown to Joplin via local REST API - Notebooks auto-created per provider+project (e.g. "ChatGPT - My Project") - Idempotent: notes updated (not duplicated) on re-run; note ID tracked in manifest - Add `--project` filter to `export` and `list` commands (substring or 'none') - Add ChatGPT Projects support via CHATGPT_PROJECT_IDS env var Config: - Add JOPLIN_API_TOKEN, JOPLIN_API_URL, JOPLIN_REQUEST_TIMEOUT - Version now read from importlib.metadata (single source of truth: pyproject.toml) - Bump version to 0.2.0 Quality: - Explicit Timeout handling in JoplinClient with actionable error messages - token validation (validate_token) separate from connectivity (ping) - Remove debug_auth.py, debug_claude.py, and untracked .har file - Add *.har to .gitignore (may contain auth cookies/session tokens) - Update README, CHANGELOG, FUTURE.md to reflect v0.2.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+17
-2
@@ -11,6 +11,21 @@ import requests
|
||||
|
||||
from src.utils import redact_secrets
|
||||
|
||||
# curl_cffi has its own exception hierarchy (rooted at CurlError → OSError),
|
||||
# completely separate from requests.exceptions. Import them so _make_request
|
||||
# can catch both when a curl_cffi session is in use.
|
||||
try:
|
||||
from curl_cffi.requests.exceptions import (
|
||||
HTTPError as _CurlHTTPError,
|
||||
ConnectionError as _CurlConnectionError,
|
||||
Timeout as _CurlTimeout,
|
||||
)
|
||||
except ImportError:
|
||||
# Fall back to requests types — catching them twice is harmless.
|
||||
_CurlHTTPError = requests.HTTPError # type: ignore[misc,assignment]
|
||||
_CurlConnectionError = requests.ConnectionError # type: ignore[misc,assignment]
|
||||
_CurlTimeout = requests.Timeout # type: ignore[misc,assignment]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Request timeouts (connect, read) in seconds
|
||||
@@ -271,7 +286,7 @@ class BaseProvider(ABC):
|
||||
except ProviderError:
|
||||
raise
|
||||
|
||||
except (requests.ConnectionError, requests.Timeout) as e:
|
||||
except (requests.ConnectionError, requests.Timeout, _CurlConnectionError, _CurlTimeout) as e:
|
||||
last_exc = e
|
||||
if attempt > MAX_RETRIES:
|
||||
raise ProviderError(
|
||||
@@ -293,7 +308,7 @@ class BaseProvider(ABC):
|
||||
)
|
||||
time.sleep(wait)
|
||||
|
||||
except requests.HTTPError as e:
|
||||
except (requests.HTTPError, _CurlHTTPError) as e:
|
||||
raise ProviderError(
|
||||
self.provider_name, f"{method} {url}", e
|
||||
) from e
|
||||
|
||||
Reference in New Issue
Block a user