sqlalchemyseed 1.0.5__tar.gz → 1.0.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {sqlalchemyseed-1.0.5/src/sqlalchemyseed.egg-info → sqlalchemyseed-1.0.7}/PKG-INFO +65 -5
  2. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/README.md +66 -2
  3. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/pyproject.toml +1 -1
  4. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/setup.cfg +3 -5
  5. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/setup.py +4 -4
  6. sqlalchemyseed-1.0.7/src/sqlalchemyseed/__init__.py +17 -0
  7. sqlalchemyseed-1.0.7/src/sqlalchemyseed/attribute.py +70 -0
  8. sqlalchemyseed-1.0.7/src/sqlalchemyseed/constants.py +4 -0
  9. sqlalchemyseed-1.0.7/src/sqlalchemyseed/dynamic_seeder.py +4 -0
  10. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/src/sqlalchemyseed/errors.py +4 -9
  11. sqlalchemyseed-1.0.7/src/sqlalchemyseed/json.py +168 -0
  12. sqlalchemyseed-1.0.7/src/sqlalchemyseed/loader.py +64 -0
  13. sqlalchemyseed-1.0.7/src/sqlalchemyseed/seeder.py +316 -0
  14. sqlalchemyseed-1.0.7/src/sqlalchemyseed/util.py +114 -0
  15. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/src/sqlalchemyseed/validator.py +1 -21
  16. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7/src/sqlalchemyseed.egg-info}/PKG-INFO +65 -5
  17. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/src/sqlalchemyseed.egg-info/SOURCES.txt +10 -2
  18. sqlalchemyseed-1.0.7/src/sqlalchemyseed.egg-info/requires.txt +4 -0
  19. sqlalchemyseed-1.0.7/tests/test_json.py +58 -0
  20. sqlalchemyseed-1.0.7/tests/test_loader.py +41 -0
  21. sqlalchemyseed-1.0.7/tests/test_seeder.py +596 -0
  22. sqlalchemyseed-1.0.7/tests/test_temp_seeder.py +10 -0
  23. sqlalchemyseed-1.0.7/tests/test_validator.py +87 -0
  24. sqlalchemyseed-1.0.5/src/sqlalchemyseed/__init__.py +0 -35
  25. sqlalchemyseed-1.0.5/src/sqlalchemyseed/class_registry.py +0 -75
  26. sqlalchemyseed-1.0.5/src/sqlalchemyseed/loader.py +0 -77
  27. sqlalchemyseed-1.0.5/src/sqlalchemyseed/seeder.py +0 -308
  28. sqlalchemyseed-1.0.5/src/sqlalchemyseed/util.py +0 -22
  29. sqlalchemyseed-1.0.5/src/sqlalchemyseed.egg-info/requires.txt +0 -8
  30. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/LICENSE +0 -0
  31. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/src/sqlalchemyseed/_future/__init__.py +0 -0
  32. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/src/sqlalchemyseed/_future/seeder.py +0 -0
  33. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/src/sqlalchemyseed.egg-info/dependency_links.txt +0 -0
  34. {sqlalchemyseed-1.0.5 → sqlalchemyseed-1.0.7}/src/sqlalchemyseed.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sqlalchemyseed
3
- Version: 1.0.5
3
+ Version: 1.0.7
4
4
  Summary: SQLAlchemy Seeder
5
5
  Home-page: https://github.com/jedymatt/sqlalchemyseed
6
6
  Author: Jedy Matt Tabasco
@@ -10,7 +10,6 @@ Project-URL: Documentation, https://sqlalchemyseed.readthedocs.io/
10
10
  Project-URL: Source, https://github.com/jedymatt/sqlalchemyseed
11
11
  Project-URL: Tracker, https://github.com/jedymatt/sqlalchemyseed/issues
12
12
  Keywords: sqlalchemy,orm,seed,seeder,json,yaml
13
- Platform: UNKNOWN
14
13
  Classifier: License :: OSI Approved :: MIT License
15
14
  Classifier: Programming Language :: Python :: 3.6
16
15
  Classifier: Programming Language :: Python :: 3.7
@@ -20,7 +19,6 @@ Classifier: Programming Language :: Python :: 3.10
20
19
  Requires-Python: >=3.6
21
20
  Description-Content-Type: text/markdown
22
21
  Provides-Extra: yaml
23
- Provides-Extra: docs
24
22
  License-File: LICENSE
25
23
 
26
24
  # sqlalchemyseed
@@ -28,7 +26,7 @@ License-File: LICENSE
28
26
  [![PyPI](https://img.shields.io/pypi/v/sqlalchemyseed)](https://pypi.org/project/sqlalchemyseed)
29
27
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sqlalchemyseed)](https://pypi.org/project/sqlalchemyseed)
30
28
  [![PyPI - License](https://img.shields.io/pypi/l/sqlalchemyseed)](https://github.com/jedymatt/sqlalchemyseed/blob/main/LICENSE)
31
- [![Build Status](https://app.travis-ci.com/jedymatt/sqlalchemyseed.svg?branch=main)](https://app.travis-ci.com/jedymatt/sqlalchemyseed)
29
+ [![Python package](https://github.com/jedymatt/sqlalchemyseed/actions/workflows/python-package.yml/badge.svg)](https://github.com/jedymatt/sqlalchemyseed/actions/workflows/python-package.yml)
32
30
  [![Maintainability](https://api.codeclimate.com/v1/badges/2ca97c98929b614658ea/maintainability)](https://codeclimate.com/github/jedymatt/sqlalchemyseed/maintainability)
33
31
  [![codecov](https://codecov.io/gh/jedymatt/sqlalchemyseed/branch/main/graph/badge.svg?token=W03MFZ2FAG)](https://codecov.io/gh/jedymatt/sqlalchemyseed)
34
32
  [![Documentation Status](https://readthedocs.org/projects/sqlalchemyseed/badge/?version=latest)](https://sqlalchemyseed.readthedocs.io/en/latest/?badge=latest)
@@ -51,8 +49,9 @@ pip install sqlalchemyseed
51
49
 
52
50
  ## Quickstart
53
51
 
52
+ main.py
53
+
54
54
  ```python
55
- # main.py
56
55
  from sqlalchemyseed import load_entities_from_json
57
56
  from sqlalchemyseed import Seeder
58
57
  from db import session
@@ -70,8 +69,69 @@ seeder.seed(entities)
70
69
  session.commit() # or seeder.session.commit()
71
70
  ```
72
71
 
72
+ data.json
73
+
74
+ ```json
75
+ {
76
+ "model": "models.Person",
77
+ "data": [
78
+ {
79
+ "name": "John March",
80
+ "age": 23
81
+ },
82
+ {
83
+ "name": "Juan Dela Cruz",
84
+ "age": 21
85
+ }
86
+ ]
87
+ }
88
+ ```
89
+
73
90
  ## Documentation
74
91
 
75
92
  <https://sqlalchemyseed.readthedocs.io/>
76
93
 
94
+ ## Found Bug?
95
+
96
+ Report here in this link:
97
+ <https://github.com/jedymatt/sqlalchemyseed/issues>
98
+
99
+ ## Want to contribute?
100
+
101
+ First, Clone this [repository](https://github.com/jedymatt/sqlalchemyseed).
102
+
103
+ ### Install dev dependencies
104
+
105
+ Inside the folder, paste this in the terminal to install necessary dependencies:
106
+
107
+ ```shell
108
+ pip install -r requirements.txt -r docs/requirements.txt
109
+ ```
110
+
111
+ Note: make sure you have the virtual environment and enabled, or if you are using vs code and docker then you can simply re-open this as container.
112
+
113
+ ### Run tests
114
+
115
+ Before running tests, make sure that the package is installed as editable:
77
116
 
117
+ ```shell
118
+ python setup.py develop --user
119
+ ```
120
+
121
+ Then run the test:
122
+
123
+ ```shell
124
+ pytest tests
125
+ ```
126
+
127
+ Run test with coverage
128
+
129
+ ```shell
130
+ coverage run -m pytest
131
+ ```
132
+
133
+ Autobuild documentation
134
+
135
+ ```shell
136
+ sphinx-autobuild docs docs/_build/html
137
+ ```
@@ -3,7 +3,7 @@
3
3
  [![PyPI](https://img.shields.io/pypi/v/sqlalchemyseed)](https://pypi.org/project/sqlalchemyseed)
4
4
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sqlalchemyseed)](https://pypi.org/project/sqlalchemyseed)
5
5
  [![PyPI - License](https://img.shields.io/pypi/l/sqlalchemyseed)](https://github.com/jedymatt/sqlalchemyseed/blob/main/LICENSE)
6
- [![Build Status](https://app.travis-ci.com/jedymatt/sqlalchemyseed.svg?branch=main)](https://app.travis-ci.com/jedymatt/sqlalchemyseed)
6
+ [![Python package](https://github.com/jedymatt/sqlalchemyseed/actions/workflows/python-package.yml/badge.svg)](https://github.com/jedymatt/sqlalchemyseed/actions/workflows/python-package.yml)
7
7
  [![Maintainability](https://api.codeclimate.com/v1/badges/2ca97c98929b614658ea/maintainability)](https://codeclimate.com/github/jedymatt/sqlalchemyseed/maintainability)
8
8
  [![codecov](https://codecov.io/gh/jedymatt/sqlalchemyseed/branch/main/graph/badge.svg?token=W03MFZ2FAG)](https://codecov.io/gh/jedymatt/sqlalchemyseed)
9
9
  [![Documentation Status](https://readthedocs.org/projects/sqlalchemyseed/badge/?version=latest)](https://sqlalchemyseed.readthedocs.io/en/latest/?badge=latest)
@@ -26,8 +26,9 @@ pip install sqlalchemyseed
26
26
 
27
27
  ## Quickstart
28
28
 
29
+ main.py
30
+
29
31
  ```python
30
- # main.py
31
32
  from sqlalchemyseed import load_entities_from_json
32
33
  from sqlalchemyseed import Seeder
33
34
  from db import session
@@ -45,6 +46,69 @@ seeder.seed(entities)
45
46
  session.commit() # or seeder.session.commit()
46
47
  ```
47
48
 
49
+ data.json
50
+
51
+ ```json
52
+ {
53
+ "model": "models.Person",
54
+ "data": [
55
+ {
56
+ "name": "John March",
57
+ "age": 23
58
+ },
59
+ {
60
+ "name": "Juan Dela Cruz",
61
+ "age": 21
62
+ }
63
+ ]
64
+ }
65
+ ```
66
+
48
67
  ## Documentation
49
68
 
50
69
  <https://sqlalchemyseed.readthedocs.io/>
70
+
71
+ ## Found Bug?
72
+
73
+ Report here in this link:
74
+ <https://github.com/jedymatt/sqlalchemyseed/issues>
75
+
76
+ ## Want to contribute?
77
+
78
+ First, Clone this [repository](https://github.com/jedymatt/sqlalchemyseed).
79
+
80
+ ### Install dev dependencies
81
+
82
+ Inside the folder, paste this in the terminal to install necessary dependencies:
83
+
84
+ ```shell
85
+ pip install -r requirements.txt -r docs/requirements.txt
86
+ ```
87
+
88
+ Note: make sure you have the virtual environment and enabled, or if you are using vs code and docker then you can simply re-open this as container.
89
+
90
+ ### Run tests
91
+
92
+ Before running tests, make sure that the package is installed as editable:
93
+
94
+ ```shell
95
+ python setup.py develop --user
96
+ ```
97
+
98
+ Then run the test:
99
+
100
+ ```shell
101
+ pytest tests
102
+ ```
103
+
104
+ Run test with coverage
105
+
106
+ ```shell
107
+ coverage run -m pytest
108
+ ```
109
+
110
+ Autobuild documentation
111
+
112
+ ```shell
113
+ sphinx-autobuild docs docs/_build/html
114
+ ```
@@ -3,4 +3,4 @@ requires = [
3
3
  "setuptools>=42",
4
4
  "wheel"
5
5
  ]
6
- build-backend = "setuptools.build_meta"
6
+ build-backend = "setuptools.build_meta"
@@ -8,7 +8,8 @@ url = https://github.com/jedymatt/sqlalchemyseed
8
8
  author = Jedy Matt Tabasco
9
9
  author_email = jedymatt@gmail.com
10
10
  license = MIT
11
- license_file = LICENSE
11
+ license_files =
12
+ LICENSE
12
13
  classifiers =
13
14
  License :: OSI Approved :: MIT License
14
15
  Programming Language :: Python :: 3.6
@@ -27,7 +28,7 @@ packages = find:
27
28
  package_dir =
28
29
  =src
29
30
  install_requires =
30
- SQLAlchemy>=1.4
31
+ SQLAlchemy>=1.4,<2.0
31
32
  python_requires = >=3.6
32
33
 
33
34
  [options.packages.find]
@@ -36,9 +37,6 @@ where = src
36
37
  [options.extras_require]
37
38
  yaml =
38
39
  PyYAML>=5.4
39
- docs =
40
- sphinx-rtd-theme>=1.0
41
- sphinx>=4.2
42
40
 
43
41
  [egg_info]
44
42
  tag_build =
@@ -1,4 +1,4 @@
1
- from setuptools import setup
2
-
3
-
4
- setup()
1
+ from setuptools import setup
2
+
3
+
4
+ setup()
@@ -0,0 +1,17 @@
1
+ """
2
+ SQLAlchemy seeder that supports nested relationships with an easy to read text files.
3
+ """
4
+
5
+ from .seeder import HybridSeeder
6
+ from .seeder import Seeder
7
+ from .loader import load_entities_from_json
8
+ from .loader import load_entities_from_yaml
9
+ from .loader import load_entities_from_csv
10
+ from . import util
11
+ from . import attribute
12
+
13
+
14
+ __version__ = "1.0.7"
15
+
16
+ if __name__ == '__main__':
17
+ pass
@@ -0,0 +1,70 @@
1
+ """
2
+ attribute module containing helper functions for instrumented attribute.
3
+ """
4
+
5
+ from functools import lru_cache
6
+ from inspect import isclass
7
+
8
+ from sqlalchemy.orm import ColumnProperty, RelationshipProperty
9
+ from sqlalchemy.orm.attributes import InstrumentedAttribute, get_attribute, set_attribute
10
+
11
+
12
+ def instrumented_attribute(class_or_instance, key: str):
13
+ """
14
+ Returns instrumented attribute from the class or instance.
15
+ """
16
+
17
+ if isclass(class_or_instance):
18
+ return getattr(class_or_instance, key)
19
+
20
+ return getattr(class_or_instance.__class__, key)
21
+
22
+
23
+ def attr_is_relationship(instrumented_attr: InstrumentedAttribute):
24
+ """
25
+ Check if instrumented attribute property is a RelationshipProperty
26
+ """
27
+ return isinstance(instrumented_attr.property, RelationshipProperty)
28
+
29
+
30
+ def attr_is_column(instrumented_attr: InstrumentedAttribute):
31
+ """
32
+ Check if instrumented attribute property is a ColumnProperty
33
+ """
34
+ return isinstance(instrumented_attr.property, ColumnProperty)
35
+
36
+
37
+ def set_instance_attribute(instance, key, value):
38
+ """
39
+ Set attribute value of instance
40
+ """
41
+
42
+ instr_attr: InstrumentedAttribute = getattr(instance.__class__, key)
43
+
44
+ if attr_is_relationship(instr_attr) and instr_attr.property.uselist:
45
+ get_attribute(instance, key).append(value)
46
+ else:
47
+ set_attribute(instance, key, value)
48
+
49
+ @lru_cache()
50
+ def foreign_key_column(instrumented_attr: InstrumentedAttribute):
51
+ """
52
+ Returns the table name of the first foreignkey.
53
+ """
54
+ return next(iter(instrumented_attr.foreign_keys)).column
55
+
56
+ @lru_cache()
57
+ def referenced_class(instrumented_attr: InstrumentedAttribute):
58
+ """
59
+ Returns class that the attribute is referenced to.
60
+ """
61
+
62
+ if attr_is_relationship(instrumented_attr):
63
+ return instrumented_attr.mapper.class_
64
+
65
+ table_name = foreign_key_column(instrumented_attr).table.name
66
+
67
+ return next(filter(
68
+ lambda mapper: mapper.class_.__tablename__ == table_name,
69
+ instrumented_attr.parent.registry.mappers
70
+ )).class_
@@ -0,0 +1,4 @@
1
+ MODEL_KEY = 'model'
2
+ DATA_KEY = 'data'
3
+ FILTER_KEY = 'filter'
4
+ SOURCE_KEYS = [DATA_KEY, FILTER_KEY]
@@ -0,0 +1,4 @@
1
+ class DynamicSeeder:
2
+ """
3
+ DynamicSeeder class
4
+ """
@@ -1,43 +1,38 @@
1
1
  class ClassNotFoundError(Exception):
2
2
  """Raised when the class is not found"""
3
- pass
4
3
 
5
4
 
6
5
  class MissingKeyError(Exception):
7
6
  """Raised when a required key is missing"""
8
- pass
9
7
 
10
8
 
11
9
  class MaxLengthExceededError(Exception):
12
10
  """Raised when maximum length of data exceeded"""
13
- pass
14
11
 
15
12
 
16
13
  class InvalidTypeError(Exception):
17
14
  """Raised when a type of data is not accepted"""
18
- pass
19
15
 
20
16
 
21
17
  class EmptyDataError(Exception):
22
18
  """Raised when data is empty"""
23
- pass
24
19
 
25
20
 
26
21
  class InvalidKeyError(Exception):
27
22
  """Raised when an invalid key is invoked"""
28
- pass
29
23
 
30
24
 
31
25
  class ParseError(Exception):
32
26
  """Raised when parsing string fails"""
33
- pass
34
27
 
35
28
 
36
29
  class UnsupportedClassError(Exception):
37
30
  """Raised when an unsupported class is invoked"""
38
- pass
39
31
 
40
32
 
41
33
  class NotInModuleError(Exception):
42
34
  """Raised when a value is not found in module"""
43
- pass
35
+
36
+
37
+ class InvalidModelPath(Exception):
38
+ """Raised when an invalid model path is invoked"""
@@ -0,0 +1,168 @@
1
+ from typing import Callable, List, Union
2
+
3
+
4
+ class JsonWalker:
5
+ """
6
+ JsonWalker class
7
+ """
8
+
9
+ def __init__(self, json: Union[list, dict] = None) -> None:
10
+ self.path = []
11
+ self.root = json
12
+ self._current = json
13
+
14
+ @property
15
+ def json(self):
16
+ """
17
+ Returns current json
18
+ """
19
+ return self._current
20
+
21
+ def keys(self):
22
+ """
23
+ Returns list of keys either str or int
24
+ """
25
+ if self.json_is_dict:
26
+ return self._current.keys()
27
+
28
+ if self.json_is_list:
29
+ return list(map(lambda index: index, range(len(self._current))))
30
+
31
+ return []
32
+
33
+ @property
34
+ def current_key(self) -> Union[int, str]:
35
+ """
36
+ Returns the key of the current json
37
+ """
38
+ return self.path[-1]
39
+
40
+ def forward(self, keys: List[Union[int, str]]):
41
+ """
42
+ Move and replace current json forward.
43
+ Returns current json.
44
+ """
45
+
46
+ if len(keys) == 0:
47
+ return self._current
48
+
49
+ self._current = self.find_from_current(keys)
50
+ self.path.extend(keys)
51
+ return self._current
52
+
53
+ def backward(self):
54
+ """
55
+ Revert current json to its parent.
56
+ Returns reverted current json
57
+ """
58
+ if len(self.path) == 0:
59
+ raise ValueError('No parent found error')
60
+
61
+ self._current = self.find_from_root(self.path[:-1])
62
+ self.path.pop()
63
+
64
+ def find_from_current(self, keys: List[Union[int, str]]):
65
+ """
66
+ Find item from current json that correlates list of keys
67
+ """
68
+ return self._find(self._current, keys)
69
+
70
+ def _find(self, json: Union[list, dict], keys: List[Union[int, str]]):
71
+ """
72
+ Recursive call of finding item
73
+ """
74
+ return self._find(json[keys[0]], keys[1:]) if keys else json
75
+
76
+ def find_from_root(self, keys: List[Union[int, str]]):
77
+ """
78
+ Find item from the root json that correlates list of keys
79
+ """
80
+ return self._find(self.root, keys)
81
+
82
+ def reset(self, root=None):
83
+ """
84
+ Resets to initial state.
85
+ If root argument is supplied, self.root will be replaced.
86
+ """
87
+ if root is not None:
88
+ self.root = root
89
+
90
+ self._current = self.root
91
+ self.path.clear()
92
+
93
+ def exec_func_iter(self, func: Callable):
94
+ """
95
+ Executes function when iterating
96
+ """
97
+ current = self._current
98
+ if self.json_is_dict:
99
+ for key in current.keys():
100
+ self.forward([key])
101
+ func()
102
+ self.backward()
103
+ elif self.json_is_list:
104
+ for index in range(len(current)):
105
+ self.forward([index])
106
+ func()
107
+ self.backward()
108
+ else:
109
+ func()
110
+
111
+ def iter_as_list(self):
112
+ """
113
+ Iterates current as list.
114
+ Yields index and value.
115
+
116
+ Raises TypeError if current json is not list
117
+ """
118
+ if not self.json_is_list:
119
+ raise TypeError('json is not list')
120
+
121
+ current = self._current
122
+ for index, value in enumerate(current):
123
+ self.forward([index])
124
+ yield index, value
125
+ self.backward()
126
+
127
+ def iter_as_dict_items(self):
128
+ """
129
+ Iterates current as dict.
130
+ Yields key and value.
131
+
132
+ Raises TypeError if current json is not dict
133
+ """
134
+ if not self.json_is_dict:
135
+ raise TypeError('json is not dict')
136
+
137
+ current = self._current
138
+ for key, value in current.items():
139
+ self.forward([key])
140
+ yield key, value
141
+ self.backward()
142
+
143
+ @property
144
+ def json_is_dict(self):
145
+ """
146
+ Returns true if current json is dict
147
+ """
148
+ return isinstance(self._current, dict)
149
+
150
+ @property
151
+ def json_is_list(self):
152
+ """
153
+ Returns true if current json is list
154
+ """
155
+ return isinstance(self._current, list)
156
+
157
+
158
+ def sort_json(json: Union[list, dict], reverse=False):
159
+ """
160
+ Sort json function
161
+ """
162
+ if isinstance(json, list):
163
+ return sorted(sorted(sort_json(item), reverse=reverse) for item in json)
164
+
165
+ if isinstance(json, dict):
166
+ return {key: sort_json(value, reverse=reverse) for key, value in json.items()}
167
+
168
+ return json
@@ -0,0 +1,64 @@
1
+ """
2
+ Text file loader module
3
+ """
4
+
5
+ import csv
6
+ import json
7
+ import sys
8
+
9
+ try:
10
+ import yaml
11
+ except ModuleNotFoundError: # pragma: no cover
12
+ pass
13
+
14
+
15
+ def load_entities_from_json(json_filepath) -> dict:
16
+ """
17
+ Get entities from json
18
+ """
19
+ try:
20
+ with open(json_filepath, 'r', encoding='utf-8') as file:
21
+ entities = json.loads(file.read())
22
+ except FileNotFoundError as error:
23
+ raise FileNotFoundError from error
24
+
25
+ return entities
26
+
27
+
28
+ def load_entities_from_yaml(yaml_filepath):
29
+ """
30
+ Get entities from yaml
31
+ """
32
+ if 'yaml' not in sys.modules:
33
+ raise ModuleNotFoundError(
34
+ 'PyYAML is not installed and is required to run this function. '
35
+ 'To use this function, py -m pip install "sqlalchemyseed[yaml]"'
36
+ )
37
+
38
+ try:
39
+ with open(yaml_filepath, 'r', encoding='utf-8') as file:
40
+ entities = yaml.load(file.read(), Loader=yaml.SafeLoader)
41
+ except FileNotFoundError as error:
42
+ raise FileNotFoundError from error
43
+
44
+ return entities
45
+
46
+
47
+ def load_entities_from_csv(csv_filepath: str, model) -> dict:
48
+ """Load entities from csv file
49
+
50
+ :param csv_filepath: string csv file path
51
+ :param model: either str or class
52
+ :return: dict of entities
53
+ """
54
+ with open(csv_filepath, 'r', encoding='utf-8') as file:
55
+ source_data = list(
56
+ map(dict, csv.DictReader(file, skipinitialspace=True)))
57
+ if isinstance(model, str):
58
+ model_name = model
59
+ else:
60
+ model_name = '.'.join([model.__module__, model.__name__])
61
+
62
+ entities = {'model': model_name, 'data': source_data}
63
+
64
+ return entities