Skip to main content

Python objective regular expression library

CI Code style: black PyPI version

  • Do you work with regular expressions often?
  • Do you want for them to me better readable and easier to support?

So do I. Tired of writing of ugly mixture of backslashes, brackets and odd symbols, I have started to wonder if there is a better, more elegant way of dealing with them.

And here is result of my thought!

This library is implementation of object-oriented approach of constructing regular expressions.

Usage examples

Let's start with construction of a few simple examples.

>>> import o_re
>>> _objectiveReg = o_re.Text("Hello world!")
>>> print(repr(_objectiveReg))
<Text 'Hello world!'>

As you can see, we have constructed object named _objectiveReg of a Text class. Text class is meant for containing of a primitive text strings that are matched using exact matching.

So, how do we construct the actual regular expression pattern out of this objective regexp? Easy. All objective regexp instances have getRegex() API function that returns regexp representation of given objective regexp.

>>> print(repr(_objectiveReg.get_regex()))
'Hello world!'

for your convinience, there is also the getCompiled() API function that returns the re.compiled object that matches that regexp pattern. It has one optional flags argument that is designed to accept the very same value you have been passing to the re.compile call. Please see Python documentation for the list of its possible values.

As you can see, the Text class automatically escapes all symbols that have special meaning:

>>> print(o_re.Text("^.*$").get_regex())
\^\.\*\$

So you can safely assume that any string within Text class will be matched exaly.

But what if one wants to construct objective regex using textual regular expression as one of its elements? Well, there is Raw class to do that. It always resolves to exactly same string than the one it was constructed from.

>>> print(o_re.Raw("^.*$").get_regex())
^.*$

As you can see, the difference in behaviour is exactly as one might have expected:

>>> print(o_re.Raw("^.*$").get_compiled().match("Hello world!"))
<re.Match object; span=(0, 12), match='Hello world!'>
>>> print(o_re.Text("^.*$").get_compiled().match("Hello world!"))
None
>>> print(o_re.Text("^.*$").get_compiled().match("^.*$"))
<re.Match object; span=(0, 4), match='^.*$'>
>>> print(o_re.Text("^.*$").get_compiled().match("^.*"))
None    

Raw regex matches any sequence of characters, while Text matches only one that it was provided with.

Let's see more sophisticated examples.

Constructing index-accessed groups:

>>> print(repr(o_re.Text("hello").as_group().get_regex()))
'(hello)'

Name-accessed groups:

>>> print(repr(o_re.Text("hello").as_group("group_name").get_regex()))
'(?P<group_name>hello)'

Joining parts of regexp together:

>>> _reg = o_re.Text("hello") + o_re.Raw("\s+") + o_re.Text("world!")
>>> print(_reg.get_regex())
(?:(?:(?:hello)(?:\s+))(?:world!))

Matching repeating patterns:

>>> _reg = o_re.Text("hello").times.any() + o_re.Raw("\s").times(5) + o_re.Text("world!").times.many()
>>> print(_reg.get_regex())
(?:(?:(?:(?:hello)*)(?:(?:\s){5}))(?:(?:world!)+)

Referencing group in the regexp:

>>> _hello = o_re.Text("hello").as_group()
>>> _reg = _hello + o_re.Text("world").as_group("wrld") + _hello
>>> print(_reg.get_regex())
(?:(?:(?:(hello))(?:(?P<wrld>world)))(?:\1))

Referencing named group is done in the same way:

>>> _hello = o_re.Text("hello").as_group("hello_group")
>>> _reg = _hello + o_re.Text("world").as_group("wrld") + _hello
>>> print(_reg.get_regex())
(?:(?:(?:(?P<hello_group>hello))(?:(?P<wrld>world)))(?:(?P=hello_group)))

Construction of a regexp that matches ether hello_world_bye of world_no_hello:

>>> _hello = o_re.Text("hello").as_group()
>>> _reg = _hello + o_re.Text("_world_") + o_re.If(_hello, "bye", "no_hello")
>>> print(_reg.get_regex())
(?:(?:(?:(hello))(?:_world_))(?:(?(1)(?:bye)|(?:no_hello)))

Expression that matches any one of provided regular expressions:

>>> _reg = o_re.ops.Any(["op1", "op2", "op3"])
>>> print(_reg.get_regex())
(?:op1)|(?:op2)|(?:op3)

The text string can be used as an operand for any regular expression. In such case, this text string is casted to the Text class, thus resulting regexp will all special symbols, that were collected from plain string instances, properly escaped.

>>> _reg = "hello! .* world " + o_re.Raw(".*") + " [a-z] something"
>>> print(_reg.get_regex())
(?:(?:(?:hello! \.\* world )(?:.*))(?: \[a-z\] something)

Metadata

Release files for objective-regex 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for objective-regex 0.1.4
File Size Uploaded Provenance Actions
objective_regex-0.1.4.tar.gz 11.1 kB Without provenance Details for objective_regex-0.1.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for objective-regex 0.1.4
File Interpreter ABI Platform Actions
objective_regex-0.1.4-py3-none-any.whl Python 3 none any Details for objective_regex-0.1.4-py3-none-any.whl

Total release size: 21.8 kB

Release files / objective_regex-0.1.4.tar.gz

Download URL objective_regex-0.1.4.tar.gz
Size 11.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1fe5629b8d760cf352002e59c3e67014ccc58ea7117ac696b3a4f3eaa29ea9ea
BLAKE2b-256 checksum
How to use checksums
52e753363cbe1a55c2cbffd34fe9c10f975d39f697963cb13714ed4c95bacd2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.9.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.9

Release files / objective_regex-0.1.4-py3-none-any.whl

Download URL objective_regex-0.1.4-py3-none-any.whl
Size 10.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ac40cb0c42d659df6d8eed687b59e93f40bcf33d39567bcd24323a2365879f15
BLAKE2b-256 checksum
How to use checksums
2e5e58d0426fa1a57c290d6dd1e3301ba12b563815ce59b18b1d412f55fd74c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.9.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.9

Security for objective-regex 0.1.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page