Commit 39cf34975d9c289c2ef4535c912e974716ac24b4
1 parent
e8c49e49
Rewrite set_to_object()
The new version supports nested objects (i.e. dictionaries in dictionaries and lists in dictionaries) just like the old one. Unlike the old version, the new one supports recursion (lists in dictionaries in lists of dictionaries in dictionaries in lists of dictionaries ...). Two-dimensional lists (lists of lists) are not yet supported.
Showing
1 changed file
with
64 additions
and
23 deletions
... | ... | @@ -379,29 +379,70 @@ def get_from_object(obj, path): |
379 | 379 | raise AttributeError('Attribute not found: {0}'.format(path)) |
380 | 380 | |
381 | 381 | |
382 | -def set_to_object(obj, attribute, value): | |
383 | - # Search the list index in path to value | |
384 | - list_index = re.search('\d+', attribute) | |
385 | - if list_index and attribute != 'stage2TenderID': | |
386 | - list_index = list_index.group(0) | |
387 | - parent, child = attribute.split('[' + list_index + '].')[:2] | |
388 | - # Split attribute to path to lits (parent) and path to value in list element (child) | |
389 | - try: | |
390 | - # Get list from parent | |
391 | - listing = get_from_object(obj, parent) | |
392 | - # Create object with list_index if he don`t exist | |
393 | - if len(listing) < int(list_index) + 1: | |
394 | - listing.append({}) | |
395 | - except AttributeError: | |
396 | - # Create list if he don`t exist | |
397 | - listing = [{}] | |
398 | - # Update list in parent | |
399 | - xpathnew(obj, parent, listing, separator='.') | |
400 | - # Set value in obj | |
401 | - xpathnew(obj, '.'.join([parent, list_index, child]), value, separator='.') | |
402 | - else: | |
403 | - xpathnew(obj, attribute, value, separator='.') | |
404 | - return munchify(obj) | |
382 | +def set_to_object(obj, path, value): | |
383 | + def recur(obj, path, value): | |
384 | + if not isinstance(obj, dict): | |
385 | + raise TypeError('expected %s, got %s' % | |
386 | + (dict.__name__, type(obj))) | |
387 | + | |
388 | + # Search the list index in path to value | |
389 | + groups = re.search(r'^(?P<key>[0-9a-zA-Z_]+)(?:\[(?P<index>-?\d+)\])?' | |
390 | + '(?:\.(?P<suffix>.+))?$', path) | |
391 | + | |
392 | + err = RuntimeError('could not parse the path: ' + path) | |
393 | + if not groups: | |
394 | + raise err | |
395 | + | |
396 | + gd = {k: v for k, v in groups.groupdict().items() if v is not None} | |
397 | + is_list = False | |
398 | + suffix = None | |
399 | + | |
400 | + if 'key' not in gd: | |
401 | + raise err | |
402 | + key = gd['key'] | |
403 | + | |
404 | + if 'index' in gd: | |
405 | + is_list = True | |
406 | + index = int(gd['index']) | |
407 | + | |
408 | + if 'suffix' in gd: | |
409 | + suffix = gd['suffix'] | |
410 | + | |
411 | + if is_list: | |
412 | + if key not in obj: | |
413 | + obj[key] = [] | |
414 | + elif not isinstance(obj[key], list): | |
415 | + raise TypeError('expected %s, got %s' % | |
416 | + (list.__name__, type(obj[key]))) | |
417 | + | |
418 | + plusone = 1 if index >= 0 else 0 | |
419 | + if len(obj[key]) < abs(index) + plusone: | |
420 | + while not len(obj[key]) == abs(index) + plusone: | |
421 | + extension = [None for _ in | |
422 | + range(abs(index) + plusone - len(obj[key]))] | |
423 | + if index < 0: | |
424 | + obj[key] = extension + obj[key] | |
425 | + else: | |
426 | + obj[key].extend(extension) | |
427 | + if suffix: | |
428 | + obj[key][index] = {} | |
429 | + if suffix: | |
430 | + obj[key][index] = recur(obj[key][index], suffix, value) | |
431 | + else: | |
432 | + obj[key][index] = value | |
433 | + else: | |
434 | + if key not in obj: | |
435 | + obj[key] = {} | |
436 | + if suffix: | |
437 | + obj[key] = recur(obj[key], suffix, value) | |
438 | + else: | |
439 | + obj[key] = value | |
440 | + | |
441 | + return obj | |
442 | + | |
443 | + if not isinstance(path, STR_TYPES): | |
444 | + raise TypeError('Path must be one of %s' % str(STR_TYPES)) | |
445 | + return munchify(recur(obj, path, value)) | |
405 | 446 | |
406 | 447 | |
407 | 448 | def wait_to_date(date_stamp): | ... | ... |
Please
register
or
login
to post a comment