B
    d                 @   s  d Z ddlmZ ddlmZ ddlZddlZddlmZ ddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlZddlZddlZddl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 m#Z$ ddl%m&Z& ddl'm(Z( ddl)m*Z* e*+ Z,dZ-dZ.dZ/dZ0G dd de1Z2dd Z3G dd dedZ4G dd dedZ5G dd de6Z7G d d! d!e7Z8d"d# Z9G d$d% d%ej:Z;G d&d' d'ej<e5Z=e9e=Z>dS )(a  Utilities for TensorBoard command line program.

This is a lightweight module for bringing up a TensorBoard HTTP server
or emulating the `tensorboard` shell command.

Those wishing to create custom builds of TensorBoard can use this module
by swapping out `tensorboard.main` with the custom definition that
modifies the set of plugins and static assets.

This module does not depend on first-party plugins or the default web
server assets. Those are defined in `tensorboard.default`.
    )ABCMeta)abstractmethodN)defaultdict)flags)argparse_flags)serving)manager)version)application)data_ingester)event_file_inspector)server_ingester)core_plugin)
tb_loggingZserveZ__tensorboard_subcommandz
NOTE: Using experimental fast data loading logic. To disable, pass
    "--load_fast=false" and report issues on GitHub. More details:
    https://github.com/tensorflow/tensorboard/issues/4784

zCould not start data server: %s.
    Try with --load_fast=false and report issues on GitHub. Details:
    https://github.com/tensorflow/tensorboard/issues/4784
c               @   sv   e Zd ZdZdddZdddZddd	Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd ZdS )TensorBoardaO  Class for running TensorBoard.

    Fields:
      plugin_loaders: Set from plugins passed to constructor.
      assets_zip_provider: Set by constructor.
      server_class: Set by constructor.
      flags: An argparse.Namespace set by the configure() method.
      cache_key: As `manager.cache_key`; set by the configure() method.
    Nc       
   
   C   s   |dkrddl m} | }|dkrjyddl m} W n, tk
r` } ztd|W dd}~X Y nX | }|dkrvt}|dkrg }dd |D | _|| _|| _	i | _
x<|D ]4}| }	|	| j
ks|	tkrtd|	 || j
|	< qW d| _dS )	a  Creates new instance.

        Args:
          plugins: A list of TensorBoard plugins to load, as TBPlugin classes or
            TBLoader instances or classes. If not specified, defaults to first-party
            plugins.
          assets_zip_provider: A function that provides a zip file containing
            assets to the application. If `None`, the default TensorBoard web
            assets will be used. (If building from source, your binary must
            explicitly depend on `//tensorboard:assets_lib` if you pass `None`.)
          server_class: An optional factory for a `TensorBoardServer` to use
            for serving the TensorBoard WSGI app. If provided, its callable
            signature should match that of `TensorBoardServer.__init__`.

        :type plugins:
          list[
            base_plugin.TBLoader | Type[base_plugin.TBLoader] |
            Type[base_plugin.TBPlugin]
          ]
        Nr   )default)assetszbNo `assets_zip_provider` given, but `tensorboard.assets` could not be imported to resolve defaultsc             S   s   g | ]}t |qS  )r
   Zmake_plugin_loader).0pr   r   E/var/www/html/venv/lib/python3.7/site-packages/tensorboard/program.py
<listcomp>   s    z(TensorBoard.__init__.<locals>.<listcomp>zDuplicate subcommand name: %r)tensorboardr   Zget_pluginsr   ImportErrorZget_default_assets_zip_provider$create_port_scanning_werkzeug_serverplugin_loadersassets_zip_providerserver_classsubcommandsname_SERVE_SUBCOMMAND_NAME
ValueErrorr   )
selfpluginsr   r   r   r   r   e
subcommandr   r   r   r   __init__`   s2    
zTensorBoard.__init__ c             K   s  t jddd}|jdt d}|jtdd}|jf tti t|dk sV|d d	r\|}n|}xH| j	
 D ]:\}}|j|| | d
}	|	jf t|i ||	 qlW x| jD ]}
|
| qW |r|d nd}||dd }t|tddkrt|tt tjt |dd |d| _|rpxFttj|D ]2}t||jrZtd|j t||j|j q:W x:|
 D ].\}}t||std| t||| qzW t|ttkrx| jD ]}
|
| qW || _|gS )a=  Configures TensorBoard behavior via flags.

        This method will populate the "flags" property with an argparse.Namespace
        representing flag values parsed from the provided argv list, overridden by
        explicit flags from remaining keyword arguments.

        Args:
          argv: Can be set to CLI args equivalent to sys.argv; the first arg is
            taken to be the name of the path being executed.
          kwargs: Additional arguments will override what was parsed from
            argv. They must be passed as Python data structures, e.g.
            `foo=1` rather than `foo="1"`.

        Returns:
          Either argv[:1] if argv was non-empty, or [''] otherwise, as a mechanism
          for absl.app.run() compatibility.

        Raises:
          ValueError: If flag values are invalid.
        r   zTensorBoard is a suite of web applications for inspecting and understanding your TensorFlow runs and graphs. https://github.com/tensorflow/tensorboard )progdescriptionz'TensorBoard subcommand (defaults to %r))helpz3start local TensorBoard server (default subcommand)      -)r+   r*   r   r(   N)Zworking_directory	argumentsZconfigure_kwargszConflicting Abseil flag: %szUnknown TensorBoard flag: %s) r   ArgumentParseradd_subparsersr    
add_parserset_defaults_SUBCOMMAND_FLAGlen
startswithr   itemsr+   r*   define_flagsr   
parse_argsgetattrsetattrr   	cache_keyosgetcwdset
absl_flagsFLAGSZget_key_flags_for_modulehasattrr   r!   value	fix_flagsr   )r"   argvkwargsZbase_parserZ
subparsersZserve_subparserZserve_parserr   r%   Z	subparserloaderZarg0r   flagkvr   r   r   	configure   sZ    



zTensorBoard.configurec             C   sL   |  tjd |   t| jt}|tkr2| j}n| j	| j
}|| jpJdS )a'  Blocking main function for TensorBoard.

        This method is called by `tensorboard.main.run_main`, which is the
        standard entrypoint for the tensorboard command line program. The
        configure() method must be called first.

        Args:
          ignored_argv: Do not pass. Required for Abseil compatibility.

        Returns:
          Process exit code, i.e. 0 if successful or non-zero on failure. In
          practice, an exception will most likely be raised instead of
          returning non-zero.

        :rtype: int
        SIGTERMr   )_install_signal_handlersignalrL   _fix_mime_typesr:   r   r4   r    _run_serve_subcommandr   run)r"   Zignored_argvsubcommand_namerunnerr   r   r   main   s    zTensorBoard.mainc          
   C   s   |j rttj dS |jrHtd tj	|j
}t|j||j dS y&|  }|  | | |  dS  tk
r } z,t|j tjd|j  tj  dS d }~X Y nX d S )Nr   z8Not bringing up TensorBoard, but inspecting event files.z
ERROR: %s
)Z
version_tbprintr	   VERSIONinspectloggerinfor=   path
expanduser
event_fileefilogdirtag_make_serverprint_serving_message_register_infoserve_foreverTensorBoardServerExceptionerrormsgsysstderrwriteflush)r"   r   r]   serverr$   r   r   r   rP     s(    


z!TensorBoard._run_serve_subcommandc             C   s.   |   }tj|jdd}d|_|  | S )a-  Python API for launching TensorBoard.

        This method is the same as main() except it launches TensorBoard in
        a separate permanent thread. The configure() method must be called
        first.

        Returns:
          The URL of the TensorBoard web server.

        :rtype: str
        r   )targetr   T)ra   	threadingThreadrd   daemonstartget_url)r"   rl   threadr   r   r   launch/  s    zTensorBoard.launchc          
   C   sj   t j| }tjtjtt		 |j
t | jj| jjp@| jj| jj| jd}ttj t| dS )zWrite a TensorBoardInfo file and arrange for its cleanup.

        Args:
          server: The result of `self._make_server()`.
        )r	   
start_timeportpidpath_prefixr_   dbr<   N)urllibparseurlparserr   r   ZTensorBoardInfor	   rW   inttimerv   r=   getpidr   rx   r_   logdir_specry   r<   atexitregisterZremove_info_fileZwrite_info_file)r"   rl   Z
server_urlrZ   r   r   r   rc   D  s    

zTensorBoard._register_infoc                s$   d  fdd}t  | dS )af  Set a signal handler to gracefully exit on the given signal.

        When this process receives the given signal, it will run `atexit`
        handlers and then exit with `0`.

        Args:
          signal_number: The numeric code for the signal to handle, like
            `signal.SIGTERM`.
          signal_name: The human-readable signal name.
        Nc                sF   t  t j tjd   t jt jfkr8 | | td d S )Nz"TensorBoard caught %s; exiting...
r   )rN   SIG_DFLrh   ri   rj   SIG_IGNexit)Zhandled_signal_numberframe)old_signal_handlersignal_namesignal_numberr   r   handleri  s    

z4TensorBoard._install_signal_handler.<locals>.handler)rN   )r"   r   r   r   r   )r   r   r   r   rM   X  s    z#TensorBoard._install_signal_handlerc             C   s(   t dd t dd t dd dS )aZ  Fix incorrect entries in the `mimetypes` registry.

        On Windows, the Python standard library's `mimetypes` reads in
        mappings from file extension to MIME type from the Windows
        registry. Other applications can and do write incorrect values
        to this registry, which causes `mimetypes.guess_type` to return
        incorrect values, which causes TensorBoard to fail to render on
        the frontend.

        This method hard-codes the correct mappings for certain MIME
        types that are known to be either used by TensorBoard or
        problematic in general.
        ztext/javascriptz.jsz
font/woff2z.woff2z	text/htmlz.htmlN)	mimetypesadd_type)r"   r   r   r   rO   x  s    zTensorBoard._fix_mime_typesc          	   C   s@   | j }t }tj||j|j|j|jt	|j
d}|  |S )z>Creates, starts, and returns a `SubprocessServerDataIngester`.)server_binaryr_   reload_intervalchannel_creds_typesamples_per_pluginextra_flags)r   r   Zget_server_binaryZSubprocessServerDataIngesterr_   r   grpc_creds_typer   shlexsplitZextra_data_server_flagsrq   )r"   r   r   ingesterr   r   r   _start_subprocess_data_ingester  s    z+TensorBoard._start_subprocess_data_ingesterc          
   C   sr  | j }|jr*tj|j|jd}|  |S |jdkry|  S  tjk
r~ } z"d| }t	j
| t	d W dd}~X Y nB tjk
r } z"t| }t	j
| t	d W dd}~X Y nX |jdkr\t|r\y"|  }t	j
t t	j
  |S  tjk
r* } ztd| W dd}~X Y n2 tjk
rZ } ztd| W dd}~X Y nX t|}|  |S )	z>Determines the right data ingester, starts it, and returns it.)r   truez*Option --load_fast=true not available: %s
r-   NautozNo data server: %sz2Data server error: %s; falling back to multiplexer)r   Zgrpc_data_providerr   ZExistingServerDataIngesterr   rq   Z	load_fastr   ZNoDataServerErrorrh   ri   rj   r   ZDataServerStartupError+_DATA_SERVER_STARTUP_ERROR_MESSAGE_TEMPLATE_should_use_data_server_DATA_SERVER_ADVISORY_MESSAGErk   rY   rZ   local_ingesterLocalDataIngester)r"   r   r   r$   rg   r   r   r   _make_data_ingester  s@    



zTensorBoard._make_data_ingesterc             C   s.   |   }|| _d}t|tjr$|j}|j|fS )z2Returns `(data_provider, deprecated_multiplexer)`.N)r   Z	_ingester
isinstancer   r   deprecated_multiplexerdata_provider)r"   r   r   r   r   r   _make_data_provider  s    zTensorBoard._make_data_providerc             C   s2   |   \}}t| j| j|| j|}| || jS )z@Constructs the TensorBoard WSGI app and instantiates the server.)r   r
   ZTensorBoardWSGIAppr   r   r   r   )r"   r   r   Zappr   r   r   ra     s    zTensorBoard._make_server)NNNN)r'   )r'   )__name__
__module____qualname____doc__r&   rK   rT   rP   rt   rc   rM   rO   r   r   r   ra   r   r   r   r   r   U   s    	   
7
`
 (r   c             C   sd   | j r| jstd dS | js$dS d| jkrH| jdsHtd dS | jdkr`td dS dS )NzNote: --logdir_spec is not supported with --load_fast behavior; falling back to slower Python-only load path. To use the data server, replace --logdir_spec with --logdir.Fz://zgs://zsNote: --load_fast behavior only supports local and GCS (gs://) paths; falling back to slower Python-only load path.Tz~Note: --detect_file_replacement=true is not supported with --load_fast behavior; falling back to slower Python-only load path.)r   r_   rY   rZ   r6   Zdetect_file_replacement)r   r   r   r   r     s    
r   c               @   sD   e Zd ZdZedd Zedd Zedd Zdd	 Zd
d Z	dS )TensorBoardSubcommandzDExperimental private API for defining subcommands to tensorboard(1).c             C   s   dS )zName of this subcommand, as specified on the command line.

        This must be unique across all subcommands.

        Returns:
          A string.
        Nr   )r"   r   r   r   r     s    	zTensorBoardSubcommand.namec             C   s   dS )ad  Configure an argument parser for this subcommand.

        Flags whose names start with two underscores (e.g., `__foo`) are
        reserved for use by the runtime and must not be defined by
        subcommands.

        Args:
          parser: An `argparse.ArgumentParser` scoped to this subcommand,
            which this function should mutate.
        Nr   )r"   parserr   r   r   r8     s    z"TensorBoardSubcommand.define_flagsc             C   s   dS )zExecute this subcommand with user-provided flags.

        Args:
          flags: An `argparse.Namespace` object with all defined flags.

        Returns:
          An `int` exit code, or `None` as an alias for `0`.
        Nr   )r"   r   r   r   r   rQ     s    
zTensorBoardSubcommand.runc             C   s   dS )z=Short, one-line help text to display on `tensorboard --help`.Nr   )r"   r   r   r   r+      s    zTensorBoardSubcommand.helpc             C   s   dS )z:Description to display on `tensorboard SUBCOMMAND --help`.Nr   )r"   r   r   r   r*   $  s    z!TensorBoardSubcommand.descriptionN)
r   r   r   r   r   r   r8   rQ   r+   r*   r   r   r   r   r     s   r   )	metaclassc               @   s<   e Zd ZdZedd Zedd Zedd Zdd	 Zd
S )TensorBoardServerz3Class for customizing TensorBoard WSGI app serving.c             C   s
   t  dS )zCreate a flag-configured HTTP server for TensorBoard's WSGI app.

        Args:
          wsgi_app: The TensorBoard WSGI application to create a server for.
          flags: argparse.Namespace instance of TensorBoard flags.
        N)NotImplementedError)r"   wsgi_appr   r   r   r   r&   ,  s    zTensorBoardServer.__init__c             C   s
   t  dS )z6Blocking call to start serving the TensorBoard server.N)r   )r"   r   r   r   rd   6  s    zTensorBoardServer.serve_foreverc             C   s
   t  dS )z7Returns a URL at which this server should be reachable.N)r   )r"   r   r   r   rr   ;  s    zTensorBoardServer.get_urlc             C   s(   t jdtj|  f  t j  dS )zxPrints a user-friendly message prior to server start.

        This will be called just before `serve_forever`.
        z,TensorBoard %s at %s (Press CTRL+C to quit)
N)rh   ri   rj   r	   rW   rr   rk   )r"   r   r   r   rb   @  s    z'TensorBoardServer.print_serving_messageN)	r   r   r   r   r   r&   rd   rr   rb   r   r   r   r   r   )  s
   
r   c               @   s   e Zd ZdZdd ZdS )re   zException raised by TensorBoardServer for user-friendly errors.

    Subclasses of TensorBoardServer can raise this exception in order to
    generate a clean error message for the user rather than a
    stacktrace.
    c             C   s
   || _ d S )N)rg   )r"   rg   r   r   r   r&   T  s    z#TensorBoardServerException.__init__N)r   r   r   r   r&   r   r   r   r   re   L  s   re   c               @   s   e Zd ZdZdS )TensorBoardPortInUseErrora  Error raised when attempting to bind to a port that is in use.

    This should be raised when it is expected that binding to another
    similar port would succeed. It is used as a signal to indicate that
    automatic port searching should continue rather than abort.
    N)r   r   r   r   r   r   r   r   r   X  s   r   c                s    fdd}|S )au  Create a server factory that performs port scanning.

    This function returns a callable whose signature matches the
    specification of `TensorBoardServer.__init__`, using `cls` as an
    underlying implementation. It passes through `flags` unchanged except
    in the case that `flags.port is None`, in which case it repeatedly
    instantiates the underlying server with new port suggestions.

    Args:
      cls: A valid implementation of `TensorBoardServer`. This class's
        initializer should raise a `TensorBoardPortInUseError` upon
        failing to bind to a port when it is expected that binding to
        another nearby port might succeed.

        The initializer for `cls` will only ever be invoked with `flags`
        such that `flags.port is not None`.

    Returns:
      A function that implements the `__init__` contract of
      `TensorBoardServer`.
    c          	      s   |j d k}|j d krtjn|j }|dkr8td|df |r@dnd}t|| d| }xTt||| D ]B}tjf t|}||_ y | |dS  t	k
r   |s Y qfX qfW td||f d S )Ni  z'TensorBoard cannot bind to port %d > %dd   r-   i   )r   r   zATensorBoard could not bind to any port around %s (tried %d times))
rv   r   ZDEFAULT_PORTre   minrangeargparse	Namespacevarsr   )r   r   Zshould_scanZ	base_portZmax_attemptsrv   Zsubflags)clsr   r   initz  s$    
z with_port_scanning.<locals>.initr   )r   r   r   )r   r   with_port_scanningc  s    r   c               @   s   e Zd ZdZdZdS )_WSGIRequestHandlerz<Custom subclass of Werkzeug request handler to use HTTP/1.1.zHTTP/1.1N)r   r   r   r   Zprotocol_versionr   r   r   r   r     s   r   c                   s\   e Zd ZdZdZ fddZdd Z fddZd	d
 Zdd Z	 fddZ
dd Z  ZS )WerkzeugServerzBImplementation of TensorBoardServer using the Werkzeug dev server.Tc          
      s8  || _ |j}|j}|j| _| jr,| |}n|d kr8d}|| _d | _|   yt	t
| |||t W n tjk
r2 } zttdr|jtjkrtd| nttdr|jtjkr|dkrtdntd| nJttdr|jtjkrtd	| n&ttd
r |jtjkr td|  W d d }~X Y nX d S )N	localhostEACCESz7TensorBoard must be run as superuser to bind to port %d
EADDRINUSEr   z(TensorBoard unable to find any open portz<TensorBoard could not bind to port %d, it was already in useEADDRNOTAVAILz4TensorBoard could not bind to unavailable address %sEAFNOSUPPORTz;Tensorboard could not bind to unsupported address family %s)_flagshostrv   bind_all_auto_wildcard_get_wildcard_address_host_url_fix_werkzeug_loggingsuperr   r&   r   socketrf   rB   errnor   re   r   r   r   r   )r"   r   r   r   rv   r$   )	__class__r   r   r&     sH    




zWerkzeugServer.__init__c       	   
   C   s   t jr
dnd}tt dry t d|t jt jt jt j}W n6 t jk
rn } zt	
d|t| |S d}~X Y nX tt}x(|D ] \}}}}}|| |d  q~W tt dr|t j r|t j d S tt dr|t j r|t j d S t	
d	| |S )
a  Returns a wildcard address for the port in question.

        This will attempt to follow the best practice of calling
        getaddrinfo() with a null host and AI_PASSIVE to request a
        server-side socket wildcard address. If that succeeds, this
        returns the first IPv6 address found, or if none, then returns
        the first IPv4 address. If that fails, then this returns the
        hardcoded address "::" if socket.has_ipv6 is True, else
        "0.0.0.0".
        z::z0.0.0.0
AI_PASSIVENz7Failed to auto-detect wildcard address, assuming %s: %sr   AF_INET6AF_INETz3Failed to auto-detect wildcard address, assuming %s)r   has_ipv6rB   getaddrinfo	AF_UNSPECSOCK_STREAMIPPROTO_TCPr   gaierrorrY   warningstrr   listappendr   r   )	r"   rv   Zfallback_addressZ	addrinfosr$   Zaddrs_by_familyfamily_sockaddrr   r   r   r     s6    

z$WerkzeugServer._get_wildcard_addressc          
      s   | j jrDy
tj W n tk
r.   tdY nX | jtjtjd ttdoZ| jj	tj
k}ttdonttd}| jr|r|ry| jtjtjd W nJ tjk
r } z*ttdr|jtjkrtdt| W d	d	}~X Y nX tt|   d	S )
z-Override to set custom options on the socket.zATensorBoard --reuse_port option is not supported on this platformr-   r   IPPROTO_IPV6IPV6_V6ONLYr   r   z(Failed to dual-bind to IPv4 wildcard: %sN)r   
reuse_portr   SO_REUSEPORTAttributeErrorre   
setsockopt
SOL_SOCKETrB   r   r   r   r   r   rf   r   r   rY   r   r   r   r   server_bind)r"   Zsocket_is_v6Zhas_v6only_optionr$   )r   r   r   r     s*    


zWerkzeugServer.server_bindc             C   sN   ~t  }|d }t|tr<|jtjkr<tdt|  ntj	d|d dS )z*Override to get rid of noisy EPIPE errors.r-   z"EPIPE caused by %s in HTTP servingzHTTP serving error)exc_infoN)
rh   r   r   IOErrorr   EPIPErY   r   r   rf   )r"   requestclient_addressr   r$   r   r   r   handle_error7  s    zWerkzeugServer.handle_errorc          
   C   s   | j s| jrXt }ytj|| jfdd W q| tjk
rT } zd}W d d }~X Y q|X n$| j}d|krx|dsxd| n|}d|| j| j	j
df | _ | j S )	Nr-   )timeoutr   :[z[%s]zhttp://%s:%d%s//)r   r   r   getfqdncreate_connectionZserver_portrf   r   r6   r   rx   rstrip)r"   Zdisplay_hostr$   r   r   r   r   rr   F  s     zWerkzeugServer.get_urlc                s<   | j jd kr*| j js*tjd tj  tt| 	  d S )Nz[Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
)
r   r   r   rh   ri   rj   rk   r   r   rb   )r"   )r   r   r   rb   `  s
    
z$WerkzeugServer.print_serving_messagec             C   s"   |  dd tdtj dS )a  Fix werkzeug logging setup so it inherits TensorBoard's log level.

        This addresses a change in werkzeug 0.15.0+ [1] that causes it set its own
        log level to INFO regardless of the root logger configuration. We instead
        want werkzeug to inherit TensorBoard's root logger log level (set via absl
        to WARNING by default).

        [1]: https://github.com/pallets/werkzeug/commit/4cf77d25858ff46ac7e9d64ade054bf05b41ce12
        debugz7Fixing werkzeug logger to inherit TensorBoard log levelwerkzeugN)loglogging	getLoggersetLevelNOTSET)r"   r   r   r   r   i  s    z$WerkzeugServer._fix_werkzeug_logging)r   r   r   r   daemon_threadsr&   r   r   r   rr   rb   r   __classcell__r   r   )r   r   r     s   7,(	r   )?r   abcr   r   r   r   collectionsr   r   r   r   r=   r   rN   r   rh   rn   r~   urllib.parserz   Zabslr   r@   Z
absl.flagsr   r   r   r   r   r	   Ztensorboard.backendr
   Z$tensorboard.backend.event_processingr   r   r   r^   Ztensorboard.datar   Ztensorboard.plugins.corer   Ztensorboard.utilr   Z
get_loggerrY   r    r4   r   r   objectr   r   r   r   	Exceptionre   r   r   ZWSGIRequestHandlerr   ZThreadedWSGIServerr   r   r   r   r   r   <module>   s\   	   1#8 X