├── .gitignore ├── LICENSE ├── README.md └── src ├── 02 Course Overview └── Course Overview.pdf ├── 03 Data transfer objects └── Data Transfer Objects.pdf ├── 04 DTOs as vanilla Python classes ├── excercise.py └── musicalbum.py ├── 05 Intro to annotations ├── exercise.py └── musicalbum.py ├── 06 Data classes ├── exercise.py └── musicalbum.py ├── 07 Post initialisation in data classes ├── exercise.py └── musicalbum.py ├── 08 Pydantic ├── exercise.py └── musicalbum.py ├── 09 Pydantic custom validators ├── exercise.py └── musicalbum.py ├── 10 Custom exceptions ├── exercise.py └── musicalbum.py ├── 11 Serialization └── Serialization.pdf ├── 12 Polymorphism and abstract classes └── Polymorphism and Abstract Classes.pdf ├── 13 Abstract serializer ├── exercise.py └── serialization.py ├── 14 Pickle serialization ├── exercise.py ├── musicalbum.py └── serialization.py ├── 15 Json serialization ├── exercise.py ├── musicalbum.py ├── serialization.py └── the_wall.json ├── 16 Yaml serialization ├── exercise.py ├── musicalbum.py └── serialization.py ├── 17 List comprehensions ├── exercise.py └── listcomprehensions.py ├── 18 Dictionary comprehensions ├── dictionarycomprehensions.py └── exercise.py ├── 19 Iterators ├── Iterators.pdf ├── exercise.py └── iterators.py ├── 20 Generators ├── Generators.pdf ├── exercise.py └── generators.py ├── 21 Lambda functions ├── exercise.py └── lambda.py ├── 22 Map filter and reduce ├── exercise.py ├── filter.py ├── map.py └── reduce.py ├── 23 Zip ├── exercise.py └── zip.py ├── 24 With statement ├── dummy.txt └── with.py ├── 25 Context managers ├── Context managers.pdf ├── contextmanagers.py └── exercise.py ├── 26 Decorators basics ├── decorators.py └── exercise.py ├── 27 Decorators with arguments ├── decorators.py └── exercise.py ├── 28 Decorating classes ├── decorators.py └── exercise.py ├── 29 Threading and multiprocessing └── Threading and Multiprocessing.pdf ├── 30 Threading basics ├── dummy_1.json ├── dummy_2.json ├── dummy_3.json ├── dummy_4.json ├── dummy_5.json ├── dummy_6.json ├── dummy_7.json ├── dummy_8.json ├── exercise.py └── multithreading.py ├── 31 Daemon and non-daemon threads └── daemons.py ├── 32 Multiprocessing basics ├── exercise.py └── multiprocess.py ├── 33 Multiprocessing with the Pool class ├── exercise.py └── pool.py ├── 35 Data pipeline design └── Data Pipeline Design.pdf └── project ├── datapipeline.py ├── errors.py ├── loading ├── loaderiterator.py └── serialization.py ├── main.py ├── product.py ├── samplefiles ├── 1.json ├── 10.json ├── 100.json ├── 101.json ├── 102.json ├── 103.json ├── 104.json ├── 105.json ├── 106.json ├── 107.json ├── 108.json ├── 109.json ├── 11.json ├── 110.json ├── 111.json ├── 112.json ├── 113.json ├── 114.json ├── 115.json ├── 116.json ├── 117.json ├── 118.json ├── 119.json ├── 12.json ├── 120.json ├── 121.json ├── 122.json ├── 123.json ├── 124.json ├── 125.json ├── 126.json ├── 127.json ├── 128.json ├── 129.json ├── 13.json ├── 130.json ├── 131.json ├── 132.json ├── 133.json ├── 134.json ├── 135.json ├── 136.json ├── 137.json ├── 138.json ├── 139.json ├── 14.json ├── 140.json ├── 141.json ├── 142.json ├── 143.json ├── 144.json ├── 145.json ├── 146.json ├── 147.json ├── 148.json ├── 149.json ├── 15.json ├── 150.json ├── 151.json ├── 152.json ├── 153.json ├── 154.json ├── 155.json ├── 156.json ├── 157.json ├── 158.json ├── 159.json ├── 16.json ├── 160.json ├── 161.json ├── 162.json ├── 163.json ├── 164.json ├── 165.json ├── 166.json ├── 167.json ├── 168.json ├── 169.json ├── 17.json ├── 170.json ├── 171.json ├── 172.json ├── 173.json ├── 174.json ├── 175.json ├── 176.json ├── 177.json ├── 178.json ├── 179.json ├── 18.json ├── 180.json ├── 181.json ├── 182.json ├── 183.json ├── 184.json ├── 185.json ├── 186.json ├── 187.json ├── 188.json ├── 189.json ├── 19.json ├── 190.json ├── 191.json ├── 192.json ├── 193.json ├── 194.json ├── 195.json ├── 196.json ├── 197.json ├── 198.json ├── 199.json ├── 2.json ├── 20.json ├── 200.json ├── 201.json ├── 202.json ├── 203.json ├── 204.json ├── 205.json ├── 206.json ├── 207.json ├── 208.json ├── 209.json ├── 21.json ├── 210.json ├── 211.json ├── 212.json ├── 213.json ├── 214.json ├── 215.json ├── 216.json ├── 217.json ├── 218.json ├── 219.json ├── 22.json ├── 220.json ├── 221.json ├── 222.json ├── 223.json ├── 224.json ├── 225.json ├── 226.json ├── 227.json ├── 228.json ├── 229.json ├── 23.json ├── 230.json ├── 231.json ├── 232.json ├── 233.json ├── 234.json ├── 235.json ├── 236.json ├── 237.json ├── 238.json ├── 239.json ├── 24.json ├── 240.json ├── 241.json ├── 242.json ├── 243.json ├── 244.json ├── 245.json ├── 246.json ├── 247.json ├── 248.json ├── 249.json ├── 25.json ├── 250.json ├── 251.json ├── 252.json ├── 253.json ├── 254.json ├── 255.json ├── 256.json ├── 257.json ├── 258.json ├── 259.json ├── 26.json ├── 260.json ├── 261.json ├── 262.json ├── 263.json ├── 264.json ├── 265.json ├── 266.json ├── 267.json ├── 268.json ├── 269.json ├── 27.json ├── 270.json ├── 271.json ├── 272.json ├── 273.json ├── 274.json ├── 275.json ├── 276.json ├── 277.json ├── 278.json ├── 279.json ├── 28.json ├── 280.json ├── 281.json ├── 282.json ├── 283.json ├── 284.json ├── 285.json ├── 286.json ├── 287.json ├── 288.json ├── 289.json ├── 29.json ├── 290.json ├── 291.json ├── 292.json ├── 293.json ├── 294.json ├── 295.json ├── 296.json ├── 297.json ├── 298.json ├── 299.json ├── 3.json ├── 30.json ├── 300.json ├── 301.json ├── 302.json ├── 303.json ├── 304.json ├── 305.json ├── 306.json ├── 307.json ├── 308.json ├── 309.json ├── 31.json ├── 310.json ├── 311.json ├── 312.json ├── 313.json ├── 314.json ├── 315.json ├── 316.json ├── 317.json ├── 318.json ├── 319.json ├── 32.json ├── 320.json ├── 321.json ├── 322.json ├── 323.json ├── 324.json ├── 325.json ├── 326.json ├── 327.json ├── 328.json ├── 329.json ├── 33.json ├── 330.json ├── 331.json ├── 332.json ├── 333.json ├── 334.json ├── 335.json ├── 336.json ├── 337.json ├── 338.json ├── 339.json ├── 34.json ├── 340.json ├── 341.json ├── 342.json ├── 343.json ├── 344.json ├── 345.json ├── 346.json ├── 347.json ├── 348.json ├── 349.json ├── 35.json ├── 350.json ├── 351.json ├── 352.json ├── 353.json ├── 354.json ├── 355.json ├── 356.json ├── 357.json ├── 358.json ├── 359.json ├── 36.json ├── 360.json ├── 361.json ├── 362.json ├── 363.json ├── 364.json ├── 365.json ├── 366.json ├── 367.json ├── 368.json ├── 369.json ├── 37.json ├── 370.json ├── 371.json ├── 372.json ├── 373.json ├── 374.json ├── 375.json ├── 376.json ├── 377.json ├── 378.json ├── 379.json ├── 38.json ├── 380.json ├── 381.json ├── 382.json ├── 383.json ├── 384.json ├── 385.json ├── 386.json ├── 387.json ├── 388.json ├── 389.json ├── 39.json ├── 390.json ├── 391.json ├── 392.json ├── 393.json ├── 394.json ├── 395.json ├── 396.json ├── 397.json ├── 398.json ├── 399.json ├── 4.json ├── 40.json ├── 400.json ├── 401.json ├── 402.json ├── 403.json ├── 404.json ├── 405.json ├── 406.json ├── 407.json ├── 408.json ├── 409.json ├── 41.json ├── 410.json ├── 411.json ├── 412.json ├── 413.json ├── 414.json ├── 415.json ├── 416.json ├── 417.json ├── 418.json ├── 419.json ├── 42.json ├── 420.json ├── 421.json ├── 422.json ├── 423.json ├── 424.json ├── 425.json ├── 426.json ├── 427.json ├── 428.json ├── 429.json ├── 43.json ├── 430.json ├── 431.json ├── 432.json ├── 433.json ├── 434.json ├── 435.json ├── 436.json ├── 437.json ├── 438.json ├── 439.json ├── 44.json ├── 440.json ├── 441.json ├── 442.json ├── 443.json ├── 444.json ├── 445.json ├── 446.json ├── 447.json ├── 448.json ├── 449.json ├── 45.json ├── 450.json ├── 451.json ├── 452.json ├── 453.json ├── 454.json ├── 455.json ├── 456.json ├── 457.json ├── 458.json ├── 459.json ├── 46.json ├── 460.json ├── 461.json ├── 462.json ├── 463.json ├── 464.json ├── 465.json ├── 466.json ├── 467.json ├── 468.json ├── 469.json ├── 47.json ├── 470.json ├── 471.json ├── 472.json ├── 473.json ├── 474.json ├── 475.json ├── 476.json ├── 477.json ├── 478.json ├── 479.json ├── 48.json ├── 480.json ├── 481.json ├── 482.json ├── 483.json ├── 484.json ├── 485.json ├── 486.json ├── 487.json ├── 488.json ├── 489.json ├── 49.json ├── 490.json ├── 491.json ├── 492.json ├── 493.json ├── 494.json ├── 495.json ├── 496.json ├── 497.json ├── 498.json ├── 499.json ├── 5.json ├── 50.json ├── 500.json ├── 501.json ├── 51.json ├── 52.json ├── 53.json ├── 54.json ├── 55.json ├── 56.json ├── 57.json ├── 58.json ├── 59.json ├── 6.json ├── 60.json ├── 61.json ├── 62.json ├── 63.json ├── 64.json ├── 65.json ├── 66.json ├── 67.json ├── 68.json ├── 69.json ├── 7.json ├── 70.json ├── 71.json ├── 72.json ├── 73.json ├── 74.json ├── 75.json ├── 76.json ├── 77.json ├── 78.json ├── 79.json ├── 8.json ├── 80.json ├── 81.json ├── 82.json ├── 83.json ├── 84.json ├── 85.json ├── 86.json ├── 87.json ├── 88.json ├── 89.json ├── 9.json ├── 90.json ├── 91.json ├── 92.json ├── 93.json ├── 94.json ├── 95.json ├── 96.json ├── 97.json ├── 98.json └── 99.json ├── storing ├── createdb.py ├── product.db ├── sqlitebatchproductstorer.py └── sqlitecontextmanager.py ├── test ├── files │ ├── 1.json │ ├── 2.json │ ├── 3.json │ ├── 4.json │ └── 5.json ├── test_batchtransformer.py ├── test_currencyconverter.py ├── test_datapipeline.py ├── test_loaderiterator.py ├── test_pricemultiplier.py ├── test_product.py ├── test_sqlitebatchproductstorer.py ├── test_sqlitecontextmanager.py └── test_utils.py ├── threadeddatapipeline.py ├── transforming ├── batchtransformer.py ├── currencyconverter.py ├── pricemultiplier.py └── transform.py └── utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | .idea 7 | 8 | src/completed 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | pip-wheel-metadata/ 28 | share/python-wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .nox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | *.py,cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | local_settings.py 65 | db.sqlite3 66 | db.sqlite3-journal 67 | 68 | # Flask stuff: 69 | instance/ 70 | .webassets-cache 71 | 72 | # Scrapy stuff: 73 | .scrapy 74 | 75 | # Sphinx documentation 76 | docs/_build/ 77 | 78 | # PyBuilder 79 | target/ 80 | 81 | # Jupyter Notebook 82 | .ipynb_checkpoints 83 | 84 | # IPython 85 | profile_default/ 86 | ipython_config.py 87 | 88 | # pyenv 89 | .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Valerio Velardo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # advancedpython 2 | Code and presentations for the Advanced Python Programming course by Valerio 3 | Velardo - The Sound of AI. 4 | -------------------------------------------------------------------------------- /src/02 Course Overview/Course Overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/02 Course Overview/Course Overview.pdf -------------------------------------------------------------------------------- /src/03 Data transfer objects/Data Transfer Objects.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/03 Data transfer objects/Data Transfer Objects.pdf -------------------------------------------------------------------------------- /src/04 DTOs as vanilla Python classes/excercise.py: -------------------------------------------------------------------------------- 1 | class EmployeeDTO: 2 | 3 | def __init__(self, 4 | first_name, 5 | last_name, 6 | work_email, 7 | mobile_number, 8 | managers): 9 | self.first_name = first_name 10 | self.last_name = last_name 11 | self.work_email = work_email 12 | self.mobile_number = mobile_number 13 | self.managers = managers 14 | 15 | def __str__(self): 16 | return f"EmployeeDTO(first_name='{self.first_name}', last_name='{self.last_name}')" 17 | 18 | def __eq__(self, other): 19 | # compare all attributes of current object with those of other 20 | if self.__dict__ == other.__dict__: 21 | return True 22 | return False 23 | 24 | 25 | if __name__ == "__main__": 26 | john_doe = EmployeeDTO("John", 27 | "Doe", 28 | "john@company.com", 29 | 12345, 30 | ["Mad Max", "Frodo Baggins"]) 31 | john_doe_2 = EmployeeDTO("John", 32 | "Doe", 33 | "john@company.com", 34 | 12345, 35 | ["Mad Max", "Frodo Baggins"]) 36 | print(john_doe) 37 | print(john_doe == john_doe_2) 38 | -------------------------------------------------------------------------------- /src/04 DTOs as vanilla Python classes/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | class MusicAlbum: 4 | 5 | def __init__(self, 6 | title, 7 | artist, 8 | year, 9 | songs): 10 | self.title = title 11 | self.artist = artist 12 | self.year = year 13 | self.songs = songs 14 | 15 | def __str__(self): 16 | return f"MusicAlbum(title='{self.title}', artist='{self.artist}')" 17 | 18 | def __eq__(self, other): 19 | if self.title == other.title and self.artist == other.artist: 20 | return True 21 | return False 22 | 23 | 24 | if __name__ == "__main__": 25 | music_album_1 = MusicAlbum("The Wall", 26 | "Pink Floyd", 27 | 1979, 28 | ["ABitW1", "ABitW2"]) 29 | music_album_2 = MusicAlbum("The Dark Side of the Moon", 30 | "Pink Floyd", 31 | 1972, 32 | ["Time", "Us and Them"]) 33 | music_album_3 = MusicAlbum("The Wall", 34 | "Pink Floyd", 35 | 1979, 36 | ["ABitW1", "ABitW2"]) 37 | 38 | print(music_album_1 == music_album_3) -------------------------------------------------------------------------------- /src/05 Intro to annotations/exercise.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import List, Union 3 | 4 | class EmployeeDTO: 5 | 6 | def __init__(self, 7 | first_name: str, 8 | last_name: str, 9 | work_email: str, 10 | mobile_number: int, 11 | managers: Union[List[str], List[EmployeeDTO]]) -> None: 12 | self.first_name = first_name 13 | self.last_name = last_name 14 | self.work_email = work_email 15 | self.mobile_number = mobile_number 16 | self.managers = managers 17 | 18 | def __str__(self) -> str: 19 | return f"EmployeeDTO(first_name='{self.first_name}', last_name='{self.last_name}')" 20 | 21 | def __eq__(self, other: EmployeeDTO) -> bool: 22 | # compare all attributes of current object with those of other 23 | if self.__dict__ == other.__dict__: 24 | return True 25 | return False 26 | -------------------------------------------------------------------------------- /src/05 Intro to annotations/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from __future__ import annotations 4 | from typing import List 5 | 6 | 7 | class MusicAlbum: 8 | 9 | def __init__(self, 10 | title: str, 11 | artist: str, 12 | year: int, 13 | songs: List[str]) -> None: 14 | self.title = title 15 | self.artist = artist 16 | self.year = year 17 | self.songs = songs 18 | 19 | def __str__(self) -> str: 20 | return f"MusicAlbum(title='{self.title}', artist='{self.artist}')" 21 | 22 | def __eq__(self, other: MusicAlbum) -> bool: 23 | if self.title == other.title and self.artist == other.artist: 24 | return True 25 | return False 26 | 27 | 28 | if __name__ == "__main__": 29 | music_album_1 = MusicAlbum("The Wall", 30 | "Pink Floyd", 31 | 1979, 32 | ["ABitW1", "ABitW2"]) 33 | music_album_2 = MusicAlbum("The Dark Side of the Moon", 34 | "Pink Floyd", 35 | 1972, 36 | ["Time", "Us and Them"]) 37 | music_album_3 = MusicAlbum("The Wall", 38 | "Pink Floyd", 39 | 1979, 40 | ["ABitW1", "ABitW2"]) 41 | 42 | print(music_album_1 == music_album_3) -------------------------------------------------------------------------------- /src/06 Data classes/exercise.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import Union, List 3 | from dataclasses import dataclass 4 | 5 | 6 | @dataclass 7 | class EmployeeDTO: 8 | first_name: str 9 | last_name: str 10 | work_email: str 11 | mobile_number: int 12 | managers: Union[List[str], List[EmployeeDTO]] 13 | 14 | @classmethod 15 | def from_dict(cls, args_dict: dict) -> EmployeeDTO: 16 | return cls(**args_dict) 17 | 18 | 19 | if __name__ == "__main__": 20 | args_dict = { 21 | "first_name": "John", 22 | "last_name": "Doe", 23 | "work_email": "john@company.com", 24 | "mobile_number": 12345, 25 | "managers": ["Max", "Frodo"] 26 | } 27 | employee = EmployeeDTO.from_dict(args_dict) 28 | print(employee) -------------------------------------------------------------------------------- /src/06 Data classes/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from dataclasses import dataclass 4 | from typing import List 5 | 6 | 7 | @dataclass 8 | class MusicAlbum: 9 | title: str 10 | artist: str 11 | year: int 12 | songs: List[str] 13 | 14 | 15 | if __name__ == "__main__": 16 | music_album_1 = MusicAlbum("The Wall", 17 | "Pink Floyd", 18 | 1979, 19 | ["ABitW1", "ABitW2"]) 20 | music_album_2 = MusicAlbum("The Dark Side of the Moon", 21 | "Pink Floyd", 22 | 1972, 23 | ["Time", "Us and Them"]) 24 | music_album_3 = MusicAlbum("The Wall", 25 | "Pink Floyd", 26 | 1979, 27 | ["ABitW1", "ABitW2"]) 28 | 29 | print(music_album_1) 30 | print(music_album_1 == music_album_3) -------------------------------------------------------------------------------- /src/07 Post initialisation in data classes/exercise.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import Union, List 3 | from dataclasses import dataclass, field 4 | 5 | 6 | @dataclass 7 | class EmployeeDTO: 8 | first_name: str 9 | last_name: str 10 | work_email: str 11 | mobile_number: int 12 | managers: Union[List[str], List[EmployeeDTO]] 13 | complete_name: str = field(init=False) 14 | 15 | def __post_init__(self): 16 | self.complete_name = f"{self.first_name} {self.last_name}" 17 | 18 | @classmethod 19 | def from_dict(cls, args_dict: dict) -> EmployeeDTO: 20 | return cls(**args_dict) 21 | 22 | 23 | if __name__ == "__main__": 24 | args_dict = { 25 | "first_name": "John", 26 | "last_name": "Doe", 27 | "work_email": "john@company.com", 28 | "mobile_number": 12345, 29 | "managers": ["Max", "Frodo"] 30 | } 31 | employee = EmployeeDTO.from_dict(args_dict) 32 | print(employee.complete_name) -------------------------------------------------------------------------------- /src/07 Post initialisation in data classes/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from dataclasses import dataclass, field, asdict 4 | from typing import List 5 | 6 | 7 | CURRENT_YEAR = 2022 8 | 9 | 10 | @dataclass 11 | class MusicAlbum: 12 | title: str 13 | artist: str 14 | year: int 15 | songs: List[str] 16 | years_from_publication: int = field(init=False) 17 | 18 | def __post_init__(self) -> None: 19 | self.years_from_publication = CURRENT_YEAR - self.year 20 | 21 | def to_dict(self) -> dict: 22 | return asdict(self) 23 | 24 | 25 | if __name__ == "__main__": 26 | music_album_1 = MusicAlbum("The Wall", 27 | "Pink Floyd", 28 | 1979, 29 | ["ABitW1", "ABitW2"]) 30 | 31 | print(music_album_1) 32 | print(music_album_1.to_dict()) -------------------------------------------------------------------------------- /src/08 Pydantic/exercise.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import Union, List 3 | 4 | from pydantic import BaseModel 5 | 6 | 7 | class EmployeeDTO(BaseModel): 8 | first_name: str 9 | last_name: str 10 | work_email: str 11 | mobile_number: int 12 | managers: Union[List[str], List[EmployeeDTO]] 13 | complete_name: str = None 14 | 15 | def __init__(self, **employee_params): 16 | super().__init__(**employee_params) 17 | self.complete_name = f"{self.first_name} {self.last_name}" 18 | 19 | @classmethod 20 | def from_dict(cls, args_dict: dict) -> EmployeeDTO: 21 | return cls(**args_dict) 22 | 23 | 24 | if __name__ == "__main__": 25 | args_dict = { 26 | "first_name": "John", 27 | "last_name": "Doe", 28 | "work_email": "john@company.com", 29 | "mobile_number": 12345, 30 | "managers": ["Max", "Frodo"] 31 | } 32 | employee = EmployeeDTO.from_dict(args_dict) 33 | print(employee) -------------------------------------------------------------------------------- /src/08 Pydantic/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from typing import List 4 | 5 | from pydantic import BaseModel 6 | 7 | 8 | CURRENT_YEAR = 2022 9 | 10 | 11 | class MusicAlbum(BaseModel): 12 | title: str 13 | artist: str 14 | year: int 15 | songs: List[str] 16 | years_from_publication: int = None 17 | 18 | def __init__(self, **kwargs) -> None: 19 | super().__init__(**kwargs) 20 | self.years_from_publication = CURRENT_YEAR - self.year 21 | 22 | 23 | if __name__ == "__main__": 24 | params = { 25 | "title": "The Wall", 26 | "artist": "Pink Floyd", 27 | "year": 1979, 28 | "songs": ["ABitW1", "ABitW2"] 29 | } 30 | 31 | music_album_1 = MusicAlbum(title="The Wall", 32 | artist="Pink Floyd", 33 | year=1979, 34 | songs=["ABitW1", "ABitW2"]) 35 | music_album_2 = MusicAlbum(**params) 36 | print(music_album_2.years_from_publication) 37 | -------------------------------------------------------------------------------- /src/09 Pydantic custom validators/exercise.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import Union, List, Dict, Any 3 | 4 | from pydantic import BaseModel, validator 5 | 6 | 7 | class EmployeeDTO(BaseModel): 8 | first_name: str 9 | last_name: str 10 | work_email: str 11 | mobile_number: int 12 | managers: Union[List[str], List[EmployeeDTO]] 13 | complete_name: str = None 14 | 15 | def __init__(self, **employee_params): 16 | super().__init__(**employee_params) 17 | self.complete_name = f"{self.first_name} {self.last_name}" 18 | 19 | @validator("mobile_number") 20 | @classmethod 21 | def check_mobile_number_has_min_length(cls, value: int) -> int: 22 | min_number_digits = 6 23 | num_digits = len(str(value)) 24 | if num_digits < min_number_digits: 25 | msg = f"Mobile number passed '{value}' has {num_digits} digits. " \ 26 | f"Minimum number of digits allowed is {min_number_digits}" 27 | raise ValueError(msg) 28 | return value 29 | 30 | @validator("work_email") 31 | @classmethod 32 | def check_work_email_contains_first_name(cls, 33 | value: str, 34 | values: Dict[str, Any]) -> str: 35 | if values["first_name"].lower() not in value: 36 | msg = f"Work email passed '{value}' doesn't contain first_name: " \ 37 | f"{values['first_name']}" 38 | raise ValueError(msg) 39 | return value 40 | 41 | @classmethod 42 | def from_dict(cls, args_dict: dict) -> EmployeeDTO: 43 | return cls(**args_dict) 44 | 45 | 46 | if __name__ == "__main__": 47 | args_dict = { 48 | "first_name": "John", 49 | "last_name": "Doe", 50 | "work_email": "dana@company.com", 51 | "mobile_number": 12345, 52 | "managers": ["Max", "Frodo"] 53 | } 54 | employee = EmployeeDTO(**args_dict) 55 | -------------------------------------------------------------------------------- /src/09 Pydantic custom validators/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from typing import List 4 | 5 | from pydantic import BaseModel, validator 6 | 7 | 8 | CURRENT_YEAR = 2022 9 | 10 | 11 | class MusicAlbum(BaseModel): 12 | title: str 13 | artist: str 14 | year: int 15 | songs: List[str] 16 | years_from_publication: int = None 17 | 18 | def __init__(self, **kwargs) -> None: 19 | super().__init__(**kwargs) 20 | self.years_from_publication = CURRENT_YEAR - self.year 21 | 22 | @validator("year") 23 | @classmethod 24 | def check_year_is_in_range(cls, value: int) -> int: 25 | supported_year_range = {"min": 1920, "max": 2022} 26 | if not supported_year_range["min"] <= value <= supported_year_range["max"]: 27 | message = f"'{value}' value isn't in supported year range: {supported_year_range}" 28 | raise ValueError(message) 29 | return value 30 | 31 | 32 | if __name__ == "__main__": 33 | music_album_1 = MusicAlbum(title="The Wall", 34 | artist="Pink Floyd", 35 | year=1919, 36 | songs=["ABitW1", "ABitW2"]) 37 | print(music_album_1) 38 | -------------------------------------------------------------------------------- /src/10 Custom exceptions/exercise.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import Union, List, Dict, Any 3 | 4 | from pydantic import BaseModel, validator 5 | 6 | 7 | class TooFewDigitsError(Exception): 8 | 9 | def __init__(self, num_digits: int, message: str): 10 | self.num_digits = num_digits 11 | self.message = message 12 | 13 | 14 | class FirstNameNotInWorkEmailError(Exception): 15 | 16 | def __init__(self, work_email: str, first_name: str, message: str): 17 | self.work_email = work_email 18 | self.first_name = first_name 19 | self.message = message 20 | 21 | 22 | class EmployeeDTO(BaseModel): 23 | first_name: str 24 | last_name: str 25 | work_email: str 26 | mobile_number: int 27 | managers: Union[List[str], List[EmployeeDTO]] 28 | complete_name: str = None 29 | 30 | def __init__(self, **employee_params): 31 | super().__init__(**employee_params) 32 | self.complete_name = f"{self.first_name} {self.last_name}" 33 | 34 | @validator("mobile_number") 35 | @classmethod 36 | def check_mobile_number_has_min_length(cls, value: int) -> int: 37 | min_number_digits = 6 38 | num_digits = len(str(value)) 39 | if num_digits < min_number_digits: 40 | msg = f"Mobile number passed '{value}' has {num_digits} digits. " \ 41 | f"Minimum number of digits allowed is {min_number_digits}" 42 | raise TooFewDigitsError(num_digits, msg) 43 | return value 44 | 45 | @validator("work_email") 46 | @classmethod 47 | def check_work_email_contains_first_name(cls, 48 | value: str, 49 | values: Dict[str, Any]) -> str: 50 | if values["first_name"].lower() not in value: 51 | msg = f"Work email passed '{value}' doesn't contain first_name: " \ 52 | f"{values['first_name']}" 53 | raise FirstNameNotInWorkEmailError(value, values["first_name"], msg) 54 | return value 55 | 56 | @classmethod 57 | def from_dict(cls, args_dict: dict) -> EmployeeDTO: 58 | return cls(**args_dict) 59 | 60 | 61 | if __name__ == "__main__": 62 | args_dict = { 63 | "first_name": "John", 64 | "last_name": "Doe", 65 | "work_email": "dana@company.com", 66 | "mobile_number": 123456, 67 | "managers": ["Max", "Frodo"] 68 | } 69 | employee = EmployeeDTO(**args_dict) 70 | -------------------------------------------------------------------------------- /src/10 Custom exceptions/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from typing import List 4 | 5 | from pydantic import BaseModel, validator 6 | 7 | 8 | CURRENT_YEAR = 2022 9 | 10 | 11 | class YearOutOfRangeError(Exception): 12 | 13 | def __init__(self, year: int, message: str) -> None: 14 | self.year = year 15 | self.message = message 16 | 17 | 18 | class MusicAlbum(BaseModel): 19 | title: str 20 | artist: str 21 | year: int 22 | songs: List[str] 23 | years_from_publication: int = None 24 | 25 | def __init__(self, **kwargs) -> None: 26 | super().__init__(**kwargs) 27 | self.years_from_publication = CURRENT_YEAR - self.year 28 | 29 | @validator("year") 30 | @classmethod 31 | def check_year_is_in_range(cls, value: int) -> int: 32 | supported_year_range = {"min": 1920, "max": 2022} 33 | if not supported_year_range["min"] <= value <= supported_year_range["max"]: 34 | message = f"'{value}' value isn't in supported year range: {supported_year_range}" 35 | raise YearOutOfRangeError(value, message) 36 | return value 37 | 38 | 39 | if __name__ == "__main__": 40 | music_album_1 = MusicAlbum(title="The Wall", 41 | artist="Pink Floyd", 42 | year=1919, 43 | songs=["ABitW1", "ABitW2"]) 44 | print(music_album_1) 45 | -------------------------------------------------------------------------------- /src/11 Serialization/Serialization.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/11 Serialization/Serialization.pdf -------------------------------------------------------------------------------- /src/12 Polymorphism and abstract classes/Polymorphism and Abstract Classes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/12 Polymorphism and abstract classes/Polymorphism and Abstract Classes.pdf -------------------------------------------------------------------------------- /src/13 Abstract serializer/exercise.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod, ABC 2 | 3 | 4 | class Animal(ABC): 5 | 6 | @property 7 | @abstractmethod 8 | def number_of_legs(self) -> int: 9 | pass 10 | 11 | @abstractmethod 12 | def make_sound(self) -> None: 13 | pass 14 | -------------------------------------------------------------------------------- /src/13 Abstract serializer/serialization.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Any 3 | from pathlib import Path 4 | 5 | 6 | class Serializer(ABC): 7 | 8 | @abstractmethod 9 | def dump(self, obj: Any, save_path: Path) -> None: 10 | pass 11 | 12 | @abstractmethod 13 | def load(self, load_path: Path) -> Any: 14 | pass 15 | 16 | 17 | if __name__ == "__main__": 18 | serializer = Serializer() -------------------------------------------------------------------------------- /src/14 Pickle serialization/exercise.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod, ABC 2 | 3 | 4 | class Animal(ABC): 5 | 6 | @property 7 | @abstractmethod 8 | def number_of_legs(self) -> int: 9 | pass 10 | 11 | @abstractmethod 12 | def make_sound(self) -> None: 13 | pass 14 | 15 | 16 | class Dog(Animal): 17 | 18 | @property 19 | def number_of_legs(self) -> int: 20 | return 4 21 | 22 | def make_sound(self) -> None: 23 | print("Woof woof!") 24 | 25 | 26 | if __name__ == "__main__": 27 | doggo = Dog() 28 | print(doggo.number_of_legs) 29 | doggo.make_sound() -------------------------------------------------------------------------------- /src/14 Pickle serialization/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from typing import List 4 | 5 | from pydantic import BaseModel, validator 6 | 7 | 8 | CURRENT_YEAR = 2022 9 | 10 | 11 | class YearOutOfRangeError(Exception): 12 | 13 | def __init__(self, year: int, message: str) -> None: 14 | self.year = year 15 | self.message = message 16 | 17 | 18 | class MusicAlbum(BaseModel): 19 | title: str 20 | artist: str 21 | year: int 22 | songs: List[str] 23 | years_from_publication: int = None 24 | 25 | def __init__(self, **kwargs) -> None: 26 | super().__init__(**kwargs) 27 | self.years_from_publication = CURRENT_YEAR - self.year 28 | 29 | @validator("year") 30 | @classmethod 31 | def check_year_is_in_range(cls, value: int) -> int: 32 | supported_year_range = {"min": 1920, "max": 2022} 33 | if not supported_year_range["min"] <= value <= supported_year_range["max"]: 34 | message = f"'{value}' value isn't in supported year range: {supported_year_range}" 35 | raise YearOutOfRangeError(value, message) 36 | return value 37 | -------------------------------------------------------------------------------- /src/14 Pickle serialization/serialization.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | from abc import ABC, abstractmethod 3 | from typing import Any 4 | from pathlib import Path 5 | 6 | from musicalbum import MusicAlbum 7 | 8 | 9 | class Serializer(ABC): 10 | 11 | @abstractmethod 12 | def dump(self, obj: Any, save_path: Path) -> None: 13 | pass 14 | 15 | @abstractmethod 16 | def load(self, load_path: Path) -> Any: 17 | pass 18 | 19 | 20 | class PickleSerializer(Serializer): 21 | 22 | def __init__(self, 23 | protocol: int = 5, 24 | encoding: str = "ASCII") -> None: 25 | self.protocol = protocol 26 | self.encoding = encoding 27 | 28 | def dump(self, obj: Any, save_path: Path) -> None: 29 | with open(save_path, "wb") as file: 30 | pickle.dump(obj, file, protocol=self.protocol) 31 | 32 | def load(self, load_path: Path) -> Any: 33 | with open(load_path, "rb") as file: 34 | return pickle.load(file, encoding=self.encoding) 35 | 36 | 37 | if __name__ == "__main__": 38 | params = { 39 | "title": "The Wall", 40 | "artist": "Pink Floyd", 41 | "year": 1979, 42 | "songs": ["ABitW1", "ABiTW2"] 43 | } 44 | the_wall = MusicAlbum(**params) 45 | #print(the_wall) 46 | 47 | pickle_serializer = PickleSerializer() 48 | pickle_serializer.dump(the_wall, Path("the_wall.pkl")) 49 | 50 | the_wall_2 = pickle_serializer.load(Path("the_wall.pkl")) 51 | print(the_wall_2) 52 | 53 | -------------------------------------------------------------------------------- /src/15 Json serialization/exercise.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod, ABC 2 | 3 | 4 | class Animal(ABC): 5 | 6 | @property 7 | @abstractmethod 8 | def number_of_legs(self) -> int: 9 | pass 10 | 11 | @abstractmethod 12 | def make_sound(self) -> None: 13 | pass 14 | 15 | 16 | class Dog(Animal): 17 | 18 | @property 19 | def number_of_legs(self) -> int: 20 | return 4 21 | 22 | def make_sound(self) -> None: 23 | print("Woof woof!") 24 | 25 | 26 | class Duck(Animal): 27 | 28 | @property 29 | def number_of_legs(self) -> int: 30 | return 2 31 | 32 | def make_sound(self) -> None: 33 | print("Quack quack!") 34 | 35 | 36 | if __name__ == "__main__": 37 | duck = Duck() 38 | print(duck.number_of_legs) 39 | duck.make_sound() -------------------------------------------------------------------------------- /src/15 Json serialization/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from typing import List 4 | 5 | from pydantic import BaseModel, validator 6 | 7 | 8 | CURRENT_YEAR = 2022 9 | 10 | 11 | class YearOutOfRangeError(Exception): 12 | 13 | def __init__(self, year: int, message: str) -> None: 14 | self.year = year 15 | self.message = message 16 | 17 | 18 | class MusicAlbum(BaseModel): 19 | title: str 20 | artist: str 21 | year: int 22 | songs: List[str] 23 | years_from_publication: int = None 24 | 25 | def __init__(self, **kwargs) -> None: 26 | super().__init__(**kwargs) 27 | self.years_from_publication = CURRENT_YEAR - self.year 28 | 29 | @validator("year") 30 | @classmethod 31 | def check_year_is_in_range(cls, value: int) -> int: 32 | supported_year_range = {"min": 1920, "max": 2022} 33 | if not supported_year_range["min"] <= value <= supported_year_range["max"]: 34 | message = f"'{value}' value isn't in supported year range: {supported_year_range}" 35 | raise YearOutOfRangeError(value, message) 36 | return value 37 | -------------------------------------------------------------------------------- /src/15 Json serialization/serialization.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import json 3 | from abc import ABC, abstractmethod 4 | from typing import Any 5 | from pathlib import Path 6 | 7 | from musicalbum import MusicAlbum 8 | 9 | 10 | class Serializer(ABC): 11 | 12 | @abstractmethod 13 | def dump(self, obj: Any, save_path: Path) -> None: 14 | pass 15 | 16 | @abstractmethod 17 | def load(self, load_path: Path) -> Any: 18 | pass 19 | 20 | 21 | class PickleSerializer(Serializer): 22 | 23 | def __init__(self, 24 | protocol: int = 5, 25 | encoding: str = "ASCII") -> None: 26 | self.protocol = protocol 27 | self.encoding = encoding 28 | 29 | def dump(self, obj: Any, save_path: Path) -> None: 30 | with open(save_path, "wb") as file: 31 | pickle.dump(obj, file, protocol=self.protocol) 32 | 33 | def load(self, load_path: Path) -> Any: 34 | with open(load_path, "rb") as file: 35 | return pickle.load(file, encoding=self.encoding) 36 | 37 | 38 | class JsonSerializer(Serializer): 39 | 40 | def __init__(self, 41 | sort_keys: bool = True, 42 | indent: int = 4): 43 | self.sort_keys = sort_keys 44 | self.indent = indent 45 | 46 | def dump(self, obj: Any, save_path: Path) -> None: 47 | with open(save_path, "w") as file: 48 | json.dump(obj, file, sort_keys=self.sort_keys, indent=self.indent) 49 | 50 | def load(self, load_path: Path) -> Any: 51 | with open(load_path, "r") as file: 52 | return json.load(file) 53 | 54 | 55 | if __name__ == "__main__": 56 | params = { 57 | "title": "The Wall", 58 | "artist": "Pink Floyd", 59 | "year": 1979, 60 | "songs": ["ABitW1", "ABiTW2"] 61 | } 62 | the_wall = MusicAlbum(**params) 63 | the_wall_dict = the_wall.dict() 64 | print(the_wall_dict) 65 | 66 | path = Path("the_wall.json") 67 | 68 | json_serializer = JsonSerializer() 69 | json_serializer.dump(the_wall_dict, path) 70 | the_wall_dict_2 = json_serializer.load(path) 71 | 72 | the_wall_2 = MusicAlbum(**the_wall_dict_2) 73 | print(the_wall_2) 74 | -------------------------------------------------------------------------------- /src/15 Json serialization/the_wall.json: -------------------------------------------------------------------------------- 1 | { 2 | "artist": "Pink Floyd", 3 | "songs": [ 4 | "ABitW1", 5 | "ABiTW2" 6 | ], 7 | "title": "The Wall", 8 | "year": 1979, 9 | "years_from_publication": 43 10 | } -------------------------------------------------------------------------------- /src/16 Yaml serialization/exercise.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from typing import Any 3 | from pathlib import Path 4 | 5 | import joblib 6 | 7 | from musicalbum import MusicAlbum 8 | 9 | 10 | class Serializer(ABC): 11 | 12 | @abstractmethod 13 | def dump(self, obj: Any, save_path: Path) -> None: 14 | pass 15 | 16 | @abstractmethod 17 | def load(self, load_path: Path) -> Any: 18 | pass 19 | 20 | 21 | class JoblibSerializer(Serializer): 22 | 23 | def __init__(self, pickle_protocol=5): 24 | self.pickle_protocol = pickle_protocol 25 | 26 | def dump(self, obj: Any, save_path: Path) -> None: 27 | joblib.dump(obj, save_path, protocol=self.pickle_protocol) 28 | 29 | def load(self, load_path: Path) -> Any: 30 | return joblib.load(load_path) 31 | 32 | 33 | if __name__ == "__main__": 34 | params = { 35 | "title": "The Wall", 36 | "artist": "Pink Floyd", 37 | "year": 1979, 38 | "songs": ["ABitW1", "ABiTW2"] 39 | } 40 | the_wall = MusicAlbum(**params) 41 | path = Path("the_wall.joblib") 42 | 43 | joblib_serializer = JoblibSerializer() 44 | joblib_serializer.dump(the_wall, path) 45 | the_wall_2 = joblib_serializer.load(path) 46 | print(the_wall_2) 47 | 48 | -------------------------------------------------------------------------------- /src/16 Yaml serialization/musicalbum.py: -------------------------------------------------------------------------------- 1 | """MusicAlbum -> title, artist, year, songs""" 2 | 3 | from typing import List 4 | 5 | from pydantic import BaseModel, validator 6 | 7 | 8 | CURRENT_YEAR = 2022 9 | 10 | 11 | class YearOutOfRangeError(Exception): 12 | 13 | def __init__(self, year: int, message: str) -> None: 14 | self.year = year 15 | self.message = message 16 | 17 | 18 | class MusicAlbum(BaseModel): 19 | title: str 20 | artist: str 21 | year: int 22 | songs: List[str] 23 | years_from_publication: int = None 24 | 25 | def __init__(self, **kwargs) -> None: 26 | super().__init__(**kwargs) 27 | self.years_from_publication = CURRENT_YEAR - self.year 28 | 29 | @validator("year") 30 | @classmethod 31 | def check_year_is_in_range(cls, value: int) -> int: 32 | supported_year_range = {"min": 1920, "max": 2022} 33 | if not supported_year_range["min"] <= value <= supported_year_range["max"]: 34 | message = f"'{value}' value isn't in supported year range: {supported_year_range}" 35 | raise YearOutOfRangeError(value, message) 36 | return value 37 | -------------------------------------------------------------------------------- /src/17 List comprehensions/exercise.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | # Exercise 1 4 | list_1 = [sqrt(i) for i in range(10)] 5 | print(list_1) 6 | 7 | # Exercise 2 8 | list_2 = [sqrt(i) if i % 3 == 0 else i**2 for i in range(20)] 9 | print(list_2) 10 | 11 | # Exercise 3 12 | list_3 = [ [i*j for i in range(3)] for j in range(4)] 13 | print(list_3) -------------------------------------------------------------------------------- /src/17 List comprehensions/listcomprehensions.py: -------------------------------------------------------------------------------- 1 | """ 2 | List comprehensions: 3 | - Compact way to create lists 4 | - Faster than loops to instantiate lists 5 | - More pythonic! 6 | """ 7 | 8 | 9 | # basic usage 10 | squares = [0, 1, 4, 9, 16, 25] 11 | squares_list = [i**2 for i in range(6)] 12 | 13 | squares_2 = [] 14 | for i in range(6): 15 | squares_2.append(i**2) 16 | 17 | 18 | # conditionals with list comprehensions 19 | squares_of_even_nums = [i**2 for i in range(6) if i % 2 == 0] 20 | 21 | # 0 -> even, 1 -> odd 22 | even_odds = ["even" if i % 2 == 0 else "odd" for i in range(6)] 23 | 24 | 25 | # nested list comprehensions 26 | matrix = [[0, 1], [0, 1], [0, 1]] 27 | matrix_list = [[i for i in range(3)] for j in range(5)] 28 | print(matrix_list) 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/18 Dictionary comprehensions/dictionarycomprehensions.py: -------------------------------------------------------------------------------- 1 | squares = {0: 0, 1: 1, 2: 4, 3: 9} 2 | 3 | squares_2 = {n:n**2 for n in range(4)} 4 | 5 | square_dictionary = {"a": 0, "b": 4, "c": 9} 6 | 7 | dictionary = {"a": 0, "b": 2, "c": 3} 8 | square_dictionary_2 = {k:v**2 for (k, v) in dictionary.items()} 9 | 10 | even_odd_dict = {k: ("even" if v % 2 == 0 else "odd") for (k, v) in dictionary.items()} 11 | print(even_odd_dict) 12 | -------------------------------------------------------------------------------- /src/18 Dictionary comprehensions/exercise.py: -------------------------------------------------------------------------------- 1 | from math import pow 2 | 3 | # Exercise 1 4 | dict_1 = {f"power_{power}": [pow(i, power) for i in range(4)] for power in range(4)} 5 | print(dict_1) 6 | 7 | # Exercise 2 8 | sample_dict = { 9 | "a": 1, 10 | "b": 4, 11 | "c": 17, 12 | "d": 16 13 | } 14 | filtered_dict = {k:v for (k, v) in sample_dict.items() if v % 4 == 0} 15 | print(filtered_dict) -------------------------------------------------------------------------------- /src/19 Iterators/Iterators.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/19 Iterators/Iterators.pdf -------------------------------------------------------------------------------- /src/19 Iterators/exercise.py: -------------------------------------------------------------------------------- 1 | class PowerSum: 2 | 3 | def __init__(self, 4 | exponent: int, 5 | start: int, 6 | stop: int) -> None: 7 | self.exponent = exponent 8 | self.start = start 9 | self.stop = stop 10 | self._sum = 0 11 | 12 | def __iter__(self): 13 | self.num = self.start 14 | return self 15 | 16 | def __next__(self): 17 | if self.num > self.stop: 18 | raise StopIteration 19 | power = pow(self.num, self.exponent) 20 | self.num += 1 21 | self._sum += power 22 | return self._sum 23 | 24 | 25 | if __name__ == "__main__": 26 | power_sum = PowerSum(2, 0, 3) 27 | for sum_ in power_sum: 28 | print(sum_) 29 | -------------------------------------------------------------------------------- /src/19 Iterators/iterators.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | # l = [1, 2, 3] 4 | # 5 | # l_iterator = iter(l) 6 | # print(next(l_iterator)) 7 | # print(next(l_iterator)) 8 | # print(next(l_iterator)) 9 | # print(next(l_iterator)) 10 | 11 | class Square: 12 | 13 | def __init__(self, start: int, stop: int) -> None: 14 | self.start = start 15 | self.stop = stop 16 | 17 | def __iter__(self) -> Square: 18 | self.num = self.start 19 | return self 20 | 21 | def __next__(self) -> int: 22 | if self.num > self.stop: 23 | raise StopIteration 24 | square = self.num ** 2 25 | self.num += 1 26 | return square 27 | 28 | 29 | if __name__ == "__main__": 30 | square = Square(0, 5) 31 | 32 | square_i = iter(square) 33 | print(next(square_i)) 34 | print(next(square_i)) 35 | print(next(square_i)) 36 | print(next(square_i)) 37 | print(next(square_i)) 38 | print(next(square_i)) 39 | print(next(square_i)) 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/20 Generators/Generators.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/20 Generators/Generators.pdf -------------------------------------------------------------------------------- /src/20 Generators/exercise.py: -------------------------------------------------------------------------------- 1 | import math 2 | from typing import Generator 3 | 4 | 5 | def factorial_generator(start: int, stop: int) -> Generator: 6 | number = start 7 | while number <= stop: 8 | value = math.factorial(number) 9 | yield value 10 | number += 1 11 | 12 | 13 | for factorial in factorial_generator(0, 3): 14 | print(factorial) 15 | -------------------------------------------------------------------------------- /src/20 Generators/generators.py: -------------------------------------------------------------------------------- 1 | # def composer_generator(): 2 | # yield "Beethoven" 3 | # yield "Mozart" 4 | # yield "Haydn" 5 | # 6 | # composer = composer_generator() 7 | 8 | # print(next(composer)) 9 | # print(next(composer)) 10 | # print(next(composer)) 11 | # print(next(composer)) 12 | 13 | # for c in composer: 14 | # print(c) 15 | 16 | def squares_sum(start, stop): 17 | i = start 18 | sum = 0 19 | while i < stop: 20 | square = i ** 2 21 | sum += square 22 | yield sum 23 | i += 1 24 | 25 | s = squares_sum(0, 3) 26 | print(next(s)) 27 | print(next(s)) 28 | print(next(s)) 29 | print(next(s)) 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/21 Lambda functions/exercise.py: -------------------------------------------------------------------------------- 1 | is_divisible_by = lambda value, divisor: True if value % divisor == 0 else False 2 | 3 | print(is_divisible_by(7, 8)) 4 | print(is_divisible_by(64, 8)) 5 | -------------------------------------------------------------------------------- /src/21 Lambda functions/lambda.py: -------------------------------------------------------------------------------- 1 | # Lambda is an anonymous function 2 | # Can take any number of params, but only 1 expression 3 | # It's useful when used with other functions (e.g., map, reduce, filter) 4 | 5 | def square(n: int) -> int: 6 | return n**2 7 | 8 | square_lambda = lambda n: n**2 9 | 10 | # print(square_lambda(2)) 11 | 12 | minimum = lambda x, y: x if x < y else y 13 | print(minimum(1, 2)) 14 | 15 | -------------------------------------------------------------------------------- /src/22 Map filter and reduce/exercise.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | from functools import reduce 3 | 4 | 5 | l = [2, 4 ,16, 80] 6 | 7 | # Exercise 1 8 | l_divided_by_2 = map(lambda n: n / 2, l) 9 | print(list(l_divided_by_2)) 10 | 11 | # Exercises 2 12 | l_filtered = filter(lambda n: sqrt(n).is_integer(), l) 13 | print(list(l_filtered)) 14 | 15 | # Exercises 3 16 | l2 = [1, 2, 3] 17 | cumulative_product = reduce(lambda current_product, value: current_product * value, l2) 18 | print(cumulative_product) -------------------------------------------------------------------------------- /src/22 Map filter and reduce/filter.py: -------------------------------------------------------------------------------- 1 | # The filter function takes in a function that returns a bool and an iterable(list, tuple, etc.) as an input. 2 | # It applies passed function to each item of an iterable and returns a filter object (an iterator). 3 | 4 | numbers = [1, 2, 3, 4] 5 | evens_only = filter(lambda n: n % 2 == 0, numbers) 6 | 7 | print(list(evens_only)) 8 | 9 | -------------------------------------------------------------------------------- /src/22 Map filter and reduce/map.py: -------------------------------------------------------------------------------- 1 | # The map function takes in a function and an iterable(list, tuple, etc.) as an input. 2 | # It applies passed function to each item of an iterable and returns a map object (an iterator). 3 | 4 | def square(n): 5 | return n**2 6 | 7 | numbers = [1, 2, 3] 8 | 9 | squared_numbers = map(square, numbers) 10 | #print(list(squared_numbers)) 11 | 12 | even_odd = map(lambda n: "even" if n % 2 == 0 else "odd", numbers) 13 | print(list(even_odd)) 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/22 Map filter and reduce/reduce.py: -------------------------------------------------------------------------------- 1 | # The reduce function applies a function cumulatively on all the items of an iterable 2 | # and returns a single value. 3 | 4 | from functools import reduce 5 | 6 | numbers = [1, 2, 3] 7 | 8 | cumulative_sum = reduce(lambda a, b: a + b, numbers) 9 | print(cumulative_sum) 10 | -------------------------------------------------------------------------------- /src/23 Zip/exercise.py: -------------------------------------------------------------------------------- 1 | first_names = ["Albert", "Isaac"] 2 | last_names = ["Einstein", "Newton"] 3 | 4 | for physicist in zip(first_names, last_names): 5 | print(f"Hi! I'm {physicist[0]} {physicist[1]}.") 6 | -------------------------------------------------------------------------------- /src/23 Zip/zip.py: -------------------------------------------------------------------------------- 1 | compositions = ["the firebird", "another brick in the wall", "fur elise"] 2 | composers = ["igor stravinsky", "pink floyd", "l. v. beethoven"] 3 | 4 | combined_structures = zip(compositions, composers) 5 | # print(list(combined_structures)) 6 | 7 | for c in zip(compositions, composers): 8 | print(c[0]) 9 | print(c[1]) 10 | print("_______") 11 | -------------------------------------------------------------------------------- /src/24 With statement/dummy.txt: -------------------------------------------------------------------------------- 1 | dummy -------------------------------------------------------------------------------- /src/24 With statement/with.py: -------------------------------------------------------------------------------- 1 | # file = open("dummy.txt", "r") 2 | # data = file.readline() 3 | # new_data = data + 2 4 | # file.close() 5 | 6 | # try: 7 | # file = open("dummy.txt", "r") 8 | # data = file.readline() 9 | # new_data = data + 2 10 | # except TypeError as error: 11 | # print(error) 12 | # finally: 13 | # print("Safely closing file") 14 | # file.close() 15 | 16 | with open("dummy.txt", "r") as file: 17 | data = file.readline() 18 | new_data = data + 2 -------------------------------------------------------------------------------- /src/25 Context managers/Context managers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/25 Context managers/Context managers.pdf -------------------------------------------------------------------------------- /src/25 Context managers/contextmanagers.py: -------------------------------------------------------------------------------- 1 | # class Greetings: 2 | # 3 | # def __init__(self, name): 4 | # self.name = name 5 | # 6 | # def __enter__(self): 7 | # print("Entering the context") 8 | # print(f"Hello {self.name}") 9 | # return self.name 10 | # 11 | # def __exit__(self, exc_type, exc_val, exc_tb): 12 | # print(exc_type, exc_val, exc_tb) 13 | # print("Exiting the context") 14 | # if isinstance(exc_val, IndexError): 15 | # print(f"Error type: {exc_type}") 16 | # print(f"Error value: {exc_val}") 17 | # return True 18 | # 19 | # 20 | # with Greetings("John") as name: 21 | # print(f"Some code for {name}") 22 | # name[50] 23 | # 24 | # print("A statement after the with block") 25 | 26 | 27 | class WriteFile: 28 | 29 | def __init__(self, path): 30 | self.path = path 31 | 32 | def __enter__(self): 33 | self.file = open(self.path, "w") 34 | return self.file 35 | 36 | def __exit__(self, exc_type, exc_val, exc_tb): 37 | # Handle exceptions 38 | self.file.close() 39 | 40 | 41 | with WriteFile("data.txt") as f: 42 | f.write("dummy dummy") 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/25 Context managers/exercise.py: -------------------------------------------------------------------------------- 1 | from time import perf_counter 2 | 3 | 4 | class CodeExecutionTimer: 5 | 6 | def __init__(self): 7 | self.start_time = None 8 | self.stop_time = None 9 | 10 | def __enter__(self): 11 | self.start_time = perf_counter() 12 | 13 | def __exit__(self, exc_type, exc_val, exc_tb): 14 | self.stop_time = perf_counter() 15 | print(f"Execution time: {self.stop_time - self.start_time} seconds") 16 | 17 | 18 | if __name__ == "__main__": 19 | with CodeExecutionTimer(): 20 | squares = [n**2 for n in range(100000)] 21 | -------------------------------------------------------------------------------- /src/26 Decorators basics/decorators.py: -------------------------------------------------------------------------------- 1 | # Decorators wrap a function / class -> modify its behaviour 2 | 3 | # Use cases: 4 | # - checking types 5 | # - timing 6 | # - wait 7 | # - check if user is logged in 8 | # - ... 9 | 10 | def greetings(func): 11 | def wrapper(): 12 | print("Welcome!") 13 | func() 14 | print("Bye!") 15 | return wrapper 16 | 17 | 18 | @greetings 19 | def hello_valerio(): 20 | print("Hello Valerio") 21 | 22 | 23 | hello_valerio() 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/26 Decorators basics/exercise.py: -------------------------------------------------------------------------------- 1 | from time import perf_counter 2 | 3 | 4 | def print_time(func): 5 | def wrapper(): 6 | start_time = perf_counter() 7 | func() 8 | stop_time = perf_counter() 9 | print(f"Execution time: {stop_time - start_time} seconds") 10 | return wrapper 11 | 12 | 13 | @print_time 14 | def create_one_million_squares_list(): 15 | return [n**2 for n in range(1000000)] 16 | 17 | 18 | if __name__ == "__main__": 19 | create_one_million_squares_list() -------------------------------------------------------------------------------- /src/27 Decorators with arguments/decorators.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | ### decorators with function arguments ### 5 | 6 | def greetings(func): 7 | def wrapper(*args, **kwargs): 8 | print("Welcome!") 9 | func(*args, **kwargs) 10 | print("Bye!") 11 | return args[0] 12 | return wrapper 13 | 14 | 15 | @greetings 16 | def hello(name: str): 17 | print(f"Hello {name}") 18 | 19 | 20 | # name = hello("Josh") 21 | # print() 22 | # print(name) 23 | 24 | 25 | def timing(func): 26 | def wrapper(*args, **kwargs): 27 | start_time = time.perf_counter() 28 | value = func(*args, **kwargs) 29 | stop_time = time.perf_counter() 30 | time_elapsed = stop_time - start_time 31 | print(f"It took {time_elapsed} seconds to run the function.") 32 | return value 33 | return wrapper 34 | 35 | @timing 36 | def squares(stop_number): 37 | return [x**2 for x in range(stop_number)] 38 | 39 | 40 | # l_squares = squares(1000000) 41 | # print(l_squares[:10]) 42 | 43 | 44 | ### decorators with arguments ### 45 | 46 | def wait(seconds: int): 47 | def wait_decorator(func): 48 | def wrapper(*args, **kwargs): 49 | print(f"Wait for the magic to happen in {seconds} seconds...") 50 | time.sleep(seconds) 51 | func(*args, **kwargs) 52 | return wrapper 53 | return wait_decorator 54 | 55 | 56 | @wait(3) 57 | @greetings 58 | def hello(name: str): 59 | print(f"Hello {name}") 60 | 61 | hello("Anna") 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/27 Decorators with arguments/exercise.py: -------------------------------------------------------------------------------- 1 | # Exercise 1 2 | def check_int(func): 3 | def wrapper(*args, **kwargs): 4 | if not isinstance(args[0], int): 5 | raise TypeError(f"The argument isn't an int. '{type(args[0])}' passed instead.") 6 | value = func(*args, **kwargs) 7 | return value 8 | return wrapper 9 | 10 | 11 | @check_int 12 | def create_squares_list(stop: int): 13 | return [n**2 for n in range(stop)] 14 | 15 | 16 | # Exercise 2 17 | def filter_divisible_by(divisor: int): 18 | def filter_divisible_by_decorator(func): 19 | def wrapper(*args, **kwargs): 20 | values = func(*args, **kwargs) 21 | filtered_values = list(filter(lambda x: x % divisor == 0, values)) 22 | return filtered_values 23 | return wrapper 24 | return filter_divisible_by_decorator 25 | 26 | 27 | @filter_divisible_by(2) 28 | def create_squares_list(stop: int): 29 | return [n**2 for n in range(stop)] 30 | 31 | 32 | print(create_squares_list(10)) 33 | 34 | -------------------------------------------------------------------------------- /src/28 Decorating classes/decorators.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | def wait(seconds: int): 5 | def wait_decorator(func): 6 | def wrapper(*args, **kwargs): 7 | print(f"Wait for the magic to happen in {seconds} seconds...") 8 | time.sleep(seconds) 9 | func(*args, **kwargs) 10 | return wrapper 11 | return wait_decorator 12 | 13 | 14 | def greet(user): 15 | def wrapper(*args, **kwargs): 16 | value = user(*args, **kwargs) 17 | print(f"Hello {value.name}") 18 | return value 19 | return wrapper 20 | 21 | 22 | @greet 23 | class User: 24 | 25 | def __init__(self, name: str) -> None: 26 | self.name = name 27 | 28 | @wait(seconds=3) 29 | def login(self) -> None: 30 | print(f"You've been logged in {self.name}") 31 | 32 | 33 | 34 | user = User("Josh") 35 | print(user.name) 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/28 Decorating classes/exercise.py: -------------------------------------------------------------------------------- 1 | def add_role(role: str): 2 | def add_role_decorator(user): 3 | def wrapper(*args, **kwargs): 4 | new_user = user(*args, **kwargs) 5 | new_user.role = role 6 | return new_user 7 | return wrapper 8 | return add_role_decorator 9 | 10 | 11 | @add_role("employee") 12 | class User: 13 | 14 | def __init__(self, name: str) -> None: 15 | self.name = name 16 | 17 | def login(self) -> None: 18 | print(f"You've been logged in {self.name}") 19 | 20 | 21 | user = User("Josh") 22 | print(user.role) 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/29 Threading and multiprocessing/Threading and Multiprocessing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/29 Threading and multiprocessing/Threading and Multiprocessing.pdf -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_1" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_2" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_3.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_3" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_4.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_4" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_5.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_5" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_6.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_6" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_7.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_7" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/dummy_8.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dummy_8" 3 | } -------------------------------------------------------------------------------- /src/30 Threading basics/exercise.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import json 3 | from typing import Dict, List 4 | from pathlib import Path 5 | 6 | 7 | NUM_THREADS = 4 8 | NUM_FILES = 8 9 | 10 | 11 | def _load_json(load_path: Path) -> Dict: 12 | with open(load_path, "r") as file: 13 | return json.load(file) 14 | 15 | 16 | def load_json_files(load_paths: List[Path], loaded_data: List) -> None: 17 | for load_path in load_paths: 18 | loaded_data.append(_load_json(load_path)) 19 | 20 | 21 | def generate_files_to_load_for_threads(common_root: str, 22 | num_threads: int, 23 | num_files: int) -> List[List[Path]]: 24 | num_files_for_thread = int(num_files / num_threads) 25 | flattened_files_for_threads = [Path(f"{common_root}{i+1}.json") for i in range(num_files)] 26 | files_for_threads = [flattened_files_for_threads[i:i+num_files_for_thread] 27 | for i in range(0, num_files, num_files_for_thread)] 28 | return files_for_threads 29 | 30 | 31 | if __name__ == "__main__": 32 | 33 | files_for_threads = generate_files_to_load_for_threads("dummy_", NUM_THREADS, NUM_FILES) 34 | 35 | threads = [] 36 | loaded_data = [] 37 | 38 | for files_for_thread in files_for_threads: 39 | thread = threading.Thread(target=load_json_files, 40 | args=(files_for_thread, loaded_data)) 41 | json_data = thread.start() 42 | threads.append(thread) 43 | 44 | for thread in threads: 45 | thread.join() 46 | 47 | for data in loaded_data: 48 | print(data) 49 | 50 | -------------------------------------------------------------------------------- /src/30 Threading basics/multithreading.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | 4 | def say_hello(person: str): 5 | print(f"Hello {person} from {threading.current_thread().name}!") 6 | 7 | 8 | def say_hi(person: str): 9 | print(f"Hi {person} from {threading.current_thread().name}!") 10 | 11 | 12 | if __name__ == "__main__": 13 | 14 | print(f"I'm in the main thread: {threading.current_thread().name}") 15 | 16 | # # create a couple of threads 17 | # thread_1 = threading.Thread(target=say_hello, name="thread_1", args=("John",)) 18 | # thread_2 = threading.Thread(target=say_hi, name="thread_2", args=("Anna",)) 19 | # 20 | # # start threads 21 | # thread_1.start() 22 | # thread_2.start() 23 | # 24 | # # wait until threads have executed instructions 25 | # thread_1.join() 26 | # thread_2.join() 27 | 28 | threads = [] 29 | persons = ["Josh", "Anna", "John", "Valerio"] 30 | for i, person in enumerate(persons): 31 | thread = threading.Thread(target=say_hello, name=f"thread-{i+1}", args=(person,)) 32 | threads.append(thread) 33 | 34 | for thread in threads: 35 | thread.start() 36 | 37 | -------------------------------------------------------------------------------- /src/31 Daemon and non-daemon threads/daemons.py: -------------------------------------------------------------------------------- 1 | # Non-daemon: Blocks main programme -> all non-daemon threads should complete 2 | # their work before programme ends 3 | 4 | # Daemon: Background thread. Programme can exit even if thread hasn't finished 5 | 6 | import time 7 | import threading 8 | 9 | def daemon(): 10 | print("In daemon") 11 | time.sleep(5) 12 | print("Out of daemon") 13 | 14 | 15 | def non_daemon(): 16 | print("In non-daemon") 17 | time.sleep(2) 18 | print("Out of non-daemon") 19 | 20 | 21 | if __name__ == "__main__": 22 | d = threading.Thread(target=daemon) 23 | d.setDaemon(True) 24 | nd = threading.Thread(target=non_daemon) 25 | 26 | d.start() 27 | nd.start() 28 | 29 | d.join(timeout=3) 30 | 31 | -------------------------------------------------------------------------------- /src/32 Multiprocessing basics/exercise.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import json 3 | from pathlib import Path 4 | from typing import Dict 5 | 6 | 7 | def save_to_json(data: Dict, save_path: Path) -> None: 8 | with open(save_path, "w") as file: 9 | return json.dump(data, file) 10 | 11 | 12 | if __name__ == "__main__": 13 | 14 | data = {"name": "Frodo", "last_name": "Baggins"} 15 | 16 | process_1 = multiprocessing.Process(target=save_to_json, 17 | args=(data, Path("frodo_1.json")), 18 | daemon=True) 19 | process_2 = multiprocessing.Process(target=save_to_json, 20 | args=(data, Path("frodo_2.json")), 21 | daemon=True) 22 | 23 | process_1.start() 24 | process_2.start() 25 | 26 | process_1.join() 27 | process_2.join() 28 | -------------------------------------------------------------------------------- /src/32 Multiprocessing basics/multiprocess.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import time 3 | 4 | def say_hello(person: str): 5 | print(f"Hello {person} from {multiprocessing.current_process().name}") 6 | 7 | 8 | def say_hi(person: str): 9 | time.sleep(2) 10 | print(f"Hi {person} from {multiprocessing.current_process().name}") 11 | 12 | 13 | if __name__ == "__main__": 14 | process_1 = multiprocessing.Process(target=say_hello, args=("John",), name="process_1") 15 | process_2 = multiprocessing.Process(target=say_hi, args=("Anna",), name="process_2", daemon=True) 16 | 17 | process_1.start() 18 | process_2.start() 19 | 20 | process_2.join() -------------------------------------------------------------------------------- /src/33 Multiprocessing with the Pool class/exercise.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | import json 3 | from pathlib import Path 4 | from typing import Dict 5 | 6 | 7 | def save_to_json(data: Dict, save_path: Path) -> None: 8 | with open(save_path, "w") as file: 9 | return json.dump(data, file) 10 | 11 | 12 | if __name__ == "__main__": 13 | 14 | frodo = {"name": "Frodo", "last_name": "Baggins"} 15 | data = [(frodo, Path("frodo_1.json")), (frodo, Path("frodo_2.json"))] 16 | pool = multiprocessing.Pool(2) 17 | pool.starmap(save_to_json, data) 18 | pool.close() -------------------------------------------------------------------------------- /src/33 Multiprocessing with the Pool class/pool.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | 3 | 4 | def say_hello(person: str): 5 | print(f"Hello {person} from {multiprocessing.current_process().name}") 6 | 7 | 8 | if __name__ == "__main__": 9 | # processes = [] 10 | # persons = ["Josh", "Anna", "Valerio"] 11 | # for i, person in enumerate(persons): 12 | # process = multiprocessing.Process(target=say_hello, 13 | # args=(person,), 14 | # name=f"process-{i}") 15 | # processes.append(process) 16 | # 17 | # for process in processes: 18 | # process.start() 19 | 20 | persons = ["Josh", "Anna", "Valerio"] 21 | pool = multiprocessing.Pool(3) 22 | pool.map(say_hello, persons) 23 | pool.close() 24 | -------------------------------------------------------------------------------- /src/35 Data pipeline design/Data Pipeline Design.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/35 Data pipeline design/Data Pipeline Design.pdf -------------------------------------------------------------------------------- /src/project/errors.py: -------------------------------------------------------------------------------- 1 | class CurrencyError(Exception): 2 | 3 | def __init__(self, currency: str, message: str) -> None: 4 | self.currency = currency 5 | self.message = message 6 | 7 | 8 | class DifferentNumberOfArgumentsError(Exception): 9 | 10 | def __init__(self, message: str) -> None: 11 | self.message = message -------------------------------------------------------------------------------- /src/project/loading/loaderiterator.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from typing import List, Dict, Optional 3 | 4 | from src.project.loading.serialization import Serializer 5 | 6 | 7 | class LoaderIterator: 8 | """Iterator that loads data from multiple files in batches.""" 9 | 10 | def __init__(self, 11 | serializer: Serializer, 12 | num_files_per_iteration: int, 13 | load_paths: Optional[List[Path]] = None) -> None: 14 | self.serializer = serializer 15 | self.num_files_per_iteration = num_files_per_iteration 16 | self._load_paths = load_paths 17 | self._current_iteration = None 18 | 19 | @property 20 | def load_paths(self) -> Optional[List[Path]]: 21 | return self._load_paths 22 | 23 | @load_paths.setter 24 | def load_paths(self, load_paths: List[Path]) -> None: 25 | self._load_paths = load_paths 26 | 27 | def __iter__(self): 28 | self._current_iteration = 0 29 | return self 30 | 31 | def __next__(self) -> List[Dict]: 32 | if self._did_load_all_batches(): 33 | raise StopIteration 34 | data_batch = self._load_data_batch() 35 | self._current_iteration += 1 36 | return data_batch 37 | 38 | def _did_load_all_batches(self) -> bool: 39 | if self._current_iteration >= len(self._load_paths) / self.num_files_per_iteration: 40 | return True 41 | return False 42 | 43 | def _load_data_batch(self) -> List[Dict]: 44 | start_index = self._current_iteration * self.num_files_per_iteration 45 | stop_index = start_index + self.num_files_per_iteration 46 | return [self.serializer.load(load_path) for load_path in 47 | self._load_paths[start_index:stop_index] if load_path.exists()] 48 | -------------------------------------------------------------------------------- /src/project/loading/serialization.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import json 3 | from abc import ABC, abstractmethod 4 | from typing import Any 5 | from pathlib import Path 6 | 7 | import yaml 8 | 9 | 10 | class Serializer(ABC): 11 | 12 | @abstractmethod 13 | def dump(self, obj: Any, save_path: Path) -> None: 14 | pass 15 | 16 | @abstractmethod 17 | def load(self, load_path: Path) -> Any: 18 | pass 19 | 20 | 21 | class JsonSerializer(Serializer): 22 | 23 | def __init__(self, 24 | sort_keys: bool = True, 25 | indent: int = 4): 26 | self.sort_keys = sort_keys 27 | self.indent = indent 28 | 29 | def dump(self, obj: Any, save_path: Path) -> None: 30 | with open(save_path, "w") as file: 31 | json.dump(obj, file, sort_keys=self.sort_keys, indent=self.indent) 32 | 33 | def load(self, load_path: Path) -> Any: 34 | with open(load_path, "r") as file: 35 | return json.load(file) 36 | 37 | 38 | class YamlSerializer(Serializer): 39 | 40 | def __init__(self, default_flow_style: bool = False) -> None: 41 | self.default_flow_style = default_flow_style 42 | 43 | def dump(self, obj: Any, save_path: Path) -> None: 44 | with open(save_path, "w") as file: 45 | yaml.dump(obj, file, default_flow_style=self.default_flow_style) 46 | 47 | def load(self, load_path: Path) -> Any: 48 | with open(load_path, "r") as file: 49 | return yaml.safe_load(file) 50 | -------------------------------------------------------------------------------- /src/project/main.py: -------------------------------------------------------------------------------- 1 | import math 2 | import sqlite3 3 | import os 4 | from pathlib import Path 5 | 6 | from src.project.datapipeline import create_hardcoded_data_pipeline 7 | from src.project.storing.createdb import create_db 8 | from src.project.utils import create_file_paths_from_dir, nest_list 9 | from src.project.threadeddatapipeline import ThreadedDataPipeline 10 | 11 | 12 | NUM_THREADS = 10 13 | 14 | 15 | def main(): 16 | create_db("test.db") 17 | 18 | # create necessary resources 19 | paths = create_file_paths_from_dir(Path("samplefiles")) 20 | nested_list_length = math.ceil(len(paths) / NUM_THREADS) 21 | nested_paths = nest_list(paths, nested_list_length) 22 | data_pipelines = [create_hardcoded_data_pipeline() for i in range(NUM_THREADS)] 23 | 24 | # run pipelines in multiple threads 25 | threads = [] 26 | for data_pipeline, paths in zip(data_pipelines, nested_paths): 27 | threads.append(ThreadedDataPipeline(data_pipeline, paths)) 28 | for thread in threads: 29 | thread.start() 30 | for thread in threads: 31 | thread.join() 32 | 33 | # fetch db entries and print them 34 | connection = sqlite3.connect("test.db") 35 | cursor = connection.cursor() 36 | cursor.execute("SELECT NAME, CURRENCY, PRICE FROM PRODUCT") 37 | products = cursor.fetchall() 38 | print(products) 39 | print(len(products)) 40 | 41 | # remove db 42 | os.remove("test.db") 43 | 44 | 45 | if __name__ == "__main__": 46 | main() -------------------------------------------------------------------------------- /src/project/product.py: -------------------------------------------------------------------------------- 1 | from typing import Tuple 2 | 3 | from pydantic import BaseModel, validator 4 | 5 | from src.project.errors import CurrencyError 6 | 7 | 8 | supported_currencies = ["dollar", "euro"] 9 | 10 | 11 | class Product(BaseModel): 12 | """This class represent a product entry.""" 13 | 14 | name: str 15 | currency: str 16 | price: float 17 | 18 | @validator("currency") 19 | @classmethod 20 | def check_currency_is_supported(cls, value: str, values: dict) -> str: 21 | if value not in supported_currencies: 22 | msg = f"Currency '{value}' isn't supported in product '{values['name']}'." 23 | raise CurrencyError(value, msg) 24 | return value 25 | 26 | def to_tuple(self) -> Tuple: 27 | """Convert Product object to a tuple of the type: 28 | (name, currency, price). 29 | """ 30 | return (self.name, self.currency, self.price) 31 | -------------------------------------------------------------------------------- /src/project/samplefiles/1.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_1", 4 | "price": 962 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/10.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_10", 4 | "price": 616 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/100.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_100", 4 | "price": 765 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/101.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_101", 4 | "price": 790 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/102.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_102", 4 | "price": 468 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/103.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_103", 4 | "price": 685 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/104.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_104", 4 | "price": 981 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/105.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_105", 4 | "price": 864 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/106.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_106", 4 | "price": 636 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/107.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_107", 4 | "price": 68 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/108.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_108", 4 | "price": 739 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/109.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_109", 4 | "price": 358 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/11.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_11", 4 | "price": 996 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/110.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_110", 4 | "price": 452 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/111.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_111", 4 | "price": 559 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/112.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_112", 4 | "price": 21 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/113.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_113", 4 | "price": 36 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/114.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_114", 4 | "price": 485 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/115.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_115", 4 | "price": 941 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/116.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_116", 4 | "price": 513 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/117.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_117", 4 | "price": 950 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/118.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_118", 4 | "price": 993 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/119.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_119", 4 | "price": 196 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/12.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_12", 4 | "price": 925 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/120.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_120", 4 | "price": 505 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/121.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_121", 4 | "price": 749 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/122.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_122", 4 | "price": 56 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/123.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_123", 4 | "price": 153 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/124.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_124", 4 | "price": 584 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/125.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_125", 4 | "price": 252 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/126.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_126", 4 | "price": 480 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/127.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_127", 4 | "price": 867 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/128.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_128", 4 | "price": 374 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/129.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_129", 4 | "price": 907 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/13.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_13", 4 | "price": 613 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/130.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_130", 4 | "price": 492 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/131.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_131", 4 | "price": 978 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/132.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_132", 4 | "price": 846 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/133.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_133", 4 | "price": 598 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/134.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_134", 4 | "price": 841 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/135.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_135", 4 | "price": 313 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/136.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_136", 4 | "price": 964 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/137.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_137", 4 | "price": 273 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/138.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_138", 4 | "price": 423 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/139.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_139", 4 | "price": 497 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/14.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_14", 4 | "price": 468 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/140.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_140", 4 | "price": 403 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/141.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_141", 4 | "price": 122 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/142.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_142", 4 | "price": 286 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/143.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_143", 4 | "price": 124 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/144.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_144", 4 | "price": 742 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/145.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_145", 4 | "price": 765 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/146.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_146", 4 | "price": 173 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/147.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_147", 4 | "price": 817 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/148.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_148", 4 | "price": 431 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/149.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_149", 4 | "price": 275 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/15.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_15", 4 | "price": 696 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/150.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_150", 4 | "price": 978 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/151.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_151", 4 | "price": 305 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/152.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_152", 4 | "price": 882 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/153.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_153", 4 | "price": 376 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/154.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_154", 4 | "price": 959 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/155.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_155", 4 | "price": 389 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/156.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_156", 4 | "price": 735 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/157.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_157", 4 | "price": 946 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/158.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_158", 4 | "price": 730 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/159.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_159", 4 | "price": 251 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/16.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_16", 4 | "price": 625 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/160.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_160", 4 | "price": 677 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/161.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_161", 4 | "price": 243 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/162.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_162", 4 | "price": 511 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/163.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_163", 4 | "price": 125 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/164.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_164", 4 | "price": 380 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/165.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_165", 4 | "price": 350 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/166.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_166", 4 | "price": 262 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/167.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_167", 4 | "price": 838 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/168.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_168", 4 | "price": 159 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/169.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_169", 4 | "price": 258 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/17.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_17", 4 | "price": 73 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/170.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_170", 4 | "price": 217 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/171.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_171", 4 | "price": 981 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/172.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_172", 4 | "price": 215 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/173.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_173", 4 | "price": 713 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/174.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_174", 4 | "price": 367 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/175.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_175", 4 | "price": 507 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/176.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_176", 4 | "price": 304 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/177.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_177", 4 | "price": 981 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/178.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_178", 4 | "price": 868 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/179.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_179", 4 | "price": 486 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/18.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_18", 4 | "price": 212 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/180.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_180", 4 | "price": 78 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/181.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_181", 4 | "price": 885 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/182.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_182", 4 | "price": 36 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/183.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_183", 4 | "price": 700 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/184.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_184", 4 | "price": 664 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/185.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_185", 4 | "price": 917 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/186.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_186", 4 | "price": 932 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/187.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_187", 4 | "price": 533 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/188.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_188", 4 | "price": 765 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/189.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_189", 4 | "price": 842 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/19.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_19", 4 | "price": 832 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/190.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_190", 4 | "price": 807 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/191.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_191", 4 | "price": 438 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/192.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_192", 4 | "price": 104 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/193.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_193", 4 | "price": 932 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/194.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_194", 4 | "price": 955 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/195.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_195", 4 | "price": 730 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/196.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_196", 4 | "price": 246 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/197.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_197", 4 | "price": 396 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/198.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_198", 4 | "price": 296 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/199.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_199", 4 | "price": 831 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/2.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_2", 4 | "price": 903 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/20.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_20", 4 | "price": 876 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/200.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_200", 4 | "price": 90 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/201.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_201", 4 | "price": 971 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/202.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_202", 4 | "price": 664 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/203.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_203", 4 | "price": 743 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/204.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_204", 4 | "price": 141 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/205.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_205", 4 | "price": 543 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/206.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_206", 4 | "price": 763 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/207.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_207", 4 | "price": 888 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/208.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_208", 4 | "price": 110 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/209.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_209", 4 | "price": 33 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/21.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_21", 4 | "price": 154 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/210.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_210", 4 | "price": 714 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/211.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_211", 4 | "price": 835 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/212.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_212", 4 | "price": 75 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/213.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_213", 4 | "price": 38 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/214.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_214", 4 | "price": 596 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/215.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_215", 4 | "price": 354 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/216.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_216", 4 | "price": 788 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/217.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_217", 4 | "price": 417 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/218.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_218", 4 | "price": 243 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/219.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_219", 4 | "price": 645 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/22.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_22", 4 | "price": 37 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/220.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_220", 4 | "price": 387 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/221.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_221", 4 | "price": 790 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/222.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_222", 4 | "price": 780 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/223.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_223", 4 | "price": 873 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/224.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_224", 4 | "price": 359 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/225.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_225", 4 | "price": 42 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/226.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_226", 4 | "price": 905 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/227.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_227", 4 | "price": 527 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/228.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_228", 4 | "price": 877 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/229.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_229", 4 | "price": 738 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/23.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_23", 4 | "price": 39 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/230.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_230", 4 | "price": 804 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/231.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_231", 4 | "price": 694 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/232.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_232", 4 | "price": 574 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/233.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_233", 4 | "price": 857 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/234.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_234", 4 | "price": 845 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/235.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_235", 4 | "price": 491 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/236.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_236", 4 | "price": 492 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/237.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_237", 4 | "price": 374 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/238.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_238", 4 | "price": 67 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/239.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_239", 4 | "price": 453 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/24.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_24", 4 | "price": 320 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/240.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_240", 4 | "price": 310 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/241.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_241", 4 | "price": 707 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/242.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_242", 4 | "price": 117 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/243.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_243", 4 | "price": 771 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/244.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_244", 4 | "price": 108 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/245.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_245", 4 | "price": 598 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/246.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_246", 4 | "price": 642 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/247.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_247", 4 | "price": 562 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/248.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_248", 4 | "price": 541 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/249.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_249", 4 | "price": 37 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/25.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_25", 4 | "price": 566 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/250.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_250", 4 | "price": 98 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/251.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_251", 4 | "price": 729 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/252.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_252", 4 | "price": 57 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/253.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_253", 4 | "price": 900 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/254.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_254", 4 | "price": 884 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/255.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_255", 4 | "price": 492 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/256.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_256", 4 | "price": 351 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/257.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_257", 4 | "price": 11 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/258.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_258", 4 | "price": 531 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/259.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_259", 4 | "price": 358 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/26.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_26", 4 | "price": 857 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/260.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_260", 4 | "price": 210 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/261.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_261", 4 | "price": 281 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/262.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_262", 4 | "price": 223 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/263.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_263", 4 | "price": 37 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/264.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_264", 4 | "price": 897 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/265.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_265", 4 | "price": 987 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/266.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_266", 4 | "price": 210 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/267.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_267", 4 | "price": 331 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/268.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_268", 4 | "price": 117 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/269.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_269", 4 | "price": 530 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/27.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_27", 4 | "price": 659 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/270.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_270", 4 | "price": 628 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/271.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_271", 4 | "price": 554 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/272.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_272", 4 | "price": 823 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/273.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_273", 4 | "price": 339 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/274.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_274", 4 | "price": 95 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/275.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_275", 4 | "price": 914 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/276.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_276", 4 | "price": 357 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/277.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_277", 4 | "price": 685 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/278.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_278", 4 | "price": 578 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/279.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_279", 4 | "price": 380 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/28.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_28", 4 | "price": 220 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/280.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_280", 4 | "price": 374 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/281.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_281", 4 | "price": 801 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/282.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_282", 4 | "price": 674 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/283.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_283", 4 | "price": 604 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/284.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_284", 4 | "price": 249 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/285.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_285", 4 | "price": 870 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/286.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_286", 4 | "price": 533 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/287.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_287", 4 | "price": 222 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/288.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_288", 4 | "price": 195 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/289.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_289", 4 | "price": 867 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/29.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_29", 4 | "price": 686 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/290.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_290", 4 | "price": 743 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/291.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_291", 4 | "price": 703 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/292.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_292", 4 | "price": 767 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/293.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_293", 4 | "price": 251 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/294.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_294", 4 | "price": 75 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/295.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_295", 4 | "price": 304 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/296.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_296", 4 | "price": 188 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/297.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_297", 4 | "price": 569 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/298.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_298", 4 | "price": 46 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/299.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_299", 4 | "price": 126 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/3.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_3", 4 | "price": 685 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/30.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_30", 4 | "price": 714 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/300.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_300", 4 | "price": 420 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/301.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_301", 4 | "price": 89 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/302.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_302", 4 | "price": 488 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/303.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_303", 4 | "price": 767 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/304.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_304", 4 | "price": 891 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/305.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_305", 4 | "price": 938 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/306.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_306", 4 | "price": 586 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/307.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_307", 4 | "price": 225 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/308.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_308", 4 | "price": 646 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/309.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_309", 4 | "price": 221 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/31.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_31", 4 | "price": 926 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/310.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_310", 4 | "price": 378 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/311.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_311", 4 | "price": 875 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/312.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_312", 4 | "price": 873 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/313.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_313", 4 | "price": 714 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/314.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_314", 4 | "price": 875 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/315.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_315", 4 | "price": 385 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/316.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_316", 4 | "price": 496 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/317.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_317", 4 | "price": 317 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/318.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_318", 4 | "price": 198 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/319.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_319", 4 | "price": 278 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/32.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_32", 4 | "price": 159 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/320.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_320", 4 | "price": 840 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/321.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_321", 4 | "price": 368 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/322.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_322", 4 | "price": 962 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/323.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_323", 4 | "price": 998 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/324.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_324", 4 | "price": 501 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/325.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_325", 4 | "price": 864 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/326.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_326", 4 | "price": 469 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/327.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_327", 4 | "price": 99 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/328.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_328", 4 | "price": 374 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/329.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_329", 4 | "price": 831 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/33.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_33", 4 | "price": 266 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/330.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_330", 4 | "price": 745 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/331.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_331", 4 | "price": 338 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/332.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_332", 4 | "price": 893 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/333.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_333", 4 | "price": 647 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/334.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_334", 4 | "price": 754 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/335.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_335", 4 | "price": 626 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/336.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_336", 4 | "price": 712 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/337.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_337", 4 | "price": 625 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/338.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_338", 4 | "price": 102 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/339.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_339", 4 | "price": 763 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/34.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_34", 4 | "price": 469 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/340.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_340", 4 | "price": 912 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/341.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_341", 4 | "price": 185 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/342.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_342", 4 | "price": 221 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/343.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_343", 4 | "price": 719 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/344.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_344", 4 | "price": 942 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/345.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_345", 4 | "price": 540 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/346.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_346", 4 | "price": 557 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/347.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_347", 4 | "price": 853 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/348.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_348", 4 | "price": 593 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/349.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_349", 4 | "price": 372 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/35.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_35", 4 | "price": 554 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/350.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_350", 4 | "price": 270 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/351.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_351", 4 | "price": 382 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/352.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_352", 4 | "price": 851 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/353.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_353", 4 | "price": 381 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/354.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_354", 4 | "price": 974 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/355.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_355", 4 | "price": 67 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/356.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_356", 4 | "price": 390 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/357.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_357", 4 | "price": 461 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/358.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_358", 4 | "price": 220 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/359.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_359", 4 | "price": 123 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/36.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_36", 4 | "price": 421 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/360.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_360", 4 | "price": 469 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/361.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_361", 4 | "price": 967 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/362.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_362", 4 | "price": 240 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/363.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_363", 4 | "price": 426 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/364.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_364", 4 | "price": 485 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/365.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_365", 4 | "price": 945 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/366.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_366", 4 | "price": 655 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/367.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_367", 4 | "price": 213 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/368.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_368", 4 | "price": 351 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/369.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_369", 4 | "price": 70 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/37.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_37", 4 | "price": 933 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/370.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_370", 4 | "price": 889 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/371.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_371", 4 | "price": 786 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/372.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_372", 4 | "price": 863 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/373.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_373", 4 | "price": 199 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/374.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_374", 4 | "price": 943 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/375.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_375", 4 | "price": 645 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/376.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_376", 4 | "price": 501 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/377.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_377", 4 | "price": 193 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/378.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_378", 4 | "price": 907 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/379.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_379", 4 | "price": 83 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/38.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_38", 4 | "price": 733 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/380.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_380", 4 | "price": 163 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/381.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_381", 4 | "price": 868 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/382.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_382", 4 | "price": 609 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/383.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_383", 4 | "price": 336 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/384.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_384", 4 | "price": 69 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/385.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_385", 4 | "price": 533 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/386.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_386", 4 | "price": 162 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/387.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_387", 4 | "price": 977 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/388.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_388", 4 | "price": 286 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/389.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_389", 4 | "price": 245 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/39.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_39", 4 | "price": 526 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/390.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_390", 4 | "price": 902 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/391.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_391", 4 | "price": 856 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/392.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_392", 4 | "price": 78 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/393.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_393", 4 | "price": 501 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/394.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_394", 4 | "price": 319 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/395.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_395", 4 | "price": 80 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/396.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_396", 4 | "price": 182 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/397.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_397", 4 | "price": 209 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/398.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_398", 4 | "price": 199 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/399.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_399", 4 | "price": 801 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/4.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_4", 4 | "price": 522 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/40.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_40", 4 | "price": 589 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/400.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_400", 4 | "price": 504 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/401.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_401", 4 | "price": 548 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/402.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_402", 4 | "price": 913 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/403.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_403", 4 | "price": 323 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/404.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_404", 4 | "price": 188 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/405.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_405", 4 | "price": 454 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/406.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_406", 4 | "price": 811 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/407.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_407", 4 | "price": 370 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/408.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_408", 4 | "price": 660 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/409.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_409", 4 | "price": 204 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/41.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_41", 4 | "price": 200 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/410.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_410", 4 | "price": 880 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/411.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_411", 4 | "price": 457 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/412.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_412", 4 | "price": 770 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/413.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_413", 4 | "price": 162 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/414.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_414", 4 | "price": 642 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/415.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_415", 4 | "price": 325 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/416.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_416", 4 | "price": 757 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/417.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_417", 4 | "price": 122 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/418.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_418", 4 | "price": 506 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/419.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_419", 4 | "price": 377 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/42.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_42", 4 | "price": 767 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/420.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_420", 4 | "price": 321 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/421.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_421", 4 | "price": 851 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/422.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_422", 4 | "price": 652 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/423.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_423", 4 | "price": 406 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/424.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_424", 4 | "price": 241 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/425.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_425", 4 | "price": 961 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/426.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_426", 4 | "price": 60 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/427.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_427", 4 | "price": 973 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/428.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_428", 4 | "price": 474 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/429.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_429", 4 | "price": 609 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/43.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_43", 4 | "price": 228 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/430.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_430", 4 | "price": 776 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/431.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_431", 4 | "price": 439 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/432.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_432", 4 | "price": 719 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/433.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_433", 4 | "price": 467 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/434.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_434", 4 | "price": 873 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/435.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_435", 4 | "price": 271 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/436.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_436", 4 | "price": 336 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/437.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_437", 4 | "price": 661 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/438.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_438", 4 | "price": 125 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/439.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_439", 4 | "price": 868 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/44.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_44", 4 | "price": 729 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/440.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_440", 4 | "price": 192 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/441.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_441", 4 | "price": 22 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/442.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_442", 4 | "price": 101 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/443.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_443", 4 | "price": 389 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/444.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_444", 4 | "price": 952 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/445.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_445", 4 | "price": 832 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/446.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_446", 4 | "price": 827 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/447.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_447", 4 | "price": 981 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/448.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_448", 4 | "price": 132 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/449.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_449", 4 | "price": 196 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/45.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_45", 4 | "price": 349 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/450.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_450", 4 | "price": 934 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/451.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_451", 4 | "price": 668 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/452.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_452", 4 | "price": 723 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/453.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_453", 4 | "price": 385 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/454.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_454", 4 | "price": 587 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/455.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_455", 4 | "price": 609 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/456.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_456", 4 | "price": 803 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/457.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_457", 4 | "price": 621 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/458.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_458", 4 | "price": 343 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/459.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_459", 4 | "price": 495 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/46.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_46", 4 | "price": 839 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/460.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_460", 4 | "price": 156 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/461.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_461", 4 | "price": 822 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/462.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_462", 4 | "price": 689 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/463.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_463", 4 | "price": 804 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/464.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_464", 4 | "price": 733 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/465.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_465", 4 | "price": 601 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/466.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_466", 4 | "price": 811 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/467.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_467", 4 | "price": 530 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/468.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_468", 4 | "price": 614 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/469.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_469", 4 | "price": 907 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/47.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_47", 4 | "price": 262 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/470.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_470", 4 | "price": 874 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/471.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_471", 4 | "price": 893 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/472.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_472", 4 | "price": 286 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/473.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_473", 4 | "price": 104 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/474.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_474", 4 | "price": 274 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/475.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_475", 4 | "price": 109 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/476.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_476", 4 | "price": 864 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/477.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_477", 4 | "price": 358 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/478.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_478", 4 | "price": 357 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/479.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_479", 4 | "price": 338 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/48.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_48", 4 | "price": 74 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/480.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_480", 4 | "price": 398 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/481.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_481", 4 | "price": 996 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/482.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_482", 4 | "price": 981 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/483.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_483", 4 | "price": 422 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/484.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_484", 4 | "price": 236 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/485.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_485", 4 | "price": 731 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/486.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_486", 4 | "price": 792 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/487.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_487", 4 | "price": 33 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/488.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_488", 4 | "price": 491 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/489.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_489", 4 | "price": 288 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/49.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_49", 4 | "price": 118 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/490.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_490", 4 | "price": 950 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/491.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_491", 4 | "price": 739 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/492.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_492", 4 | "price": 393 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/493.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_493", 4 | "price": 632 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/494.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_494", 4 | "price": 617 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/495.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_495", 4 | "price": 186 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/496.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_496", 4 | "price": 988 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/497.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_497", 4 | "price": 620 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/498.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_498", 4 | "price": 957 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/499.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_499", 4 | "price": 309 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/5.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_5", 4 | "price": 860 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/50.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_50", 4 | "price": 555 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/500.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_500", 4 | "price": 196 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/501.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_501", 4 | "price": 432 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/51.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_51", 4 | "price": 902 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/52.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_52", 4 | "price": 806 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/53.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_53", 4 | "price": 957 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/54.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_54", 4 | "price": 368 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/55.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_55", 4 | "price": 217 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/56.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_56", 4 | "price": 715 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/57.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_57", 4 | "price": 577 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/58.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_58", 4 | "price": 38 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/59.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_59", 4 | "price": 615 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/6.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_6", 4 | "price": 512 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/60.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_60", 4 | "price": 167 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/61.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_61", 4 | "price": 20 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/62.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_62", 4 | "price": 176 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/63.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_63", 4 | "price": 321 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/64.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_64", 4 | "price": 18 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/65.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_65", 4 | "price": 929 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/66.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_66", 4 | "price": 572 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/67.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_67", 4 | "price": 842 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/68.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_68", 4 | "price": 832 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/69.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_69", 4 | "price": 307 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/7.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_7", 4 | "price": 847 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/70.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_70", 4 | "price": 452 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/71.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_71", 4 | "price": 175 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/72.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_72", 4 | "price": 432 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/73.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_73", 4 | "price": 815 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/74.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_74", 4 | "price": 644 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/75.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_75", 4 | "price": 386 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/76.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_76", 4 | "price": 604 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/77.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_77", 4 | "price": 177 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/78.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_78", 4 | "price": 656 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/79.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_79", 4 | "price": 933 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/8.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_8", 4 | "price": 412 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/80.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_80", 4 | "price": 678 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/81.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_81", 4 | "price": 146 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/82.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_82", 4 | "price": 85 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/83.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_83", 4 | "price": 949 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/84.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_84", 4 | "price": 898 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/85.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_85", 4 | "price": 618 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/86.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_86", 4 | "price": 51 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/87.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_87", 4 | "price": 944 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/88.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_88", 4 | "price": 447 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/89.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_89", 4 | "price": 783 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/9.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_9", 4 | "price": 891 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/90.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_90", 4 | "price": 500 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/91.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_91", 4 | "price": 112 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/92.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_92", 4 | "price": 767 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/93.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_93", 4 | "price": 128 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/94.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_94", 4 | "price": 235 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/95.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_95", 4 | "price": 344 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/96.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_96", 4 | "price": 941 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/97.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_97", 4 | "price": 526 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/98.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "euro", 3 | "name": "product_98", 4 | "price": 847 5 | } -------------------------------------------------------------------------------- /src/project/samplefiles/99.json: -------------------------------------------------------------------------------- 1 | { 2 | "currency": "dollar", 3 | "name": "product_99", 4 | "price": 826 5 | } -------------------------------------------------------------------------------- /src/project/storing/createdb.py: -------------------------------------------------------------------------------- 1 | """This is a simple script to generate a dummy sqlite database with single 2 | table called 'products'. 3 | """ 4 | 5 | import sqlite3 6 | 7 | 8 | def create_db(db_path: str) -> None: 9 | """Create an sqlite db with a single table, called 'product'.""" 10 | connection = sqlite3.connect(db_path) 11 | print(f"Created database successfully and stored at '{db_path}'") 12 | connection.execute( 13 | ''' 14 | CREATE TABLE PRODUCT 15 | (ID INTEGER PRIMARY KEY AUTOINCREMENT, 16 | NAME CHAR(50) NOT NULL, 17 | CURRENCY CHAR(20) NOT NULL, 18 | PRICE REAL NOT NULL) 19 | ''' 20 | ) 21 | print("'Product' table created successfully") 22 | 23 | 24 | if __name__ == "__main__": 25 | create_db("product.db") -------------------------------------------------------------------------------- /src/project/storing/product.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musikalkemist/advancedpython/848696e3278caef93b6285b4e38fe00d09cbc838/src/project/storing/product.db -------------------------------------------------------------------------------- /src/project/storing/sqlitebatchproductstorer.py: -------------------------------------------------------------------------------- 1 | from typing import List, Tuple 2 | 3 | import sqlite3 4 | 5 | from src.project.product import Product 6 | from src.project.utils import accepts_types 7 | 8 | 9 | class SQLiteBatchProductStorer: 10 | """This class is responsible to batch insert product entries in the db.""" 11 | 12 | def __init__(self, table: str = "product"): 13 | self.table = table 14 | 15 | @accepts_types(sqlite3.Cursor, list) 16 | def store(self, 17 | db_cursor: sqlite3.Cursor, 18 | products: List[Product]) -> None: 19 | """Batch insert list of products in the 'product' table of the db.""" 20 | products_list = self._convert_products_to_list(products) 21 | db_cursor.executemany(f"INSERT INTO {self.table}(name, currency, price) VALUES(?, ?, ?)", products_list) 22 | 23 | @staticmethod 24 | def _convert_products_to_list(products: List[Product]) -> List[Tuple[str, str, float]]: 25 | return [product.to_tuple() for product in products] 26 | 27 | -------------------------------------------------------------------------------- /src/project/storing/sqlitecontextmanager.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | class SQLiteContextManager: 5 | """Context manager for SQLite db, that handles db open / closing 6 | connection. 7 | """ 8 | 9 | def __init__(self, db_path: str) -> None: 10 | self.db_path = db_path 11 | self.connection = None 12 | 13 | def __enter__(self): 14 | """Establish connection with db and return cursor to be used to execute 15 | db queries. 16 | """ 17 | self.connection = sqlite3.connect(self.db_path) 18 | return self.connection.cursor() 19 | 20 | def __exit__(self, exc_type, exc_val, exc_tb): 21 | """Commit queries and close connection.""" 22 | self.connection.commit() 23 | self.connection.close() 24 | -------------------------------------------------------------------------------- /src/project/test/files/1.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "product_1", 3 | "currency": "dollar", 4 | "price": 100 5 | } 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/project/test/files/2.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "product_2", 3 | "currency": "dollar", 4 | "price": 10 5 | } 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/project/test/files/3.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "product_3", 3 | "currency": "dollar", 4 | "price": 10 5 | } 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/project/test/files/4.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "product_4", 3 | "currency": "dollar", 4 | "price": 10 5 | } 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/project/test/files/5.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "product_5", 3 | "currency": "euro", 4 | "price": 10 5 | } 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/project/test/test_batchtransformer.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from src.project.transforming.batchtransformer import BatchTransformer 4 | from src.project.transforming.currencyconverter import CurrencyConverter 5 | from src.project.transforming.pricemultiplier import PriceMultiplier 6 | from src.project.product import Product 7 | 8 | 9 | @pytest.fixture 10 | def batch_transformer(): 11 | exchange_rate = {"euro": {"dollar": 2}} 12 | currency_converter = CurrencyConverter(exchange_rate, "euro") 13 | price_multiplier = PriceMultiplier(2) 14 | return BatchTransformer([currency_converter, price_multiplier]) 15 | 16 | 17 | def test_batch_transform_init(batch_transformer): 18 | assert type(batch_transformer) == BatchTransformer 19 | assert len(batch_transformer.transforms) == 2 20 | assert type(batch_transformer.transforms[0]) == CurrencyConverter 21 | 22 | 23 | def test_apply_transforms(batch_transformer): 24 | products = [Product(name="product_1", currency="dollar", price=10.), 25 | Product(name="product_2", currency="euro", price=10.)] 26 | transformed_products = batch_transformer.apply(products) 27 | assert len(transformed_products) == 2 28 | assert transformed_products[0].currency == "euro" 29 | assert transformed_products[0].price == 40. 30 | assert transformed_products[1].price == 20. 31 | 32 | -------------------------------------------------------------------------------- /src/project/test/test_currencyconverter.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from src.project.transforming.currencyconverter import CurrencyConverter, latest_exchange_rates 4 | from src.project.product import Product 5 | 6 | 7 | @pytest.fixture 8 | def product(): 9 | return Product(name="product_1", 10 | currency="dollar", 11 | price=10.) 12 | 13 | 14 | @pytest.fixture 15 | def currency_converter(): 16 | exchange_rate = {"euro": {"dollar": 2}} 17 | return CurrencyConverter(exchange_rate, "euro") 18 | 19 | 20 | def test_apply_on_product_that_doesnt_have_target_currency(currency_converter): 21 | product = Product(name="product_1", 22 | currency="euro", 23 | price=10.) 24 | new_product = currency_converter.apply(product) 25 | assert new_product == product 26 | 27 | 28 | def test_create_currency_converted_product_is_called_once(currency_converter, mocker): 29 | product = Product(name="product_1", 30 | currency="dollar", 31 | price=10.) 32 | mock_method = mocker.patch.object(currency_converter, "_create_currency_converted_product", autospec=True) 33 | mock_method.return_value = "dummy" 34 | _ = currency_converter.apply(product) 35 | mock_method.assert_called_once_with(product) 36 | 37 | 38 | def test_apply_on_product_that_already_has_target_currency(product, currency_converter): 39 | currency_converted_product = currency_converter.apply(product) 40 | assert currency_converted_product.price == 20. 41 | assert currency_converted_product.name == "product_1" 42 | assert currency_converted_product.currency == "euro" 43 | 44 | 45 | def test_currenty_converted_product_is_created(product, currency_converter): 46 | currency_converted_product = currency_converter._create_currency_converted_product(product) 47 | assert currency_converted_product.price == 20. 48 | assert currency_converted_product.name == "product_1" 49 | assert currency_converted_product.currency == "euro" 50 | 51 | 52 | def test_convert_price(product, currency_converter): 53 | converted_price = currency_converter._convert_price(product) 54 | assert converted_price == 20. 55 | 56 | 57 | def test_currency_converter_init(): 58 | currency_converter = CurrencyConverter(latest_exchange_rates, "euro") 59 | assert type(currency_converter) == CurrencyConverter 60 | assert currency_converter.exchange_rates == latest_exchange_rates 61 | assert currency_converter.target_currency == "euro" 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/project/test/test_pricemultiplier.py: -------------------------------------------------------------------------------- 1 | from src.project.transforming.pricemultiplier import PriceMultiplier 2 | from src.project.product import Product 3 | 4 | 5 | def test_price_multiplier_init(): 6 | price_multiplier = PriceMultiplier(0.8) 7 | assert type(price_multiplier) == PriceMultiplier 8 | assert price_multiplier.multiplier == 0.8 9 | 10 | 11 | def test_apply(): 12 | price_multiplier = PriceMultiplier(0.8) 13 | product = Product(name="product_1", 14 | currency="dollar", 15 | price=10.) 16 | 17 | transformed_product = price_multiplier.apply(product) 18 | assert transformed_product != product 19 | assert transformed_product.name == product.name 20 | assert transformed_product.currency == product.currency 21 | assert transformed_product.price == 8. 22 | 23 | -------------------------------------------------------------------------------- /src/project/test/test_product.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from src.project.product import Product 4 | from src.project.errors import CurrencyError 5 | from src.project.utils import create_products 6 | 7 | 8 | def test_product_init(): 9 | product = Product(name="product_1", 10 | currency="dollar", 11 | price=13.5) 12 | assert type(product) == Product 13 | assert product.name == "product_1" 14 | assert product.currency == "dollar" 15 | assert product.price == 13.5 16 | 17 | 18 | def test_currency_error_raised_when_passing_unsupported_currency(): 19 | with pytest.raises(CurrencyError): 20 | Product(name="product_1", 21 | currency="UNSUPPORTED_CURRENCY", 22 | price=13.5) 23 | 24 | 25 | def test_product_to_tuple(): 26 | product = Product(name="product_1", 27 | currency="dollar", 28 | price=13.5) 29 | product_tuple = product.to_tuple() 30 | assert len(product_tuple) == 3 31 | assert type(product_tuple) == tuple 32 | assert product_tuple[0] == "product_1" 33 | assert product_tuple[1] == "dollar" 34 | assert product_tuple[2] == 13.5 -------------------------------------------------------------------------------- /src/project/test/test_sqlitebatchproductstorer.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import os 3 | 4 | import pytest 5 | 6 | from src.project.storing.sqlitebatchproductstorer import SQLiteBatchProductStorer 7 | from src.project.product import Product 8 | from src.project.storing.createdb import create_db 9 | 10 | 11 | @pytest.fixture 12 | def products(): 13 | return [Product(name="product_1", currency="dollar", price=10.), 14 | Product(name="product_2", currency="euro", price=10.)] 15 | 16 | 17 | @pytest.fixture 18 | def expected_product_list(): 19 | return [("product_1", "dollar", 10.), ("product_2", "euro", 10.)] 20 | 21 | 22 | def test_sqlite_batch_product_storer_init(): 23 | product_storer = SQLiteBatchProductStorer("table") 24 | assert type(product_storer) == SQLiteBatchProductStorer 25 | assert product_storer.table == "table" 26 | 27 | 28 | def test_products_are_inserted_in_db(products, expected_product_list): 29 | try: 30 | create_db("dummy.db") 31 | product_storer = SQLiteBatchProductStorer("product") 32 | connection = sqlite3.connect("dummy.db") 33 | cursor = connection.cursor() 34 | 35 | product_storer.store(cursor, products) 36 | cursor.execute("SELECT NAME, CURRENCY, PRICE FROM PRODUCT") 37 | products = cursor.fetchall() 38 | 39 | assert products == expected_product_list 40 | finally: 41 | os.remove("dummy.db") 42 | 43 | 44 | def test_convert_products_to_list(products, expected_product_list): 45 | products_list = SQLiteBatchProductStorer._convert_products_to_list(products) 46 | assert products_list == expected_product_list -------------------------------------------------------------------------------- /src/project/test/test_sqlitecontextmanager.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Cursor 2 | import os 3 | 4 | from src.project.storing.sqlitecontextmanager import SQLiteContextManager 5 | 6 | 7 | def test_sqlite_context_manager_init(): 8 | sqlite_context_manger = SQLiteContextManager("dummy2.db") 9 | assert type(sqlite_context_manger) == SQLiteContextManager 10 | 11 | 12 | def test_enter_context_manager(): 13 | with SQLiteContextManager("dummy.db") as cursor: 14 | assert type(cursor) == Cursor 15 | os.remove("dummy.db") 16 | 17 | -------------------------------------------------------------------------------- /src/project/test/test_utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | from src.project.utils import create_products 4 | from src.project.utils import create_file_paths_from_dir, nest_list 5 | from src.project.product import Product 6 | 7 | 8 | 9 | def test_create_products(): 10 | product_params = [ 11 | { 12 | "name": "product_1", 13 | "currency": "dollar", 14 | "price": 100 15 | }, 16 | { 17 | "name": "product_2", 18 | "currency": "dollar", 19 | "price": 10 20 | } 21 | ] 22 | products = create_products(product_params) 23 | assert len(products) == 2 24 | assert type(products[0]) == Product 25 | assert products[1].price == 10.0 26 | 27 | 28 | def test_create_file_paths_from_dir(): 29 | dir = Path("files") 30 | paths = create_file_paths_from_dir(dir) 31 | assert paths == [Path("files/5.json"), Path("files/4.json"), Path("files/3.json"), Path("files/2.json"), Path("files/1.json")] 32 | 33 | 34 | def test_nest_list(): 35 | l = [0, 1, 2, 3, 4, 5] 36 | 37 | nested_l = nest_list(l, 6) 38 | assert nested_l == [[0, 1, 2, 3, 4, 5]] 39 | 40 | nested_l = nest_list(l, 5) 41 | assert nested_l == [[0, 1, 2, 3, 4], [5]] 42 | 43 | nested_l = nest_list(l, 4) 44 | assert nested_l == [[0, 1, 2, 3], [4, 5]] 45 | 46 | nested_l = nest_list(l, 3) 47 | assert nested_l == [[0, 1, 2], [3, 4, 5]] 48 | 49 | nested_l = nest_list(l, 2) 50 | assert nested_l == [[0, 1], [2, 3], [4, 5]] 51 | 52 | nested_l = nest_list(l, 1) 53 | assert nested_l == [[0], [1], [2], [3], [4], [5]] 54 | 55 | -------------------------------------------------------------------------------- /src/project/threadeddatapipeline.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import logging 3 | from pathlib import Path 4 | from typing import List 5 | 6 | from src.project.datapipeline import DataPipeline 7 | 8 | 9 | logging.basicConfig(level=logging.INFO, format="(%(threadName)-5s) %(message)s",) 10 | 11 | 12 | class ThreadedDataPipeline(threading.Thread): 13 | """Class that wraps a data pipeline in a thread.""" 14 | 15 | def __init__(self, 16 | data_pipeline: DataPipeline, 17 | load_paths: List[Path], 18 | **kwargs) -> None: 19 | super().__init__(**kwargs) 20 | self.data_pipeline = data_pipeline 21 | self.load_paths = load_paths 22 | 23 | def run(self) -> None: 24 | logging.info("Started processing data") 25 | self.data_pipeline.process(self.load_paths) 26 | logging.info("Finished processing data") 27 | -------------------------------------------------------------------------------- /src/project/transforming/batchtransformer.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from src.project.transforming.transform import Transform 4 | from src.project.utils import accepts_types 5 | from src.project.product import Product 6 | 7 | 8 | class BatchTransformer: 9 | """Class that applies multiple transforms to products.""" 10 | 11 | def __init__(self, transforms: List[Transform]) -> None: 12 | self._transforms = transforms 13 | 14 | @property 15 | def transforms(self) -> List[Transform]: 16 | return self._transforms 17 | 18 | @transforms.setter 19 | def transforms(self, transforms: List[Transform]) -> None: 20 | self._transforms = transforms 21 | 22 | @accepts_types(list) 23 | def apply(self, products: List[Product]) -> List[Product]: 24 | for transform in self._transforms: 25 | products = list(map(transform.apply, products)) 26 | return products 27 | -------------------------------------------------------------------------------- /src/project/transforming/currencyconverter.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from src.project.transforming.transform import Transform 4 | from src.project.product import Product 5 | from src.project.utils import accepts_types 6 | 7 | 8 | latest_exchange_rates = { 9 | "euro": {"dollar": 1.1}, 10 | "dollar": {"euro": 0.909} 11 | } 12 | 13 | 14 | class CurrencyConverter(Transform): 15 | """Convert the currency of a product, changing its currency and adjusting 16 | the price according to the exchange rate. It's a concrete Transform. 17 | """ 18 | 19 | def __init__(self, 20 | exchange_rates: Dict[str, Dict[str, float]], 21 | target_currency: str = "dollar") -> None: 22 | self.exchange_rates = exchange_rates 23 | self.target_currency = target_currency 24 | 25 | @accepts_types(Product) 26 | def apply(self, product: Product) -> Product: 27 | """Convert currency and adjust price. If product currency is already 28 | target currency, no changes are applied. 29 | """ 30 | if product.currency == self.target_currency: 31 | return product 32 | return self._create_currency_converted_product(product) 33 | 34 | def _create_currency_converted_product(self, product: Product) -> Product: 35 | currency_converted_product_params = { 36 | "name": product.name, 37 | "currency": self.target_currency, 38 | "price": self._convert_price(product) 39 | } 40 | return Product(**currency_converted_product_params) 41 | 42 | def _convert_price(self, product: Product) -> float: 43 | exchange_rate = self.exchange_rates[self.target_currency][product.currency] 44 | return product.price * exchange_rate 45 | -------------------------------------------------------------------------------- /src/project/transforming/pricemultiplier.py: -------------------------------------------------------------------------------- 1 | from src.project.transforming.transform import Transform 2 | from src.project.product import Product 3 | from src.project.utils import accepts_types 4 | 5 | 6 | class PriceMultiplier(Transform): 7 | """Modify the product price by multiplying it by a given factor. It's a 8 | concrete Transform. 9 | """ 10 | 11 | def __init__(self, multiplier: float) -> None: 12 | self.multiplier = multiplier 13 | 14 | @accepts_types(Product) 15 | def apply(self, product: Product) -> Product: 16 | """Creates a new product with price multiplied by 17 | 'self.price_multiplier'. 18 | """ 19 | transformed_price = product.price * self.multiplier 20 | return Product(name=product.name, 21 | currency=product.currency, 22 | price=transformed_price) 23 | -------------------------------------------------------------------------------- /src/project/transforming/transform.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from src.project.product import Product 4 | 5 | 6 | class Transform(ABC): 7 | """Interface for concrete Transform which modify a product object.""" 8 | 9 | @abstractmethod 10 | def apply(self, product: Product) -> Product: 11 | """Apply a transform to a product. Method must be implemented by 12 | concrete transforms.""" 13 | --------------------------------------------------------------------------------