pierre-storage 0.11.0__py3-none-any.whl → 0.12.1__py3-none-any.whl

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.
pierre_storage/client.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Main client for Pierre Git Storage SDK."""
2
2
 
3
3
  import uuid
4
- from typing import Any, Dict, Optional
4
+ from typing import Any, Dict, Optional, cast
5
5
  from urllib.parse import urlencode
6
6
 
7
7
  import httpx
@@ -10,7 +10,10 @@ from pierre_storage.auth import generate_jwt
10
10
  from pierre_storage.errors import ApiError
11
11
  from pierre_storage.repo import DEFAULT_TOKEN_TTL_SECONDS, RepoImpl
12
12
  from pierre_storage.types import (
13
+ BaseRepo,
13
14
  DeleteRepoResult,
15
+ ForkBaseRepo,
16
+ GitHubBaseRepo,
14
17
  GitStorageOptions,
15
18
  ListReposResult,
16
19
  Repo,
@@ -102,17 +105,18 @@ class GitStorage:
102
105
  self,
103
106
  *,
104
107
  id: Optional[str] = None,
105
- default_branch: str = "main",
106
- base_repo: Optional[Dict[str, Any]] = None,
108
+ default_branch: Optional[str] = None,
109
+ base_repo: Optional[BaseRepo] = None,
107
110
  ttl: Optional[int] = None,
108
111
  ) -> Repo:
109
112
  """Create a new repository.
110
113
 
111
114
  Args:
112
115
  id: Repository ID (auto-generated if not provided)
113
- default_branch: Default branch name (default: "main")
114
- base_repo: Optional base repository for GitHub sync
115
- (provider, owner, name, default_branch)
116
+ default_branch: Default branch name (default: "main" for non-forks)
117
+ base_repo: Optional base repository for GitHub sync or fork
118
+ GitHub: owner, name, default_branch
119
+ Fork: id, ref, sha
116
120
  ttl: Token TTL in seconds
117
121
 
118
122
  Returns:
@@ -129,19 +133,52 @@ class GitStorage:
129
133
  )
130
134
 
131
135
  url = f"{self.options['api_base_url']}/api/v{self.options['api_version']}/repos"
132
- body: Dict[str, Any] = {"default_branch": default_branch}
136
+ body: Dict[str, Any] = {}
133
137
 
134
138
  # Match backend priority: base_repo.default_branch > default_branch > 'main'
135
- resolved_default_branch = default_branch
139
+ explicit_default_branch = default_branch is not None
140
+ resolved_default_branch: Optional[str] = None
141
+
136
142
  if base_repo:
137
- # Ensure provider is set to 'github' if not provided
138
- base_repo_with_provider = {
139
- "provider": "github",
140
- **base_repo,
141
- }
142
- body["base_repo"] = base_repo_with_provider
143
- if base_repo.get("default_branch"):
144
- resolved_default_branch = base_repo["default_branch"]
143
+ if "id" in base_repo:
144
+ fork_repo = cast(ForkBaseRepo, base_repo)
145
+ base_repo_token = self._generate_jwt(
146
+ fork_repo["id"],
147
+ {"permissions": ["git:read"], "ttl": ttl},
148
+ )
149
+ base_repo_payload: Dict[str, Any] = {
150
+ "provider": "code",
151
+ "owner": self.options["name"],
152
+ "name": fork_repo["id"],
153
+ "operation": "fork",
154
+ "auth": {"token": base_repo_token},
155
+ }
156
+ if fork_repo.get("ref"):
157
+ base_repo_payload["ref"] = fork_repo["ref"]
158
+ if fork_repo.get("sha"):
159
+ base_repo_payload["sha"] = fork_repo["sha"]
160
+ body["base_repo"] = base_repo_payload
161
+ if explicit_default_branch:
162
+ resolved_default_branch = default_branch
163
+ body["default_branch"] = default_branch
164
+ else:
165
+ github_repo = cast(GitHubBaseRepo, base_repo)
166
+ # Ensure provider is set to 'github' if not provided
167
+ base_repo_with_provider = {
168
+ "provider": "github",
169
+ **github_repo,
170
+ }
171
+ body["base_repo"] = base_repo_with_provider
172
+ if github_repo.get("default_branch"):
173
+ resolved_default_branch = github_repo["default_branch"]
174
+ elif explicit_default_branch:
175
+ resolved_default_branch = default_branch
176
+ else:
177
+ resolved_default_branch = "main"
178
+ body["default_branch"] = resolved_default_branch
179
+ else:
180
+ resolved_default_branch = default_branch if explicit_default_branch else "main"
181
+ body["default_branch"] = resolved_default_branch
145
182
 
146
183
  async with httpx.AsyncClient() as client:
147
184
  response = await client.post(
@@ -173,7 +210,7 @@ class GitStorage:
173
210
 
174
211
  return RepoImpl(
175
212
  repo_id,
176
- resolved_default_branch,
213
+ resolved_default_branch or "main",
177
214
  api_base_url,
178
215
  storage_base_url,
179
216
  name,
pierre_storage/types.py CHANGED
@@ -41,7 +41,7 @@ class GitStorageOptions(TypedDict, total=False):
41
41
  default_ttl: Optional[int]
42
42
 
43
43
 
44
- class BaseRepo(TypedDict, total=False):
44
+ class GitHubBaseRepo(TypedDict, total=False):
45
45
  """Base repository configuration for GitHub sync."""
46
46
 
47
47
  provider: Literal["github"] # required
@@ -50,6 +50,17 @@ class BaseRepo(TypedDict, total=False):
50
50
  default_branch: Optional[str]
51
51
 
52
52
 
53
+ class ForkBaseRepo(TypedDict, total=False):
54
+ """Base repository configuration for code storage forks."""
55
+
56
+ id: str # required
57
+ ref: Optional[str]
58
+ sha: Optional[str]
59
+
60
+
61
+ BaseRepo = Union[GitHubBaseRepo, ForkBaseRepo]
62
+
63
+
53
64
  class DeleteRepoResult(TypedDict):
54
65
  """Result from deleting a repository."""
55
66
 
pierre_storage/version.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Version information for Pierre Storage SDK."""
2
2
 
3
3
  PACKAGE_NAME = "code-storage-py-sdk"
4
- PACKAGE_VERSION = "0.9.0"
4
+ PACKAGE_VERSION = "0.12.1"
5
5
 
6
6
 
7
7
  def get_user_agent() -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pierre-storage
3
- Version: 0.11.0
3
+ Version: 0.12.1
4
4
  Summary: Pierre Git Storage SDK for Python
5
5
  Author-email: Pierre <support@pierre.io>
6
6
  License-Expression: MIT
@@ -83,6 +83,15 @@ github_repo = await storage.create_repo(
83
83
  }
84
84
  )
85
85
  # This repository will sync with github.com/octocat/Hello-World
86
+
87
+ # Create a repository by forking an existing repo
88
+ forked_repo = await storage.create_repo(
89
+ id="my-fork",
90
+ base_repo={
91
+ "id": "my-template-id",
92
+ "ref": "main", # optional
93
+ },
94
+ )
86
95
  ```
87
96
 
88
97
  ### Finding a Repository
@@ -472,6 +481,23 @@ commits = await repo.list_commits()
472
481
  3. You can then use all Pierre SDK features (diffs, commits, file access) on the synced content
473
482
  4. The provider is automatically set to `"github"` when using `base_repo`
474
483
 
484
+ ### Forking Repositories
485
+
486
+ You can fork an existing repository within the same Pierre org:
487
+
488
+ ```python
489
+ forked_repo = await storage.create_repo(
490
+ id="my-fork",
491
+ base_repo={
492
+ "id": "my-template-id",
493
+ "ref": "main", # optional (branch/tag)
494
+ # "sha": "abc123..." # optional commit SHA (overrides ref)
495
+ },
496
+ )
497
+ ```
498
+
499
+ When `default_branch` is omitted, the SDK returns `"main"`.
500
+
475
501
  ### Restoring Commits
476
502
 
477
503
  You can restore a repository to a previous commit:
@@ -500,7 +526,7 @@ class GitStorage:
500
526
  self,
501
527
  *,
502
528
  id: Optional[str] = None,
503
- default_branch: str = "main",
529
+ default_branch: Optional[str] = None, # defaults to "main"
504
530
  base_repo: Optional[BaseRepo] = None,
505
531
  ttl: Optional[int] = None,
506
532
  ) -> Repo: ...
@@ -639,6 +665,8 @@ Key types are provided via TypedDict for better IDE support:
639
665
  from pierre_storage.types import (
640
666
  GitStorageOptions,
641
667
  BaseRepo,
668
+ GitHubBaseRepo,
669
+ ForkBaseRepo,
642
670
  CommitSignature,
643
671
  CreateCommitOptions,
644
672
  ListFilesResult,
@@ -652,12 +680,19 @@ from pierre_storage.types import (
652
680
  # ... and more
653
681
  )
654
682
 
655
- # BaseRepo type for GitHub sync
656
- class BaseRepo(TypedDict, total=False):
657
- provider: Literal["github"] # Always "github"
683
+ # BaseRepo type for GitHub sync or forks
684
+ class GitHubBaseRepo(TypedDict, total=False):
685
+ provider: Literal["github"] # Always "github"
658
686
  owner: str # GitHub organization or user
659
687
  name: str # Repository name
660
688
  default_branch: Optional[str] # Default branch (optional)
689
+
690
+ class ForkBaseRepo(TypedDict, total=False):
691
+ id: str # Source repo ID
692
+ ref: Optional[str] # Optional ref name
693
+ sha: Optional[str] # Optional commit SHA
694
+
695
+ BaseRepo = Union[GitHubBaseRepo, ForkBaseRepo]
661
696
  ```
662
697
 
663
698
  ## Webhook Validation
@@ -1,15 +1,15 @@
1
1
  pierre_storage/__init__.py,sha256=8t6r3VUY4MSZhSuBXaoxzuxd4FLRAbVLWFxXiC_fcQY,1905
2
2
  pierre_storage/auth.py,sha256=aT0KNaUKa9fXERtQvJb8C6zL5IxrfA1KLxMBcprAq5A,2074
3
- pierre_storage/client.py,sha256=LPU0iZoduQvE7CDAMEKcYnMDn6WDH8vZtJw4BKO8lAg,13213
3
+ pierre_storage/client.py,sha256=FVUB-r1Oxr112nFAXPEo_rpkGVFdxYvu_NpBXh8aclI,14908
4
4
  pierre_storage/commit.py,sha256=ks5hKScHHricJ3sx8DyLSAASM72CPmVv-tbtUgHbUF4,16766
5
5
  pierre_storage/errors.py,sha256=-vuA2BUGwyDlErFtdh2boLdk0fDFDFYBEIohJk4AsIs,2184
6
6
  pierre_storage/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
7
7
  pierre_storage/repo.py,sha256=wnTDVtHx9v8tJTHJ9cHJs8cn5dImsCA3M3xxx7RqhS8,44117
8
- pierre_storage/types.py,sha256=MNTp4LYIActTUaxII-Qa0xjsKszVSPJKlLOvaw6nIOY,14425
9
- pierre_storage/version.py,sha256=HFSPY5BelU4QBXsW9MXZlFAE6Sa70XR3e_RzOQe1RO4,315
8
+ pierre_storage/types.py,sha256=9THfT19hM_qEkozdNH5qhiL34_USubSGIRFHUw8HY9E,14661
9
+ pierre_storage/version.py,sha256=L7upS30suP-fz3rFGhpCsKcU2OKkpynrjqNIfdNDhFc,316
10
10
  pierre_storage/webhook.py,sha256=hyjSmTlU_x35m612erXDqNXbLUh5i5As5GRw7kxylFc,7425
11
- pierre_storage-0.11.0.dist-info/licenses/LICENSE,sha256=CFzxoMyurfMUB0u0RaXBFZ6IDeUd6FQhKrLR_IeXtuU,1063
12
- pierre_storage-0.11.0.dist-info/METADATA,sha256=0TaxHV-8GRD2iX1u6JpUrZHGe7P0wKdmp1sg0F8DyVg,22367
13
- pierre_storage-0.11.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
14
- pierre_storage-0.11.0.dist-info/top_level.txt,sha256=RzcYFaSdETlcwX-45G9Q39xUgXWZLJEWcOiK0p6ZepY,15
15
- pierre_storage-0.11.0.dist-info/RECORD,,
11
+ pierre_storage-0.12.1.dist-info/licenses/LICENSE,sha256=CFzxoMyurfMUB0u0RaXBFZ6IDeUd6FQhKrLR_IeXtuU,1063
12
+ pierre_storage-0.12.1.dist-info/METADATA,sha256=r1wvmVRSZsARL6StuI8cLWRz5b7KYbQByBjEnmv7MXk,23306
13
+ pierre_storage-0.12.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
14
+ pierre_storage-0.12.1.dist-info/top_level.txt,sha256=RzcYFaSdETlcwX-45G9Q39xUgXWZLJEWcOiK0p6ZepY,15
15
+ pierre_storage-0.12.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5