Uploaded image for project: 'SonarPython'
  1. SonarPython
  2. SONARPY-641

Improve rule S5655 by using annotations and runtime checks

    Details

    • Type: Improvement
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Rules
    • Labels:
      None

      Description

      1/ We will use type annotations on function parameters to deduce their type.

      Noncompliant Code Example

      def annotation(var: str):
          #Note that type annotations are not checked at runtime. Only type checkers will detect issues.
          pass
      
      annotation(42)  # Noncompliant
      

      Compliant Solution

      def annotation(var: str):
          pass
      
      annotation("42")
      

      2/ We will use runtime checks to deduce the type of a parameter

      Noncompliant Code Example

      def assert_isinstance(var):
          assert isinstance(var, str), "unexpected type for var"
          # Note that using assert to validate arguments is not recommended as asserts are disabled when __debug__ is False
      
      assert_isinstance(42)  # Noncompliant
      
      def raise_type_error(var):
          if not isinstance(var, str):
              raise TypeError("unexpected type for var")
      
      raise_type_error(42)  # Noncompliant
      

      Compliant Solution

      def assert_isinstance(var):
          assert isinstance(var, str), "unexpected type for var"
      
      assert_isinstance("42")
      
      def raise_type_error(var):
          if not isinstance(var, str):
              raise TypeError("unexpected type for var")
      
      raise_type_error("42")
      

      If possible we should try to deduce the type of a parameter from the way it is used, and not only from calls to isinstance.

      def expect_number(var):
          round(var)  # This makes it clear that "var" is a number
      
      expect_number("42.3")  # Noncompliant
      
      def not_none(var):
         var.foo()  # This makes it clear that "var" is not None
      
      not_none(None)  # Noncompliant
      

      Note that we can have the signature of builtin functions from Typeshed

      RSPEC modification:

      Once implemented we need to modify the RSPEC as follow

      ==========================================================
      Python does not check the type of arguments provided to functions. However python developers often add code to test their type. Going against these checks by providing an argument of the wrong type will create a bug.

      This rule raises an issue when a function argument does not match the corresponding parameter's type.

      Noncompliant Code Example

      def assert_isinstance(var):
          assert isinstance(var, str), "unexpected type for var"
          # Note that using assert to validate arguments is not recommended as asserts are disabled when __debug__ is False
      
      assert_isinstance(42)  # Noncompliant
      
      def raise_type_error(var):
          if not isinstance(var, str):
              raise TypeError("unexpected type for var")
      
      raise_type_error(42)  # Noncompliant
      
      def annotation(var: str):
          #Note that type annotations are not checked at runtime. Only type checkers will detect issues.
          pass
      
      annotation(42)  # Noncompliant
      
      round("42.3")  # Noncompliant
      

      Compliant Solution

      def assert_isinstance(var):
          assert isinstance(var, str), "unexpected type for var"
      
      assert_isinstance("42")
      
      def raise_type_error(var):
          if not isinstance(var, str):
              raise TypeError("unexpected type for var")
      
      raise_type_error("42")
      
      def annotation(var: str):
          pass
      
      annotation("42")
      
      round(42.3)
      

      See

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                nicolas.harraudeau Nicolas Harraudeau
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated: