title: PyCharm: 'Function Doesn't Return Anything'
body: <p>I just started working with PyCharm Community Edition 2016.3.2 today. Every time I assign a value from my function <code>at_square</code>, it warns me that 'Function <code>at_square</code> doesn't return anything,' but it definitely does in every instance unless an error is raised during execution, and every use of the function is behaving as expected. I want to know why PyCharm thinks it doesn't and if there's anything I can do to correct it. (I know there is an option to suppress the warning for that particular function, but it does so by inserting a commented line in my code above the function, and I find it just as annoying to have to remember to take that out at the end of the project.)</p>
  
  <p>This is the function in question:</p>
  
  <pre><code>def at_square(self, square):
      """ Return the value at the given square """
      if type(square) == str:
          file, rank = Board.tup_from_an(square)
      elif type(square) == tuple:
          file, rank = square
      else:
          raise ValueError("Expected tuple or AN str, got " + str(type(square)))
  
      if not 0 &lt;= file &lt;= 7:
          raise ValueError("File out of range: " + str(file))
      if not 0 &lt;= rank &lt;= 7:
          raise ValueError("Rank out of range: " + str(rank))
  
      return self.board[file][rank]
  </code></pre>
  
  <p>If it matters, this is more precisely a method of an object. I stuck with the term 'function' because that is the language PyCharm is using.</p>
  
  <p>My only thought is that my use of error raising might be confusing PyCharm, but that seems too simple. (Please feel free to critique my error raising, as I'm not sure this is the idiomatic way to do it.)</p>
  
  <p><strong>Update:</strong> Humorously, if I remove the return line altogether, the warning goes away and returns immediately when I put it back. It also goes away if I replace <code>self.board[file][rank]</code> with a constant value like <code>8</code>. Changing <code>file</code> or <code>rank</code> to constant values does not remove the warning, so I gather that PyCharm is somehow confused about the nature of <code>self.board</code>, which is a list of 8 other lists.</p>
  
  <p><strong>Update:</strong> Per the suggestion of @StephenRauch, I created a minimal example that reflects everything relevant to data assignment done by <code>at_square</code>:</p>
  
  <pre><code>class Obj:
      def __init__(self):
          self.nested_list = [[0],[1]]
  
      @staticmethod
      def tup_method(data):
          return tuple(data)
  
      def method(self,data):
          x,y = Obj.tup_method(data)
          return self.nested_list[x][y]
  
      def other_method(self,data):
          value = self.method(data)
          print(value)
  
  x = Obj()
  x.other_method([1,2])
  </code></pre>
  
  <p>PyCharm doesn't give any warnings for this. In <code>at_square</code>, I've tried commenting out every single line down to the two following:</p>
  
  <pre><code>def at_square(self, square):
      file, rank = Board.tup_from_an(square)
      return self.board[file][rank]
  </code></pre>
  
  <p>PyCharm gives the same warning. If I leave only the return line, then and only then does the warning disappear. PyCharm appears to be confused by the simultaneous assignment of <code>file</code> and <code>rank</code> via <code>tup_from_an</code>. Here is the code for that method:</p>
  
  <pre><code>@staticmethod
  def tup_from_an(an):
      """ Convert a square in algebraic notation into a coordinate tuple """
      if an[0] in Board.a_file_dict:
          file = Board.a_file_dict[an[0]]
      else:
          raise ValueError("Invalid an syntax (file out of range a-h): " + str(an))
  
      if not an[1].isnumeric():
          raise ValueError("Invalid an syntax (rank out of range 1-8): " + str(an))
      elif int(an[1]) - 1 in Board.n_file_dict:
          rank = int(an[1]) - 1
      else:
          raise ValueError("Invalid an syntax (rank out of range 1-8): " + str(an))
  
      return file, rank
  </code></pre>
  
  <p><strong>Update:</strong> In its constructor, the class <code>Board</code> (which is the parent class for all these methods) saves a reference to the instance in a static variable <code>instance</code>. <code>self.at_square(square)</code> gives the warning, while <code>Board.instance.at_square(square)</code> does not. I'm still going to use the former where appropriate, but that could shed some light on what PyCharm is thinking.</p>