Skip to content

Commit

Permalink
Deprecate use of typing.List (#173)
Browse files Browse the repository at this point in the history
typing.List is deprecated as of Python 3.9 - use `list`, or `Sequence` or
`Iterable` from `collections.abc` instead.
  • Loading branch information
istride authored Mar 6, 2025
1 parent 4ea8a99 commit bfdc04d
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 51 deletions.
21 changes: 12 additions & 9 deletions src/rpft/parsers/common/rowparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,15 @@ def get_list_child_model(model):


def is_list_type(model):
# Determine whether model is a list type,
# such as list, List, List[str], ...
# issubclass only works for Python <=3.6
# model.__dict__.get('__origin__') returns different things in different Python
# version.
# This function tries to accommodate both 3.6 and 3.8 (at least)
"""
Determine whether model is a list type, such as list, list[str], List, List[str].
typing.List is deprecated as of Python 3.9
"""
return (
is_basic_list_type(model)
or model is List
or model.__dict__.get("__origin__") in [list, List]
or getattr(model, "__origin__", None) is list
)


Expand Down Expand Up @@ -205,7 +204,7 @@ def assign_value(self, field, key, value, model):
value = list(value)
if isinstance(value[0], str):
assert len(value) == 2
field[key] = {value[0] : value[1]}
field[key] = {value[0]: value[1]}
elif isinstance(value[0], list):
for entry in value:
assert len(entry) == 2
Expand Down Expand Up @@ -327,7 +326,11 @@ def parse_entry(
# The model of field[key] is model, and thus value should also be interpreted
# as being of type model.
if not value_is_parsed:
if is_list_type(model) or is_basic_dict_type(model) or is_parser_model_type(model):
if (
is_list_type(model)
or is_basic_dict_type(model)
or is_parser_model_type(model)
):
# If the expected type of the value is list/object,
# parse the cell content as such.
# Otherwise leave it as a string
Expand Down
6 changes: 2 additions & 4 deletions src/rpft/parsers/creation/contentindexparser.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import importlib
import logging
from collections import OrderedDict
from typing import Dict, List

from rpft.logger.logger import logging_context
from rpft.parsers.common.model_inference import model_from_headers
from rpft.parsers.common.sheetparser import SheetParser
Expand Down Expand Up @@ -58,8 +56,8 @@ def __init__(
self.tag_matcher = tag_matcher
self.template_sheets = {}
self.data_sheets = {}
self.flow_definition_rows: List[ContentIndexRowModel] = []
self.campaign_parsers: Dict[str, tuple[str, CampaignParser]] = {}
self.flow_definition_rows: list[ContentIndexRowModel] = []
self.campaign_parsers: dict[str, tuple[str, CampaignParser]] = {}
self.surveys = {}
self.trigger_parsers = OrderedDict()
self.user_models_module = (
Expand Down
7 changes: 3 additions & 4 deletions src/rpft/parsers/creation/contentindexrowmodel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from enum import Enum
from typing import List

from rpft.parsers.common.rowparser import ParserModel
from rpft.parsers.creation.models import SurveyConfig
Expand All @@ -24,18 +23,18 @@ class Operation(ParserModel):
class ContentIndexRowModel(ParserModel):
type: str = ""
new_name: str = ""
sheet_name: List[str] = []
sheet_name: list[str] = []
data_sheet: str = ""
data_row_id: str = ""
template_argument_definitions: List[TemplateArgument] = [] # internal name
template_argument_definitions: list[TemplateArgument] = [] # internal name
template_arguments: list = []
options: dict = {}
survey_config: SurveyConfig = SurveyConfig()
operation: Operation = Operation()
data_model: str = ""
group: str = ""
status: str = ""
tags: List[str] = []
tags: list[str] = []

def field_name_to_header_name(field):
if field == "template_argument_definitions":
Expand Down
26 changes: 9 additions & 17 deletions src/rpft/parsers/creation/flowrowmodel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import List

from rpft.parsers.common.rowparser import ParserModel
from rpft.parsers.creation.models import Condition

Expand Down Expand Up @@ -43,7 +41,7 @@ def dict_to_list_of_pairs(headers):
class WhatsAppTemplating(ParserModel):
name: str = ""
uuid: str = ""
variables: List[str] = []
variables: list[str] = []


class Edge(ParserModel):
Expand All @@ -69,15 +67,15 @@ def header_name_to_field_name_with_context(header, row):
class FlowRowModel(ParserModel):
row_id: str = ""
type: str
edges: List[Edge]
loop_variable: List[str] = []
edges: list[Edge]
loop_variable: list[str] = []
include_if: bool = True
mainarg_message_text: str = ""
mainarg_value: str = ""
mainarg_groups: List[str] = []
mainarg_groups: list[str] = []
mainarg_none: str = ""
mainarg_dict: list = [] # encoded as list of pairs
mainarg_destination_row_ids: List[str] = []
mainarg_destination_row_ids: list[str] = []
mainarg_flow_name: str = ""
mainarg_expression: str = ""
mainarg_iterlist: list = []
Expand All @@ -86,28 +84,22 @@ class FlowRowModel(ParserModel):
data_sheet: str = ""
data_row_id: str = ""
template_arguments: list = []
choices: List[str] = []
choices: list[str] = []
save_name: str = ""
result_category: str = ""
image: str = ""
audio: str = ""
video: str = ""
attachments: List[str] = []
attachments: list[str] = []
urn_scheme: str = ""
obj_name: str = ""
obj_id: str = ""
node_name: str = ""
node_uuid: str = ""
no_response: str = ""
ui_type: str = ""
ui_position: List[str] = []

# TODO: Extra validation here, e.g. from must not be empty
# type must come from row_type_to_main_arg.keys() (see below)
# image/audio/video only makes sense if type == send_message
# mainarg_none should be ''
# _ui_position should be '' or a list of two ints
# ...
ui_position: list[str] = []

def field_name_to_header_name(field):
field_map = {
"node_uuid": "_nodeId",
Expand Down
18 changes: 8 additions & 10 deletions src/rpft/parsers/creation/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import List

from rpft.parsers.common.rowparser import ParserModel


Expand Down Expand Up @@ -31,7 +29,7 @@ class ConditionWithMessage(ParserModel):


class ConditionsWithMessage(ParserModel):
conditions: List[ConditionWithMessage] = []
conditions: list[ConditionWithMessage] = []
general_message: str = ""


Expand Down Expand Up @@ -61,7 +59,7 @@ class Message(ParserModel):
image: str = ""
audio: str = ""
video: str = ""
attachments: List[str] = []
attachments: list[str] = []


class TemplateSheet:
Expand All @@ -76,7 +74,7 @@ def __init__(
self,
flow_definitions,
data_sheets,
templates: List[TemplateSheet],
templates: list[TemplateSheet],
surveys,
):
self.flow_definitions = flow_definitions
Expand Down Expand Up @@ -119,7 +117,7 @@ class MCQChoice(ParserModel):


class PostProcessing(ParserModel):
assignments: List[Assignment] = []
assignments: list[Assignment] = []
"""
Assignments to perform via save_value rows.
"""
Expand Down Expand Up @@ -157,7 +155,7 @@ class SurveyQuestionModel(ParserModel):
Type of the question.
"""

messages: List[Message]
messages: list[Message]
"""
Question text.
"""
Expand All @@ -175,7 +173,7 @@ class SurveyQuestionModel(ParserModel):
the question ID as {variable}_complete.
"""

choices: List[MCQChoice] = []
choices: list[MCQChoice] = []
"""
MCQ specific fields.
"""
Expand All @@ -186,7 +184,7 @@ class SurveyQuestionModel(ParserModel):
configuration is used.
"""

relevant: List[Condition] = []
relevant: list[Condition] = []
"""
Conditions required to present the question, otherwise skipped.
"""
Expand Down Expand Up @@ -223,7 +221,7 @@ class SurveyQuestionModel(ParserModel):
that is triggered.
"""

tags: List[str] = []
tags: list[str] = []
"""
Tags allowing to filter questions to appear in a survey.
"""
Expand Down
8 changes: 3 additions & 5 deletions src/rpft/parsers/creation/triggerrowmodel.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
from typing import List

from pydantic.v1 import validator

from rpft.parsers.common.rowparser import ParserModel


class TriggerRowModel(ParserModel):
type: str
keywords: List[str] = ""
keywords: list[str] = ""
flow: str = ""
groups: List[str] = []
exclude_groups: List[str] = []
groups: list[str] = []
exclude_groups: list[str] = []
channel: str = ""
match_type: str = ""

Expand Down
4 changes: 2 additions & 2 deletions src/rpft/parsers/sheets.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
from abc import ABC
from collections.abc import Mapping
from pathlib import Path
from typing import List, Mapping

import tablib
from googleapiclient.discovery import build
Expand All @@ -28,7 +28,7 @@ def sheets(self) -> Mapping[str, Sheet]:
def get_sheet(self, name) -> Sheet:
return self.sheets.get(name)

def get_sheets_by_name(self, name) -> List[Sheet]:
def get_sheets_by_name(self, name) -> list[Sheet]:
return [sheet] if (sheet := self.get_sheet(name)) else []


Expand Down

0 comments on commit bfdc04d

Please sign in to comment.