B
    @\{:                 @   s  d Z ddlmZmZmZmZ ddlZeeZ	ddl
Z
ddlmZ ddlmZmZmZ ddlZddlmZ ddlmZ ddlmZmZ dd	lmZmZ dd
lmZ ddlmZm Z m!Z! ddl"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m,Z, ddl-m.Z. ddl/m0Z0 ddl1m2Z2 e,3 Z3dZ4G dd deZ5G dd deZ6G dd deZ7dd Z8d d! Z9d"d# Z:d$d% Z;d&d' Z<d(d) Z=d:d+d,Z>d-d. Z?e3dkre+d/d0Z*nLe3d1kre+d2d3d4Z*n4e3@d5re+d2d6e3Ad7d  d4Z*ne+d/e3d8Z*eBd9ejCZDdS );am   Include Bokeh plots in Sphinx HTML documentation.

For other output types, the placeholder text ``[graph]`` will
be generated.

The ``bokeh-plot`` directive can be used by either supplying:

**A path to a source file** as the argument to the directive::

    .. bokeh-plot:: path/to/plot.py

.. note::
    .py scripts are not scanned automatically! In order to include
    certain directories into .py scanning process use following directive
    in sphinx conf.py file: bokeh_plot_pyfile_include_dirs = ["dir1","dir2"]

**Inline code** as the content of the directive::

 .. bokeh-plot::

     from bokeh.plotting import figure, output_file, show

     output_file("example.html")

     x = [1, 2, 3, 4, 5]
     y = [6, 7, 6, 4, 5]

     p = figure(title="example", plot_width=300, plot_height=300)
     p.line(x, y, line_width=2)
     p.circle(x, y, size=10, fill_color="white")

     show(p)

This directive also works in conjunction with Sphinx autodoc, when
used in docstrings.

The ``bokeh-plot`` directive accepts the following options:

source-position : enum('above', 'below', 'none')
    Where to locate the the block of formatted source
    code (if anywhere).

linenos : flag
    Whether to display line numbers along with the source.

Examples
--------

The inline example code above produces the following output:

.. bokeh-plot::

    from bokeh.plotting import figure, output_file, show

    output_file("example.html")

    x = [1, 2, 3, 4, 5]
    y = [6, 7, 6, 4, 5]

    p = figure(title="example", plot_width=300, plot_height=300)
    p.line(x, y, line_width=2)
    p.circle(x, y, size=10, fill_color="white")

    show(p)

    )absolute_importdivisionprint_functionunicode_literalsN)getenv)basenamedirnamejoin)uuid4)nodes)	DirectiveParser)choiceflag)SphinxError)copyfile	ensuredirstatus_iterator)set_source_info   )Document)autoload_static)Model)	Resources)settings)decode_utf8   )ExampleHandler)	PLOT_PAGE)	PlotScriptErrorPlotScriptParserBokehPlotDirectiveenv_before_read_docsbuilder_initedhtml_page_contextbuild_finishedenv_purge_docsetupc               @   s   e Zd ZdZdZdS )r   z Error during script parsing. zPlotScript errorN)__name__
__module____qualname____doc__category r-   r-   9lib/python3.7/site-packages/bokeh/sphinxext/bokeh_plot.pyr      s   r   c               @   s   e Zd ZdZdZdd ZdS )r    a
   This Parser recognizes .py files in the Sphinx source tree,
    assuming that they contain bokeh examples

    Note: it is important that the .py files are parsed first. This is
    accomplished by reordering the doc names in the env_before_read_docs callback

    )pythonc             C   s   t d|}|jj}||j}t|}t|}|dk	rd|	d}|j
d j}d||d }dt j }	t||||	|jj\}
}}}|
|||f|j|j< tj|t|||
d}d|d< t| || dS )	z; Parse ``source``, write results to ``document``.

         N
r   zbokeh-plot-%s.js)sourcefilename	docstringscriptTbokeh_plot_include_bokehjs)CODINGsubr   envdoc2pathdocnameastparseZget_docstringsplitZbodylinenor	   r
   hex_process_scriptconfigbokeh_plot_use_relative_pathsbokeh_plot_filesr   Zrenderr   r   )selfr2   documentr9   r3   mr4   linesr?   js_namer5   jsjs_pathZrstr-   r-   r.   r=      s$    


zPlotScriptParser.parseN)r(   r)   r*   r+   Z	supportedr=   r-   r-   r-   r.   r       s   r    c               @   s.   e Zd ZdZdZdd dd dZdd Zd	S )
r!   Tr   c             C   s
   t | dS )N)belowaboveZnone)r   )xr-   r-   r.   <lambda>   s    zBokehPlotDirective.<lambda>c             C   s   t | d krdS dS )NTF)r   )rN   r-   r-   r.   rO      s    )zsource-positionlinenosc             C   sp  | j jjj}|j}| jr&| jr&td| jr|d|j	 d
| j}|j	dd}d|t jf }t
|j|}t|||||jj\}}}	}|jjr|dt|j	d }|||	|f|j|< n
| jd	 d d
 }
|
|jkr(|d|j	| jd	  |j|
 \}}}	}|jjr|dt|j	d }n|d|j	| jd	  t| jd	  }t|}|j	dd}d|t jf }t|| jd	 |||jj\}}}	}|jjr|dt|j	d }|||	|f|j|< d|j	t|	f }tjdd|gd}|g}| jdd}tj||d|g d}t| | | jdd}|dkrB||g7 }|tjd|ddg7 }|dkrl||g7 }|S )Nz7bokeh-plot:: directive can't have both args and contentz*[bokeh-plot] handling inline example in %rr1   /-zbokeh-plot-%s-inline-%s.jsz
$REL_PATH$scriptsr   z0[bokeh-plot] handling internal example in %r: %sz0[bokeh-plot] handling external example in %r: %szbokeh-plot-%s-external-%s.jsz%s.%sr0   )ZidsrP   Fr/   )ZlanguagerP   classeszsource-positionrL   rM   html)format)staterF   r   r9   appZ	argumentsZcontentr   debugr;   r	   replacer
   r@   bokeh_plot_auxdirrA   rB   rC   _get_file_depth_stringrD   openreadr   r   r   targetZoptionsgetZliteral_blockr   raw)rE   r9   rY   r2   r;   rI   pathr5   rJ   rK   Zexample_pathZ	target_idr`   resultrP   codeZsource_positionr-   r-   r.   run   sT    
"


 

 
zBokehPlotDirective.runN)r(   r)   r*   Zhas_contentZoptional_argumentsZoption_specrf   r-   r-   r-   r.   r!      s
   r!   c                s^   |j  fddd xD fdd|D D ].}|t jjjs( j| || q(W d S )Nc                s     | drdS dS )Nz.pyr   r   )r:   endswith)rN   )r9   r-   r.   rO     s    z&env_before_read_docs.<locals>.<lambda>)keyc                s    g | ]}  |d r|qS )z.py)r:   rg   ).0rN   )r9   r-   r.   
<listcomp>  s    z(env_before_read_docs.<locals>.<listcomp>)sort
startswithtuplerY   rB   bokeh_plot_pyfile_include_dirsZ
found_docsremove)rY   r9   Zdocnamesnamer-   )r9   r.   r"   	  s
    r"   c             C   s6   t | jjd| j_t| jj t| jds2i | j_d S )NZ
bokeh_plotrD   )r	   r9   Z
doctreedirr\   r   hasattrrD   )rY   r-   r-   r.   r#     s    r#   c             C   s&   |r"| dr"tj|d< tj|d< dS )z/ Add BokehJS to pages that contain plots.

    r6   Zbokeh_css_filesZbokeh_js_filesN)ra   	resourcesZ	css_filesZjs_files)rY   ZpagenameZtemplatenamecontextZdoctreer-   r-   r.   r$     s    
r$   c             C   s   t  }x&| jj D ]\}}}}|| qW tt|ddt|dd d}xn|D ]f}t| j	j
dt|}	tt|	 yt||	 W qR tk
r }
 ztd||
f W d d }
~
X Y qRX qRW d S )Nzcopying bokeh-plot files... Zbrownc             S   s   t | S )N)r   )rN   r-   r-   r.   rO   +  s    z build_finished.<locals>.<lambda>)Zstringify_funcrS   z%cannot copy local file %r, reason: %s)setr9   rD   valuesaddr   sortedlenr	   ZbuilderZoutdirr   r   r   r   OSErrorr   )rY   Z	exceptionfilesr5   rJ   rK   r2   Z
files_iterfiler`   er-   r-   r.   r%   !  s    
r%   c             C   s   ||j kr|j |= dS )z/ Remove local files for a given document.

    N)rD   )rY   r9   r;   r-   r-   r.   r&   5  s    
r&   c             C   s   |  dg d |  ddd |  ddd | dt | dt | d	t | d
t | dt | dt	 | dt
 dS )zG sphinx config variable to scan .py files in provided directories only rn   rV   rC   Fbokeh_missing_google_api_key_okTz.pyz
bokeh-plotzenv-before-read-docszbuilder-initedzhtml-page-contextzbuild-finishedzenv-purge-docN)Zadd_config_valueZadd_source_parserr    Zadd_directiver!   Zconnectr"   r#   r$   r%   r&   )rY   r-   r-   r.   r'   <  s    r'   Fc          	   C   s   t d| } t  d| krPtd}|d krB|jjr:d}ntd| d|}n| }t	||d}t
 }|| |jrt|jd }	|rtd|}	n
td|}	t|j|}
t|jd t|	\}}t|
d	}|| W d Q R X |||
| fS )
Nr0   GOOGLE_API_KEYZMISSING_API_KEYzThe GOOGLE_API_KEY environment variable is not set. Set GOOGLE_API_KEY to a valid API key, or set bokeh_missing_google_api_key_ok=True in conf.py to build anyway (with broken GMaps))r2   r3   z
$REL_PATH$z/scriptsr   w)r7   r8   r   Z_clear_extensionsr   rB   r}   r   r[   r   r   Zmodify_documenterrorr   Zerror_detailr	   r\   r   rootsrr   r^   write)r2   r3   r9   rI   Zuse_relative_pathsr~   Z
run_sourcecdZscript_pathrK   rJ   r5   fr-   r-   r.   rA   P  s0    


rA   c             C   s0   d}|  d}|dkrd}nddg| }|S )z5Get relative path string of file containing directiver0   rQ   Nz../)countr	   )r;   Zpre_pathZdepthr-   r-   r.   r]   y  s    
r]   Zcdn)modeZlocalZserverz/en/latest/)r   Zroot_urlztest:z/en/%s/:)r   versionz^# -\*- coding: (.*) -\*-$)F)Er+   Z
__future__r   r   r   r   ZloggingZ	getLoggerr(   logr<   osr   os.pathr   r   r	   reZuuidr
   Zdocutilsr   Zdocutils.parsers.rstr   r   Zdocutils.parsers.rst.directivesr   r   Zsphinx.errorsr   Zsphinx.utilr   r   r   Zsphinx.util.nodesr   rF   r   Zembedr   Zmodelr   rr   r   r   Zutil.stringr   Zexample_handlerr   Z	templatesr   Zdocs_cdn__all__r   r    r!   r"   r#   r$   r%   r&   r'   rA   r]   rl   r>   compileMr7   r-   r-   r-   r.   <module>H   sV   
.P	
)

