ssc_codegen 0.7.4__tar.gz → 0.7.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/PKG-INFO +1 -1
  2. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/pyproject.toml +1 -2
  3. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/__init__.py +1 -1
  4. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/ast_ssc.py +4 -0
  5. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/py_base.py +3 -3
  6. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/templates/py.py +27 -3
  7. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/document.py +33 -7
  8. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/document_utlis.py +6 -0
  9. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/.gitignore +0 -0
  10. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/LICENSE +0 -0
  11. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/README.md +0 -0
  12. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/_compat.py +0 -0
  13. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/ast_build_utils.py +0 -0
  14. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/ast_builder.py +0 -0
  15. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/cli/__init__.py +0 -0
  16. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/cli/cli_callbacks.py +0 -0
  17. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/cli/cli_utils.py +0 -0
  18. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/cli/code_callbacks.py +0 -0
  19. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/cli/consts.py +0 -0
  20. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/cli/main.py +0 -0
  21. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
  22. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/compiler.py +0 -0
  23. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/consts.py +0 -0
  24. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/__init__.py +0 -0
  25. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/ast_utils.py +0 -0
  26. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/base.py +0 -0
  27. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/dart_universal_html.py +0 -0
  28. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/go_goquery.py +0 -0
  29. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/js_pure.py +0 -0
  30. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/json_to_schema.py +0 -0
  31. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/py_bs4.py +0 -0
  32. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/py_parsel.py +0 -0
  33. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/py_scrapy.py +0 -0
  34. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/py_selectolax.py +0 -0
  35. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/templates/dart.py +0 -0
  36. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/templates/go.py +0 -0
  37. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/templates/js.py +0 -0
  38. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/converters/templates/template_bindings.py +0 -0
  39. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/json_struct.py +0 -0
  40. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/schema.py +0 -0
  41. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/selector_utils.py +0 -0
  42. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/str_utils.py +0 -0
  43. {ssc_codegen-0.7.4 → ssc_codegen-0.7.5}/ssc_codegen/tokens.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssc_codegen
3
- Version: 0.7.4
3
+ Version: 0.7.5
4
4
  Summary: Python-dsl code converter to html parser for web scraping
5
5
  Project-URL: Documentation, https://github.com/vypivshiy/selector_schema_codegen#readme
6
6
  Project-URL: Issues, https://github.com/vypivshiy/selector_schema_codegen/issues
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ssc_codegen"
3
- version = "0.7.4"
3
+ version = "0.7.5"
4
4
  description = "Python-dsl code converter to html parser for web scraping "
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -26,7 +26,6 @@ classifiers = [
26
26
  "Programming Language :: Python :: 3.11",
27
27
  "Programming Language :: Python :: 3.12",
28
28
  "Programming Language :: Python :: 3.13",
29
-
30
29
  ]
31
30
 
32
31
  [project.urls]
@@ -3,7 +3,7 @@ from .document import HTMLDocument, StringDocument, ArrayDocument, AssertDocumen
3
3
  from .json_struct import Json
4
4
  from .schema import ItemSchema, DictSchema, ListSchema, FlatListSchema
5
5
 
6
- VERSION = "0.7.4"
6
+ VERSION = "0.7.5"
7
7
 
8
8
  class __MISSING(object):
9
9
  pass
@@ -664,6 +664,7 @@ class RegexExpression(BaseExpression):
664
664
  ret_type: VariableType = VariableType.STRING
665
665
  pattern: str
666
666
  group: int
667
+ ignore_case: bool = False
667
668
 
668
669
 
669
670
  @dataclass(kw_only=True)
@@ -683,6 +684,7 @@ class RegexAllExpression(BaseExpression):
683
684
  accept_type: VariableType = VariableType.STRING
684
685
  ret_type: VariableType = VariableType.LIST_STRING
685
686
  pattern: str
687
+ ignore_case: bool = False
686
688
 
687
689
 
688
690
  @dataclass(kw_only=True)
@@ -700,6 +702,7 @@ class RegexSubExpression(BaseExpression):
700
702
  ret_type: VariableType = VariableType.STRING
701
703
  pattern: str
702
704
  repl: str
705
+ ignore_case: bool = False
703
706
 
704
707
 
705
708
  @dataclass(kw_only=True)
@@ -849,6 +852,7 @@ class IsRegexMatchExpression(BaseExpression):
849
852
  ret_type: VariableType = VariableType.STRING
850
853
  pattern: str
851
854
  msg: str
855
+ ignore_case: bool = False
852
856
 
853
857
 
854
858
  @dataclass(kw_only=True)
@@ -401,7 +401,7 @@ def tt_regex(node: RegexExpression) -> str:
401
401
  prv, nxt = lr_var_names(variable=node.variable)
402
402
  pattern = repr(node.pattern)
403
403
  group = node.group
404
- code = py.BINDINGS[node.kind, nxt, pattern, prv, group]
404
+ code = py.BINDINGS[node.kind, nxt, pattern, prv, group, node.ignore_case]
405
405
  return indent + code
406
406
 
407
407
 
@@ -410,7 +410,7 @@ def tt_regex_all(node: RegexAllExpression) -> str:
410
410
 
411
411
  prv, nxt = lr_var_names(variable=node.variable)
412
412
  pattern = repr(node.pattern)
413
- code = py.BINDINGS[node.kind, nxt, pattern, prv]
413
+ code = py.BINDINGS[node.kind, nxt, pattern, prv, node.ignore_case]
414
414
  return indent + code
415
415
 
416
416
 
@@ -497,7 +497,7 @@ def tt_is_regex(node: IsRegexMatchExpression) -> str:
497
497
  pattern = repr(node.pattern)
498
498
  msg = repr(node.msg)
499
499
 
500
- code = py.BINDINGS[node.kind, pattern, prv, msg]
500
+ code = py.BINDINGS[node.kind, pattern, prv, msg, node.ignore_case]
501
501
  if node.next.kind == TokenType.EXPR_NO_RETURN:
502
502
  return indent + code
503
503
  return indent + code + "\n" + indent + f"{nxt} = {prv}"
@@ -103,9 +103,25 @@ BINDINGS[TokenType.EXPR_LIST_STRING_REPLACE] = (
103
103
  "{} = [e.replace({}, {}) for e in {}]"
104
104
  )
105
105
  BINDINGS[TokenType.EXPR_STRING_SPLIT] = "{} = {}.split({})"
106
+
107
+
106
108
  # regex
107
- BINDINGS[TokenType.EXPR_REGEX] = "{} = re.search({}, {})[{}]"
108
- BINDINGS[TokenType.EXPR_REGEX_ALL] = "{} = re.findall({}, {})"
109
+ def expr_re(
110
+ nxt: str, pattern: str, prv: str, group: int, ignore_case: bool
111
+ ) -> str:
112
+ if ignore_case:
113
+ return f"{nxt} = re.search({pattern}, '{prv}', re.IGNORECASE)[{group}]"
114
+ return f"{nxt} = re.search({pattern}, '{prv}')[{group}]"
115
+
116
+
117
+ def expr_re_all(nxt: str, pattern: str, prv: str, ignore_case: bool) -> str:
118
+ if ignore_case:
119
+ return f"{nxt} = re.findall({pattern}, '{prv}', re.IGNORECASE)"
120
+ return f"{nxt} = re.findall({pattern}, '{prv}')"
121
+
122
+
123
+ BINDINGS[TokenType.EXPR_REGEX] = expr_re
124
+ BINDINGS[TokenType.EXPR_REGEX_ALL] = expr_re_all
109
125
  BINDINGS[TokenType.EXPR_REGEX_SUB] = "{} = re.sub({}, {}, {})"
110
126
  BINDINGS[TokenType.EXPR_LIST_REGEX_SUB] = "{} = [re.sub({}, {}, e) for e in {}]"
111
127
 
@@ -118,7 +134,15 @@ BINDINGS[TokenType.EXPR_LIST_JOIN] = "{} = {}.join({})"
118
134
  BINDINGS[TokenType.IS_EQUAL] = "assert {} == {}, {}"
119
135
  BINDINGS[TokenType.IS_NOT_EQUAL] = "assert {} != {}, {}"
120
136
  BINDINGS[TokenType.IS_CONTAINS] = "assert {} in {}, {}"
121
- BINDINGS[TokenType.IS_REGEX_MATCH] = "assert re.search({}, {}), {}"
137
+
138
+
139
+ def is_regex(pattern: str, prv: str, msg: str, ignore_case: bool) -> str:
140
+ if ignore_case:
141
+ return f"assert re.search({pattern}, {prv}, re.IGNORECASE), {msg}"
142
+ return f"assert re.search({pattern}, {prv}), {msg}"
143
+
144
+
145
+ BINDINGS[TokenType.IS_REGEX_MATCH] = is_regex
122
146
 
123
147
  # int, float converters
124
148
  BINDINGS[TokenType.TO_INT] = "{} = int({})"
@@ -51,7 +51,11 @@ from .ast_ssc import (
51
51
  ToBool,
52
52
  ArrayLengthExpression,
53
53
  )
54
- from .document_utlis import assert_re_expression, unverbosify_regex
54
+ from .document_utlis import (
55
+ assert_re_expression,
56
+ unverbosify_regex,
57
+ is_ignore_case_regex,
58
+ )
55
59
  from .schema import BaseSchema
56
60
  from .selector_utils import validate_css_query, validate_xpath_query
57
61
  from .tokens import VariableType
@@ -458,7 +462,9 @@ class StringDocument(BaseDocument):
458
462
  )
459
463
  return self
460
464
 
461
- def re(self, pattern: str | Pattern, group: int = 1) -> Self:
465
+ def re(
466
+ self, pattern: str | Pattern, group: int = 1, ignore_case: bool = False
467
+ ) -> Self:
462
468
  """extract first regex result.
463
469
 
464
470
  NOTE:
@@ -466,6 +472,10 @@ class StringDocument(BaseDocument):
466
472
 
467
473
  - accept STRING, return STRING
468
474
  """
475
+ # TODO: implement, js, go, dart ignorecase flag
476
+ if not isinstance(pattern, str):
477
+ ignore_case = is_ignore_case_regex(pattern)
478
+
469
479
  pattern = unverbosify_regex(pattern)
470
480
  assert_re_expression(pattern)
471
481
 
@@ -473,21 +483,28 @@ class StringDocument(BaseDocument):
473
483
  self._raise_wrong_type_error(
474
484
  self.stack_last_ret, VariableType.STRING
475
485
  )
476
- self._add(RegexExpression(pattern=pattern, group=group))
486
+ self._add(
487
+ RegexExpression(
488
+ pattern=pattern, group=group, ignore_case=ignore_case
489
+ )
490
+ )
477
491
  return self
478
492
 
479
- def re_all(self, pattern: str | Pattern) -> Self:
493
+ def re_all(self, pattern: str | Pattern, ignore_case: bool = False) -> Self:
480
494
  """extract all regex results.
481
495
 
482
496
  - accept STRING, return LIST_STRING
483
497
  """
498
+ if not isinstance(pattern, str):
499
+ ignore_case = is_ignore_case_regex(pattern)
500
+
484
501
  pattern = unverbosify_regex(pattern)
485
502
  assert_re_expression(pattern, max_groups=1)
486
503
  if self.stack_last_ret != VariableType.STRING:
487
504
  self._raise_wrong_type_error(
488
505
  self.stack_last_ret, VariableType.STRING
489
506
  )
490
- self._add(RegexAllExpression(pattern=pattern))
507
+ self._add(RegexAllExpression(pattern=pattern, ignore_case=ignore_case))
491
508
  return self
492
509
 
493
510
  def re_sub(self, pattern: str | Pattern, repl: str = "") -> Self:
@@ -674,20 +691,29 @@ class AssertDocument(BaseDocument):
674
691
  self._add(IsContainsExpression(item=item, msg=msg))
675
692
  return self
676
693
 
677
- def is_regex(self, pattern: str, msg: str = "") -> Self:
694
+ def is_regex(
695
+ self, pattern: str | Pattern, msg: str = "", ignore_case: bool = False
696
+ ) -> Self:
678
697
  """assert value matched by regex. If in generated code check failed - throw exception with passed msg
679
698
 
680
699
  EXPR DO NOT MODIFY variable
681
700
 
682
701
  - accept STRING, return STRING
683
702
  """
703
+ if not isinstance(pattern, str):
704
+ ignore_case = is_ignore_case_regex(pattern)
705
+ pattern = unverbosify_regex(pattern)
684
706
  if self.stack_last_ret != VariableType.STRING:
685
707
  self._raise_wrong_type_error(
686
708
  self.stack_last_ret, VariableType.STRING
687
709
  )
688
710
  assert_re_expression(pattern, allow_empty_groups=True)
689
711
 
690
- self._add(IsRegexMatchExpression(pattern=pattern, msg=msg))
712
+ self._add(
713
+ IsRegexMatchExpression(
714
+ pattern=pattern, msg=msg, ignore_case=ignore_case
715
+ )
716
+ )
691
717
  return self
692
718
 
693
719
 
@@ -22,6 +22,12 @@ CM2_RX = r"(\\)?((\\{2})*)(#)"
22
22
  WS_RX = r"(\\)?((\\{2})*)(\s)\s*"
23
23
 
24
24
 
25
+ def is_ignore_case_regex(pattern: str | Pattern) -> bool:
26
+ if isinstance(pattern, str):
27
+ return False
28
+ return bool(pattern.flags & re.IGNORECASE)
29
+
30
+
25
31
  def unverbosify_regex(pattern: str | Pattern) -> str:
26
32
  if isinstance(pattern, str):
27
33
  return pattern
File without changes
File without changes
File without changes