runspec-gitlab-core 0.4.0__tar.gz → 0.5.0__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.
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to `runspec-gitlab-core` are documented here.
4
4
 
5
+ ## [0.5.0] — 2026-10-25
6
+
7
+ - `search_projects` can list the token user's projects: `search` is now
8
+ optional, and with no term the call asks for member projects only (listing
9
+ every visible project on gitlab.com is no use). A term also matches the
10
+ group/namespace path (`search_namespaces`), so a username or group name finds
11
+ the projects under it. New `owned` parameter limits results to owned projects.
12
+
5
13
  ## [0.4.0] — 2026-10-25
6
14
 
7
15
  - `config_from_env` reads the token from `GITLAB_TOKEN` or `GITLAB_PAT` (each
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: runspec-gitlab-core
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Pure-Python GitLab REST helpers — the importable core behind runspec-gitlab (no runspec dependency, no runnables)
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: httpx
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "runspec-gitlab-core"
7
- version = "0.4.0"
7
+ version = "0.5.0"
8
8
  requires-python = ">=3.10"
9
9
  description = "Pure-Python GitLab REST helpers — the importable core behind runspec-gitlab (no runspec dependency, no runnables)"
10
10
  dependencies = [
@@ -47,27 +47,32 @@ def get_project(config: GitlabConfig, project: str | None = None) -> dict[str, A
47
47
 
48
48
  def search_projects(
49
49
  config: GitlabConfig,
50
- search: str,
50
+ search: str | None = None,
51
51
  membership: bool = False,
52
52
  per_page: int = 20,
53
53
  page: int = 1,
54
+ owned: bool = False,
54
55
  ) -> list[dict[str, Any]]:
55
- """Search visible projects by name/path.
56
-
57
- ``membership`` limits results to projects the token's user is a member of.
56
+ """Search or list projects, most recently active first.
57
+
58
+ ``search`` matches the project name or path, including its group/namespace
59
+ path (so ``"finejason"`` finds projects under that user's namespace). GitLab
60
+ matches a term shorter than 3 characters only as an exact name. With no
61
+ ``search`` the call lists the token user's projects: ``membership`` is
62
+ implied, since listing every visible project on a public instance is
63
+ useless. ``owned`` limits results to projects the user owns.
58
64
  """
59
- return gitlab_request(
60
- "GET",
61
- "/projects",
62
- config=config,
63
- params={
64
- "search": search,
65
- "membership": membership,
66
- "order_by": "last_activity_at",
67
- "per_page": per_page,
68
- "page": page,
69
- },
70
- )
65
+ params: dict[str, Any] = {
66
+ "membership": membership or not search or None,
67
+ "owned": owned or None,
68
+ "order_by": "last_activity_at",
69
+ "per_page": per_page,
70
+ "page": page,
71
+ }
72
+ if search:
73
+ params["search"] = search
74
+ params["search_namespaces"] = True
75
+ return gitlab_request("GET", "/projects", config=config, params=params)
71
76
 
72
77
 
73
78
  def resolve_user_ids(config: GitlabConfig, usernames: list[str] | None) -> list[int] | None:
@@ -53,6 +53,23 @@ def test_search_projects_encodes_membership(monkeypatch):
53
53
  assert seen["path"] == "/api/v4/projects"
54
54
  assert seen["query"]["search"] == "runspec"
55
55
  assert seen["query"]["membership"] == "true"
56
+ assert seen["query"]["search_namespaces"] == "true"
57
+ assert "owned" not in seen["query"]
58
+
59
+
60
+ def test_search_projects_without_term_lists_member_projects(monkeypatch):
61
+ seen = _capture(monkeypatch, httpx.Response(200, json=[]))
62
+ search_projects(CFG)
63
+ assert seen["query"]["membership"] == "true"
64
+ assert "search" not in seen["query"]
65
+ assert "search_namespaces" not in seen["query"]
66
+
67
+
68
+ def test_search_projects_term_without_membership_leaves_it_off(monkeypatch):
69
+ seen = _capture(monkeypatch, httpx.Response(200, json=[]))
70
+ search_projects(CFG, "runspec", owned=True)
71
+ assert "membership" not in seen["query"]
72
+ assert seen["query"]["owned"] == "true"
56
73
 
57
74
 
58
75
  def test_list_issues_uses_default_project_and_filters(monkeypatch):