U
    Vc                     @   s~   d Z ddlmZmZ ddlmZ G dd deZdd ZG d	d
 d
eZ	dd Z
dddZe	g Zdd Zdd Zdd ZdS )z*Helper classes for tensor shape inference.   )compatdtypes    )tensor_shape_pb2c                   @   s   e Zd Z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e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&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Z d:S );	Dimensionz7Represents the value of one dimension in a TensorShape.c                 C   sr   |dkrd| _ n^t|tjr*td| nDt|| _ t|tjsV| j |krVtd| | j dk rntd| j  dS )z-Creates a new Dimension with the given value.NzCannot convert %s to DimensionzAmbiguous dimension: %sr   zDimension %d must be >= 0)	_value
isinstancer   ZDType	TypeErrorintr   bytes_or_text_types
ValueErrorselfvalue r   S/tmp/pip-unpacked-wheel-g8kmtpbc/tensorboard/compat/tensorflow_stub/tensor_shape.py__init__   s    


zDimension.__init__c                 C   s   dt | j S )NzDimension(%s))reprr   r   r   r   r   __repr__)   s    zDimension.__repr__c                 C   s   | j }|d krdS t|S )N?)r   strr   r   r   r   __str__,   s    zDimension.__str__c              	   C   sN   zt |}W n ttfk
r(   t Y S X | jdks>|jdkrBdS | j|jkS )zKReturns true if `other` has the same known value as this
        Dimension.Nas_dimensionr	   r   NotImplementedr   r   r   otherr   r   r   __eq__0   s    
zDimension.__eq__c              	   C   sN   zt |}W n ttfk
r(   t Y S X | jdks>|jdkrBdS | j|jkS )z@Returns true if `other` has a different known value from `self`.Nr   r   r   r   r   __ne__;   s    
zDimension.__ne__c                 C   s   | j S Nr   r   r   r   r   __int__E   s    zDimension.__int__c                 C   s   | j S r    r!   r   r   r   r   __long__J   s    zDimension.__long__c                 C   s   | j S r    r!   r   r   r   r   	__index__M   s    zDimension.__index__c                 C   s   | j S )z6The value of this dimension, or None if it is unknown.r!   r   r   r   r   r   Q   s    zDimension.valuec                 C   s(   t |}| jdkp&|jdkp&| j|jkS )aY  Returns true if `other` is convertible with this Dimension.

        Two known Dimensions are convertible if they have the same value.
        An unknown Dimension is convertible with all other Dimensions.

        Args:
          other: Another Dimension.

        Returns:
          True if this Dimension and `other` are convertible.
        Nr   r   r   r   r   r   r   is_convertible_withV   s    

zDimension.is_convertible_withc                 C   s   |  |std| |f dS )a  Raises an exception if `other` is not convertible with this
        Dimension.

        Args:
          other: Another Dimension.

        Raises:
          ValueError: If `self` and `other` are not convertible (see
            is_convertible_with).
        z(Dimensions %s and %s are not convertibleNr&   r   r   r   r   r   assert_is_convertible_withi   s    

z$Dimension.assert_is_convertible_withc                 C   s4   t |}| | | jdkr&t|jS t| jS dS )aK  Returns a Dimension that combines the information in `self` and
        `other`.

        Dimensions are combined as follows:

        ```python
        tf.Dimension(n)   .merge_with(tf.Dimension(n))    == tf.Dimension(n)
        tf.Dimension(n)   .merge_with(tf.Dimension(None)) == tf.Dimension(n)
        tf.Dimension(None).merge_with(tf.Dimension(n))    == tf.Dimension(n)
        tf.Dimension(None).merge_with(tf.Dimension(None)) == tf.Dimension(None)
        tf.Dimension(n)   .merge_with(tf.Dimension(m))  # raises ValueError for n != m
        ```

        Args:
          other: Another Dimension.

        Returns:
          A Dimension containing the combined information of `self` and
          `other`.

        Raises:
          ValueError: If `self` and `other` are not convertible (see
            is_convertible_with).
        N)r   r(   r   r   r   r   r   r   r   
merge_withy   s
    


zDimension.merge_withc                 C   s8   t |}| jdks|jdkr$tdS t| j|j S dS )aB  Returns the sum of `self` and `other`.

        Dimensions are summed as follows:

        ```python
        tf.Dimension(m)    + tf.Dimension(n)    == tf.Dimension(m + n)
        tf.Dimension(m)    + tf.Dimension(None) == tf.Dimension(None)
        tf.Dimension(None) + tf.Dimension(n)    == tf.Dimension(None)
        tf.Dimension(None) + tf.Dimension(None) == tf.Dimension(None)
        ```

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is the sum of `self` and `other`.
        Nr   r   r   r   r   r   r   r   __add__   s    zDimension.__add__c                 C   s   | | S )zReturns the sum of `other` and `self`.

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is the sum of `self` and `other`.
        r   r   r   r   r   __radd__   s    	zDimension.__radd__c                 C   s8   t |}| jdks|jdkr$tdS t| j|j S dS )aX  Returns the subtraction of `other` from `self`.

        Dimensions are subtracted as follows:

        ```python
        tf.Dimension(m)    - tf.Dimension(n)    == tf.Dimension(m - n)
        tf.Dimension(m)    - tf.Dimension(None) == tf.Dimension(None)
        tf.Dimension(None) - tf.Dimension(n)    == tf.Dimension(None)
        tf.Dimension(None) - tf.Dimension(None) == tf.Dimension(None)
        ```

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is the subtraction of `other` from `self`.
        Nr*   r   r   r   r   __sub__   s    zDimension.__sub__c                 C   s8   t |}| jdks|jdkr$tdS t|j| j S dS )zReturns the subtraction of `self` from `other`.

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is the subtraction of `self` from `other`.
        Nr*   r   r   r   r   __rsub__   s    	zDimension.__rsub__c              	   C   sZ   zt |}W n ttfk
r(   t Y S X | jdks>|jdkrFtdS t| j|j S dS )aJ  Returns the product of `self` and `other`.

        Dimensions are summed as follows:

        ```python
        tf.Dimension(m)    * tf.Dimension(n)    == tf.Dimension(m * n)
        tf.Dimension(m)    * tf.Dimension(None) == tf.Dimension(None)
        tf.Dimension(None) * tf.Dimension(n)    == tf.Dimension(None)
        tf.Dimension(None) * tf.Dimension(None) == tf.Dimension(None)
        ```

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is the product of `self` and `other`.
        Nr   r	   r   r   r   r   r   r   r   r   r   __mul__   s    
zDimension.__mul__c                 C   s   | | S )zReturns the product of `self` and `other`.

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is the product of `self` and `other`.
        r   r   r   r   r   __rmul__   s    	zDimension.__rmul__c              	   C   sZ   zt |}W n ttfk
r(   t Y S X | jdks>|jdkrFtdS t| j|j S dS )ai  Returns the quotient of `self` and `other` rounded down.

        Dimensions are divided as follows:

        ```python
        tf.Dimension(m)    // tf.Dimension(n)    == tf.Dimension(m // n)
        tf.Dimension(m)    // tf.Dimension(None) == tf.Dimension(None)
        tf.Dimension(None) // tf.Dimension(n)    == tf.Dimension(None)
        tf.Dimension(None) // tf.Dimension(None) == tf.Dimension(None)
        ```

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A `Dimension` whose value is the integer quotient of `self` and `other`.
        Nr/   r   r   r   r   __floordiv__
  s    
zDimension.__floordiv__c                 C   s8   t |}| jdks|jdkr$tdS t|j| j S dS )a   Returns the quotient of `other` and `self` rounded down.

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A `Dimension` whose value is the integer quotient of `self` and `other`.
        Nr*   r   r   r   r   __rfloordiv__%  s    	zDimension.__rfloordiv__c                 C   s   | | S )a  DEPRECATED: Use `__floordiv__` via `x // y` instead.

        This function exists only for backwards convertibility purposes; new code
        should use `__floordiv__` via the syntax `x // y`.  Using `x // y`
        communicates clearly that the result rounds down, and is forward convertible
        to Python 3.

        Args:
          other: Another `Dimension`.

        Returns:
          A `Dimension` whose value is the integer quotient of `self` and `other`.
        r   r   r   r   r   __div__4  s    zDimension.__div__c              	   C   sZ   zt |}W n ttfk
r(   t Y S X | jdks>|jdkrFtdS t| j|j S dS )a:  Returns `self` modulo `other`.

        Dimension moduli are computed as follows:

        ```python
        tf.Dimension(m)    % tf.Dimension(n)    == tf.Dimension(m % n)
        tf.Dimension(m)    % tf.Dimension(None) == tf.Dimension(None)
        tf.Dimension(None) % tf.Dimension(n)    == tf.Dimension(None)
        tf.Dimension(None) % tf.Dimension(None) == tf.Dimension(None)
        ```

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is `self` modulo `other`.
        Nr/   r   r   r   r   __mod__D  s    
zDimension.__mod__c              	   C   s2   zt |}W n ttfk
r(   t Y S X ||  S )zReturns `other` modulo `self`.

        Args:
          other: Another Dimension, or a value accepted by `as_dimension`.

        Returns:
          A Dimension whose value is `other` modulo `self`.
        )r   r	   r   r   r   r   r   r   __rmod___  s
    	
zDimension.__rmod__c                 C   s0   t |}| jdks|jdkr dS | j|jk S dS )a  Returns True if `self` is known to be less than `other`.

        Dimensions are compared as follows:

        ```python
        (tf.Dimension(m)    < tf.Dimension(n))    == (m < n)
        (tf.Dimension(m)    < tf.Dimension(None)) == None
        (tf.Dimension(None) < tf.Dimension(n))    == None
        (tf.Dimension(None) < tf.Dimension(None)) == None
        ```

        Args:
          other: Another Dimension.

        Returns:
          The value of `self.value < other.value` if both are known, otherwise
          None.
        Nr%   r   r   r   r   __lt__n  s    zDimension.__lt__c                 C   s0   t |}| jdks|jdkr dS | j|jkS dS )a.  Returns True if `self` is known to be less than or equal to `other`.

        Dimensions are compared as follows:

        ```python
        (tf.Dimension(m)    <= tf.Dimension(n))    == (m <= n)
        (tf.Dimension(m)    <= tf.Dimension(None)) == None
        (tf.Dimension(None) <= tf.Dimension(n))    == None
        (tf.Dimension(None) <= tf.Dimension(None)) == None
        ```

        Args:
          other: Another Dimension.

        Returns:
          The value of `self.value <= other.value` if both are known, otherwise
          None.
        Nr%   r   r   r   r   __le__  s    zDimension.__le__c                 C   s0   t |}| jdks|jdkr dS | j|jkS dS )a  Returns True if `self` is known to be greater than `other`.

        Dimensions are compared as follows:

        ```python
        (tf.Dimension(m)    > tf.Dimension(n))    == (m > n)
        (tf.Dimension(m)    > tf.Dimension(None)) == None
        (tf.Dimension(None) > tf.Dimension(n))    == None
        (tf.Dimension(None) > tf.Dimension(None)) == None
        ```

        Args:
          other: Another Dimension.

        Returns:
          The value of `self.value > other.value` if both are known, otherwise
          None.
        Nr%   r   r   r   r   __gt__  s    zDimension.__gt__c                 C   s0   t |}| jdks|jdkr dS | j|jkS dS )a9  Returns True if `self` is known to be greater than or equal to
        `other`.

        Dimensions are compared as follows:

        ```python
        (tf.Dimension(m)    >= tf.Dimension(n))    == (m >= n)
        (tf.Dimension(m)    >= tf.Dimension(None)) == None
        (tf.Dimension(None) >= tf.Dimension(n))    == None
        (tf.Dimension(None) >= tf.Dimension(None)) == None
        ```

        Args:
          other: Another Dimension.

        Returns:
          The value of `self.value >= other.value` if both are known, otherwise
          None.
        Nr%   r   r   r   r   __ge__  s    zDimension.__ge__c                 C   s   t | jffS r    )r   r   r   r   r   r   
__reduce__  s    zDimension.__reduce__N)!__name__
__module____qualname____doc__r   r   r   r   r   r"   r#   r$   propertyr   r&   r(   r)   r+   r,   r-   r.   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r   r   r   r   r      s<   

 r   c                 C   s   t | tr| S t| S dS )a_  Converts the given value to a Dimension.

    A Dimension input will be returned unmodified.
    An input of `None` will be converted to an unknown Dimension.
    An integer input will be converted to a Dimension with that value.

    Args:
      value: The value to be converted.

    Returns:
      A Dimension corresponding to the given value.
    N)r   r   r   r   r   r   r     s    
r   c                   @   s  e Zd ZdZdd Zdd Zdd Zedd	 Zej	d
d	 Zedd Z
dd Zdd Ze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#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 Z d7d8 Z!d9S ):TensorShapea  Represents the shape of a `Tensor`.

    A `TensorShape` represents a possibly-partial shape specification for a
    `Tensor`. It may be one of the following:

    * *Fully-known shape:* has a known number of dimensions and a known size
      for each dimension. e.g. `TensorShape([16, 256])`
    * *Partially-known shape:* has a known number of dimensions, and an unknown
      size for one or more dimension. e.g. `TensorShape([None, 256])`
    * *Unknown shape:* has an unknown number of dimensions, and an unknown
      size in all dimensions. e.g. `TensorShape(None)`

    If a tensor is produced by an operation of type `"Foo"`, its shape
    may be inferred if there is a registered shape function for
    `"Foo"`. See @{$adding_an_op#shape-functions-in-c$`Shape functions in C++`}
    for details of shape functions and how to register them. Alternatively,
    the shape may be set explicitly using @{tf.Tensor.set_shape}.
    c                 C   s   |dkrd| _ nt|tjr*td| nt|tjrX|jrDd| _ qdd |jD | _ nRt|t	rl|j
| _ n>zt|}W n  tk
r   t|g| _ Y nX dd |D | _ d| _dS )a;  Creates a new TensorShape with the given dimensions.

        Args:
          dims: A list of Dimensions, or None if the shape is unspecified.
            DEPRECATED: A single integer is treated as a singleton list.

        Raises:
          TypeError: If dims cannot be converted to a list of dimensions.
        NzRA string has ambiguous TensorShape, please wrap in a list or convert to an int: %sc                 S   s$   g | ]}t |jd kr|jndqS )N)r   size.0dimr   r   r   
<listcomp>  s   z(TensorShape.__init__.<locals>.<listcomp>c                 S   s   g | ]}t |qS r   )r   rF   dr   r   r   rH   $  s     )_dimsr   r   r   r	   r   TensorShapeProtounknown_rankrG   rB   dimsiterr   _ndims)r   rN   Z	dims_iterr   r   r   r     s,    


zTensorShape.__init__c                 C   s
   d| j  S )NzTensorShape(%r)rK   r   r   r   r   r   '  s    zTensorShape.__repr__c                 C   sD   | j d krdS | j dkr&d| jd  S dddd | jD  S d S )	Nz	<unknown>r   z(%s,)r   z(%s)z, c                 s   s   | ]}t |V  qd S r    )r   rI   r   r   r   	<genexpr>0  s     z&TensorShape.__str__.<locals>.<genexpr>)ndimsrK   joinr   r   r   r   r   *  s
    

zTensorShape.__str__c                 C   s   | j S )zJReturns a list of Dimensions, or None if the shape is
        unspecified.rQ   r   r   r   r   rN   2  s    zTensorShape.dimsc                 C   s   || _ d | _d S r    )rK   rP   )r   rN   r   r   r   rN   8  s    c                 C   s.   | j dkrdS | jdkr$t| j | _| jS dS )z=Returns the rank of this shape, or None if it is unspecified.N)rK   rP   lenr   r   r   r   rS   =  s
    

zTensorShape.ndimsc                 C   s   | j dkrtd| jS )zLReturns the rank of this shape, or raises ValueError if
        unspecified.Nz2Cannot take the length of Shape with unknown rank.)rK   r   rS   r   r   r   r   __len__G  s
    
zTensorShape.__len__c                 C   s
   | j dk	S )z9Returns True if this shape contains non-zero information.NrQ   r   r   r   r   __bool__P  s    zTensorShape.__bool__c                 C   s"   | j dkrtdn
t| j S dS )zNReturns `self.dims` if the rank is known, otherwise raises
        ValueError.Nz.Cannot iterate over a shape with unknown rank.)rK   r   rO   r   r   r   r   __iter__W  s    

zTensorShape.__iter__c                 C   s   | j dk	r.t|tr"t| j | S | j | S nrt|tr|jdk	rH|jnd}|j}|jdk	rdtd|dkrrt S |dk s|dk rt S t|| dS nt	dS dS )aI  Returns the value of a dimension or a shape, depending on the key.

        Args:
          key: If `key` is an integer, returns the dimension at that index;
            otherwise if `key` is a slice, returns a TensorShape whose
            dimensions are those selected by the slice from `self`.

        Returns:
          A dimension if `key` is an integer, or a `TensorShape` if `key` is a
          slice.

        Raises:
          ValueError: If `key` is a slice, and any of its elements are negative, or
            if `self` is completely unknown and the step is set.
        Nr   zSteps are not yet handledrS   )
rK   r   slicerB   startstopstepr   unknown_shaper   )r   keyr[   r\   r   r   r   __getitem___  s    



zTensorShape.__getitem__c                 C   s.   |   r&d}| jD ]}||j9 }q|S dS dS )zLReturns the total number of elements, or none for incomplete
        shapes.r   N)is_fully_definedrK   r   )r   rD   rG   r   r   r   num_elements  s    
zTensorShape.num_elementsc                 C   s   t |}| jdkr|S z@| | g }t| jD ]\}}||||  q0t|W S  tk
rz   td| |f Y nX dS )a  Returns a `TensorShape` combining the information in `self` and
        `other`.

        The dimensions in `self` and `other` are merged elementwise,
        according to the rules defined for `Dimension.merge_with()`.

        Args:
          other: Another `TensorShape`.

        Returns:
          A `TensorShape` containing the combined information of `self` and
          `other`.

        Raises:
          ValueError: If `self` and `other` are not convertible.
        Nz$Shapes %s and %s are not convertible)as_shaperK   assert_same_rank	enumerateappendr)   rB   r   )r   r   Znew_dimsirG   r   r   r   r)     s    



zTensorShape.merge_withc                 C   s6   t |}| jdks|jdkr"t S t| j|j S dS )a   Returns the concatenation of the dimension in `self` and `other`.

        *N.B.* If either `self` or `other` is completely unknown,
        concatenation will discard information about the other shape. In
        future, we might support concatenation that preserves this
        information for use with slicing.

        Args:
          other: Another `TensorShape`.

        Returns:
          A `TensorShape` whose dimensions are the concatenation of the
          dimensions in `self` and `other`.
        N)rc   rK   rN   r^   rB   r   r   r   r   concatenate  s    zTensorShape.concatenatec                 C   s<   t |}| jdk	r8|jdk	r8| j|jkr8td| |f dS )a  Raises an exception if `self` and `other` do not have convertible
        ranks.

        Args:
          other: Another `TensorShape`.

        Raises:
          ValueError: If `self` and `other` do not represent shapes with the
            same rank.
        Nz(Shapes %s and %s must have the same rank)rc   rS   r   r   r   r   r   rd     s    
zTensorShape.assert_same_rankc                 C   s"   | j d|fkrtd| |f dS )zRaises an exception if `self` is not convertible with the given
        `rank`.

        Args:
          rank: An integer.

        Raises:
          ValueError: If `self` does not represent a shape with the given `rank`.
        NShape %s must have rank %drS   r   r   Zrankr   r   r   assert_has_rank  s    
zTensorShape.assert_has_rankc                 C   s<   z|  t|dW S  tk
r6   td| |f Y nX dS )a  Returns a shape based on `self` with the given rank.

        This method promotes a completely unknown shape to one with a
        known rank.

        Args:
          rank: An integer.

        Returns:
          A shape that is at least as specific as `self` with the given rank.

        Raises:
          ValueError: If `self` does not represent a shape with the given `rank`.
        rY   ri   N)r)   r^   r   rk   r   r   r   	with_rank  s    zTensorShape.with_rankc                 C   s.   | j dk	r&| j |k r&td| |f n| S dS )a\  Returns a shape based on `self` with at least the given rank.

        Args:
          rank: An integer.

        Returns:
          A shape that is at least as specific as `self` with at least the given
          rank.

        Raises:
          ValueError: If `self` does not represent a shape with at least the given
            `rank`.
        Nz#Shape %s must have rank at least %drj   rk   r   r   r   with_rank_at_least   s
    
zTensorShape.with_rank_at_leastc                 C   s.   | j dk	r&| j |kr&td| |f n| S dS )aY  Returns a shape based on `self` with at most the given rank.

        Args:
          rank: An integer.

        Returns:
          A shape that is at least as specific as `self` with at most the given
          rank.

        Raises:
          ValueError: If `self` does not represent a shape with at most the given
            `rank`.
        Nz"Shape %s must have rank at most %drj   rk   r   r   r   with_rank_at_most  s
    
zTensorShape.with_rank_at_mostc                 C   sX   t |}| jdk	rT|jdk	rT| j|jkr,dS t| j|jD ]\}}||s: dS q:dS )a  Returns True iff `self` is convertible with `other`.

        Two possibly-partially-defined shapes are convertible if there
        exists a fully-defined shape that both shapes can represent. Thus,
        convertibility allows the shape inference code to reason about
        partially-defined shapes. For example:

        * TensorShape(None) is convertible with all shapes.

        * TensorShape([None, None]) is convertible with all two-dimensional
          shapes, such as TensorShape([32, 784]), and also TensorShape(None). It is
          not convertible with, for example, TensorShape([None]) or
          TensorShape([None, None, None]).

        * TensorShape([32, None]) is convertible with all two-dimensional shapes
          with size 32 in the 0th dimension, and also TensorShape([None, None])
          and TensorShape(None). It is not convertible with, for example,
          TensorShape([32]), TensorShape([32, None, 1]) or TensorShape([64, None]).

        * TensorShape([32, 784]) is convertible with itself, and also
          TensorShape([32, None]), TensorShape([None, 784]), TensorShape([None,
          None]) and TensorShape(None). It is not convertible with, for example,
          TensorShape([32, 1, 784]) or TensorShape([None]).

        The convertibility relation is reflexive and symmetric, but not
        transitive. For example, TensorShape([32, 784]) is convertible with
        TensorShape(None), and TensorShape(None) is convertible with
        TensorShape([4, 4]), but TensorShape([32, 784]) is not convertible with
        TensorShape([4, 4]).

        Args:
          other: Another TensorShape.

        Returns:
          True iff `self` is convertible with `other`.
        NFT)rc   rK   rN   rS   zipr&   )r   r   Zx_dimZy_dimr   r   r   r&   *  s    %
zTensorShape.is_convertible_withc                 C   s   |  |std| |f dS )a`  Raises exception if `self` and `other` do not represent the same
        shape.

        This method can be used to assert that there exists a shape that both
        `self` and `other` represent.

        Args:
          other: Another TensorShape.

        Raises:
          ValueError: If `self` and `other` do not represent the same shape.
        z"Shapes %s and %s are inconvertibleNr'   r   r   r   r   r(   X  s    

z&TensorShape.assert_is_convertible_withc                 C   s   t |}| jdks(|jdks(| j|jkr.t S tdg| j }tt| j|jD ],\}\}}|dk	rP|dk	rP||krP|||< qPt|S )a/  Returns the most specific TensorShape convertible with `self` and
        `other`.

        * TensorShape([None, 1]) is the most specific TensorShape convertible with
          both TensorShape([2, 1]) and TensorShape([5, 1]). Note that
          TensorShape(None) is also convertible with above mentioned TensorShapes.

        * TensorShape([1, 2, 3]) is the most specific TensorShape convertible with
          both TensorShape([1, 2, 3]) and TensorShape([1, 2, 3]). There are more
          less specific TensorShapes convertible with above mentioned TensorShapes,
          e.g. TensorShape([1, 2, None]), TensorShape(None).

        Args:
          other: Another `TensorShape`.

        Returns:
          A `TensorShape` which is the most specific convertible shape of `self`
          and `other`.
        N)	rc   rK   rN   rS   r^   r   re   rp   rB   )r   r   rN   rg   d1Zd2r   r   r   most_specific_convertible_shapej  s    

z+TensorShape.most_specific_convertible_shapec                 C   s   | j dk	otdd | j D S )z<Returns True iff `self` is fully defined in every dimension.Nc                 s   s   | ]}|j d k	V  qd S r    rA   rE   r   r   r   rR     s    z/TensorShape.is_fully_defined.<locals>.<genexpr>)rK   allr   r   r   r   ra     s    zTensorShape.is_fully_definedc                 C   s   |   std|  dS )zRaises an exception if `self` is not fully defined in every
        dimension.

        Raises:
          ValueError: If `self` does not have a known value for every dimension.
        zShape %s is not fully definedN)ra   r   r   r   r   r   assert_is_fully_defined  s    z#TensorShape.assert_is_fully_definedc                 C   s"   | j dkrtddd | j D S )zReturns a list of integers or `None` for each dimension.

        Returns:
          A list of integers or `None` for each dimension.

        Raises:
          ValueError: If `self` is an unknown shape with an unknown rank.
        Nz3as_list() is not defined on an unknown TensorShape.c                 S   s   g | ]
}|j qS r   rA   rE   r   r   r   rH     s     z'TensorShape.as_list.<locals>.<listcomp>)rK   r   r   r   r   r   as_list  s
    	
zTensorShape.as_listc                 C   s2   | j dkrtjddS tjdd | j D dS dS )z+Returns this shape as a `TensorShapeProto`.NT)rM   c                 S   s*   g | ]"}t jj|jd krdn|jdqS )NrC   )rD   )r   rL   ZDimr   rI   r   r   r   rH     s   z(TensorShape.as_proto.<locals>.<listcomp>)rG   )rK   r   rL   r   r   r   r   as_proto  s    
zTensorShape.as_protoc                 C   s2   zt |}W n tk
r$   t Y S X | j|jkS )z0Returns True if `self` is equivalent to `other`.)rc   r	   r   rK   rN   r   r   r   r   r     s
    
zTensorShape.__eq__c                 C   s^   zt |}W n tk
r$   t Y S X | jdks:|jdkrBtd| j|jkrRdS | j|jkS )z=Returns True if `self` is known to be different from `other`.Nz4The inequality of unknown TensorShapes is undefined.T)rc   r	   r   rS   r   rK   rN   r   r   r   r   r     s    
zTensorShape.__ne__c                 C   s   t | jffS r    )rB   rK   r   r   r   r   r;     s    zTensorShape.__reduce__N)"r<   r=   r>   r?   r   r   r   r@   rN   setterrS   rV   rW   __nonzero__rX   r`   rb   r)   rh   rd   rl   rm   rn   ro   r&   r(   rr   ra   rt   ru   rv   r   r   r;   r   r   r   r   rB     sB   (


		, .#
rB   c                 C   s   t | tr| S t| S dS )z+Converts the given object to a TensorShape.N)r   rB   )shaper   r   r   rc     s    
rc   Nc                 C   s&   | dkrt dS t tdg|  S dS )zReturns an unknown TensorShape, optionally with a known rank.

    Args:
      ndims: (Optional) If specified, the number of dimensions in the shape.

    Returns:
      An unknown TensorShape.
    N)rB   r   rY   r   r   r   r^     s    	r^   c                   C   s   t S )z&Returns a shape representing a scalar.)_SCALAR_SHAPEr   r   r   r   scalar  s    r{   c                 C   s
   t | gS )zReturns a shape representing a vector.

    Args:
      length: The length of the vector, which may be None if unknown.

    Returns:
      A TensorShape representing a vector of the given length.
    rB   )lengthr   r   r   vector  s    	r~   c                 C   s   t | |gS )a  Returns a shape representing a matrix.

    Args:
      rows: The number of rows in the matrix, which may be None if unknown.
      cols: The number of columns in the matrix, which may be None if unknown.

    Returns:
      A TensorShape representing a matrix of the given size.
    r|   )Zrowscolsr   r   r   matrix  s    
r   )N)r?    r   r   Ztensorboard.compat.protor   objectr   r   rB   rc   r^   rz   r{   r~   r   r   r   r   r   <module>   s"      D   l
