Skip to content

Commit cf5edfc

Browse files
authored
Merge pull request #195 from AnswerDotAI/gist-with-imgs
Create gist with imgs
2 parents 17ced3c + 6bc5d3c commit cf5edfc

File tree

4 files changed

+106
-40
lines changed

4 files changed

+106
-40
lines changed

00_core.ipynb

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"from datetime import datetime,timedelta\n",
3737
"from pprint import pprint\n",
3838
"from time import sleep\n",
39-
"import os"
39+
"import os, shutil, tempfile, git"
4040
]
4141
},
4242
{
@@ -1068,10 +1068,46 @@
10681068
"outputs": [],
10691069
"source": [
10701070
"#|export\n",
1071+
"img_md_pat = re.compile(r'!\\[(?P<alt>.*?)\\]\\((?P<url>[^\\s]+)\\)')\n",
1072+
"def replace_md_imgs(content, func): return img_md_pat.sub(func, content)\n",
1073+
"\n",
10711074
"@patch\n",
1072-
"def create_gist(self:GhApi, description, content, filename='gist.txt', public=False):\n",
1073-
" \"Create a gist containing a single file\"\n",
1074-
" return self.gists.create(description, public=public, files={filename: {\"content\": content}})"
1075+
"def create_gist(self:GhApi, description, content, filename='gist.txt', public=False, img_paths=None):\n",
1076+
" 'Create a gist, optionally with images where each md img url will be placed with img upload urls.'\n",
1077+
" gist = self.gists.create(description, public=public, files={filename: {\"content\": content}})\n",
1078+
" if not img_paths: return gist\n",
1079+
" with tempfile.TemporaryDirectory() as clone_dir:\n",
1080+
" gist_id, gist_url = gist.id, gist.html_url\n",
1081+
" token = self.headers['Authorization'].split('token ')[1]\n",
1082+
" repo = git.Repo.clone_from(f'https://{token}@gist.github.com/{gist_id}.git', clone_dir)\n",
1083+
" clone_dir, img_paths = Path(clone_dir), L(img_paths).map(Path)\n",
1084+
" for o in img_paths: \n",
1085+
" shutil.copy2(o, clone_dir/o.name)\n",
1086+
" repo.index.add([o.name])\n",
1087+
" repo.index.commit(\"Add images\")\n",
1088+
" repo.remotes.origin.push() \n",
1089+
" updated_gist = self.gists.get(gist_id)\n",
1090+
" img_urls = {o.name: updated_gist.files[o.name].raw_url for o in img_paths}\n",
1091+
" content = replace_md_imgs(content, lambda m: f\"![{m['alt']}]({img_urls.get(m['url'], m['url'])})\")\n",
1092+
" return self.gists.update(gist_id, files={filename:{'content':content}})"
1093+
]
1094+
},
1095+
{
1096+
"cell_type": "code",
1097+
"execution_count": null,
1098+
"metadata": {},
1099+
"outputs": [
1100+
{
1101+
"name": "stdout",
1102+
"output_type": "stream",
1103+
"text": [
1104+
"https://gist.github.com/KeremTurgutlu/81232c80389c9257a82bcf4ddeaffac0\n"
1105+
]
1106+
}
1107+
],
1108+
"source": [
1109+
"gist = api.create_gist(\"some description\", \"some content\")\n",
1110+
"print(gist.html_url)"
10751111
]
10761112
},
10771113
{
@@ -1082,8 +1118,7 @@
10821118
{
10831119
"data": {
10841120
"text/plain": [
1085-
"('https://gist.github.com/hamelsmu/2543b0c1699eafd0a36319a4a6284afa',\n",
1086-
" 'some content')"
1121+
"'some content'"
10871122
]
10881123
},
10891124
"execution_count": null,
@@ -1092,8 +1127,25 @@
10921127
}
10931128
],
10941129
"source": [
1095-
"gist = api.create_gist(\"some description\", \"some content\")\n",
1096-
"gist.html_url, gist.files['gist.txt'].content"
1130+
"gist.files['gist.txt'].content"
1131+
]
1132+
},
1133+
{
1134+
"cell_type": "code",
1135+
"execution_count": null,
1136+
"metadata": {},
1137+
"outputs": [
1138+
{
1139+
"name": "stdout",
1140+
"output_type": "stream",
1141+
"text": [
1142+
"https://gist.github.com/KeremTurgutlu/82af4d178db85fcb585029854b495bae\n"
1143+
]
1144+
}
1145+
],
1146+
"source": [
1147+
"gist = api.create_gist(\"some description\", \"some image\\n\\n![image](puppy.jpg)\", 'gist.md', img_paths=['puppy.jpg'])\n",
1148+
"print(gist.html_url)"
10971149
]
10981150
},
10991151
{
@@ -1103,13 +1155,8 @@
11031155
"outputs": [
11041156
{
11051157
"data": {
1106-
"text/markdown": [
1107-
"```json\n",
1108-
"{}\n",
1109-
"```"
1110-
],
11111158
"text/plain": [
1112-
"{}"
1159+
"'some image\\n\\n![image](https://gist.githubusercontent.com/KeremTurgutlu/82af4d178db85fcb585029854b495bae/raw/c7f420c839f58c6ac0c05f1116317645d31d7e80/puppy.jpg)'"
11131160
]
11141161
},
11151162
"execution_count": null,
@@ -1118,7 +1165,7 @@
11181165
}
11191166
],
11201167
"source": [
1121-
"api.gists.delete(gist.id)"
1168+
"gist.files['gist.md'].content"
11221169
]
11231170
},
11241171
{
@@ -1772,9 +1819,9 @@
17721819
],
17731820
"metadata": {
17741821
"kernelspec": {
1775-
"display_name": "python3",
1822+
"display_name": "python",
17761823
"language": "python",
1777-
"name": "python3"
1824+
"name": "python"
17781825
}
17791826
},
17801827
"nbformat": 4,

ghapi/_modidx.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@
8888
'ghapi.core._preview_hdr': ('core.html#_preview_hdr', 'ghapi/core.py'),
8989
'ghapi.core.date2gh': ('core.html#date2gh', 'ghapi/core.py'),
9090
'ghapi.core.gh2date': ('core.html#gh2date', 'ghapi/core.py'),
91-
'ghapi.core.print_summary': ('core.html#print_summary', 'ghapi/core.py')},
91+
'ghapi.core.print_summary': ('core.html#print_summary', 'ghapi/core.py'),
92+
'ghapi.core.replace_md_imgs': ('core.html#replace_md_imgs', 'ghapi/core.py')},
9293
'ghapi.event': { 'ghapi.event.GhApi.fetch_events': ('event.html#ghapi.fetch_events', 'ghapi/event.py'),
9394
'ghapi.event.GhApi.list_events': ('event.html#ghapi.list_events', 'ghapi/event.py'),
9495
'ghapi.event.GhApi.list_events_parallel': ('event.html#ghapi.list_events_parallel', 'ghapi/event.py'),

ghapi/core.py

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# AUTOGENERATED! DO NOT EDIT! File to edit: ../00_core.ipynb.
44

55
# %% auto 0
6-
__all__ = ['GH_HOST', 'EMPTY_TREE_SHA', 'print_summary', 'GhApi', 'date2gh', 'gh2date']
6+
__all__ = ['GH_HOST', 'img_md_pat', 'EMPTY_TREE_SHA', 'print_summary', 'GhApi', 'date2gh', 'gh2date', 'replace_md_imgs']
77

88
# %% ../00_core.ipynb 2
99
from fastcore.all import *
@@ -17,7 +17,7 @@
1717
from datetime import datetime,timedelta
1818
from pprint import pprint
1919
from time import sleep
20-
import os
20+
import os, shutil, tempfile, git
2121

2222
# %% ../00_core.ipynb 4
2323
GH_HOST = os.getenv('GH_HOST', "https://api.github.com")
@@ -163,19 +163,37 @@ def gh2date(dtstr:str)->datetime:
163163
return datetime.fromisoformat(dtstr.replace('Z', ''))
164164

165165
# %% ../00_core.ipynb 69
166+
img_md_pat = re.compile(r'!\[(?P<alt>.*?)\]\((?P<url>[^\s]+)\)')
167+
def replace_md_imgs(content, func): return img_md_pat.sub(func, content)
168+
166169
@patch
167-
def create_gist(self:GhApi, description, content, filename='gist.txt', public=False):
168-
"Create a gist containing a single file"
169-
return self.gists.create(description, public=public, files={filename: {"content": content}})
170+
def create_gist(self:GhApi, description, content, filename='gist.txt', public=False, img_paths=None):
171+
'Create a gist, optionally with images where each md img url will be placed with img upload urls.'
172+
gist = self.gists.create(description, public=public, files={filename: {"content": content}})
173+
if not img_paths: return gist
174+
with tempfile.TemporaryDirectory() as clone_dir:
175+
gist_id, gist_url = gist.id, gist.html_url
176+
token = self.headers['Authorization'].split('token ')[1]
177+
repo = git.Repo.clone_from(f'https://{token}@gist.github.com/{gist_id}.git', clone_dir)
178+
clone_dir, img_paths = Path(clone_dir), L(img_paths).map(Path)
179+
for o in img_paths:
180+
shutil.copy2(o, clone_dir/o.name)
181+
repo.index.add([o.name])
182+
repo.index.commit("Add images")
183+
repo.remotes.origin.push()
184+
updated_gist = self.gists.get(gist_id)
185+
img_urls = {o.name: updated_gist.files[o.name].raw_url for o in img_paths}
186+
content = replace_md_imgs(content, lambda m: f"![{m['alt']}]({img_urls.get(m['url'], m['url'])})")
187+
return self.gists.update(gist_id, files={filename:{'content':content}})
170188

171-
# %% ../00_core.ipynb 74
189+
# %% ../00_core.ipynb 76
172190
@patch
173191
def delete_release(self:GhApi, release):
174192
"Delete a release and its associated tag"
175193
self.repos.delete_release(release.id)
176194
self.git.delete_ref(f'tags/{release.tag_name}')
177195

178-
# %% ../00_core.ipynb 76
196+
# %% ../00_core.ipynb 78
179197
@patch
180198
def upload_file(self:GhApi, rel, fn):
181199
"Upload `fn` to endpoint for release `rel`"
@@ -184,7 +202,7 @@ def upload_file(self:GhApi, rel, fn):
184202
mime = mimetypes.guess_type(fn, False)[0] or 'application/octet-stream'
185203
return self(url, 'POST', headers={'Content-Type':mime}, query = {'name':fn.name}, data=fn.read_bytes())
186204

187-
# %% ../00_core.ipynb 77
205+
# %% ../00_core.ipynb 79
188206
@patch
189207
def create_release(self:GhApi, tag_name, branch='master', name=None, body='',
190208
draft=False, prerelease=False, files=None):
@@ -195,62 +213,62 @@ def create_release(self:GhApi, tag_name, branch='master', name=None, body='',
195213
for file in listify(files): self.upload_file(rel, file)
196214
return rel
197215

198-
# %% ../00_core.ipynb 85
216+
# %% ../00_core.ipynb 87
199217
@patch
200218
def list_tags(self:GhApi, prefix:str=''):
201219
"List all tags, optionally filtered to those starting with `prefix`"
202220
return self.git.list_matching_refs(f'tags/{prefix}')
203221

204-
# %% ../00_core.ipynb 90
222+
# %% ../00_core.ipynb 92
205223
@patch
206224
def list_branches(self:GhApi, prefix:str=''):
207225
"List all branches, optionally filtered to those starting with `prefix`"
208226
return self.git.list_matching_refs(f'heads/{prefix}')
209227

210-
# %% ../00_core.ipynb 95
228+
# %% ../00_core.ipynb 97
211229
# See https://stackoverflow.com/questions/9765453
212230
EMPTY_TREE_SHA = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'
213231

214-
# %% ../00_core.ipynb 97
232+
# %% ../00_core.ipynb 99
215233
@patch
216234
def create_branch_empty(self:GhApi, branch):
217235
t = self.git.create_tree(base_tree=EMPTY_TREE_SHA, tree = [dict(
218236
path='.dummy', content='ignore me', mode='100644', type='blob')])
219237
c = self.git.create_commit(f'create {branch}', t.sha)
220238
return self.git.create_ref(f'refs/heads/{branch}', c.sha)
221239

222-
# %% ../00_core.ipynb 99
240+
# %% ../00_core.ipynb 101
223241
@patch
224242
def delete_tag(self:GhApi, tag:str):
225243
"Delete a tag"
226244
return self.git.delete_ref(f'tags/{tag}')
227245

228-
# %% ../00_core.ipynb 100
246+
# %% ../00_core.ipynb 102
229247
@patch
230248
def delete_branch(self:GhApi, branch:str):
231249
"Delete a branch"
232250
return self.git.delete_ref(f'heads/{branch}')
233251

234-
# %% ../00_core.ipynb 102
252+
# %% ../00_core.ipynb 104
235253
@patch
236254
def get_branch(self:GhApi, branch=None):
237255
branch = branch or self.repos.get().default_branch
238256
return self.list_branches(branch)[0]
239257

240-
# %% ../00_core.ipynb 104
258+
# %% ../00_core.ipynb 106
241259
@patch
242260
def list_files(self:GhApi, branch=None):
243261
ref = self.get_branch(branch)
244262
res = self.git.get_tree(ref.object.sha).tree
245263
return {o.path:o for o in res}
246264

247-
# %% ../00_core.ipynb 106
265+
# %% ../00_core.ipynb 108
248266
@patch
249267
def get_content(self:GhApi, path):
250268
res = self.repos.get_content(path)
251269
return base64.b64decode(res.content)
252270

253-
# %% ../00_core.ipynb 108
271+
# %% ../00_core.ipynb 110
254272
@patch
255273
def create_or_update_file(self:GhApi, path, message, committer, author, content=None, sha=None, branch=''):
256274
if not branch: branch = api.repos.get()['default_branch']
@@ -260,28 +278,28 @@ def create_or_update_file(self:GhApi, path, message, committer, author, content=
260278
return self.repos.create_or_update_file_contents(path, message, content=content,
261279
branch=branch, committer=committer or {}, author=author or {}, **kwargs)
262280

263-
# %% ../00_core.ipynb 109
281+
# %% ../00_core.ipynb 111
264282
@patch
265283
def create_file(self:GhApi, path, message, committer, author, content=None, branch=None):
266284
if not branch: branch = api.repos.get()['default_branch']
267285
return self.create_or_update_file(path, message, branch=branch, committer=committer, content=content, author=author)
268286

269-
# %% ../00_core.ipynb 111
287+
# %% ../00_core.ipynb 113
270288
@patch
271289
def delete_file(self:GhApi, path, message, committer, author, sha=None, branch=None):
272290
if not branch: branch = api.repos.get()['default_branch']
273291
if sha is None: sha = self.list_files()[path].sha
274292
return self.repos.delete_file(path, message=message, sha=sha,
275293
branch=branch, committer=committer, author=author)
276294

277-
# %% ../00_core.ipynb 113
295+
# %% ../00_core.ipynb 115
278296
@patch
279297
def update_contents(self:GhApi, path, message, committer, author, content, sha=None, branch=None):
280298
if not branch: branch = api.repos.get()['default_branch']
281299
if sha is None: sha = self.list_files()[path].sha
282300
return self.create_or_update_file(path, message, committer=committer, author=author, content=content, sha=sha, branch=branch)
283301

284-
# %% ../00_core.ipynb 117
302+
# %% ../00_core.ipynb 119
285303
@patch
286304
def enable_pages(self:GhApi, branch=None, path="/"):
287305
"Enable or update pages for a repo to point to a `branch` and `path`."

puppy.jpg

23.7 KB
Loading

0 commit comments

Comments
 (0)