Skip to content

Commit 5b1c4d9

Browse files
taliawsmileySebastian Smileypre-commit-ci[bot]edgarrmondragon
authored
fix: Addressed race condition with multiple streams (#130)
Closes #129 --------- Co-authored-by: Sebastian Smiley <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Edgar Ramírez-Mondragón <[email protected]>
1 parent 186b356 commit 5b1c4d9

File tree

6 files changed

+498
-358
lines changed

6 files changed

+498
-358
lines changed

poetry.lock

Lines changed: 444 additions & 347 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

target_csv/serialization.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import csv # noqa: D100
22
from pathlib import Path
33
from typing import Any, List, Callable
4-
import os
54

65

76
def create_folder_if_not_exists(func: Any) -> Callable[..., int]:
87
"""Decorator to create folder if it does not exist."""
98

109
def wrapper(*args: Any, **kwargs: Any) -> int:
1110
try:
12-
filepath = kwargs["filepath"]
11+
filepath = Path(kwargs["filepath"])
1312
except KeyError:
14-
filepath = args[0]
15-
folder = os.path.dirname(filepath)
16-
if not os.path.exists(folder) and folder != "":
17-
os.makedirs(folder)
13+
filepath = Path(args[0])
14+
filepath.parent.mkdir(parents=True, exist_ok=True)
1815
return func(*args, **kwargs)
1916

2017
return wrapper

tests/data_files/__init__.py

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{"type": "STATE", "value": {}}
2+
{"type": "SCHEMA", "stream": "employees", "schema": {"properties": {"employee_id": {"type": ["integer"]}, "first_name": {"type": ["string"]}, "last_name": {"type": ["string"]}}, "type": "object", "required": ["employee_id", "first_name", "last_name"]}, "key_properties": ["employee_id"]}
3+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 1, "first_name": "Alice", "last_name": "Smith"}, "time_extracted": "2024-07-19T20:34:52.872497+00:00"}
4+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 2, "first_name": "Bob", "last_name": "Johnson"}, "time_extracted": "2024-07-19T20:34:52.873094+00:00"}
5+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 3, "first_name": "Carol", "last_name": "McMann"}, "time_extracted": "2024-07-19T20:34:52.873231+00:00"}
6+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 4, "first_name": "Duke", "last_name": "DeLaney"}, "time_extracted": "2024-07-19T20:34:52.873309+00:00"}
7+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 5, "first_name": "Edward", "last_name": "Smith"}, "time_extracted": "2024-07-19T20:34:52.873379+00:00"}
8+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 6, "first_name": "Frank", "last_name": "Aggarwal"}, "time_extracted": "2024-07-19T20:34:52.873462+00:00"}
9+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 7, "first_name": "Gina", "last_name": "Griffith"}, "time_extracted": "2024-07-19T20:34:52.873703+00:00"}
10+
{"type": "RECORD", "stream": "employees", "record": {"employee_id": 8, "first_name": "Hiram", "last_name": "Green"}, "time_extracted": "2024-07-19T20:34:52.873801+00:00"}
11+
{"type": "STATE", "value": {"bookmarks": {"employees": {}}}}
12+
{"type": "SCHEMA", "stream": "users", "schema": {"properties": {"user_id": {"type": ["integer"]}, "first_name": {"type": ["string"]}, "last_name": {"type": ["string"]}}, "type": "object", "required": ["user_id", "first_name", "last_name"]}, "key_properties": ["user_id"]}
13+
{"type": "RECORD", "stream": "users", "record": {"user_id": 1, "first_name": "Abraham", "last_name": "Qamar"}, "time_extracted": "2024-07-19T20:34:52.879965+00:00"}
14+
{"type": "RECORD", "stream": "users", "record": {"user_id": 2, "first_name": "Betty", "last_name": "Pattinson"}, "time_extracted": "2024-07-19T20:34:52.880376+00:00"}
15+
{"type": "RECORD", "stream": "users", "record": {"user_id": 3, "first_name": "Charlie", "last_name": "Orlando"}, "time_extracted": "2024-07-19T20:34:52.880493+00:00"}
16+
{"type": "RECORD", "stream": "users", "record": {"user_id": 4, "first_name": "Deborah", "last_name": "Nooning"}, "time_extracted": "2024-07-19T20:34:52.880562+00:00"}
17+
{"type": "RECORD", "stream": "users", "record": {"user_id": 5, "first_name": "Edward", "last_name": "Michaelson"}, "time_extracted": "2024-07-19T20:34:52.880624+00:00"}
18+
{"type": "RECORD", "stream": "users", "record": {"user_id": 6, "first_name": "Francesca", "last_name": "Little"}, "time_extracted": "2024-07-19T20:34:52.880686+00:00"}
19+
{"type": "RECORD", "stream": "users", "record": {"user_id": 7, "first_name": "Graham", "last_name": "Kingston"}, "time_extracted": "2024-07-19T20:34:52.880901+00:00"}
20+
{"type": "RECORD", "stream": "users", "record": {"user_id": 8, "first_name": "Holly", "last_name": "Johnson"}, "time_extracted": "2024-07-19T20:34:52.881002+00:00"}
21+
{"type": "STATE", "value": {"bookmarks": {"employees": {}, "users": {}}}}

tests/test_core.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,41 @@
11
"""Tests standard target features using the built-in SDK tests library."""
22

3+
from pathlib import Path
4+
import sys
35
from typing import Any, Dict
46

57
from singer_sdk.testing import get_target_test_class
8+
from singer_sdk.testing.suites import TestSuite
9+
from singer_sdk.testing.templates import TargetFileTestTemplate
610

11+
from . import data_files
712
from target_csv.target import TargetCSV
813

14+
if sys.version_info >= (3, 9):
15+
from importlib.resources import files
16+
else:
17+
from importlib_resources import files
18+
919
SAMPLE_CONFIG: Dict[str, Any] = {
1020
"escape_character": '"',
1121
}
1222

13-
TestTargetCSV = get_target_test_class(TargetCSV, config=SAMPLE_CONFIG)
23+
24+
class MultipleStreamsTest(TargetFileTestTemplate):
25+
name = "users_and_employees"
26+
27+
@property
28+
def singer_filepath(self) -> Path:
29+
return files(data_files) / f"{self.name}.singer"
30+
31+
32+
TestTargetCSV = get_target_test_class(
33+
TargetCSV,
34+
config=SAMPLE_CONFIG,
35+
custom_suites=[
36+
TestSuite(
37+
kind="target",
38+
tests=[MultipleStreamsTest],
39+
)
40+
],
41+
)

tests/test_csv.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,8 @@ def test_file_paths(output_dir) -> List[Path]:
6363
paths = []
6464
for dir in range(4):
6565
path = Path(output_dir / f"test-dir-{dir}/csv-test-output-{dir}.csv")
66-
if path.exists():
67-
path.unlink()
68-
66+
path.unlink(missing_ok=True)
6967
paths.append(path)
70-
7168
return paths
7269

7370

0 commit comments

Comments
 (0)