Convert a key into something that is accessible as an attribute
(self, attr)
| 902 | return self[item] |
| 903 | |
| 904 | def _safe_attr(self, attr): |
| 905 | """Convert a key into something that is accessible as an attribute""" |
| 906 | if isinstance(attr, str): |
| 907 | # By assuming most people are using string first we get substantial speed ups |
| 908 | if attr.isidentifier() and not iskeyword(attr): |
| 909 | return attr |
| 910 | |
| 911 | if isinstance(attr, tuple): |
| 912 | attr = "_".join([str(x) for x in attr]) |
| 913 | |
| 914 | attr = attr.decode("utf-8", "ignore") if isinstance(attr, bytes) else str(attr) |
| 915 | if self.__box_config()["camel_killer_box"]: |
| 916 | attr = _camel_killer(attr) |
| 917 | |
| 918 | if attr.isidentifier() and not iskeyword(attr): |
| 919 | return attr |
| 920 | |
| 921 | if sum(1 for character in attr if character.isidentifier() and not iskeyword(character)) == 0: |
| 922 | attr = f'{self.__box_config()["box_safe_prefix"]}{attr}' |
| 923 | if attr.isidentifier() and not iskeyword(attr): |
| 924 | return attr |
| 925 | |
| 926 | out = [] |
| 927 | last_safe = 0 |
| 928 | for i, character in enumerate(attr): |
| 929 | if f"x{character}".isidentifier(): |
| 930 | last_safe = i |
| 931 | out.append(character) |
| 932 | elif not out: |
| 933 | continue |
| 934 | else: |
| 935 | if last_safe == i - 1: |
| 936 | out.append("_") |
| 937 | |
| 938 | out = "".join(out)[: last_safe + 1] |
| 939 | |
| 940 | try: |
| 941 | int(out[0]) |
| 942 | except (ValueError, IndexError): |
| 943 | pass |
| 944 | else: |
| 945 | out = f'{self.__box_config()["box_safe_prefix"]}{out}' |
| 946 | |
| 947 | if iskeyword(out): |
| 948 | out = f'{self.__box_config()["box_safe_prefix"]}{out}' |
| 949 | |
| 950 | return out |
| 951 | |
| 952 | def _conversion_checks(self, item): |
| 953 | """ |