// include the latest version of the regex crate in your Cargo.toml
extern crate regex;
use regex::Regex;
fn main() {
let regex = Regex::new(r"(?m)(?P<preceeding>^(?P<whitespace>(?:[ ]{4}|\t)+)(?!self\.)(?P<attrprefix>[a-z0-9_\.]{1,})?(?P<clsattrname>[A-Z_]{1,}): )(?P<annotation>(?!ClassVar)(?:[A-Za-z0-9_]+\.*)+(?:(?:(?:\[?[A-Za-z0-9_]+(?:, | \| )?)+(?:\.{3})?)*(?:\]*))*)+(?P<remainder>.*?$[\r\n])").unwrap();
let string = "# Regex:
regex_str = r\"(?P<preceeding>^(?P<whitespace>(?:[ ]{4}|\\t)+)(?!self\\.)(?P<attrprefix>[a-z0-9_\\.]{1,})?(?P<clsattrname>[A-Z_]{1,}): )(?P<annotation>(?!ClassVar)(?:[A-Za-z0-9_]+\\.*)+(?:(?:(?:\\[?[A-Za-z0-9_]+(?:, | \\| )?)+(?:\\.{3})?)*(?:\\]*))*)+(?P<remainder>.*?$[\\r\\n])\"
#pycharm_compatible_version = (?<preceeding>^(?<whitespace>(?:[ ]{4}|\\t)+)(?!self\\.)(?<attrprefix>[a-z0-9_\\.]{1,})?(?<clsattrname>[A-Z_]{1,}): )(?<annotation>(?!ClassVar)(?:[A-Za-z0-9_]+\\.*)+(?:(?:(?:\\[?[A-Za-z0-9_]+(?:, | \\| )?)+(?:\\.{3})?)*(?:\\]*))*)+(?<remainder>.*?$[\\r\\n])
# WARNINGS
# - Top-level functions and local constants are capture as well if they are written in SCREAMING_SNAKE style!
#Assumes:
# - Class variables are named according to SCREAMING_SNAKE convention.
# - Functions and attributes are named according to underscored_lowercase convention.
# - Indent -> 4 spaces or 1 tab per level.
# Notes:
# - Unannotated variables are skipped
# - In PyCharm IDE regex replace; replace occurences of ?P< with ?<
import pathlib, os
TOPLEVEL_CONSTANT: str = 'nomatch' # No match
class TestAttr:
class TestAttrNested:
underscore_test = 'asdf'
class SomeClass(ParentClass, SomeMixin):
FOO_CLS_ATTR: Union[str, int] = 'foo' # Regex should match
BAR_CLS_ATTR: Sequence[tuple[int, ...]] = ((1, 2), (3, 4)) # Regex should match
ANNOTATION_AS_ATTR_ATTR: TestAttr.TestAttrNested.underscore_test = 'asdf' # Regex should match
FIZZ_CLS_ATTR: ClassVar[bool] = True # No match
BUZZ_CLS_ATTR = 10 # No match (not annotated)
def __init__(self):
local_instance_attribute: float = 1337.420 # No match
self.instance_attribute: str = 'NO_MATCH_PLEASE'
class NestedClass:
NESTED_ATTR: str = 'nested_attribute'
@classmethod
def nested_method(cls):
cls.NESTED_ATTR: str = 'should_match' # Regex should match
print(\"Nested lvl 1!\")
def arbitrarilyy_nested_func(obj):
obj.a.b.c.d.ARBITRARILY_NESTED_ATTR: str = 'nested' # Regex should match
@classmethod
def some_method(cls):
cls.FOO_CLS_ATTR: str = 'foo' # Regex should match
cls.instance_attribute.OTHER_CLASATTR: str = 'foo' # Regex should match
print(cls.FOO_CLS_ATTR) # No Match
def toplevel_func(arg1: int, CONST_ARG: int = 10) -> int: # No match
MULTIPLIER: float = 6.9
# ^^ Warning! Constants in top-level functions are captured as well!
# ^^ Python doesn't support subpatterns AFAIK.
return arg1*MULTIPLIER
### --> after replacing by ${preceeding}ClassVar[${annotation}]${remainder} ###
class SomeClass(ParentClass, SomeMixin):
FOO_CLS_ATTR: ClassVar[str] = 'foo' # Regex matches
BAR_CLS_ATTR: ClassVar[Sequence[int]] = (1, 2, 3)
FIZZ_CLS_ATTR: ClassVar[bool] = True
BUZZ_CLS_ATTR = 10 # No match (not annotated)
instance_attribute: float = 1337.420
class NestedClass:
NESTED_ATTR: ClassVar[str] = 'nested_attribute'
@classmethod
def nested_method(cls):
cls.NESTED_ATTR: ClassVar[str] = 'should_match'
print(\"Nested lvl 1!\")
def arbitrarilyy_nested_func(obj):
obj.a.b.c.d.ARBITRARILY_NESTED_ATTR: ClassVar[str] = 'nested'
@classmethod
def some_method(cls):
cls.FOO_CLS_ATTR: ClassVar[str] = 'foo' # Regex matches
cls.instance_attribute.OTHER_CLASATTR: ClassVar[str] = 'foo'
print(cls.FOO_CLS_ATTR) # No Match
def toplevel_func(arg1: int, CONST_ARG: int = 10) -> int
MULTIPLIER: ClassVar[float] = 6.9
# ^^ ERRONEOUSLY ADJUSTED...
# ^^ Warning! Constants in top-level functions are captured as well!
# ^^ Python doesn't support subpatterns AFAIK.
return arg1*MULTIPLIER";
// result will be an iterator over tuples containing the start and end indices for each match in the string
let result = regex.captures_iter(string);
for mat in result {
println!("{:?}", mat);
}
}
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Rust, please visit: https://docs.rs/regex/latest/regex/