deepxl-python-sdk 1.0.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 DeepXL.ai
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.
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: deepxl-python-sdk
3
+ Version: 1.0.0
4
+ Summary: Python Software Development Kit for DeepXL AI Fraud Detection Services
5
+ Author-email: deepxl <david@deepxl.ai>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://deepxl.ai
8
+ Project-URL: Issues, https://github.com/deepxl/python-sdk
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Dynamic: license-file
15
+
16
+ # deepxl-python-sdk
17
+ Python Software Development Kit for DeepXL fraud detection services
18
+
19
+ ## Installation
20
+
21
+ Install the SDK using pip
22
+
23
+ ```bash
24
+ pip install deepxl-python-sdk
25
+ ```
26
+
27
+ ## Example
28
+
29
+ To use the DeepXL client, you must first create an API key in the [dashboard](https://app.deepxl.ai/settings?tab=apiKeys). You can create a new API key in Settings -> API Keys -> Create API Key.
30
+
31
+ Treat this API key like you would any environment secret. Do not commit to a public repository or store in plain text.
32
+
33
+ ```python
34
+ from deepxl-python-sdk import DeepXLClient
35
+
36
+ client = new DeepXLClient(MY_API_KEY)
37
+
38
+ analysis_result = client.analyze_file("documents-model", ".\\file.pdf")
39
+ ```
40
+
41
+ ## Client methods
42
+
43
+ ### check_usage
44
+ Returns the monthly usage quota and current usage for the payment period for each media type.
45
+
46
+ #### Returns:
47
+
48
+ Returns a ```UsageResponse``` object with the following properties:
49
+
50
+ |Property|Type|
51
+ |----|----|
52
+ |image_usage_limit|int|
53
+ |image_usage|int|
54
+ |video_usage_limit|int|
55
+ |video_usage|int|
56
+ |audio_usage_limit|int|
57
+ |audio_usage|int|
58
+ |document_usage_limit|int|
59
+ |document_usage|int|
60
+
61
+ ### analyze
62
+
63
+ Analyze file data with DeepXL fraud detection.
64
+
65
+ #### Inputs
66
+
67
+ - **model_name:** the name of the model to use. You can find a complete list in our docs.
68
+ - **file_name:** the name of the file to analyze
69
+ - **file_data**: byte array of file data to analyze
70
+
71
+ > Note: while you can use a constant string as file name, it is recommended you use unique identifiers to make files easier to find in analysis history.
72
+
73
+ ### analyze_file
74
+
75
+ Analyze file with DeepXL fraud detection. This does the same thing as ```analyze``` but takes a file path as input instead of binary file data.
76
+
77
+ #### Inputs
78
+
79
+ - **model_name:** the name of the model to use. You can find a complete list in our docs.
80
+ - **file:** path of the file to analyze
81
+
82
+ #### Returns
83
+
84
+ Both ```analyze``` and ```analyze_file``` return an ```AnalysisResult``` object with the following properties:
85
+
86
+ | Property | Type | Description |
87
+ |----------|------|-|
88
+ |likelihood|float|The percent likelihood that the file has been manipulated|
89
+ |reasoning|str[]|model reasoning|
90
+ |model_results|dict|model-specific outputs|
91
+
92
+
@@ -0,0 +1,77 @@
1
+ # deepxl-python-sdk
2
+ Python Software Development Kit for DeepXL fraud detection services
3
+
4
+ ## Installation
5
+
6
+ Install the SDK using pip
7
+
8
+ ```bash
9
+ pip install deepxl-python-sdk
10
+ ```
11
+
12
+ ## Example
13
+
14
+ To use the DeepXL client, you must first create an API key in the [dashboard](https://app.deepxl.ai/settings?tab=apiKeys). You can create a new API key in Settings -> API Keys -> Create API Key.
15
+
16
+ Treat this API key like you would any environment secret. Do not commit to a public repository or store in plain text.
17
+
18
+ ```python
19
+ from deepxl-python-sdk import DeepXLClient
20
+
21
+ client = new DeepXLClient(MY_API_KEY)
22
+
23
+ analysis_result = client.analyze_file("documents-model", ".\\file.pdf")
24
+ ```
25
+
26
+ ## Client methods
27
+
28
+ ### check_usage
29
+ Returns the monthly usage quota and current usage for the payment period for each media type.
30
+
31
+ #### Returns:
32
+
33
+ Returns a ```UsageResponse``` object with the following properties:
34
+
35
+ |Property|Type|
36
+ |----|----|
37
+ |image_usage_limit|int|
38
+ |image_usage|int|
39
+ |video_usage_limit|int|
40
+ |video_usage|int|
41
+ |audio_usage_limit|int|
42
+ |audio_usage|int|
43
+ |document_usage_limit|int|
44
+ |document_usage|int|
45
+
46
+ ### analyze
47
+
48
+ Analyze file data with DeepXL fraud detection.
49
+
50
+ #### Inputs
51
+
52
+ - **model_name:** the name of the model to use. You can find a complete list in our docs.
53
+ - **file_name:** the name of the file to analyze
54
+ - **file_data**: byte array of file data to analyze
55
+
56
+ > Note: while you can use a constant string as file name, it is recommended you use unique identifiers to make files easier to find in analysis history.
57
+
58
+ ### analyze_file
59
+
60
+ Analyze file with DeepXL fraud detection. This does the same thing as ```analyze``` but takes a file path as input instead of binary file data.
61
+
62
+ #### Inputs
63
+
64
+ - **model_name:** the name of the model to use. You can find a complete list in our docs.
65
+ - **file:** path of the file to analyze
66
+
67
+ #### Returns
68
+
69
+ Both ```analyze``` and ```analyze_file``` return an ```AnalysisResult``` object with the following properties:
70
+
71
+ | Property | Type | Description |
72
+ |----------|------|-|
73
+ |likelihood|float|The percent likelihood that the file has been manipulated|
74
+ |reasoning|str[]|model reasoning|
75
+ |model_results|dict|model-specific outputs|
76
+
77
+
@@ -0,0 +1,23 @@
1
+ [project]
2
+ name = "deepxl-python-sdk"
3
+ version = "1.0.0"
4
+ authors = [
5
+ { name="deepxl", email="david@deepxl.ai" },
6
+ ]
7
+ description = "Python Software Development Kit for DeepXL AI Fraud Detection Services"
8
+ readme = "README.md"
9
+ requires-python = ">=3.9"
10
+ classifiers = [
11
+ "Programming Language :: Python :: 3",
12
+ "Operating System :: OS Independent",
13
+ ]
14
+ license = "MIT"
15
+ license-files = ["LICEN[CS]E*"]
16
+
17
+ [build-system]
18
+ requires = ["setuptools >= 77"]
19
+ build-backend = "setuptools.build_meta"
20
+
21
+ [project.urls]
22
+ Homepage = "https://deepxl.ai"
23
+ Issues = "https://github.com/deepxl/python-sdk"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,9 @@
1
+ from .client import DeepXLClient, UsageResponse, AnalysisResponse
2
+ from .error import DeepXLError
3
+
4
+ __all__ = [
5
+ "DeepXLClient",
6
+ "UsageResponse",
7
+ "AnalysisResponse",
8
+ "DeepXLError"
9
+ ]
@@ -0,0 +1,158 @@
1
+ import requests
2
+ from .mimetypes import get_mimetype
3
+ from .error import DeepXLError
4
+ import re
5
+
6
+ URL = "https://api.deepxl.ai/"
7
+
8
+
9
+ class UsageResponse:
10
+ def __init__(self, image_usage_limit, image_usage, video_usage_limit, video_usage, audio_usage_limit, audio_usage, document_usage_limit, document_usage):
11
+ self.image_usage_limit = image_usage_limit
12
+ self.image_usage = image_usage
13
+ self.video_usage_limit = video_usage_limit
14
+ self.video_usage = video_usage
15
+ self.audio_usage_limit = audio_usage_limit
16
+ self.audio_usage = audio_usage
17
+ self.document_usage_limit = document_usage_limit
18
+ self.document_usage = document_usage
19
+
20
+
21
+ def __str__(self):
22
+ return f"Image Usage: {self.image_usage} / {self.image_usage_limit}\nVideo Usage: {self.video_usage} / {self.video_usage_limit}\nAudio Usage: {self.audio_usage} / {self.audio_usage_limit}\nDocument Usage: {self.document_usage} / {self.document_usage_limit}"
23
+
24
+
25
+ class AnalysisResponse:
26
+ def __init__(self, likelihood, reasoning, model_results: dict):
27
+ self.likelihood = likelihood
28
+ self.reasoning = reasoning
29
+ self.model_results = model_results
30
+
31
+
32
+ def __str__(self):
33
+ return f"Likelihood: {self.likelihood}\nReasoning: {self.reasoning}\nModel Results: {self.model_results}"
34
+
35
+
36
+ def handle_http_error(res):
37
+ json = res.json()
38
+ # print(res.status_code, json)
39
+ if res.status_code == 200:
40
+ return
41
+ if res.status_code == 400:
42
+ raise DeepXLError(json["message"] if json["message"] else "Bad request.")
43
+ if res.status_code == 401:
44
+ raise DeepXLError("Invalid API key.")
45
+ if res.status_code == 402:
46
+ raise DeepXLError(json["message"] if json["message"] else "Usage limit reached.")
47
+ if res.status_code == 403:
48
+ pass
49
+ if res.status_code == 404:
50
+ raise DeepXLError(json["message"] if json["message"] else "Invalid model.")
51
+ if res.status_code == 415:
52
+ raise DeepXLError(json["message"] if json["message"] else "Invalid file type or file type is not compatible with the model.")
53
+ if res.statusCode == 500:
54
+ raise DeepXLError("Server error occured. Contact support or try again later.")
55
+ raise DeepXLError(f"An unknown error occured. Status code: {res.status_code}, Response: {json}")
56
+
57
+
58
+ class DeepXLClient:
59
+ def __init__(self, api_key):
60
+ self.api_key = api_key
61
+
62
+
63
+ def check_usage(self):
64
+ res = requests.get(
65
+ URL + "v1/account/",
66
+ headers={ "x-api-key": self.api_key },
67
+ timeout=5.0
68
+ )
69
+ try:
70
+ if res.status_code == 200:
71
+ json = res.json()
72
+ return UsageResponse(
73
+ json["imageUsageLimit"],
74
+ json["imageUsage"],
75
+ json["videoUsageLimit"],
76
+ json["videoUsage"],
77
+ json["audioUsageLimit"],
78
+ json["audioUsage"],
79
+ json["documentUsageLimit"],
80
+ json["documentUsage"]
81
+ )
82
+ else:
83
+ handle_http_error(res)
84
+ except ConnectionError as e:
85
+ raise e
86
+
87
+
88
+ def analyze(self, model_name: str, file_name: str, file_data: bytes):
89
+ if (len(file_data) == 0):
90
+ raise DeepXLError("File data is missing or invalid.")
91
+ try:
92
+ file_type = get_mimetype(file_name)
93
+ res = requests.post(
94
+ URL + "v1/analysis",
95
+ headers={
96
+ "x-api-key": self.api_key,
97
+ },
98
+ data={
99
+ "model": model_name
100
+ },
101
+ files={
102
+ "file": (file_name, file_data, file_type)
103
+ },
104
+ timeout=5.0
105
+ )
106
+ if res.status_code == 200:
107
+ result = res.json()["result"]
108
+ return AnalysisResponse(
109
+ likelihood=result["likelihood"],
110
+ reasoning=result["reasoning"],
111
+ model_results=result["modelResults"]
112
+ )
113
+ else:
114
+ handle_http_error(res)
115
+ except ConnectionError as e:
116
+ raise e
117
+ except DeepXLError as e:
118
+ raise e
119
+
120
+
121
+ def analyze_file(self, model_name: str, file: str):
122
+ f = None
123
+ try:
124
+ f = open(file, "rb")
125
+ base_name = file.split(r"[\\/]+")[-1]
126
+ file_type = get_mimetype(file)
127
+ res = requests.post(
128
+ URL + "v1/analysis",
129
+ headers={
130
+ "x-api-key": self.api_key,
131
+ },
132
+ data={
133
+ "model": model_name
134
+ },
135
+ files={
136
+ "file": (base_name, f, file_type)
137
+ },
138
+ timeout=5.0
139
+ )
140
+ f.close()
141
+ if res.status_code == 200:
142
+ result = res.json()["result"]
143
+ return AnalysisResponse(
144
+ likelihood=result["likelihood"],
145
+ reasoning=result["reasoning"],
146
+ model_results=result["modelResults"]
147
+ )
148
+ else:
149
+ handle_http_error(res)
150
+ except ConnectionError as e:
151
+ if not f.closed:
152
+ f.close()
153
+ raise e
154
+ except FileNotFoundError as e:
155
+ raise DeepXLError(f'File "{file}" does not exist.')
156
+ except DeepXLError as e:
157
+ raise e
158
+
@@ -0,0 +1,5 @@
1
+ class DeepXLError(Exception):
2
+
3
+ def __init__(self, message: str):
4
+ self.message = message
5
+ super().__init__(self.message)
@@ -0,0 +1,36 @@
1
+
2
+ # https://mimetype.io/all-types
3
+
4
+ # This list is likely incomplete. Expand with need for more file compatibility
5
+
6
+ def get_mimetype(filename: str):
7
+ ext = filename.split('.')[-1]
8
+ if (ext == 'jpg' or ext == 'jpeg'):
9
+ return 'image/jpeg'
10
+ elif ext == 'png':
11
+ return 'image/png'
12
+ elif ext == 'gif':
13
+ return 'image/gif'
14
+ elif ext == 'tif' or ext == 'tiff':
15
+ return 'image/tiff'
16
+ elif ext == 'bmp':
17
+ return 'image/bmp'
18
+ elif ext == 'mp4' or ext == 'mp4v' or ext == 'mpg4':
19
+ return 'video/mp4'
20
+ elif ext == 'avi':
21
+ return 'video/x-msvideo'
22
+ elif ext == 'wmv':
23
+ return 'video/x-ms-wmv'
24
+ elif ext == 'mpeg' or ext == 'mpg' or ext == 'mpe' or ext == 'm1v' or ext == 'm2v' or ext == 'mpa':
25
+ return 'video/mpeg'
26
+ elif ext == 'wav':
27
+ return 'audio/wav'
28
+ elif ext == 'mp3' or ext == 'mpga' or ext == 'm2a' or ext == 'm3a' or ext == 'mp2':
29
+ return 'audio/mpeg'
30
+ elif ext == 'wma':
31
+ return 'audio/x-ma-wma'
32
+ elif ext == 'wax':
33
+ return 'audio/x-ms-wax'
34
+ elif ext == 'pdf':
35
+ return 'application/pdf'
36
+ return None
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: deepxl-python-sdk
3
+ Version: 1.0.0
4
+ Summary: Python Software Development Kit for DeepXL AI Fraud Detection Services
5
+ Author-email: deepxl <david@deepxl.ai>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://deepxl.ai
8
+ Project-URL: Issues, https://github.com/deepxl/python-sdk
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Dynamic: license-file
15
+
16
+ # deepxl-python-sdk
17
+ Python Software Development Kit for DeepXL fraud detection services
18
+
19
+ ## Installation
20
+
21
+ Install the SDK using pip
22
+
23
+ ```bash
24
+ pip install deepxl-python-sdk
25
+ ```
26
+
27
+ ## Example
28
+
29
+ To use the DeepXL client, you must first create an API key in the [dashboard](https://app.deepxl.ai/settings?tab=apiKeys). You can create a new API key in Settings -> API Keys -> Create API Key.
30
+
31
+ Treat this API key like you would any environment secret. Do not commit to a public repository or store in plain text.
32
+
33
+ ```python
34
+ from deepxl-python-sdk import DeepXLClient
35
+
36
+ client = new DeepXLClient(MY_API_KEY)
37
+
38
+ analysis_result = client.analyze_file("documents-model", ".\\file.pdf")
39
+ ```
40
+
41
+ ## Client methods
42
+
43
+ ### check_usage
44
+ Returns the monthly usage quota and current usage for the payment period for each media type.
45
+
46
+ #### Returns:
47
+
48
+ Returns a ```UsageResponse``` object with the following properties:
49
+
50
+ |Property|Type|
51
+ |----|----|
52
+ |image_usage_limit|int|
53
+ |image_usage|int|
54
+ |video_usage_limit|int|
55
+ |video_usage|int|
56
+ |audio_usage_limit|int|
57
+ |audio_usage|int|
58
+ |document_usage_limit|int|
59
+ |document_usage|int|
60
+
61
+ ### analyze
62
+
63
+ Analyze file data with DeepXL fraud detection.
64
+
65
+ #### Inputs
66
+
67
+ - **model_name:** the name of the model to use. You can find a complete list in our docs.
68
+ - **file_name:** the name of the file to analyze
69
+ - **file_data**: byte array of file data to analyze
70
+
71
+ > Note: while you can use a constant string as file name, it is recommended you use unique identifiers to make files easier to find in analysis history.
72
+
73
+ ### analyze_file
74
+
75
+ Analyze file with DeepXL fraud detection. This does the same thing as ```analyze``` but takes a file path as input instead of binary file data.
76
+
77
+ #### Inputs
78
+
79
+ - **model_name:** the name of the model to use. You can find a complete list in our docs.
80
+ - **file:** path of the file to analyze
81
+
82
+ #### Returns
83
+
84
+ Both ```analyze``` and ```analyze_file``` return an ```AnalysisResult``` object with the following properties:
85
+
86
+ | Property | Type | Description |
87
+ |----------|------|-|
88
+ |likelihood|float|The percent likelihood that the file has been manipulated|
89
+ |reasoning|str[]|model reasoning|
90
+ |model_results|dict|model-specific outputs|
91
+
92
+
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/deepxl_python_sdk/__init__.py
5
+ src/deepxl_python_sdk/client.py
6
+ src/deepxl_python_sdk/error.py
7
+ src/deepxl_python_sdk/mimetypes.py
8
+ src/deepxl_python_sdk.egg-info/PKG-INFO
9
+ src/deepxl_python_sdk.egg-info/SOURCES.txt
10
+ src/deepxl_python_sdk.egg-info/dependency_links.txt
11
+ src/deepxl_python_sdk.egg-info/top_level.txt
12
+ test/test_client.py
@@ -0,0 +1 @@
1
+ deepxl_python_sdk
@@ -0,0 +1,102 @@
1
+ from deepxl_python_sdk import DeepXLClient, UsageResponse, AnalysisResponse, DeepXLError
2
+ import unittest
3
+ import os
4
+
5
+
6
+ API_KEY = os.environ['TESTING_API_KEY']
7
+
8
+
9
+ class TestClient(unittest.TestCase):
10
+
11
+ def test_check_usage(self):
12
+ client = DeepXLClient(API_KEY)
13
+ response = client.check_usage()
14
+ self.assertIsInstance(response, UsageResponse)
15
+ self.assertTrue(response.image_usage_limit is not None)
16
+ self.assertTrue(response.image_usage is not None)
17
+ self.assertTrue(response.video_usage_limit is not None)
18
+ self.assertTrue(response.video_usage is not None)
19
+ self.assertTrue(response.audio_usage_limit is not None)
20
+ self.assertTrue(response.audio_usage is not None)
21
+ self.assertTrue(response.document_usage_limit is not None)
22
+ self.assertTrue(response.document_usage is not None)
23
+
24
+
25
+ def test_analyze(self):
26
+ client = DeepXLClient(API_KEY)
27
+ f = open(".\\test\\rickroll.jpg", 'rb')
28
+ data = f.read()
29
+ f.close()
30
+ response = client.analyze("always-false", "rickroll.jpg", data)
31
+ self.assertIsInstance(response, AnalysisResponse)
32
+ self.assertTrue(response.likelihood is not None)
33
+ self.assertTrue(response.reasoning is not None)
34
+ self.assertTrue(response.model_results is not None)
35
+
36
+
37
+ def test_analyze_file(self):
38
+ client = DeepXLClient(API_KEY)
39
+ response = client.analyze_file("always-true", ".\\test\\rickroll.jpg")
40
+ print(response)
41
+ self.assertIsInstance(response, AnalysisResponse)
42
+ self.assertTrue(response.likelihood is not None)
43
+ self.assertTrue(response.reasoning is not None)
44
+ self.assertTrue(response.model_results is not None)
45
+
46
+
47
+ def test_unauthorized(self):
48
+ client = DeepXLClient("bad123")
49
+ try:
50
+ response = client.check_usage()
51
+ except Exception as e:
52
+ self.assertIsInstance(e, DeepXLError)
53
+ self.assertEqual(e.message, "Invalid API key.")
54
+
55
+ try:
56
+ response = client.analyze_file("always-true", "C:\\Users\\David\\Pictures\\rickroll.jpg")
57
+ except Exception as e:
58
+ self.assertIsInstance(e, DeepXLError)
59
+ self.assertEqual(e.message, "Invalid API key.")
60
+
61
+
62
+ def test_invalid_model_name(self):
63
+ client = DeepXLClient(API_KEY)
64
+ model_name = "not-a-model"
65
+ try:
66
+ f = open(".\\test\\rickroll.jpg", 'rb')
67
+ data = f.read()
68
+ f.close()
69
+ response = client.analyze(model_name, "rickroll.jpg", data)
70
+ except Exception as e:
71
+ self.assertIsInstance(e, DeepXLError)
72
+ self.assertEqual(e.message, f"Invalid model: {model_name}")
73
+
74
+ try:
75
+ response = client.analyze_file(model_name, ".\\test\\rickroll.jpg")
76
+ except Exception as e:
77
+ self.assertIsInstance(e, DeepXLError)
78
+ self.assertEqual(e.message, f"Invalid model: {model_name}")
79
+
80
+
81
+ def test_no_file_data(self):
82
+ client = DeepXLClient(API_KEY)
83
+ try:
84
+ response = client.analyze("always-true", "rickroll.jpg", b"")
85
+ except Exception as e:
86
+ self.assertIsInstance(e, DeepXLError)
87
+ self.assertEqual(e.message, "File data is missing or invalid.")
88
+
89
+
90
+ def test_file_not_found(self):
91
+ client = DeepXLClient(API_KEY)
92
+ file = ".\\file\\not\\here.png"
93
+ try:
94
+ response = client.analyze_file("always-true", file)
95
+ except Exception as e:
96
+ self.assertIsInstance(e, DeepXLError)
97
+ self.assertEqual(e.message, f'File "{file}" does not exist.')
98
+
99
+
100
+ if __name__ == '__main__':
101
+ unittest.main()
102
+