Skip to content

Commit ca0a28d

Browse files
committed
Add compatibility code to not break access of existing int attributes
E.g. 0x1.bit_length() will not require parentheses around the hexadecimal integer literal (like 1.bit_length() for decimal int).
1 parent 384920f commit ca0a28d

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

Lib/test/test_grammar.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ def test_plain_integers(self):
178178
else:
179179
self.fail('Weird maxsize value %r' % maxsize)
180180

181+
def test_attrs_on_hexintegers(self):
182+
good_meth = [m for m in dir(int) if not m.startswith('_')]
183+
for m in good_meth:
184+
self.assertEqual(eval('0x1.' + m), eval('(0x1).' + m))
185+
self.check_syntax_error('0x1.spam', "invalid hexadecimal literal",
186+
lineno=1, offset=4)
187+
self.check_syntax_error('0x1.foo', "invalid hexadecimal literal",
188+
lineno=1, offset=5)
189+
181190
def test_long_integers(self):
182191
x = 0
183192
x = 0xffffffffffffffff

Parser/lexer/lexer.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,24 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
779779
if (c == '.') {
780780
c = tok_nextc(tok);
781781
hexfraction:
782+
/* Allow attribute access on hexadecimal integer literals for
783+
* for existing public attributes on int's, e.g. 0x1.bit_length(). */
784+
if ((c == 'a' && lookahead(tok, "s_integer_ratio")) ||
785+
(c == 't' && lookahead(tok, "o_bytes")) ||
786+
(c == 'b' && (lookahead(tok, "it_count") ||
787+
lookahead(tok, "it_length"))) ||
788+
(c == 'c' && lookahead(tok, "onjugate")) ||
789+
(c == 'd' && lookahead(tok, "enominator")) ||
790+
(c == 'f' && lookahead(tok, "rom_bytes")) ||
791+
(c == 'i' && (lookahead(tok, "mag") ||
792+
lookahead(tok, "s_integer"))) ||
793+
(c == 'n' && lookahead(tok, "umerator")) ||
794+
(c == 'r' && lookahead(tok, "eal")))
795+
{
796+
tok_backup(tok, c);
797+
c = '.';
798+
goto hexint;
799+
}
782800
if (Py_ISXDIGIT(c)) {
783801
c = tok_digits_tail(tok, 16);
784802
if (c == 0) {
@@ -791,6 +809,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
791809
if (c == 'p' || c == 'P') {
792810
goto exponent;
793811
}
812+
hexint:
794813
if (!verify_end_of_number(tok, c, "hexadecimal")) {
795814
return MAKE_TOKEN(ERRORTOKEN);
796815
}

0 commit comments

Comments
 (0)