fastapi-startkit 0.1.0__py3-none-any.whl

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 (76) hide show
  1. fastapi_startkit/__init__.py +3 -0
  2. fastapi_startkit/application.py +40 -0
  3. fastapi_startkit/configuration/Configuration.py +80 -0
  4. fastapi_startkit/configuration/__init__.py +2 -0
  5. fastapi_startkit/configuration/helpers.py +5 -0
  6. fastapi_startkit/configuration/providers/ConfigurationProvider.py +16 -0
  7. fastapi_startkit/configuration/providers/__init__.py +1 -0
  8. fastapi_startkit/container/__init__.py +1 -0
  9. fastapi_startkit/container/container.py +494 -0
  10. fastapi_startkit/environment/environment.py +76 -0
  11. fastapi_startkit/exceptions/DD.py +38 -0
  12. fastapi_startkit/exceptions/ExceptionHandler.py +76 -0
  13. fastapi_startkit/exceptions/__init__.py +38 -0
  14. fastapi_startkit/exceptions/exceptionite/__init__.py +0 -0
  15. fastapi_startkit/exceptions/exceptionite/blocks.py +101 -0
  16. fastapi_startkit/exceptions/exceptionite/controllers.py +13 -0
  17. fastapi_startkit/exceptions/exceptionite/solutions.py +66 -0
  18. fastapi_startkit/exceptions/exceptionite/tabs.py +19 -0
  19. fastapi_startkit/exceptions/exceptions.py +218 -0
  20. fastapi_startkit/exceptions/handlers/DumpExceptionHandler.py +104 -0
  21. fastapi_startkit/exceptions/handlers/HttpExceptionHandler.py +28 -0
  22. fastapi_startkit/exceptions/handlers/ModelNotFoundHandler.py +13 -0
  23. fastapi_startkit/facades/Auth.py +5 -0
  24. fastapi_startkit/facades/Auth.pyi +32 -0
  25. fastapi_startkit/facades/Broadcast.py +5 -0
  26. fastapi_startkit/facades/Cache.py +5 -0
  27. fastapi_startkit/facades/Config.py +5 -0
  28. fastapi_startkit/facades/Config.pyi +14 -0
  29. fastapi_startkit/facades/Dump.py +5 -0
  30. fastapi_startkit/facades/Dump.pyi +26 -0
  31. fastapi_startkit/facades/Facade.py +5 -0
  32. fastapi_startkit/facades/Gate.py +5 -0
  33. fastapi_startkit/facades/Gate.pyi +32 -0
  34. fastapi_startkit/facades/Hash.py +5 -0
  35. fastapi_startkit/facades/Hash.pyi +28 -0
  36. fastapi_startkit/facades/Loader.py +5 -0
  37. fastapi_startkit/facades/Loader.pyi +30 -0
  38. fastapi_startkit/facades/Mail.py +5 -0
  39. fastapi_startkit/facades/Mail.pyi +14 -0
  40. fastapi_startkit/facades/Notification.py +5 -0
  41. fastapi_startkit/facades/Notification.pyi +25 -0
  42. fastapi_startkit/facades/Queue.py +5 -0
  43. fastapi_startkit/facades/Queue.pyi +10 -0
  44. fastapi_startkit/facades/RateLimiter.py +5 -0
  45. fastapi_startkit/facades/RateLimiter.pyi +43 -0
  46. fastapi_startkit/facades/Request.py +5 -0
  47. fastapi_startkit/facades/Request.pyi +88 -0
  48. fastapi_startkit/facades/Response.py +5 -0
  49. fastapi_startkit/facades/Response.pyi +68 -0
  50. fastapi_startkit/facades/Session.py +5 -0
  51. fastapi_startkit/facades/Session.pyi +59 -0
  52. fastapi_startkit/facades/Storage.py +5 -0
  53. fastapi_startkit/facades/Storage.pyi +12 -0
  54. fastapi_startkit/facades/Url.py +5 -0
  55. fastapi_startkit/facades/Url.pyi +22 -0
  56. fastapi_startkit/facades/View.py +5 -0
  57. fastapi_startkit/facades/View.pyi +54 -0
  58. fastapi_startkit/facades/__init__.py +19 -0
  59. fastapi_startkit/loader/Loader.py +78 -0
  60. fastapi_startkit/loader/__init__.py +1 -0
  61. fastapi_startkit/providers/ConfigurationProvider.py +13 -0
  62. fastapi_startkit/providers/Provider.py +14 -0
  63. fastapi_startkit/providers/__init__.py +4 -0
  64. fastapi_startkit/utils/__init__.py +0 -0
  65. fastapi_startkit/utils/collections.py +545 -0
  66. fastapi_startkit/utils/console.py +39 -0
  67. fastapi_startkit/utils/data/mime.types +1863 -0
  68. fastapi_startkit/utils/filesystem.py +100 -0
  69. fastapi_startkit/utils/http.py +101 -0
  70. fastapi_startkit/utils/location.py +90 -0
  71. fastapi_startkit/utils/str.py +120 -0
  72. fastapi_startkit/utils/structures.py +97 -0
  73. fastapi_startkit/utils/time.py +58 -0
  74. fastapi_startkit-0.1.0.dist-info/METADATA +13 -0
  75. fastapi_startkit-0.1.0.dist-info/RECORD +76 -0
  76. fastapi_startkit-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,76 @@
1
+ """Module for the LoadEnvironment class."""
2
+
3
+ import os
4
+ import sys
5
+ from pathlib import Path
6
+
7
+
8
+ class LoadEnvironment:
9
+ """This class is used for loading the environment from .env and .env.* files."""
10
+
11
+ def __init__(self, environment=None, override=True, only=None, base_path=None):
12
+ """LoadEnvironment constructor.
13
+
14
+ Keyword Arguments:
15
+ env {string} -- An additional environment file that you want to load. (default: {None})
16
+ override {bool} -- Whether or not the environment variables found should overwrite existing ones. (default: {False})
17
+ only {string} -- If this is set then it will only load that environment. (default: {None})
18
+ base_path {string} -- The base path to look for the environment file. (default: {None})
19
+ """
20
+ from dotenv import load_dotenv
21
+
22
+ self.env = load_dotenv
23
+ self.base_path = Path(base_path) if base_path else Path(".")
24
+
25
+ if only:
26
+ self._load_environment(only, override=override)
27
+ return
28
+
29
+ env_path = str(self.base_path / ".env")
30
+ self.env(env_path, override=override)
31
+
32
+ if os.environ.get("APP_ENV"):
33
+ self._load_environment(os.environ.get("APP_ENV"), override=override)
34
+ if environment:
35
+ self._load_environment(environment, override=override)
36
+
37
+ if "PYTEST_CURRENT_TEST" in os.environ:
38
+ self._load_environment("testing", override=override)
39
+
40
+ def _load_environment(self, environment, override=False):
41
+ """Load the environment depending on the env file.
42
+
43
+ Arguments:
44
+ environment {string} -- Name of the environment file to load from
45
+
46
+ Keyword Arguments:
47
+ override {bool} -- Whether the environment file should overwrite existing environment keys. (default: {False})
48
+ """
49
+ env_path = str(self.base_path / f".env.{environment}")
50
+ self.env(dotenv_path=env_path, override=override)
51
+
52
+
53
+ def env(value, default="", cast=True):
54
+ """Helper to retrieve the value of an environment variable or returns
55
+ a default value. In addition, if type can be inferred then the value can be casted to the
56
+ inferred type."""
57
+ env_var = os.getenv(value, default)
58
+
59
+ if not cast:
60
+ return env_var
61
+
62
+ if env_var == "":
63
+ env_var = default
64
+
65
+ if isinstance(env_var, bool):
66
+ return env_var
67
+ elif env_var is None:
68
+ return None
69
+ elif env_var.isnumeric():
70
+ return int(env_var)
71
+ elif env_var in ("false", "False"):
72
+ return False
73
+ elif env_var in ("true", "True"):
74
+ return True
75
+ else:
76
+ return env_var
@@ -0,0 +1,38 @@
1
+ import inspect
2
+ import warnings
3
+
4
+ from .exceptions import DumpException
5
+
6
+
7
+ warnings.warn(
8
+ "DD class will be removed in Masonite 5. Please use Dump facade instead.",
9
+ DeprecationWarning,
10
+ )
11
+
12
+
13
+ class DD:
14
+ def __init__(self, container):
15
+ self.app = container
16
+
17
+ def die_and_dump(self, *args):
18
+ """Dump all provided args and die, ie raise a DumpException."""
19
+ self.dump(*args)
20
+ raise DumpException
21
+
22
+ def dump(self, *args):
23
+ """Dump all provided args and let flow continue. This does not raise a DumpException."""
24
+ print(
25
+ inspect.stack()[1].function,
26
+ inspect.stack()[1].filename,
27
+ inspect.stack()[1].lineno,
28
+ )
29
+ if self.app.has("ObjDumpList"):
30
+ dump_list = self.app.make("ObjDumpList")
31
+ else:
32
+ dump_list = []
33
+ start = len(dump_list)
34
+ for i, obj in enumerate(args):
35
+ dump_name = f"ObjDump{start + i}"
36
+ self.app.bind(dump_name, obj)
37
+ dump_list.append(dump_name)
38
+ self.app.bind("ObjDumpList", dump_list)
@@ -0,0 +1,76 @@
1
+ class ExceptionHandler:
2
+ def __init__(self, application, driver_config=None):
3
+ self.application = application
4
+ self.drivers = {}
5
+ self.driver_config = driver_config or {}
6
+ self.options = {}
7
+
8
+ def set_options(self, options):
9
+ self.options = options
10
+ return self
11
+
12
+ def add_driver(self, name, driver):
13
+ self.drivers.update({name: driver})
14
+
15
+ def set_configuration(self, config):
16
+ self.driver_config = config
17
+ return self
18
+
19
+ def get_driver(self, name=None):
20
+ if name is None:
21
+ return self.drivers[self.driver_config.get("default")]
22
+ return self.drivers[name]
23
+
24
+ def get_config_options(self, driver=None):
25
+ if driver is None:
26
+ return self.driver_config[self.driver_config.get("default")]
27
+
28
+ return self.driver_config.get(driver, {})
29
+
30
+ def handle(self, exception):
31
+ response = self.application.make("response")
32
+ request = self.application.make("request")
33
+
34
+ self.application.make("event").fire(
35
+ f"masonite.exception.{exception.__class__.__name__}", exception
36
+ )
37
+
38
+ # add headers to response if any
39
+ if hasattr(exception, "get_headers"):
40
+ headers = exception.get_headers()
41
+ response.with_headers(headers)
42
+
43
+ # if an exception handler is registered for this exception, use it instead
44
+ # add headers to response if any
45
+ if hasattr(exception, "get_headers"):
46
+ headers = exception.get_headers()
47
+ response.with_headers(headers)
48
+
49
+ if self.application.has(f"{exception.__class__.__name__}Handler"):
50
+ return self.application.make(
51
+ f"{exception.__class__.__name__}Handler"
52
+ ).handle(exception)
53
+
54
+ # handle exception in production
55
+ if not self.application.is_debug():
56
+ # for HTTP error codes (500, 404, 403...) a specific page should be displayed
57
+ # if a renderable exception is raised let it be displayed
58
+ if hasattr(exception, "is_http_exception") or hasattr(
59
+ exception, "get_response"
60
+ ):
61
+ return self.application.make("HttpExceptionHandler").handle(exception)
62
+
63
+ # else fallback to an unknown exception that should be displayed as a 500 error
64
+ exception.get_status = lambda: 500
65
+ exception.get_response = lambda: str(exception) or "Unknown error"
66
+ return self.application.make("HttpExceptionHandler").handle(exception)
67
+
68
+ # handle exception in development mode with Exceptionite
69
+ exceptionite = self.get_driver("exceptionite")
70
+ exceptionite.start(exception)
71
+ exceptionite.render("terminal")
72
+
73
+ if request.accepts_json():
74
+ return response.view(exceptionite.render("json"), status=500)
75
+ else:
76
+ return response.view(exceptionite.render("web"), status=500)
@@ -0,0 +1,38 @@
1
+ from .ExceptionHandler import ExceptionHandler
2
+ from .handlers.DumpExceptionHandler import DumpExceptionHandler
3
+ from .handlers.HttpExceptionHandler import HttpExceptionHandler
4
+ from .handlers.ModelNotFoundHandler import ModelNotFoundHandler
5
+ from .DD import DD
6
+ from .exceptions import (
7
+ AuthorizationException,
8
+ InvalidRouteCompileException,
9
+ RouteMiddlewareNotFound,
10
+ ContainerError,
11
+ MissingContainerBindingNotFound,
12
+ StrictContainerException,
13
+ ResponseError,
14
+ InvalidHTTPStatusCode,
15
+ RequiredContainerBindingNotFound,
16
+ ViewException,
17
+ RouteNotFoundException,
18
+ DumpException,
19
+ InvalidSecretKey,
20
+ InvalidCSRFToken,
21
+ NotificationException,
22
+ InvalidToken,
23
+ ProjectLimitReached,
24
+ ProjectProviderTimeout,
25
+ ProjectProviderHttpError,
26
+ ProjectTargetNotEmpty,
27
+ MixFileNotFound,
28
+ MixManifestNotFound,
29
+ InvalidConfigurationLocation,
30
+ InvalidConfigurationSetup,
31
+ InvalidPackageName,
32
+ LoaderNotFound,
33
+ QueueException,
34
+ AmbiguousError,
35
+ MethodNotAllowedException,
36
+ ModelNotFoundException,
37
+ ThrottleRequestsException,
38
+ )
File without changes
@@ -0,0 +1,101 @@
1
+ from exceptionite import Block
2
+
3
+ from ... import __version__
4
+ from ...helpers import optional
5
+ from ...utils.str import get_controller_name
6
+
7
+
8
+ def recursive_serializer(data):
9
+ if isinstance(data, (int, bool, str, bytes)):
10
+ return data
11
+ elif isinstance(data, (list, tuple)):
12
+ return [recursive_serializer(item) for item in data]
13
+ elif isinstance(data, dict):
14
+ return {key: recursive_serializer(val) for key, val in data.items()}
15
+ elif callable(data):
16
+ return str(data)
17
+ elif hasattr(data, "serialize"):
18
+ return data.serialize()
19
+ else:
20
+ return str(data)
21
+
22
+
23
+ class AppBlock(Block):
24
+ id = "application"
25
+ name = "Application"
26
+ icon = "DesktopComputerIcon"
27
+ has_sections = True
28
+
29
+ def build(self):
30
+ request = self.handler.app.make("request")
31
+ route = request.get_route()
32
+
33
+ data = {
34
+ "Info": {
35
+ "Masonite Version": __version__,
36
+ "Environment": self.handler.app.environment(),
37
+ "Debug": self.handler.app.is_debug(),
38
+ }
39
+ }
40
+
41
+ # add app route data
42
+ if route:
43
+ data.update(
44
+ {
45
+ "Route": {
46
+ "Controller": get_controller_name(route.controller),
47
+ "Name": route.get_name(),
48
+ "Middlewares": route.get_middlewares(),
49
+ }
50
+ }
51
+ )
52
+
53
+ # add user route data
54
+ user = request.user()
55
+ if user:
56
+ data.update(
57
+ {
58
+ "User": {
59
+ "E-mail": optional(user).email,
60
+ "ID": optional(user).id,
61
+ }
62
+ }
63
+ )
64
+
65
+ return data
66
+
67
+
68
+ class RequestBlock(Block):
69
+ id = "request"
70
+ name = "Request"
71
+ icon = "SwitchHorizontalIcon"
72
+ has_sections = True
73
+
74
+ def build(self):
75
+ request = self.handler.app.make("request")
76
+ # serialize inputs (e.g. in case of file)
77
+ inputs = {}
78
+ for name, value in request.all().items():
79
+ inputs[name] = recursive_serializer(value)
80
+ return {
81
+ "Parameters": {
82
+ "Path": request.get_path(),
83
+ "Input": inputs or None,
84
+ "Request Method": request.get_request_method(),
85
+ },
86
+ "Headers": request.header_bag.to_dict(),
87
+ }
88
+
89
+
90
+ class ConfigBlock(Block):
91
+ id = "config"
92
+ name = "Configuration"
93
+ icon = "CogIcon"
94
+ has_sections = True
95
+
96
+ def build(self):
97
+ data = {}
98
+ for section, config_data in self.handler.app.make("config").all().items():
99
+ section_name = section.title()
100
+ data[section_name] = recursive_serializer(config_data)
101
+ return data
@@ -0,0 +1,13 @@
1
+ from ...request import Request
2
+ from ...controllers import Controller
3
+ from ...response import Response
4
+
5
+
6
+ class ExceptioniteController(Controller):
7
+ def run_action(self, request: Request, response: Response):
8
+ handler = request.app.make("exception_handler").get_driver("exceptionite")
9
+ data = handler.run_action(request.input("action_id"), request.input("options"))
10
+ try:
11
+ return response.json({"message": "ok", "data": data}, 200)
12
+ except: # noqa: E722
13
+ return response.json({"message": "An error happened", "data": data}, 400)
@@ -0,0 +1,66 @@
1
+ class TableNotFound:
2
+ def title(self):
3
+ return "Table Not Found"
4
+
5
+ def description(self):
6
+ return "You are trying to make a query on a table that cannot be found. Check that :table migration exists and that migrations have been ran with 'python craft migrate' command."
7
+
8
+ def regex(self):
9
+ return r"no such table: (?P<table>(\w+))"
10
+
11
+
12
+ class MissingCSRFToken:
13
+ def title(self):
14
+ return "Missing CSRF Token"
15
+
16
+ def description(self):
17
+ return "You are trying to make a sensitive request without providing a CSRF token. Your request might be vulnerable to Cross Site Request Forgery. To resolve this issue you should use {{ csrf_field }} in HTML forms or add X-CSRF-TOKEN header in AJAX requests."
18
+
19
+ def regex(self):
20
+ return r"Missing CSRF Token"
21
+
22
+
23
+ class InvalidCSRFToken:
24
+ def title(self):
25
+ return "The session does not match the CSRF token"
26
+
27
+ def description(self):
28
+ return "Try clearing your cookies for the localhost domain in your browsers developer tools."
29
+
30
+ def regex(self):
31
+ return r"Invalid CSRF Token"
32
+
33
+
34
+ class TemplateNotFound:
35
+ def title(self):
36
+ return "Template Not Found"
37
+
38
+ def description(self):
39
+ return """':template.html' view file has not been found in registered view locations. Please verify the spelling of the template and that it exists in locations declared in Kernel file. You can check
40
+ available view locations with app.make('view.locations')."""
41
+
42
+ def regex(self):
43
+ return r"Template '(?P<template>(\w+))' not found"
44
+
45
+
46
+ class NoneResponse:
47
+ def title(self):
48
+ return "Response cannot be None"
49
+
50
+ def description(self):
51
+ return """Ensure that the controller method used in this request returned something. A controller method cannot return None or nothing.
52
+ If you don't want to return a value you can return an empty string ''."""
53
+
54
+ def regex(self):
55
+ return r"Responses cannot be of type: None."
56
+
57
+
58
+ class RouteMiddlewareNotFound:
59
+ def title(self):
60
+ return "Did you register the middleware key in your Kernel.py file?"
61
+
62
+ def description(self):
63
+ return "Check your Kernel.py file inside your 'route_middleware' attribute and look for a :middleware key"
64
+
65
+ def regex(self):
66
+ return r"Could not find the \'(?P<middleware>(\w+))\' middleware key"
@@ -0,0 +1,19 @@
1
+ from exceptionite import Tab
2
+
3
+
4
+ class DumpsTab(Tab):
5
+ id = "dumps"
6
+ name = "Dumps"
7
+ component = "DumpsTab"
8
+ icon = "CodeIcon"
9
+ advertise_content = True
10
+ empty_msg = "Nothing dumped !"
11
+
12
+ def build(self):
13
+ dumps = self.handler.app.make("dumper").get_serialized_dumps()
14
+ return {
15
+ "dumps": dumps,
16
+ }
17
+
18
+ def has_content(self):
19
+ return len(self.handler.app.make("dumper").get_dumps()) > 0
@@ -0,0 +1,218 @@
1
+ class DriverNotFound(Exception):
2
+ pass
3
+
4
+
5
+ class DriverLibraryNotFound(Exception):
6
+ pass
7
+
8
+
9
+ class FileTypeException(Exception):
10
+ pass
11
+
12
+
13
+ class RequiredContainerBindingNotFound(Exception):
14
+ pass
15
+
16
+
17
+ class MissingContainerBindingNotFound(Exception):
18
+ pass
19
+
20
+
21
+ class UnacceptableDriverType(Exception):
22
+ pass
23
+
24
+
25
+ class ContainerError(Exception):
26
+ pass
27
+
28
+
29
+ class InvalidCSRFToken(Exception):
30
+ pass
31
+
32
+
33
+ class InvalidHTTPStatusCode(Exception):
34
+ pass
35
+
36
+
37
+ class RouteMiddlewareNotFound(Exception):
38
+ pass
39
+
40
+
41
+ class ResponseError(Exception):
42
+ pass
43
+
44
+
45
+ class InvalidAutoloadPath(Exception):
46
+ pass
47
+
48
+
49
+ class AutoloadContainerOverwrite(Exception):
50
+ pass
51
+
52
+
53
+ class InvalidSecretKey(Exception):
54
+ pass
55
+
56
+
57
+ class InvalidToken(Exception):
58
+ pass
59
+
60
+
61
+ class StrictContainerException(Exception):
62
+ pass
63
+
64
+
65
+ class InvalidRouteCompileException(Exception):
66
+ pass
67
+
68
+
69
+ class RouteException(Exception):
70
+ pass
71
+
72
+
73
+ class RouteNotFoundException(Exception):
74
+ is_http_exception = True
75
+
76
+ def __init__(self, message):
77
+ super().__init__(message)
78
+ self.message = message or "Route Not Found"
79
+
80
+ def get_response(self):
81
+ return self.message
82
+
83
+ def get_status(self):
84
+ return 404
85
+
86
+
87
+ class MethodNotAllowedException(Exception):
88
+ is_http_exception = True
89
+
90
+ def __init__(self, allowed_methods, method):
91
+ allowed_list = ", ".join(allowed_methods)
92
+ message = f"{method} method not allowed for this route. Supported methods are: {allowed_list}."
93
+ super().__init__(message)
94
+ self.message = message
95
+ self.headers = {"Allow": allowed_list}
96
+
97
+ def get_response(self):
98
+ return self.message
99
+
100
+ def get_headers(self):
101
+ return self.headers
102
+
103
+ def get_status(self):
104
+ return 405
105
+
106
+
107
+ class DebugException(Exception):
108
+ pass
109
+
110
+
111
+ class DumpException(Exception):
112
+ pass
113
+
114
+
115
+ class ViewException(Exception):
116
+ pass
117
+
118
+
119
+ class QueueException(Exception):
120
+ pass
121
+
122
+
123
+ class AmbiguousError(Exception):
124
+ pass
125
+
126
+
127
+ class ProjectLimitReached(Exception):
128
+ pass
129
+
130
+
131
+ class ProjectProviderTimeout(Exception):
132
+ pass
133
+
134
+
135
+ class ProjectProviderHttpError(Exception):
136
+ pass
137
+
138
+
139
+ class ProjectTargetNotEmpty(Exception):
140
+ pass
141
+
142
+
143
+ class NotificationException(Exception):
144
+ pass
145
+
146
+
147
+ class ModelNotFoundException(Exception):
148
+ is_http_exception = True
149
+
150
+ def get_response(self):
151
+ return "Model Not Found"
152
+
153
+ def get_status(self):
154
+ return 404
155
+
156
+
157
+ class AuthorizationException(Exception):
158
+ is_http_exception = True
159
+
160
+ def __init__(self, message="", status=403):
161
+ super().__init__(message)
162
+ self.message = message or "Action not authorized"
163
+ self.status = status or 403
164
+
165
+ def get_response(self):
166
+ return self.message
167
+
168
+ def get_status(self):
169
+ return self.status
170
+
171
+
172
+ class ThrottleRequestsException(Exception):
173
+ def __init__(self, message="Too many attempts", status=429, headers={}):
174
+ super().__init__(message)
175
+ self.message = message
176
+ self.status = status
177
+ self.headers = headers
178
+
179
+ def get_headers(self):
180
+ return self.headers
181
+
182
+ def get_response(self):
183
+ return self.message
184
+
185
+ def get_status(self):
186
+ return self.status
187
+
188
+
189
+ class GateDoesNotExist(Exception):
190
+ pass
191
+
192
+
193
+ class PolicyDoesNotExist(Exception):
194
+ pass
195
+
196
+
197
+ class MixManifestNotFound(Exception):
198
+ pass
199
+
200
+
201
+ class MixFileNotFound(Exception):
202
+ pass
203
+
204
+
205
+ class InvalidConfigurationLocation(Exception):
206
+ pass
207
+
208
+
209
+ class InvalidConfigurationSetup(Exception):
210
+ pass
211
+
212
+
213
+ class InvalidPackageName(Exception):
214
+ pass
215
+
216
+
217
+ class LoaderNotFound(Exception):
218
+ pass