|
1 | 1 | import datetime |
2 | | -from typing import Union |
| 2 | + |
| 3 | +from python_utils import types |
3 | 4 |
|
4 | 5 |
|
5 | 6 | def camel_to_underscore(name: str) -> str: |
6 | | - '''Convert camel case style naming to underscore style naming |
| 7 | + '''Convert camel case style naming to underscore/snake case style naming |
7 | 8 |
|
8 | 9 | If there are existing underscores they will be collapsed with the |
9 | 10 | to-be-added underscores. Multiple consecutive capital letters will not be |
@@ -40,8 +41,44 @@ def camel_to_underscore(name: str) -> str: |
40 | 41 | return ''.join(output) |
41 | 42 |
|
42 | 43 |
|
43 | | -def timesince(dt: Union[datetime.datetime, datetime.timedelta], |
44 | | - default: str = 'just now') -> str: |
| 44 | +def apply_recursive( |
| 45 | + function: types.Callable[[str], str], |
| 46 | + data: types.OptionalScope = None, |
| 47 | + **kwargs |
| 48 | +) -> types.OptionalScope: |
| 49 | + ''' |
| 50 | + Apply a function to all keys in a scope recursively |
| 51 | +
|
| 52 | + >>> apply_recursive(camel_to_underscore, {'SpamEggsAndBacon': 'spam'}) |
| 53 | + {'spam_eggs_and_bacon': 'spam'} |
| 54 | + >>> apply_recursive(camel_to_underscore, {'SpamEggsAndBacon': { |
| 55 | + ... 'SpamEggsAndBacon': 'spam', |
| 56 | + ... }}) |
| 57 | + {'spam_eggs_and_bacon': {'spam_eggs_and_bacon': 'spam'}} |
| 58 | +
|
| 59 | + >>> a = {'a_b_c': 123, 'def': {'DeF': 456}} |
| 60 | + >>> b = apply_recursive(camel_to_underscore, a) |
| 61 | + >>> b |
| 62 | + {'a_b_c': 123, 'def': {'de_f': 456}} |
| 63 | +
|
| 64 | + >>> apply_recursive(camel_to_underscore, None) |
| 65 | + ''' |
| 66 | + if data is None: |
| 67 | + return None |
| 68 | + |
| 69 | + elif isinstance(data, dict): |
| 70 | + return { |
| 71 | + function(key): apply_recursive(function, value, **kwargs) |
| 72 | + for key, value in data.items() |
| 73 | + } |
| 74 | + else: |
| 75 | + return data |
| 76 | + |
| 77 | + |
| 78 | +def timesince( |
| 79 | + dt: types.Union[datetime.datetime, datetime.timedelta], |
| 80 | + default: str = 'just now' |
| 81 | +) -> str: |
45 | 82 | ''' |
46 | 83 | Returns string representing 'time since' e.g. |
47 | 84 | 3 days ago, 5 hours ago etc. |
|
0 commit comments