ipykernel-helper 0.0.14__tar.gz → 0.0.25__tar.gz

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.
Files changed (19) hide show
  1. {ipykernel_helper-0.0.14/ipykernel_helper.egg-info → ipykernel_helper-0.0.25}/PKG-INFO +5 -3
  2. ipykernel_helper-0.0.25/ipykernel_helper/__init__.py +2 -0
  3. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper/_modidx.py +9 -0
  4. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper/core.py +118 -47
  5. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25/ipykernel_helper.egg-info}/PKG-INFO +5 -3
  6. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/requires.txt +4 -2
  7. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/settings.ini +2 -2
  8. ipykernel_helper-0.0.14/ipykernel_helper/__init__.py +0 -2
  9. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/LICENSE +0 -0
  10. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/MANIFEST.in +0 -0
  11. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/README.md +0 -0
  12. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/SOURCES.txt +0 -0
  13. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/dependency_links.txt +0 -0
  14. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/entry_points.txt +0 -0
  15. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/not-zip-safe +0 -0
  16. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/top_level.txt +0 -0
  17. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/pyproject.toml +0 -0
  18. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/setup.cfg +0 -0
  19. {ipykernel_helper-0.0.14 → ipykernel_helper-0.0.25}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ipykernel-helper
3
- Version: 0.0.14
3
+ Version: 0.0.25
4
4
  Summary: Helpers for ipykernel and friends
5
5
  Home-page: https://github.com/AnswerDotAI/ipykernel-helper
6
6
  Author: Jeremy Howard
@@ -18,14 +18,16 @@ Classifier: License :: OSI Approved :: Apache Software License
18
18
  Requires-Python: >=3.9
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: fastcore
22
- Requires-Dist: toolslm>=0.2.0
21
+ Requires-Dist: fastcore>=1.11.0
22
+ Requires-Dist: toolslm>=0.3.13
23
23
  Requires-Dist: jedi
24
24
  Requires-Dist: ipython
25
25
  Requires-Dist: ipykernel
26
26
  Requires-Dist: beautifulsoup4
27
+ Requires-Dist: lxml
27
28
  Requires-Dist: html2text
28
29
  Requires-Dist: cloudscraper
30
+ Requires-Dist: ghapi
29
31
  Provides-Extra: dev
30
32
  Dynamic: author
31
33
  Dynamic: author-email
@@ -0,0 +1,2 @@
1
+ __version__ = "0.0.25"
2
+ from .core import *
@@ -21,13 +21,22 @@ d = { 'settings': { 'branch': 'main',
21
21
  'ipykernel_helper/core.py'),
22
22
  'ipykernel_helper.core.InteractiveShell.xpush': ( 'core.html#interactiveshell.xpush',
23
23
  'ipykernel_helper/core.py'),
24
+ 'ipykernel_helper.core._absolutify_imgs': ('core.html#_absolutify_imgs', 'ipykernel_helper/core.py'),
25
+ 'ipykernel_helper.core._aify_imgs': ('core.html#_aify_imgs', 'ipykernel_helper/core.py'),
26
+ 'ipykernel_helper.core._convert_math': ('core.html#_convert_math', 'ipykernel_helper/core.py'),
27
+ 'ipykernel_helper.core._extract_section': ('core.html#_extract_section', 'ipykernel_helper/core.py'),
28
+ 'ipykernel_helper.core._get_math_mode': ('core.html#_get_math_mode', 'ipykernel_helper/core.py'),
24
29
  'ipykernel_helper.core._get_schema': ('core.html#_get_schema', 'ipykernel_helper/core.py'),
25
30
  'ipykernel_helper.core._rank': ('core.html#_rank', 'ipykernel_helper/core.py'),
26
31
  'ipykernel_helper.core._safe_repr': ('core.html#_safe_repr', 'ipykernel_helper/core.py'),
27
32
  'ipykernel_helper.core._signatures': ('core.html#_signatures', 'ipykernel_helper/core.py'),
33
+ 'ipykernel_helper.core.fix_editable_priority': ( 'core.html#fix_editable_priority',
34
+ 'ipykernel_helper/core.py'),
28
35
  'ipykernel_helper.core.get_md': ('core.html#get_md', 'ipykernel_helper/core.py'),
36
+ 'ipykernel_helper.core.gh_blob_to_raw': ('core.html#gh_blob_to_raw', 'ipykernel_helper/core.py'),
29
37
  'ipykernel_helper.core.load_ipython_extension': ( 'core.html#load_ipython_extension',
30
38
  'ipykernel_helper/core.py'),
39
+ 'ipykernel_helper.core.read_gh_repo': ('core.html#read_gh_repo', 'ipykernel_helper/core.py'),
31
40
  'ipykernel_helper.core.read_url': ('core.html#read_url', 'ipykernel_helper/core.py'),
32
41
  'ipykernel_helper.core.run_cmd': ('core.html#run_cmd', 'ipykernel_helper/core.py'),
33
42
  'ipykernel_helper.core.scrape_url': ('core.html#scrape_url', 'ipykernel_helper/core.py'),
@@ -3,11 +3,14 @@
3
3
  # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.
4
4
 
5
5
  # %% auto 0
6
- __all__ = ['transient', 'run_cmd', 'get_md', 'scrape_url', 'read_url', 'load_ipython_extension']
6
+ __all__ = ['transient', 'run_cmd', 'get_md', 'scrape_url', 'gh_blob_to_raw', 'read_gh_repo', 'read_url', 'fix_editable_priority',
7
+ 'load_ipython_extension']
7
8
 
8
9
  # %% ../nbs/00_core.ipynb
9
10
  from fastcore.meta import delegates
10
11
  from fastcore.utils import patch,dict2obj
12
+ from fastcore.docments import sig_source,DocmentText
13
+ from fastcore.net import HTTP404NotFoundError
11
14
  from types import ModuleType, FunctionType, MethodType, BuiltinFunctionType
12
15
  from inspect import signature, currentframe
13
16
  from functools import cmp_to_key,partial
@@ -15,9 +18,12 @@ from collections.abc import Mapping
15
18
  from textwrap import dedent
16
19
  from cloudscraper import create_scraper
17
20
  from toolslm.funccall import *
21
+ from toolslm.xml import *
18
22
  from ast import literal_eval
23
+ from urllib.parse import urlparse, urljoin
24
+ from ghapi.all import GhApi
19
25
 
20
- import typing,warnings,re
26
+ import typing,warnings,re,os,html2text,base64
21
27
 
22
28
  from IPython.core.interactiveshell import InteractiveShell
23
29
  from IPython.core.completer import ProvisionalCompleterWarning
@@ -115,7 +121,7 @@ def get_vars(self:InteractiveShell, vs:list, literal=True):
115
121
  def _get_schema(ns: dict, t):
116
122
  "Check if tool `t` has errors."
117
123
  if t not in ns: return f"`{t}` not found. Did you run it?"
118
- try: return get_schema(ns[t])
124
+ try: return {'type':'function', 'function':get_schema(ns[t], pname='parameters', evalable=True, skip_hidden=True)}
119
125
  except Exception as e: return f"`{t}`: {e}."
120
126
 
121
127
  @patch
@@ -146,65 +152,130 @@ def run_cmd(cmd, data='', meta=None, update=False, **kw):
146
152
  transient(data, meta=meta, update=update, cmd=cmd, **kw)
147
153
 
148
154
  # %% ../nbs/00_core.ipynb
149
- def get_md(cts):
150
- from html2text import HTML2Text
151
- h2t = HTML2Text(bodywidth=5000)
152
- h2t.ignore_links = False
153
- h2t.mark_code = True
154
- h2t.ignore_images = False
155
- res = h2t.handle(cts)
156
- def _f(m): return f'```\n{dedent(m.group(1))}\n```'
157
- return re.sub(r'\[code]\s*\n(.*?)\n\[/code]', _f, res or '', flags=re.DOTALL).strip()
155
+ def _absolutify_imgs(md, base_url):
156
+ def fix(m):
157
+ alt,img_url = m.group(1),m.group(2)
158
+ if not img_url.startswith('http'): img_url = urljoin(base_url, img_url)
159
+ alt = alt.replace('\\','')
160
+ return f'![{alt}]({img_url})'
161
+ return re.sub(r'!\[(.*?)\]\((.*?)\)', fix, md)
162
+
163
+ # %% ../nbs/00_core.ipynb
164
+ def get_md(html, url='', mmode=None, ignore_links=False, ignore_images=False, mark_code=True):
165
+ "Convert HTML to markdown with absolute image URLs and optional math mode"
166
+ h = html2text.HTML2Text()
167
+ h.body_width = 0
168
+ h.ignore_links, h.ignore_images, h.mark_code = ignore_links, ignore_images, mark_code
169
+ res = _absolutify_imgs(h.handle(str(html)), url)
170
+ if mmode == 'safe': res = res.replace(r'\\(',r'\(').replace(r'\\)',r'\)')
171
+ return re.sub(r'\[code]\s*\n(.*?)\n\[/code]', lambda m: f'```\n{dedent(m.group(1))}\n```', res, flags=re.DOTALL).strip()
158
172
 
159
173
  # %% ../nbs/00_core.ipynb
160
174
  def scrape_url(url): return create_scraper().get(url)
161
175
 
162
176
  # %% ../nbs/00_core.ipynb
163
- def read_url(
164
- url:str, # URL to read
165
- as_md:bool=True, # Convert HTML to Markdown?
166
- extract_section:bool=True, # If url has an anchor, return only that section
167
- selector:str=None # Select section(s) using BeautifulSoup.select (overrides extract_section)
168
- ):
169
- "Read URL and return contents"
170
- from urllib.parse import urlparse
177
+ def _get_math_mode():
178
+ v = os.getenv('USE_KATEX', '')
179
+ if v.lower() in {'0', 'false', 'none', ''}: return None
180
+ return 'dollar' if v.lower().startswith('d') else 'safe'
181
+
182
+ # %% ../nbs/00_core.ipynb
183
+ def _aify_imgs(md): return re.sub(r'!\[(.*?)\]\((.*?)\)', r'![\1](\2#ai)', md)
184
+
185
+ # %% ../nbs/00_core.ipynb
186
+ def gh_blob_to_raw(url):
187
+ "Convert github.com/user/repo/blob/... URL to raw.githubusercontent.com URL"
188
+ m = re.match(r'https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/blob/([^/]+)/(.+)', url)
189
+ if not m: return url
190
+ owner, repo, ref, path = m.groups()
191
+ return f'https://raw.githubusercontent.com/{owner}/{repo}/{ref}/{path}'
192
+
193
+ # %% ../nbs/00_core.ipynb
194
+ def _extract_section(soup, url, selector=None):
195
+ "Extract a specific section from soup, or the whole thing"
196
+ if selector: return '\n\n'.join(str(s) for s in soup.select(selector))
197
+ parsed = urlparse(url)
198
+ if not parsed.fragment: return str(soup)
199
+ section = soup.find(id=parsed.fragment)
200
+ if not section: return ''
201
+ elements = [section]
202
+ current = section.next_sibling
203
+ while current:
204
+ if hasattr(current, 'name') and current.name == section.name: break
205
+ elements.append(current)
206
+ current = current.next_sibling
207
+ return ''.join(str(el) for el in elements)
208
+
209
+ # %% ../nbs/00_core.ipynb
210
+ def _convert_math(soup, mode):
211
+ for math in soup.find_all('math'):
212
+ annot = math.find('annotation', {'encoding': 'application/x-tex'})
213
+ if not annot: continue
214
+ tex,display = annot.text.strip(), math.get('display') == 'block'
215
+ if mode == 'dollar': wrap = f'$${tex}$$' if display else f'${tex}$'
216
+ else: wrap = f'$${tex}$$' if display else fr'\({tex}\)'
217
+ math.replace_with(wrap)
218
+
219
+ # %% ../nbs/00_core.ipynb
220
+ def read_gh_repo(owner, repo, ref=None, path=''):
221
+ "Read GitHub repo info: description, file list, and README"
222
+ api = GhApi()
223
+ info = api.repos.get(owner, repo)
224
+ res = [f"# {info.full_name}", info.description or '']
225
+ ref = ref or info.default_branch
226
+ contents = api.repos.get_content(owner, repo, path or '', ref=ref)
227
+ files = [f"- {'📁 ' if c.type=='dir' else ''}{c.name}" for c in contents]
228
+ res.append(f'\n## /{path or ""} Files\n' + '\n'.join(files))
229
+ if not path:
230
+ try:
231
+ readme = api.repos.get_readme(owner, repo, ref=ref)
232
+ res.append('\n## README\n' + base64.b64decode(readme.content).decode())
233
+ except HTTP404NotFoundError: pass
234
+ return '\n'.join(res)
235
+
236
+ # %% ../nbs/00_core.ipynb
237
+ def read_url(url:str, as_md:bool=True, extract_section:bool=True, selector:str=None, ai_img:bool=False):
238
+ "Read url from web"
171
239
  from bs4 import BeautifulSoup
172
-
240
+ gh = parse_gh_url(url)
241
+ if gh:
242
+ if gh['typ']=='blob': url = gh_blob_to_raw(url)
243
+ elif gh['typ'] in (None, 'tree'): return read_gh_repo(gh['owner'], gh['repo'], gh['ref'], gh['path'])
173
244
  o = scrape_url(url)
174
- res, ctype = o.text, o.headers.get('content-type').split(';')[0]
175
-
176
- soup = BeautifulSoup(res, "html.parser")
177
-
178
- if selector:
179
- sections = soup.select(selector)
180
- if sections: res = '\n\n'.join(str(section) for section in sections)
181
- else: res = ''
182
- elif extract_section:
183
- parsed = urlparse(url)
184
- if parsed.fragment:
185
- section = soup.find(id=parsed.fragment)
186
- if section:
187
- tag_name = section.name
188
- elements = [section]
189
- current = section.next_sibling
190
- while current:
191
- if hasattr(current, 'name') and current.name == tag_name: break
192
- elements.append(current)
193
- current = current.next_sibling
194
- res = ''.join(str(el) for el in elements)
195
- else: res = ''
196
- if as_md and ctype == 'text/html': return get_md(res)
245
+ ctype = (o.headers.get('content-type') or 'text/plain').split(';')[0]
246
+ res = o.text
247
+ if ctype == 'text/html':
248
+ soup = BeautifulSoup(res, 'lxml')
249
+ if ('#' in url and extract_section) or selector: soup = BeautifulSoup(_extract_section(soup, url, selector), 'lxml')
250
+ mmode = _get_math_mode()
251
+ if mmode: _convert_math(soup, mmode)
252
+ base = soup.find('base')
253
+ base_url = urljoin(url, base['href'] if base else '')
254
+ res = get_md(soup, base_url, mmode) if as_md else str(soup)
255
+ if ai_img: res = _aify_imgs(res)
197
256
  return res
198
257
 
258
+ # %% ../nbs/00_core.ipynb
259
+ def fix_editable_priority():
260
+ import sys
261
+ from importlib.machinery import PathFinder
262
+ try: sys.meta_path.append(sys.meta_path.pop(sys.meta_path.index(PathFinder)))
263
+ except ValueError: pass
264
+
199
265
  # %% ../nbs/00_core.ipynb
200
266
  @patch
201
267
  def _get_info(self:Inspector, obj, oname='', formatter=None, info=None, detail_level=0, omit_sections=()):
202
- "Custom formatter for ?? output"
268
+ "Custom formatter for ? and ?? output"
203
269
  orig = self._orig__get_info(obj, oname=oname, formatter=formatter, info=info,
204
270
  detail_level=detail_level, omit_sections=omit_sections)
205
- if detail_level==0: return orig
206
- info_dict = self.info(obj, oname=oname, info=info, detail_level=detail_level)
271
+ info_dict = self.info(obj, oname=oname, info=info, detail_level=2)
207
272
  out = []
273
+ if detail_level==0:
274
+ out.append(f"```python\n{DocmentText(obj)}\n```")
275
+ if c:=info_dict.get('docstring'): out.append(c)
276
+ if c:=info_dict.get('file'): out.append(f"**File:** `{c}`")
277
+ if c:=info_dict.get('type_name'): out.append(f"**Type:** {c}")
278
+ return {'text/markdown': '\n\n'.join(out), 'text/html': '', 'text/plain': orig['text/plain']}
208
279
  if c:=info_dict.get('source'): out.append(f"\n```python\n{dedent(c)}\n```")
209
280
  if c:=info_dict.get('file'): out.append(f"**File:** `{c}`")
210
281
  return {'text/markdown': '\n\n'.join(out), 'text/html': '', 'text/plain': orig['text/plain']}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ipykernel-helper
3
- Version: 0.0.14
3
+ Version: 0.0.25
4
4
  Summary: Helpers for ipykernel and friends
5
5
  Home-page: https://github.com/AnswerDotAI/ipykernel-helper
6
6
  Author: Jeremy Howard
@@ -18,14 +18,16 @@ Classifier: License :: OSI Approved :: Apache Software License
18
18
  Requires-Python: >=3.9
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: fastcore
22
- Requires-Dist: toolslm>=0.2.0
21
+ Requires-Dist: fastcore>=1.11.0
22
+ Requires-Dist: toolslm>=0.3.13
23
23
  Requires-Dist: jedi
24
24
  Requires-Dist: ipython
25
25
  Requires-Dist: ipykernel
26
26
  Requires-Dist: beautifulsoup4
27
+ Requires-Dist: lxml
27
28
  Requires-Dist: html2text
28
29
  Requires-Dist: cloudscraper
30
+ Requires-Dist: ghapi
29
31
  Provides-Extra: dev
30
32
  Dynamic: author
31
33
  Dynamic: author-email
@@ -1,10 +1,12 @@
1
- fastcore
2
- toolslm>=0.2.0
1
+ fastcore>=1.11.0
2
+ toolslm>=0.3.13
3
3
  jedi
4
4
  ipython
5
5
  ipykernel
6
6
  beautifulsoup4
7
+ lxml
7
8
  html2text
8
9
  cloudscraper
10
+ ghapi
9
11
 
10
12
  [dev]
@@ -1,11 +1,11 @@
1
1
  [DEFAULT]
2
2
  repo = ipykernel-helper
3
3
  lib_name = ipykernel-helper
4
- version = 0.0.14
4
+ version = 0.0.25
5
5
  min_python = 3.9
6
6
  license = apache2
7
7
  black_formatting = False
8
- requirements = fastcore toolslm>=0.2.0 jedi ipython ipykernel beautifulsoup4 html2text cloudscraper
8
+ requirements = fastcore>=1.11.0 toolslm>=0.3.13 jedi ipython ipykernel beautifulsoup4 lxml html2text cloudscraper ghapi
9
9
  cell_number = False
10
10
  doc_path = _docs
11
11
  lib_path = ipykernel_helper
@@ -1,2 +0,0 @@
1
- __version__ = "0.0.14"
2
- from .core import *