Python-checkins
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
January 2021
- 1 participants
- 287 discussions
bpo-42927: Update the What's new entry for LOAD_ATTR optimizations (GH-24383)
by pablogsal 31 Jan '21
by pablogsal 31 Jan '21
31 Jan '21
https://github.com/python/cpython/commit/a776da90b8f2a1342f4f9bfd23a62cea9a…
commit: a776da90b8f2a1342f4f9bfd23a62cea9a0497c6
branch: master
author: Pablo Galindo <Pablogsal(a)gmail.com>
committer: pablogsal <Pablogsal(a)gmail.com>
date: 2021-01-31T22:55:48Z
summary:
bpo-42927: Update the What's new entry for LOAD_ATTR optimizations (GH-24383)
files:
M Doc/whatsnew/3.10.rst
diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst
index cf7d1e80758a0..3dccb7c50019b 100644
--- a/Doc/whatsnew/3.10.rst
+++ b/Doc/whatsnew/3.10.rst
@@ -556,10 +556,10 @@ Optimizations
(Contributed by Victor Stinner in :issue:`41006`.)
* The ``LOAD_ATTR`` instruction now uses new "per opcode cache" mechanism. It
- is about 36% faster now. This makes optimized ``LOAD_ATTR`` instructions the
- current most performance attribute access method (faster than slots).
- (Contributed by Pablo Galindo and Yury Selivanov in :issue:`42093`, based on
- ideas implemented originally in PyPy and MicroPython.)
+ is about 36% faster now for regular attributes and 44% faster for slots.
+ (Contributed by Pablo Galindo and Yury Selivanov in :issue:`42093` and Guido
+ van Rossum in :issue:`42927`, based on ideas implemented originally in PyPy
+ and MicroPython.)
* When building Python with ``--enable-optimizations`` now
``-fno-semantic-interposition`` is added to both the compile and link line.
1
0
bpo-43017: Improve error message for unparenthesised tuples in comprehensions (GH24314)
by pablogsal 31 Jan '21
by pablogsal 31 Jan '21
31 Jan '21
https://github.com/python/cpython/commit/835f14ff8eec10b3d96f821a1eb46a986e…
commit: 835f14ff8eec10b3d96f821a1eb46a986e00c690
branch: master
author: Pablo Galindo <Pablogsal(a)gmail.com>
committer: pablogsal <Pablogsal(a)gmail.com>
date: 2021-01-31T22:52:56Z
summary:
bpo-43017: Improve error message for unparenthesised tuples in comprehensions (GH24314)
files:
A Misc/NEWS.d/next/Core and Builtins/2021-01-24-18-02-05.bpo-43017.emEcXX.rst
M Grammar/python.gram
M Lib/test/test_named_expressions.py
M Lib/test/test_syntax.py
M Parser/parser.c
diff --git a/Grammar/python.gram b/Grammar/python.gram
index 05ddce520fbae..e72158be22380 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -507,7 +507,7 @@ strings[expr_ty] (memo): a=STRING+ { _PyPegen_concatenate_strings(p, a) }
list[expr_ty]:
| '[' a=[star_named_expressions] ']' { _Py_List(a, Load, EXTRA) }
listcomp[expr_ty]:
- | '[' a=named_expression ~ b=for_if_clauses ']' { _Py_ListComp(a, b, EXTRA) }
+ | '[' a=named_expression b=for_if_clauses ']' { _Py_ListComp(a, b, EXTRA) }
| invalid_comprehension
tuple[expr_ty]:
| '(' a=[y=star_named_expression ',' z=[star_named_expressions] { _PyPegen_seq_insert_in_front(p, y, z) } ] ')' {
@@ -516,11 +516,11 @@ group[expr_ty]:
| '(' a=(yield_expr | named_expression) ')' { a }
| invalid_group
genexp[expr_ty]:
- | '(' a=named_expression ~ b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
+ | '(' a=named_expression b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
| invalid_comprehension
set[expr_ty]: '{' a=star_named_expressions '}' { _Py_Set(a, EXTRA) }
setcomp[expr_ty]:
- | '{' a=named_expression ~ b=for_if_clauses '}' { _Py_SetComp(a, b, EXTRA) }
+ | '{' a=named_expression b=for_if_clauses '}' { _Py_SetComp(a, b, EXTRA) }
| invalid_comprehension
dict[expr_ty]:
| '{' a=[double_starred_kvpairs] '}' {
@@ -692,6 +692,8 @@ invalid_primary:
invalid_comprehension:
| ('[' | '(' | '{') a=starred_expression for_if_clauses {
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") }
+ | ('[' | '{') a=star_named_expression ',' [star_named_expressions] {
+ RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "did you forget parentheses around the comprehension target?") }
invalid_dict_comprehension:
| '{' a='**' bitwise_or for_if_clauses '}' {
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "dict unpacking cannot be used in dict comprehension") }
diff --git a/Lib/test/test_named_expressions.py b/Lib/test/test_named_expressions.py
index 5908f1210857a..20ac2e699f0c3 100644
--- a/Lib/test/test_named_expressions.py
+++ b/Lib/test/test_named_expressions.py
@@ -101,7 +101,8 @@ def test_named_expression_invalid_16(self):
def test_named_expression_invalid_17(self):
code = "[i := 0, j := 1 for i, j in [(1, 2), (3, 4)]]"
- with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
+ with self.assertRaisesRegex(SyntaxError,
+ "did you forget parentheses around the comprehension target?"):
exec(code, {}, {})
def test_named_expression_invalid_in_class_body(self):
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index c8d191df4cc49..604474f1e8387 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -235,6 +235,21 @@
Traceback (most recent call last):
SyntaxError: invalid syntax
+Comprehensions creating tuples without parentheses
+should produce a specialized error message:
+
+>>> [x,y for x,y in range(100)]
+Traceback (most recent call last):
+SyntaxError: did you forget parentheses around the comprehension target?
+
+>>> {x,y for x,y in range(100)}
+Traceback (most recent call last):
+SyntaxError: did you forget parentheses around the comprehension target?
+
+>>> {x,y: None for x,y in range(100)}
+Traceback (most recent call last):
+SyntaxError: did you forget parentheses around the comprehension target?
+
From compiler_complex_args():
>>> def f(None=1):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-01-24-18-02-05.bpo-43017.emEcXX.rst b/Misc/NEWS.d/next/Core and Builtins/2021-01-24-18-02-05.bpo-43017.emEcXX.rst
new file mode 100644
index 0000000000000..a809f5cbb1de1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-01-24-18-02-05.bpo-43017.emEcXX.rst
@@ -0,0 +1,2 @@
+Improve error message in the parser when using un-parenthesised tuples in
+comprehensions. Patch by Pablo Galindo.
diff --git a/Parser/parser.c b/Parser/parser.c
index f7794e715b918..d333accf71cca 100644
--- a/Parser/parser.c
+++ b/Parser/parser.c
@@ -362,11 +362,11 @@ static KeywordToken *reserved_keywords[] = {
#define _loop0_129_type 1293
#define _tmp_130_type 1294
#define _tmp_131_type 1295
-#define _loop0_132_type 1296
-#define _loop1_133_type 1297
-#define _loop0_134_type 1298
-#define _loop1_135_type 1299
-#define _tmp_136_type 1300
+#define _tmp_132_type 1296
+#define _loop0_133_type 1297
+#define _loop1_134_type 1298
+#define _loop0_135_type 1299
+#define _loop1_136_type 1300
#define _tmp_137_type 1301
#define _tmp_138_type 1302
#define _tmp_139_type 1303
@@ -385,6 +385,7 @@ static KeywordToken *reserved_keywords[] = {
#define _tmp_152_type 1316
#define _tmp_153_type 1317
#define _tmp_154_type 1318
+#define _tmp_155_type 1319
static mod_ty file_rule(Parser *p);
static mod_ty interactive_rule(Parser *p);
@@ -682,11 +683,11 @@ static asdl_seq *_loop0_128_rule(Parser *p);
static asdl_seq *_loop0_129_rule(Parser *p);
static void *_tmp_130_rule(Parser *p);
static void *_tmp_131_rule(Parser *p);
-static asdl_seq *_loop0_132_rule(Parser *p);
-static asdl_seq *_loop1_133_rule(Parser *p);
-static asdl_seq *_loop0_134_rule(Parser *p);
-static asdl_seq *_loop1_135_rule(Parser *p);
-static void *_tmp_136_rule(Parser *p);
+static void *_tmp_132_rule(Parser *p);
+static asdl_seq *_loop0_133_rule(Parser *p);
+static asdl_seq *_loop1_134_rule(Parser *p);
+static asdl_seq *_loop0_135_rule(Parser *p);
+static asdl_seq *_loop1_136_rule(Parser *p);
static void *_tmp_137_rule(Parser *p);
static void *_tmp_138_rule(Parser *p);
static void *_tmp_139_rule(Parser *p);
@@ -705,6 +706,7 @@ static void *_tmp_151_rule(Parser *p);
static void *_tmp_152_rule(Parser *p);
static void *_tmp_153_rule(Parser *p);
static void *_tmp_154_rule(Parser *p);
+static void *_tmp_155_rule(Parser *p);
// file: statements? $
@@ -11089,7 +11091,7 @@ list_rule(Parser *p)
return _res;
}
-// listcomp: '[' named_expression ~ for_if_clauses ']' | invalid_comprehension
+// listcomp: '[' named_expression for_if_clauses ']' | invalid_comprehension
static expr_ty
listcomp_rule(Parser *p)
{
@@ -11109,13 +11111,12 @@ listcomp_rule(Parser *p)
UNUSED(_start_lineno); // Only used by EXTRA macro
int _start_col_offset = p->tokens[_mark]->col_offset;
UNUSED(_start_col_offset); // Only used by EXTRA macro
- { // '[' named_expression ~ for_if_clauses ']'
+ { // '[' named_expression for_if_clauses ']'
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' named_expression ~ for_if_clauses ']'"));
- int _cut_var = 0;
+ D(fprintf(stderr, "%*c> listcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'"));
Token * _literal;
Token * _literal_1;
expr_ty a;
@@ -11125,14 +11126,12 @@ listcomp_rule(Parser *p)
&&
(a = named_expression_rule(p)) // named_expression
&&
- (_cut_var = 1)
- &&
(b = for_if_clauses_rule(p)) // for_if_clauses
&&
(_literal_1 = _PyPegen_expect_token(p, 10)) // token=']'
)
{
- D(fprintf(stderr, "%*c+ listcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' named_expression ~ for_if_clauses ']'"));
+ D(fprintf(stderr, "%*c+ listcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' named_expression for_if_clauses ']'"));
Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
if (_token == NULL) {
D(p->level--);
@@ -11152,11 +11151,7 @@ listcomp_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s listcomp[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'[' named_expression ~ for_if_clauses ']'"));
- if (_cut_var) {
- D(p->level--);
- return NULL;
- }
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'[' named_expression for_if_clauses ']'"));
}
if (p->call_invalid_rules) { // invalid_comprehension
if (p->error_indicator) {
@@ -11314,7 +11309,7 @@ group_rule(Parser *p)
return _res;
}
-// genexp: '(' named_expression ~ for_if_clauses ')' | invalid_comprehension
+// genexp: '(' named_expression for_if_clauses ')' | invalid_comprehension
static expr_ty
genexp_rule(Parser *p)
{
@@ -11334,13 +11329,12 @@ genexp_rule(Parser *p)
UNUSED(_start_lineno); // Only used by EXTRA macro
int _start_col_offset = p->tokens[_mark]->col_offset;
UNUSED(_start_col_offset); // Only used by EXTRA macro
- { // '(' named_expression ~ for_if_clauses ')'
+ { // '(' named_expression for_if_clauses ')'
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
- int _cut_var = 0;
+ D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' named_expression for_if_clauses ')'"));
Token * _literal;
Token * _literal_1;
expr_ty a;
@@ -11350,14 +11344,12 @@ genexp_rule(Parser *p)
&&
(a = named_expression_rule(p)) // named_expression
&&
- (_cut_var = 1)
- &&
(b = for_if_clauses_rule(p)) // for_if_clauses
&&
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
+ D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' named_expression for_if_clauses ')'"));
Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
if (_token == NULL) {
D(p->level--);
@@ -11377,11 +11369,7 @@ genexp_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
- if (_cut_var) {
- D(p->level--);
- return NULL;
- }
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' named_expression for_if_clauses ')'"));
}
if (p->call_invalid_rules) { // invalid_comprehension
if (p->error_indicator) {
@@ -11473,7 +11461,7 @@ set_rule(Parser *p)
return _res;
}
-// setcomp: '{' named_expression ~ for_if_clauses '}' | invalid_comprehension
+// setcomp: '{' named_expression for_if_clauses '}' | invalid_comprehension
static expr_ty
setcomp_rule(Parser *p)
{
@@ -11493,13 +11481,12 @@ setcomp_rule(Parser *p)
UNUSED(_start_lineno); // Only used by EXTRA macro
int _start_col_offset = p->tokens[_mark]->col_offset;
UNUSED(_start_col_offset); // Only used by EXTRA macro
- { // '{' named_expression ~ for_if_clauses '}'
+ { // '{' named_expression for_if_clauses '}'
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'"));
- int _cut_var = 0;
+ D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'"));
Token * _literal;
Token * _literal_1;
expr_ty a;
@@ -11509,14 +11496,12 @@ setcomp_rule(Parser *p)
&&
(a = named_expression_rule(p)) // named_expression
&&
- (_cut_var = 1)
- &&
(b = for_if_clauses_rule(p)) // for_if_clauses
&&
(_literal_1 = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'"));
+ D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' named_expression for_if_clauses '}'"));
Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
if (_token == NULL) {
D(p->level--);
@@ -11536,11 +11521,7 @@ setcomp_rule(Parser *p)
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s setcomp[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'"));
- if (_cut_var) {
- D(p->level--);
- return NULL;
- }
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' named_expression for_if_clauses '}'"));
}
if (p->call_invalid_rules) { // invalid_comprehension
if (p->error_indicator) {
@@ -15194,7 +15175,9 @@ invalid_primary_rule(Parser *p)
return _res;
}
-// invalid_comprehension: ('[' | '(' | '{') starred_expression for_if_clauses
+// invalid_comprehension:
+// | ('[' | '(' | '{') starred_expression for_if_clauses
+// | ('[' | '{') star_named_expression ',' star_named_expressions?
static void *
invalid_comprehension_rule(Parser *p)
{
@@ -15235,6 +15218,40 @@ invalid_comprehension_rule(Parser *p)
D(fprintf(stderr, "%*c%s invalid_comprehension[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses"));
}
+ { // ('[' | '{') star_named_expression ',' star_named_expressions?
+ if (p->error_indicator) {
+ D(p->level--);
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions?"));
+ Token * _literal;
+ void *_opt_var;
+ UNUSED(_opt_var); // Silence compiler warnings
+ void *_tmp_132_var;
+ expr_ty a;
+ if (
+ (_tmp_132_var = _tmp_132_rule(p)) // '[' | '{'
+ &&
+ (a = star_named_expression_rule(p)) // star_named_expression
+ &&
+ (_literal = _PyPegen_expect_token(p, 12)) // token=','
+ &&
+ (_opt_var = star_named_expressions_rule(p), 1) // star_named_expressions?
+ )
+ {
+ D(fprintf(stderr, "%*c+ invalid_comprehension[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions?"));
+ _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "did you forget parentheses around the comprehension target?" );
+ if (_res == NULL && PyErr_Occurred()) {
+ p->error_indicator = 1;
+ D(p->level--);
+ return NULL;
+ }
+ goto done;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s invalid_comprehension[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions?"));
+ }
_res = NULL;
done:
D(p->level--);
@@ -15311,11 +15328,11 @@ invalid_parameters_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* invalid_parameters_helper param_no_default"));
- asdl_seq * _loop0_132_var;
+ asdl_seq * _loop0_133_var;
void *invalid_parameters_helper_var;
arg_ty param_no_default_var;
if (
- (_loop0_132_var = _loop0_132_rule(p)) // param_no_default*
+ (_loop0_133_var = _loop0_133_rule(p)) // param_no_default*
&&
(invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper
&&
@@ -15382,13 +15399,13 @@ invalid_parameters_helper_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
- asdl_seq * _loop1_133_var;
+ asdl_seq * _loop1_134_var;
if (
- (_loop1_133_var = _loop1_133_rule(p)) // param_with_default+
+ (_loop1_134_var = _loop1_134_rule(p)) // param_with_default+
)
{
D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
- _res = _loop1_133_var;
+ _res = _loop1_134_var;
goto done;
}
p->mark = _mark;
@@ -15419,11 +15436,11 @@ invalid_lambda_parameters_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default"));
- asdl_seq * _loop0_134_var;
+ asdl_seq * _loop0_135_var;
void *invalid_lambda_parameters_helper_var;
arg_ty lambda_param_no_default_var;
if (
- (_loop0_134_var = _loop0_134_rule(p)) // lambda_param_no_default*
+ (_loop0_135_var = _loop0_135_rule(p)) // lambda_param_no_default*
&&
(invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper
&&
@@ -15492,13 +15509,13 @@ invalid_lambda_parameters_helper_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
- asdl_seq * _loop1_135_var;
+ asdl_seq * _loop1_136_var;
if (
- (_loop1_135_var = _loop1_135_rule(p)) // lambda_param_with_default+
+ (_loop1_136_var = _loop1_136_rule(p)) // lambda_param_with_default+
)
{
D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
- _res = _loop1_135_var;
+ _res = _loop1_136_var;
goto done;
}
p->mark = _mark;
@@ -15529,11 +15546,11 @@ invalid_star_etc_rule(Parser *p)
}
D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))"));
Token * _literal;
- void *_tmp_136_var;
+ void *_tmp_137_var;
if (
(_literal = _PyPegen_expect_token(p, 16)) // token='*'
&&
- (_tmp_136_var = _tmp_136_rule(p)) // ')' | ',' (')' | '**')
+ (_tmp_137_var = _tmp_137_rule(p)) // ')' | ',' (')' | '**')
)
{
D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))"));
@@ -15603,11 +15620,11 @@ invalid_lambda_star_etc_rule(Parser *p)
}
D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))"));
Token * _literal;
- void *_tmp_137_var;
+ void *_tmp_138_var;
if (
(_literal = _PyPegen_expect_token(p, 16)) // token='*'
&&
- (_tmp_137_var = _tmp_137_rule(p)) // ':' | ',' (':' | '**')
+ (_tmp_138_var = _tmp_138_rule(p)) // ':' | ',' (':' | '**')
)
{
D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))"));
@@ -17116,12 +17133,12 @@ _loop1_22_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_138_var;
+ void *_tmp_139_var;
while (
- (_tmp_138_var = _tmp_138_rule(p)) // star_targets '='
+ (_tmp_139_var = _tmp_139_rule(p)) // star_targets '='
)
{
- _res = _tmp_138_var;
+ _res = _tmp_139_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -17624,12 +17641,12 @@ _loop0_31_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
- void *_tmp_139_var;
+ void *_tmp_140_var;
while (
- (_tmp_139_var = _tmp_139_rule(p)) // '.' | '...'
+ (_tmp_140_var = _tmp_140_rule(p)) // '.' | '...'
)
{
- _res = _tmp_139_var;
+ _res = _tmp_140_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -17690,12 +17707,12 @@ _loop1_32_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
- void *_tmp_140_var;
+ void *_tmp_141_var;
while (
- (_tmp_140_var = _tmp_140_rule(p)) // '.' | '...'
+ (_tmp_141_var = _tmp_141_rule(p)) // '.' | '...'
)
{
- _res = _tmp_140_var;
+ _res = _tmp_141_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -19852,12 +19869,12 @@ _loop1_68_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)"));
- void *_tmp_141_var;
+ void *_tmp_142_var;
while (
- (_tmp_141_var = _tmp_141_rule(p)) // '@' named_expression NEWLINE
+ (_tmp_142_var = _tmp_142_rule(p)) // '@' named_expression NEWLINE
)
{
- _res = _tmp_141_var;
+ _res = _tmp_142_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -19970,12 +19987,12 @@ _loop1_70_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)"));
- void *_tmp_142_var;
+ void *_tmp_143_var;
while (
- (_tmp_142_var = _tmp_142_rule(p)) // ',' star_expression
+ (_tmp_143_var = _tmp_143_rule(p)) // ',' star_expression
)
{
- _res = _tmp_142_var;
+ _res = _tmp_143_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -20155,12 +20172,12 @@ _loop1_73_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)"));
- void *_tmp_143_var;
+ void *_tmp_144_var;
while (
- (_tmp_143_var = _tmp_143_rule(p)) // ',' expression
+ (_tmp_144_var = _tmp_144_rule(p)) // ',' expression
)
{
- _res = _tmp_143_var;
+ _res = _tmp_144_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -21185,12 +21202,12 @@ _loop1_88_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)"));
- void *_tmp_144_var;
+ void *_tmp_145_var;
while (
- (_tmp_144_var = _tmp_144_rule(p)) // 'or' conjunction
+ (_tmp_145_var = _tmp_145_rule(p)) // 'or' conjunction
)
{
- _res = _tmp_144_var;
+ _res = _tmp_145_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -21256,12 +21273,12 @@ _loop1_89_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)"));
- void *_tmp_145_var;
+ void *_tmp_146_var;
while (
- (_tmp_145_var = _tmp_145_rule(p)) // 'and' inversion
+ (_tmp_146_var = _tmp_146_rule(p)) // 'and' inversion
)
{
- _res = _tmp_145_var;
+ _res = _tmp_146_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -22177,12 +22194,12 @@ _loop0_104_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
- void *_tmp_146_var;
+ void *_tmp_147_var;
while (
- (_tmp_146_var = _tmp_146_rule(p)) // 'if' disjunction
+ (_tmp_147_var = _tmp_147_rule(p)) // 'if' disjunction
)
{
- _res = _tmp_146_var;
+ _res = _tmp_147_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -22243,12 +22260,12 @@ _loop0_105_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
- void *_tmp_147_var;
+ void *_tmp_148_var;
while (
- (_tmp_147_var = _tmp_147_rule(p)) // 'if' disjunction
+ (_tmp_148_var = _tmp_148_rule(p)) // 'if' disjunction
)
{
- _res = _tmp_147_var;
+ _res = _tmp_148_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -22314,7 +22331,7 @@ _loop0_107_rule(Parser *p)
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_148_rule(p)) // starred_expression | named_expression !'='
+ (elem = _tmp_149_rule(p)) // starred_expression | named_expression !'='
)
{
_res = elem;
@@ -22377,7 +22394,7 @@ _gather_106_rule(Parser *p)
void *elem;
asdl_seq * seq;
if (
- (elem = _tmp_148_rule(p)) // starred_expression | named_expression !'='
+ (elem = _tmp_149_rule(p)) // starred_expression | named_expression !'='
&&
(seq = _loop0_107_rule(p)) // _loop0_107
)
@@ -22923,12 +22940,12 @@ _loop0_117_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
- void *_tmp_149_var;
+ void *_tmp_150_var;
while (
- (_tmp_149_var = _tmp_149_rule(p)) // ',' star_target
+ (_tmp_150_var = _tmp_150_rule(p)) // ',' star_target
)
{
- _res = _tmp_149_var;
+ _res = _tmp_150_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -23103,12 +23120,12 @@ _loop1_120_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
- void *_tmp_150_var;
+ void *_tmp_151_var;
while (
- (_tmp_150_var = _tmp_150_rule(p)) // ',' star_target
+ (_tmp_151_var = _tmp_151_rule(p)) // ',' star_target
)
{
- _res = _tmp_150_var;
+ _res = _tmp_151_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -23564,12 +23581,12 @@ _loop0_128_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_151_var;
+ void *_tmp_152_var;
while (
- (_tmp_151_var = _tmp_151_rule(p)) // star_targets '='
+ (_tmp_152_var = _tmp_152_rule(p)) // star_targets '='
)
{
- _res = _tmp_151_var;
+ _res = _tmp_152_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -23630,12 +23647,12 @@ _loop0_129_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_152_var;
+ void *_tmp_153_var;
while (
- (_tmp_152_var = _tmp_152_rule(p)) // star_targets '='
+ (_tmp_153_var = _tmp_153_rule(p)) // star_targets '='
)
{
- _res = _tmp_152_var;
+ _res = _tmp_153_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
@@ -23798,9 +23815,64 @@ _tmp_131_rule(Parser *p)
return _res;
}
-// _loop0_132: param_no_default
+// _tmp_132: '[' | '{'
+static void *
+_tmp_132_rule(Parser *p)
+{
+ D(p->level++);
+ if (p->error_indicator) {
+ D(p->level--);
+ return NULL;
+ }
+ void * _res = NULL;
+ int _mark = p->mark;
+ { // '['
+ if (p->error_indicator) {
+ D(p->level--);
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['"));
+ Token * _literal;
+ if (
+ (_literal = _PyPegen_expect_token(p, 9)) // token='['
+ )
+ {
+ D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['"));
+ _res = _literal;
+ goto done;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['"));
+ }
+ { // '{'
+ if (p->error_indicator) {
+ D(p->level--);
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'"));
+ Token * _literal;
+ if (
+ (_literal = _PyPegen_expect_token(p, 25)) // token='{'
+ )
+ {
+ D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'"));
+ _res = _literal;
+ goto done;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'"));
+ }
+ _res = NULL;
+ done:
+ D(p->level--);
+ return _res;
+}
+
+// _loop0_133: param_no_default
static asdl_seq *
-_loop0_132_rule(Parser *p)
+_loop0_133_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -23824,7 +23896,7 @@ _loop0_132_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default"));
+ D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default"));
arg_ty param_no_default_var;
while (
(param_no_default_var = param_no_default_rule(p)) // param_no_default
@@ -23846,7 +23918,7 @@ _loop0_132_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
@@ -23859,14 +23931,14 @@ _loop0_132_rule(Parser *p)
}
for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_132_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_133: param_with_default
+// _loop1_134: param_with_default
static asdl_seq *
-_loop1_133_rule(Parser *p)
+_loop1_134_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -23890,7 +23962,7 @@ _loop1_133_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default"));
+ D(fprintf(stderr, "%*c> _loop1_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default"));
NameDefaultPair* param_with_default_var;
while (
(param_with_default_var = param_with_default_rule(p)) // param_with_default
@@ -23912,7 +23984,7 @@ _loop1_133_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_133[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_134[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default"));
}
if (_n == 0 || p->error_indicator) {
@@ -23930,14 +24002,14 @@ _loop1_133_rule(Parser *p)
}
for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_133_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_134_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_134: lambda_param_no_default
+// _loop0_135: lambda_param_no_default
static asdl_seq *
-_loop0_134_rule(Parser *p)
+_loop0_135_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -23961,7 +24033,7 @@ _loop0_134_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
@@ -23983,7 +24055,7 @@ _loop0_134_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena);
@@ -23996,14 +24068,14 @@ _loop0_134_rule(Parser *p)
}
for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_134_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_135_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_135: lambda_param_with_default
+// _loop1_136: lambda_param_with_default
static asdl_seq *
-_loop1_135_rule(Parser *p)
+_loop1_136_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24027,7 +24099,7 @@ _loop1_135_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop1_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
@@ -24049,7 +24121,7 @@ _loop1_135_rule(Parser *p)
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_135[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_136[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
if (_n == 0 || p->error_indicator) {
@@ -24067,14 +24139,14 @@ _loop1_135_rule(Parser *p)
}
for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_135_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_136_type, _seq);
D(p->level--);
return _seq;
}
-// _tmp_136: ')' | ',' (')' | '**')
+// _tmp_137: ')' | ',' (')' | '**')
static void *
-_tmp_136_rule(Parser *p)
+_tmp_137_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24088,18 +24160,18 @@ _tmp_136_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'"));
}
{ // ',' (')' | '**')
@@ -24107,21 +24179,21 @@ _tmp_136_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
+ D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
Token * _literal;
- void *_tmp_153_var;
+ void *_tmp_154_var;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_tmp_153_var = _tmp_153_rule(p)) // ')' | '**'
+ (_tmp_154_var = _tmp_154_rule(p)) // ')' | '**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
- _res = _PyPegen_dummy_name(p, _literal, _tmp_153_var);
+ D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
+ _res = _PyPegen_dummy_name(p, _literal, _tmp_154_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')"));
}
_res = NULL;
@@ -24130,9 +24202,9 @@ _tmp_136_rule(Parser *p)
return _res;
}
-// _tmp_137: ':' | ',' (':' | '**')
+// _tmp_138: ':' | ',' (':' | '**')
static void *
-_tmp_137_rule(Parser *p)
+_tmp_138_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24146,18 +24218,18 @@ _tmp_137_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // ',' (':' | '**')
@@ -24165,21 +24237,21 @@ _tmp_137_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
+ D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
Token * _literal;
- void *_tmp_154_var;
+ void *_tmp_155_var;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_tmp_154_var = _tmp_154_rule(p)) // ':' | '**'
+ (_tmp_155_var = _tmp_155_rule(p)) // ':' | '**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
- _res = _PyPegen_dummy_name(p, _literal, _tmp_154_var);
+ D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
+ _res = _PyPegen_dummy_name(p, _literal, _tmp_155_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')"));
}
_res = NULL;
@@ -24188,9 +24260,9 @@ _tmp_137_rule(Parser *p)
return _res;
}
-// _tmp_138: star_targets '='
+// _tmp_139: star_targets '='
static void *
-_tmp_138_rule(Parser *p)
+_tmp_139_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24204,7 +24276,7 @@ _tmp_138_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty z;
if (
@@ -24213,7 +24285,7 @@ _tmp_138_rule(Parser *p)
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24223,7 +24295,7 @@ _tmp_138_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
@@ -24232,9 +24304,9 @@ _tmp_138_rule(Parser *p)
return _res;
}
-// _tmp_139: '.' | '...'
+// _tmp_140: '.' | '...'
static void *
-_tmp_139_rule(Parser *p)
+_tmp_140_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24248,18 +24320,18 @@ _tmp_139_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 23)) // token='.'
)
{
- D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
}
{ // '...'
@@ -24267,18 +24339,18 @@ _tmp_139_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 52)) // token='...'
)
{
- D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
}
_res = NULL;
@@ -24287,9 +24359,9 @@ _tmp_139_rule(Parser *p)
return _res;
}
-// _tmp_140: '.' | '...'
+// _tmp_141: '.' | '...'
static void *
-_tmp_140_rule(Parser *p)
+_tmp_141_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24303,18 +24375,18 @@ _tmp_140_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 23)) // token='.'
)
{
- D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
}
{ // '...'
@@ -24322,18 +24394,18 @@ _tmp_140_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 52)) // token='...'
)
{
- D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
}
_res = NULL;
@@ -24342,9 +24414,9 @@ _tmp_140_rule(Parser *p)
return _res;
}
-// _tmp_141: '@' named_expression NEWLINE
+// _tmp_142: '@' named_expression NEWLINE
static void *
-_tmp_141_rule(Parser *p)
+_tmp_142_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24358,7 +24430,7 @@ _tmp_141_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+ D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
Token * _literal;
expr_ty f;
Token * newline_var;
@@ -24370,7 +24442,7 @@ _tmp_141_rule(Parser *p)
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
{
- D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+ D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
_res = f;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24380,7 +24452,7 @@ _tmp_141_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE"));
}
_res = NULL;
@@ -24389,9 +24461,9 @@ _tmp_141_rule(Parser *p)
return _res;
}
-// _tmp_142: ',' star_expression
+// _tmp_143: ',' star_expression
static void *
-_tmp_142_rule(Parser *p)
+_tmp_143_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24405,7 +24477,7 @@ _tmp_142_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+ D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
Token * _literal;
expr_ty c;
if (
@@ -24414,7 +24486,7 @@ _tmp_142_rule(Parser *p)
(c = star_expression_rule(p)) // star_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24424,7 +24496,7 @@ _tmp_142_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression"));
}
_res = NULL;
@@ -24433,9 +24505,9 @@ _tmp_142_rule(Parser *p)
return _res;
}
-// _tmp_143: ',' expression
+// _tmp_144: ',' expression
static void *
-_tmp_143_rule(Parser *p)
+_tmp_144_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24449,7 +24521,7 @@ _tmp_143_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
+ D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
Token * _literal;
expr_ty c;
if (
@@ -24458,7 +24530,7 @@ _tmp_143_rule(Parser *p)
(c = expression_rule(p)) // expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
+ D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24468,7 +24540,7 @@ _tmp_143_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression"));
}
_res = NULL;
@@ -24477,9 +24549,9 @@ _tmp_143_rule(Parser *p)
return _res;
}
-// _tmp_144: 'or' conjunction
+// _tmp_145: 'or' conjunction
static void *
-_tmp_144_rule(Parser *p)
+_tmp_145_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24493,7 +24565,7 @@ _tmp_144_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+ D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
Token * _keyword;
expr_ty c;
if (
@@ -24502,7 +24574,7 @@ _tmp_144_rule(Parser *p)
(c = conjunction_rule(p)) // conjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24512,7 +24584,7 @@ _tmp_144_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction"));
}
_res = NULL;
@@ -24521,9 +24593,9 @@ _tmp_144_rule(Parser *p)
return _res;
}
-// _tmp_145: 'and' inversion
+// _tmp_146: 'and' inversion
static void *
-_tmp_145_rule(Parser *p)
+_tmp_146_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24537,7 +24609,7 @@ _tmp_145_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+ D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
Token * _keyword;
expr_ty c;
if (
@@ -24546,7 +24618,7 @@ _tmp_145_rule(Parser *p)
(c = inversion_rule(p)) // inversion
)
{
- D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+ D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24556,7 +24628,7 @@ _tmp_145_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion"));
}
_res = NULL;
@@ -24565,9 +24637,9 @@ _tmp_145_rule(Parser *p)
return _res;
}
-// _tmp_146: 'if' disjunction
+// _tmp_147: 'if' disjunction
static void *
-_tmp_146_rule(Parser *p)
+_tmp_147_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24581,7 +24653,7 @@ _tmp_146_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
Token * _keyword;
expr_ty z;
if (
@@ -24590,7 +24662,7 @@ _tmp_146_rule(Parser *p)
(z = disjunction_rule(p)) // disjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24600,7 +24672,7 @@ _tmp_146_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
}
_res = NULL;
@@ -24609,9 +24681,9 @@ _tmp_146_rule(Parser *p)
return _res;
}
-// _tmp_147: 'if' disjunction
+// _tmp_148: 'if' disjunction
static void *
-_tmp_147_rule(Parser *p)
+_tmp_148_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24625,7 +24697,7 @@ _tmp_147_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
Token * _keyword;
expr_ty z;
if (
@@ -24634,7 +24706,7 @@ _tmp_147_rule(Parser *p)
(z = disjunction_rule(p)) // disjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24644,7 +24716,7 @@ _tmp_147_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
}
_res = NULL;
@@ -24653,9 +24725,9 @@ _tmp_147_rule(Parser *p)
return _res;
}
-// _tmp_148: starred_expression | named_expression !'='
+// _tmp_149: starred_expression | named_expression !'='
static void *
-_tmp_148_rule(Parser *p)
+_tmp_149_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24669,18 +24741,18 @@ _tmp_148_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
expr_ty starred_expression_var;
if (
(starred_expression_var = starred_expression_rule(p)) // starred_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
_res = starred_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression"));
}
{ // named_expression !'='
@@ -24688,7 +24760,7 @@ _tmp_148_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
+ D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
expr_ty named_expression_var;
if (
(named_expression_var = named_expression_rule(p)) // named_expression
@@ -24696,12 +24768,12 @@ _tmp_148_rule(Parser *p)
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
+ D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
_res = named_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression !'='"));
}
_res = NULL;
@@ -24710,9 +24782,9 @@ _tmp_148_rule(Parser *p)
return _res;
}
-// _tmp_149: ',' star_target
+// _tmp_150: ',' star_target
static void *
-_tmp_149_rule(Parser *p)
+_tmp_150_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24726,7 +24798,7 @@ _tmp_149_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
Token * _literal;
expr_ty c;
if (
@@ -24735,7 +24807,7 @@ _tmp_149_rule(Parser *p)
(c = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24745,7 +24817,7 @@ _tmp_149_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
}
_res = NULL;
@@ -24754,9 +24826,9 @@ _tmp_149_rule(Parser *p)
return _res;
}
-// _tmp_150: ',' star_target
+// _tmp_151: ',' star_target
static void *
-_tmp_150_rule(Parser *p)
+_tmp_151_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24770,7 +24842,7 @@ _tmp_150_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
Token * _literal;
expr_ty c;
if (
@@ -24779,7 +24851,7 @@ _tmp_150_rule(Parser *p)
(c = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
@@ -24789,7 +24861,7 @@ _tmp_150_rule(Parser *p)
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
}
_res = NULL;
@@ -24798,9 +24870,9 @@ _tmp_150_rule(Parser *p)
return _res;
}
-// _tmp_151: star_targets '='
+// _tmp_152: star_targets '='
static void *
-_tmp_151_rule(Parser *p)
+_tmp_152_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24814,7 +24886,7 @@ _tmp_151_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty star_targets_var;
if (
@@ -24823,12 +24895,12 @@ _tmp_151_rule(Parser *p)
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = _PyPegen_dummy_name(p, star_targets_var, _literal);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
@@ -24837,9 +24909,9 @@ _tmp_151_rule(Parser *p)
return _res;
}
-// _tmp_152: star_targets '='
+// _tmp_153: star_targets '='
static void *
-_tmp_152_rule(Parser *p)
+_tmp_153_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24853,7 +24925,7 @@ _tmp_152_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty star_targets_var;
if (
@@ -24862,12 +24934,12 @@ _tmp_152_rule(Parser *p)
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = _PyPegen_dummy_name(p, star_targets_var, _literal);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
@@ -24876,9 +24948,9 @@ _tmp_152_rule(Parser *p)
return _res;
}
-// _tmp_153: ')' | '**'
+// _tmp_154: ')' | '**'
static void *
-_tmp_153_rule(Parser *p)
+_tmp_154_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24892,18 +24964,18 @@ _tmp_153_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'"));
}
{ // '**'
@@ -24911,18 +24983,18 @@ _tmp_153_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 35)) // token='**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
}
_res = NULL;
@@ -24931,9 +25003,9 @@ _tmp_153_rule(Parser *p)
return _res;
}
-// _tmp_154: ':' | '**'
+// _tmp_155: ':' | '**'
static void *
-_tmp_154_rule(Parser *p)
+_tmp_155_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
@@ -24947,18 +25019,18 @@ _tmp_154_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // '**'
@@ -24966,18 +25038,18 @@ _tmp_154_rule(Parser *p)
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 35)) // token='**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
}
_res = NULL;
1
0
bpo-42986: Fix parser crash when reporting syntax errors in f-string with newlines (GH-24279)
by pablogsal 31 Jan '21
by pablogsal 31 Jan '21
31 Jan '21
https://github.com/python/cpython/commit/40901518167c66abc1ebc5b71c5b86d733…
commit: 40901518167c66abc1ebc5b71c5b86d733cfa154
branch: master
author: Pablo Galindo <Pablogsal(a)gmail.com>
committer: pablogsal <Pablogsal(a)gmail.com>
date: 2021-01-31T22:48:23Z
summary:
bpo-42986: Fix parser crash when reporting syntax errors in f-string with newlines (GH-24279)
files:
A Misc/NEWS.d/next/Core and Builtins/2021-01-20-23-44-15.bpo-42986.sWoaGf.rst
M Lib/test/test_fstring.py
M Parser/pegen.c
diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py
index 7ca1512ebbf1b..d7143d154a1bc 100644
--- a/Lib/test/test_fstring.py
+++ b/Lib/test/test_fstring.py
@@ -664,6 +664,9 @@ def test_parens_in_expressions(self):
self.assertAllRaise(SyntaxError, 'unterminated string literal',
["f'{\n}'",
])
+ def test_newlines_before_syntax_error(self):
+ self.assertAllRaise(SyntaxError, "invalid syntax",
+ ["f'{.}'", "\nf'{.}'", "\n\nf'{.}'"])
def test_backslashes_in_string_part(self):
self.assertEqual(f'\t', '\t')
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-01-20-23-44-15.bpo-42986.sWoaGf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-01-20-23-44-15.bpo-42986.sWoaGf.rst
new file mode 100644
index 0000000000000..6e4ed60bf224d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-01-20-23-44-15.bpo-42986.sWoaGf.rst
@@ -0,0 +1,2 @@
+Fix parser crash when reporting syntax errors in f-string with newlines.
+Patch by Pablo Galindo.
diff --git a/Parser/pegen.c b/Parser/pegen.c
index 0e7f86bc99e45..2554273877f78 100644
--- a/Parser/pegen.c
+++ b/Parser/pegen.c
@@ -454,7 +454,7 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
does not physically exist */
assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF);
- if (p->tok->lineno == lineno) {
+ if (p->tok->lineno <= lineno) {
Py_ssize_t size = p->tok->inp - p->tok->buf;
error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace");
}
1
0
31 Jan '21
https://github.com/python/cpython/commit/a1e9a1e120a11c563e166c15721169184c…
commit: a1e9a1e120a11c563e166c15721169184c802f8b
branch: master
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2021-01-31T23:21:55+02:00
summary:
bpo-43016: Fix test_curses on platform without cursesw (GH-24405)
files:
M Lib/test/test_curses.py
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index 29286bce99e89..a9f7001d39f08 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -240,13 +240,21 @@ def test_refresh_control(self):
def test_output_character(self):
stdscr = self.stdscr
+ encoding = stdscr.encoding
# addch()
stdscr.refresh()
stdscr.move(0, 0)
stdscr.addch('A')
stdscr.addch(b'A')
stdscr.addch(65)
- stdscr.addch('\u20ac')
+ c = '\u20ac'
+ try:
+ stdscr.addch(c)
+ except UnicodeEncodeError:
+ self.assertRaises(UnicodeEncodeError, c.encode, encoding)
+ except OverflowError:
+ encoded = c.encode(encoding)
+ self.assertNotEqual(len(encoded), 1, repr(encoded))
stdscr.addch('A', curses.A_BOLD)
stdscr.addch(1, 2, 'A')
stdscr.addch(2, 3, 'A', curses.A_BOLD)
@@ -258,19 +266,25 @@ def test_output_character(self):
stdscr.echochar('A')
stdscr.echochar(b'A')
stdscr.echochar(65)
- self.assertRaises(OverflowError, stdscr.echochar, '\u20ac')
+ with self.assertRaises((UnicodeEncodeError, OverflowError)):
+ stdscr.echochar('\u20ac')
stdscr.echochar('A', curses.A_BOLD)
self.assertIs(stdscr.is_wintouched(), False)
def test_output_string(self):
stdscr = self.stdscr
+ encoding = stdscr.encoding
# addstr()/insstr()
for func in [stdscr.addstr, stdscr.insstr]:
with self.subTest(func.__qualname__):
stdscr.move(0, 0)
func('abcd')
func(b'abcd')
- func('àßçđ')
+ s = 'àßçđ'
+ try:
+ func(s)
+ except UnicodeEncodeError:
+ self.assertRaises(UnicodeEncodeError, s.encode, encoding)
func('abcd', curses.A_BOLD)
func(1, 2, 'abcd')
func(2, 3, 'abcd', curses.A_BOLD)
@@ -281,7 +295,11 @@ def test_output_string(self):
stdscr.move(0, 0)
func('1234', 3)
func(b'1234', 3)
- func('\u0661\u0662\u0663\u0664', 3)
+ s = '\u0661\u0662\u0663\u0664'
+ try:
+ func(s, 3)
+ except UnicodeEncodeError:
+ self.assertRaises(UnicodeEncodeError, s.encode, encoding)
func('1234', 5)
func('1234', 3, curses.A_BOLD)
func(1, 2, '1234', 3)
@@ -471,7 +489,7 @@ def test_background(self):
win = curses.newwin(5, 15, 5, 2)
win.addstr(0, 0, 'Lorem ipsum')
- self.assertEqual(win.getbkgd(), 0)
+ self.assertIn(win.getbkgd(), (0, 32))
# bkgdset()
win.bkgdset('_')
1
0
[3.9] bpo-41604: Don't decrement the reference count of the previous user_ptr when set_panel_usertpr fails (GH-21933). (GH-24403)
by miss-islington 31 Jan '21
by miss-islington 31 Jan '21
31 Jan '21
https://github.com/python/cpython/commit/931263baab62b1c3fa7647e45ec6ee6ef4…
commit: 931263baab62b1c3fa7647e45ec6ee6ef4409e7c
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: miss-islington <31488909+miss-islington(a)users.noreply.github.com>
date: 2021-01-31T12:51:23-08:00
summary:
[3.9] bpo-41604: Don't decrement the reference count of the previous user_ptr when set_panel_usertpr fails (GH-21933). (GH-24403)
(cherry picked from commit 3243e8a4b4b4cf321f9b28335d565742a34b1976)
Co-authored-by: Anonymous Maarten <madebr(a)users.noreply.github.com>
(cherry picked from commit 3c8d6934436e20163be802f5239c5b4e4925eeec)
Co-authored-by: Serhiy Storchaka <storchaka(a)gmail.com>
files:
A Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
M Modules/_curses_panel.c
diff --git a/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst b/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
new file mode 100644
index 0000000000000..0f9794cbdb321
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
@@ -0,0 +1,2 @@
+Don't decrement the reference count of the previous user_ptr when
+set_panel_userptr fails.
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index 53849e3a29cc0..d22e2adf89c83 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -433,7 +433,9 @@ _curses_panel_panel_set_userptr(PyCursesPanelObject *self, PyObject *obj)
/* In case of an ncurses error, decref the new object again */
Py_DECREF(obj);
}
- Py_XDECREF(oldobj);
+ else {
+ Py_XDECREF(oldobj);
+ }
return PyCursesCheckERR(rc, "set_panel_userptr");
}
1
0
[3.9] bpo-41604: Don't decrement the reference count of the previous user_ptr when set_panel_usertpr fails (GH-21933). (GH-24403)
by serhiy-storchaka 31 Jan '21
by serhiy-storchaka 31 Jan '21
31 Jan '21
https://github.com/python/cpython/commit/3c8d6934436e20163be802f5239c5b4e49…
commit: 3c8d6934436e20163be802f5239c5b4e4925eeec
branch: 3.9
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2021-01-31T21:44:31+02:00
summary:
[3.9] bpo-41604: Don't decrement the reference count of the previous user_ptr when set_panel_usertpr fails (GH-21933). (GH-24403)
(cherry picked from commit 3243e8a4b4b4cf321f9b28335d565742a34b1976)
Co-authored-by: Anonymous Maarten <madebr(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
M Modules/_curses_panel.c
diff --git a/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst b/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
new file mode 100644
index 0000000000000..0f9794cbdb321
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
@@ -0,0 +1,2 @@
+Don't decrement the reference count of the previous user_ptr when
+set_panel_userptr fails.
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index f124803493d88..4f026794e3417 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -440,7 +440,9 @@ _curses_panel_panel_set_userptr(PyCursesPanelObject *self, PyObject *obj)
/* In case of an ncurses error, decref the new object again */
Py_DECREF(obj);
}
- Py_XDECREF(oldobj);
+ else {
+ Py_XDECREF(oldobj);
+ }
return PyCursesCheckERR(rc, "set_panel_userptr");
}
1
0
bpo-41604: Don't decrement the reference count of the previous user_ptr when set_panel_usertpr fails (GH-21933)
by serhiy-storchaka 31 Jan '21
by serhiy-storchaka 31 Jan '21
31 Jan '21
https://github.com/python/cpython/commit/3243e8a4b4b4cf321f9b28335d565742a3…
commit: 3243e8a4b4b4cf321f9b28335d565742a34b1976
branch: master
author: Anonymous Maarten <madebr(a)users.noreply.github.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2021-01-31T19:55:15+02:00
summary:
bpo-41604: Don't decrement the reference count of the previous user_ptr when set_panel_usertpr fails (GH-21933)
files:
A Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
M Modules/_curses_panel.c
diff --git a/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst b/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
new file mode 100644
index 0000000000000..0f9794cbdb321
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-08-21-15-24-14.bpo-41604.rTXleO.rst
@@ -0,0 +1,2 @@
+Don't decrement the reference count of the previous user_ptr when
+set_panel_userptr fails.
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index d782ccd086798..94caf8c93bc8c 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -456,7 +456,9 @@ _curses_panel_panel_set_userptr_impl(PyCursesPanelObject *self,
/* In case of an ncurses error, decref the new object again */
Py_DECREF(obj);
}
- Py_XDECREF(oldobj);
+ else {
+ Py_XDECREF(oldobj);
+ }
_curses_panel_state *state = PyType_GetModuleState(cls);
return PyCursesCheckERR(state, rc, "set_panel_userptr");
1
0
[3.8] bpo-43016: Rewrite tests for curses (GH-24312). (GH-24399) (GH-24401)
by serhiy-storchaka 31 Jan '21
by serhiy-storchaka 31 Jan '21
31 Jan '21
https://github.com/python/cpython/commit/7ca947e93bff2b9d78312dc8ed8e0a2b7d…
commit: 7ca947e93bff2b9d78312dc8ed8e0a2b7d25d3f3
branch: 3.8
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2021-01-31T19:44:12+02:00
summary:
[3.8] bpo-43016: Rewrite tests for curses (GH-24312). (GH-24399) (GH-24401)
(cherry picked from commit d64fd4bb5bb4fd2e3277f39d3ad99b5a8d193e1b).
(cherry picked from commit e9d4960d15c5282904cf26e469ce7cee39f634f7)
files:
M Lib/test/test_curses.py
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index 8991134e08063..f47c9876eed88 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -1,18 +1,9 @@
-#
-# Test script for the curses module
-#
-# This script doesn't actually display anything very coherent. but it
-# does call (nearly) every method and function.
-#
-# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr()
-# Only called, not tested: getmouse(), ungetmouse()
-#
-
+import functools
+import inspect
import os
import string
import sys
import tempfile
-import functools
import unittest
from test.support import requires, import_module, verbose, SaveSignals
@@ -20,7 +11,6 @@
# Optionally test curses module. This currently requires that the
# 'curses' resource be given on the regrtest command line using the -u
# option. If not available, nothing after this line will be executed.
-import inspect
requires('curses')
# If either of these don't exist, skip the tests.
@@ -36,6 +26,17 @@ def requires_curses_func(name):
return unittest.skipUnless(hasattr(curses, name),
'requires curses.%s' % name)
+def requires_curses_window_meth(name):
+ def deco(test):
+ @functools.wraps(test)
+ def wrapped(self, *args, **kwargs):
+ if not hasattr(self.stdscr, name):
+ raise unittest.SkipTest('requires curses.window.%s' % name)
+ test(self, *args, **kwargs)
+ return wrapped
+ return deco
+
+
def requires_colors(test):
@functools.wraps(test)
def wrapped(self, *args, **kwargs):
@@ -110,208 +111,716 @@ def setUp(self):
curses.savetty()
self.addCleanup(curses.endwin)
self.addCleanup(curses.resetty)
+ self.stdscr.erase()
+
+ @requires_curses_func('filter')
+ def test_filter(self):
+ # TODO: Should be called before initscr() or newterm() are called.
+ # TODO: nofilter()
+ curses.filter()
+
+ @requires_curses_func('use_env')
+ def test_use_env(self):
+ # TODO: Should be called before initscr() or newterm() are called.
+ # TODO: use_tioctl()
+ curses.use_env(False)
+ curses.use_env(True)
+
+ def test_create_windows(self):
+ win = curses.newwin(5, 10)
+ self.assertEqual(win.getbegyx(), (0, 0))
+ self.assertEqual(win.getparyx(), (-1, -1))
+ self.assertEqual(win.getmaxyx(), (5, 10))
+
+ win = curses.newwin(10, 15, 2, 5)
+ self.assertEqual(win.getbegyx(), (2, 5))
+ self.assertEqual(win.getparyx(), (-1, -1))
+ self.assertEqual(win.getmaxyx(), (10, 15))
+
+ win2 = win.subwin(3, 7)
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (1, 2))
+ self.assertEqual(win2.getmaxyx(), (9, 13))
+
+ win2 = win.subwin(5, 10, 3, 7)
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (1, 2))
+ self.assertEqual(win2.getmaxyx(), (5, 10))
+
+ win3 = win.derwin(2, 3)
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 3))
+ self.assertEqual(win3.getmaxyx(), (8, 12))
+
+ win3 = win.derwin(6, 11, 2, 3)
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 3))
+ self.assertEqual(win3.getmaxyx(), (6, 11))
+
+ win.mvwin(0, 1)
+ self.assertEqual(win.getbegyx(), (0, 1))
+ self.assertEqual(win.getparyx(), (-1, -1))
+ self.assertEqual(win.getmaxyx(), (10, 15))
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (1, 2))
+ self.assertEqual(win2.getmaxyx(), (5, 10))
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 3))
+ self.assertEqual(win3.getmaxyx(), (6, 11))
+
+ win2.mvderwin(2, 1)
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (2, 1))
+ self.assertEqual(win2.getmaxyx(), (5, 10))
+
+ win3.mvderwin(2, 1)
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 1))
+ self.assertEqual(win3.getmaxyx(), (6, 11))
+
+ def test_move_cursor(self):
+ stdscr = self.stdscr
+ win = stdscr.subwin(10, 15, 2, 5)
+ stdscr.move(1, 2)
+ win.move(2, 4)
+ self.assertEqual(stdscr.getyx(), (1, 2))
+ self.assertEqual(win.getyx(), (2, 4))
+
+ win.cursyncup()
+ self.assertEqual(stdscr.getyx(), (4, 9))
- def test_window_funcs(self):
- "Test the methods of windows"
+ def test_refresh_control(self):
stdscr = self.stdscr
- win = curses.newwin(10,10)
- win = curses.newwin(5,5, 5,5)
- win2 = curses.newwin(15,15, 5,5)
-
- for meth in [stdscr.addch, stdscr.addstr]:
- for args in [('a',), ('a', curses.A_BOLD),
- (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
- with self.subTest(meth=meth.__qualname__, args=args):
- meth(*args)
-
- for meth in [stdscr.clear, stdscr.clrtobot,
- stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
- stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
- stdscr.getbkgd, stdscr.getmaxyx,
- stdscr.getparyx, stdscr.getyx, stdscr.inch,
- stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
- win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
- stdscr.standout, stdscr.standend, stdscr.syncdown,
- stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
- with self.subTest(meth=meth.__qualname__):
- meth()
-
- stdscr.addnstr('1234', 3)
- stdscr.addnstr('1234', 3, curses.A_BOLD)
- stdscr.addnstr(4,4, '1234', 3)
- stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
-
- stdscr.attron(curses.A_BOLD)
- stdscr.attroff(curses.A_BOLD)
- stdscr.attrset(curses.A_BOLD)
- stdscr.bkgd(' ')
- stdscr.bkgd(' ', curses.A_REVERSE)
- stdscr.bkgdset(' ')
- stdscr.bkgdset(' ', curses.A_REVERSE)
+ # touchwin()/untouchwin()/is_wintouched()
+ stdscr.refresh()
+ self.assertIs(stdscr.is_wintouched(), False)
+ stdscr.touchwin()
+ self.assertIs(stdscr.is_wintouched(), True)
+ stdscr.refresh()
+ self.assertIs(stdscr.is_wintouched(), False)
+ stdscr.touchwin()
+ self.assertIs(stdscr.is_wintouched(), True)
+ stdscr.untouchwin()
+ self.assertIs(stdscr.is_wintouched(), False)
+
+ # touchline()/untouchline()/is_linetouched()
+ stdscr.touchline(5, 2)
+ self.assertIs(stdscr.is_linetouched(5), True)
+ self.assertIs(stdscr.is_linetouched(6), True)
+ self.assertIs(stdscr.is_wintouched(), True)
+ stdscr.touchline(5, 1, False)
+ self.assertIs(stdscr.is_linetouched(5), False)
+
+ # syncup()
+ win = stdscr.subwin(10, 15, 2, 5)
+ win2 = win.subwin(5, 10, 3, 7)
+ win2.touchwin()
+ stdscr.untouchwin()
+ win2.syncup()
+ self.assertIs(win.is_wintouched(), True)
+ self.assertIs(stdscr.is_wintouched(), True)
+
+ # syncdown()
+ stdscr.touchwin()
+ win.untouchwin()
+ win2.untouchwin()
+ win2.syncdown()
+ self.assertIs(win2.is_wintouched(), True)
+
+ # syncok()
+ if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
+ win.untouchwin()
+ stdscr.untouchwin()
+ for syncok in [False, True]:
+ win2.syncok(syncok)
+ win2.addch('a')
+ self.assertIs(win.is_wintouched(), syncok)
+ self.assertIs(stdscr.is_wintouched(), syncok)
+
+ def test_output_character(self):
+ stdscr = self.stdscr
+ # addch()
+ stdscr.refresh()
+ stdscr.move(0, 0)
+ stdscr.addch('A')
+ stdscr.addch(b'A')
+ stdscr.addch(65)
+ stdscr.addch('\u20ac')
+ stdscr.addch('A', curses.A_BOLD)
+ stdscr.addch(1, 2, 'A')
+ stdscr.addch(2, 3, 'A', curses.A_BOLD)
+ self.assertIs(stdscr.is_wintouched(), True)
+
+ # echochar()
+ stdscr.refresh()
+ stdscr.move(0, 0)
+ stdscr.echochar('A')
+ stdscr.echochar(b'A')
+ stdscr.echochar(65)
+ self.assertRaises(OverflowError, stdscr.echochar, '\u20ac')
+ stdscr.echochar('A', curses.A_BOLD)
+ self.assertIs(stdscr.is_wintouched(), False)
+
+ def test_output_string(self):
+ stdscr = self.stdscr
+ # addstr()/insstr()
+ for func in [stdscr.addstr, stdscr.insstr]:
+ with self.subTest(func.__qualname__):
+ stdscr.move(0, 0)
+ func('abcd')
+ func(b'abcd')
+ func('àßçđ')
+ func('abcd', curses.A_BOLD)
+ func(1, 2, 'abcd')
+ func(2, 3, 'abcd', curses.A_BOLD)
+
+ # addnstr()/insnstr()
+ for func in [stdscr.addnstr, stdscr.insnstr]:
+ with self.subTest(func.__qualname__):
+ stdscr.move(0, 0)
+ func('1234', 3)
+ func(b'1234', 3)
+ func('\u0661\u0662\u0663\u0664', 3)
+ func('1234', 5)
+ func('1234', 3, curses.A_BOLD)
+ func(1, 2, '1234', 3)
+ func(2, 3, '1234', 3, curses.A_BOLD)
+
+ def test_output_string_embedded_null_chars(self):
+ # reject embedded null bytes and characters
+ stdscr = self.stdscr
+ for arg in ['a\0', b'a\0']:
+ with self.subTest(arg=arg):
+ self.assertRaises(ValueError, stdscr.addstr, arg)
+ self.assertRaises(ValueError, stdscr.addnstr, arg, 1)
+ self.assertRaises(ValueError, stdscr.insstr, arg)
+ self.assertRaises(ValueError, stdscr.insnstr, arg, 1)
- win.border(65, 66, 67, 68,
- 69, 70, 71, 72)
+ def test_read_from_window(self):
+ stdscr = self.stdscr
+ stdscr.addstr(0, 1, 'ABCD', curses.A_BOLD)
+ # inch()
+ stdscr.move(0, 1)
+ self.assertEqual(stdscr.inch(), 65 | curses.A_BOLD)
+ self.assertEqual(stdscr.inch(0, 3), 67 | curses.A_BOLD)
+ stdscr.move(0, 0)
+ # instr()
+ self.assertEqual(stdscr.instr()[:6], b' ABCD ')
+ self.assertEqual(stdscr.instr(3)[:6], b' AB')
+ self.assertEqual(stdscr.instr(0, 2)[:4], b'BCD ')
+ self.assertEqual(stdscr.instr(0, 2, 4), b'BCD ')
+ self.assertRaises(ValueError, stdscr.instr, -2)
+ self.assertRaises(ValueError, stdscr.instr, 0, 2, -2)
+
+ def test_getch(self):
+ win = curses.newwin(5, 12, 5, 2)
+
+ # TODO: Test with real input by writing to master fd.
+ for c in 'spam\n'[::-1]:
+ curses.ungetch(c)
+ self.assertEqual(win.getch(3, 1), b's'[0])
+ self.assertEqual(win.getyx(), (3, 1))
+ self.assertEqual(win.getch(3, 4), b'p'[0])
+ self.assertEqual(win.getyx(), (3, 4))
+ self.assertEqual(win.getch(), b'a'[0])
+ self.assertEqual(win.getyx(), (3, 4))
+ self.assertEqual(win.getch(), b'm'[0])
+ self.assertEqual(win.getch(), b'\n'[0])
+
+ def test_getstr(self):
+ win = curses.newwin(5, 12, 5, 2)
+ curses.echo()
+ self.addCleanup(curses.noecho)
+
+ self.assertRaises(ValueError, win.getstr, -400)
+ self.assertRaises(ValueError, win.getstr, 2, 3, -400)
+
+ # TODO: Test with real input by writing to master fd.
+ for c in 'Lorem\nipsum\ndolor\nsit\namet\n'[::-1]:
+ curses.ungetch(c)
+ self.assertEqual(win.getstr(3, 1, 2), b'Lo')
+ self.assertEqual(win.instr(3, 0), b' Lo ')
+ self.assertEqual(win.getstr(3, 5, 10), b'ipsum')
+ self.assertEqual(win.instr(3, 0), b' Lo ipsum ')
+ self.assertEqual(win.getstr(1, 5), b'dolor')
+ self.assertEqual(win.instr(1, 0), b' dolor ')
+ self.assertEqual(win.getstr(2), b'si')
+ self.assertEqual(win.instr(1, 0), b'si dolor ')
+ self.assertEqual(win.getstr(), b'amet')
+ self.assertEqual(win.instr(1, 0), b'amet dolor ')
+
+ def test_clear(self):
+ win = curses.newwin(5, 15, 5, 2)
+ lorem_ipsum(win)
+
+ win.move(0, 8)
+ win.clrtoeol()
+ self.assertEqual(win.instr(0, 0).rstrip(), b'Lorem ip')
+ self.assertEqual(win.instr(1, 0).rstrip(), b'dolor sit amet,')
+
+ win.move(0, 3)
+ win.clrtobot()
+ self.assertEqual(win.instr(0, 0).rstrip(), b'Lor')
+ self.assertEqual(win.instr(1, 0).rstrip(), b'')
+
+ for func in [win.erase, win.clear]:
+ lorem_ipsum(win)
+ func()
+ self.assertEqual(win.instr(0, 0).rstrip(), b'')
+ self.assertEqual(win.instr(1, 0).rstrip(), b'')
+
+ def test_insert_delete(self):
+ win = curses.newwin(5, 15, 5, 2)
+ lorem_ipsum(win)
+
+ win.move(0, 2)
+ win.delch()
+ self.assertEqual(win.instr(0, 0), b'Loem ipsum ')
+ win.delch(0, 7)
+ self.assertEqual(win.instr(0, 0), b'Loem ipum ')
+
+ win.move(1, 5)
+ win.deleteln()
+ self.assertEqual(win.instr(0, 0), b'Loem ipum ')
+ self.assertEqual(win.instr(1, 0), b'consectetur ')
+ self.assertEqual(win.instr(2, 0), b'adipiscing elit')
+ self.assertEqual(win.instr(3, 0), b'sed do eiusmod ')
+ self.assertEqual(win.instr(4, 0), b' ')
+
+ win.move(1, 5)
+ win.insertln()
+ self.assertEqual(win.instr(0, 0), b'Loem ipum ')
+ self.assertEqual(win.instr(1, 0), b' ')
+ self.assertEqual(win.instr(2, 0), b'consectetur ')
+
+ win.clear()
+ lorem_ipsum(win)
+ win.move(1, 5)
+ win.insdelln(2)
+ self.assertEqual(win.instr(0, 0), b'Lorem ipsum ')
+ self.assertEqual(win.instr(1, 0), b' ')
+ self.assertEqual(win.instr(2, 0), b' ')
+ self.assertEqual(win.instr(3, 0), b'dolor sit amet,')
+
+ win.clear()
+ lorem_ipsum(win)
+ win.move(1, 5)
+ win.insdelln(-2)
+ self.assertEqual(win.instr(0, 0), b'Lorem ipsum ')
+ self.assertEqual(win.instr(1, 0), b'adipiscing elit')
+ self.assertEqual(win.instr(2, 0), b'sed do eiusmod ')
+ self.assertEqual(win.instr(3, 0), b' ')
+
+ def test_scroll(self):
+ win = curses.newwin(5, 15, 5, 2)
+ lorem_ipsum(win)
+ win.scrollok(True)
+ win.scroll()
+ self.assertEqual(win.instr(0, 0), b'dolor sit amet,')
+ win.scroll(2)
+ self.assertEqual(win.instr(0, 0), b'adipiscing elit')
+ win.scroll(-3)
+ self.assertEqual(win.instr(0, 0), b' ')
+ self.assertEqual(win.instr(2, 0), b' ')
+ self.assertEqual(win.instr(3, 0), b'adipiscing elit')
+ win.scrollok(False)
+
+ def test_attributes(self):
+ # TODO: attr_get(), attr_set(), ...
+ win = curses.newwin(5, 15, 5, 2)
+ win.attron(curses.A_BOLD)
+ win.attroff(curses.A_BOLD)
+ win.attrset(curses.A_BOLD)
+
+ win.standout()
+ win.standend()
+
+ @requires_curses_window_meth('chgat')
+ def test_chgat(self):
+ win = curses.newwin(5, 15, 5, 2)
+ win.addstr(2, 0, 'Lorem ipsum')
+ win.addstr(3, 0, 'dolor sit amet')
+
+ win.move(2, 8)
+ win.chgat(curses.A_BLINK)
+ self.assertEqual(win.inch(2, 7), b'p'[0])
+ self.assertEqual(win.inch(2, 8), b's'[0] | curses.A_BLINK)
+ self.assertEqual(win.inch(2, 14), b' '[0] | curses.A_BLINK)
+
+ win.move(2, 1)
+ win.chgat(3, curses.A_BOLD)
+ self.assertEqual(win.inch(2, 0), b'L'[0])
+ self.assertEqual(win.inch(2, 1), b'o'[0] | curses.A_BOLD)
+ self.assertEqual(win.inch(2, 3), b'e'[0] | curses.A_BOLD)
+ self.assertEqual(win.inch(2, 4), b'm'[0])
+
+ win.chgat(3, 2, curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 1), b'o'[0])
+ self.assertEqual(win.inch(3, 2), b'l'[0] | curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 14), b' '[0] | curses.A_UNDERLINE)
+
+ win.chgat(3, 4, 7, curses.A_BLINK)
+ self.assertEqual(win.inch(3, 3), b'o'[0] | curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 4), b'r'[0] | curses.A_BLINK)
+ self.assertEqual(win.inch(3, 10), b'a'[0] | curses.A_BLINK)
+ self.assertEqual(win.inch(3, 11), b'm'[0] | curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 14), b' '[0] | curses.A_UNDERLINE)
+
+ def test_background(self):
+ win = curses.newwin(5, 15, 5, 2)
+ win.addstr(0, 0, 'Lorem ipsum')
+
+ self.assertEqual(win.getbkgd(), 0)
+
+ # bkgdset()
+ win.bkgdset('_')
+ self.assertEqual(win.getbkgd(), b'_'[0])
+ win.bkgdset(b'#')
+ self.assertEqual(win.getbkgd(), b'#'[0])
+ win.bkgdset(65)
+ self.assertEqual(win.getbkgd(), 65)
+ win.bkgdset(0)
+ self.assertEqual(win.getbkgd(), 32)
+
+ win.bkgdset('#', curses.A_REVERSE)
+ self.assertEqual(win.getbkgd(), b'#'[0] | curses.A_REVERSE)
+ self.assertEqual(win.inch(0, 0), b'L'[0])
+ self.assertEqual(win.inch(0, 5), b' '[0])
+ win.bkgdset(0)
+
+ # bkgd()
+ win.bkgd('_')
+ self.assertEqual(win.getbkgd(), b'_'[0])
+ self.assertEqual(win.inch(0, 0), b'L'[0])
+ self.assertEqual(win.inch(0, 5), b'_'[0])
+
+ win.bkgd('#', curses.A_REVERSE)
+ self.assertEqual(win.getbkgd(), b'#'[0] | curses.A_REVERSE)
+ self.assertEqual(win.inch(0, 0), b'L'[0] | curses.A_REVERSE)
+ self.assertEqual(win.inch(0, 5), b'#'[0] | curses.A_REVERSE)
+
+ def test_overlay(self):
+ srcwin = curses.newwin(5, 18, 3, 4)
+ lorem_ipsum(srcwin)
+ dstwin = curses.newwin(7, 17, 5, 7)
+ for i in range(6):
+ dstwin.addstr(i, 0, '_'*17)
+
+ srcwin.overlay(dstwin)
+ self.assertEqual(dstwin.instr(0, 0), b'sectetur_________')
+ self.assertEqual(dstwin.instr(1, 0), b'piscing_elit,____')
+ self.assertEqual(dstwin.instr(2, 0), b'_do_eiusmod______')
+ self.assertEqual(dstwin.instr(3, 0), b'_________________')
+
+ srcwin.overwrite(dstwin)
+ self.assertEqual(dstwin.instr(0, 0), b'sectetur __')
+ self.assertEqual(dstwin.instr(1, 0), b'piscing elit, __')
+ self.assertEqual(dstwin.instr(2, 0), b' do eiusmod __')
+ self.assertEqual(dstwin.instr(3, 0), b'_________________')
+
+ srcwin.overlay(dstwin, 1, 4, 3, 2, 4, 11)
+ self.assertEqual(dstwin.instr(3, 0), b'__r_sit_amet_____')
+ self.assertEqual(dstwin.instr(4, 0), b'__ectetur________')
+ self.assertEqual(dstwin.instr(5, 0), b'_________________')
+
+ srcwin.overwrite(dstwin, 1, 4, 3, 2, 4, 11)
+ self.assertEqual(dstwin.instr(3, 0), b'__r sit amet_____')
+ self.assertEqual(dstwin.instr(4, 0), b'__ectetur _____')
+ self.assertEqual(dstwin.instr(5, 0), b'_________________')
+
+ def test_refresh(self):
+ win = curses.newwin(5, 15, 2, 5)
+ win.noutrefresh()
+ win.redrawln(1, 2)
+ win.redrawwin()
+ win.refresh()
+ curses.doupdate()
+
+ @requires_curses_window_meth('resize')
+ def test_resize(self):
+ win = curses.newwin(5, 15, 2, 5)
+ win.resize(4, 20)
+ self.assertEqual(win.getmaxyx(), (4, 20))
+ win.resize(5, 15)
+ self.assertEqual(win.getmaxyx(), (5, 15))
+
+ @requires_curses_window_meth('enclose')
+ def test_enclose(self):
+ win = curses.newwin(5, 15, 2, 5)
+ # TODO: Return bool instead of 1/0
+ self.assertTrue(win.enclose(2, 5))
+ self.assertFalse(win.enclose(1, 5))
+ self.assertFalse(win.enclose(2, 4))
+ self.assertTrue(win.enclose(6, 19))
+ self.assertFalse(win.enclose(7, 19))
+ self.assertFalse(win.enclose(6, 20))
+
+ def test_putwin(self):
+ win = curses.newwin(5, 12, 1, 2)
+ win.addstr(2, 1, 'Lorem ipsum')
+ with tempfile.TemporaryFile() as f:
+ win.putwin(f)
+ del win
+ f.seek(0)
+ win = curses.getwin(f)
+ self.assertEqual(win.getbegyx(), (1, 2))
+ self.assertEqual(win.getmaxyx(), (5, 12))
+ self.assertEqual(win.instr(2, 0), b' Lorem ipsum')
+
+ def test_borders_and_lines(self):
+ win = curses.newwin(5, 10, 5, 2)
win.border('|', '!', '-', '_',
'+', '\\', '#', '/')
- with self.assertRaises(TypeError,
- msg="Expected win.border() to raise TypeError"):
- win.border(65, 66, 67, 68,
- 69, [], 71, 72)
-
- win.box(65, 67)
- win.box('!', '_')
+ self.assertEqual(win.instr(0, 0), b'+--------\\')
+ self.assertEqual(win.instr(1, 0), b'| !')
+ self.assertEqual(win.instr(4, 0), b'#________/')
+ win.border(b'|', b'!', b'-', b'_',
+ b'+', b'\\', b'#', b'/')
+ win.border(65, 66, 67, 68,
+ 69, 70, 71, 72)
+ self.assertRaises(TypeError, win.border,
+ 65, 66, 67, 68, 69, [], 71, 72)
+ self.assertRaises(TypeError, win.border,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73)
+ self.assertRaises(TypeError, win.border,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73)
+ win.border(65, 66, 67, 68, 69, 70, 71)
+ win.border(65, 66, 67, 68, 69, 70)
+ win.border(65, 66, 67, 68, 69)
+ win.border(65, 66, 67, 68)
+ win.border(65, 66, 67)
+ win.border(65, 66)
+ win.border(65)
+ win.border()
+
+ win.box(':', '~')
+ self.assertEqual(win.instr(0, 1, 8), b'~~~~~~~~')
+ self.assertEqual(win.instr(1, 0), b': :')
+ self.assertEqual(win.instr(4, 1, 8), b'~~~~~~~~')
win.box(b':', b'~')
+ win.box(65, 67)
self.assertRaises(TypeError, win.box, 65, 66, 67)
self.assertRaises(TypeError, win.box, 65)
win.box()
- stdscr.clearok(1)
+ win.move(1, 2)
+ win.hline('-', 5)
+ self.assertEqual(win.instr(1, 1, 7), b' ----- ')
+ win.hline(b'-', 5)
+ win.hline(45, 5)
+ win.hline('-', 5, curses.A_BOLD)
+ win.hline(1, 1, '-', 5)
+ win.hline(1, 1, '-', 5, curses.A_BOLD)
+
+ win.move(1, 2)
+ win.vline('a', 3)
+ win.vline(b'a', 3)
+ win.vline(97, 3)
+ win.vline('a', 3, curses.A_STANDOUT)
+ win.vline(1, 1, 'a', 3)
+ win.vline(1, 1, ';', 2, curses.A_STANDOUT)
+ self.assertEqual(win.inch(1, 1), b';'[0] | curses.A_STANDOUT)
+ self.assertEqual(win.inch(2, 1), b';'[0] | curses.A_STANDOUT)
+ self.assertEqual(win.inch(3, 1), b'a'[0])
+
+ def test_unctrl(self):
+ # TODO: wunctrl()
+ self.assertEqual(curses.unctrl(b'A'), b'A')
+ self.assertEqual(curses.unctrl('A'), b'A')
+ self.assertEqual(curses.unctrl(65), b'A')
+ self.assertEqual(curses.unctrl(b'\n'), b'^J')
+ self.assertEqual(curses.unctrl('\n'), b'^J')
+ self.assertEqual(curses.unctrl(10), b'^J')
+ self.assertRaises(TypeError, curses.unctrl, b'')
+ self.assertRaises(TypeError, curses.unctrl, b'AB')
+ self.assertRaises(TypeError, curses.unctrl, '')
+ self.assertRaises(TypeError, curses.unctrl, 'AB')
+ self.assertRaises(OverflowError, curses.unctrl, 2**64)
+
+ def test_endwin(self):
+ if not self.isatty:
+ self.skipTest('requires terminal')
+ self.assertIs(curses.isendwin(), False)
+ curses.endwin()
+ self.assertIs(curses.isendwin(), True)
+ curses.doupdate()
+ self.assertIs(curses.isendwin(), False)
+
+ def test_terminfo(self):
+ self.assertIsInstance(curses.tigetflag('hc'), int)
+ self.assertEqual(curses.tigetflag('cols'), -1)
+ self.assertEqual(curses.tigetflag('cr'), -1)
+
+ self.assertIsInstance(curses.tigetnum('cols'), int)
+ self.assertEqual(curses.tigetnum('hc'), -2)
+ self.assertEqual(curses.tigetnum('cr'), -2)
+
+ self.assertIsInstance(curses.tigetstr('cr'), (bytes, type(None)))
+ self.assertIsNone(curses.tigetstr('hc'))
+ self.assertIsNone(curses.tigetstr('cols'))
+
+ cud = curses.tigetstr('cud')
+ if cud is not None:
+ # See issue10570.
+ self.assertIsInstance(cud, bytes)
+ curses.tparm(cud, 2)
+ cud_2 = curses.tparm(cud, 2)
+ self.assertIsInstance(cud_2, bytes)
+ curses.putp(cud_2)
+
+ curses.putp(b'abc\n')
+
+ def test_misc_module_funcs(self):
+ curses.delay_output(1)
+ curses.flushinp()
+
+ curses.doupdate()
+ self.assertIs(curses.isendwin(), False)
+
+ curses.napms(100)
+
+ curses.newpad(50, 50)
+
+ def test_env_queries(self):
+ # TODO: term_attrs(), erasewchar(), killwchar()
+ self.assertIsInstance(curses.termname(), bytes)
+ self.assertIsInstance(curses.longname(), bytes)
+ self.assertIsInstance(curses.baudrate(), int)
+ self.assertIsInstance(curses.has_ic(), bool)
+ self.assertIsInstance(curses.has_il(), bool)
+ self.assertIsInstance(curses.termattrs(), int)
+
+ c = curses.killchar()
+ self.assertIsInstance(c, bytes)
+ self.assertEqual(len(c), 1)
+ c = curses.erasechar()
+ self.assertIsInstance(c, bytes)
+ self.assertEqual(len(c), 1)
+
+ def test_output_options(self):
+ stdscr = self.stdscr
+
+ stdscr.clearok(True)
+ stdscr.clearok(False)
- win4 = stdscr.derwin(2,2)
- win4 = stdscr.derwin(1,1, 5,5)
- win4.mvderwin(9,9)
+ stdscr.idcok(True)
+ stdscr.idcok(False)
- stdscr.echochar('a')
- stdscr.echochar('a', curses.A_BOLD)
- stdscr.hline('-', 5)
- stdscr.hline('-', 5, curses.A_BOLD)
- stdscr.hline(1,1,'-', 5)
- stdscr.hline(1,1,'-', 5, curses.A_BOLD)
+ stdscr.idlok(False)
+ stdscr.idlok(True)
- stdscr.idcok(1)
- stdscr.idlok(1)
if hasattr(stdscr, 'immedok'):
- stdscr.immedok(1)
- stdscr.immedok(0)
- stdscr.insch('c')
- stdscr.insdelln(1)
- stdscr.insnstr('abc', 3)
- stdscr.insnstr('abc', 3, curses.A_BOLD)
- stdscr.insnstr(5, 5, 'abc', 3)
- stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
-
- stdscr.insstr('def')
- stdscr.insstr('def', curses.A_BOLD)
- stdscr.insstr(5, 5, 'def')
- stdscr.insstr(5, 5, 'def', curses.A_BOLD)
- stdscr.is_linetouched(0)
- stdscr.keypad(1)
- stdscr.leaveok(1)
- stdscr.move(3,3)
- win.mvwin(2,2)
- stdscr.nodelay(1)
- stdscr.notimeout(1)
- win2.overlay(win)
- win2.overwrite(win)
- win2.overlay(win, 1, 2, 2, 1, 3, 3)
- win2.overwrite(win, 1, 2, 2, 1, 3, 3)
- stdscr.redrawln(1,2)
-
- stdscr.scrollok(1)
- stdscr.scroll()
- stdscr.scroll(2)
- stdscr.scroll(-3)
-
- stdscr.move(12, 2)
- stdscr.setscrreg(10,15)
- win3 = stdscr.subwin(10,10)
- win3 = stdscr.subwin(10,10, 5,5)
- if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
- stdscr.syncok(1)
- stdscr.timeout(5)
- stdscr.touchline(5,5)
- stdscr.touchline(5,5,0)
- stdscr.vline('a', 3)
- stdscr.vline('a', 3, curses.A_STANDOUT)
- if hasattr(stdscr, 'chgat'):
- stdscr.chgat(5, 2, 3, curses.A_BLINK)
- stdscr.chgat(3, curses.A_BOLD)
- stdscr.chgat(5, 8, curses.A_UNDERLINE)
- stdscr.chgat(curses.A_BLINK)
- stdscr.refresh()
+ stdscr.immedok(True)
+ stdscr.immedok(False)
- stdscr.vline(1,1, 'a', 3)
- stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
+ stdscr.leaveok(True)
+ stdscr.leaveok(False)
- if hasattr(stdscr, 'resize'):
- stdscr.resize(25, 80)
- if hasattr(stdscr, 'enclose'):
- stdscr.enclose(10, 10)
+ stdscr.scrollok(True)
+ stdscr.scrollok(False)
- with tempfile.TemporaryFile() as f:
- self.stdscr.putwin(f)
- f.seek(0)
- curses.getwin(f)
+ stdscr.setscrreg(5, 10)
- self.assertRaises(ValueError, stdscr.getstr, -400)
- self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
- self.assertRaises(ValueError, stdscr.instr, -2)
- self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
+ curses.nonl()
+ curses.nl(True)
+ curses.nl(False)
+ curses.nl()
- def test_embedded_null_chars(self):
- # reject embedded null bytes and characters
+
+ def test_input_options(self):
stdscr = self.stdscr
- for arg in ['a', b'a']:
- with self.subTest(arg=arg):
- self.assertRaises(ValueError, stdscr.addstr, 'a\0')
- self.assertRaises(ValueError, stdscr.addnstr, 'a\0', 1)
- self.assertRaises(ValueError, stdscr.insstr, 'a\0')
- self.assertRaises(ValueError, stdscr.insnstr, 'a\0', 1)
-
- def test_module_funcs(self):
- "Test module-level functions"
- for func in [curses.baudrate, curses.beep, curses.can_change_color,
- curses.doupdate, curses.flash, curses.flushinp,
- curses.has_colors, curses.has_ic, curses.has_il,
- curses.isendwin, curses.killchar, curses.longname,
- curses.noecho, curses.nonl, curses.noqiflush,
- curses.termattrs, curses.termname, curses.erasechar]:
- with self.subTest(func=func.__qualname__):
- func()
+
if self.isatty:
- for func in [curses.cbreak, curses.def_prog_mode,
- curses.nocbreak, curses.noraw,
- curses.reset_prog_mode]:
- with self.subTest(func=func.__qualname__):
- func()
- if hasattr(curses, 'filter'):
- curses.filter()
- if hasattr(curses, 'getsyx'):
- curses.getsyx()
-
- # Functions that actually need arguments
- if curses.tigetstr("cnorm"):
- curses.curs_set(1)
- curses.delay_output(1)
- curses.echo() ; curses.echo(1)
+ curses.nocbreak()
+ curses.cbreak()
+ curses.cbreak(False)
+ curses.cbreak(True)
+ curses.intrflush(True)
+ curses.intrflush(False)
+
+ curses.raw()
+ curses.raw(False)
+ curses.raw(True)
+ curses.noraw()
+
+ curses.noecho()
+ curses.echo()
+ curses.echo(False)
+ curses.echo(True)
+
+ curses.halfdelay(255)
curses.halfdelay(1)
- if self.isatty:
- curses.intrflush(1)
- curses.meta(1)
- curses.napms(100)
- curses.newpad(50,50)
- win = curses.newwin(5,5)
- win = curses.newwin(5,5, 1,1)
- curses.nl() ; curses.nl(1)
- curses.putp(b'abc')
+
+ stdscr.keypad(True)
+ stdscr.keypad(False)
+
+ curses.meta(True)
+ curses.meta(False)
+
+ stdscr.nodelay(True)
+ stdscr.nodelay(False)
+
+ curses.noqiflush()
+ curses.qiflush(True)
+ curses.qiflush(False)
curses.qiflush()
- if self.isatty:
- curses.raw() ; curses.raw(1)
- if hasattr(curses, 'setsyx'):
- curses.setsyx(5,5)
- curses.tigetflag('hc')
- curses.tigetnum('co')
- curses.tigetstr('cr')
- curses.tparm(b'cr')
- if hasattr(curses, 'typeahead'):
- curses.typeahead(sys.__stdin__.fileno())
- curses.unctrl('a')
- curses.ungetch('a')
- if hasattr(curses, 'use_env'):
- curses.use_env(1)
-
- # Functions only available on a few platforms
+
+ stdscr.notimeout(True)
+ stdscr.notimeout(False)
+
+ stdscr.timeout(-1)
+ stdscr.timeout(0)
+ stdscr.timeout(5)
+
+ @requires_curses_func('typeahead')
+ def test_typeahead(self):
+ curses.typeahead(sys.__stdin__.fileno())
+ curses.typeahead(-1)
+
+ def test_prog_mode(self):
+ if not self.isatty:
+ self.skipTest('requires terminal')
+ curses.def_prog_mode()
+ curses.reset_prog_mode()
+
+ def test_beep(self):
+ if (curses.tigetstr("bel") is not None
+ or curses.tigetstr("flash") is not None):
+ curses.beep()
+ else:
+ try:
+ curses.beep()
+ except curses.error:
+ self.skipTest('beep() failed')
+
+ def test_flash(self):
+ if (curses.tigetstr("bel") is not None
+ or curses.tigetstr("flash") is not None):
+ curses.flash()
+ else:
+ try:
+ curses.flash()
+ except curses.error:
+ self.skipTest('flash() failed')
+
+ def test_curs_set(self):
+ for vis, cap in [(0, 'civis'), (2, 'cvvis'), (1, 'cnorm')]:
+ if curses.tigetstr(cap) is not None:
+ curses.curs_set(vis)
+ else:
+ try:
+ curses.curs_set(vis)
+ except curses.error:
+ pass
+
+ @requires_curses_func('getsyx')
+ def test_getsyx(self):
+ y, x = curses.getsyx()
+ self.assertIsInstance(y, int)
+ self.assertIsInstance(x, int)
+ curses.setsyx(4, 5)
+ self.assertEqual(curses.getsyx(), (4, 5))
def bad_colors(self):
return (-2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
@@ -319,6 +828,10 @@ def bad_colors(self):
def bad_pairs(self):
return (-2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
+ def test_has_colors(self):
+ self.assertIsInstance(curses.has_colors(), bool)
+ self.assertIsInstance(curses.can_change_color(), bool)
+
def test_start_color(self):
if not curses.has_colors():
self.skipTest('requires colors support')
@@ -342,7 +855,7 @@ def test_color_content(self):
@requires_colors
def test_init_color(self):
- if not curses.can_change_color:
+ if not curses.can_change_color():
self.skipTest('cannot change color')
old = curses.color_content(0)
@@ -430,14 +943,22 @@ def test_color_attrs(self):
@requires_curses_func('use_default_colors')
@requires_colors
def test_use_default_colors(self):
- self.assertIn(curses.pair_content(0),
- ((curses.COLOR_WHITE, curses.COLOR_BLACK), (-1, -1)))
- curses.use_default_colors()
+ old = curses.pair_content(0)
+ try:
+ curses.use_default_colors()
+ except curses.error:
+ self.skipTest('cannot change color (use_default_colors() failed)')
self.assertEqual(curses.pair_content(0), (-1, -1))
+ self.assertIn(old, [(curses.COLOR_WHITE, curses.COLOR_BLACK), (-1, -1), (0, 0)])
- @requires_curses_func('keyname')
def test_keyname(self):
- curses.keyname(13)
+ # TODO: key_name()
+ self.assertEqual(curses.keyname(65), b'A')
+ self.assertEqual(curses.keyname(13), b'^M')
+ self.assertEqual(curses.keyname(127), b'^?')
+ self.assertEqual(curses.keyname(0), b'^@')
+ self.assertRaises(ValueError, curses.keyname, -1)
+ self.assertIsInstance(curses.keyname(256), bytes)
@requires_curses_func('has_key')
def test_has_key(self):
@@ -493,22 +1014,46 @@ def test_new_curses_panel(self):
@requires_curses_func('is_term_resized')
def test_is_term_resized(self):
- curses.is_term_resized(*self.stdscr.getmaxyx())
+ lines, cols = curses.LINES, curses.COLS
+ self.assertIs(curses.is_term_resized(lines, cols), False)
+ self.assertIs(curses.is_term_resized(lines-1, cols-1), True)
@requires_curses_func('resize_term')
def test_resize_term(self):
- curses.resize_term(*self.stdscr.getmaxyx())
+ curses.update_lines_cols()
+ lines, cols = curses.LINES, curses.COLS
+ new_lines = lines - 1
+ new_cols = cols + 1
+ curses.resize_term(new_lines, new_cols)
+ self.assertEqual(curses.LINES, new_lines)
+ self.assertEqual(curses.COLS, new_cols)
+
+ curses.resize_term(lines, cols)
+ self.assertEqual(curses.LINES, lines)
+ self.assertEqual(curses.COLS, cols)
@requires_curses_func('resizeterm')
def test_resizeterm(self):
+ curses.update_lines_cols()
lines, cols = curses.LINES, curses.COLS
new_lines = lines - 1
new_cols = cols + 1
curses.resizeterm(new_lines, new_cols)
-
self.assertEqual(curses.LINES, new_lines)
self.assertEqual(curses.COLS, new_cols)
+ curses.resizeterm(lines, cols)
+ self.assertEqual(curses.LINES, lines)
+ self.assertEqual(curses.COLS, cols)
+
+ def test_ungetch(self):
+ curses.ungetch(b'A')
+ self.assertEqual(self.stdscr.getkey(), 'A')
+ curses.ungetch('B')
+ self.assertEqual(self.stdscr.getkey(), 'B')
+ curses.ungetch(67)
+ self.assertEqual(self.stdscr.getkey(), 'C')
+
def test_issue6243(self):
curses.ungetch(1025)
self.stdscr.getkey()
@@ -537,10 +1082,6 @@ def test_unget_wch(self):
read = stdscr.get_wch()
self.assertEqual(read, ch)
- def test_issue10570(self):
- b = curses.tparm(curses.tigetstr("cup"), 5, 3)
- self.assertIs(type(b), bytes)
-
def test_encoding(self):
stdscr = self.stdscr
import codecs
@@ -580,26 +1121,25 @@ def test_issue21088(self):
human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
self.assertIn("[y, x,]", human_readable_signature)
+ @requires_curses_window_meth('resize')
def test_issue13051(self):
- stdscr = self.stdscr
- if not hasattr(stdscr, 'resize'):
- raise unittest.SkipTest('requires curses.window.resize')
- box = curses.textpad.Textbox(stdscr, insert_mode=True)
- lines, cols = stdscr.getmaxyx()
- stdscr.resize(lines-2, cols-2)
+ win = curses.newwin(5, 15, 2, 5)
+ box = curses.textpad.Textbox(win, insert_mode=True)
+ lines, cols = win.getmaxyx()
+ win.resize(lines-2, cols-2)
# this may cause infinite recursion, leading to a RuntimeError
box._insert_printable_char('a')
class MiscTests(unittest.TestCase):
- @requires_curses_func('update_lines_cols')
def test_update_lines_cols(self):
- # this doesn't actually test that LINES and COLS are updated,
- # because we can't automate changing them. See Issue #4254 for
- # a manual test script. We can only test that the function
- # can be called.
curses.update_lines_cols()
+ lines, cols = curses.LINES, curses.COLS
+ curses.LINES = curses.COLS = 0
+ curses.update_lines_cols()
+ self.assertEqual(curses.LINES, lines)
+ self.assertEqual(curses.COLS, cols)
@requires_curses_func('ncurses_version')
def test_ncurses_version(self):
@@ -621,6 +1161,7 @@ def test_ncurses_version(self):
self.assertGreaterEqual(v.minor, 0)
self.assertGreaterEqual(v.patch, 0)
+
class TestAscii(unittest.TestCase):
def test_controlnames(self):
@@ -709,5 +1250,21 @@ def test_unctrl(self):
self.assertEqual(unctrl(ord('\xc1')), '!A')
+def lorem_ipsum(win):
+ text = [
+ 'Lorem ipsum',
+ 'dolor sit amet,',
+ 'consectetur',
+ 'adipiscing elit,',
+ 'sed do eiusmod',
+ 'tempor incididunt',
+ 'ut labore et',
+ 'dolore magna',
+ 'aliqua.',
+ ]
+ maxy, maxx = win.getmaxyx()
+ for y, line in enumerate(text[:maxy]):
+ win.addstr(y, 0, line[:maxx - (y == maxy - 1)])
+
if __name__ == '__main__':
unittest.main()
1
0
31 Jan '21
https://github.com/python/cpython/commit/e9d4960d15c5282904cf26e469ce7cee39…
commit: e9d4960d15c5282904cf26e469ce7cee39f634f7
branch: 3.9
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2021-01-31T18:11:13+02:00
summary:
[3.9] bpo-43016: Rewrite tests for curses (GH-24312). (GH-24399)
(cherry picked from commit d64fd4bb5bb4fd2e3277f39d3ad99b5a8d193e1b)
files:
M Lib/test/test_curses.py
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index de9f301737d8c..f5287e0143fcb 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -1,18 +1,9 @@
-#
-# Test script for the curses module
-#
-# This script doesn't actually display anything very coherent. but it
-# does call (nearly) every method and function.
-#
-# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr()
-# Only called, not tested: getmouse(), ungetmouse()
-#
-
+import functools
+import inspect
import os
import string
import sys
import tempfile
-import functools
import unittest
from test.support import requires, import_module, verbose, SaveSignals
@@ -20,7 +11,6 @@
# Optionally test curses module. This currently requires that the
# 'curses' resource be given on the regrtest command line using the -u
# option. If not available, nothing after this line will be executed.
-import inspect
requires('curses')
# If either of these don't exist, skip the tests.
@@ -36,6 +26,17 @@ def requires_curses_func(name):
return unittest.skipUnless(hasattr(curses, name),
'requires curses.%s' % name)
+def requires_curses_window_meth(name):
+ def deco(test):
+ @functools.wraps(test)
+ def wrapped(self, *args, **kwargs):
+ if not hasattr(self.stdscr, name):
+ raise unittest.SkipTest('requires curses.window.%s' % name)
+ test(self, *args, **kwargs)
+ return wrapped
+ return deco
+
+
def requires_colors(test):
@functools.wraps(test)
def wrapped(self, *args, **kwargs):
@@ -110,212 +111,732 @@ def setUp(self):
curses.savetty()
self.addCleanup(curses.endwin)
self.addCleanup(curses.resetty)
+ self.stdscr.erase()
+
+ @requires_curses_func('filter')
+ def test_filter(self):
+ # TODO: Should be called before initscr() or newterm() are called.
+ # TODO: nofilter()
+ curses.filter()
+
+ @requires_curses_func('use_env')
+ def test_use_env(self):
+ # TODO: Should be called before initscr() or newterm() are called.
+ # TODO: use_tioctl()
+ curses.use_env(False)
+ curses.use_env(True)
+
+ def test_create_windows(self):
+ win = curses.newwin(5, 10)
+ self.assertEqual(win.getbegyx(), (0, 0))
+ self.assertEqual(win.getparyx(), (-1, -1))
+ self.assertEqual(win.getmaxyx(), (5, 10))
+
+ win = curses.newwin(10, 15, 2, 5)
+ self.assertEqual(win.getbegyx(), (2, 5))
+ self.assertEqual(win.getparyx(), (-1, -1))
+ self.assertEqual(win.getmaxyx(), (10, 15))
+
+ win2 = win.subwin(3, 7)
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (1, 2))
+ self.assertEqual(win2.getmaxyx(), (9, 13))
+
+ win2 = win.subwin(5, 10, 3, 7)
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (1, 2))
+ self.assertEqual(win2.getmaxyx(), (5, 10))
+
+ win3 = win.derwin(2, 3)
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 3))
+ self.assertEqual(win3.getmaxyx(), (8, 12))
+
+ win3 = win.derwin(6, 11, 2, 3)
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 3))
+ self.assertEqual(win3.getmaxyx(), (6, 11))
+
+ win.mvwin(0, 1)
+ self.assertEqual(win.getbegyx(), (0, 1))
+ self.assertEqual(win.getparyx(), (-1, -1))
+ self.assertEqual(win.getmaxyx(), (10, 15))
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (1, 2))
+ self.assertEqual(win2.getmaxyx(), (5, 10))
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 3))
+ self.assertEqual(win3.getmaxyx(), (6, 11))
+
+ win2.mvderwin(2, 1)
+ self.assertEqual(win2.getbegyx(), (3, 7))
+ self.assertEqual(win2.getparyx(), (2, 1))
+ self.assertEqual(win2.getmaxyx(), (5, 10))
+
+ win3.mvderwin(2, 1)
+ self.assertEqual(win3.getbegyx(), (4, 8))
+ self.assertEqual(win3.getparyx(), (2, 1))
+ self.assertEqual(win3.getmaxyx(), (6, 11))
+
+ def test_move_cursor(self):
+ stdscr = self.stdscr
+ win = stdscr.subwin(10, 15, 2, 5)
+ stdscr.move(1, 2)
+ win.move(2, 4)
+ self.assertEqual(stdscr.getyx(), (1, 2))
+ self.assertEqual(win.getyx(), (2, 4))
+
+ win.cursyncup()
+ self.assertEqual(stdscr.getyx(), (4, 9))
- def test_window_funcs(self):
- "Test the methods of windows"
+ def test_refresh_control(self):
stdscr = self.stdscr
- win = curses.newwin(10,10)
- win = curses.newwin(5,5, 5,5)
- win2 = curses.newwin(15,15, 5,5)
-
- for meth in [stdscr.addch, stdscr.addstr]:
- for args in [('a',), ('a', curses.A_BOLD),
- (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
- with self.subTest(meth=meth.__qualname__, args=args):
- meth(*args)
-
- for meth in [stdscr.clear, stdscr.clrtobot,
- stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
- stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
- stdscr.getbkgd, stdscr.getmaxyx,
- stdscr.getparyx, stdscr.getyx, stdscr.inch,
- stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
- win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
- stdscr.standout, stdscr.standend, stdscr.syncdown,
- stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
- with self.subTest(meth=meth.__qualname__):
- meth()
-
- stdscr.addnstr('1234', 3)
- stdscr.addnstr('1234', 3, curses.A_BOLD)
- stdscr.addnstr(4,4, '1234', 3)
- stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
-
- stdscr.attron(curses.A_BOLD)
- stdscr.attroff(curses.A_BOLD)
- stdscr.attrset(curses.A_BOLD)
- stdscr.bkgd(' ')
- stdscr.bkgd(' ', curses.A_REVERSE)
- stdscr.bkgdset(' ')
- stdscr.bkgdset(' ', curses.A_REVERSE)
+ # touchwin()/untouchwin()/is_wintouched()
+ stdscr.refresh()
+ self.assertIs(stdscr.is_wintouched(), False)
+ stdscr.touchwin()
+ self.assertIs(stdscr.is_wintouched(), True)
+ stdscr.refresh()
+ self.assertIs(stdscr.is_wintouched(), False)
+ stdscr.touchwin()
+ self.assertIs(stdscr.is_wintouched(), True)
+ stdscr.untouchwin()
+ self.assertIs(stdscr.is_wintouched(), False)
+
+ # touchline()/untouchline()/is_linetouched()
+ stdscr.touchline(5, 2)
+ self.assertIs(stdscr.is_linetouched(5), True)
+ self.assertIs(stdscr.is_linetouched(6), True)
+ self.assertIs(stdscr.is_wintouched(), True)
+ stdscr.touchline(5, 1, False)
+ self.assertIs(stdscr.is_linetouched(5), False)
+
+ # syncup()
+ win = stdscr.subwin(10, 15, 2, 5)
+ win2 = win.subwin(5, 10, 3, 7)
+ win2.touchwin()
+ stdscr.untouchwin()
+ win2.syncup()
+ self.assertIs(win.is_wintouched(), True)
+ self.assertIs(stdscr.is_wintouched(), True)
+
+ # syncdown()
+ stdscr.touchwin()
+ win.untouchwin()
+ win2.untouchwin()
+ win2.syncdown()
+ self.assertIs(win2.is_wintouched(), True)
+
+ # syncok()
+ if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
+ win.untouchwin()
+ stdscr.untouchwin()
+ for syncok in [False, True]:
+ win2.syncok(syncok)
+ win2.addch('a')
+ self.assertIs(win.is_wintouched(), syncok)
+ self.assertIs(stdscr.is_wintouched(), syncok)
+
+ def test_output_character(self):
+ stdscr = self.stdscr
+ # addch()
+ stdscr.refresh()
+ stdscr.move(0, 0)
+ stdscr.addch('A')
+ stdscr.addch(b'A')
+ stdscr.addch(65)
+ stdscr.addch('\u20ac')
+ stdscr.addch('A', curses.A_BOLD)
+ stdscr.addch(1, 2, 'A')
+ stdscr.addch(2, 3, 'A', curses.A_BOLD)
+ self.assertIs(stdscr.is_wintouched(), True)
+
+ # echochar()
+ stdscr.refresh()
+ stdscr.move(0, 0)
+ stdscr.echochar('A')
+ stdscr.echochar(b'A')
+ stdscr.echochar(65)
+ self.assertRaises(OverflowError, stdscr.echochar, '\u20ac')
+ stdscr.echochar('A', curses.A_BOLD)
+ self.assertIs(stdscr.is_wintouched(), False)
+
+ def test_output_string(self):
+ stdscr = self.stdscr
+ # addstr()/insstr()
+ for func in [stdscr.addstr, stdscr.insstr]:
+ with self.subTest(func.__qualname__):
+ stdscr.move(0, 0)
+ func('abcd')
+ func(b'abcd')
+ func('àßçđ')
+ func('abcd', curses.A_BOLD)
+ func(1, 2, 'abcd')
+ func(2, 3, 'abcd', curses.A_BOLD)
+
+ # addnstr()/insnstr()
+ for func in [stdscr.addnstr, stdscr.insnstr]:
+ with self.subTest(func.__qualname__):
+ stdscr.move(0, 0)
+ func('1234', 3)
+ func(b'1234', 3)
+ func('\u0661\u0662\u0663\u0664', 3)
+ func('1234', 5)
+ func('1234', 3, curses.A_BOLD)
+ func(1, 2, '1234', 3)
+ func(2, 3, '1234', 3, curses.A_BOLD)
+
+ def test_output_string_embedded_null_chars(self):
+ # reject embedded null bytes and characters
+ stdscr = self.stdscr
+ for arg in ['a\0', b'a\0']:
+ with self.subTest(arg=arg):
+ self.assertRaises(ValueError, stdscr.addstr, arg)
+ self.assertRaises(ValueError, stdscr.addnstr, arg, 1)
+ self.assertRaises(ValueError, stdscr.insstr, arg)
+ self.assertRaises(ValueError, stdscr.insnstr, arg, 1)
- win.border(65, 66, 67, 68,
- 69, 70, 71, 72)
+ def test_read_from_window(self):
+ stdscr = self.stdscr
+ stdscr.addstr(0, 1, 'ABCD', curses.A_BOLD)
+ # inch()
+ stdscr.move(0, 1)
+ self.assertEqual(stdscr.inch(), 65 | curses.A_BOLD)
+ self.assertEqual(stdscr.inch(0, 3), 67 | curses.A_BOLD)
+ stdscr.move(0, 0)
+ # instr()
+ self.assertEqual(stdscr.instr()[:6], b' ABCD ')
+ self.assertEqual(stdscr.instr(3)[:6], b' AB')
+ self.assertEqual(stdscr.instr(0, 2)[:4], b'BCD ')
+ self.assertEqual(stdscr.instr(0, 2, 4), b'BCD ')
+ self.assertRaises(ValueError, stdscr.instr, -2)
+ self.assertRaises(ValueError, stdscr.instr, 0, 2, -2)
+
+ def test_getch(self):
+ win = curses.newwin(5, 12, 5, 2)
+
+ # TODO: Test with real input by writing to master fd.
+ for c in 'spam\n'[::-1]:
+ curses.ungetch(c)
+ self.assertEqual(win.getch(3, 1), b's'[0])
+ self.assertEqual(win.getyx(), (3, 1))
+ self.assertEqual(win.getch(3, 4), b'p'[0])
+ self.assertEqual(win.getyx(), (3, 4))
+ self.assertEqual(win.getch(), b'a'[0])
+ self.assertEqual(win.getyx(), (3, 4))
+ self.assertEqual(win.getch(), b'm'[0])
+ self.assertEqual(win.getch(), b'\n'[0])
+
+ def test_getstr(self):
+ win = curses.newwin(5, 12, 5, 2)
+ curses.echo()
+ self.addCleanup(curses.noecho)
+
+ self.assertRaises(ValueError, win.getstr, -400)
+ self.assertRaises(ValueError, win.getstr, 2, 3, -400)
+
+ # TODO: Test with real input by writing to master fd.
+ for c in 'Lorem\nipsum\ndolor\nsit\namet\n'[::-1]:
+ curses.ungetch(c)
+ self.assertEqual(win.getstr(3, 1, 2), b'Lo')
+ self.assertEqual(win.instr(3, 0), b' Lo ')
+ self.assertEqual(win.getstr(3, 5, 10), b'ipsum')
+ self.assertEqual(win.instr(3, 0), b' Lo ipsum ')
+ self.assertEqual(win.getstr(1, 5), b'dolor')
+ self.assertEqual(win.instr(1, 0), b' dolor ')
+ self.assertEqual(win.getstr(2), b'si')
+ self.assertEqual(win.instr(1, 0), b'si dolor ')
+ self.assertEqual(win.getstr(), b'amet')
+ self.assertEqual(win.instr(1, 0), b'amet dolor ')
+
+ def test_clear(self):
+ win = curses.newwin(5, 15, 5, 2)
+ lorem_ipsum(win)
+
+ win.move(0, 8)
+ win.clrtoeol()
+ self.assertEqual(win.instr(0, 0).rstrip(), b'Lorem ip')
+ self.assertEqual(win.instr(1, 0).rstrip(), b'dolor sit amet,')
+
+ win.move(0, 3)
+ win.clrtobot()
+ self.assertEqual(win.instr(0, 0).rstrip(), b'Lor')
+ self.assertEqual(win.instr(1, 0).rstrip(), b'')
+
+ for func in [win.erase, win.clear]:
+ lorem_ipsum(win)
+ func()
+ self.assertEqual(win.instr(0, 0).rstrip(), b'')
+ self.assertEqual(win.instr(1, 0).rstrip(), b'')
+
+ def test_insert_delete(self):
+ win = curses.newwin(5, 15, 5, 2)
+ lorem_ipsum(win)
+
+ win.move(0, 2)
+ win.delch()
+ self.assertEqual(win.instr(0, 0), b'Loem ipsum ')
+ win.delch(0, 7)
+ self.assertEqual(win.instr(0, 0), b'Loem ipum ')
+
+ win.move(1, 5)
+ win.deleteln()
+ self.assertEqual(win.instr(0, 0), b'Loem ipum ')
+ self.assertEqual(win.instr(1, 0), b'consectetur ')
+ self.assertEqual(win.instr(2, 0), b'adipiscing elit')
+ self.assertEqual(win.instr(3, 0), b'sed do eiusmod ')
+ self.assertEqual(win.instr(4, 0), b' ')
+
+ win.move(1, 5)
+ win.insertln()
+ self.assertEqual(win.instr(0, 0), b'Loem ipum ')
+ self.assertEqual(win.instr(1, 0), b' ')
+ self.assertEqual(win.instr(2, 0), b'consectetur ')
+
+ win.clear()
+ lorem_ipsum(win)
+ win.move(1, 5)
+ win.insdelln(2)
+ self.assertEqual(win.instr(0, 0), b'Lorem ipsum ')
+ self.assertEqual(win.instr(1, 0), b' ')
+ self.assertEqual(win.instr(2, 0), b' ')
+ self.assertEqual(win.instr(3, 0), b'dolor sit amet,')
+
+ win.clear()
+ lorem_ipsum(win)
+ win.move(1, 5)
+ win.insdelln(-2)
+ self.assertEqual(win.instr(0, 0), b'Lorem ipsum ')
+ self.assertEqual(win.instr(1, 0), b'adipiscing elit')
+ self.assertEqual(win.instr(2, 0), b'sed do eiusmod ')
+ self.assertEqual(win.instr(3, 0), b' ')
+
+ def test_scroll(self):
+ win = curses.newwin(5, 15, 5, 2)
+ lorem_ipsum(win)
+ win.scrollok(True)
+ win.scroll()
+ self.assertEqual(win.instr(0, 0), b'dolor sit amet,')
+ win.scroll(2)
+ self.assertEqual(win.instr(0, 0), b'adipiscing elit')
+ win.scroll(-3)
+ self.assertEqual(win.instr(0, 0), b' ')
+ self.assertEqual(win.instr(2, 0), b' ')
+ self.assertEqual(win.instr(3, 0), b'adipiscing elit')
+ win.scrollok(False)
+
+ def test_attributes(self):
+ # TODO: attr_get(), attr_set(), ...
+ win = curses.newwin(5, 15, 5, 2)
+ win.attron(curses.A_BOLD)
+ win.attroff(curses.A_BOLD)
+ win.attrset(curses.A_BOLD)
+
+ win.standout()
+ win.standend()
+
+ @requires_curses_window_meth('chgat')
+ def test_chgat(self):
+ win = curses.newwin(5, 15, 5, 2)
+ win.addstr(2, 0, 'Lorem ipsum')
+ win.addstr(3, 0, 'dolor sit amet')
+
+ win.move(2, 8)
+ win.chgat(curses.A_BLINK)
+ self.assertEqual(win.inch(2, 7), b'p'[0])
+ self.assertEqual(win.inch(2, 8), b's'[0] | curses.A_BLINK)
+ self.assertEqual(win.inch(2, 14), b' '[0] | curses.A_BLINK)
+
+ win.move(2, 1)
+ win.chgat(3, curses.A_BOLD)
+ self.assertEqual(win.inch(2, 0), b'L'[0])
+ self.assertEqual(win.inch(2, 1), b'o'[0] | curses.A_BOLD)
+ self.assertEqual(win.inch(2, 3), b'e'[0] | curses.A_BOLD)
+ self.assertEqual(win.inch(2, 4), b'm'[0])
+
+ win.chgat(3, 2, curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 1), b'o'[0])
+ self.assertEqual(win.inch(3, 2), b'l'[0] | curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 14), b' '[0] | curses.A_UNDERLINE)
+
+ win.chgat(3, 4, 7, curses.A_BLINK)
+ self.assertEqual(win.inch(3, 3), b'o'[0] | curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 4), b'r'[0] | curses.A_BLINK)
+ self.assertEqual(win.inch(3, 10), b'a'[0] | curses.A_BLINK)
+ self.assertEqual(win.inch(3, 11), b'm'[0] | curses.A_UNDERLINE)
+ self.assertEqual(win.inch(3, 14), b' '[0] | curses.A_UNDERLINE)
+
+ def test_background(self):
+ win = curses.newwin(5, 15, 5, 2)
+ win.addstr(0, 0, 'Lorem ipsum')
+
+ self.assertEqual(win.getbkgd(), 0)
+
+ # bkgdset()
+ win.bkgdset('_')
+ self.assertEqual(win.getbkgd(), b'_'[0])
+ win.bkgdset(b'#')
+ self.assertEqual(win.getbkgd(), b'#'[0])
+ win.bkgdset(65)
+ self.assertEqual(win.getbkgd(), 65)
+ win.bkgdset(0)
+ self.assertEqual(win.getbkgd(), 32)
+
+ win.bkgdset('#', curses.A_REVERSE)
+ self.assertEqual(win.getbkgd(), b'#'[0] | curses.A_REVERSE)
+ self.assertEqual(win.inch(0, 0), b'L'[0])
+ self.assertEqual(win.inch(0, 5), b' '[0])
+ win.bkgdset(0)
+
+ # bkgd()
+ win.bkgd('_')
+ self.assertEqual(win.getbkgd(), b'_'[0])
+ self.assertEqual(win.inch(0, 0), b'L'[0])
+ self.assertEqual(win.inch(0, 5), b'_'[0])
+
+ win.bkgd('#', curses.A_REVERSE)
+ self.assertEqual(win.getbkgd(), b'#'[0] | curses.A_REVERSE)
+ self.assertEqual(win.inch(0, 0), b'L'[0] | curses.A_REVERSE)
+ self.assertEqual(win.inch(0, 5), b'#'[0] | curses.A_REVERSE)
+
+ def test_overlay(self):
+ srcwin = curses.newwin(5, 18, 3, 4)
+ lorem_ipsum(srcwin)
+ dstwin = curses.newwin(7, 17, 5, 7)
+ for i in range(6):
+ dstwin.addstr(i, 0, '_'*17)
+
+ srcwin.overlay(dstwin)
+ self.assertEqual(dstwin.instr(0, 0), b'sectetur_________')
+ self.assertEqual(dstwin.instr(1, 0), b'piscing_elit,____')
+ self.assertEqual(dstwin.instr(2, 0), b'_do_eiusmod______')
+ self.assertEqual(dstwin.instr(3, 0), b'_________________')
+
+ srcwin.overwrite(dstwin)
+ self.assertEqual(dstwin.instr(0, 0), b'sectetur __')
+ self.assertEqual(dstwin.instr(1, 0), b'piscing elit, __')
+ self.assertEqual(dstwin.instr(2, 0), b' do eiusmod __')
+ self.assertEqual(dstwin.instr(3, 0), b'_________________')
+
+ srcwin.overlay(dstwin, 1, 4, 3, 2, 4, 11)
+ self.assertEqual(dstwin.instr(3, 0), b'__r_sit_amet_____')
+ self.assertEqual(dstwin.instr(4, 0), b'__ectetur________')
+ self.assertEqual(dstwin.instr(5, 0), b'_________________')
+
+ srcwin.overwrite(dstwin, 1, 4, 3, 2, 4, 11)
+ self.assertEqual(dstwin.instr(3, 0), b'__r sit amet_____')
+ self.assertEqual(dstwin.instr(4, 0), b'__ectetur _____')
+ self.assertEqual(dstwin.instr(5, 0), b'_________________')
+
+ def test_refresh(self):
+ win = curses.newwin(5, 15, 2, 5)
+ win.noutrefresh()
+ win.redrawln(1, 2)
+ win.redrawwin()
+ win.refresh()
+ curses.doupdate()
+
+ @requires_curses_window_meth('resize')
+ def test_resize(self):
+ win = curses.newwin(5, 15, 2, 5)
+ win.resize(4, 20)
+ self.assertEqual(win.getmaxyx(), (4, 20))
+ win.resize(5, 15)
+ self.assertEqual(win.getmaxyx(), (5, 15))
+
+ @requires_curses_window_meth('enclose')
+ def test_enclose(self):
+ win = curses.newwin(5, 15, 2, 5)
+ # TODO: Return bool instead of 1/0
+ self.assertTrue(win.enclose(2, 5))
+ self.assertFalse(win.enclose(1, 5))
+ self.assertFalse(win.enclose(2, 4))
+ self.assertTrue(win.enclose(6, 19))
+ self.assertFalse(win.enclose(7, 19))
+ self.assertFalse(win.enclose(6, 20))
+
+ def test_putwin(self):
+ win = curses.newwin(5, 12, 1, 2)
+ win.addstr(2, 1, 'Lorem ipsum')
+ with tempfile.TemporaryFile() as f:
+ win.putwin(f)
+ del win
+ f.seek(0)
+ win = curses.getwin(f)
+ self.assertEqual(win.getbegyx(), (1, 2))
+ self.assertEqual(win.getmaxyx(), (5, 12))
+ self.assertEqual(win.instr(2, 0), b' Lorem ipsum')
+
+ def test_borders_and_lines(self):
+ win = curses.newwin(5, 10, 5, 2)
win.border('|', '!', '-', '_',
'+', '\\', '#', '/')
- with self.assertRaises(TypeError,
- msg="Expected win.border() to raise TypeError"):
- win.border(65, 66, 67, 68,
- 69, [], 71, 72)
-
- win.box(65, 67)
- win.box('!', '_')
+ self.assertEqual(win.instr(0, 0), b'+--------\\')
+ self.assertEqual(win.instr(1, 0), b'| !')
+ self.assertEqual(win.instr(4, 0), b'#________/')
+ win.border(b'|', b'!', b'-', b'_',
+ b'+', b'\\', b'#', b'/')
+ win.border(65, 66, 67, 68,
+ 69, 70, 71, 72)
+ self.assertRaises(TypeError, win.border,
+ 65, 66, 67, 68, 69, [], 71, 72)
+ self.assertRaises(TypeError, win.border,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73)
+ self.assertRaises(TypeError, win.border,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73)
+ win.border(65, 66, 67, 68, 69, 70, 71)
+ win.border(65, 66, 67, 68, 69, 70)
+ win.border(65, 66, 67, 68, 69)
+ win.border(65, 66, 67, 68)
+ win.border(65, 66, 67)
+ win.border(65, 66)
+ win.border(65)
+ win.border()
+
+ win.box(':', '~')
+ self.assertEqual(win.instr(0, 1, 8), b'~~~~~~~~')
+ self.assertEqual(win.instr(1, 0), b': :')
+ self.assertEqual(win.instr(4, 1, 8), b'~~~~~~~~')
win.box(b':', b'~')
+ win.box(65, 67)
self.assertRaises(TypeError, win.box, 65, 66, 67)
self.assertRaises(TypeError, win.box, 65)
win.box()
- stdscr.clearok(1)
+ win.move(1, 2)
+ win.hline('-', 5)
+ self.assertEqual(win.instr(1, 1, 7), b' ----- ')
+ win.hline(b'-', 5)
+ win.hline(45, 5)
+ win.hline('-', 5, curses.A_BOLD)
+ win.hline(1, 1, '-', 5)
+ win.hline(1, 1, '-', 5, curses.A_BOLD)
+
+ win.move(1, 2)
+ win.vline('a', 3)
+ win.vline(b'a', 3)
+ win.vline(97, 3)
+ win.vline('a', 3, curses.A_STANDOUT)
+ win.vline(1, 1, 'a', 3)
+ win.vline(1, 1, ';', 2, curses.A_STANDOUT)
+ self.assertEqual(win.inch(1, 1), b';'[0] | curses.A_STANDOUT)
+ self.assertEqual(win.inch(2, 1), b';'[0] | curses.A_STANDOUT)
+ self.assertEqual(win.inch(3, 1), b'a'[0])
+
+ def test_unctrl(self):
+ # TODO: wunctrl()
+ self.assertEqual(curses.unctrl(b'A'), b'A')
+ self.assertEqual(curses.unctrl('A'), b'A')
+ self.assertEqual(curses.unctrl(65), b'A')
+ self.assertEqual(curses.unctrl(b'\n'), b'^J')
+ self.assertEqual(curses.unctrl('\n'), b'^J')
+ self.assertEqual(curses.unctrl(10), b'^J')
+ self.assertRaises(TypeError, curses.unctrl, b'')
+ self.assertRaises(TypeError, curses.unctrl, b'AB')
+ self.assertRaises(TypeError, curses.unctrl, '')
+ self.assertRaises(TypeError, curses.unctrl, 'AB')
+ self.assertRaises(OverflowError, curses.unctrl, 2**64)
+
+ def test_endwin(self):
+ if not self.isatty:
+ self.skipTest('requires terminal')
+ self.assertIs(curses.isendwin(), False)
+ curses.endwin()
+ self.assertIs(curses.isendwin(), True)
+ curses.doupdate()
+ self.assertIs(curses.isendwin(), False)
+
+ def test_terminfo(self):
+ self.assertIsInstance(curses.tigetflag('hc'), int)
+ self.assertEqual(curses.tigetflag('cols'), -1)
+ self.assertEqual(curses.tigetflag('cr'), -1)
+
+ self.assertIsInstance(curses.tigetnum('cols'), int)
+ self.assertEqual(curses.tigetnum('hc'), -2)
+ self.assertEqual(curses.tigetnum('cr'), -2)
+
+ self.assertIsInstance(curses.tigetstr('cr'), (bytes, type(None)))
+ self.assertIsNone(curses.tigetstr('hc'))
+ self.assertIsNone(curses.tigetstr('cols'))
+
+ cud = curses.tigetstr('cud')
+ if cud is not None:
+ # See issue10570.
+ self.assertIsInstance(cud, bytes)
+ curses.tparm(cud, 2)
+ cud_2 = curses.tparm(cud, 2)
+ self.assertIsInstance(cud_2, bytes)
+ curses.putp(cud_2)
+
+ curses.putp(b'abc\n')
+
+ def test_misc_module_funcs(self):
+ curses.delay_output(1)
+ curses.flushinp()
- win4 = stdscr.derwin(2,2)
- win4 = stdscr.derwin(1,1, 5,5)
- win4.mvderwin(9,9)
+ curses.doupdate()
+ self.assertIs(curses.isendwin(), False)
- stdscr.echochar('a')
- stdscr.echochar('a', curses.A_BOLD)
- stdscr.hline('-', 5)
- stdscr.hline('-', 5, curses.A_BOLD)
- stdscr.hline(1,1,'-', 5)
- stdscr.hline(1,1,'-', 5, curses.A_BOLD)
+ curses.napms(100)
+
+ curses.newpad(50, 50)
+
+ def test_env_queries(self):
+ # TODO: term_attrs(), erasewchar(), killwchar()
+ self.assertIsInstance(curses.termname(), bytes)
+ self.assertIsInstance(curses.longname(), bytes)
+ self.assertIsInstance(curses.baudrate(), int)
+ self.assertIsInstance(curses.has_ic(), bool)
+ self.assertIsInstance(curses.has_il(), bool)
+ self.assertIsInstance(curses.termattrs(), int)
+
+ c = curses.killchar()
+ self.assertIsInstance(c, bytes)
+ self.assertEqual(len(c), 1)
+ c = curses.erasechar()
+ self.assertIsInstance(c, bytes)
+ self.assertEqual(len(c), 1)
+
+ def test_output_options(self):
+ stdscr = self.stdscr
+
+ stdscr.clearok(True)
+ stdscr.clearok(False)
+
+ stdscr.idcok(True)
+ stdscr.idcok(False)
+
+ stdscr.idlok(False)
+ stdscr.idlok(True)
- stdscr.idcok(1)
- stdscr.idlok(1)
if hasattr(stdscr, 'immedok'):
- stdscr.immedok(1)
- stdscr.immedok(0)
- stdscr.insch('c')
- stdscr.insdelln(1)
- stdscr.insnstr('abc', 3)
- stdscr.insnstr('abc', 3, curses.A_BOLD)
- stdscr.insnstr(5, 5, 'abc', 3)
- stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
-
- stdscr.insstr('def')
- stdscr.insstr('def', curses.A_BOLD)
- stdscr.insstr(5, 5, 'def')
- stdscr.insstr(5, 5, 'def', curses.A_BOLD)
- stdscr.is_linetouched(0)
- stdscr.keypad(1)
- stdscr.leaveok(1)
- stdscr.move(3,3)
- win.mvwin(2,2)
- stdscr.nodelay(1)
- stdscr.notimeout(1)
- win2.overlay(win)
- win2.overwrite(win)
- win2.overlay(win, 1, 2, 2, 1, 3, 3)
- win2.overwrite(win, 1, 2, 2, 1, 3, 3)
- stdscr.redrawln(1,2)
-
- stdscr.scrollok(1)
- stdscr.scroll()
- stdscr.scroll(2)
- stdscr.scroll(-3)
-
- stdscr.move(12, 2)
- stdscr.setscrreg(10,15)
- win3 = stdscr.subwin(10,10)
- win3 = stdscr.subwin(10,10, 5,5)
- if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
- stdscr.syncok(1)
- stdscr.timeout(5)
- stdscr.touchline(5,5)
- stdscr.touchline(5,5,0)
- stdscr.vline('a', 3)
- stdscr.vline('a', 3, curses.A_STANDOUT)
- if hasattr(stdscr, 'chgat'):
- stdscr.chgat(5, 2, 3, curses.A_BLINK)
- stdscr.chgat(3, curses.A_BOLD)
- stdscr.chgat(5, 8, curses.A_UNDERLINE)
- stdscr.chgat(curses.A_BLINK)
- stdscr.refresh()
+ stdscr.immedok(True)
+ stdscr.immedok(False)
- stdscr.vline(1,1, 'a', 3)
- stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
+ stdscr.leaveok(True)
+ stdscr.leaveok(False)
- if hasattr(stdscr, 'resize'):
- stdscr.resize(25, 80)
- if hasattr(stdscr, 'enclose'):
- stdscr.enclose(10, 10)
+ stdscr.scrollok(True)
+ stdscr.scrollok(False)
- with tempfile.TemporaryFile() as f:
- self.stdscr.putwin(f)
- f.seek(0)
- curses.getwin(f)
+ stdscr.setscrreg(5, 10)
- self.assertRaises(ValueError, stdscr.getstr, -400)
- self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
- self.assertRaises(ValueError, stdscr.instr, -2)
- self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
+ curses.nonl()
+ curses.nl(True)
+ curses.nl(False)
+ curses.nl()
- def test_embedded_null_chars(self):
- # reject embedded null bytes and characters
+
+ def test_input_options(self):
stdscr = self.stdscr
- for arg in ['a', b'a']:
- with self.subTest(arg=arg):
- self.assertRaises(ValueError, stdscr.addstr, 'a\0')
- self.assertRaises(ValueError, stdscr.addnstr, 'a\0', 1)
- self.assertRaises(ValueError, stdscr.insstr, 'a\0')
- self.assertRaises(ValueError, stdscr.insnstr, 'a\0', 1)
-
- def test_module_funcs(self):
- "Test module-level functions"
- for func in [curses.baudrate, curses.beep, curses.can_change_color,
- curses.doupdate, curses.flash, curses.flushinp,
- curses.has_colors, curses.has_ic, curses.has_il,
- curses.isendwin, curses.killchar, curses.longname,
- curses.noecho, curses.nonl, curses.noqiflush,
- curses.termattrs, curses.termname, curses.erasechar]:
- with self.subTest(func=func.__qualname__):
- func()
+
if self.isatty:
- for func in [curses.cbreak, curses.def_prog_mode,
- curses.nocbreak, curses.noraw,
- curses.reset_prog_mode]:
- with self.subTest(func=func.__qualname__):
- func()
- if hasattr(curses, 'filter'):
- curses.filter()
- if hasattr(curses, 'getsyx'):
- curses.getsyx()
-
- # Functions that actually need arguments
- if curses.tigetstr("cnorm"):
- curses.curs_set(1)
- curses.delay_output(1)
- curses.echo() ; curses.echo(1)
+ curses.nocbreak()
+ curses.cbreak()
+ curses.cbreak(False)
+ curses.cbreak(True)
+
+ curses.intrflush(True)
+ curses.intrflush(False)
+ curses.raw()
+ curses.raw(False)
+ curses.raw(True)
+ curses.noraw()
+
+ curses.noecho()
+ curses.echo()
+ curses.echo(False)
+ curses.echo(True)
+
+ curses.halfdelay(255)
curses.halfdelay(1)
- if self.isatty:
- curses.intrflush(1)
- curses.meta(1)
- curses.napms(100)
- curses.newpad(50,50)
- win = curses.newwin(5,5)
- win = curses.newwin(5,5, 1,1)
- curses.nl() ; curses.nl(1)
- curses.putp(b'abc')
+
+ stdscr.keypad(True)
+ stdscr.keypad(False)
+
+ curses.meta(True)
+ curses.meta(False)
+
+ stdscr.nodelay(True)
+ stdscr.nodelay(False)
+
+ curses.noqiflush()
+ curses.qiflush(True)
+ curses.qiflush(False)
curses.qiflush()
- if self.isatty:
- curses.raw() ; curses.raw(1)
+
+ stdscr.notimeout(True)
+ stdscr.notimeout(False)
+
+ stdscr.timeout(-1)
+ stdscr.timeout(0)
+ stdscr.timeout(5)
+
+ @requires_curses_func('typeahead')
+ def test_typeahead(self):
+ curses.typeahead(sys.__stdin__.fileno())
+ curses.typeahead(-1)
+
+ def test_prog_mode(self):
+ if not self.isatty:
+ self.skipTest('requires terminal')
+ curses.def_prog_mode()
+ curses.reset_prog_mode()
+
+ def test_beep(self):
+ if (curses.tigetstr("bel") is not None
+ or curses.tigetstr("flash") is not None):
+ curses.beep()
+ else:
+ try:
+ curses.beep()
+ except curses.error:
+ self.skipTest('beep() failed')
+
+ def test_flash(self):
+ if (curses.tigetstr("bel") is not None
+ or curses.tigetstr("flash") is not None):
+ curses.flash()
+ else:
+ try:
+ curses.flash()
+ except curses.error:
+ self.skipTest('flash() failed')
+
+ def test_curs_set(self):
+ for vis, cap in [(0, 'civis'), (2, 'cvvis'), (1, 'cnorm')]:
+ if curses.tigetstr(cap) is not None:
+ curses.curs_set(vis)
+ else:
+ try:
+ curses.curs_set(vis)
+ except curses.error:
+ pass
+
+ @requires_curses_func('get_escdelay')
+ def test_escdelay(self):
+ escdelay = curses.get_escdelay()
+ self.assertIsInstance(escdelay, int)
curses.set_escdelay(25)
self.assertEqual(curses.get_escdelay(), 25)
+ curses.set_escdelay(escdelay)
+
+ @requires_curses_func('get_tabsize')
+ def test_tabsize(self):
+ tabsize = curses.get_tabsize()
+ self.assertIsInstance(tabsize, int)
curses.set_tabsize(4)
self.assertEqual(curses.get_tabsize(), 4)
- if hasattr(curses, 'setsyx'):
- curses.setsyx(5,5)
- curses.tigetflag('hc')
- curses.tigetnum('co')
- curses.tigetstr('cr')
- curses.tparm(b'cr')
- if hasattr(curses, 'typeahead'):
- curses.typeahead(sys.__stdin__.fileno())
- curses.unctrl('a')
- curses.ungetch('a')
- if hasattr(curses, 'use_env'):
- curses.use_env(1)
-
- # Functions only available on a few platforms
+ curses.set_tabsize(tabsize)
+
+ @requires_curses_func('getsyx')
+ def test_getsyx(self):
+ y, x = curses.getsyx()
+ self.assertIsInstance(y, int)
+ self.assertIsInstance(x, int)
+ curses.setsyx(4, 5)
+ self.assertEqual(curses.getsyx(), (4, 5))
def bad_colors(self):
return (-2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
@@ -323,6 +844,10 @@ def bad_colors(self):
def bad_pairs(self):
return (-2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
+ def test_has_colors(self):
+ self.assertIsInstance(curses.has_colors(), bool)
+ self.assertIsInstance(curses.can_change_color(), bool)
+
def test_start_color(self):
if not curses.has_colors():
self.skipTest('requires colors support')
@@ -346,7 +871,7 @@ def test_color_content(self):
@requires_colors
def test_init_color(self):
- if not curses.can_change_color:
+ if not curses.can_change_color():
self.skipTest('cannot change color')
old = curses.color_content(0)
@@ -434,14 +959,22 @@ def test_color_attrs(self):
@requires_curses_func('use_default_colors')
@requires_colors
def test_use_default_colors(self):
- self.assertIn(curses.pair_content(0),
- ((curses.COLOR_WHITE, curses.COLOR_BLACK), (-1, -1)))
- curses.use_default_colors()
+ old = curses.pair_content(0)
+ try:
+ curses.use_default_colors()
+ except curses.error:
+ self.skipTest('cannot change color (use_default_colors() failed)')
self.assertEqual(curses.pair_content(0), (-1, -1))
+ self.assertIn(old, [(curses.COLOR_WHITE, curses.COLOR_BLACK), (-1, -1), (0, 0)])
- @requires_curses_func('keyname')
def test_keyname(self):
- curses.keyname(13)
+ # TODO: key_name()
+ self.assertEqual(curses.keyname(65), b'A')
+ self.assertEqual(curses.keyname(13), b'^M')
+ self.assertEqual(curses.keyname(127), b'^?')
+ self.assertEqual(curses.keyname(0), b'^@')
+ self.assertRaises(ValueError, curses.keyname, -1)
+ self.assertIsInstance(curses.keyname(256), bytes)
@requires_curses_func('has_key')
def test_has_key(self):
@@ -497,22 +1030,46 @@ def test_new_curses_panel(self):
@requires_curses_func('is_term_resized')
def test_is_term_resized(self):
- curses.is_term_resized(*self.stdscr.getmaxyx())
+ lines, cols = curses.LINES, curses.COLS
+ self.assertIs(curses.is_term_resized(lines, cols), False)
+ self.assertIs(curses.is_term_resized(lines-1, cols-1), True)
@requires_curses_func('resize_term')
def test_resize_term(self):
- curses.resize_term(*self.stdscr.getmaxyx())
+ curses.update_lines_cols()
+ lines, cols = curses.LINES, curses.COLS
+ new_lines = lines - 1
+ new_cols = cols + 1
+ curses.resize_term(new_lines, new_cols)
+ self.assertEqual(curses.LINES, new_lines)
+ self.assertEqual(curses.COLS, new_cols)
+
+ curses.resize_term(lines, cols)
+ self.assertEqual(curses.LINES, lines)
+ self.assertEqual(curses.COLS, cols)
@requires_curses_func('resizeterm')
def test_resizeterm(self):
+ curses.update_lines_cols()
lines, cols = curses.LINES, curses.COLS
new_lines = lines - 1
new_cols = cols + 1
curses.resizeterm(new_lines, new_cols)
-
self.assertEqual(curses.LINES, new_lines)
self.assertEqual(curses.COLS, new_cols)
+ curses.resizeterm(lines, cols)
+ self.assertEqual(curses.LINES, lines)
+ self.assertEqual(curses.COLS, cols)
+
+ def test_ungetch(self):
+ curses.ungetch(b'A')
+ self.assertEqual(self.stdscr.getkey(), 'A')
+ curses.ungetch('B')
+ self.assertEqual(self.stdscr.getkey(), 'B')
+ curses.ungetch(67)
+ self.assertEqual(self.stdscr.getkey(), 'C')
+
def test_issue6243(self):
curses.ungetch(1025)
self.stdscr.getkey()
@@ -541,10 +1098,6 @@ def test_unget_wch(self):
read = stdscr.get_wch()
self.assertEqual(read, ch)
- def test_issue10570(self):
- b = curses.tparm(curses.tigetstr("cup"), 5, 3)
- self.assertIs(type(b), bytes)
-
def test_encoding(self):
stdscr = self.stdscr
import codecs
@@ -584,26 +1137,25 @@ def test_issue21088(self):
human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
self.assertIn("[y, x,]", human_readable_signature)
+ @requires_curses_window_meth('resize')
def test_issue13051(self):
- stdscr = self.stdscr
- if not hasattr(stdscr, 'resize'):
- raise unittest.SkipTest('requires curses.window.resize')
- box = curses.textpad.Textbox(stdscr, insert_mode=True)
- lines, cols = stdscr.getmaxyx()
- stdscr.resize(lines-2, cols-2)
+ win = curses.newwin(5, 15, 2, 5)
+ box = curses.textpad.Textbox(win, insert_mode=True)
+ lines, cols = win.getmaxyx()
+ win.resize(lines-2, cols-2)
# this may cause infinite recursion, leading to a RuntimeError
box._insert_printable_char('a')
class MiscTests(unittest.TestCase):
- @requires_curses_func('update_lines_cols')
def test_update_lines_cols(self):
- # this doesn't actually test that LINES and COLS are updated,
- # because we can't automate changing them. See Issue #4254 for
- # a manual test script. We can only test that the function
- # can be called.
curses.update_lines_cols()
+ lines, cols = curses.LINES, curses.COLS
+ curses.LINES = curses.COLS = 0
+ curses.update_lines_cols()
+ self.assertEqual(curses.LINES, lines)
+ self.assertEqual(curses.COLS, cols)
@requires_curses_func('ncurses_version')
def test_ncurses_version(self):
@@ -625,6 +1177,7 @@ def test_ncurses_version(self):
self.assertGreaterEqual(v.minor, 0)
self.assertGreaterEqual(v.patch, 0)
+
class TestAscii(unittest.TestCase):
def test_controlnames(self):
@@ -713,5 +1266,21 @@ def test_unctrl(self):
self.assertEqual(unctrl(ord('\xc1')), '!A')
+def lorem_ipsum(win):
+ text = [
+ 'Lorem ipsum',
+ 'dolor sit amet,',
+ 'consectetur',
+ 'adipiscing elit,',
+ 'sed do eiusmod',
+ 'tempor incididunt',
+ 'ut labore et',
+ 'dolore magna',
+ 'aliqua.',
+ ]
+ maxy, maxx = win.getmaxyx()
+ for y, line in enumerate(text[:maxy]):
+ win.addstr(y, 0, line[:maxx - (y == maxy - 1)])
+
if __name__ == '__main__':
unittest.main()
1
0
https://github.com/python/cpython/commit/8a833a6f94d8c2baa6aa38abd9fc699881…
commit: 8a833a6f94d8c2baa6aa38abd9fc699881a5b0e1
branch: 3.9
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: miss-islington <31488909+miss-islington(a)users.noreply.github.com>
date: 2021-01-31T08:06:15-08:00
summary:
bpo-43083: Fix error handling in _sqlite3 (GH-24395)
(cherry picked from commit 9073180db521dc83e6216ff0da1479d00167f643)
Co-authored-by: Serhiy Storchaka <storchaka(a)gmail.com>
files:
M Modules/_sqlite/connection.c
M Modules/_sqlite/cursor.c
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index b80037347f13b..d20339ca3f7df 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -1704,7 +1704,11 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
(callable != Py_None) ? callable : NULL,
(callable != Py_None) ? pysqlite_collation_callback : NULL);
if (rc != SQLITE_OK) {
- PyDict_DelItem(self->collations, uppercase_name);
+ if (callable != Py_None) {
+ if (PyDict_DelItem(self->collations, uppercase_name) < 0) {
+ PyErr_Clear();
+ }
+ }
_pysqlite_seterror(self->db, NULL);
goto finally;
}
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index 5cfb4b97d61df..dd0ce7e1ea6a3 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -569,11 +569,13 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
}
if (!multiple) {
- Py_DECREF(self->lastrowid);
Py_BEGIN_ALLOW_THREADS
lastrowid = sqlite3_last_insert_rowid(self->connection->db);
Py_END_ALLOW_THREADS
- self->lastrowid = PyLong_FromLongLong(lastrowid);
+ Py_SETREF(self->lastrowid, PyLong_FromLongLong(lastrowid));
+ if (self->lastrowid == NULL) {
+ goto error;
+ }
}
if (rc == SQLITE_ROW) {
@@ -802,8 +804,11 @@ PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObj
}
while ((row = pysqlite_cursor_iternext(self))) {
- PyList_Append(list, row);
- Py_XDECREF(row);
+ if (PyList_Append(list, row) < 0) {
+ Py_DECREF(row);
+ break;
+ }
+ Py_DECREF(row);
if (++counter == maxrows) {
break;
@@ -829,8 +834,11 @@ PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args)
}
while ((row = pysqlite_cursor_iternext(self))) {
- PyList_Append(list, row);
- Py_XDECREF(row);
+ if (PyList_Append(list, row) < 0) {
+ Py_DECREF(row);
+ break;
+ }
+ Py_DECREF(row);
}
if (PyErr_Occurred()) {
1
0