From 532927a3c48918e0b059dbf46bd2096e67db12c6 Mon Sep 17 00:00:00 2001 From: ines Date: Wed, 17 May 2017 17:35:53 +0200 Subject: [PATCH 1/6] Update quickstart --- website/assets/css/_components/_quickstart.sass | 10 +++++++--- website/assets/js/quickstart.js | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/website/assets/css/_components/_quickstart.sass b/website/assets/css/_components/_quickstart.sass index f9972db70..4065940bc 100644 --- a/website/assets/css/_components/_quickstart.sass +++ b/website/assets/css/_components/_quickstart.sass @@ -10,7 +10,10 @@ padding: 2rem 3rem .c-quickstart__input - display: none + @include size(0) + opacity: 0 + position: absolute + left: -9999px .c-quickstart__label cursor: pointer @@ -25,6 +28,9 @@ &:hover background: lighten($color-theme-light, 5) + .c-quickstart__input:focus + & + border: 1px solid $color-theme + .c-quickstart__input--radio:checked + & color: $color-back border-color: $color-theme @@ -36,8 +42,6 @@ display: inline-block width: 20px height: 20px - position: relative - bottom: 0.2rem border: 1px solid $color-subtle vertical-align: middle margin-right: 1rem diff --git a/website/assets/js/quickstart.js b/website/assets/js/quickstart.js index a5a61661a..5212c46fb 100644 --- a/website/assets/js/quickstart.js +++ b/website/assets/js/quickstart.js @@ -4,4 +4,4 @@ * @author Ines Montani * @version 0.0.1 * @license MIT - */'use strict';var _createClass=function(){function a(b,c){for(var e,d=0;d['+this.dpfx+'-'+c+']'+e+' {display: none}';this._$('['+this.dpfx+'-style="'+c+'"]').textContent=g}},{key:'updateContainer',value:function updateContainer(){if(!this._$('['+this.dpfx+'-results]')){var b=this.childNodes(this.container,'pre'),c=b?b[0]:this._c('pre',this.pfx+'-code'),d=this.childNodes(c,'code')||this.childNodes(this.container,'code'),e=d?d[0]:this._c('code',this.pfx+'-results');e.setAttribute(this.dpfx+'-results','');var f=this.childNodes(e,'span')||this.childNodes(c,'span')||this.childNodes(this.container,'span');f&&f.forEach(function(g){return e.appendChild(g)}),c.appendChild(e),this.container.appendChild(c)}}},{key:'createGroup',value:function createGroup(b){var d=this,c=this._c('div',this.pfx+'-group');c.setAttribute(this.dpfx+'-group',b.id),c.innerHTML=this.createStyles(b.id).outerHTML,c.innerHTML+='
'+b.title+'
',c.innerHTML+='
'+b.options.map(function(e){var f=b.multiple?'checkbox':'radio';return''}).join('')+'
',this.container.insertBefore(c,this.container.firstChild),this.initGroup(c,b.id)}},{key:'createStyles',value:function createStyles(b){var c=this._c('style');return c.setAttribute(this.dpfx+'-style',b),c.textContent='['+this.dpfx+'-results]>['+this.dpfx+'-'+b+'] {display: none}',c}},{key:'childNodes',value:function childNodes(b,c){var d=c.toUpperCase();if(!b.hasChildNodes)return!1;var e=[].concat(_toConsumableArray(b.childNodes)).filter(function(f){return f.nodeName===d});return!!e.length&&e}},{key:'_$',value:function _$(b){return document.querySelector(b)}},{key:'_$$',value:function _$$(b){return[].concat(_toConsumableArray(document.querySelectorAll(b)))}},{key:'_c',value:function _c(b,c){var d=document.createElement(b);return c&&(d.className=c),d}}]),a}(); + */'use strict';var _createClass=function(){function a(b,c){for(var e,d=0;d['+this.dpfx+'-'+c+']'+e+' {display: none}';this._$('['+this.dpfx+'-style="'+c+'"]').textContent=g}},{key:'updateContainer',value:function updateContainer(){if(!this._$('['+this.dpfx+'-results]')){var b=this.childNodes(this.container,'pre'),c=b?b[0]:this._c('pre',this.pfx+'-code'),d=this.childNodes(c,'code')||this.childNodes(this.container,'code'),e=d?d[0]:this._c('code',this.pfx+'-results');e.setAttribute(this.dpfx+'-results','');var f=this.childNodes(e,'span')||this.childNodes(c,'span')||this.childNodes(this.container,'span');f&&f.forEach(function(g){return e.appendChild(g)}),c.appendChild(e),this.container.appendChild(c)}}},{key:'createGroup',value:function createGroup(b){var d=this,c=this._c('fieldset',this.pfx+'-group');c.setAttribute(this.dpfx+'-group',b.id),c.innerHTML=this.createStyles(b.id).outerHTML,c.innerHTML+=''+b.title+'',c.innerHTML+=b.options.map(function(e){var f=b.multiple?'checkbox':'radio';return''}).join(''),this.container.insertBefore(c,this.container.firstChild),this.initGroup(c,b.id)}},{key:'createStyles',value:function createStyles(b){var c=this._c('style');return c.setAttribute(this.dpfx+'-style',b),c.textContent='['+this.dpfx+'-results]>['+this.dpfx+'-'+b+'] {display: none}',c}},{key:'childNodes',value:function childNodes(b,c){var d=c.toUpperCase();if(!b.hasChildNodes)return!1;var e=[].concat(_toConsumableArray(b.childNodes)).filter(function(f){return f.nodeName===d});return!!e.length&&e}},{key:'_$',value:function _$(b){return document.querySelector(b)}},{key:'_$$',value:function _$$(b){return[].concat(_toConsumableArray(document.querySelectorAll(b)))}},{key:'_c',value:function _c(b,c){var d=document.createElement(b);return c&&(d.className=c),d}}]),a}(); From 57beef5d3677a7b7c836c630a8ae7a1d80dc8428 Mon Sep 17 00:00:00 2001 From: ines Date: Thu, 18 May 2017 13:51:31 +0200 Subject: [PATCH 2/6] Tidy up .gitignore --- .gitignore | 94 ++++++++++++++++++++++++------------------------------ 1 file changed, 42 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index 8716a8ef0..b165abf4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,50 +1,43 @@ -# Vim -*.swp -*.sw* -Profile.prof -tmp/ -.dev -.denv -.pypyenv -.eggs -*.tgz -.sass-cache -.python-version - -MANIFEST - +# spaCy +spacy/data/ corpora/ models/ keys/ -spacy/syntax/*.cpp -spacy/syntax/*.html -spacy/en/*.cpp -spacy/tokens/*.cpp -spacy/serialize/*.cpp -spacy/en/data/* -spacy/*.cpp -spacy/ner/*.cpp -spacy/orthography/*.cpp -ext/murmurhash.cpp -ext/sparsehash.cpp +# Website +website/www/ +website/_deploy.sh +website/package.json +website/announcement.jade +website/.gitignore -/spacy/data/ - -_build/ -.env/ -tmp/ +# Cython / C extensions cythonize.json - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] - -# C extensions +spacy/*.html +*.cpp *.so -# Distribution / packaging +# Vim / VSCode / editors +*.swp +*.sw* +Profile.prof +.vscode +.sass-cache + +# Python .Python +.python-version +__pycache__/ +*.py[cod] +.env/ +.~env/ +.venv +venv/ +.dev +.denv +.pypyenv + +# Distribution / packaging env/ bin/ build/ @@ -59,6 +52,12 @@ var/ *.egg-info/ .installed.cfg *.egg +.eggs +MANIFEST + +# Temporary files +*.~* +tmp/ # Installer logs pip-log.txt @@ -87,25 +86,16 @@ coverage.xml *.log *.pot -# Windows local helper files +# Windows *.bat +Thumbs.db +Desktop.ini # Mac OS X *.DS_Store -# Temporary files / Dropbox hack -*.~* - # Komodo project files *.komodoproject -# Website -website/_deploy.sh -website/package.json -website/announcement.jade -website/www/ -website/.gitignore - -# Python virtualenv -venv -venv/* +# Other +*.tgz From 33decd85b6a796290a0ccea55f25830bac891871 Mon Sep 17 00:00:00 2001 From: ines Date: Thu, 18 May 2017 14:12:31 +0200 Subject: [PATCH 3/6] Reorganise and explicitly state what's importable --- spacy/compat.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spacy/compat.py b/spacy/compat.py index 42c675b6e..35f6ecef3 100644 --- a/spacy/compat.py +++ b/spacy/compat.py @@ -16,6 +16,11 @@ try: except ImportError: import copyreg as copy_reg +pickle = pickle +copy_reg = copy_reg +CudaStream = CudaStream +cupy = cupy +fix_text = ftfy.fix_text is_python2 = six.PY2 is_python3 = six.PY3 @@ -23,8 +28,6 @@ is_windows = sys.platform.startswith('win') is_linux = sys.platform.startswith('linux') is_osx = sys.platform == 'darwin' -fix_text = ftfy.fix_text - if is_python2: bytes_ = str From abf0188b0a45624d97c839d3aedba8521b184315 Mon Sep 17 00:00:00 2001 From: ines Date: Thu, 18 May 2017 14:12:45 +0200 Subject: [PATCH 4/6] Move cupy and CudaStream to compat --- spacy/compat.py | 11 +++++++++++ spacy/util.py | 10 +--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/spacy/compat.py b/spacy/compat.py index 35f6ecef3..2a551a831 100644 --- a/spacy/compat.py +++ b/spacy/compat.py @@ -16,6 +16,17 @@ try: except ImportError: import copyreg as copy_reg +try: + from cupy.cuda.stream import Stream as CudaStream +except ImportError: + CudaStream = None + +try: + import cupy +except ImportError: + cupy = None + + pickle = pickle copy_reg = copy_reg CudaStream = CudaStream diff --git a/spacy/util.py b/spacy/util.py index 717e4f160..0fbe9f92d 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -10,20 +10,12 @@ import sys import textwrap from .symbols import ORTH -from .compat import path2str, basestring_, input_, unicode_ +from .compat import cupy, CudaStream, path2str, basestring_, input_, unicode_ LANGUAGES = {} _data_path = Path(__file__).parent / 'data' -try: - from cupy.cuda.stream import Stream as CudaStream -except ImportError: - CudaStream = None -try: - import cupy -except ImportError: - cupy = None def get_lang_class(lang): """Import and load a Language class. From 489d2fb4baf5946672602290b809a3508a1e9a21 Mon Sep 17 00:00:00 2001 From: ines Date: Thu, 18 May 2017 14:13:14 +0200 Subject: [PATCH 5/6] Add is_in_jupyter() helper for displaCy (see #1058) --- spacy/displacy/__init__.py | 5 +++-- spacy/util.py | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/spacy/displacy/__init__.py b/spacy/displacy/__init__.py index 45671612f..5b35b865d 100644 --- a/spacy/displacy/__init__.py +++ b/spacy/displacy/__init__.py @@ -3,13 +3,14 @@ from __future__ import unicode_literals from .render import DependencyRenderer, EntityRenderer from ..tokens import Doc -from ..util import prints +from ..util import prints, is_in_jupyter _html = {} +IS_JUPYTER = is_in_jupyter() -def render(docs, style='dep', page=False, minify=False, jupyter=False, options={}): +def render(docs, style='dep', page=False, minify=False, jupyter=IS_JUPYTER, options={}): """Render displaCy visualisation. docs (list or Doc): Document(s) to visualise. diff --git a/spacy/util.py b/spacy/util.py index 0fbe9f92d..ad40d4c87 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -142,6 +142,20 @@ def parse_package_meta(package_path, require=True): return None +def is_in_jupyter(): + """Check if user is in a Jupyter notebook. Mainly used for displaCy. + + RETURNS (bool): True if in Jupyter, False if not. + """ + try: + cfg = get_ipython().config + if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook': + return True + except NameError: + return False + return False + + def get_cuda_stream(require=False): # TODO: Error and tell to install chainer if not found # Requires GPU From 476b8209fe60bbff38b019f5de6a485c9a26a6ec Mon Sep 17 00:00:00 2001 From: ines Date: Thu, 18 May 2017 14:58:17 +0200 Subject: [PATCH 6/6] Update docs with new Jupyter auto-detection --- website/docs/api/displacy.jade | 6 +++--- website/docs/usage/visualizers.jade | 25 +++++++++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/website/docs/api/displacy.jade b/website/docs/api/displacy.jade index 92b1543fd..de5707722 100644 --- a/website/docs/api/displacy.jade +++ b/website/docs/api/displacy.jade @@ -101,9 +101,9 @@ p Render a dependency parse tree or named entity visualization. +cell #[code jupyter] +cell bool +cell - | Returns markup using #[+a("http://jupyter.org/") Jupyter]'s - | internal methods, ready to be rendered in a notebook. - +cell #[code False] + | Explicitly enable "#[+a("http://jupyter.org/") Jupyter] mode" to + | return markup ready to be rendered in a notebook. + +cell detected automatically +row +cell #[code options] diff --git a/website/docs/usage/visualizers.jade b/website/docs/usage/visualizers.jade index 0eff2e4d1..ea675e70c 100644 --- a/website/docs/usage/visualizers.jade +++ b/website/docs/usage/visualizers.jade @@ -11,8 +11,12 @@ p | process. Instead of printing a list of dependency labels or entity spans, | you can simply pass your #[code Doc] objects to #[code displacy] and view | the visualizations in your browser, or export them as HTML files or - | vector graphics. displaCy also comes with a #[+a("#jupyter") Jupyter hook] - | that returns the markup in a format ready to be rendered in a notebook. + | vector graphics. + +p + | If you're running a #[+a("https://jupyter.org") Jupyter] notebook, + | displaCy will detect this and return the markup in a format + | #[+a("#jupyter") ready to be rendered and exported]. +aside("What about the old visualizers?") | Our JavaScript-based visualizers #[+src(gh("displacy")) displacy.js] and @@ -219,10 +223,10 @@ p +h(2, "jupyter") Using displaCy in Jupyter notebooks p - | If you're working with a #[+a("https://jupyter.org") Jupyter] notebook, - | you can use displaCy's "Jupyter mode" to return markup that can be - | rendered in a cell straight away. When you export your notebook, the - | visualizations will be included as HTML. + | displaCy is able to detect whether you're within a + | #[+a("https://jupyter.org") Jupyter] notebook, and will return markup + | that can be rendered in a cell straight away. When you export your + | notebook, the visualizations will be included as HTML. +code("Jupyter Example"). # don't forget to install a model, e.g.: python -m spacy download en @@ -230,10 +234,15 @@ p from spacy import displacy doc = nlp(u'Rats are various medium-sized, long-tailed rodents.') - displacy.render(doc, style='dep', jupyter=True) + displacy.render(doc, style='dep') doc2 = nlp(LONG_NEWS_ARTICLE) - displacy.render(doc2, style='ent', jupyter=True) + displacy.render(doc2, style='ent') + ++aside("Enabling or disabling Jupyter mode") + | To explicitly enable or disable "Jupyter mode", you can use the + | #[code jupyter] keyword argument – e.g. to return raw HTML in a notebook, + | or to force Jupyter rendering if auto-detection fails. +image("/assets/img/docs/displacy_jupyter.jpg", 700, false, "Example of using the displaCy dependency and named entity visualizer in a Jupyter notebook")