ssc_codegen 0.8.19__tar.gz → 0.8.21__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 (53) hide show
  1. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/PKG-INFO +1 -1
  2. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/pyproject.toml +1 -1
  3. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/__init__.py +1 -1
  4. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/__init__.py +1 -1
  5. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/nodes_array.py +8 -0
  6. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/go_goquery.py +2 -0
  7. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/js_pure.py +10 -1
  8. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/py_base.py +11 -0
  9. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/document.py +9 -0
  10. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/tokens.py +1 -0
  11. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/.gitignore +0 -0
  12. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/LICENSE +0 -0
  13. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/README.md +0 -0
  14. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/_compat.py +0 -0
  15. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/base.py +0 -0
  16. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/nodes_cast.py +0 -0
  17. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/nodes_core.py +0 -0
  18. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/nodes_filter.py +0 -0
  19. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/nodes_selectors.py +0 -0
  20. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/nodes_string.py +0 -0
  21. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_/nodes_validate.py +0 -0
  22. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_build/__init__.py +0 -0
  23. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_build/main.py +0 -0
  24. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/ast_build/utils.py +0 -0
  25. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/cli/__init__.py +0 -0
  26. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/cli/cli_callbacks.py +0 -0
  27. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/cli/cli_utils.py +0 -0
  28. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/cli/code_callbacks.py +0 -0
  29. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/cli/consts.py +0 -0
  30. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/cli/main.py +0 -0
  31. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/cli/runtime_parse_runners.py +0 -0
  32. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/compiler.py +0 -0
  33. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/consts.py +0 -0
  34. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/__init__.py +0 -0
  35. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/base.py +0 -0
  36. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/helpers.py +0 -0
  37. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/py_bs4.py +0 -0
  38. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/py_parsel.py +0 -0
  39. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/py_selectolax.py +0 -0
  40. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/templates/__init__.py +0 -0
  41. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/templates/go_goquery.py +0 -0
  42. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/converters/templates/js_pure.py +0 -0
  43. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/document_utlis.py +0 -0
  44. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/json_struct.py +0 -0
  45. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/json_to_scc.py +0 -0
  46. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/logs.py +0 -0
  47. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/pseudo_selectors.py +0 -0
  48. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/schema.py +0 -0
  49. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/selector_utils.py +0 -0
  50. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/static_checker/__init__.py +0 -0
  51. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/static_checker/base.py +0 -0
  52. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/static_checker/callbacks.py +0 -0
  53. {ssc_codegen-0.8.19 → ssc_codegen-0.8.21}/ssc_codegen/str_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ssc_codegen
3
- Version: 0.8.19
3
+ Version: 0.8.21
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.8.19"
3
+ version = "0.8.21"
4
4
  description = "Python-dsl code converter to html parser for web scraping "
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -7,7 +7,7 @@ from ssc_codegen.schema import ItemSchema, DictSchema, ListSchema, FlatListSchem
7
7
 
8
8
  setup_logger()
9
9
 
10
- VERSION = "0.8.19"
10
+ VERSION = "0.8.21"
11
11
 
12
12
 
13
13
  class __MISSING(object):
@@ -1,5 +1,5 @@
1
1
  from .base import BaseAstNode
2
- from .nodes_array import ExprIndex, ExprToListLength, ExprListStringJoin
2
+ from .nodes_array import ExprIndex, ExprToListLength, ExprListStringJoin, ExprListUnique
3
3
  from .nodes_cast import ExprNested, ExprJsonify, ExprToInt, ExprToFloat, ExprToListInt, ExprToListFloat, ExprToBool
4
4
  from .nodes_core import (ExprReturn,
5
5
  ExprNoReturn,
@@ -31,3 +31,11 @@ class ExprToListLength(BaseAstNode[T_EMPTY_KWARGS, tuple]):
31
31
  kind: ClassVar[TokenType] = TokenType.EXPR_LIST_LEN
32
32
  accept_type: VariableType = VariableType.LIST_ANY
33
33
  ret_type: VariableType = VariableType.INT
34
+
35
+
36
+ @dataclass(kw_only=True)
37
+ class ExprListUnique(BaseAstNode[T_EMPTY_KWARGS, tuple]):
38
+ # TODO: support LIST_INT, LIST_FLOAT
39
+ kind: ClassVar[TokenType] = TokenType.EXPR_LIST_UNIQUE
40
+ accept_type: VariableType = VariableType.LIST_STRING
41
+ ret_type: VariableType = VariableType.LIST_STRING
@@ -1263,3 +1263,5 @@ def pre_list_str_rm_prefix_and_suffix(
1263
1263
 
1264
1264
  # TODO impl ExprHasAttr, ExprListHasAttr
1265
1265
  # TODO: impl Filter Expr
1266
+ # TODO: impl ExprListUnique
1267
+
@@ -101,6 +101,7 @@ from ssc_codegen.ast_ import (
101
101
  FilterStrLenLe,
102
102
  FilterStrLenGt,
103
103
  FilterStrLenGe,
104
+ ExprListUnique,
104
105
  )
105
106
  from ssc_codegen.converters.base import BaseCodeConverter
106
107
  from ssc_codegen.converters.helpers import (
@@ -721,7 +722,7 @@ def pre_list_str_rm_prefix_and_suffix(
721
722
  def pre_has_attr(node: ExprHasAttr) -> str:
722
723
  prv, nxt = prev_next_var(node)
723
724
  key, msg = node.unpack_args()
724
- expr = f"if (!{prv}?.hasAttribute({key!r}) throw new Error({msg!r});"
725
+ expr = f"if (!{prv}?.hasAttribute({key!r})) throw new Error({msg!r});"
725
726
  if is_last_var_no_ret(node):
726
727
  return expr
727
728
  return expr + f"let {nxt} = {prv};"
@@ -914,3 +915,11 @@ def pre_filter_str_len_ge(node: FilterStrLenGe) -> str:
914
915
  if not is_first_node_cond(node) and is_prev_node_atomic_cond(node):
915
916
  return f" && {expr}"
916
917
  return expr
918
+
919
+
920
+ @CONVERTER(ExprListUnique.kind)
921
+ def pre_list_unique(node: ExprListUnique) -> str:
922
+ prv, nxt = prev_next_var(node)
923
+ # save order guaranteed
924
+ # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#description
925
+ return f"let {nxt} = [...new Set({prv})]; "
@@ -103,6 +103,7 @@ from ssc_codegen.ast_ import (
103
103
  FilterStrLenLe,
104
104
  FilterStrLenGt,
105
105
  FilterStrLenGe,
106
+ ExprListUnique,
106
107
  )
107
108
  from ssc_codegen.converters.base import (
108
109
  BaseCodeConverter,
@@ -271,6 +272,7 @@ class BasePyCodeConverter(BaseCodeConverter):
271
272
  FilterStrLenLe.kind: pre_filter_str_len_le,
272
273
  FilterStrLenGe.kind: pre_filter_str_len_ge,
273
274
  FilterStrLenGt.kind: pre_filter_str_len_gt,
275
+ ExprListUnique.kind: pre_list_unique,
274
276
  }
275
277
 
276
278
  self.post_definitions = {
@@ -1069,3 +1071,12 @@ def pre_filter_str_len_ge(node: FilterStrLenGe) -> str:
1069
1071
  if not is_first_node_cond(node) and is_prev_node_atomic_cond(node):
1070
1072
  return f" and {expr}"
1071
1073
  return expr
1074
+
1075
+
1076
+ def pre_list_unique(node: ExprListUnique) -> str:
1077
+ indent = (
1078
+ INDENT_DEFAULT_BODY if have_default_expr(node) else INDENT_METHOD_BODY
1079
+ )
1080
+ prv, nxt = prev_next_var(node)
1081
+ # use `dict.fromkeys()` instead `set()` for guarantees insertion order (py 3.7+) reason
1082
+ return f"{indent}{nxt} = list(dict.fromkeys({prv}))"
@@ -75,6 +75,7 @@ from ssc_codegen.ast_ import (
75
75
  FilterStrLenLe,
76
76
  FilterStrLenGt,
77
77
  FilterStrLenGe,
78
+ ExprListUnique,
78
79
  )
79
80
  from ssc_codegen.document_utlis import (
80
81
  analyze_re_expression,
@@ -487,6 +488,14 @@ class ArrayDocument(BaseDocument):
487
488
  self._add(ExprFilter(body=expr.stack))
488
489
  return self
489
490
 
491
+ def unique(self) -> Self:
492
+ """Remove duplicates from array-like object
493
+
494
+ - accept LIST_STRING, return LIST_STRING
495
+ """
496
+ self._add(ExprListUnique())
497
+ return self
498
+
490
499
 
491
500
  class StringDocument(BaseDocument):
492
501
  def rm_prefix(self, substr: str) -> Self:
@@ -146,6 +146,7 @@ class TokenType(IntEnum):
146
146
  EXPR_LIST_ANY_INDEX = auto()
147
147
  EXPR_LIST_JOIN = auto()
148
148
  EXPR_LIST_LEN = auto()
149
+ EXPR_LIST_UNIQUE = auto()
149
150
 
150
151
  # ASSERT
151
152
  IS_EQUAL = auto()
File without changes
File without changes
File without changes