github-forker 1.0.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.
@@ -0,0 +1,117 @@
1
+ """
2
+ pygithub_fork.models
3
+ ~~~~~~~~~~~~~~~~~~~~
4
+ Dataclasses and enums for fork operations.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ from dataclasses import dataclass, field
9
+ from enum import Enum
10
+ from typing import Callable, Optional, Union
11
+
12
+ from github.Repository import Repository
13
+ from github.Organization import Organization
14
+
15
+
16
+ class ForkStatus(Enum):
17
+ PENDING = "pending" # Submitted but not yet confirmed
18
+ CREATED = "created" # API call succeeded; readiness unconfirmed
19
+ ALREADY_EXISTED = "already_existed" # Idempotent re-run; fork pre-existed
20
+ READY = "ready" # Fork is fully populated and usable
21
+ TIMED_OUT_WAITING = "timed_out_waiting" # Created but readiness unconfirmed within timeout
22
+ FAILED = "failed" # Unrecoverable error
23
+
24
+
25
+ @dataclass
26
+ class ForkRequest:
27
+ """Declarative description of a single fork operation for use with fork_many / pool."""
28
+ source: Union[str, Repository]
29
+ organization: Optional[Union[str, Organization]] = None
30
+ name: Optional[str] = None
31
+ default_branch_only: Optional[bool] = None
32
+ # Per-request post-fork actions (override global config when set)
33
+ add_upstream_remote: Optional[bool] = None # git remote add upstream <clone_url>
34
+ local_path: Optional[str] = None # path to local clone for remote setup
35
+ register_webhook: Optional[bool] = None # register push/fork events webhook
36
+ webhook_url: Optional[str] = None # target URL for webhook
37
+ webhook_events: Optional[list[str]] = None # e.g. ["push", "fork"]
38
+
39
+
40
+ @dataclass
41
+ class ForkResult:
42
+ """Outcome of a single fork operation."""
43
+ source_full_name: str
44
+ fork: Optional[Repository]
45
+ status: ForkStatus
46
+ already_existed: bool
47
+ attempts: int = 1
48
+ elapsed_seconds: float = 0.0
49
+ error: Optional[Exception] = None
50
+ upstream_remote_added: bool = False
51
+ webhook_id: Optional[int] = None # GitHub hook ID if webhook was registered
52
+
53
+ @property
54
+ def succeeded(self) -> bool:
55
+ return self.fork is not None and self.error is None
56
+
57
+ @property
58
+ def clone_url(self) -> Optional[str]:
59
+ return self.fork.clone_url if self.fork else None
60
+
61
+ @property
62
+ def ssh_url(self) -> Optional[str]:
63
+ return self.fork.ssh_url if self.fork else None
64
+
65
+ def __repr__(self) -> str: # pragma: no cover
66
+ return (
67
+ f"ForkResult(source={self.source_full_name!r}, "
68
+ f"status={self.status.value}, "
69
+ f"fork={self.fork.full_name if self.fork else None!r}, "
70
+ f"elapsed={self.elapsed_seconds:.2f}s)"
71
+ )
72
+
73
+
74
+ @dataclass
75
+ class ForkerConfig:
76
+ """
77
+ Tunable behavior for GitHubForker. All fields have sensible production
78
+ defaults; override only what you need.
79
+ """
80
+ # ---- Retry / rate-limit ----
81
+ max_retries: int = 5
82
+ base_backoff_seconds: float = 1.5
83
+ max_backoff_seconds: float = 60.0
84
+
85
+ # ---- Fork readiness polling ----
86
+ wait_for_ready: bool = True
87
+ ready_timeout_seconds: float = 90.0
88
+ ready_poll_interval_seconds: float = 3.0
89
+
90
+ # ---- Thread pool (fork_many / fork_async) ----
91
+ pool_workers: int = 4
92
+ """Max concurrent forks. GitHub secondary rate limits kick in when you
93
+ fork too many repos in rapid succession; keep this ≤ 4 for safety."""
94
+
95
+ # ---- Post-fork: upstream remote ----
96
+ add_upstream_remote: bool = False
97
+ """If True, runs `git remote add upstream <source_clone_url>` in
98
+ local_clone_path after a successful fork."""
99
+ local_clone_path: Optional[str] = None
100
+ """Absolute path of the local clone where the upstream remote is added.
101
+ Only used when add_upstream_remote=True."""
102
+
103
+ # ---- Post-fork: webhook ----
104
+ register_webhook: bool = False
105
+ """If True, registers a webhook on the freshly created fork."""
106
+ webhook_url: Optional[str] = None
107
+ """Payload URL for the webhook."""
108
+ webhook_events: list[str] = field(default_factory=lambda: ["push", "fork"])
109
+ webhook_content_type: str = "json"
110
+ webhook_secret: Optional[str] = None
111
+ webhook_insecure_ssl: bool = False
112
+
113
+ # ---- Callbacks ----
114
+ on_retry: Optional[Callable[[int, Exception, float], None]] = None
115
+ """Called as on_retry(attempt, exc, sleep_seconds) before each retry sleep."""
116
+ on_fork_done: Optional[Callable[["ForkResult"], None]] = None
117
+ """Called after each successful (or failed) fork when using fork_many/pool."""