toolslm 0.3.3__py3-none-any.whl → 0.3.7__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.
- toolslm/__init__.py +1 -1
- toolslm/_modidx.py +7 -3
- toolslm/funccall.py +56 -12
- toolslm/md_hier.py +35 -6
- toolslm/xml.py +55 -25
- {toolslm-0.3.3.dist-info → toolslm-0.3.7.dist-info}/METADATA +2 -2
- toolslm-0.3.7.dist-info/RECORD +13 -0
- toolslm-0.3.3.dist-info/RECORD +0 -13
- {toolslm-0.3.3.dist-info → toolslm-0.3.7.dist-info}/WHEEL +0 -0
- {toolslm-0.3.3.dist-info → toolslm-0.3.7.dist-info}/entry_points.txt +0 -0
- {toolslm-0.3.3.dist-info → toolslm-0.3.7.dist-info}/licenses/LICENSE +0 -0
- {toolslm-0.3.3.dist-info → toolslm-0.3.7.dist-info}/top_level.txt +0 -0
toolslm/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.3.
|
|
1
|
+
__version__ = "0.3.7"
|
toolslm/_modidx.py
CHANGED
|
@@ -14,7 +14,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
14
14
|
'toolslm.download.read_html': ('download.html#read_html', 'toolslm/download.py'),
|
|
15
15
|
'toolslm.download.read_md': ('download.html#read_md', 'toolslm/download.py'),
|
|
16
16
|
'toolslm.download.split_url': ('download.html#split_url', 'toolslm/download.py')},
|
|
17
|
-
'toolslm.funccall': { 'toolslm.funccall.
|
|
17
|
+
'toolslm.funccall': { 'toolslm.funccall._coerce_inputs': ('funccall.html#_coerce_inputs', 'toolslm/funccall.py'),
|
|
18
18
|
'toolslm.funccall._copy_loc': ('funccall.html#_copy_loc', 'toolslm/funccall.py'),
|
|
19
19
|
'toolslm.funccall._get_nested_schema': ('funccall.html#_get_nested_schema', 'toolslm/funccall.py'),
|
|
20
20
|
'toolslm.funccall._handle_container': ('funccall.html#_handle_container', 'toolslm/funccall.py'),
|
|
@@ -29,7 +29,10 @@ d = { 'settings': { 'branch': 'main',
|
|
|
29
29
|
'toolslm.funccall.call_func_async': ('funccall.html#call_func_async', 'toolslm/funccall.py'),
|
|
30
30
|
'toolslm.funccall.get_schema': ('funccall.html#get_schema', 'toolslm/funccall.py'),
|
|
31
31
|
'toolslm.funccall.mk_ns': ('funccall.html#mk_ns', 'toolslm/funccall.py'),
|
|
32
|
-
'toolslm.funccall.
|
|
32
|
+
'toolslm.funccall.mk_param': ('funccall.html#mk_param', 'toolslm/funccall.py'),
|
|
33
|
+
'toolslm.funccall.mk_tool': ('funccall.html#mk_tool', 'toolslm/funccall.py'),
|
|
34
|
+
'toolslm.funccall.python': ('funccall.html#python', 'toolslm/funccall.py'),
|
|
35
|
+
'toolslm.funccall.schema2sig': ('funccall.html#schema2sig', 'toolslm/funccall.py')},
|
|
33
36
|
'toolslm.md_hier': {},
|
|
34
37
|
'toolslm.shell': { 'toolslm.shell.TerminalInteractiveShell.run_cell': ( 'shell.html#terminalinteractiveshell.run_cell',
|
|
35
38
|
'toolslm/shell.py'),
|
|
@@ -46,4 +49,5 @@ d = { 'settings': { 'branch': 'main',
|
|
|
46
49
|
'toolslm.xml.mk_doc': ('xml.html#mk_doc', 'toolslm/xml.py'),
|
|
47
50
|
'toolslm.xml.mk_doctype': ('xml.html#mk_doctype', 'toolslm/xml.py'),
|
|
48
51
|
'toolslm.xml.nb2xml': ('xml.html#nb2xml', 'toolslm/xml.py'),
|
|
49
|
-
'toolslm.xml.read_file': ('xml.html#read_file', 'toolslm/xml.py')
|
|
52
|
+
'toolslm.xml.read_file': ('xml.html#read_file', 'toolslm/xml.py'),
|
|
53
|
+
'toolslm.xml.repo2ctx': ('xml.html#repo2ctx', 'toolslm/xml.py')}}}
|
toolslm/funccall.py
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../01_funccall.ipynb.
|
|
2
2
|
|
|
3
3
|
# %% auto 0
|
|
4
|
-
__all__ = ['empty', 'custom_types', 'get_schema', '
|
|
4
|
+
__all__ = ['empty', 'custom_types', 'get_schema', 'python', 'mk_ns', 'call_func', 'call_func_async', 'mk_param', 'schema2sig',
|
|
5
|
+
'mk_tool']
|
|
5
6
|
|
|
6
7
|
# %% ../01_funccall.ipynb
|
|
7
|
-
import inspect
|
|
8
|
+
import inspect, json
|
|
8
9
|
from collections import abc
|
|
9
10
|
from fastcore.utils import *
|
|
10
11
|
from fastcore.docments import docments
|
|
11
|
-
from typing import get_origin, get_args, Dict, List, Optional, Tuple, Union
|
|
12
|
+
from typing import get_origin, get_args, Dict, List, Optional, Tuple, Union, Any
|
|
12
13
|
from types import UnionType
|
|
14
|
+
from typing import get_type_hints
|
|
15
|
+
from inspect import Parameter, Signature
|
|
16
|
+
from decimal import Decimal
|
|
17
|
+
from uuid import UUID
|
|
13
18
|
|
|
14
19
|
# %% ../01_funccall.ipynb
|
|
15
20
|
empty = inspect.Parameter.empty
|
|
@@ -41,7 +46,7 @@ def _param(name, info):
|
|
|
41
46
|
return pschema
|
|
42
47
|
|
|
43
48
|
# %% ../01_funccall.ipynb
|
|
44
|
-
custom_types = {Path}
|
|
49
|
+
custom_types = {Path, bytes, Decimal, UUID}
|
|
45
50
|
|
|
46
51
|
def _handle_type(t, defs):
|
|
47
52
|
"Handle a single type, creating nested schemas if necessary"
|
|
@@ -123,14 +128,9 @@ def get_schema(f:Union[callable,dict], pname='input_schema')->dict:
|
|
|
123
128
|
assert desc, "Docstring missing!"
|
|
124
129
|
d = docments(f, full=True)
|
|
125
130
|
ret = d.pop('return')
|
|
126
|
-
if ret.anno is not empty: desc += f'\n\nReturns:\n- type: {_types(ret.anno)[0]}'
|
|
131
|
+
if (ret.anno is not empty) and (ret.anno is not None): desc += f'\n\nReturns:\n- type: {_types(ret.anno)[0]}'
|
|
127
132
|
return {"name": f.__name__, "description": desc, pname: schema}
|
|
128
133
|
|
|
129
|
-
# %% ../01_funccall.ipynb
|
|
130
|
-
def PathArg(
|
|
131
|
-
path: str # A filesystem path
|
|
132
|
-
): return Path(path)
|
|
133
|
-
|
|
134
134
|
# %% ../01_funccall.ipynb
|
|
135
135
|
import ast, time, signal, traceback
|
|
136
136
|
from fastcore.utils import *
|
|
@@ -193,14 +193,26 @@ def mk_ns(fs):
|
|
|
193
193
|
elif callable(o) and hasattr(o, '__name__'): merged |= {o.__name__: o}
|
|
194
194
|
return merged
|
|
195
195
|
|
|
196
|
+
# %% ../01_funccall.ipynb
|
|
197
|
+
def _coerce_inputs(func, inputs):
|
|
198
|
+
"Coerce inputs based on function type annotations"
|
|
199
|
+
hints = get_type_hints(func) if hasattr(func, '__annotations__') else {}
|
|
200
|
+
res = {}
|
|
201
|
+
for k,v in inputs.items():
|
|
202
|
+
ann = hints.get(k)
|
|
203
|
+
if ann in custom_types: res[k] = ann(v)
|
|
204
|
+
elif isinstance(v, dict) and callable(ann): res[k] = ann(**v)
|
|
205
|
+
else: res[k] = v
|
|
206
|
+
return res
|
|
207
|
+
|
|
196
208
|
# %% ../01_funccall.ipynb
|
|
197
209
|
def call_func(fc_name, fc_inputs, ns, raise_on_err=True):
|
|
198
210
|
"Call the function `fc_name` with the given `fc_inputs` using namespace `ns`."
|
|
199
211
|
if not isinstance(ns, abc.Mapping): ns = mk_ns(ns)
|
|
200
212
|
func = ns[fc_name]
|
|
201
|
-
# Clean up bad param names
|
|
202
213
|
inps = {re.sub(r'\W', '', k):v for k,v in fc_inputs.items()}
|
|
203
|
-
|
|
214
|
+
inps = _coerce_inputs(func, inps)
|
|
215
|
+
try: return func(**inps)
|
|
204
216
|
except Exception as e:
|
|
205
217
|
if raise_on_err: raise e from None
|
|
206
218
|
else: return traceback.format_exc()
|
|
@@ -215,3 +227,35 @@ async def call_func_async(fc_name, fc_inputs, ns, raise_on_err=True):
|
|
|
215
227
|
if raise_on_err: raise e from None
|
|
216
228
|
else: return traceback.format_exc()
|
|
217
229
|
return res
|
|
230
|
+
|
|
231
|
+
# %% ../01_funccall.ipynb
|
|
232
|
+
def mk_param(nm, props, req):
|
|
233
|
+
"Create a `Parameter` for `nm` with schema `props`"
|
|
234
|
+
kind = Parameter.POSITIONAL_OR_KEYWORD if nm in req else Parameter.KEYWORD_ONLY
|
|
235
|
+
default = Parameter.empty if nm in req else props.get('default')
|
|
236
|
+
if props.get('type') == 'array' and 'items' in props:
|
|
237
|
+
item_type = type_map.get(props['items'].get('type'), Any)
|
|
238
|
+
anno = list[item_type]
|
|
239
|
+
else: anno = type_map.get(props.get('type'), Any)
|
|
240
|
+
return Parameter(nm, kind, default=default, annotation=anno)
|
|
241
|
+
|
|
242
|
+
# %% ../01_funccall.ipynb
|
|
243
|
+
def schema2sig(tool):
|
|
244
|
+
"Convert json schema `tool` to a `Signature`"
|
|
245
|
+
props, req = tool.inputSchema['properties'], tool.inputSchema.get('required', [])
|
|
246
|
+
params = sorted([mk_param(k, v, req) for k, v in props.items()], key=lambda p: p.kind)
|
|
247
|
+
return Signature(params)
|
|
248
|
+
|
|
249
|
+
# %% ../01_funccall.ipynb
|
|
250
|
+
def mk_tool(dispfn, tool):
|
|
251
|
+
"Create a callable function from a JSON schema tool definition"
|
|
252
|
+
sig = schema2sig(tool)
|
|
253
|
+
props = tool.inputSchema['properties']
|
|
254
|
+
def fn(*args, **kwargs):
|
|
255
|
+
bound = sig.bind(*args, **kwargs)
|
|
256
|
+
return dispfn(tool.name, **bound.arguments)
|
|
257
|
+
fn.__doc__ = tool.description
|
|
258
|
+
fn.__signature__ = sig
|
|
259
|
+
fn.__name__ = fn.__qualname__ = tool.name
|
|
260
|
+
fn.__annotations__ = {k: p.annotation for k, p in sig.parameters.items()}
|
|
261
|
+
return fn
|
toolslm/md_hier.py
CHANGED
|
@@ -14,20 +14,32 @@ def create_heading_dict(text, rm_fenced=True):
|
|
|
14
14
|
original_text = text
|
|
15
15
|
original_lines = text.splitlines()
|
|
16
16
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
# Build line mapping when removing fenced blocks
|
|
18
|
+
if rm_fenced:
|
|
19
|
+
filtered_lines,original_line_map,in_fenced = [],{},False
|
|
20
|
+
for i, line in enumerate(original_lines):
|
|
21
|
+
if line.strip().startswith('```'):
|
|
22
|
+
in_fenced = not in_fenced
|
|
23
|
+
continue
|
|
24
|
+
if not in_fenced:
|
|
25
|
+
original_line_map[len(filtered_lines)] = i
|
|
26
|
+
filtered_lines.append(line)
|
|
27
|
+
|
|
28
|
+
lines_for_headings = filtered_lines
|
|
29
|
+
else:
|
|
30
|
+
lines_for_headings = original_lines
|
|
31
|
+
original_line_map = {i: i for i in range(len(original_lines))}
|
|
20
32
|
|
|
21
|
-
lines_for_headings = text_for_headings.splitlines()
|
|
22
33
|
headings = []
|
|
23
34
|
|
|
24
|
-
# Parse headings with their levels and line numbers
|
|
35
|
+
# Parse headings with their levels and original line numbers
|
|
25
36
|
for idx, line in enumerate(lines_for_headings):
|
|
26
37
|
match = re.match(r'^(#{1,6})\s+\S.*', line)
|
|
27
38
|
if match:
|
|
28
39
|
level = len(match.group(1))
|
|
29
40
|
title = line.strip('#').strip()
|
|
30
|
-
|
|
41
|
+
original_line_idx = original_line_map[idx]
|
|
42
|
+
headings.append({'level': level, 'title': title, 'line': original_line_idx})
|
|
31
43
|
|
|
32
44
|
# Assign text content to each heading using original lines
|
|
33
45
|
for i, h in enumerate(headings):
|
|
@@ -270,9 +282,26 @@ More content after code."""
|
|
|
270
282
|
assert '💻 Computer' in result['🚀 Rocket Heading']
|
|
271
283
|
assert result.text == md_content
|
|
272
284
|
|
|
285
|
+
def test_fenced_blocks_between_headings():
|
|
286
|
+
md_content = """# First Header
|
|
287
|
+
Content here.
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
# A comment that should be ignored for structure
|
|
291
|
+
def example():
|
|
292
|
+
pass
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
# Second Header
|
|
296
|
+
This content belongs to Second Header."""
|
|
297
|
+
result = create_heading_dict(md_content)
|
|
298
|
+
assert "def example():" not in result['Second Header'].text
|
|
299
|
+
assert result['Second Header'].text == "# Second Header\nThis content belongs to Second Header."
|
|
300
|
+
|
|
273
301
|
test_empty_input()
|
|
274
302
|
test_whitespace_only()
|
|
275
303
|
test_malformed_headings()
|
|
276
304
|
test_unicode_and_emojis()
|
|
305
|
+
test_fenced_blocks_between_headings()
|
|
277
306
|
print('tests passed')
|
|
278
307
|
|
toolslm/xml.py
CHANGED
|
@@ -2,19 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
# %% auto 0
|
|
4
4
|
__all__ = ['doctype', 'json_to_xml', 'get_mime_text', 'cell2out', 'cell2xml', 'nb2xml', 'mk_doctype', 'mk_doc', 'docs_xml',
|
|
5
|
-
'read_file', 'files2ctx', 'folder2ctx', 'folder2ctx_cli']
|
|
5
|
+
'read_file', 'files2ctx', 'folder2ctx', 'repo2ctx', 'folder2ctx_cli']
|
|
6
6
|
|
|
7
7
|
# %% ../00_xml.ipynb
|
|
8
8
|
import hashlib,xml.etree.ElementTree as ET
|
|
9
9
|
from collections import namedtuple
|
|
10
|
+
from ghapi.all import GhApi
|
|
10
11
|
|
|
11
12
|
from fastcore.utils import *
|
|
12
13
|
from fastcore.meta import delegates
|
|
13
14
|
from fastcore.xtras import hl_md
|
|
14
|
-
from fastcore.xml import to_xml, Document, Documents, Document_content, Src, Source,Out,Outs,Cell
|
|
15
|
+
from fastcore.xml import to_xml, Document, Documents, Document_content, Src, Source,Out,Outs,Cell,Notebook,Md,Code
|
|
15
16
|
from fastcore.script import call_parse
|
|
16
|
-
try: from IPython import display
|
|
17
|
-
except: display=None
|
|
18
17
|
|
|
19
18
|
# %% ../00_xml.ipynb
|
|
20
19
|
def json_to_xml(d:dict, # JSON dictionary to convert
|
|
@@ -50,20 +49,23 @@ def cell2out(o):
|
|
|
50
49
|
if hasattr(o, 'ename'): return Out(f"{o.ename}: {o.evalue}", type='error')
|
|
51
50
|
|
|
52
51
|
# %% ../00_xml.ipynb
|
|
53
|
-
def cell2xml(cell):
|
|
52
|
+
def cell2xml(cell, out=True):
|
|
54
53
|
"Convert notebook cell to concise XML format"
|
|
55
|
-
|
|
54
|
+
src = ''.join(getattr(cell, 'source', ''))
|
|
55
|
+
f = Code if cell.cell_type=='code' else Md
|
|
56
|
+
if not out: return f(src)
|
|
57
|
+
parts = [Source(src)]
|
|
56
58
|
out_items = L(getattr(cell,'outputs',[])).map(cell2out).filter()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
parts = [p for p in [cts, outs] if p]
|
|
60
|
-
return Cell(*parts, type=cell.cell_type)
|
|
59
|
+
if out_items: parts.append(Outs(*out_items))
|
|
60
|
+
return f(*parts)
|
|
61
61
|
|
|
62
62
|
# %% ../00_xml.ipynb
|
|
63
|
-
def nb2xml(fname):
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
def nb2xml(fname=None, nb=None, out=True):
|
|
64
|
+
"Convert notebook to XML format"
|
|
65
|
+
assert bool(fname)^bool(nb), "Pass either `fname` or `nb`"
|
|
66
|
+
if not nb: nb = dict2obj(fname.read_json())
|
|
67
|
+
cells_xml = [to_xml(cell2xml(c, out=out), do_escape=False) for c in nb.cells if c.cell_type in ('code','markdown')]
|
|
68
|
+
return to_xml(Notebook(*cells_xml), do_escape=False)
|
|
67
69
|
|
|
68
70
|
# %% ../00_xml.ipynb
|
|
69
71
|
doctype = namedtuple('doctype', ['src', 'content'])
|
|
@@ -110,37 +112,65 @@ def docs_xml(docs:list[str], # The content of each document
|
|
|
110
112
|
return pre + to_xml(Documents(docs), do_escape=False)
|
|
111
113
|
|
|
112
114
|
# %% ../00_xml.ipynb
|
|
113
|
-
def read_file(fname):
|
|
115
|
+
def read_file(fname, out=True):
|
|
114
116
|
"Read file content, converting notebooks to XML if needed"
|
|
115
117
|
fname = Path(fname)
|
|
116
|
-
if fname.suffix == '.ipynb': return nb2xml(fname)
|
|
118
|
+
if fname.suffix == '.ipynb': return nb2xml(fname, out=out)
|
|
117
119
|
return fname.read_text()
|
|
118
120
|
|
|
119
121
|
# %% ../00_xml.ipynb
|
|
120
122
|
def files2ctx(
|
|
121
123
|
fnames:list[Union[str,Path]], # List of file names to add to context
|
|
122
|
-
prefix:bool=True # Include Anthropic's suggested prose intro?
|
|
124
|
+
prefix:bool=True, # Include Anthropic's suggested prose intro?
|
|
125
|
+
out:bool=True, # Include notebook cell outputs?
|
|
126
|
+
srcs:Optional[list]=None # Use the labels instead of `fnames`
|
|
123
127
|
)->str: # XML for LM context
|
|
124
128
|
"Convert files to XML context, handling notebooks"
|
|
125
129
|
fnames = [Path(o) for o in fnames]
|
|
126
|
-
contents = [read_file(o) for o in fnames]
|
|
127
|
-
return docs_xml(contents, fnames, prefix=prefix)
|
|
130
|
+
contents = [read_file(o, out=out) for o in fnames]
|
|
131
|
+
return docs_xml(contents, srcs or fnames, prefix=prefix)
|
|
128
132
|
|
|
129
133
|
# %% ../00_xml.ipynb
|
|
130
134
|
@delegates(globtastic)
|
|
131
135
|
def folder2ctx(
|
|
132
|
-
folder:Union[str,Path],
|
|
133
|
-
prefix:bool=True,
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
folder:Union[str,Path],
|
|
137
|
+
prefix:bool=True,
|
|
138
|
+
out:bool=True,
|
|
139
|
+
include_base:bool=True,
|
|
140
|
+
**kwargs
|
|
141
|
+
)->str:
|
|
142
|
+
"Convert folder contents to XML context, handling notebooks"
|
|
143
|
+
folder = Path(folder)
|
|
136
144
|
fnames = globtastic(folder, **kwargs)
|
|
137
|
-
|
|
145
|
+
srcs = fnames if include_base else [Path(f).relative_to(folder) for f in fnames]
|
|
146
|
+
return files2ctx(fnames, prefix=prefix, out=out, srcs=srcs)
|
|
147
|
+
|
|
148
|
+
# %% ../00_xml.ipynb
|
|
149
|
+
@delegates(folder2ctx)
|
|
150
|
+
def repo2ctx(
|
|
151
|
+
owner:str, # GitHub repo owner
|
|
152
|
+
repo:str, # GitHub repo name
|
|
153
|
+
ref:str=None, # Git ref (branch/tag/sha); defaults to repo's default branch
|
|
154
|
+
**kwargs # Passed to `folder2ctx`
|
|
155
|
+
)->str: # XML for LM context
|
|
156
|
+
"Convert GitHub repo to XML context without cloning"
|
|
157
|
+
import tempfile, tarfile, io
|
|
158
|
+
api = GhApi()
|
|
159
|
+
if ref is None: ref = api.repos.get(owner, repo).default_branch
|
|
160
|
+
data = api.repos.download_tarball_archive(owner, repo, ref)
|
|
161
|
+
tf = tarfile.open(fileobj=io.BytesIO(data))
|
|
162
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
163
|
+
tf.extractall(tmp, filter='data')
|
|
164
|
+
subdir = Path(tmp) / tf.getmembers()[0].name.split('/')[0]
|
|
165
|
+
return folder2ctx(subdir, include_base=False, **kwargs)
|
|
138
166
|
|
|
139
167
|
# %% ../00_xml.ipynb
|
|
140
168
|
@call_parse
|
|
141
169
|
@delegates(folder2ctx)
|
|
142
170
|
def folder2ctx_cli(
|
|
143
171
|
folder:str, # Folder name containing files to add to context
|
|
172
|
+
out:bool=True, # Include notebook cell outputs?
|
|
144
173
|
**kwargs # Passed to `folder2ctx`
|
|
145
174
|
)->str: # XML for Claude context
|
|
146
|
-
|
|
175
|
+
"CLI to convert folder contents to XML context, handling notebooks"
|
|
176
|
+
print(folder2ctx(folder, out=out, **kwargs))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: toolslm
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: Tools to make language models a bit easier to use
|
|
5
5
|
Home-page: https://github.com/AnswerDotAI/toolslm
|
|
6
6
|
Author: Jeremy Howard
|
|
@@ -16,7 +16,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
16
16
|
Requires-Python: >=3.9
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: fastcore>=1.
|
|
19
|
+
Requires-Dist: fastcore>=1.9.6
|
|
20
20
|
Requires-Dist: httpx
|
|
21
21
|
Provides-Extra: dev
|
|
22
22
|
Dynamic: author
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
toolslm/__init__.py,sha256=J0I0c7-a50EOnWXMryTu_E6xhXSYFBPjVpeYP_a3vRI,22
|
|
2
|
+
toolslm/_modidx.py,sha256=kpgsDpj-Tvn90wezrHaMttyzhNcyNVgw_dQgK10qotI,5308
|
|
3
|
+
toolslm/download.py,sha256=g3BxUSxylC_575M7RFSJ1GI3Co3EwPDdEeWzxaf2Czk,4451
|
|
4
|
+
toolslm/funccall.py,sha256=0OBrx6KzI0KK13L-5Hn69yah9oZhgTsKchmMenCoT0A,10421
|
|
5
|
+
toolslm/md_hier.py,sha256=r_NPezhgfxjRmSYFlu_ND42hXt1qSbaPWHTcjbviOn4,11010
|
|
6
|
+
toolslm/shell.py,sha256=dGInuRKvexu21VmtZkw_0S3BGiTsbAongUG-yG4YHpc,1566
|
|
7
|
+
toolslm/xml.py,sha256=TO3i6QD1g_ya8B7Wxwib2ZWv7pwVpfyaAalw1qrKb74,7148
|
|
8
|
+
toolslm-0.3.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
9
|
+
toolslm-0.3.7.dist-info/METADATA,sha256=IaRtHzIR_YzPP-XOAcO5EdSKWChZwgpSOz5HCdgGqGc,2403
|
|
10
|
+
toolslm-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
toolslm-0.3.7.dist-info/entry_points.txt,sha256=xFz0Eymlo5X7BGpaO6DI9gMxvN5A7faebzrlr8ctp5I,95
|
|
12
|
+
toolslm-0.3.7.dist-info/top_level.txt,sha256=4hRTrFWayz_Kz5221XjvlpCwVFrW3WPi1P0fllkTq9s,8
|
|
13
|
+
toolslm-0.3.7.dist-info/RECORD,,
|
toolslm-0.3.3.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
toolslm/__init__.py,sha256=8KcCYTXH99C2-gCLuPILJvtT9YftRWJsartIx6TQ2ZY,22
|
|
2
|
-
toolslm/_modidx.py,sha256=KeI16uj9ZfA5ZWlmov5ATQwf3291dayJ42Bp1dh69gU,4856
|
|
3
|
-
toolslm/download.py,sha256=g3BxUSxylC_575M7RFSJ1GI3Co3EwPDdEeWzxaf2Czk,4451
|
|
4
|
-
toolslm/funccall.py,sha256=PSmQ9kZsJvYh3egH7k1vQPYFn-XBm5E_CCKDVdX9tfg,8506
|
|
5
|
-
toolslm/md_hier.py,sha256=Havk9Hf0t2Xt67n_r7ZxCsS0pciR85iLcE5quShvkTg,10032
|
|
6
|
-
toolslm/shell.py,sha256=dGInuRKvexu21VmtZkw_0S3BGiTsbAongUG-yG4YHpc,1566
|
|
7
|
-
toolslm/xml.py,sha256=2QGVGrTWfyyf0duBDn_Of5kFzYFoBjvl8PrZKgNxbUU,5806
|
|
8
|
-
toolslm-0.3.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
9
|
-
toolslm-0.3.3.dist-info/METADATA,sha256=6jm9oNXtN4EDwj2OEbgtQg2pQ3vu24bV9VGN7oex2BU,2404
|
|
10
|
-
toolslm-0.3.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
toolslm-0.3.3.dist-info/entry_points.txt,sha256=xFz0Eymlo5X7BGpaO6DI9gMxvN5A7faebzrlr8ctp5I,95
|
|
12
|
-
toolslm-0.3.3.dist-info/top_level.txt,sha256=4hRTrFWayz_Kz5221XjvlpCwVFrW3WPi1P0fllkTq9s,8
|
|
13
|
-
toolslm-0.3.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|