- Notifications
You must be signed in to change notification settings - Fork 123
Add 3rd party regex support #925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -1730,6 +1730,20 @@ ensure_is_finite_numeric(PyObject *val, const char *param, bool positive) { | |
| return true; | ||
| } | ||
| | ||
| static bool | ||
| ensure_is_re_pattern_compatible (PyObject *val, const char *param) { | ||
| if (PyUnicode_CheckExact(val)) return true; | ||
| if (PyObject_HasAttrString(val, "pattern") && PyObject_HasAttrString(val, "search")) { | ||
| Contributor Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check is currently very rudimentary. How strict do we want to be with this? Another option would be to make the | ||
| return true; | ||
| } | ||
| PyErr_Format( | ||
| PyExc_TypeError, | ||
| "`%s` must be a str, or an re.Pattern like type, got %.200s", | ||
| param, Py_TYPE(val)->tp_name | ||
| ); | ||
| return false; | ||
| } | ||
| | ||
| PyDoc_STRVAR(Meta__doc__, | ||
| "Meta(*, gt=None, ge=None, lt=None, le=None, multiple_of=None, pattern=None, " | ||
| "min_length=None, max_length=None, tz=None, title=None, description=None, " | ||
| | @@ -1846,7 +1860,7 @@ Meta_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { | |
| if (lt != NULL && !ensure_is_finite_numeric(lt, "lt", false)) return NULL; | ||
| if (le != NULL && !ensure_is_finite_numeric(le, "le", false)) return NULL; | ||
| if (multiple_of != NULL && !ensure_is_finite_numeric(multiple_of, "multiple_of", true)) return NULL; | ||
| if (pattern != NULL && !ensure_is_string(pattern, "pattern")) return NULL; | ||
| if (pattern != NULL && !ensure_is_re_pattern_compatible(pattern, "pattern")) return NULL; | ||
| if (min_length != NULL && !ensure_is_nonnegative_integer(min_length, "min_length")) return NULL; | ||
| if (max_length != NULL && !ensure_is_nonnegative_integer(max_length, "max_length")) return NULL; | ||
| if (tz != NULL && !ensure_is_bool(tz, "tz")) return NULL; | ||
| | @@ -1901,9 +1915,16 @@ Meta_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { | |
| | ||
| /* regex compile pattern if provided */ | ||
| if (pattern != NULL) { | ||
| MsgspecState *mod = msgspec_get_global_state(); | ||
| regex = PyObject_CallOneArg(mod->re_compile, pattern); | ||
| if (regex == NULL) return NULL; | ||
| if (PyUnicode_Check(pattern)) { | ||
| // 'pattern' is a string; compile it using re.compile | ||
| MsgspecState *mod = msgspec_get_global_state(); | ||
| regex = PyObject_CallOneArg(mod->re_compile, pattern); | ||
| if (regex == NULL) return NULL; | ||
| } else { | ||
| // 'pattern' is an re.Pattern like object. no need to do anything | ||
| // do no Py_INCREF here, since will be done during SET_FIELD later | ||
| regex = pattern; | ||
| } | ||
| } | ||
| | ||
| Meta *out = (Meta *)Meta_Type.tp_alloc(&Meta_Type, 0); | ||
| | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -331,3 +331,14 @@ def inner(obj): | |
| def rebuild(cls, kwargs): | ||
| """Used to unpickle Structs with keyword-only fields""" | ||
| return cls(**kwargs) | ||
| | ||
| | ||
| class RegexPatternProtocol(typing.Protocol): | ||
| Contributor Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've kept the required API as minimal as possible here. | ||
| pattern: str | ||
| | ||
| def search( | ||
| self, | ||
| string: str, | ||
| pos: int = 0, | ||
| endpos: int = sys.maxsize, | ||
| ) -> object | None: ... | ||
| Contributor Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Returning | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to publish this?