|
62 | 62 | "cell_type": "markdown", |
63 | 63 | "metadata": {}, |
64 | 64 | "source": [ |
65 | | - "When working with jupyter notebooks (which are json files behind the scenes) and GitHub, it is very common that a merge conflict (that will add new lines in the notebook source file) will break some notebooks you are working on. This module defines the function `fix_conflicts` to fix those notebooks for you, and attempt to automatically merge standard conflicts. The remaining ones will be delimited by markdown cells like this:" |
| 65 | + "When working with jupyter notebooks (which are json files behind the scenes) and GitHub, it is very common that a merge conflict (that will add new lines in the notebook source file) will break some notebooks you are working on. This module defines the function `nbdev_fix` to fix those notebooks for you, and attempt to automatically merge standard conflicts. The remaining ones will be delimited by markdown cells like this:" |
66 | 66 | ] |
67 | 67 | }, |
68 | 68 | { |
|
273 | 273 | "data": { |
274 | 274 | "text/markdown": [ |
275 | 275 | "```json\n", |
276 | | - "{ 'cells': [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=3\\nz', 'idx_': 0}, {'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 7, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1}, {'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n", |
| 276 | + "{ 'cells': [ { 'cell_type': 'code',\n", |
| 277 | + " 'execution_count': 6,\n", |
| 278 | + " 'idx_': 0,\n", |
| 279 | + " 'metadata': {},\n", |
| 280 | + " 'outputs': [ { 'data': {'text/plain': ['3']},\n", |
| 281 | + " 'execution_count': 6,\n", |
| 282 | + " 'metadata': {},\n", |
| 283 | + " 'output_type': 'execute_result'}],\n", |
| 284 | + " 'source': 'z=3\\nz'},\n", |
| 285 | + " { 'cell_type': 'code',\n", |
| 286 | + " 'execution_count': 5,\n", |
| 287 | + " 'idx_': 1,\n", |
| 288 | + " 'metadata': {},\n", |
| 289 | + " 'outputs': [ { 'data': {'text/plain': ['6']},\n", |
| 290 | + " 'execution_count': 7,\n", |
| 291 | + " 'metadata': {},\n", |
| 292 | + " 'output_type': 'execute_result'}],\n", |
| 293 | + " 'source': 'x=3\\ny=3\\nx+y'},\n", |
| 294 | + " { 'cell_type': 'code',\n", |
| 295 | + " 'execution_count': None,\n", |
| 296 | + " 'idx_': 2,\n", |
| 297 | + " 'metadata': {},\n", |
| 298 | + " 'outputs': [],\n", |
| 299 | + " 'source': ''}],\n", |
277 | 300 | " 'metadata': { 'kernelspec': { 'display_name': 'Python 3',\n", |
278 | 301 | " 'language': 'python',\n", |
279 | 302 | " 'name': 'python3'}},\n", |
|
282 | 305 | "```" |
283 | 306 | ], |
284 | 307 | "text/plain": [ |
285 | | - "{'cells': (#3) [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=3\\nz', 'idx_': 0},{'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 7, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1},{'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n", |
| 308 | + "{'cells': [{'cell_type': 'code',\n", |
| 309 | + " 'execution_count': 6,\n", |
| 310 | + " 'metadata': {},\n", |
| 311 | + " 'outputs': [{'data': {'text/plain': ['3']},\n", |
| 312 | + " 'execution_count': 6,\n", |
| 313 | + " 'metadata': {},\n", |
| 314 | + " 'output_type': 'execute_result'}],\n", |
| 315 | + " 'source': 'z=3\\nz',\n", |
| 316 | + " 'idx_': 0},\n", |
| 317 | + " {'cell_type': 'code',\n", |
| 318 | + " 'execution_count': 5,\n", |
| 319 | + " 'metadata': {},\n", |
| 320 | + " 'outputs': [{'data': {'text/plain': ['6']},\n", |
| 321 | + " 'execution_count': 7,\n", |
| 322 | + " 'metadata': {},\n", |
| 323 | + " 'output_type': 'execute_result'}],\n", |
| 324 | + " 'source': 'x=3\\ny=3\\nx+y',\n", |
| 325 | + " 'idx_': 1},\n", |
| 326 | + " {'cell_type': 'code',\n", |
| 327 | + " 'execution_count': None,\n", |
| 328 | + " 'metadata': {},\n", |
| 329 | + " 'outputs': [],\n", |
| 330 | + " 'source': '',\n", |
| 331 | + " 'idx_': 2}],\n", |
286 | 332 | " 'metadata': {'kernelspec': {'display_name': 'Python 3',\n", |
287 | 333 | " 'language': 'python',\n", |
288 | 334 | " 'name': 'python3'}},\n", |
|
309 | 355 | "data": { |
310 | 356 | "text/markdown": [ |
311 | 357 | "```json\n", |
312 | | - "{ 'cells': [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=2\\nz', 'idx_': 0}, {'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 5, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1}, {'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n", |
| 358 | + "{ 'cells': [ { 'cell_type': 'code',\n", |
| 359 | + " 'execution_count': 6,\n", |
| 360 | + " 'idx_': 0,\n", |
| 361 | + " 'metadata': {},\n", |
| 362 | + " 'outputs': [ { 'data': {'text/plain': ['3']},\n", |
| 363 | + " 'execution_count': 6,\n", |
| 364 | + " 'metadata': {},\n", |
| 365 | + " 'output_type': 'execute_result'}],\n", |
| 366 | + " 'source': 'z=2\\nz'},\n", |
| 367 | + " { 'cell_type': 'code',\n", |
| 368 | + " 'execution_count': 5,\n", |
| 369 | + " 'idx_': 1,\n", |
| 370 | + " 'metadata': {},\n", |
| 371 | + " 'outputs': [ { 'data': {'text/plain': ['6']},\n", |
| 372 | + " 'execution_count': 5,\n", |
| 373 | + " 'metadata': {},\n", |
| 374 | + " 'output_type': 'execute_result'}],\n", |
| 375 | + " 'source': 'x=3\\ny=3\\nx+y'},\n", |
| 376 | + " { 'cell_type': 'code',\n", |
| 377 | + " 'execution_count': None,\n", |
| 378 | + " 'idx_': 2,\n", |
| 379 | + " 'metadata': {},\n", |
| 380 | + " 'outputs': [],\n", |
| 381 | + " 'source': ''}],\n", |
313 | 382 | " 'metadata': { 'kernelspec': { 'display_name': 'Python 3',\n", |
314 | 383 | " 'language': 'python',\n", |
315 | 384 | " 'name': 'python3'}},\n", |
|
318 | 387 | "```" |
319 | 388 | ], |
320 | 389 | "text/plain": [ |
321 | | - "{'cells': (#3) [{'cell_type': 'code', 'execution_count': 6, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['3']}, 'execution_count': 6, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'z=2\\nz', 'idx_': 0},{'cell_type': 'code', 'execution_count': 5, 'metadata': {}, 'outputs': [{'data': {'text/plain': ['6']}, 'execution_count': 5, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'x=3\\ny=3\\nx+y', 'idx_': 1},{'cell_type': 'code', 'execution_count': None, 'metadata': {}, 'outputs': [], 'source': '', 'idx_': 2}],\n", |
| 390 | + "{'cells': [{'cell_type': 'code',\n", |
| 391 | + " 'execution_count': 6,\n", |
| 392 | + " 'metadata': {},\n", |
| 393 | + " 'outputs': [{'data': {'text/plain': ['3']},\n", |
| 394 | + " 'execution_count': 6,\n", |
| 395 | + " 'metadata': {},\n", |
| 396 | + " 'output_type': 'execute_result'}],\n", |
| 397 | + " 'source': 'z=2\\nz',\n", |
| 398 | + " 'idx_': 0},\n", |
| 399 | + " {'cell_type': 'code',\n", |
| 400 | + " 'execution_count': 5,\n", |
| 401 | + " 'metadata': {},\n", |
| 402 | + " 'outputs': [{'data': {'text/plain': ['6']},\n", |
| 403 | + " 'execution_count': 5,\n", |
| 404 | + " 'metadata': {},\n", |
| 405 | + " 'output_type': 'execute_result'}],\n", |
| 406 | + " 'source': 'x=3\\ny=3\\nx+y',\n", |
| 407 | + " 'idx_': 1},\n", |
| 408 | + " {'cell_type': 'code',\n", |
| 409 | + " 'execution_count': None,\n", |
| 410 | + " 'metadata': {},\n", |
| 411 | + " 'outputs': [],\n", |
| 412 | + " 'source': '',\n", |
| 413 | + " 'idx_': 2}],\n", |
322 | 414 | " 'metadata': {'kernelspec': {'display_name': 'Python 3',\n", |
323 | 415 | " 'language': 'python',\n", |
324 | 416 | " 'name': 'python3'}},\n", |
|
386 | 478 | "outputs": [], |
387 | 479 | "source": [ |
388 | 480 | "#|export\n", |
389 | | - "def _nbdev_fix(nbname:str, # Notebook filename to fix\n", |
| 481 | + "@call_parse\n", |
| 482 | + "def nbdev_fix(nbname:str, # Notebook filename to fix\n", |
390 | 483 | " outname:str=None, # Filename of output notebook (defaults to `nbname`)\n", |
391 | 484 | " nobackup:bool_arg=True, # Do not backup `nbname` to `nbname`.bak if `outname` not provided\n", |
392 | 485 | " theirs:bool=False, # Use their outputs and metadata instead of ours\n", |
|
407 | 500 | " return conflict" |
408 | 501 | ] |
409 | 502 | }, |
410 | | - { |
411 | | - "cell_type": "code", |
412 | | - "execution_count": null, |
413 | | - "metadata": {}, |
414 | | - "outputs": [], |
415 | | - "source": [ |
416 | | - "#|export\n", |
417 | | - "nbdev_fix = call_parse(_nbdev_fix)" |
418 | | - ] |
419 | | - }, |
420 | 503 | { |
421 | 504 | "cell_type": "markdown", |
422 | 505 | "metadata": {}, |
|
507 | 590 | " \"Git merge driver for notebooks\"\n", |
508 | 591 | " if not _git_merge_file(base, ours, theirs).returncode: return\n", |
509 | 592 | " theirs = str2bool(os.environ.get('THEIRS', False))\n", |
510 | | - " return _nbdev_fix(ours, theirs=theirs)" |
511 | | - ] |
512 | | - }, |
513 | | - { |
514 | | - "cell_type": "markdown", |
515 | | - "metadata": {}, |
516 | | - "source": [ |
517 | | - "This implements a [git merge driver](https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver) for notebooks that automatically resolves conflicting metadata and outputs, and splits remaining conflicts as separate cells so that the notebook can be viewed and fixed in Jupyter. The easiest way to install it is by running `nbdev_install_hooks`." |
| 593 | + " return nbdev_fix.__wrapped__(ours, theirs=theirs)" |
518 | 594 | ] |
519 | 595 | }, |
520 | 596 | { |
521 | 597 | "cell_type": "markdown", |
522 | 598 | "metadata": {}, |
523 | 599 | "source": [ |
| 600 | + "This implements a [git merge driver](https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver) for notebooks that automatically resolves conflicting metadata and outputs, and splits remaining conflicts as separate cells so that the notebook can be viewed and fixed in Jupyter. The easiest way to install it is by running `nbdev_install_hooks`.\n", |
| 601 | + "\n", |
524 | 602 | "This works by first running Git's default merge driver, and then `nbdev_fix` if there are still conflicts. You can set `nbdev_fix`'s `theirs` argument using the `THEIRS` environment variable, for example:\n", |
525 | 603 | "\n", |
526 | 604 | " THEIRS=True git merge branch" |
|
540 | 618 | "outputs": [], |
541 | 619 | "source": [ |
542 | 620 | "#|hide\n", |
543 | | - "from nbdev.doclinks import nbdev_export\n", |
544 | | - "nbdev_export()" |
| 621 | + "import nbdev.doclinks; nbdev.nbdev_export()" |
545 | 622 | ] |
546 | 623 | }, |
547 | 624 | { |
|
0 commit comments