|
22 | 22 | "from functools import wraps\n", |
23 | 23 | "\n", |
24 | 24 | "import mimetypes,pickle,random,json,subprocess,shlex,bz2,gzip,zipfile,tarfile\n", |
25 | | - "import imghdr,struct,distutils.util,tempfile,time,string\n", |
| 25 | + "import imghdr,struct,distutils.util,tempfile,time,string,collections\n", |
26 | 26 | "from contextlib import contextmanager,ExitStack\n", |
27 | 27 | "from pdb import set_trace\n", |
28 | 28 | "from datetime import datetime, timezone\n", |
|
618 | 618 | { |
619 | 619 | "data": { |
620 | 620 | "text/plain": [ |
621 | | - "['d', 'c', 'h', 'a', 'b', 'g', 'e', 'f']" |
| 621 | + "['a', 'e', 'h', 'b', 'g', 'd', 'c', 'f']" |
622 | 622 | ] |
623 | 623 | }, |
624 | 624 | "execution_count": null, |
|
1326 | 1326 | "outputs": [], |
1327 | 1327 | "source": [ |
1328 | 1328 | "#export\n", |
1329 | | - "def truncstr(s:str, maxlen:int, suf:str='…')->str:\n", |
| 1329 | + "def truncstr(s:str, maxlen:int, suf:str='…', space='')->str:\n", |
1330 | 1330 | " \"Truncate `s` to length `maxlen`, adding suffix `suf` if truncated\"\n", |
1331 | | - " return s[:maxlen-len(suf)]+suf if len(s)>maxlen else s" |
| 1331 | + " return s[:maxlen-len(suf)]+suf if len(s)+len(space)>maxlen else s+space" |
1332 | 1332 | ] |
1333 | 1333 | }, |
1334 | 1334 | { |
|
1338 | 1338 | "outputs": [], |
1339 | 1339 | "source": [ |
1340 | 1340 | "w = 'abacadabra'\n", |
1341 | | - "test_eq(truncstr(w, 15), w)\n", |
| 1341 | + "test_eq(truncstr(w, 10), w)\n", |
1342 | 1342 | "test_eq(truncstr(w, 5), 'abac…')\n", |
1343 | 1343 | "test_eq(truncstr(w, 5, suf=''), 'abaca')\n", |
| 1344 | + "test_eq(truncstr(w, 11, space='_'), w+\"_\")\n", |
| 1345 | + "test_eq(truncstr(w, 10, space='_'), w[:-1]+'…')\n", |
1344 | 1346 | "test_eq(truncstr(w, 5, suf='!!'), 'aba!!')" |
1345 | 1347 | ] |
1346 | 1348 | }, |
|
1374 | 1376 | "outputs": [], |
1375 | 1377 | "source": [ |
1376 | 1378 | "#export\n", |
1377 | | - "def sparkline(data, empty_zero=False):\n", |
| 1379 | + "def sparkline(data, mn=None, mx=None, empty_zero=False):\n", |
1378 | 1380 | " \"Sparkline for `data`, with `None`s (and zero, if `empty_zero`) shown as empty column\"\n", |
1379 | 1381 | " valid = [o for o in data if o is not None]\n", |
1380 | | - " mn,mx,n = min(valid),max(valid),len(spark_chars)\n", |
| 1382 | + " mn,mx,n = ifnone(mn,min(valid)),ifnone(mx,max(valid)),len(spark_chars)\n", |
1381 | 1383 | " res = [_sparkchar(o,mn,(mx-mn)/n,empty_zero) for o in data]\n", |
1382 | 1384 | " return ''.join(res)" |
1383 | 1385 | ] |
|
1440 | 1442 | "This is convenient for tracking the frequency of events. Call `send(n)` any time you want to add `n` events to the counter. Pass the object to `next()` to get a tuple of the number of events and the frequency/second." |
1441 | 1443 | ] |
1442 | 1444 | }, |
| 1445 | + { |
| 1446 | + "cell_type": "code", |
| 1447 | + "execution_count": null, |
| 1448 | + "metadata": {}, |
| 1449 | + "outputs": [], |
| 1450 | + "source": [ |
| 1451 | + "# Random wait function for testing `time_events`\n", |
| 1452 | + "def _randwait(): yield from (sleep(random.random()/200) for _ in range(100))" |
| 1453 | + ] |
| 1454 | + }, |
1443 | 1455 | { |
1444 | 1456 | "cell_type": "code", |
1445 | 1457 | "execution_count": null, |
|
1449 | 1461 | "name": "stdout", |
1450 | 1462 | "output_type": "stream", |
1451 | 1463 | "text": [ |
1452 | | - "# Events: 10, Freq/sec: 80.30\n" |
| 1464 | + "# Events: 100, Freq/sec: 396.51\n" |
1453 | 1465 | ] |
1454 | 1466 | } |
1455 | 1467 | ], |
1456 | 1468 | "source": [ |
1457 | | - "# Random wait function for testing `time_events`\n", |
1458 | | - "def _randwait(): yield from (sleep(random.random()/30) for _ in range(10))\n", |
1459 | | - "\n", |
1460 | 1469 | "c = time_events() # Start timer\n", |
1461 | 1470 | "for o in _randwait(): c.send(1) # Send an event\n", |
1462 | 1471 | "events,freq = next(c) # Return counter values\n", |
1463 | 1472 | "c.close() # Close when done\n", |
1464 | 1473 | "print(f'# Events: {events}, Freq/sec: {freq:.02f}')" |
1465 | 1474 | ] |
1466 | 1475 | }, |
| 1476 | + { |
| 1477 | + "cell_type": "code", |
| 1478 | + "execution_count": null, |
| 1479 | + "metadata": {}, |
| 1480 | + "outputs": [], |
| 1481 | + "source": [ |
| 1482 | + "#export\n", |
| 1483 | + "class EventTimer:\n", |
| 1484 | + " \"An event timer with history of `store` items of time `span`\"\n", |
| 1485 | + " def __init__(self, store=5, span=60):\n", |
| 1486 | + " self.hist,self.span,self.last = collections.deque(maxlen=store),span,default_timer()\n", |
| 1487 | + " self._reset()\n", |
| 1488 | + "\n", |
| 1489 | + " def _reset(self): self.start,self.events = self.last,0\n", |
| 1490 | + "\n", |
| 1491 | + " def add(self, n=1):\n", |
| 1492 | + " \"Record `n` events\"\n", |
| 1493 | + " if self.duration>self.span:\n", |
| 1494 | + " self.hist.append(self.freq)\n", |
| 1495 | + " self._reset()\n", |
| 1496 | + " self.events +=n\n", |
| 1497 | + " self.last = default_timer()\n", |
| 1498 | + " \n", |
| 1499 | + " @property\n", |
| 1500 | + " def duration(self): return default_timer()-self.start\n", |
| 1501 | + " @property\n", |
| 1502 | + " def freq(self): return self.events/self.duration" |
| 1503 | + ] |
| 1504 | + }, |
| 1505 | + { |
| 1506 | + "cell_type": "code", |
| 1507 | + "execution_count": null, |
| 1508 | + "metadata": {}, |
| 1509 | + "outputs": [ |
| 1510 | + { |
| 1511 | + "data": { |
| 1512 | + "text/markdown": [ |
| 1513 | + "<h4 id=\"EventTimer\" class=\"doc_header\"><code>class</code> <code>EventTimer</code><a href=\"\" class=\"source_link\" style=\"float:right\">[source]</a></h4>\n", |
| 1514 | + "\n", |
| 1515 | + "> <code>EventTimer</code>(**`store`**=*`5`*, **`span`**=*`60`*)\n", |
| 1516 | + "\n", |
| 1517 | + "An event timer with history of `store` items of time `span`" |
| 1518 | + ], |
| 1519 | + "text/plain": [ |
| 1520 | + "<IPython.core.display.Markdown object>" |
| 1521 | + ] |
| 1522 | + }, |
| 1523 | + "metadata": {}, |
| 1524 | + "output_type": "display_data" |
| 1525 | + } |
| 1526 | + ], |
| 1527 | + "source": [ |
| 1528 | + "show_doc(EventTimer, title_level=4)" |
| 1529 | + ] |
| 1530 | + }, |
| 1531 | + { |
| 1532 | + "cell_type": "markdown", |
| 1533 | + "metadata": {}, |
| 1534 | + "source": [ |
| 1535 | + "Add events with `add`, and get number of `events` and their frequency (`freq`)." |
| 1536 | + ] |
| 1537 | + }, |
| 1538 | + { |
| 1539 | + "cell_type": "code", |
| 1540 | + "execution_count": null, |
| 1541 | + "metadata": {}, |
| 1542 | + "outputs": [ |
| 1543 | + { |
| 1544 | + "name": "stdout", |
| 1545 | + "output_type": "stream", |
| 1546 | + "text": [ |
| 1547 | + "Num Events: 5, Freq/sec: 646.7\n", |
| 1548 | + "Most recent: ▁▇▃▇▆ 259.5 450.4 362.1 441.0 427.9\n" |
| 1549 | + ] |
| 1550 | + } |
| 1551 | + ], |
| 1552 | + "source": [ |
| 1553 | + "c = EventTimer(store=5, span=0.03)\n", |
| 1554 | + "for o in _randwait(): c.add(1)\n", |
| 1555 | + "print(f'Num Events: {c.events}, Freq/sec: {c.freq:.01f}')\n", |
| 1556 | + "print('Most recent: ', sparkline(c.hist), *L(c.hist).map('{:.01f}'))" |
| 1557 | + ] |
| 1558 | + }, |
1467 | 1559 | { |
1468 | 1560 | "cell_type": "code", |
1469 | 1561 | "execution_count": null, |
|
0 commit comments