| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 504ddd3 commit 8254e87
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,10 +3,16 @@ | |||
| 3 | 3 | All functions take cursor offset from the beginning of the line and the line of | |
| 4 | 4 | Python code, and return None, or a tuple of the start index, end index, and the | |
| 5 | 5 | word.""" | |
| 6 | + from __future__ import unicode_literals | ||
| 7 | + | ||
| 8 | + import re | ||
| 6 | 9 | ||
| 7 | 10 | from itertools import chain | |
| 8 | 11 | from collections import namedtuple | |
| 12 | + from pygments.token import Token | ||
| 13 | + | ||
| 9 | 14 | from bpython.lazyre import LazyReCompile | |
| 15 | + from bpython._py3compat import PythonLexer, py3 | ||
| 10 | 16 | ||
| 11 | 17 | current_word_re = LazyReCompile(r'[\w_][\w0-9._]*[(]?') | |
| 12 | 18 | LinePart = namedtuple('LinePart', ['start', 'stop', 'word']) | |
@@ -93,7 +99,7 @@ def current_object(cursor_offset, line): | |||
| 93 | 99 | return LinePart(start, start+len(s), s) | |
| 94 | 100 | ||
| 95 | 101 | ||
| 96 | - current_object_attribute_re = LazyReCompile(r'([\w_][\w0-9_]*)[.]?') | ||
| 102 | + current_object_attribute_re = LazyReCompile(r'([\w_][\w0-9_]*)') | ||
| 97 | 103 | ||
| 98 | 104 | ||
| 99 | 105 | def current_object_attribute(cursor_offset, line): | |
@@ -264,14 +270,40 @@ def current_indexed_member_access_member(cursor_offset, line): | |||
| 264 | 270 | if m.start(3) <= cursor_offset and m.end(3) >= cursor_offset: | |
| 265 | 271 | return LinePart(m.start(3), m.end(3), m.group(3)) | |
| 266 | 272 | ||
| 273 | + current_simple_expression_re = LazyReCompile( | ||
| 274 | + r'''([a-zA-Z_][\w.]*)\[([a-zA-Z0-9_"']+)\]\.([\w.]*)''') | ||
| 275 | + | ||
| 276 | + def _current_simple_expression(cursor_offset, line): | ||
| 277 | + """ | ||
| 278 | + Returns the current "simple expression" being attribute accessed | ||
| 279 | + | ||
| 280 | + build asts from with increasing numbers of characters. | ||
| 281 | + Find the biggest valid ast. | ||
| 282 | + Once our attribute access is a subtree, stop | ||
| 283 | + | ||
| 284 | + | ||
| 285 | + """ | ||
| 286 | + for i in range(cursor): | ||
| 287 | + pass | ||
| 288 | + | ||
| 289 | + | ||
| 267 | 290 | def current_simple_expression(cursor_offset, line): | |
| 268 | 291 | """The expression attribute lookup being performed on | |
| 269 | 292 | ||
| 270 | 293 | e.g. <foo[0][1].bar>.ba|z | |
| 271 | 294 | A "simple expression" contains only . lookup and [] indexing.""" | |
| 272 | 295 | ||
| 296 | + | ||
| 273 | 297 | def current_simple_expression_attribute(cursor_offset, line): | |
| 274 | 298 | """The attribute being looked up on a simple expression | |
| 275 | 299 | ||
| 276 | 300 | e.g. foo[0][1].bar.<ba|z> | |
| 277 | 301 | A "simple expression" contains only . lookup and [] indexing.""" | |
| 302 | + | ||
| 303 | + | ||
| 304 | + | ||
| 305 | + | ||
| 306 | + | ||
| 307 | + | ||
| 308 | + | ||
| 309 | + | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -81,3 +81,33 @@ def safe_getitem(obj, index): | |||
| 81 | 81 | if type(obj) in (list, tuple, dict, bytes) + string_types: | |
| 82 | 82 | return obj[index] | |
| 83 | 83 | raise ValueError('unsafe to lookup on object of type %s' % (type(obj), )) | |
| 84 | + | ||
| 85 | + | ||
| 86 | + class AttributeSearcher(NodeVisitor): | ||
| 87 | + """Search for a Load of an Attribute at col_offset""" | ||
| 88 | + def visit_attribute(self, node): | ||
| 89 | + print node.attribute | ||
| 90 | + | ||
| 91 | + def _current_simple_expression(cursor_offset, line): | ||
| 92 | + """ | ||
| 93 | + Returns the current "simple expression" being attribute accessed | ||
| 94 | + | ||
| 95 | + build asts from with increasing numbers of characters. | ||
| 96 | + Find the biggest valid ast. | ||
| 97 | + Once our attribute access is a subtree, stop | ||
| 98 | + | ||
| 99 | + | ||
| 100 | + """ | ||
| 101 | + | ||
| 102 | + # in case attribute is blank, e.g. foo.| -> foo.xxx| | ||
| 103 | + temp_line = line[:cursor_offset] + 'xxx' + line[cursor_offset:] | ||
| 104 | + temp_cursor = cursor_offset + 3 | ||
| 105 | + | ||
| 106 | + for i in range(temp_cursor-1, -1, -1): | ||
| 107 | + try: | ||
| 108 | + tree = parse(temp_line[i:temp_cursor]) | ||
| 109 | + except SyntaxError: | ||
| 110 | + return None | ||
| 111 | + | ||
| 112 | + | ||
| 113 | + | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -225,6 +225,11 @@ def test_simple(self): | |||
| 225 | 225 | self.assertAccess('stuff[asdf[asd|fg]') | |
| 226 | 226 | self.assertAccess('Object.attr1.<|attr2>') | |
| 227 | 227 | self.assertAccess('Object.<attr1|>.attr2') | |
| 228 | + self.assertAccess('Object.<attr1|>.attr2') | ||
| 229 | + | ||
| 230 | + def test_after_dot(self): | ||
| 231 | + self.assertAccess('Object.<attr1|>.') | ||
| 232 | + self.assertAccess('Object.attr1.|') | ||
| 228 | 233 | ||
| 229 | 234 | ||
| 230 | 235 | class TestCurrentFromImportFrom(LineTestCase): | |
@@ -343,42 +348,6 @@ def test_simple(self): | |||
| 343 | 348 | self.assertAccess('abc[def].gh |i') | |
| 344 | 349 | self.assertAccess('abc[def]|') | |
| 345 | 350 | ||
| 346 | - @unittest.skip("TODO") | ||
| 347 | - class TestCurrentSimpleExpression(LineTestCase): | ||
| 348 | - def setUp(self): | ||
| 349 | - self.func = current_simple_expression | ||
| 350 | - | ||
| 351 | - def test_only_dots(self): | ||
| 352 | - self.assertAccess('<Object>.attr1|') | ||
| 353 | - self.assertAccess('<Object>.|') | ||
| 354 | - self.assertAccess('Object|') | ||
| 355 | - self.assertAccess('Object|.') | ||
| 356 | - self.assertAccess('<Object>.|') | ||
| 357 | - self.assertAccess('<Object.attr1>.attr2|') | ||
| 358 | - self.assertAccess('<Object>.att|r1.attr2') | ||
| 359 | - self.assertAccess('stuff[stuff] + {123: 456} + <Object.attr1>.attr2|') | ||
| 360 | - self.assertAccess('stuff[asd|fg]') | ||
| 361 | - self.assertAccess('stuff[asdf[asd|fg]') | ||
| 362 | - | ||
| 363 | - def test_with_brackets(self): | ||
| 364 | - self.assertAccess('<foo[a]>.ba|r') | ||
| 365 | - self.assertAccess('<foo[a]>.ba|r baz[qux]xyzzy') | ||
| 366 | - self.assertAccess('foo[<bar[baz]>.qux|].xyzzy') | ||
| 367 | - self.assertAccess('<foo[bar[baz].qux]>.xyzzy|') | ||
| 368 | - self.assertAccess('foo[bar[baz].qux].xyzzy, <a>.b|') | ||
| 369 | - self.assertAccess('foo[bar[<baz>.|') | ||
| 370 | - self.assertAccess('foo[bar[<baz>.|] + 1].qux') | ||
| 371 | - | ||
| 372 | - def test_cases_disallowed_by_simple_eval(self): | ||
| 373 | - # These are allowed for now, but could be changed. | ||
| 374 | - # for example, function calls are not allowed in simple expressions but | ||
| 375 | - # seem like they'd be a pain to weed out so we catch them in the next step.""" | ||
| 376 | - self.assertAccess('foo().bar|') | ||
| 377 | - self.assertAccess('foo[bar(a, b)].baz|') | ||
| 378 | - self.assertAccess('foo(a, b).bar|') | ||
| 379 | - self.assertAccess('<(1 + 1)>.bar|') | ||
| 380 | - self.assertAccess('<(1 + 1 - foo.bar()[1])>.baz|') | ||
| 381 | - | ||
| 382 | 351 | ||
| 383 | 352 | if __name__ == '__main__': | |
| 384 | 353 | unittest.main() | |
| Back | FazBrowse Home | New Git URL |
0 commit comments