|
1514 | 1514 | "outputs": [],
|
1515 | 1515 | "source": [
|
1516 | 1516 | "#export\n",
|
1517 |
| - "class L(CollBase, metaclass=_L_Meta):\n", |
| 1517 | + "class L(GetAttr, CollBase, metaclass=_L_Meta):\n", |
1518 | 1518 | " \"Behaves like a list of `items` but can also index with list of indices or masks\"\n",
|
1519 | 1519 | " _default='items'\n",
|
1520 | 1520 | " def __init__(self, items=None, *rest, use_list=False, match=None):\n",
|
|
1616 | 1616 | " res = filter(g, self.map(f, *args, gen=gen, **kwargs))\n",
|
1617 | 1617 | " if gen: return res\n",
|
1618 | 1618 | " return self._new(res)\n",
|
1619 |
| - " def map_first(self, f=noop, g=noop, *args, **kwargs): return first(self.map_filter(f, g, *args, gen=False, **kwargs))\n", |
| 1619 | + " def map_first(self, f=noop, g=noop, *args, **kwargs):\n", |
| 1620 | + " return first(self.map_filter(f, g, *args, gen=False, **kwargs))\n", |
1620 | 1621 | "\n",
|
1621 | 1622 | " def starmap(self, f, *args, **kwargs): return self._new(itertools.starmap(partial(f,*args,**kwargs), self))\n",
|
1622 | 1623 | " def zip(self, cycled=False): return self._new((zip_cycle if cycled else zip)(*self))\n",
|
1623 | 1624 | " def zipwith(self, *rest, cycled=False): return self._new([self, *rest]).zip(cycled=cycled)\n",
|
1624 | 1625 | " def map_zip(self, f, *args, cycled=False, **kwargs): return self.zip(cycled=cycled).starmap(f, *args, **kwargs)\n",
|
1625 |
| - " def map_zipwith(self, f, *rest, cycled=False, **kwargs): return self.zipwith(*rest, cycled=cycled).starmap(f, **kwargs)\n", |
1626 |
| - " def concat(self): return self._new(itertools.chain.from_iterable(self.map(L)))\n", |
| 1626 | + " def map_zipwith(self, f, *rest, cycled=False, **kwargs):\n", |
| 1627 | + " return self.zipwith(*rest, cycled=cycled).starmap(f, **kwargs)\n", |
1627 | 1628 | " def shuffle(self):\n",
|
1628 | 1629 | " it = copy(self.items)\n",
|
1629 | 1630 | " random.shuffle(it)\n",
|
1630 | 1631 | " return self._new(it)\n",
|
1631 | 1632 | "\n",
|
1632 |
| - " def append(self,o): return self.items.append(o)\n", |
1633 |
| - " def remove(self,o): return self.items.remove(o)\n", |
1634 |
| - " def count (self,o): return self.items.count(o)\n", |
1635 |
| - " def reverse(self ): return self.items.reverse()\n", |
1636 |
| - " def pop(self,o=-1): return self.items.pop(o)\n", |
1637 |
| - " def clear(self ): return self.items.clear()\n", |
1638 |
| - " def insert(self,idx,o): return self.items.insert(idx,o)\n", |
1639 |
| - " def index(self, value, start=0, stop=sys.maxsize): return self.items.index(value, start, stop)\n", |
1640 |
| - " def sort(self, key=None, reverse=False): return self.items.sort(key=key, reverse=reverse)\n", |
| 1633 | + " def concat(self): return self._new(itertools.chain.from_iterable(self.map(L)))\n", |
1641 | 1634 | " def reduce(self, f, initial=None): return reduce(f, self) if initial is None else reduce(f, self, initial)\n",
|
1642 | 1635 | " def sum(self): return self.reduce(operator.add)\n",
|
1643 |
| - " def product(self): return self.reduce(operator.mul)" |
| 1636 | + " def product(self): return self.reduce(operator.mul)\n", |
| 1637 | + " def setattrs(self, attr, val): [setattr(o,attr,val) for o in self]" |
1644 | 1638 | ]
|
1645 | 1639 | },
|
1646 | 1640 | {
|
|
1650 | 1644 | "outputs": [],
|
1651 | 1645 | "source": [
|
1652 | 1646 | "#export\n",
|
1653 |
| - "_docs = {o:\"Passthru to `list` method\" for o in\n", |
1654 |
| - " 'append count remove reverse sort pop clear insert index'.split()}\n", |
1655 | 1647 | "add_docs(L,\n",
|
1656 | 1648 | " __getitem__=\"Retrieve `idx` (can be list of indices, or mask, or int) items\",\n",
|
1657 |
| - " range=\"Class Method: Same as `range`, but returns an `L`. Can pass a collection for `a`, to use `len(a)`\",\n", |
| 1649 | + " range=\"Class Method: Same as `range`, but returns `L`. Can pass collection for `a`, to use `len(a)`\",\n", |
1658 | 1650 | " split=\"Class Method: Same as `str.split`, but returns an `L`\",\n",
|
1659 | 1651 | " copy=\"Same as `list.copy`, but returns an `L`\",\n",
|
1660 |
| - " sorted=\"New `L` sorted by `key`. If key is str then use `attrgetter`. If key is int then use `itemgetter`\",\n", |
| 1652 | + " sorted=\"New `L` sorted by `key`. If key is str use `attrgetter`; if int use `itemgetter`\",\n", |
1661 | 1653 | " unique=\"Unique items, in stable order\",\n",
|
1662 | 1654 | " val2idx=\"Dict from value to index\",\n",
|
1663 | 1655 | " filter=\"Create new `L` filtered by predicate `f`, passing `args` and `kwargs` to `f`\",\n",
|
|
1680 | 1672 | " reduce=\"Wrapper for `functools.reduce`\",\n",
|
1681 | 1673 | " sum=\"Sum of the items\",\n",
|
1682 | 1674 | " product=\"Product of the items\",\n",
|
1683 |
| - " **_docs)" |
| 1675 | + " setattrs=\"Call `setattr` on all items\"\n", |
| 1676 | + " )" |
1684 | 1677 | ]
|
1685 | 1678 | },
|
1686 | 1679 | {
|
|
1826 | 1819 | {
|
1827 | 1820 | "data": {
|
1828 | 1821 | "text/plain": [
|
1829 |
| - "[0, 7, 11]" |
| 1822 | + "[4, 1, 2]" |
1830 | 1823 | ]
|
1831 | 1824 | },
|
1832 | 1825 | "execution_count": null,
|
|
2318 | 2311 | "cell_type": "markdown",
|
2319 | 2312 | "metadata": {},
|
2320 | 2313 | "source": [
|
2321 |
| - "If the special argument `_arg` is passed, then that is the kwarg used in the map." |
2322 |
| - ] |
2323 |
| - }, |
2324 |
| - { |
2325 |
| - "cell_type": "code", |
2326 |
| - "execution_count": null, |
2327 |
| - "metadata": {}, |
2328 |
| - "outputs": [], |
2329 |
| - "source": [ |
2330 |
| - "#What is this? TODO Jeremy: fix\n", |
2331 |
| - "#L.range(4).map(f, b=arg0)" |
| 2314 | + "You can also pass the same `arg` params that `bind` accepts:" |
2332 | 2315 | ]
|
2333 | 2316 | },
|
2334 | 2317 | {
|
|
2385 | 2368 | {
|
2386 | 2369 | "data": {
|
2387 | 2370 | "text/markdown": [
|
2388 |
| - "<h4 id=\"L.zip\" class=\"doc_header\"><code>L.zip</code><a href=\"__main__.py#L107\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
| 2371 | + "<h4 id=\"L.zip\" class=\"doc_header\"><code>L.zip</code><a href=\"__main__.py#L108\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
2389 | 2372 | "\n",
|
2390 | 2373 | "> <code>L.zip</code>(**`cycled`**=*`False`*)\n",
|
2391 | 2374 | "\n",
|
|
2432 | 2415 | {
|
2433 | 2416 | "data": {
|
2434 | 2417 | "text/markdown": [
|
2435 |
| - "<h4 id=\"L.map_zip\" class=\"doc_header\"><code>L.map_zip</code><a href=\"__main__.py#L109\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
| 2418 | + "<h4 id=\"L.map_zip\" class=\"doc_header\"><code>L.map_zip</code><a href=\"__main__.py#L110\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
2436 | 2419 | "\n",
|
2437 | 2420 | "> <code>L.map_zip</code>(**`f`**, **\\*`args`**, **`cycled`**=*`False`*, **\\*\\*`kwargs`**)\n",
|
2438 | 2421 | "\n",
|
|
2468 | 2451 | {
|
2469 | 2452 | "data": {
|
2470 | 2453 | "text/markdown": [
|
2471 |
| - "<h4 id=\"L.zipwith\" class=\"doc_header\"><code>L.zipwith</code><a href=\"__main__.py#L108\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
| 2454 | + "<h4 id=\"L.zipwith\" class=\"doc_header\"><code>L.zipwith</code><a href=\"__main__.py#L109\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
2472 | 2455 | "\n",
|
2473 | 2456 | "> <code>L.zipwith</code>(**\\*`rest`**, **`cycled`**=*`False`*)\n",
|
2474 | 2457 | "\n",
|
|
2505 | 2488 | {
|
2506 | 2489 | "data": {
|
2507 | 2490 | "text/markdown": [
|
2508 |
| - "<h4 id=\"L.map_zipwith\" class=\"doc_header\"><code>L.map_zipwith</code><a href=\"__main__.py#L110\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
| 2491 | + "<h4 id=\"L.map_zipwith\" class=\"doc_header\"><code>L.map_zipwith</code><a href=\"__main__.py#L111\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
2509 | 2492 | "\n",
|
2510 | 2493 | "> <code>L.map_zipwith</code>(**`f`**, **\\*`rest`**, **`cycled`**=*`False`*, **\\*\\*`kwargs`**)\n",
|
2511 | 2494 | "\n",
|
|
2620 | 2603 | "\n",
|
2621 | 2604 | "> <code>L.sorted</code>(**`key`**=*`None`*, **`reverse`**=*`False`*)\n",
|
2622 | 2605 | "\n",
|
2623 |
| - "New [`L`](/foundation.html#L) sorted by `key`. If key is str then use `attrgetter`. If key is int then use `itemgetter`" |
| 2606 | + "New [`L`](/foundation.html#L) sorted by `key`. If key is str use `attrgetter`; if int use `itemgetter`" |
2624 | 2607 | ],
|
2625 | 2608 | "text/plain": [
|
2626 | 2609 | "<IPython.core.display.Markdown object>"
|
|
2690 | 2673 | "\n",
|
2691 | 2674 | "> <code>L.range</code>(**`a`**, **`b`**=*`None`*, **`step`**=*`None`*)\n",
|
2692 | 2675 | "\n",
|
2693 |
| - "Class Method: Same as `range`, but returns an [`L`](/foundation.html#L). Can pass a collection for `a`, to use `len(a)`" |
| 2676 | + "Class Method: Same as `range`, but returns [`L`](/foundation.html#L). Can pass collection for `a`, to use `len(a)`" |
2694 | 2677 | ],
|
2695 | 2678 | "text/plain": [
|
2696 | 2679 | "<IPython.core.display.Markdown object>"
|
|
2722 | 2705 | {
|
2723 | 2706 | "data": {
|
2724 | 2707 | "text/markdown": [
|
2725 |
| - "<h4 id=\"L.concat\" class=\"doc_header\"><code>L.concat</code><a href=\"__main__.py#L111\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
| 2708 | + "<h4 id=\"L.concat\" class=\"doc_header\"><code>L.concat</code><a href=\"__main__.py#L118\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
2726 | 2709 | "\n",
|
2727 | 2710 | "> <code>L.concat</code>()\n",
|
2728 | 2711 | "\n",
|
|
2857 | 2840 | "test_eq(t.map_first(lambda o:o*2 if o>2 else None), 6)"
|
2858 | 2841 | ]
|
2859 | 2842 | },
|
| 2843 | + { |
| 2844 | + "cell_type": "code", |
| 2845 | + "execution_count": null, |
| 2846 | + "metadata": {}, |
| 2847 | + "outputs": [ |
| 2848 | + { |
| 2849 | + "data": { |
| 2850 | + "text/markdown": [ |
| 2851 | + "<h4 id=\"L.setattrs\" class=\"doc_header\"><code>L.setattrs</code><a href=\"__main__.py#L122\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
| 2852 | + "\n", |
| 2853 | + "> <code>L.setattrs</code>(**`attr`**, **`val`**)\n", |
| 2854 | + "\n", |
| 2855 | + "Call `setattr` on all items" |
| 2856 | + ], |
| 2857 | + "text/plain": [ |
| 2858 | + "<IPython.core.display.Markdown object>" |
| 2859 | + ] |
| 2860 | + }, |
| 2861 | + "metadata": {}, |
| 2862 | + "output_type": "display_data" |
| 2863 | + } |
| 2864 | + ], |
| 2865 | + "source": [ |
| 2866 | + "show_doc(L.setattrs)" |
| 2867 | + ] |
| 2868 | + }, |
| 2869 | + { |
| 2870 | + "cell_type": "code", |
| 2871 | + "execution_count": null, |
| 2872 | + "metadata": {}, |
| 2873 | + "outputs": [], |
| 2874 | + "source": [ |
| 2875 | + "t = L(SimpleNamespace(),SimpleNamespace())\n", |
| 2876 | + "t.setattrs('foo', 'bar')\n", |
| 2877 | + "test_eq(t.attrgot('foo'), ['bar','bar'])" |
| 2878 | + ] |
| 2879 | + }, |
2860 | 2880 | {
|
2861 | 2881 | "cell_type": "markdown",
|
2862 | 2882 | "metadata": {},
|
|
2904 | 2924 | "metadata": {},
|
2905 | 2925 | "outputs": [],
|
2906 | 2926 | "source": [
|
2907 |
| - "_d = dict(user='fastai', lib_name='fastcore')\n", |
| 2927 | + "_d = dict(user='fastai', lib_name='fastcore', some_path='test')\n", |
2908 | 2928 | "try:\n",
|
2909 | 2929 | " save_config_file('tmp.ini', _d)\n",
|
2910 | 2930 | " res = read_config_file('tmp.ini')\n",
|
|
2945 | 2965 | " _add_new_defaults(self.d, self.config_file,\n",
|
2946 | 2966 | " host=\"github\", doc_host=\"https://%(user)s.github.io\", doc_baseurl=\"/%(lib_name)s/\")\n",
|
2947 | 2967 | "\n",
|
2948 |
| - " def __getattr__(self,k):\n", |
2949 |
| - " if k=='d' or k not in self.d: raise AttributeError(k)\n", |
2950 |
| - " return self.config_file.parent/self.d[k] if k.endswith('_path') else self.get(k)\n", |
2951 |
| - "\n", |
2952 |
| - " def get(self,k,default=None): return self.d.get(k, default)\n", |
2953 | 2968 | " def __setitem__(self,k,v): self.d[k] = str(v)\n",
|
2954 | 2969 | " def __contains__(self,k): return k in self.d\n",
|
2955 |
| - " def save(self): save_config_file(self.config_file,self.d)" |
| 2970 | + " def save(self): save_config_file(self.config_file,self.d)\n", |
| 2971 | + " def __getattr__(self,k): return stop(AttributeError(k)) if k=='d' or k not in self.d else self.get(k)\n", |
| 2972 | + "\n", |
| 2973 | + " def get(self,k,default=None):\n", |
| 2974 | + " v = self.d.get(k)\n", |
| 2975 | + " return self.config_file.parent/v if k.endswith('_path') else v" |
2956 | 2976 | ]
|
2957 | 2977 | },
|
2958 | 2978 | {
|
2959 | 2979 | "cell_type": "markdown",
|
2960 | 2980 | "metadata": {},
|
2961 | 2981 | "source": [
|
2962 |
| - "`Config` searches parent directories for a config file, and provides direct access to the 'DEFAULT' section. " |
| 2982 | + "`Config` searches parent directories for a config file, and provides direct access to the 'DEFAULT' section. Keys ending in `_path` are converted to paths in the config file's directory." |
2963 | 2983 | ]
|
2964 | 2984 | },
|
2965 | 2985 | {
|
|
2973 | 2993 | " cfg = Config('tmp.ini')\n",
|
2974 | 2994 | " test_eq(cfg.user,'fastai')\n",
|
2975 | 2995 | " test_eq(cfg.doc_baseurl,'/fastcore/')\n",
|
| 2996 | + " test_eq(cfg.get('some_path'), Path('../test').resolve())\n", |
2976 | 2997 | "finally: os.unlink('../tmp.ini')"
|
2977 | 2998 | ]
|
2978 | 2999 | },
|
|
0 commit comments