Giter Club home page Giter Club logo

nbdev's Introduction

Getting Started

CI

nbdev is a notebook-driven development platform. Simply write notebooks with lightweight markup and get high-quality documentation, tests, continuous integration, and packaging for free!

nbdev makes debugging and refactoring your code much easier than in traditional programming environments since you always have live objects at your fingertips. nbdev also promotes software engineering best practices because tests and documentation are first class.

  • Documentation is automatically generated using Quarto and hosted on GitHub Pages. Docs support LaTeX, are searchable, and are automatically hyperlinked (including out-of-the-box support for many packages via nbdev-index)
  • Publish packages to PyPI and conda as well as tools to simplify package releases. Python best practices are automatically followed, for example, only exported objects are included in __all__
  • Two-way sync between notebooks and plaintext source code allowing you to use your IDE for code navigation or quick edits
  • Tests written as ordinary notebook cells are run in parallel with a single command
  • Continuous integration out-of-the-box with GitHub Actions that run your tests and rebuild your docs
  • Git-friendly notebooks with Jupyter/Git hooks that clean unwanted metadata and render merge conflicts in a human-readable format
  • … and much more!

Install

nbdev works on macOS, Linux, and most Unix-style operating systems. It works on Windows under WSL, but not under cmd or Powershell.

You can install nbdev with pip:

pip install nbdev

… or with conda (or mamba):

conda install -c fastai nbdev

Note that nbdev must be installed into the same Python environment that you use for both Jupyter and your project.

How to use nbdev

The best way to learn how to use nbdev is to complete either the written walkthrough or video walkthrough:

Alternatively, there’s a shortened version of the video walkthrough with coding sections sped up using the unsilence Python library – it’s 27 minutes faster, but a bit harder to follow.

You can also run nbdev_help from the terminal to see the full list of available commands:

!nbdev_help
nbdev_bump_version        Increment version in settings.ini by one
nbdev_changelog           Create a CHANGELOG.md file from closed and labeled GitHub issues
nbdev_clean               Clean all notebooks in `fname` to avoid merge conflicts
nbdev_conda               Create a `meta.yaml` file ready to be built into a package, and optionally build and upload it
nbdev_create_config       Create a config file.
nbdev_docs                Create Quarto docs and README.md
nbdev_export              Export notebooks in `path` to Python modules
nbdev_filter              A notebook filter for Quarto
nbdev_fix                 Create working notebook from conflicted notebook `nbname`
nbdev_help                Show help for all console scripts
nbdev_install             Install Quarto and the current library
nbdev_install_hooks       Install Jupyter and git hooks to automatically clean, trust, and fix merge conflicts in notebooks
nbdev_install_quarto      Install latest Quarto on macOS or Linux, prints instructions for Windows
nbdev_merge               Git merge driver for notebooks
nbdev_migrate             Convert all markdown and notebook files in `path` from v1 to v2
nbdev_new                 Create an nbdev project.
nbdev_prepare             Export, test, and clean notebooks, and render README if needed
nbdev_preview             Preview docs locally
nbdev_proc_nbs            Process notebooks in `path` for docs rendering
nbdev_pypi                Create and upload Python package to PyPI
nbdev_readme              Create README.md from readme_nb (index.ipynb by default)
nbdev_release_both        Release both conda and PyPI packages
nbdev_release_gh          Calls `nbdev_changelog`, lets you edit the result, then pushes to git and calls `nbdev_release_git`
nbdev_release_git         Tag and create a release in GitHub for the current version
nbdev_sidebar             Create sidebar.yml
nbdev_test                Test in parallel notebooks matching `path`, passing along `flags`
nbdev_trust               Trust notebooks matching `fname`
nbdev_update              Propagate change in modules matching `fname` to notebooks that created them

FAQ

Q: What is the warning “Found a cell containing mix of imports and computations. Please use separate cells”?

A: You should not have cells that are not exported, and contain a mix of import statements along with other code. For instance, don’t do this in a single cell:

import some_module
some_module.something()

Instead, split this into two cells, one which does import some_module, and the other which does some_module.something().

The reason for this is that when we create your documentation website, we ensure that all of the signatures for functions you document are up to date, by running the imports, exported cells, and show_doc functions in your notebooks. When you mix imports with other code, that other code will be run too, which can cause errors (or at least slowdowns) when creating your website.

Q: Why is nbdev asking for root access? How do I install Quarto without root access?

A: When you setup your first project, nbdev will attempt to automatically download and install Quarto for you. This is the program that we use to create your documentation website.

Quarto’s standard installation process requires root access, and nbdev will therefore ask for your root password during installation. For most people, this will work fine and everything will be handled automatically – if so, you can skip over the rest of this section, which talks about installing without root access.

If you need to install Quarto without root access on Linux, first cd to wherever you want to store it, then download Quarto, and type:

dpkg -x quarto*.deb .
mv opt/quarto ./
rmdir opt
mkdir -p ~/.local/bin
ln -s "$(pwd)"/quarto/bin/quarto ~/.local/bin

To use this non-root version of Quarto, you’ll need ~/.local/bin in your PATH environment variable. (Alternatively, change the ln -s step to place the symlink somewhere else in your path.)

Q: Someone told me not to use notebooks for “serious” software development!

A: Watch this video. Don’t worry, we still get this too, despite having used nbdev for a wide range of “very serious” software projects over the last three years, including deep learning libraries, API clients, Python language extensions, terminal user interfaces, and more!

Contributing

If you want to contribute to nbdev, be sure to review the contributions guidelines. This project adheres to fastai’s code of conduct. By participating, you are expected to uphold this code. In general, we strive to abide by generally accepted best practices in open-source software development.

Make sure you have nbdev’s git hooks installed by running nbdev_install_hooks in the cloned repository.

Copyright

Copyright © 2019 onward fast.ai, Inc. Licensed under the Apache License, Version 2.0 (the “License”); you may not use this project’s files except in compliance with the License. A copy of the License is provided in the LICENSE file in this repository.

nbdev's People

Contributors

benoit-cty avatar bkowshik avatar danteoz avatar deven-gqc avatar deven367 avatar dleen avatar fabge avatar hamelsmu avatar hugetim avatar isaac-flath avatar itepifanio avatar jmoralez avatar joel-lbth avatar jph00 avatar kbodolai avatar kevinbird15 avatar michaelaye avatar mone27 avatar muellerzr avatar nhstanley avatar omlnaut avatar p4perf4ce avatar renato145 avatar restlessronin avatar seem avatar shacharhelmer avatar slee5777 avatar tylere avatar xl0 avatar yegeniy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nbdev's Issues

Export Error

Hello nbdev Team,

I try to use nbdev to develop a prototyped library, but I constantly encounter this problem when I executing notebook2script():

Converted 00_rec.ipynb.
Converted 01_ts.ipynb.
Converted 02_nlp.ipynb.

KeyError Traceback (most recent call last)
~\Anaconda3\envs\ml_env\lib\sre_parse.py in parse_template(source, pattern)
1014 try:
-> 1015 this = chr(ESCAPES[this][1])
1016 except KeyError:

KeyError: '\l'

During handling of the above exception, another exception occurred:

error Traceback (most recent call last)
in
1 from nbdev.export import notebook2script
----> 2 notebook2script()

~\Anaconda3\envs\ml_env\lib\site-packages\nbdev\export.py in notebook2script(fname, silent, to_dict)
322 else: files = glob.glob(fname)
323 d = collections.defaultdict(list) if to_dict else None
--> 324 for f in sorted(files): d = _notebook2script(f, silent=silent, to_dict=d)
325 if to_dict: return d
326 else: add_init(Config().lib_path)

~\Anaconda3\envs\ml_env\lib\site-packages\nbdev\export.py in _notebook2script(fname, silent, to_dict)
298 with open(fname_out, 'a', encoding='utf8') as f: f.write(code)
299 if f'{e}.py' not in mod.modules: mod.modules.append(f'{e}.py')
--> 300 save_nbdev_module(mod)
301
302 if not silent: print(f"Converted {fname.name}.")

~\Anaconda3\envs\ml_env\lib\site-packages\nbdev\export.py in save_nbdev_module(mod)
259 code = _re_index_idx.sub("index = {"+ t +"}", code)
260 t = ',\n '.join([f'"{f}"' for f in mod.modules])
--> 261 code = _re_index_mod.sub(f"modules = [{t}]", code)
262 with open(fname, 'w') as f: f.write(code)
263

~\Anaconda3\envs\ml_env\lib\re.py in _subx(pattern, template)
307 def _subx(pattern, template):
308 # internal: Pattern.sub/subn implementation helper
--> 309 template = _compile_repl(template, pattern)
310 if not template[0] and len(template[1]) == 1:
311 # literal replacement

~\Anaconda3\envs\ml_env\lib\re.py in _compile_repl(repl, pattern)
298 def _compile_repl(repl, pattern):
299 # internal: compile replacement pattern
--> 300 return sre_parse.parse_template(repl, pattern)
301
302 def _expand(pattern, match, template):

~\Anaconda3\envs\ml_env\lib\sre_parse.py in parse_template(source, pattern)
1016 except KeyError:
1017 if c in ASCIILETTERS:
-> 1018 raise s.error('bad escape %s' % this, len(this))
1019 lappend(this)
1020 else:

error: bad escape \l at position 18

`
I have no idea where the code crash, but seems like there is some problems in my 03a_*.ipynb notebook since after I delete this notebook, everything works well. But after recreating this notebook and executing a few exports, this problem occurs again.

I am using Windows Anaconda, Jupyter Notebook.

Best

Does nbdev work if my repo is not hosted on GitHub?

In one of the first steps of the README, the user is asked to create a (GitHub) repo from the template.

My code runs on a local git server (as my organization doesn't use GitHub atm).

Can I run/use nbdev anyway, or is GitHub a hard dependency? (in case it is, it might be helpful to state it early on in the README). Thanks!

CI problem - can't import dependency

Hi,

First of all - thanks for sharing this! I'm just starting to use nbdev but it looks like an amazing platform for library development.

I'm having trouble setting up CI with nbdev. This is possibly not nbdev-related - in which case, I'd appreciate any pointers you might have regarding where to ask this.

One of the dependencies of my library is rpy2. At first I was thinking that Github's CI would "catch" the dependencies and install them (similarly to find_packages()) but the first build failed because rpy2 wasn't installed. I then manually added pip install rpy2 to main.yaml and got:

Collecting rpy2
18
  Downloading https://files.pythonhosted.org/packages/d9/51/d5c41ac70e0aa3272f24cf836bd35d6246c95b98d8d811f338cec5a8098e/rpy2-3.2.2.tar.gz (162kB)
19
    ERROR: Command errored out with exit status 1:
20
     command: /opt/hostedtoolcache/Python/3.6.9/x64/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-alanql6m/rpy2/setup.py'"'"'; __file__='"'"'/tmp/pip-install-alanql6m/rpy2/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-alanql6m/rpy2/pip-egg-info
21
         cwd: /tmp/pip-install-alanql6m/rpy2/
22
    Complete output (1 lines):
23
    There is no R_HOME and the R executable cannot be found.

I wasn't able to solve this, so I tried replacing pip install rpy2 with conda install -c r rpy2 in main.yaml. In this case installation was successful, but in the "Run tests" stage I got ModuleNotFoundError: No module named 'rpy2'. The entire trace is available here.

Any help would be much appreciated, and thanks again!

nb_build_docs fails if show_doc is in different cell

I was following the tutorial and after implementing the HelloSayer class, the nb_build_docs command failed with:

converting: /home/connor/Projects/nbdev-test/00_core.ipynb
An error occurred while executing the following cell:
------------------
show_doc(HelloSayer.say)

------------------

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-693d9388d4f4> in <module>()
----> 1 show_doc(HelloSayer.say)

NameError: name 'HelloSayer' is not defined
NameError: name 'HelloSayer' is not defined

This can be fixed by putting the show_doc(HelloSayer.say) in the same cell as the class definition, but this doesn't seem like intended behaviour so I thought I'd mention it.

The code leading to this error can be found here: https://github.com/ConnorJL/nbdev-test

Dependency to twine package is missing.

Greetings,
I tried to add my project to pypi. I followed the instructions under "Adding your project to pypi" and ran into the following error:

twine upload --repository pypi dist/*
/bin/sh: 1: twine: not found
Makefile:23: recipe for target 'pypi' failed
make: *** [pypi] Error 127

I was able to fix the issue by running pip install twine. But I think it would be helpful to add twine to the nbdev requirements or at least but a note under "Adding your project to pypi" that this step might be needed for first-time users of pypi.

All the best
cpow-89

Multiple translations in the same Notebook

Is there a way to add multiple markdown translations and using something like a tab button to switch to that translation, instead of having to duplicate a notebook per language, making it harder to maintain the source code? When talking about translations I'm refering to handmade ones, not autogenerated by something like Google Translate

Key error.

Hello ndbev team,
When i'm trying to follow Jeremy tutorial on nbdev i was not able to build the library.

(base) mac:fastrl[master*] »nbdev_build_lib
Traceback (most recent call last):
File "/Users/vinay/anaconda3/bin/nbdev_build_lib", line 11, in
sys.exit(nbdev_build_lib())
File "/Users/vinay/anaconda3/lib/python3.7/site-packages/fastscript/core.py", line 73, in _f
func(**args.dict)
File "/Users/vinay/anaconda3/lib/python3.7/site-packages/nbdev/cli.py", line 20, in nbdev_build_lib
write_tmpls()
File "/Users/vinay/anaconda3/lib/python3.7/site-packages/nbdev/export2html.py", line 329, in write_tmpls
write_tmpl(config_tmpl, 'user lib_name title copyright description', cfg, cfg.doc_path/'_config.yml')
File "/Users/vinay/anaconda3/lib/python3.7/site-packages/nbdev/export2html.py", line 321, in write_tmpl
vs = {o:cfg.d[o] for o in nms.split()}
File "/Users/vinay/anaconda3/lib/python3.7/site-packages/nbdev/export2html.py", line 321, in
vs = {o:cfg.d[o] for o in nms.split()}
File "/Users/vinay/anaconda3/lib/python3.7/configparser.py", line 1251, in getitem
raise KeyError(key)
KeyError: 'copyright'

Math in Markdown

Hi. I am using nbdev to develop my library and everything works fine except for the rendering of math in the README.md. It looks ok in the documentation, but it is not rendered in Github's README.md (the $$ signs still appear). I can see you have the same issue in your very own REDME.md. Are you aware of this issue ? Thanks.

The nbdev pip package seems incompatible with the jupyter conda package

I am no expert on how conda and pip interact, so I'm not sure if this incompatibility is worth worrying about. But I thought I would mention it here in case someone else encounters it:

If I use conda to install only python, and then use pip to install nbdev (and thus pull in jupyter as a dependency), then it's fine:

conda create -n working
conda activate working
conda install -y python
pip install nbdev
# notebooks work fine

However, when I use conda to install jupyter, and then use pip to install nbdev, I get in invalid install:

conda create -n broken
conda activate broken
conda install -y jupyter
pip install nbdev
pip check
# => ipython 7.10.1 has requirement prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0, but you have prompt-toolkit 1.0.18
# and notebooks don't open properly

I am not sure what's producing the incompatible requirement for the low version of prompt-toolkit 1.0.18. It seems to becoming from the requirement of an older version of jupyter-console 5.2.0, as opposed to the jupyter-console 6.0.0 .

nbdev_build_docs failure on markdown.tpl

# nbdev_build_docs
converting: /home/neuron/src/sch/p10n-experiments-nbdev/02_yapoexperiment.ipynb
basic.tpl
Traceback (most recent call last):
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/bin/nbdev_build_docs", line 8, in <module>
    sys.exit(nbdev_build_docs())
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/fastscript/core.py", line 73, in _f
    func(**args.__dict__)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/nbdev/cli.py", line 158, in nbdev_build_docs
    if mk_readme: make_readme()
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/nbdev/cli.py", line 145, in make_readme
    convert_md(index_fn, Config().config_file.parent, jekyll=False)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/nbdev/export2html.py", line 408, in convert_md
    export = exp.from_notebook_node(nb, resources=meta_jekyll)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/nbconvert/exporters/templateexporter.py", line 357, in from_notebook_node
    output = self.template.render(nb=nb_copy, resources=resources)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
    return original_render(self, *args, **kwargs)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
    return self.environment.handle_exception(exc_info, True)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "/home/neuron/src/sch/p10n-experiments-nbdev/.venv/lib/python3.6/site-packages/nbdev/templates/md.tpl", line 1, in top-level template code
    {%- extends 'markdown.tpl' -%}{% block body %}
jinja2.exceptions.TemplateNotFound: markdown.tpl

At first glance looks like a duplicate of #8, but I'm using nbdev 0.2.5.

# find . -name markdown.tpl
./.venv/lib/python3.6/site-packages/nbconvert/templates/markdown.tpl

Installation Error With Latest Version of nbdev followed by nbdev_install_git_hooks

I'm running this in a Docker Container to ensure reproduceability:

I run
pip install nbdev

followed by
nbdev_install_git_hooks

And I get the below. I am able to reproduce this error

root@72f2708e1479:/# nbdev_install_git_hooks
Traceback (most recent call last):
  File "/usr/local/bin/nbdev_install_git_hooks", line 8, in <module>
    sys.exit(nbdev_install_git_hooks())
  File "/usr/local/lib/python3.6/site-packages/fastscript/core.py", line 73, in _f
    func(**args.__dict__)
  File "/usr/local/lib/python3.6/site-packages/nbdev/cli.py", line 241, in nbdev_install_git_hooks
    path = Config().config_file.parent
  File "/usr/local/lib/python3.6/site-packages/nbdev/imports.py", line 42, in __init__
    assert self.config_file.exists(), "Use `Config.create` to create a `Config` object the first time"
AssertionError: Use `Config.create` to create a `Config` object the first time

Escape LaTeX math with Liquid "raw" tags?

This is a Feature Request.

At the request of @hamelsmu in PR github/covid19-dashboard#89, I'm opening this Issue to see if there could be automatic support for LaTeX equations in nbdev such that they don't generate conflicts with Liquid (for Fastpages) later.

Could you make it so that LaTeX equations (in text cells) such as

$$ ... $$

gets automatically replaced with

{{% raw %}}
$$ ... $$
{{% endraw %}}

?

Not sure if this would introduce problems elsewhere. However, it would help with Fastpages supporting seeming 'innocuous' math equations (pun intended) such as in this covid-19 dashboard notebook github/covid19-dashboard#89

Perhaps some command line switch like --liquid could be used to let nbdev know that its output is intended for use with Liquid.

Question: Captions for local image files just like urls ?

With nbdev, you can include captions in images like this:

![](https://www.fast.ai/images/fastai_paper/show_batch.png "My Caption")

However, when the link is a local file, instead of a url this is not picked up by nbdev. For example,

![](my_icons/fastai_logo.png "hello")

is not handled the same way - this results an in error when someone tries to do this. @sgugger I believe perhaps we should make an ammendment to the _img2jkl function:

nbdev/nbdev/export2html.py

Lines 125 to 129 in 9f572b2

def _img2jkl(d, h, jekyll=True):
if not jekyll: return '<img ' + h.attrs2str() + '>'
if 'width' in d: d['max-width'] = d.pop('width')
if 'src' in d: d['file'] = d.pop('src')
return '{% include image.html ' + h.attrs2str() + ' %}'

However, I am not completely sure that is as easy as changing this function. We might have to also (1) copy the image (2) change the relative path to the copied location. Please let me know your thoughts.

The related issue on fatpages: fastai/fastpages#225

cc:@noklam

_config.yml is not generated using nbdev_build_docs

When using nbdev_build_docs from the command line the _config.yml file in the docs folder is not generated.

When using the below code in a notebook cell it does work.

#hide
from nbdev.export import *
notebook2script()

export to 2 modules from 1 notebook

  • I was trying to export 2 modules from 1 single notebook, as I learnt from the doc here
  • Upon nbdev_build_lib , I ran into error
Traceback (most recent call last):
  File "/Users/salvor/anaconda3/bin/nbdev_build_lib", line 8, in <module>
    sys.exit(nbdev_build_lib())
  File "/Users/salvor/.local/lib/python3.7/site-packages/fastscript/core.py", line 73, in _f
    func(**args.__dict__)
  File "/Users/salvor/.local/lib/python3.7/site-packages/nbdev/cli.py", line 22, in nbdev_build_lib
    notebook2script(fname=fname)
  File "/Users/salvor/.local/lib/python3.7/site-packages/nbdev/export.py", line 371, in notebook2script
    for f in sorted(files): d = _notebook2script(f, silent=silent, to_dict=d)
  File "/Users/salvor/.local/lib/python3.7/site-packages/nbdev/export.py", line 310, in _notebook2script
    if to_dict is None: _add2add(fname_out, [f"'{f}'" for f in names if '.' not in f and len(f) > 0] + extra)
  File "/Users/salvor/.local/lib/python3.7/site-packages/nbdev/export.py", line 183, in _add2add
    start,end = re_all.start(),re_all.end()
AttributeError: 'NoneType' object has no attribute 'start'
  • I realize #default_exp [module] can solve this, as this call the function create_mod_file to create the __all__ expression , but put 2 #default_exp cells in 1 notebook will make the 2nd one ignored.

  • I also tried to avoid this by creating a notebook with a single cell specifying a second #default_exp [module], I can run nbdev_build_lib smoothly, but nbdev_build_docs run into further error

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-e7b5de274890> in <module>
----> 1 show_doc(docModel, default_cls_level=2)
                                                                                      
NameError: name 'docModel' is not defined

  File "/Users/salvor/anaconda3/bin/nbdev_build_docs", line 8, in <module>
    sys.exit(nbdev_build_docs())
  File "/Users/salvor/.local/lib/python3.7/site-packages/fastscript/core.py", line 73, in _f
    func(**args.__dict__)
  File "/Users/salvor/.local/lib/python3.7/site-packages/nbdev/cli.py", line 164, in nbdev_build_docs
    notebook2html(fname=fname, force_all=force_all, n_workers=n_workers)
  File "/Users/salvor/.local/lib/python3.7/site-packages/nbdev/export2html.py", line 412, in notebook2html
    raise Exception(msg + '\n'.join([f.name for p,f in zip(passed,files) if not p]))
Exception: Conversion failed on the following:
python_parse.ipynb

Please pardon my stubborn about this, I just find generate 2 modules from 1 notebook useful, I can expand an entire project from 1 experimenting notebook easily. Thanks

Help Using `notebook2html`

I am trying to use notebook2html by itself. I'm confused because I'm able to import the library just fine

from nbdev.export2html import notebook2html

However, getting a strange error regarding ModuleNotFoundError when trying to call notebook2html in an ipython console. Perhaps its something to do with the way nbdev is being called but I'm not sure?

Python 3.6.7 (v3.6.7:6ec5cf24b7, Oct 20 2018, 03:02:14)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.11.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from nbdev.export2html import notebook2html

In [2]: notebook2html('1-altair_introduction.ipynb')
converting: 1-altair_introduction.ipynb
An error occurred while executing the following cell:
------------------
#export
from nbdev.showdoc import show_doc
------------------

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-5f00178d23a7> in <module>()
      1 #export
----> 2 from nbdev.showdoc import show_doc

ModuleNotFoundError: No module named 'nbdev'
ModuleNotFoundError: No module named 'nbdev'

broken image urls

I found out my previous pull request resulted in some broken URLs (as pointed out in #28), this didn't show up in my tests since the tests were using the previous URL pattern.

I saw that @sgugger already fixed some of these issues by setting a doc_url in settings.ini (while I was also working on it) and it seems to be working now. The only downside of this is that some URLs will point to an external source when running the code locally, but I guess this is not a big issue and I cannot find a cleaner solution right now either.

I just want to point out that same problem causes image URLs to not work (if they are not on the homepage), for example here http://nbdev.fast.ai/merge/
The image refers to http://nbdev.fast.ai/merge/images/merge.PNG instead of to http://nbdev.fast.ai/images/merge.PNG but http://nbdev.fast.ai/images/export_example.png on the http://nbdev.fast.ai/ still works.

supporting multiple paths for nbs_path?

In my programming sense, the notebooks could be better organized when they are stored into different categories of directories.

Let me know about what your thoughts

function reference URL in tip or note will break jekyll build

I discovered that when using a function reference URL in a > note: or > tip: it will break the jekyll build locally as well as on my Heroku app with the following exception:

Liquid Exception: Invalid syntax for include tag: content="The <a href="utils#example_func">The <code>example_func</code></a> does something ." Valid syntax: {% include file.ext param='value' param2='value' %} in utils.html

I confirmed this by removing one of the links (then it gave an error on the next one) and by removing both of them (solving the error).

I think this is caused by the double quotes in the url breaking the content=" ... ", maybe a solution would be to use single quotes in the translation of the urls to html. I will try this and make a pull request if it works.

Wheel missing as dependency

After running pip install nbdev I receive this error (though it does appear to install correctly):

  Complete output from command /home/vagrant/wlyze/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-6zfwmzwq/pyrsistent/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" bdist_wheel -d /tmp/tmph67xwsmupip-wheel- --python-tag cp36:
  usage: -c [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
     or: -c --help [cmd1 cmd2 ...]
     or: -c --help-commands
     or: -c cmd --help
  
  error: invalid command 'bdist_wheel'

It appears that 'wheel' should be added to settings.ini based on this answer: https://stackoverflow.com/questions/34819221/why-is-python-setup-py-saying-invalid-command-bdist-wheel-on-travis-ci

run command nbdev_build_lib got KeyError: 'copyright'

i am running command nbdev_build_lib, got:

:~/openthings/nbdev_template$ nbdev_build_lib
Traceback (most recent call last):
  File "/home/supermap/anaconda3/bin/nbdev_build_lib", line 8, in <module>
    sys.exit(nbdev_build_lib())
  File "/home/supermap/anaconda3/lib/python3.6/site-packages/fastscript/core.py", line 73, in _f
    func(**args.__dict__)
  File "/home/supermap/anaconda3/lib/python3.6/site-packages/nbdev/cli.py", line 21, in nbdev_build_lib
    write_tmpls()
  File "/home/supermap/anaconda3/lib/python3.6/site-packages/nbdev/export2html.py", line 334, in write_tmpls
    write_tmpl(config_tmpl, 'user lib_name title copyright description', cfg, cfg.doc_path/'_config.yml')
  File "/home/supermap/anaconda3/lib/python3.6/site-packages/nbdev/export2html.py", line 326, in write_tmpl
    vs = {o:cfg.d[o] for o in nms.split()}
  File "/home/supermap/anaconda3/lib/python3.6/site-packages/nbdev/export2html.py", line 326, in <dictcomp>
    vs = {o:cfg.d[o] for o in nms.split()}
  File "/home/supermap/anaconda3/lib/python3.6/configparser.py", line 1233, in __getitem__
    raise KeyError(key)
KeyError: 'copyright'

add following to setting.ini,success:

copyright = openthings
description = test

An automated security update nokogiri

Hi, I use 'nbdev' to build a Python package. Today I receive an alert from GitHub.
Here is the alert public address https://github.com/JiaxiangBU/pyks/network/alert/Gemfile.lock/nokogiri/open
It suggests I should run gem "nokogiri", ">= 1.10.8" to update 'nokogiri'. I don't use 'Ruby' before.
How could I fix this?

In the Gemfile.lock file, it sets https://github.com/JiaxiangBU/pyks/blob/525f1632201da914654f4f3d7378160c96b8a518/Gemfile.lock#L75

Here is the package address hosted at GitHub: https://github.com/JiaxiangBU/pyks

Latest release breaks command `#hide_input`

Before 0.2.14 the comment #hide_input would hide input only

Now, with release 0.2.14 the comment #hide_input hides BOTH the input and the output.

I believe this is a bug? Or has this functionality been changed? @sgugger

Thank you!

TOC generation breakage

Hi,

When I put text directly after the notebook title cell, the table of contents is not generated correctly. I've attached a screenshot of the notebook and the resulting documentation page.

  • The methods are correctly shown in the TOC, but the headings are not. Instead, they are printed just after the TOC with bullet points.
  • The problematic text is not shown in the generated documentation.
  • When I insert a new heading right after the title, the TOC is correctly generated.

Problematic notebook

Screenshot 2020-02-14 at 17 01 43

Generated documentation

Screenshot 2020-02-14 at 16 58 18

Best way to export captions from markdown in nbdev?

the fastai blog has captions

image

Would love to add this to fastpages, not completely sure how to inject captions.

I took a look at https://github.com/fastai/nbdev/blob/2eb60a5634d2296bc6b67fcd671ca0d584e22e35/nbs/index.ipynb, and it looks like this is done via HTML in a notebook like this?

<img alt="Exporting from nbdev" width="700" caption="An example of a function defined in one cell (marked with the export flag) and explained, along with a visual example, in the following cells" src="images/export_example.png" />

What is the best path for me to convert markdown in a similar way (as you can have descriptions in markdown as well)? Such as ![Some descritpion](images/image.png)

I can help add this to nbdev but wanted to check here first. Happy to post on forums instead if that is more appropriate. Thank you 🙇

Support determenistic builds

Currently nbdev installs the latest versions of dependencies, so unless you put every transitive dependency in settings.ini which is quite cumbersome. You won't have deterministic builds.

I'd like to see support for systems that deal with this better. requirements.txt is probably the most used one, but I strongly favor pipenv personally. (https://pipenv.kennethreitz.org/en/latest/)

One way of doing this that should be fairly flexible is separating "how to install the dependency management tool + running it..".

requirements = pipenv
requirements_cmd = pipenv install

Either that or supporting picking up a requirements.txt / Pipfile* files in the root directory.

_config.yml not included after clone from nbdev_template

Description

I'm following the steps in the tutorial and find that the Build lib step fails with the following error:

$ nbdev_build_lib
Traceback (most recent call last):
  File "/usr/local/anaconda3/bin/nbdev_build_lib", line 8, in <module>
    sys.exit(nbdev_build_lib())
  File "/usr/local/anaconda3/lib/python3.7/site-packages/fastscript/core.py", line 73, in _f
    func(**args.__dict__)
  File "/usr/local/anaconda3/lib/python3.7/site-packages/nbdev/cli.py", line 20, in nbdev_build_lib
    notebook2script(fname=fname)
  File "/usr/local/anaconda3/lib/python3.7/site-packages/nbdev/export.py", line 364, in notebook2script
    update_baseurl()
  File "/usr/local/anaconda3/lib/python3.7/site-packages/nbdev/export.py", line 351, in update_baseurl
    with open(fname, 'r') as f: code = f.read()
FileNotFoundError: [Errno 2] No such file or directory: '/Users/lewtun/git/ds-lectures/docs/_config.yml'

For some reason, the _config.yml file is not generated when using nbdev_template - see here for an example of the contents of docs/ after creating the repo.

Steps to reproduce the problem

  1. Create a repo using nbdev_template
  2. Clone the repo
  3. Configure settings.ini
  4. Run nbdev_install_git_hooks (this works)
  5. Run nbdev_build_lib

Steps to fix the problem

Include _config.yml in the repo template. Adding this locally solved the problem for me.

source link to methods or classes for locally hosted website

Hi,

Thanks for the amazing repo. I am able to get it up and running in a day with all the content transferred from my existing repo.

I have a private repo which I am hosting locally instead of Github Pages. I followed the documentation available in the repo for local hosting

But the documentation website(locally hosted) doesn't have correct links to the methods and classes used in the notebook. They try to link to github website. Is there any way to make the source links point to the current repo instead of github location

Let me know if my question is not clear. I will go more in detail

Thanks

Docs: Add tutorials in Sidebar

Hey,

First of, thanks for nbdev 😀.

I am struggling to put all my tutorials under the same toggle in the sidebar like you do in fastai2.

I named my notebooks :

  • 0x_tutorial.how_to_read_an_image.ipynb
  • 0x_tutorial.how_to_compute_histograms.ipynb

I wanted to get them under the same toggle in the sidebar but no luck so far. Even digging into the fastai2 or nbdev repo...

So How can I achieve my goal?

Getting in a Tutorials toggle in the sidebar:
Tutorials/

  • How to read an image
  • How to compute histograms

PS: I have digged into the fastai2 repo and got the idea from there 😉

Link to generate repo broken

Link to https://github.com/fastai/nbdev_template/generate in the readme returns a 404. Is it just supposed to go to the repo or is there a widget to customize the settings.ini info?

Broken hyperlinks inside section summaries in fastpages _notebooks

In fastpages, placing a hyperlink inside a section summary, that is, after a ">" breaks the link. The link works fine inside Jupyter Notebook, but when posted, the link address is changed.

I re-created the problem in the Intro to fastpages notebook. In the first paragraph that begins, "We are pleased to announce . . .", converting that paragraph to a section summary breaks the link to fastpages.

Initially I submitted this to fastpages, but per @hamelsmu, it's more an nbdev issue

cc
@sgugger

Running nbdev_build_lib generates FileNotFoundError

Here is my sequence .

  1. I generate my project from the github template,
  2. clone my project to my local machine
  3. edit my settings.ini file with my project meta data
  4. run nbdev_build_lib

When I run nbdev_build_lib i get this error.

nbdev_build_lib
Traceback (most recent call last):
File "/gpfs/home/s4s004/vanstee/anaconda3/envs/powerai-1.6.2/bin/nbdev_build_lib", line 8, in
sys.exit(nbdev_build_lib())
File "/gpfs/home/s4s004/vanstee/anaconda3/envs/powerai-1.6.2/lib/python3.7/site-packages/fastscript/core.py", line 73, in _f
func(**args.dict)
File "/gpfs/home/s4s004/vanstee/anaconda3/envs/powerai-1.6.2/lib/python3.7/site-packages/nbdev/cli.py", line 20, in nbdev_build_lib
notebook2script(fname=fname)
File "/gpfs/home/s4s004/vanstee/anaconda3/envs/powerai-1.6.2/lib/python3.7/site-packages/nbdev/export.py", line 364, in notebook2script
update_baseurl()
File "/gpfs/home/s4s004/vanstee/anaconda3/envs/powerai-1.6.2/lib/python3.7/site-packages/nbdev/export.py", line 351, in update_baseurl
with open(fname, 'r') as f: code = f.read()
FileNotFoundError: [Errno 2] No such file or directory: '/gpfs/home/s4s004/vanstee/2019-10-kaggle-fastai/2020-01-pku/docs/_config.yml'

As a workaround, I just touch the docs/_config.yml file and I am able to get past this issue.

notebook2script saves based on data on filesystem, not jupyter content

So this issue is a bit hard to describe, but very logical when you look into it.

To demonstrate create the following new notebook

# Cell
#export
print("Test")

# Cell
from nbdev.export import notebook2script
notebook2script()

If you execute this from top to bottom, it won't export what would be expected. The reason is due to how jupyter saves files in checkpoints/to disk. notebook2script will work on the ipynb file on disk, but that's only saved by default once every 120 seconds.

This makes a lot of sense once you think about it, but it's not naturally logical that when working in a code window. When working in the code window you normally don't have to care what of your file has been buffered to disk and what hasn't.

I had a few issues with this, where I was looking at the .py files on disk to figure out why my code was failing, even though I was sure I fixed the bug is was failing on and ran the export (in many cases using nbdev_build). Then I wrote this #50 in order to not forget - and realized it didn't fix the issue.

Some ideas on how to solve this:

  1. Modify the autosave interval. With notebooks you can do that, but its not yet supported in jupyterlab. - jupyterlab/jupyterlab#7083 (triggering the same javascript in jupyter lab does not work...)
  2. Trigger the save function through javascript. This works, but it's hacky. And to make it considerably more hacky triggering javascript like this is async, which means we have to wait until the disk is updated to actually trigger the notebook2script... It might also need different methods for notebook vs jupyter lab.
  3. Make a jupyter plugin instead of %magic command. That can trigger on post_save. Then offer an installer like nbdev_install_git_hooks and tell people we auto export after ctrl+s. I'm not sure if this is trivial to do with notebooks as well as jupyter lab.

These are the only viable ideas I've found so far... I like #3 the best, but I think a warning in documentation / somewhere is needed to avoid this issue.. Hell maybe nbdev_build should check the .ipynb_checkpoints dir to see if there is temp files in there to warn the user that they are about to export something that isn't saved to disk first. It doesn't feel like a clean/elegant solution though...

Generate submenu item for submodule in sidebar

Hello all 👋

I have created several notebooks following a structure like this:

10_explore.ipynb
11_explore.first.ipynb
12_explore.second.ipynb

each defining a default export, e.g. # default_exp explore.first at the top of the notebook.

For readers of my documentation, it would be clear if the submodules (e.g. explore.first and explore.second) would get their own submenu item in the sidebar. From the fastai custom sidebar, I can see that there is support for this. However, I'm not seeing this being automatically generated. Am I doing something wrong or is automatic generation of submenus not (yet) supported?

URLs in Code cells get mangled

Original issue over in fastpages fastai/fastpages#215

Take a look at this notebook and scroll down to the NOTE.
https://tylerleonhardt.github.io/blog/jupyter/powershell/pswordcloud/2020/03/16/Word-Clouds.html

I'm using a magic command #!markdown to render markdown instead of a normal code block so I can show the markdown code behind it.

Unfortunately, for some reason fastpages mangles the path of my svg in the code sample:

![.NET Interactive codebase word cloud](/blog/images/copied_from_nb/dotnet-interactive.svg)

instead of

![.NET Interactive codebase word cloud](dotnet-interactive.svg)

which is what it is in source:
https://github.com/TylerLeonhardt/blog/blob/56e0f224d03866fd5118131ab41bcb8effb81453/_notebooks/2020-03-16-Word-Clouds.ipynb#L110

Expected Behavior

My url isn't touched.

![.NET Interactive codebase word cloud](dotnet-interactive.svg)

Actual Behavior

My url is mangled.

![.NET Interactive codebase word cloud](/blog/images/copied_from_nb/dotnet-interactive.svg)

Proposed solution

Don't expand image tags in Code blocks?

More context

so #!markdown is exposed by .NET Interactive:

https://github.com/dotnet/interactive

Which is a new hybrid-language kernel that supports the ability to call upon languages within different cells using magic commands

It supports:

C#, F#, PowerShell, JavaScript, HTML, Markdown

If the default language is PowerShell, for example, and I want to have a cell use Markdown, I can use the #!markdown magic command

Now I can agree that a #!markdown magic command is kinda silly because.. well... that's what a Markdown cell is for...

But the difference is that you see the markdown in addition to the output.

I guess It'd be the equivalent to a Markdown cell of:

## my markdown code

My markdown code

How to create subfolders for the documentation website

Hi,

I am able to create subfolders in the library_name folder (libraryname/foldername/modulename.py) by assigning the default_exp to foldername.modulename. I also renamed the notebook to number_foldername.modulename.ipynb.

But the documentation website for my repository still doesn't have any subfolders like I see in the documentation for fastai2 website at https://dev.fast.ai/

image

As an example, in the above picture, Optimizer is documented under Training. I am not sure how it is generated automatically. Can you provide some information on this.

I couldnt find the information to do this in the nbdev. If the information is not available and there is any need to document the process, I can make a PR

Thanks

Docs not building

I just made a test repo and followed the getting started guide.

I can build the modules but I get an error when trying to build the docs

nbdev_build_docs

result

converting: /home/jovyan/work/testingNBDev/99_index.ipynb jekyll.tpl Traceback (most recent call last): File "/opt/conda/bin/nbdev_build_docs", line 10, in <module> sys.exit(nbdev_build_docs()) File "/opt/conda/lib/python3.7/site-packages/fastscript/fastscript.py", line 42, in _f func(**args.__dict__) File "/opt/conda/lib/python3.7/site-packages/nbdev/cli.py", line 148, in nbdev_build_docs if mk_readme: make_readme() File "/opt/conda/lib/python3.7/site-packages/nbdev/cli.py", line 136, in make_readme convert_md(index_fn, Config().config_file.parent, jekyll=False) File "/opt/conda/lib/python3.7/site-packages/nbdev/export2html.py", line 401, in convert_md f.write(exp.from_notebook_node(nb, resources=meta_jekyll)[0]) File "/opt/conda/lib/python3.7/site-packages/nbconvert/exporters/templateexporter.py", line 322, in from_notebook_node output = self.template.render(nb=nb_copy, resources=resources) File "/opt/conda/lib/python3.7/site-packages/nbconvert/exporters/templateexporter.py", line 114, in template self._template_cached = self._load_template() File "/opt/conda/lib/python3.7/site-packages/nbconvert/exporters/templateexporter.py", line 293, in _load_template return self.environment.get_template(template_file) File "/opt/conda/lib/python3.7/site-packages/jinja2/environment.py", line 830, in get_template return self._load_template(name, self.make_globals(globals)) File "/opt/conda/lib/python3.7/site-packages/jinja2/environment.py", line 804, in _load_template template = self.loader.load(self, name, globals) File "/opt/conda/lib/python3.7/site-packages/jinja2/loaders.py", line 408, in load raise TemplateNotFound(name) jinja2.exceptions.TemplateNotFound: md.tpl

Customize Documentation Page / Theme

Thanks for the project, very excited about this! I managed to set up my first nbdev documentation page as the tutorial under my domain:

I want to go a step further to customize the documentation page to make its style consistent with my own existing blog (which is set up by Pelican):

Do you have any advice or direction where should I start or look into? For example, is there an easy way to switch from Jekyll to Pelican? If the Jekyll is the way to go, what are the recommended way to customize style?

I'm sure when nbdev becomes super popular, these questions will be asked frequently. Thanks in advance!

I think `add_jekyll_notes` is not flexible?

While looking around fastpages project, I have felt add_jekyll_notes is not flexible. (I might be wrong)

def add_jekyll_notes(cell):
    "Convert block quotes to jekyll notes in `cell`"
    _styles = ['note', 'warning', 'tip', 'important']
    def _inner(m):
        title,text = m.groups()
        if title.lower() not in _styles: return f"> {m.groups()[0]}: {m.groups()[1]}"
        return '{% include '+title.lower()+".html content=\'"+_to_html(text)+"\' %}"
    if cell['cell_type'] == 'markdown':
        cell['source'] = _re_block_notes.sub(_inner, cell['source'])
    return cell

Above is add_jekyll_notes function, and _styles are defined and assigned with static values.
When I want to add more styles like embedded twitter post or something, I need to define my own function. However, the only thing that has to change is _styles while the remaining codes are the same.

Below is add_embedded_links function from fastpages project.

def add_embedded_links(cell):
    "Convert block quotes to embedded links in `cell`"
    _styles = ['youtube', 'twitter']
    def _inner(m):
        title,text = m.groups()
        if title.lower() not in _styles: return f"> {m.groups()[0]}: {m.groups()[1]}"
        return '{% include '+title.lower()+".html content=\'`"+_to_html(text)+"`\' %}"
    if cell['cell_type'] == 'markdown':
        cell['source'] = _re_block_notes.sub(_inner, cell['source'])
    return cell

What do you think about separating _styles out as an parameters or property?
In that way, other projects relying on nbdev could be extended easier while hiding some internal complexity.

doc_host and doc_baseurl are not used properly in Heroku

I am running my documentation in an Heroku app that has an url of the form https://appname.herokuapp.com which I set as doc_host in the settings.ini file and I set the doc_baseurl to /.

When I run it like this locally it works as expected. However, when I push this to my Heroku app, the menu links don't work anymore and point to https://module instead of to https://appname.herokuapp.com/module.

The only way I can fix this is by manually editing the baseurl in docs/_config.yml to:

baseurl: https://appname.herokuapp.com

and then not running nbdev_build_lib. When I change the base_url in settings.ini to https://appname.herokuapp.com and do run nbdev_build_lib it creates other problems.

For now, it is not a big problem since I can just manually change the docs/_config.yml before pushing it to Heroku. But maybe there is some underlying issue that is causing this behavior.

Image URLs are getting treated as files

Following up from fastpages issue fastai/fastpages#58.

The error happens precisely in nbdev/export2html.py, in copy_images(), line 143:

 shutil.copy(Path(fname).parent/src, Path(dest)/src)

At this point, src is still a URL.
Example, I added a print statement just before this line for one of my image urls (see fastai/fastpages#58)

Output was:

calling shutil.copy, fname =  /home/shawley/devblog2/_notebooks/2019-12-21-PCA-From-Scratch.ipynb , src =  https://i.imgur.com/vKiH8As.png

This copy command tries to treat src like it's a filename, so it strips out extra slashes, and... yea things fail.

The other checks elsewhere in the file, e.g. in adapt_img_path() don't even get run before the code exits with an error.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.