This commit was manufactured by cvs2svn to create tag 'r23b1-mac'.
[python/dscho.git] / Lib / test / test_grammar.py
blobea0a88ceb921618d53df1cee60019b6543abd850
1 # Python test set -- part 1, grammar.
2 # This just tests whether the parser accepts them all.
4 # NOTE: When you run this test as a script from the command line, you
5 # get warnings about certain hex/oct constants. Since those are
6 # issued by the parser, you can't suppress them by adding a
7 # filterwarnings() call to this module. Therefore, to shut up the
8 # regression test, the filterwarnings() call has been added to
9 # regrtest.py.
11 from test.test_support import TestFailed, verify, check_syntax
12 import sys
14 print '1. Parser'
16 print '1.1 Tokens'
18 print '1.1.1 Backslashes'
20 # Backslash means line continuation:
21 x = 1 \
22 + 1
23 if x != 2: raise TestFailed, 'backslash for line continuation'
25 # Backslash does not means continuation in comments :\
26 x = 0
27 if x != 0: raise TestFailed, 'backslash ending comment'
29 print '1.1.2 Numeric literals'
31 print '1.1.2.1 Plain integers'
32 if 0xff != 255: raise TestFailed, 'hex int'
33 if 0377 != 255: raise TestFailed, 'octal int'
34 if 2147483647 != 017777777777: raise TestFailed, 'large positive int'
35 try:
36 from sys import maxint
37 except ImportError:
38 maxint = 2147483647
39 if maxint == 2147483647:
40 # The following test will start to fail in Python 2.4;
41 # change the 020000000000 to -020000000000
42 if -2147483647-1 != 020000000000: raise TestFailed, 'max negative int'
43 # XXX -2147483648
44 if 037777777777 != -1: raise TestFailed, 'oct -1'
45 if 0xffffffff != -1: raise TestFailed, 'hex -1'
46 for s in '2147483648', '040000000000', '0x100000000':
47 try:
48 x = eval(s)
49 except OverflowError:
50 print "OverflowError on huge integer literal " + `s`
51 elif eval('maxint == 9223372036854775807'):
52 if eval('-9223372036854775807-1 != 01000000000000000000000'):
53 raise TestFailed, 'max negative int'
54 if eval('01777777777777777777777') != -1: raise TestFailed, 'oct -1'
55 if eval('0xffffffffffffffff') != -1: raise TestFailed, 'hex -1'
56 for s in '9223372036854775808', '02000000000000000000000', \
57 '0x10000000000000000':
58 try:
59 x = eval(s)
60 except OverflowError:
61 print "OverflowError on huge integer literal " + `s`
62 else:
63 print 'Weird maxint value', maxint
65 print '1.1.2.2 Long integers'
66 x = 0L
67 x = 0l
68 x = 0xffffffffffffffffL
69 x = 0xffffffffffffffffl
70 x = 077777777777777777L
71 x = 077777777777777777l
72 x = 123456789012345678901234567890L
73 x = 123456789012345678901234567890l
75 print '1.1.2.3 Floating point'
76 x = 3.14
77 x = 314.
78 x = 0.314
79 # XXX x = 000.314
80 x = .314
81 x = 3e14
82 x = 3E14
83 x = 3e-14
84 x = 3e+14
85 x = 3.e14
86 x = .3e14
87 x = 3.1e4
89 print '1.1.3 String literals'
91 x = ''; y = ""; verify(len(x) == 0 and x == y)
92 x = '\''; y = "'"; verify(len(x) == 1 and x == y and ord(x) == 39)
93 x = '"'; y = "\""; verify(len(x) == 1 and x == y and ord(x) == 34)
94 x = "doesn't \"shrink\" does it"
95 y = 'doesn\'t "shrink" does it'
96 verify(len(x) == 24 and x == y)
97 x = "does \"shrink\" doesn't it"
98 y = 'does "shrink" doesn\'t it'
99 verify(len(x) == 24 and x == y)
100 x = """
101 The "quick"
102 brown fox
103 jumps over
104 the 'lazy' dog.
106 y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n'
107 verify(x == y)
108 y = '''
109 The "quick"
110 brown fox
111 jumps over
112 the 'lazy' dog.
113 '''; verify(x == y)
114 y = "\n\
115 The \"quick\"\n\
116 brown fox\n\
117 jumps over\n\
118 the 'lazy' dog.\n\
119 "; verify(x == y)
120 y = '\n\
121 The \"quick\"\n\
122 brown fox\n\
123 jumps over\n\
124 the \'lazy\' dog.\n\
125 '; verify(x == y)
128 print '1.2 Grammar'
130 print 'single_input' # NEWLINE | simple_stmt | compound_stmt NEWLINE
131 # XXX can't test in a script -- this rule is only used when interactive
133 print 'file_input' # (NEWLINE | stmt)* ENDMARKER
134 # Being tested as this very moment this very module
136 print 'expr_input' # testlist NEWLINE
137 # XXX Hard to test -- used only in calls to input()
139 print 'eval_input' # testlist ENDMARKER
140 x = eval('1, 0 or 1')
142 print 'funcdef'
143 ### 'def' NAME parameters ':' suite
144 ### parameters: '(' [varargslist] ')'
145 ### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME]
146 ### | ('**'|'*' '*') NAME)
147 ### | fpdef ['=' test] (',' fpdef ['=' test])* [',']
148 ### fpdef: NAME | '(' fplist ')'
149 ### fplist: fpdef (',' fpdef)* [',']
150 ### arglist: (argument ',')* (argument | *' test [',' '**' test] | '**' test)
151 ### argument: [test '='] test # Really [keyword '='] test
152 def f1(): pass
153 f1()
154 f1(*())
155 f1(*(), **{})
156 def f2(one_argument): pass
157 def f3(two, arguments): pass
158 def f4(two, (compound, (argument, list))): pass
159 def f5((compound, first), two): pass
160 verify(f2.func_code.co_varnames == ('one_argument',))
161 verify(f3.func_code.co_varnames == ('two', 'arguments'))
162 if sys.platform.startswith('java'):
163 verify(f4.func_code.co_varnames ==
164 ('two', '(compound, (argument, list))', 'compound', 'argument',
165 'list',))
166 verify(f5.func_code.co_varnames ==
167 ('(compound, first)', 'two', 'compound', 'first'))
168 else:
169 verify(f4.func_code.co_varnames == ('two', '.2', 'compound',
170 'argument', 'list'))
171 verify(f5.func_code.co_varnames == ('.0', 'two', 'compound', 'first'))
172 def a1(one_arg,): pass
173 def a2(two, args,): pass
174 def v0(*rest): pass
175 def v1(a, *rest): pass
176 def v2(a, b, *rest): pass
177 def v3(a, (b, c), *rest): return a, b, c, rest
178 if sys.platform.startswith('java'):
179 verify(v3.func_code.co_varnames == ('a', '(b, c)', 'rest', 'b', 'c'))
180 else:
181 verify(v3.func_code.co_varnames == ('a', '.2', 'rest', 'b', 'c'))
182 verify(v3(1, (2, 3), 4) == (1, 2, 3, (4,)))
183 def d01(a=1): pass
184 d01()
185 d01(1)
186 d01(*(1,))
187 d01(**{'a':2})
188 def d11(a, b=1): pass
189 d11(1)
190 d11(1, 2)
191 d11(1, **{'b':2})
192 def d21(a, b, c=1): pass
193 d21(1, 2)
194 d21(1, 2, 3)
195 d21(*(1, 2, 3))
196 d21(1, *(2, 3))
197 d21(1, 2, *(3,))
198 d21(1, 2, **{'c':3})
199 def d02(a=1, b=2): pass
200 d02()
201 d02(1)
202 d02(1, 2)
203 d02(*(1, 2))
204 d02(1, *(2,))
205 d02(1, **{'b':2})
206 d02(**{'a': 1, 'b': 2})
207 def d12(a, b=1, c=2): pass
208 d12(1)
209 d12(1, 2)
210 d12(1, 2, 3)
211 def d22(a, b, c=1, d=2): pass
212 d22(1, 2)
213 d22(1, 2, 3)
214 d22(1, 2, 3, 4)
215 def d01v(a=1, *rest): pass
216 d01v()
217 d01v(1)
218 d01v(1, 2)
219 d01v(*(1, 2, 3, 4))
220 d01v(*(1,))
221 d01v(**{'a':2})
222 def d11v(a, b=1, *rest): pass
223 d11v(1)
224 d11v(1, 2)
225 d11v(1, 2, 3)
226 def d21v(a, b, c=1, *rest): pass
227 d21v(1, 2)
228 d21v(1, 2, 3)
229 d21v(1, 2, 3, 4)
230 d21v(*(1, 2, 3, 4))
231 d21v(1, 2, **{'c': 3})
232 def d02v(a=1, b=2, *rest): pass
233 d02v()
234 d02v(1)
235 d02v(1, 2)
236 d02v(1, 2, 3)
237 d02v(1, *(2, 3, 4))
238 d02v(**{'a': 1, 'b': 2})
239 def d12v(a, b=1, c=2, *rest): pass
240 d12v(1)
241 d12v(1, 2)
242 d12v(1, 2, 3)
243 d12v(1, 2, 3, 4)
244 d12v(*(1, 2, 3, 4))
245 d12v(1, 2, *(3, 4, 5))
246 d12v(1, *(2,), **{'c': 3})
247 def d22v(a, b, c=1, d=2, *rest): pass
248 d22v(1, 2)
249 d22v(1, 2, 3)
250 d22v(1, 2, 3, 4)
251 d22v(1, 2, 3, 4, 5)
252 d22v(*(1, 2, 3, 4))
253 d22v(1, 2, *(3, 4, 5))
254 d22v(1, *(2, 3), **{'d': 4})
256 ### lambdef: 'lambda' [varargslist] ':' test
257 print 'lambdef'
258 l1 = lambda : 0
259 verify(l1() == 0)
260 l2 = lambda : a[d] # XXX just testing the expression
261 l3 = lambda : [2 < x for x in [-1, 3, 0L]]
262 verify(l3() == [0, 1, 0])
263 l4 = lambda x = lambda y = lambda z=1 : z : y() : x()
264 verify(l4() == 1)
265 l5 = lambda x, y, z=2: x + y + z
266 verify(l5(1, 2) == 5)
267 verify(l5(1, 2, 3) == 6)
268 check_syntax("lambda x: x = 2")
270 ### stmt: simple_stmt | compound_stmt
271 # Tested below
273 ### simple_stmt: small_stmt (';' small_stmt)* [';']
274 print 'simple_stmt'
275 x = 1; pass; del x
277 ### small_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt
278 # Tested below
280 print 'expr_stmt' # (exprlist '=')* exprlist
282 1, 2, 3
283 x = 1
284 x = 1, 2, 3
285 x = y = z = 1, 2, 3
286 x, y, z = 1, 2, 3
287 abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4)
288 # NB these variables are deleted below
290 check_syntax("x + 1 = 1")
291 check_syntax("a + 1 = b + 2")
293 print 'print_stmt' # 'print' (test ',')* [test]
294 print 1, 2, 3
295 print 1, 2, 3,
296 print
297 print 0 or 1, 0 or 1,
298 print 0 or 1
300 print 'extended print_stmt' # 'print' '>>' test ','
301 import sys
302 print >> sys.stdout, 1, 2, 3
303 print >> sys.stdout, 1, 2, 3,
304 print >> sys.stdout
305 print >> sys.stdout, 0 or 1, 0 or 1,
306 print >> sys.stdout, 0 or 1
308 # test printing to an instance
309 class Gulp:
310 def write(self, msg): pass
312 gulp = Gulp()
313 print >> gulp, 1, 2, 3
314 print >> gulp, 1, 2, 3,
315 print >> gulp
316 print >> gulp, 0 or 1, 0 or 1,
317 print >> gulp, 0 or 1
319 # test print >> None
320 def driver():
321 oldstdout = sys.stdout
322 sys.stdout = Gulp()
323 try:
324 tellme(Gulp())
325 tellme()
326 finally:
327 sys.stdout = oldstdout
329 # we should see this once
330 def tellme(file=sys.stdout):
331 print >> file, 'hello world'
333 driver()
335 # we should not see this at all
336 def tellme(file=None):
337 print >> file, 'goodbye universe'
339 driver()
341 # syntax errors
342 check_syntax('print ,')
343 check_syntax('print >> x,')
345 print 'del_stmt' # 'del' exprlist
346 del abc
347 del x, y, (z, xyz)
349 print 'pass_stmt' # 'pass'
350 pass
352 print 'flow_stmt' # break_stmt | continue_stmt | return_stmt | raise_stmt
353 # Tested below
355 print 'break_stmt' # 'break'
356 while 1: break
358 print 'continue_stmt' # 'continue'
359 i = 1
360 while i: i = 0; continue
362 msg = ""
363 while not msg:
364 msg = "continue + try/except ok"
365 try:
366 continue
367 msg = "continue failed to continue inside try"
368 except:
369 msg = "continue inside try called except block"
370 print msg
372 msg = ""
373 while not msg:
374 msg = "finally block not called"
375 try:
376 continue
377 finally:
378 msg = "continue + try/finally ok"
379 print msg
382 # This test warrants an explanation. It is a test specifically for SF bugs
383 # #463359 and #462937. The bug is that a 'break' statement executed or
384 # exception raised inside a try/except inside a loop, *after* a continue
385 # statement has been executed in that loop, will cause the wrong number of
386 # arguments to be popped off the stack and the instruction pointer reset to
387 # a very small number (usually 0.) Because of this, the following test
388 # *must* written as a function, and the tracking vars *must* be function
389 # arguments with default values. Otherwise, the test will loop and loop.
391 print "testing continue and break in try/except in loop"
392 def test_break_continue_loop(extra_burning_oil = 1, count=0):
393 big_hippo = 2
394 while big_hippo:
395 count += 1
396 try:
397 if extra_burning_oil and big_hippo == 1:
398 extra_burning_oil -= 1
399 break
400 big_hippo -= 1
401 continue
402 except:
403 raise
404 if count > 2 or big_hippo <> 1:
405 print "continue then break in try/except in loop broken!"
406 test_break_continue_loop()
408 print 'return_stmt' # 'return' [testlist]
409 def g1(): return
410 def g2(): return 1
411 g1()
412 x = g2()
414 print 'raise_stmt' # 'raise' test [',' test]
415 try: raise RuntimeError, 'just testing'
416 except RuntimeError: pass
417 try: raise KeyboardInterrupt
418 except KeyboardInterrupt: pass
420 print 'import_stmt' # 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*)
421 import sys
422 import time, sys
423 from time import time
424 from sys import *
425 from sys import path, argv
427 print 'global_stmt' # 'global' NAME (',' NAME)*
428 def f():
429 global a
430 global a, b
431 global one, two, three, four, five, six, seven, eight, nine, ten
433 print 'exec_stmt' # 'exec' expr ['in' expr [',' expr]]
434 def f():
435 z = None
436 del z
437 exec 'z=1+1\n'
438 if z != 2: raise TestFailed, 'exec \'z=1+1\'\\n'
439 del z
440 exec 'z=1+1'
441 if z != 2: raise TestFailed, 'exec \'z=1+1\''
442 z = None
443 del z
444 import types
445 if hasattr(types, "UnicodeType"):
446 exec r"""if 1:
447 exec u'z=1+1\n'
448 if z != 2: raise TestFailed, 'exec u\'z=1+1\'\\n'
449 del z
450 exec u'z=1+1'
451 if z != 2: raise TestFailed, 'exec u\'z=1+1\''
454 g = {}
455 exec 'z = 1' in g
456 if g.has_key('__builtins__'): del g['__builtins__']
457 if g != {'z': 1}: raise TestFailed, 'exec \'z = 1\' in g'
458 g = {}
459 l = {}
461 import warnings
462 warnings.filterwarnings("ignore", "global statement", module="<string>")
463 exec 'global a; a = 1; b = 2' in g, l
464 if g.has_key('__builtins__'): del g['__builtins__']
465 if l.has_key('__builtins__'): del l['__builtins__']
466 if (g, l) != ({'a':1}, {'b':2}): raise TestFailed, 'exec ... in g (%s), l (%s)' %(g,l)
469 print "assert_stmt" # assert_stmt: 'assert' test [',' test]
470 assert 1
471 assert 1, 1
472 assert lambda x:x
473 assert 1, lambda x:x+1
475 ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
476 # Tested below
478 print 'if_stmt' # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
479 if 1: pass
480 if 1: pass
481 else: pass
482 if 0: pass
483 elif 0: pass
484 if 0: pass
485 elif 0: pass
486 elif 0: pass
487 elif 0: pass
488 else: pass
490 print 'while_stmt' # 'while' test ':' suite ['else' ':' suite]
491 while 0: pass
492 while 0: pass
493 else: pass
495 print 'for_stmt' # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
496 for i in 1, 2, 3: pass
497 for i, j, k in (): pass
498 else: pass
499 class Squares:
500 def __init__(self, max):
501 self.max = max
502 self.sofar = []
503 def __len__(self): return len(self.sofar)
504 def __getitem__(self, i):
505 if not 0 <= i < self.max: raise IndexError
506 n = len(self.sofar)
507 while n <= i:
508 self.sofar.append(n*n)
509 n = n+1
510 return self.sofar[i]
511 n = 0
512 for x in Squares(10): n = n+x
513 if n != 285: raise TestFailed, 'for over growing sequence'
515 print 'try_stmt'
516 ### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
517 ### | 'try' ':' suite 'finally' ':' suite
518 ### except_clause: 'except' [expr [',' expr]]
519 try:
521 except ZeroDivisionError:
522 pass
523 else:
524 pass
525 try: 1/0
526 except EOFError: pass
527 except TypeError, msg: pass
528 except RuntimeError, msg: pass
529 except: pass
530 else: pass
531 try: 1/0
532 except (EOFError, TypeError, ZeroDivisionError): pass
533 try: 1/0
534 except (EOFError, TypeError, ZeroDivisionError), msg: pass
535 try: pass
536 finally: pass
538 print 'suite' # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
539 if 1: pass
540 if 1:
541 pass
542 if 1:
546 pass
547 pass
549 pass
552 print 'test'
553 ### and_test ('or' and_test)*
554 ### and_test: not_test ('and' not_test)*
555 ### not_test: 'not' not_test | comparison
556 if not 1: pass
557 if 1 and 1: pass
558 if 1 or 1: pass
559 if not not not 1: pass
560 if not 1 and 1 and 1: pass
561 if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass
563 print 'comparison'
564 ### comparison: expr (comp_op expr)*
565 ### comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
566 if 1: pass
567 x = (1 == 1)
568 if 1 == 1: pass
569 if 1 != 1: pass
570 if 1 <> 1: pass
571 if 1 < 1: pass
572 if 1 > 1: pass
573 if 1 <= 1: pass
574 if 1 >= 1: pass
575 if 1 is 1: pass
576 if 1 is not 1: pass
577 if 1 in (): pass
578 if 1 not in (): pass
579 if 1 < 1 > 1 == 1 >= 1 <= 1 <> 1 != 1 in 1 not in 1 is 1 is not 1: pass
581 print 'binary mask ops'
582 x = 1 & 1
583 x = 1 ^ 1
584 x = 1 | 1
586 print 'shift ops'
587 x = 1 << 1
588 x = 1 >> 1
589 x = 1 << 1 >> 1
591 print 'additive ops'
592 x = 1
593 x = 1 + 1
594 x = 1 - 1 - 1
595 x = 1 - 1 + 1 - 1 + 1
597 print 'multiplicative ops'
598 x = 1 * 1
599 x = 1 / 1
600 x = 1 % 1
601 x = 1 / 1 * 1 % 1
603 print 'unary ops'
604 x = +1
605 x = -1
606 x = ~1
607 x = ~1 ^ 1 & 1 | 1 & 1 ^ -1
608 x = -1*1/1 + 1*1 - ---1*1
610 print 'selectors'
611 ### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
612 ### subscript: expr | [expr] ':' [expr]
613 f1()
614 f2(1)
615 f2(1,)
616 f3(1, 2)
617 f3(1, 2,)
618 f4(1, (2, (3, 4)))
619 v0()
620 v0(1)
621 v0(1,)
622 v0(1,2)
623 v0(1,2,3,4,5,6,7,8,9,0)
624 v1(1)
625 v1(1,)
626 v1(1,2)
627 v1(1,2,3)
628 v1(1,2,3,4,5,6,7,8,9,0)
629 v2(1,2)
630 v2(1,2,3)
631 v2(1,2,3,4)
632 v2(1,2,3,4,5,6,7,8,9,0)
633 v3(1,(2,3))
634 v3(1,(2,3),4)
635 v3(1,(2,3),4,5,6,7,8,9,0)
636 print
637 import sys, time
638 c = sys.path[0]
639 x = time.time()
640 x = sys.modules['time'].time()
641 a = '01234'
642 c = a[0]
643 c = a[-1]
644 s = a[0:5]
645 s = a[:5]
646 s = a[0:]
647 s = a[:]
648 s = a[-5:]
649 s = a[:-1]
650 s = a[-4:-3]
652 print 'atoms'
653 ### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING
654 ### dictmaker: test ':' test (',' test ':' test)* [',']
656 x = (1)
657 x = (1 or 2 or 3)
658 x = (1 or 2 or 3, 2, 3)
660 x = []
661 x = [1]
662 x = [1 or 2 or 3]
663 x = [1 or 2 or 3, 2, 3]
664 x = []
666 x = {}
667 x = {'one': 1}
668 x = {'one': 1,}
669 x = {'one' or 'two': 1 or 2}
670 x = {'one': 1, 'two': 2}
671 x = {'one': 1, 'two': 2,}
672 x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6}
674 x = `x`
675 x = `1 or 2 or 3`
676 x = x
677 x = 'x'
678 x = 123
680 ### exprlist: expr (',' expr)* [',']
681 ### testlist: test (',' test)* [',']
682 # These have been exercised enough above
684 print 'classdef' # 'class' NAME ['(' testlist ')'] ':' suite
685 class B: pass
686 class C1(B): pass
687 class C2(B): pass
688 class D(C1, C2, B): pass
689 class C:
690 def meth1(self): pass
691 def meth2(self, arg): pass
692 def meth3(self, a1, a2): pass
694 # list comprehension tests
695 nums = [1, 2, 3, 4, 5]
696 strs = ["Apple", "Banana", "Coconut"]
697 spcs = [" Apple", " Banana ", "Coco nut "]
699 print [s.strip() for s in spcs]
700 print [3 * x for x in nums]
701 print [x for x in nums if x > 2]
702 print [(i, s) for i in nums for s in strs]
703 print [(i, s) for i in nums for s in [f for f in strs if "n" in f]]
705 def test_in_func(l):
706 return [None < x < 3 for x in l if x > 2]
708 print test_in_func(nums)
710 def test_nested_front():
711 print [[y for y in [x, x + 1]] for x in [1,3,5]]
713 test_nested_front()
715 check_syntax("[i, s for i in nums for s in strs]")
716 check_syntax("[x if y]")
718 suppliers = [
719 (1, "Boeing"),
720 (2, "Ford"),
721 (3, "Macdonalds")
724 parts = [
725 (10, "Airliner"),
726 (20, "Engine"),
727 (30, "Cheeseburger")
730 suppart = [
731 (1, 10), (1, 20), (2, 20), (3, 30)
734 print [
735 (sname, pname)
736 for (sno, sname) in suppliers
737 for (pno, pname) in parts
738 for (sp_sno, sp_pno) in suppart
739 if sno == sp_sno and pno == sp_pno