ffx-cli 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/PKG-INFO +2 -1
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/config.py +8 -1
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/pyproject.toml +2 -2
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_auth.py +8 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_get.py +2 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_list.py +2 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_config.py +35 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/uv.lock +2 -2
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/.github/workflows/ci.yml +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/.github/workflows/publish.yml +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/.gitignore +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/CLAUDE.md +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/README.md +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/__init__.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/__main__.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/api_client.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/__init__.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/action_items.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/auth.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/brief.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/export.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/get.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/list_cmd.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/search.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/speaker.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/summary.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/topics.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/transcript.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/commands/week.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/models.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/ffx/output.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/__init__.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/conftest.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_api_client.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/__init__.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_action_items.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_brief.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_export.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_search.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_speaker.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_summary.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_topics.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_transcript.py +0 -0
- {ffx_cli-0.1.0 → ffx_cli-0.1.2}/tests/test_commands/test_week.py +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ffx-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Fireflies.ai CLI
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: gql[httpx]>=3.5
|
|
7
|
+
Requires-Dist: python-dotenv>=1.0
|
|
7
8
|
Requires-Dist: pyyaml>=6.0
|
|
8
9
|
Requires-Dist: rich>=13.7
|
|
9
10
|
Requires-Dist: typer>=0.12
|
|
@@ -3,6 +3,7 @@ import stat
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
import yaml
|
|
6
|
+
from dotenv import dotenv_values
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def _ffx_home() -> Path:
|
|
@@ -39,7 +40,13 @@ class Config:
|
|
|
39
40
|
|
|
40
41
|
@property
|
|
41
42
|
def api_key(self) -> str | None:
|
|
42
|
-
|
|
43
|
+
env_key = os.environ.get("FIREFLIES_API_KEY")
|
|
44
|
+
if env_key:
|
|
45
|
+
return env_key
|
|
46
|
+
dotenv_key = dotenv_values(".env").get("FIREFLIES_API_KEY")
|
|
47
|
+
if dotenv_key:
|
|
48
|
+
return dotenv_key
|
|
49
|
+
return self.get("api_key")
|
|
43
50
|
|
|
44
51
|
@property
|
|
45
52
|
def home(self) -> Path:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ffx-cli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "Fireflies.ai CLI"
|
|
5
5
|
requires-python = ">=3.11"
|
|
6
6
|
dependencies = [
|
|
@@ -8,6 +8,7 @@ dependencies = [
|
|
|
8
8
|
"gql[httpx]>=3.5",
|
|
9
9
|
"rich>=13.7",
|
|
10
10
|
"pyyaml>=6.0",
|
|
11
|
+
"python-dotenv>=1.0",
|
|
11
12
|
]
|
|
12
13
|
|
|
13
14
|
[project.scripts]
|
|
@@ -26,5 +27,4 @@ dev = [
|
|
|
26
27
|
"pytest-cov>=5.0",
|
|
27
28
|
"respx>=0.21",
|
|
28
29
|
"httpx>=0.27",
|
|
29
|
-
"python-dotenv>=1.2.2",
|
|
30
30
|
]
|
|
@@ -6,6 +6,8 @@ runner = CliRunner()
|
|
|
6
6
|
|
|
7
7
|
def test_auth_stores_key(tmp_path, monkeypatch):
|
|
8
8
|
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
9
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
10
|
+
monkeypatch.chdir(tmp_path)
|
|
9
11
|
result = runner.invoke(app, ["auth"], input="test-api-key-123\n")
|
|
10
12
|
assert result.exit_code == 0
|
|
11
13
|
assert "API key saved" in result.output
|
|
@@ -13,12 +15,16 @@ def test_auth_stores_key(tmp_path, monkeypatch):
|
|
|
13
15
|
|
|
14
16
|
def test_auth_empty_key_rejected(tmp_path, monkeypatch):
|
|
15
17
|
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
18
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
19
|
+
monkeypatch.chdir(tmp_path)
|
|
16
20
|
result = runner.invoke(app, ["auth"], input="\n")
|
|
17
21
|
assert result.exit_code == 1
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
def test_auth_shows_confirmation_when_key_exists(tmp_path, monkeypatch):
|
|
21
25
|
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
26
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
27
|
+
monkeypatch.chdir(tmp_path)
|
|
22
28
|
runner.invoke(app, ["auth"], input="first-key\n")
|
|
23
29
|
result = runner.invoke(app, ["auth"], input="y\nnew-key\n")
|
|
24
30
|
assert result.exit_code == 0
|
|
@@ -26,6 +32,8 @@ def test_auth_shows_confirmation_when_key_exists(tmp_path, monkeypatch):
|
|
|
26
32
|
|
|
27
33
|
def test_auth_key_stored_with_correct_permissions(tmp_path, monkeypatch):
|
|
28
34
|
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
35
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
36
|
+
monkeypatch.chdir(tmp_path)
|
|
29
37
|
runner.invoke(app, ["auth"], input="test-key\n")
|
|
30
38
|
config_file = tmp_path / "config.yaml"
|
|
31
39
|
assert config_file.exists()
|
|
@@ -56,6 +56,8 @@ def test_get_json_mode(tmp_path, monkeypatch):
|
|
|
56
56
|
|
|
57
57
|
def test_get_no_api_key(tmp_path, monkeypatch):
|
|
58
58
|
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
59
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
60
|
+
monkeypatch.chdir(tmp_path)
|
|
59
61
|
result = runner.invoke(app, ["get", "abc123"])
|
|
60
62
|
assert result.exit_code == 2
|
|
61
63
|
assert "ffx auth" in result.output
|
|
@@ -75,6 +75,8 @@ def test_list_with_multiple_participants(tmp_path, monkeypatch):
|
|
|
75
75
|
|
|
76
76
|
def test_list_no_api_key(tmp_path, monkeypatch):
|
|
77
77
|
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
78
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
79
|
+
monkeypatch.chdir(tmp_path)
|
|
78
80
|
result = runner.invoke(app, ["list"])
|
|
79
81
|
assert result.exit_code == 2
|
|
80
82
|
assert "ffx auth" in result.output
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
from ffx.config import Config
|
|
2
4
|
|
|
3
5
|
|
|
@@ -26,6 +28,8 @@ def test_missing_key_returns_none(tmp_path, monkeypatch):
|
|
|
26
28
|
|
|
27
29
|
def test_api_key_property(tmp_path, monkeypatch):
|
|
28
30
|
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
31
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
32
|
+
monkeypatch.chdir(tmp_path)
|
|
29
33
|
config = Config()
|
|
30
34
|
assert config.api_key is None
|
|
31
35
|
config.set("api_key", "sk-abc")
|
|
@@ -45,3 +49,34 @@ def test_env_var_used_when_no_config(tmp_path, monkeypatch):
|
|
|
45
49
|
monkeypatch.setenv("FIREFLIES_API_KEY", "env-key-only")
|
|
46
50
|
config = Config()
|
|
47
51
|
assert config.api_key == "env-key-only"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_dotenv_file_loaded(tmp_path, monkeypatch):
|
|
55
|
+
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
56
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
57
|
+
dotenv_file = tmp_path / ".env"
|
|
58
|
+
dotenv_file.write_text("FIREFLIES_API_KEY=dotenv-key-456\n")
|
|
59
|
+
monkeypatch.chdir(tmp_path)
|
|
60
|
+
config = Config()
|
|
61
|
+
assert config.api_key == "dotenv-key-456"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_env_var_overrides_dotenv(tmp_path, monkeypatch):
|
|
65
|
+
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
66
|
+
monkeypatch.setenv("FIREFLIES_API_KEY", "explicit-env-key")
|
|
67
|
+
dotenv_file = tmp_path / ".env"
|
|
68
|
+
dotenv_file.write_text("FIREFLIES_API_KEY=dotenv-key-456\n")
|
|
69
|
+
monkeypatch.chdir(tmp_path)
|
|
70
|
+
config = Config()
|
|
71
|
+
assert config.api_key == "explicit-env-key"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_dotenv_overrides_config_yaml(tmp_path, monkeypatch):
|
|
75
|
+
monkeypatch.setenv("FFX_HOME", str(tmp_path))
|
|
76
|
+
monkeypatch.delenv("FIREFLIES_API_KEY", raising=False)
|
|
77
|
+
config = Config()
|
|
78
|
+
config.set("api_key", "yaml-key")
|
|
79
|
+
dotenv_file = tmp_path / ".env"
|
|
80
|
+
dotenv_file.write_text("FIREFLIES_API_KEY=dotenv-key-789\n")
|
|
81
|
+
monkeypatch.chdir(tmp_path)
|
|
82
|
+
assert config.api_key == "dotenv-key-789"
|
|
@@ -173,6 +173,7 @@ version = "0.1.0"
|
|
|
173
173
|
source = { editable = "." }
|
|
174
174
|
dependencies = [
|
|
175
175
|
{ name = "gql", extra = ["httpx"] },
|
|
176
|
+
{ name = "python-dotenv" },
|
|
176
177
|
{ name = "pyyaml" },
|
|
177
178
|
{ name = "rich" },
|
|
178
179
|
{ name = "typer" },
|
|
@@ -183,13 +184,13 @@ dev = [
|
|
|
183
184
|
{ name = "httpx" },
|
|
184
185
|
{ name = "pytest" },
|
|
185
186
|
{ name = "pytest-cov" },
|
|
186
|
-
{ name = "python-dotenv" },
|
|
187
187
|
{ name = "respx" },
|
|
188
188
|
]
|
|
189
189
|
|
|
190
190
|
[package.metadata]
|
|
191
191
|
requires-dist = [
|
|
192
192
|
{ name = "gql", extras = ["httpx"], specifier = ">=3.5" },
|
|
193
|
+
{ name = "python-dotenv", specifier = ">=1.0" },
|
|
193
194
|
{ name = "pyyaml", specifier = ">=6.0" },
|
|
194
195
|
{ name = "rich", specifier = ">=13.7" },
|
|
195
196
|
{ name = "typer", specifier = ">=0.12" },
|
|
@@ -200,7 +201,6 @@ dev = [
|
|
|
200
201
|
{ name = "httpx", specifier = ">=0.27" },
|
|
201
202
|
{ name = "pytest", specifier = ">=8.1" },
|
|
202
203
|
{ name = "pytest-cov", specifier = ">=5.0" },
|
|
203
|
-
{ name = "python-dotenv", specifier = ">=1.2.2" },
|
|
204
204
|
{ name = "respx", specifier = ">=0.21" },
|
|
205
205
|
]
|
|
206
206
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|