|
6675 | 6675 |
|
6676 | 6676 | (prefer-method evolve basilisp.lang.interfaces/IRecord basilisp.lang.interfaces/IPersistentMap) |
6677 | 6677 |
|
| 6678 | +(defn -mangle-py-field |
| 6679 | + "Implementation detail of :lpy:fn:`defrecord` to support Python's managled field |
| 6680 | + names." |
| 6681 | + [type-sym field-name] |
| 6682 | + (if (and (.startswith field-name "__") |
| 6683 | + (not (.endswith field-name "__"))) |
| 6684 | + (let [munged-type-name (.lstrip (munge type-sym) "_")] |
| 6685 | + (str "_" munged-type-name field-name)) |
| 6686 | + field-name)) |
| 6687 | + |
6678 | 6688 | (defn ^:private validate-record-fields |
6679 | 6689 | "Validate that record fields do not contain any reserved entries, are not declared as |
6680 | 6690 | mutable, and do not declare any default values." |
|
6779 | 6789 | :map)))) |
6780 | 6790 |
|
6781 | 6791 | new-recmap# (when (seq map#) |
6782 | | - ;; Python attrs does not allow the underscore prefixed |
6783 | | - ;; field name in the constructor |
6784 | | - ["recmap" (->> (mapcat identity map#) |
6785 | | - (apply assoc ~'_recmap))])] |
| 6792 | + ["_recmap" (->> (mapcat identity map#) |
| 6793 | + (apply assoc ~'_recmap))])] |
6786 | 6794 | (->> fields# |
6787 | | - (map (fn [[k# v#]] [(name k#) v#])) |
| 6795 | + (map (fn [[k# v#]] [(munge k#) v#])) |
6788 | 6796 | (mapcat identity) |
6789 | 6797 | (concat new-recmap#) |
6790 | 6798 | (apply evolve ~this-gs)))) |
|
6846 | 6854 | (contains? (.- new-rec# ~'_recmap) f#) |
6847 | 6855 | (recur r# |
6848 | 6856 | (->> (dissoc (.- new-rec# ~'_recmap) f#) |
6849 | | - (evolve new-rec# "recmap"))) |
| 6857 | + (evolve new-rec# "_recmap"))) |
6850 | 6858 |
|
6851 | 6859 | :else |
6852 | 6860 | (recur r# new-rec#)))) |
6853 | 6861 | (~'contains [~this-gs ~key-gs] |
6854 | 6862 | (or (~field-kw-set ~key-gs) |
6855 | 6863 | (contains? ~'_recmap ~key-gs))) |
6856 | 6864 | (~'entry [~this-gs ~key-gs] |
6857 | | - (cond |
6858 | | - (contains? ~field-kw-set ~key-gs) |
6859 | | - (map-entry ~key-gs (python/getattr ~this-gs (munge ~key-gs))) |
6860 | | - |
6861 | | - (contains? ~'_recmap ~key-gs) |
6862 | | - (map-entry ~key-gs (get ~'_recmap ~key-gs)))) |
| 6865 | + (when-let [val# (.val-at ~this-gs ~key-gs)] |
| 6866 | + (map-entry ~key-gs val#))) |
6863 | 6867 | (~'val-at [~this-gs ~key-gs ~'& args#] |
6864 | 6868 | (let [[default#] args#] |
6865 | 6869 | (cond |
6866 | 6870 | (contains? ~field-kw-set ~key-gs) |
6867 | | - (python/getattr ~this-gs (munge ~key-gs)) |
| 6871 | + (python/getattr ~this-gs (-mangle-py-field '~type-name (munge ~key-gs))) |
6868 | 6872 |
|
6869 | 6873 | (contains? ~'_recmap ~key-gs) |
6870 | 6874 | (get ~'_recmap ~key-gs default#)))) |
|
6891 | 6895 | (~'_record_lrepr [~this-gs py-kwargs#] |
6892 | 6896 | (let [{print-meta :print_meta} (py->lisp py-kwargs#) |
6893 | 6897 |
|
6894 | | - ns-name (name *ns*) |
6895 | | - qual-name (.- ~type-name ~'__qualname__)] |
| 6898 | + ;; Accessing this type name directly as `(.-__qualname__ this)` |
| 6899 | + ;; can fail in cases where the type name is munged and starts |
| 6900 | + ;; with a leading double underscore. Python apparently mangles |
| 6901 | + ;; the name as it would for any object field prefixed with a |
| 6902 | + ;; dunder. |
| 6903 | + qual-name (.- (python/type ~this-gs) ~'__qualname__)] |
6896 | 6904 | (cond->> (->> (mapcat identity ~this-gs) |
6897 | 6905 | (apply hash-map) |
6898 | 6906 | (repr) |
6899 | | - (str "#" ns-name "." qual-name)) |
| 6907 | + (str "#" ~(name *ns*) "." qual-name)) |
6900 | 6908 | print-meta (str "^" (repr (meta ~this-gs)) " ")))) |
6901 | 6909 |
|
6902 | 6910 | ;; object |
|
0 commit comments