ipykernel-helper 0.0.12__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.12/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.12 → ipykernel_helper-0.0.25}/ipykernel_helper/_modidx.py +9 -0
  4. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/ipykernel_helper/core.py +125 -48
  5. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25/ipykernel_helper.egg-info}/PKG-INFO +5 -3
  6. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/requires.txt +4 -2
  7. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/settings.ini +2 -2
  8. ipykernel_helper-0.0.12/ipykernel_helper/__init__.py +0 -2
  9. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/LICENSE +0 -0
  10. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/MANIFEST.in +0 -0
  11. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/README.md +0 -0
  12. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/SOURCES.txt +0 -0
  13. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/dependency_links.txt +0 -0
  14. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/entry_points.txt +0 -0
  15. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/not-zip-safe +0 -0
  16. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/ipykernel_helper.egg-info/top_level.txt +0 -0
  17. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/pyproject.toml +0 -0
  18. {ipykernel_helper-0.0.12 → ipykernel_helper-0.0.25}/setup.cfg +0 -0
  19. {ipykernel_helper-0.0.12 → 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.12
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,8 +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 *
22
+ from ast import literal_eval
23
+ from urllib.parse import urlparse, urljoin
24
+ from ghapi.all import GhApi
18
25
 
19
- import typing,warnings,re
26
+ import typing,warnings,re,os,html2text,base64
20
27
 
21
28
  from IPython.core.interactiveshell import InteractiveShell
22
29
  from IPython.core.completer import ProvisionalCompleterWarning
@@ -102,16 +109,19 @@ def sig_help(self:InteractiveShell, code, line_no=None, col_no=None):
102
109
 
103
110
  # %% ../nbs/00_core.ipynb
104
111
  @patch
105
- def get_vars(self:InteractiveShell, vs:list):
112
+ def get_vars(self:InteractiveShell, vs:list, literal=True):
106
113
  "Get variables from namespace."
107
114
  ns = self.user_ns
108
- return {v:ns[v] for v in vs if v in ns}
115
+ def _maybe_eval(o):
116
+ try: literal_eval(repr(o)); return o
117
+ except: return str(o)
118
+ return {v:_maybe_eval(ns[v]) if literal else str(ns[v]) for v in vs if v in ns}
109
119
 
110
120
  # %% ../nbs/00_core.ipynb
111
121
  def _get_schema(ns: dict, t):
112
122
  "Check if tool `t` has errors."
113
123
  if t not in ns: return f"`{t}` not found. Did you run it?"
114
- try: return get_schema(ns[t])
124
+ try: return {'type':'function', 'function':get_schema(ns[t], pname='parameters', evalable=True, skip_hidden=True)}
115
125
  except Exception as e: return f"`{t}`: {e}."
116
126
 
117
127
  @patch
@@ -142,63 +152,130 @@ def run_cmd(cmd, data='', meta=None, update=False, **kw):
142
152
  transient(data, meta=meta, update=update, cmd=cmd, **kw)
143
153
 
144
154
  # %% ../nbs/00_core.ipynb
145
- def get_md(cts):
146
- from html2text import HTML2Text
147
- h2t = HTML2Text(bodywidth=5000)
148
- h2t.ignore_links = False
149
- h2t.mark_code = True
150
- h2t.ignore_images = False
151
- res = h2t.handle(cts)
152
- def _f(m): return f'```\n{dedent(m.group(1))}\n```'
153
- 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()
154
172
 
155
173
  # %% ../nbs/00_core.ipynb
156
174
  def scrape_url(url): return create_scraper().get(url)
157
175
 
158
176
  # %% ../nbs/00_core.ipynb
159
- def read_url(
160
- url:str, # URL to read
161
- as_md:bool=True, # Convert HTML to Markdown?
162
- extract_section:bool=True, # If url has an anchor, return only that section
163
- selector:str=None # Select section(s) using BeautifulSoup.select (overrides extract_section)
164
- ):
165
- "Read URL and return contents"
166
- 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"
167
239
  from bs4 import BeautifulSoup
168
-
169
- res = scrape_url(url).text
170
- soup = BeautifulSoup(res, "html.parser")
171
-
172
- if selector:
173
- sections = soup.select(selector)
174
- if sections: res = '\n\n'.join(str(section) for section in sections)
175
- else: res = ''
176
- elif extract_section:
177
- parsed = urlparse(url)
178
- if parsed.fragment:
179
- section = soup.find(id=parsed.fragment)
180
- if section:
181
- tag_name = section.name
182
- elements = [section]
183
- current = section.next_sibling
184
- while current:
185
- if hasattr(current, 'name') and current.name == tag_name: break
186
- elements.append(current)
187
- current = current.next_sibling
188
- res = ''.join(str(el) for el in elements)
189
- else: res = ''
190
- if as_md: return get_md(res)
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'])
244
+ o = scrape_url(url)
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)
191
256
  return res
192
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
+
193
265
  # %% ../nbs/00_core.ipynb
194
266
  @patch
195
267
  def _get_info(self:Inspector, obj, oname='', formatter=None, info=None, detail_level=0, omit_sections=()):
196
- "Custom formatter for ?? output"
268
+ "Custom formatter for ? and ?? output"
197
269
  orig = self._orig__get_info(obj, oname=oname, formatter=formatter, info=info,
198
270
  detail_level=detail_level, omit_sections=omit_sections)
199
- if detail_level==0: return orig
200
- 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)
201
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']}
202
279
  if c:=info_dict.get('source'): out.append(f"\n```python\n{dedent(c)}\n```")
203
280
  if c:=info_dict.get('file'): out.append(f"**File:** `{c}`")
204
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.12
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.12
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.12"
2
- from .core import *