superset-showtime 0.2.8__py3-none-any.whl → 0.4.2__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.

Potentially problematic release.


This version of superset-showtime might be problematic. Click here for more details.

showtime/core/circus.py DELETED
@@ -1,279 +0,0 @@
1
- """
2
- 🎪 Circus tent emoji label parsing and state management
3
-
4
- Core logic for parsing GitHub labels with circus tent emoji patterns.
5
- """
6
-
7
- from dataclasses import dataclass
8
- from datetime import datetime
9
- from typing import TYPE_CHECKING, List, Optional
10
-
11
- if TYPE_CHECKING:
12
- from .github import GitHubInterface
13
-
14
-
15
- @dataclass
16
- class Show:
17
- """Single ephemeral environment state from circus labels"""
18
-
19
- pr_number: int
20
- sha: str # 7-char commit SHA
21
- status: str # building, running, updating, failed
22
- ip: Optional[str] = None # Environment IP address
23
- created_at: Optional[str] = None # ISO timestamp
24
- ttl: str = "24h" # 24h, 48h, close, etc.
25
- requested_by: Optional[str] = None # GitHub username
26
-
27
- @property
28
- def aws_service_name(self) -> str:
29
- """Deterministic ECS service name: pr-{pr_number}-{sha}"""
30
- return f"pr-{self.pr_number}-{self.sha}"
31
-
32
- @property
33
- def aws_image_tag(self) -> str:
34
- """Deterministic ECR image tag: pr-{pr_number}-{sha}-ci"""
35
- return f"pr-{self.pr_number}-{self.sha}-ci"
36
-
37
- @property
38
- def ecs_service_name(self) -> str:
39
- """Deterministic ECS service name with -service suffix: pr-{pr_number}-{sha}-service"""
40
- return f"{self.aws_service_name}-service"
41
-
42
- @property
43
- def short_sha(self) -> str:
44
- """7-character SHA for display (GitHub standard)"""
45
- return self.sha[:7]
46
-
47
- @property
48
- def is_active(self) -> bool:
49
- """Check if this is the currently active show"""
50
- return self.status == "running"
51
-
52
- @property
53
- def is_building(self) -> bool:
54
- """Check if environment is currently building"""
55
- return self.status == "building"
56
-
57
- @property
58
- def is_updating(self) -> bool:
59
- """Check if environment is currently updating"""
60
- return self.status == "updating"
61
-
62
- def needs_update(self, latest_sha: str) -> bool:
63
- """Check if environment needs update to latest SHA"""
64
- return self.sha != latest_sha[:7]
65
-
66
- def to_circus_labels(self) -> List[str]:
67
- """Convert show state to circus tent emoji labels (per-SHA format)"""
68
- if not self.created_at:
69
- self.created_at = datetime.utcnow().strftime("%Y-%m-%dT%H-%M")
70
-
71
- labels = [
72
- f"🎪 {self.sha} 🚦 {self.status}", # SHA-first status
73
- f"🎪 🎯 {self.sha}", # Active pointer (no value)
74
- f"🎪 {self.sha} 📅 {self.created_at}", # SHA-first timestamp
75
- f"🎪 {self.sha} ⌛ {self.ttl}", # SHA-first TTL
76
- ]
77
-
78
- if self.ip:
79
- labels.append(f"🎪 {self.sha} 🌐 {self.ip}:8080")
80
-
81
- if self.requested_by:
82
- labels.append(f"🎪 {self.sha} 🤡 {self.requested_by}")
83
-
84
- return labels
85
-
86
- @classmethod
87
- def from_circus_labels(cls, pr_number: int, labels: List[str], sha: str) -> Optional["Show"]:
88
- """Create Show from circus tent labels for specific SHA"""
89
- show_data = {
90
- "pr_number": pr_number,
91
- "sha": sha,
92
- "status": "building", # default
93
- }
94
-
95
- for label in labels:
96
- if not label.startswith("🎪 "):
97
- continue
98
-
99
- parts = label.split(" ", 3) # Split into 4 parts for per-SHA format
100
-
101
- if len(parts) == 3: # Old format: 🎪 🎯 sha
102
- emoji, value = parts[1], parts[2]
103
- if emoji == "🎯" and value == sha: # Active pointer
104
- pass # This SHA is active
105
- elif len(parts) == 4: # SHA-first format: 🎪 sha 🚦 status
106
- label_sha, emoji, value = parts[1], parts[2], parts[3]
107
-
108
- if label_sha != sha: # Only process labels for this SHA
109
- continue
110
-
111
- if emoji == "🚦": # Status
112
- show_data["status"] = value
113
- elif emoji == "📅": # Timestamp
114
- show_data["created_at"] = value
115
- elif emoji == "🌐": # IP with port
116
- show_data["ip"] = value.replace(":8080", "") # Remove port for storage
117
- elif emoji == "⌛": # TTL
118
- show_data["ttl"] = value
119
- elif emoji == "🤡": # User (clown!)
120
- show_data["requested_by"] = value
121
-
122
- # Only return Show if we found relevant labels for this SHA
123
- if any(label.endswith(f" {sha}") for label in labels if "🎯" in label or "🏗️" in label):
124
- return cls(**show_data)
125
-
126
- return None
127
-
128
-
129
- class PullRequest:
130
- """GitHub PR with its shows parsed from circus labels"""
131
-
132
- def __init__(self, pr_number: int, labels: List[str]):
133
- self.pr_number = pr_number
134
- self.labels = labels
135
- self._shows = self._parse_shows_from_labels()
136
-
137
- @property
138
- def shows(self) -> List[Show]:
139
- """All shows found in labels"""
140
- return self._shows
141
-
142
- @property
143
- def current_show(self) -> Optional[Show]:
144
- """The currently active show (from 🎯 label)"""
145
- # Find the SHA that's marked as active (🎯)
146
- active_sha = None
147
- for label in self.labels:
148
- if label.startswith("🎪 🎯 "):
149
- active_sha = label.split(" ")[2]
150
- break
151
-
152
- if not active_sha:
153
- return None
154
-
155
- # Find the show with that SHA
156
- for show in self.shows:
157
- if show.sha == active_sha:
158
- return show
159
-
160
- return None
161
-
162
- @property
163
- def building_show(self) -> Optional[Show]:
164
- """Show currently being built (from 🏗️ label)"""
165
- building_sha = None
166
- for label in self.labels:
167
- if label.startswith("🎪 🏗️ "):
168
- building_sha = label.split(" ")[2]
169
- break
170
-
171
- if not building_sha:
172
- return None
173
-
174
- for show in self.shows:
175
- if show.sha == building_sha:
176
- return show
177
-
178
- return None
179
-
180
- @property
181
- def circus_labels(self) -> List[str]:
182
- """All circus tent labels"""
183
- return [label for label in self.labels if label.startswith("🎪 ")]
184
-
185
- def has_shows(self) -> bool:
186
- """Check if PR has any shows"""
187
- return len(self.shows) > 0
188
-
189
- def get_show_by_sha(self, sha: str) -> Optional[Show]:
190
- """Get specific show by SHA"""
191
- for show in self.shows:
192
- if show.sha == sha[:7]:
193
- return show
194
- return None
195
-
196
- def _parse_shows_from_labels(self) -> List[Show]:
197
- """Parse all shows from circus labels"""
198
- shows = []
199
-
200
- # Find all unique SHAs mentioned in labels
201
- shas = set()
202
- for label in self.labels:
203
- if label.startswith("🎪 🎯 ") or label.startswith("🎪 🏗️ "):
204
- sha = label.split(" ")[2]
205
- shas.add(sha)
206
-
207
- # Create Show object for each SHA
208
- for sha in shas:
209
- show = Show.from_circus_labels(self.pr_number, self.labels, sha)
210
- if show:
211
- shows.append(show)
212
-
213
- return shows
214
-
215
- @classmethod
216
- def from_id(cls, pr_number: int, github: "GitHubInterface") -> "PullRequest":
217
- """Load PR with current labels from GitHub"""
218
- labels = github.get_labels(pr_number)
219
- return cls(pr_number, labels)
220
-
221
- def refresh_labels(self, github: "GitHubInterface") -> None:
222
- """Refresh labels from GitHub and reparse shows"""
223
- self.labels = github.get_labels(self.pr_number)
224
- self._shows = self._parse_shows_from_labels()
225
-
226
-
227
- def parse_ttl_days(ttl_str: str) -> Optional[float]:
228
- """Parse TTL string to days"""
229
- import re
230
-
231
- if ttl_str == "never":
232
- return None # Never expire
233
-
234
- if ttl_str == "close":
235
- return None # Special handling needed
236
-
237
- # Parse number + unit: 24h, 7d, 2w, etc.
238
- match = re.match(r"(\d+(?:\.\d+)?)(h|d|w)", ttl_str.lower())
239
- if not match:
240
- return 2.0 # Default 2 days if invalid
241
-
242
- value = float(match.group(1))
243
- unit = match.group(2)
244
-
245
- if unit == "h":
246
- return value / 24.0 # Hours to days
247
- elif unit == "d":
248
- return value # Already in days
249
- elif unit == "w":
250
- return value * 7.0 # Weeks to days
251
-
252
- return 2.0 # Default
253
-
254
-
255
- def get_effective_ttl(pr) -> Optional[float]:
256
- """Get effective TTL in days for a PR (handles multiple labels, conflicts)"""
257
- ttl_labels = []
258
-
259
- # Find all TTL labels for all shows
260
- for show in pr.shows:
261
- if show.ttl:
262
- ttl_days = parse_ttl_days(show.ttl)
263
- if ttl_days is None: # "never" or "close"
264
- if show.ttl == "never":
265
- return None # Never expire takes precedence
266
- # For "close", continue checking others
267
- else:
268
- ttl_labels.append(ttl_days)
269
-
270
- if not ttl_labels:
271
- return 2.0 # Default 2 days
272
-
273
- # Use longest duration if multiple labels
274
- return max(ttl_labels)
275
-
276
-
277
- def short_sha(full_sha: str) -> str:
278
- """Truncate SHA to 7 characters for display (GitHub standard)"""
279
- return full_sha[:7]
@@ -1,17 +0,0 @@
1
- showtime/__init__.py,sha256=1wse0Q42I1-_VwF1AYaIDYvkqx4eC32omodFrMeStlE,420
2
- showtime/__main__.py,sha256=EVaDaTX69yIhCzChg99vqvFSCN4ELstEt7Mpb9FMZX8,109
3
- showtime/cli.py,sha256=gd8OIjdQov7ei8A9A2X8bdreOeWJVhc5FFhAN9u_spQ,62913
4
- showtime/commands/__init__.py,sha256=M2wn5hYgwNCryMjLT79ncobvK884r-xk3znkCmINN_0,28
5
- showtime/commands/start.py,sha256=DPGbgvGPh7I60LK_VioDljUhdmhNFVjEy6BchFv1lCo,1026
6
- showtime/core/__init__.py,sha256=54hbdFNGrzuNMBdraezfjT8Zi6g221pKlJ9mREnKwCw,34
7
- showtime/core/aws.py,sha256=xWrje3MS3LpFeilH6jloWy_VgE9Wky_G5VkRCOB0ZNw,32535
8
- showtime/core/circus.py,sha256=dtYEU1YnmaE9oWhPwrPiMof1GF5tzckvcDrc9iJ9VpQ,9037
9
- showtime/core/emojis.py,sha256=MHEDuPIdfNiop4zbNLuviz3eY05QiftYSHHCVbkfKhw,2129
10
- showtime/core/github.py,sha256=HWhM8_Yq4P-AHq0FV3UfrfQHUHXxkhn74vvc_9RguKA,9822
11
- showtime/core/github_messages.py,sha256=iKd3AS0uvTnCtR-2jPtEq_efuThC8HUzEAMmQt5c3y4,7187
12
- showtime/core/label_colors.py,sha256=efhbFnz_3nqEnEqmgyF6_hZbxtCu_fmb68BIIUpSsnk,3895
13
- showtime/data/ecs-task-definition.json,sha256=0ZaE0FZ8IWduXd2RyscMhXeVgxyym6qtjH02CK9mXBI,2235
14
- superset_showtime-0.2.8.dist-info/METADATA,sha256=fMZkdKW3pgcxx-AXRP5rmTpmOBLEXtVcSaLr2L5A7xg,14635
15
- superset_showtime-0.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- superset_showtime-0.2.8.dist-info/entry_points.txt,sha256=rDW7oZ57mqyBUS4N_3_R7bZNGVHB-104jwmY-hHC_ck,85
17
- superset_showtime-0.2.8.dist-info/RECORD,,