19
19
import argparse
20
20
21
21
orgs = [
22
- # "binder-examples",
23
- # "binderhub-ci-repos",
22
+ "binder-examples" ,
23
+ "binderhub-ci-repos" ,
24
24
"ipython" ,
25
- # "jupyter",
26
- # "jupyter-book",
27
- # "jupyter-governance",
28
- # "jupyter-incubator",
29
- # "jupyter-server",
30
- # "jupyter-standards",
31
- # "jupyter-widgets",
32
- # "jupyterhub",
33
- # "jupyterlab",
34
- # "jupyter-xeus",
35
- # "jupytercon",
36
- # "voila-dashboards",
37
- # "voila-gallery",
25
+ "jupyter" ,
26
+ "jupyter-book" ,
27
+ "jupyter-governance" ,
28
+ "jupyter-incubator" ,
29
+ "jupyter-server" ,
30
+ "jupyter-standards" ,
31
+ "jupyter-widgets" ,
32
+ "jupyterhub" ,
33
+ "jupyterlab" ,
34
+ "jupyter-xeus" ,
35
+ "jupytercon" ,
36
+ "voila-dashboards" ,
37
+ "voila-gallery" ,
38
38
]
39
39
40
40
token = os .getenv ("GH_TOKEN" )
47
47
"Accept" : "application/vnd.github.v3+json" ,
48
48
}
49
49
50
+ class DateTimeCache (diskcache .Cache ):
51
+ """Custom cache class that handles datetime serialization."""
52
+
53
+ def __setitem__ (self , key , value ):
54
+ """Override to serialize datetime objects."""
55
+ if isinstance (value , datetime ):
56
+ value = {'__datetime__' : value .isoformat ()}
57
+ super ().__setitem__ (key , value )
58
+
59
+ def __getitem__ (self , key ):
60
+ """Override to deserialize datetime objects."""
61
+ value = super ().__getitem__ (key )
62
+ if isinstance (value , dict ) and '__datetime__' in value :
63
+ return datetime .fromisoformat (value ['__datetime__' ])
64
+ return value
65
+
66
+ def get (self , key , default = None , retry = False ):
67
+ """Override to handle datetime deserialization in get method with retry."""
68
+ try :
69
+ return super ().get (key , default = default , retry = retry )
70
+ except KeyError :
71
+ return default
72
+
50
73
# Configure DiskCache in the current directory
51
74
CACHE_DIR = "github_cache"
52
- cache = diskcache . Cache (CACHE_DIR )
75
+ cache = DateTimeCache (CACHE_DIR )
53
76
54
77
async def get_org_members (session : aiohttp .ClientSession , org : str ) -> List [Dict ]:
55
78
"""Fetch all members of a GitHub organization with caching.
@@ -77,8 +100,8 @@ async def get_org_members(session: aiohttp.ClientSession, org: str) -> List[Dict
77
100
"""
78
101
cache_key = f"org_members_{ org } "
79
102
80
- # Try to get from cache
81
- cached_data = cache .get (cache_key )
103
+ # Try to get from cache with retry
104
+ cached_data = cache .get (cache_key , retry = True )
82
105
if cached_data is not None :
83
106
print (f"[cyan]Cache hit for { org } members[/cyan]" )
84
107
return cached_data
@@ -101,7 +124,7 @@ async def get_org_members(session: aiohttp.ClientSession, org: str) -> List[Dict
101
124
members .extend (page_members )
102
125
103
126
# Cache the results
104
- cache . set ( cache_key , members , expire = 3600 * 24 ) # 24 hours
127
+ cache [ cache_key ] = members # Using __setitem__ instead of set()
105
128
print (f"[green]Cached { len (members )} members for { org } [/green]" )
106
129
return members
107
130
@@ -131,12 +154,12 @@ async def get_user_activity(session: aiohttp.ClientSession, username: str) -> Op
131
154
if events :
132
155
last_activity = datetime .fromisoformat (events [0 ]["created_at" ].replace ('Z' , '+00:00' ))
133
156
# Cache the results
134
- cache . set ( cache_key , last_activity , expire = 3600 * 24 ) # 24 hours
157
+ cache [ cache_key ] = last_activity # Using __setitem__ instead of set()
135
158
print (f"[green]Cached activity for { username } [/green]" )
136
159
return last_activity
137
160
else :
138
161
print (f"[yellow]No activity found for { username } [/yellow]" )
139
- cache . set ( cache_key , None , expire = 3600 * 24 )
162
+ cache [ cache_key ] = None # Using __setitem__ instead of set( )
140
163
else :
141
164
print (f"[red]Error fetching activity for { username } : { response .status } [/red]" )
142
165
except Exception as e :
@@ -205,11 +228,10 @@ async def main():
205
228
# Print results sorted by last activity
206
229
user_activities = []
207
230
for (username , _ ), last_activity in zip (tasks , results ):
208
- if last_activity :
209
- user_activities .append ((username , last_activity , all_members [username ]))
231
+ user_activities .append ((username , last_activity , all_members [username ]))
210
232
211
- for username , last_activity , user_orgs in sorted (user_activities , key = lambda x : x [1 ], reverse = True ):
212
- last_activity_ago = humanize .naturaltime (datetime .now (last_activity .tzinfo ) - last_activity )
233
+ for username , last_activity , user_orgs in sorted (user_activities , key = lambda x : x [1 ] if x [ 1 ] is not None else datetime . fromtimestamp ( 0 ). astimezone ( datetime . now (). tzinfo ) , reverse = True ):
234
+ last_activity_ago = humanize .naturaltime (datetime .now (last_activity .tzinfo ) - last_activity ) if last_activity else "[red]never[/red]"
213
235
orgs_str = ", " .join (user_orgs )
214
236
print (f"{ username :<20} : Last activity { last_activity_ago } in orgs: { orgs_str } " )
215
237
0 commit comments