diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index eb57105af..467777382 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -11,7 +11,7 @@ jobs: fail-fast: true matrix: os: [ubuntu, macos] - version: ["3.7", "3.8", "3.9", "3.10"] + version: ["3.7", "3.8", "3.9", "3.10", "3.11"] runs-on: ${{ matrix.os }}-latest steps: - uses: fastai/workflows/nbdev-ci@master diff --git a/nbdev/showdoc.py b/nbdev/showdoc.py index a57393d98..5c8eee64b 100644 --- a/nbdev/showdoc.py +++ b/nbdev/showdoc.py @@ -29,7 +29,7 @@ def _escape_markdown(s): return s.replace('\n', '
') # %% ../nbs/api/08_showdoc.ipynb 9 -def _maybe_nm(o): +def _maybe_nm(o): if (o == inspect._empty): return '' else: return o.__name__ if hasattr(o, '__name__') else _escape_markdown(str(o)) @@ -40,7 +40,7 @@ def _list2row(l:list): return '| '+' | '.join([_maybe_nm(o) for o in l]) + ' |' class DocmentTbl: # this is the column order we want these items to appear _map = OrderedDict({'anno':'Type', 'default':'Default', 'docment':'Details'}) - + def __init__(self, obj, verbose=True, returns=True): "Compute the docment table string" self.verbose = verbose @@ -52,30 +52,30 @@ def __init__(self, obj, verbose=True, returns=True): if 'self' in _dm: del _dm['self'] for d in _dm.values(): d['docment'] = ifnone(d['docment'], inspect._empty) self.dm = _dm - + @property def _columns(self): "Compute the set of fields that have at least one non-empty value so we don't show tables empty columns" cols = set(flatten(L(self.dm.values()).filter().map(_non_empty_keys))) candidates = self._map if self.verbose else {'docment': 'Details'} return OrderedDict({k:v for k,v in candidates.items() if k in cols}) - + @property - def has_docment(self): return 'docment' in self._columns and self._row_list + def has_docment(self): return 'docment' in self._columns and self._row_list @property def has_return(self): return self.returns and bool(_non_empty_keys(self.dm.get('return', {}))) - - def _row(self, nm, props): + + def _row(self, nm, props): "unpack data for single row to correspond with column names." return [nm] + [props[c] for c in self._columns] - + @property def _row_list(self): "unpack data for all rows." ordered_params = [(p, self.dm[p]) for p in self.params if p != 'self' and p in self.dm] return L([self._row(nm, props) for nm,props in ordered_params]) - + @property def _hdr_list(self): return [' '] + [_bold(l) for l in L(self._columns.values())] @@ -84,23 +84,23 @@ def hdr_str(self): "The markdown string for the header portion of the table" md = _list2row(self._hdr_list) return md + '\n' + _list2row(['-' * len(l) for l in self._hdr_list]) - + @property - def params_str(self): + def params_str(self): "The markdown string for the parameters portion of the table." return '\n'.join(self._row_list.map(_list2row)) - + @property def return_str(self): "The markdown string for the returns portion of the table." return _list2row(['**Returns**']+[_bold(_maybe_nm(self.dm['return'][c])) for c in self._columns]) - + def _repr_markdown_(self): if not self.has_docment: return '' _tbl = [self.hdr_str, self.params_str] if self.has_return: _tbl.append(self.return_str) return '\n'.join(_tbl) - + def __eq__(self,other): return self.__str__() == str(other).strip() __str__ = _repr_markdown_ diff --git a/nbs/api/08_showdoc.ipynb b/nbs/api/08_showdoc.ipynb index 51d33289d..31069b61e 100644 --- a/nbs/api/08_showdoc.ipynb +++ b/nbs/api/08_showdoc.ipynb @@ -120,7 +120,7 @@ "outputs": [], "source": [ "#|export\n", - "def _maybe_nm(o): \n", + "def _maybe_nm(o):\n", " if (o == inspect._empty): return ''\n", " else: return o.__name__ if hasattr(o, '__name__') else _escape_markdown(str(o))" ] @@ -171,7 +171,7 @@ "class DocmentTbl:\n", " # this is the column order we want these items to appear\n", " _map = OrderedDict({'anno':'Type', 'default':'Default', 'docment':'Details'})\n", - " \n", + "\n", " def __init__(self, obj, verbose=True, returns=True):\n", " \"Compute the docment table string\"\n", " self.verbose = verbose\n", @@ -183,30 +183,30 @@ " if 'self' in _dm: del _dm['self']\n", " for d in _dm.values(): d['docment'] = ifnone(d['docment'], inspect._empty)\n", " self.dm = _dm\n", - " \n", + "\n", " @property\n", " def _columns(self):\n", " \"Compute the set of fields that have at least one non-empty value so we don't show tables empty columns\"\n", " cols = set(flatten(L(self.dm.values()).filter().map(_non_empty_keys)))\n", " candidates = self._map if self.verbose else {'docment': 'Details'}\n", " return OrderedDict({k:v for k,v in candidates.items() if k in cols})\n", - " \n", + "\n", " @property\n", - " def has_docment(self): return 'docment' in self._columns and self._row_list \n", + " def has_docment(self): return 'docment' in self._columns and self._row_list\n", "\n", " @property\n", " def has_return(self): return self.returns and bool(_non_empty_keys(self.dm.get('return', {})))\n", - " \n", - " def _row(self, nm, props): \n", + "\n", + " def _row(self, nm, props):\n", " \"unpack data for single row to correspond with column names.\"\n", " return [nm] + [props[c] for c in self._columns]\n", - " \n", + "\n", " @property\n", " def _row_list(self):\n", " \"unpack data for all rows.\"\n", " ordered_params = [(p, self.dm[p]) for p in self.params if p != 'self' and p in self.dm]\n", " return L([self._row(nm, props) for nm,props in ordered_params])\n", - " \n", + "\n", " @property\n", " def _hdr_list(self): return [' '] + [_bold(l) for l in L(self._columns.values())]\n", "\n", @@ -215,23 +215,23 @@ " \"The markdown string for the header portion of the table\"\n", " md = _list2row(self._hdr_list)\n", " return md + '\\n' + _list2row(['-' * len(l) for l in self._hdr_list])\n", - " \n", + "\n", " @property\n", - " def params_str(self): \n", + " def params_str(self):\n", " \"The markdown string for the parameters portion of the table.\"\n", " return '\\n'.join(self._row_list.map(_list2row))\n", - " \n", + "\n", " @property\n", " def return_str(self):\n", " \"The markdown string for the returns portion of the table.\"\n", " return _list2row(['**Returns**']+[_bold(_maybe_nm(self.dm['return'][c])) for c in self._columns])\n", - " \n", + "\n", " def _repr_markdown_(self):\n", " if not self.has_docment: return ''\n", " _tbl = [self.hdr_str, self.params_str]\n", " if self.has_return: _tbl.append(self.return_str)\n", " return '\\n'.join(_tbl)\n", - " \n", + "\n", " def __eq__(self,other): return self.__str__() == str(other).strip()\n", "\n", " __str__ = _repr_markdown_\n", @@ -272,7 +272,7 @@ } ], "source": [ - "def _f(a, # description of param a \n", + "def _f(a, # description of param a\n", " b=True, # description of param b\n", " c:str=None\n", " ) -> int: ...\n", @@ -334,7 +334,7 @@ } ], "source": [ - "def _f(a, \n", + "def _f(a,\n", " b, #param b\n", " c #param c\n", " ): ...\n", @@ -378,13 +378,13 @@ "outputs": [], "source": [ "class _Test:\n", - " def __init__(self, \n", - " a, # description of param a \n", + " def __init__(self,\n", + " a, # description of param a\n", " b=True, # description of param b\n", " c:str=None):\n", " ...\n", - " \n", - " def foo(self, \n", + "\n", + " def foo(self,\n", " c:int, # description of param c\n", " d=True, # description of param d\n", " ):\n", @@ -598,7 +598,7 @@ "def _long_f(a_param, b_param=True, c_param:str='Some quite long value', d:int=2, e:bool=False):\n", " \"A docstring\"\n", " ...\n", - " \n", + "\n", "_res = \"> (a_param, b_param=True, c_param:str='Some quite long value', d:int=2,\\n> e:bool=False)\"\n", "_sig = _fmt_sig(signature_ex(_long_f, eval_str=True))\n", "test_eq(_wrap_sig(_sig), _res)" @@ -727,14 +727,14 @@ "def f(x=1):\n", " \"\"\"\n", " func docstring in the numpy style.\n", - " \n", + "\n", " This is another line of the docstring.\n", - " \n", + "\n", " Parameters\n", " ----------\n", " x : int\n", " the parameter x\n", - " \n", + "\n", " Returns\n", " -------\n", " None\n", @@ -811,7 +811,7 @@ " \"This is the docstring for the `__init__` method\"\n", " ...\n", " @property\n", - " def some_prop(self): \n", + " def some_prop(self):\n", " \"This is a class property.\"\n", " return 'foo property'\n", "\n", @@ -873,7 +873,7 @@ "source": [ "#|hide\n", "@patch\n", - "def a_method(self:Foo, \n", + "def a_method(self:Foo,\n", " a:list, # param a\n", " b:dict,c):\n", " \"This is a method\"\n", @@ -1009,7 +1009,7 @@ "text/html": [ "
\n", "

show_doc

\n", - "
show_doc(sym, renderer=None, name:Optional[str]=None, title_level:int=3)

Show signature and docstring for `sym`

\n", + "
show_doc(sym, renderer=None, name:str|None=None, title_level:int=3)

Show signature and docstring for `sym`

\n", "

Show in docs

" ], "text/plain": [ @@ -1054,12 +1054,12 @@ " def __init__(self, x:int=1): ...\n", "\n", " @classmethod\n", - " def class_method(cls, \n", + " def class_method(cls,\n", " foo:str, # docment for parameter foo\n", " bar:int):\n", " \"This is a class method.\"\n", " pass\n", - " \n", + "\n", " def regular_method(self,\n", " baz:bool=True): # docment for parameter baz\n", " \"This is a regular method\"\n", @@ -1285,18 +1285,6 @@ "## Test Edgecases -" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "66569922", - "metadata": {}, - "outputs": [], - "source": [ - "#|hide\n", - "e = enum.Enum('e', 'a b')\n", - "test_eq(str(show_doc(e)), '---\\n\\n### e\\n\\n> e (value, names=None, module=None, qualname=None, type=None, start=1)\\n\\nAn enumeration.')" - ] - }, { "cell_type": "code", "execution_count": null, @@ -1353,14 +1341,6 @@ "#|hide\n", "import nbdev; nbdev. nbdev_export()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b508e79a", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/setup.py b/setup.py index d405e2a07..a5aa9996e 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,9 @@ -from pkg_resources import parse_version +import shlex from configparser import ConfigParser -import setuptools,shlex + +import setuptools +from pkg_resources import parse_version + assert parse_version(setuptools.__version__)>=parse_version('36.2') # note: all settings are in settings.ini; edit there, not here @@ -23,7 +26,7 @@ } statuses = [ '0 - Pre-Planning', '1 - Planning', '2 - Pre-Alpha', '3 - Alpha', '4 - Beta', '5 - Production/Stable', '6 - Mature', '7 - Inactive' ] -py_versions = '3.7 3.8 3.9 3.10'.split() +py_versions = '3.7 3.8 3.9 3.10 3.11'.split() requirements = shlex.split(cfg.get('requirements', '')) if cfg.get('pip_requirements'): requirements += shlex.split(cfg.get('pip_requirements', ''))