code: def test_PythonMPQ():
      #
      # Test PythonMPQ and also mpq if gmpy/gmpy2 is installed.
      #
      for Q, TQ, Z, TZ in rational_types:
  
          def check_Q(q):
              assert isinstance(q, TQ)
              assert isinstance(q.numerator, TZ)
              assert isinstance(q.denominator, TZ)
              return q.numerator, q.denominator
  
          # Check construction from different types
          assert check_Q(Q(3)) == (3, 1)
          assert check_Q(Q(3, 5)) == (3, 5)
          assert check_Q(Q(Q(3, 5))) == (3, 5)
          assert check_Q(Q(0.5)) == (1, 2)
          assert check_Q(Q("0.5")) == (1, 2)
          assert check_Q(Q(Fraction(3, 5))) == (3, 5)
  
          # https://github.com/aleaxit/gmpy/issues/327
          if Q is PythonMPQ:
              assert check_Q(Q(Decimal("0.6"))) == (3, 5)
  
          # Invalid types
          raises(TypeError, lambda: Q([]))
          raises(TypeError, lambda: Q([], []))
  
          # Check normalisation of signs
          assert check_Q(Q(2, 3)) == (2, 3)
          assert check_Q(Q(-2, 3)) == (-2, 3)
          assert check_Q(Q(2, -3)) == (-2, 3)
          assert check_Q(Q(-2, -3)) == (2, 3)
  
          # Check gcd calculation
          assert check_Q(Q(12, 8)) == (3, 2)
  
          # __int__/__float__
          assert int(Q(5, 3)) == 1
          assert int(Q(-5, 3)) == -1
          assert float(Q(5, 2)) == 2.5
          assert float(Q(-5, 2)) == -2.5
  
          # __str__/__repr__
          assert str(Q(2, 1)) == "2"
          assert str(Q(1, 2)) == "1/2"
          if Q is PythonMPQ:
              assert repr(Q(2, 1)) == "MPQ(2,1)"
              assert repr(Q(1, 2)) == "MPQ(1,2)"
          else:
              assert repr(Q(2, 1)) == "mpq(2,1)"
              assert repr(Q(1, 2)) == "mpq(1,2)"
  
          # __bool__
          assert bool(Q(1, 2)) is True
          assert bool(Q(0)) is False
  
          # __eq__/__ne__
          assert (Q(2, 3) == Q(2, 3)) is True
          assert (Q(2, 3) == Q(2, 5)) is False
          assert (Q(2, 3) != Q(2, 3)) is False
          assert (Q(2, 3) != Q(2, 5)) is True
  
          # __hash__
          assert hash(Q(3, 5)) == hash(Fraction(3, 5))
  
          # __reduce__
          q = Q(2, 3)
          assert pickle.loads(pickle.dumps(q)) == q
  
          # __ge__/__gt__/__le__/__lt__
          assert (Q(1, 3) < Q(2, 3)) is True
          assert (Q(2, 3) < Q(2, 3)) is False
          assert (Q(2, 3) < Q(1, 3)) is False
          assert (Q(-2, 3) < Q(1, 3)) is True
          assert (Q(1, 3) < Q(-2, 3)) is False
  
          assert (Q(1, 3) <= Q(2, 3)) is True
          assert (Q(2, 3) <= Q(2, 3)) is True
          assert (Q(2, 3) <= Q(1, 3)) is False
          assert (Q(-2, 3) <= Q(1, 3)) is True
          assert (Q(1, 3) <= Q(-2, 3)) is False
  
          assert (Q(1, 3) > Q(2, 3)) is False
          assert (Q(2, 3) > Q(2, 3)) is False
          assert (Q(2, 3) > Q(1, 3)) is True
          assert (Q(-2, 3) > Q(1, 3)) is False
          assert (Q(1, 3) > Q(-2, 3)) is True
  
          assert (Q(1, 3) >= Q(2, 3)) is False
          assert (Q(2, 3) >= Q(2, 3)) is True
          assert (Q(2, 3) >= Q(1, 3)) is True
          assert (Q(-2, 3) >= Q(1, 3)) is False
          assert (Q(1, 3) >= Q(-2, 3)) is True
  
          # __abs__/__pos__/__neg__
          assert abs(Q(2, 3)) == abs(Q(-2, 3)) == Q(2, 3)
          assert +Q(2, 3) == Q(2, 3)
          assert -Q(2, 3) == Q(-2, 3)
  
          # __add__/__radd__
          assert Q(2, 3) + Q(5, 7) == Q(29, 21)
          assert Q(2, 3) + 1 == Q(5, 3)
          assert 1 + Q(2, 3) == Q(5, 3)
          raises(TypeError, lambda: [] + Q(1))
          raises(TypeError, lambda: Q(1) + [])
  
          # __sub__/__rsub__
          assert Q(2, 3) - Q(5, 7) == Q(-1, 21)
          assert Q(2, 3) - 1 == Q(-1, 3)
          assert 1 - Q(2, 3) == Q(1, 3)
          raises(TypeError, lambda: [] - Q(1))
          raises(TypeError, lambda: Q(1) - [])
  
          # __mul__/__rmul__
          assert Q(2, 3) * Q(5, 7) == Q(10, 21)
          assert Q(2, 3) * 1 == Q(2, 3)
          assert 1 * Q(2, 3) == Q(2, 3)
          raises(TypeError, lambda: [] * Q(1))
          raises(TypeError, lambda: Q(1) * [])
  
          # __pow__/__rpow__
          assert Q(2, 3) ** 2 == Q(4, 9)
          assert Q(2, 3) ** 1 == Q(2, 3)
          assert Q(-2, 3) ** 2 == Q(4, 9)
          assert Q(-2, 3) ** -1 == Q(-3, 2)
          if Q is PythonMPQ:
              raises(TypeError, lambda: 1 ** Q(2, 3))
              raises(TypeError, lambda: Q(1, 4) ** Q(1, 2))
          raises(TypeError, lambda: [] ** Q(1))
          raises(TypeError, lambda: Q(1) ** [])
  
          # __div__/__rdiv__
          assert Q(2, 3) / Q(5, 7) == Q(14, 15)
          assert Q(2, 3) / 1 == Q(2, 3)
          assert 1 / Q(2, 3) == Q(3, 2)
          raises(TypeError, lambda: [] / Q(1))
          raises(TypeError, lambda: Q(1) / [])
          raises(ZeroDivisionError, lambda: Q(1, 2) / Q(0))
  
          # __divmod__
          if Q is PythonMPQ:
              raises(TypeError, lambda: Q(2, 3) // Q(1, 3))
              raises(TypeError, lambda: Q(2, 3) % Q(1, 3))
              raises(TypeError, lambda: 1 // Q(1, 3))
              raises(TypeError, lambda: 1 % Q(1, 3))
              raises(TypeError, lambda: Q(2, 3) // 1)
              raises(TypeError, lambda: Q(2, 3) % 1)
  
imports: from fractions import Fraction
  from decimal import Decimal
  import pickle
  from typing import Callable, List, Tuple, Type
  from sympy.testing.pytest import raises
  from sympy.external.pythonmpq import PythonMPQ
label_desc: Use image node_id 1 for calling a global function with example usage: test_PythonMPQ() and returns: q,  q