From e0b7fffff7e3a1a370dbdb95a0ba5780a37cfe43 Mon Sep 17 00:00:00 2001
From: Elazarcl <elazarb@copyleaks.com>
Date: Wed, 4 Sep 2024 12:29:43 +0300
Subject: [PATCH 1/3] added ai detector and writing assistant functions

added ai detector and writing assistant functions
---
 copyleaks/clients/__init__.py                 |  0
 copyleaks/clients/ai_detection_client.py      | 81 ++++++++++++++++
 copyleaks/clients/writing_assistant_client.py | 92 +++++++++++++++++++
 copyleaks/copyleaks.py                        |  5 +
 copyleaks/helpers/__init__.py                 |  0
 copyleaks/helpers/copyleaks_client_helper.py  | 24 +++++
 .../models/submit/ai_detection_document.py    | 72 +++++++++++++++
 copyleaks/models/submit/score_weights.py      | 52 +++++++++++
 .../submit/writing_assistant_document.py      | 63 +++++++++++++
 9 files changed, 389 insertions(+)
 create mode 100644 copyleaks/clients/__init__.py
 create mode 100644 copyleaks/clients/ai_detection_client.py
 create mode 100644 copyleaks/clients/writing_assistant_client.py
 create mode 100644 copyleaks/helpers/__init__.py
 create mode 100644 copyleaks/helpers/copyleaks_client_helper.py
 create mode 100644 copyleaks/models/submit/ai_detection_document.py
 create mode 100644 copyleaks/models/submit/score_weights.py
 create mode 100644 copyleaks/models/submit/writing_assistant_document.py

diff --git a/copyleaks/clients/__init__.py b/copyleaks/clients/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/copyleaks/clients/ai_detection_client.py b/copyleaks/clients/ai_detection_client.py
new file mode 100644
index 0000000..3d2b5d1
--- /dev/null
+++ b/copyleaks/clients/ai_detection_client.py
@@ -0,0 +1,81 @@
+
+'''
+ The MIT License(MIT)
+ 
+ Copyright(c) 2016 Copyleaks LTD (https://copyleaks.com)
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+'''
+
+from aifc import Error
+import requests
+from copyleaks.consts import Consts
+from copyleaks.helpers.copyleaks_client_helper import CopyleaksClientHelper
+
+class _AIDetectionClient:
+    @staticmethod
+    def __submit(url, auth_token, scan_id, submission):
+        assert url and scan_id and submission
+
+        CopyleaksClientHelper.verify_auth_token(auth_token)
+
+        headers = {
+            'Content-Type': 'application/json',
+            'User-Agent': Consts.USER_AGENT,
+            'Authorization': f"Bearer {auth_token['access_token']}"
+        }
+        json = submission.toJSON()
+        response = requests.post(url, headers=headers, data=json)
+        if response.ok:
+            return response.json()
+        elif response.status_code == 503:
+            raise Error()
+        else:
+            raise Error(response)
+        
+    @staticmethod
+    def submit_natural_language(auth_token, scan_id, submission):
+        '''
+            Use Copyleaks AI Content Detection to differentiate between human texts and AI written texts.
+            This endpoint will receive submitted text to be checked. At the end of the processing stage, 
+            the result will be shown as classifications. Text classification is divided into sections. 
+            Each section may have a different classification
+
+            Raises:
+                `CommandError`: Server reject the request. See response status code, headers and content for more info.
+                `UnderMaintenanceError`: Copyleaks servers are unavailable for maintenance. We recommend to implement exponential backoff algorithm as described here: https://api.copyleaks.com/documentation/v3/exponential-backoff
+        '''
+        url = f"{Consts.API_SERVER_URI}/v2/writer-detector/{scan_id}/check"
+        return _AIDetectionClient.__submit(url, auth_token, scan_id, submission)
+    
+    
+    @staticmethod
+    def submit_source_code(auth_token, scan_id, submission):
+        '''
+            Use Copyleaks AI Content Detection to differentiate between human source code and AI written source code.
+            This endpoint will receive submitted source code to be checked. 
+            At the end of the processing stage, the result will be shown as classifications. 
+            Source code classification is divided into sections. Each section may have a different classification.
+
+            Raises:
+                `CommandError`: Server reject the request. See response status code, headers and content for more info.
+                `UnderMaintenanceError`: Copyleaks servers are unavailable for maintenance. We recommend to implement exponential backoff algorithm as described here: https://api.copyleaks.com/documentation/v3/exponential-backoff
+        '''
+        url = f"{Consts.API_SERVER_URI}/v2/writer-detector/source-code/{scan_id}/check"
+        return _AIDetectionClient.__submit(url, auth_token, scan_id, submission)
\ No newline at end of file
diff --git a/copyleaks/clients/writing_assistant_client.py b/copyleaks/clients/writing_assistant_client.py
new file mode 100644
index 0000000..8ad7028
--- /dev/null
+++ b/copyleaks/clients/writing_assistant_client.py
@@ -0,0 +1,92 @@
+
+'''
+ The MIT License(MIT)
+ 
+ Copyright(c) 2016 Copyleaks LTD (https://copyleaks.com)
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+'''
+
+import requests
+from copyleaks.consts import Consts
+from copyleaks.exceptions.command_error import CommandError
+from copyleaks.exceptions.under_maintenance_error import UnderMaintenanceError
+from copyleaks.helpers.copyleaks_client_helper import CopyleaksClientHelper
+
+class _WritingAssistantClient:
+    @staticmethod
+    def __submit(url, auth_token, scan_id, submission):
+        assert url and scan_id and submission
+
+        CopyleaksClientHelper.verify_auth_token(auth_token)
+
+        headers = {
+            'Content-Type': 'application/json',
+            'User-Agent': Consts.USER_AGENT,
+            'Authorization': f"Bearer {auth_token['access_token']}"
+        }
+        json = submission.toJSON()
+        response = requests.post(url, headers=headers, data=json)
+        if response.ok:
+            return response.json()
+        elif response.status_code == 503:
+            raise UnderMaintenanceError()
+        else:
+            raise CommandError(response)
+        
+    @staticmethod
+    def submit_text(auth_token, scan_id, submission):
+        '''
+            Use Copyleaks Writing Assistant to generate grammar, spelling and sentence corrections for a given text.
+            This endpoint will receive submitted text to be checked. The response will show the suggested corrections to the input text.
+
+            Raises:
+                `CommandError`: Server reject the request. See response status code, headers and content for more info.
+                `UnderMaintenanceError`: Copyleaks servers are unavailable for maintenance. We recommend to implement exponential backoff algorithm as described here: https://api.copyleaks.com/documentation/v3/exponential-backoff
+        '''
+        url = f"{Consts.API_SERVER_URI}/v1/writing-feedback/{scan_id}/check"
+        return _WritingAssistantClient.__submit(url, auth_token, scan_id, submission)
+    
+    @staticmethod
+    def get_correction_types(language_code):
+        '''
+            Get a list of correction types supported within the Writing Assistant API. 
+            Correction types apply to all supported languages. 
+            The supplied language code for this request is used to determine the language of the texts returned.
+
+            Raises:
+                `CommandError`: Server reject the request. See response status code, headers and content for more info.
+                `UnderMaintenanceError`: Copyleaks servers are unavailable for maintenance. We recommend to implement exponential backoff algorithm as described here: https://api.copyleaks.com/documentation/v3/exponential-backoff
+
+            Returns:
+                List of supported correction types.
+        '''
+
+        url = f"{Consts.API_SERVER_URI}/v1/writing-feedback/correction-types/{language_code}"
+        headers = {
+            'User-Agent': Consts.USER_AGENT
+        }
+
+        response = requests.get(url, headers=headers)
+        if response.ok:
+            return response.json()
+        elif response.status_code == 503:
+            raise UnderMaintenanceError()
+        else:
+            raise CommandError(response.content)
diff --git a/copyleaks/copyleaks.py b/copyleaks/copyleaks.py
index 941236e..3dd4f3d 100644
--- a/copyleaks/copyleaks.py
+++ b/copyleaks/copyleaks.py
@@ -33,10 +33,15 @@
 from copyleaks.exceptions.rate_limit_error import RateLimitError
 from copyleaks.exceptions.auth_expired_error import AuthExipredError
 from enum import Enum
+from copyleaks.clients.ai_detection_client import _AIDetectionClient
+from copyleaks.clients.writing_assistant_client import _WritingAssistantClient
 
 
 class Copyleaks(object):
 
+    WritingAssistantClient = _WritingAssistantClient
+    AiDetectionClient = _AIDetectionClient
+    
     @staticmethod
     def set_identity_uri(uri):
         '''
diff --git a/copyleaks/helpers/__init__.py b/copyleaks/helpers/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/copyleaks/helpers/copyleaks_client_helper.py b/copyleaks/helpers/copyleaks_client_helper.py
new file mode 100644
index 0000000..9934b2e
--- /dev/null
+++ b/copyleaks/helpers/copyleaks_client_helper.py
@@ -0,0 +1,24 @@
+from datetime import datetime, timedelta
+import dateutil.parser
+import pytz
+from copyleaks.exceptions.auth_expired_error import AuthExipredError
+
+class CopyleaksClientHelper:
+    @staticmethod
+    def verify_auth_token(auth_token):
+        '''
+            Verify that Copyleaks authentication token is exists and not expired.
+
+            Parameters:
+                auth_token: Copyleaks authentication token
+
+            Raises:
+                `AuthExipredError`: authentication expired. Need to login again.
+        '''
+        assert auth_token and auth_token['.expires'] and auth_token['access_token']
+
+        now = pytz.UTC.localize(datetime.utcnow() + timedelta(0, 5 * 60))  # adds 5 minutes ahead for a safety shield.
+        upTo = dateutil.parser.parse(auth_token['.expires'])
+
+        if upTo <= now:
+            raise AuthExipredError()  # expired
diff --git a/copyleaks/models/submit/ai_detection_document.py b/copyleaks/models/submit/ai_detection_document.py
new file mode 100644
index 0000000..09a0dbd
--- /dev/null
+++ b/copyleaks/models/submit/ai_detection_document.py
@@ -0,0 +1,72 @@
+'''
+ The MIT License(MIT)
+
+ Copyright(c) 2016 Copyleaks LTD (https://copyleaks.com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+'''
+
+from abc import ABC
+import json
+
+class AiDetectionDocument(ABC):
+    def __init__(self, text):
+        assert text
+        self.text = text
+
+    def get_text(self):
+        return self.text
+
+    def set_text(self, value):
+        assert value
+        self.text = value
+
+    def get_sandbox(self):
+        return self.sandbox
+
+    def set_sandbox(self, value):
+        self.sandbox = value
+
+    def toJSON(self):
+        return json.dumps(self, default=lambda o: o.__dict__,
+                          sort_keys=True, indent=4)
+
+
+class NaturalLanguageDocument(AiDetectionDocument):
+    def __init__(self, text):
+        super().__init__(text)
+
+    def get_language(self):
+        return self.language
+
+    def set_language(self, value):
+        self.language = value
+
+
+class SourceCodeDocument(AiDetectionDocument):
+    def __init__(self, text, filename):
+        super().__init__(text)
+        self.filename = filename
+
+    def get_filename(self):
+        return self.filename
+
+    def set_filename(self, value):
+        assert value
+        self.filename = value
diff --git a/copyleaks/models/submit/score_weights.py b/copyleaks/models/submit/score_weights.py
new file mode 100644
index 0000000..fe79d86
--- /dev/null
+++ b/copyleaks/models/submit/score_weights.py
@@ -0,0 +1,52 @@
+'''
+ The MIT License(MIT)
+
+ Copyright(c) 2016 Copyleaks LTD (https://copyleaks.com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+'''
+
+class ScoreWeights:
+    def get_grammar_score_weight(self):
+        return self.grammarScoreWeight
+
+    def set_grammar_score_weight(self, value):
+        assert value
+        self.grammarScoreWeight = value
+
+    def get_mechanics_score_weight(self):
+        return self.mechanicsScoreWeight
+
+    def set_mechanics_score_weight(self, value):
+        assert value
+        self.mechanicsScoreWeight = value
+
+    def get_sentence_structure_score_weight(self):
+        return self.sentenceStructureScoreWeight
+
+    def set_sentence_structure_score_weight(self, value):
+        assert value
+        self.sentenceStructureScoreWeight = value
+
+    def get_word_choice_score_weight(self):
+        return self.wordChoiceScoreWeight
+
+    def set_word_choice_score_weight(self, value):
+        self.wordChoiceScoreWeight = value
+        assert value
diff --git a/copyleaks/models/submit/writing_assistant_document.py b/copyleaks/models/submit/writing_assistant_document.py
new file mode 100644
index 0000000..8e3c361
--- /dev/null
+++ b/copyleaks/models/submit/writing_assistant_document.py
@@ -0,0 +1,63 @@
+'''
+ The MIT License(MIT)
+
+ Copyright(c) 2016 Copyleaks LTD (https://copyleaks.com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+'''
+
+import json
+
+class WritingAssistantDocument():
+
+    def __init__(self, text):
+        assert text
+        self.text = text
+        
+    def get_text(self):
+        return self.text
+
+    def set_text(self, value):
+        assert value
+        self.text = value
+
+    def get_sandbox(self):
+        return self.sandbox
+
+    def set_sandbox(self, value):
+        assert value
+        self.sandbox = value
+
+    def get_language(self):
+        return self.language
+
+    def set_language(self, value):
+        assert value
+        self.language = value
+
+    def get_score(self):
+        return self.score
+
+    def set_score(self, value):
+        assert value
+        self.score = value
+
+    def toJSON(self):
+        return json.dumps(self, default=lambda o: o.__dict__,
+                          sort_keys=True, indent=4)

From 162e2b1033492ef213a6ee5dd74b5731f8688095 Mon Sep 17 00:00:00 2001
From: Elazarcl <elazarb@copyleaks.com>
Date: Thu, 5 Sep 2024 14:55:05 +0300
Subject: [PATCH 2/3] spacing fix

spacing fix
---
 copyleaks/clients/ai_detection_client.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/copyleaks/clients/ai_detection_client.py b/copyleaks/clients/ai_detection_client.py
index 3d2b5d1..0fbc679 100644
--- a/copyleaks/clients/ai_detection_client.py
+++ b/copyleaks/clients/ai_detection_client.py
@@ -64,7 +64,7 @@ def submit_natural_language(auth_token, scan_id, submission):
         url = f"{Consts.API_SERVER_URI}/v2/writer-detector/{scan_id}/check"
         return _AIDetectionClient.__submit(url, auth_token, scan_id, submission)
     
-    
+
     @staticmethod
     def submit_source_code(auth_token, scan_id, submission):
         '''
@@ -78,4 +78,4 @@ def submit_source_code(auth_token, scan_id, submission):
                 `UnderMaintenanceError`: Copyleaks servers are unavailable for maintenance. We recommend to implement exponential backoff algorithm as described here: https://api.copyleaks.com/documentation/v3/exponential-backoff
         '''
         url = f"{Consts.API_SERVER_URI}/v2/writer-detector/source-code/{scan_id}/check"
-        return _AIDetectionClient.__submit(url, auth_token, scan_id, submission)
\ No newline at end of file
+        return _AIDetectionClient.__submit(url, auth_token, scan_id, submission)

From aa6b7f9df6a93e64fb175bc61b579e69c53a179f Mon Sep 17 00:00:00 2001
From: Elazarcl <elazarb@copyleaks.com>
Date: Mon, 9 Sep 2024 16:45:45 +0300
Subject: [PATCH 3/3] add tests for ai detector and writing feedback

add tests for ai detector and writing feedback
---
 example.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/example.py b/example.py
index 2f770d0..b627bb5 100644
--- a/example.py
+++ b/example.py
@@ -26,9 +26,12 @@
 import random
 from copyleaks.copyleaks import Copyleaks
 from copyleaks.exceptions.command_error import CommandError
+from copyleaks.models.submit.ai_detection_document import NaturalLanguageDocument, SourceCodeDocument
 from copyleaks.models.submit.document import FileDocument, UrlDocument, OcrFileDocument
 from copyleaks.models.submit.properties.scan_properties import ScanProperties
 from copyleaks.models.export import *
+from copyleaks.models.submit.score_weights import ScoreWeights
+from copyleaks.models.submit.writing_assistant_document import WritingAssistantDocument
 # Register on https://api.copyleaks.com and grab your secret key (from the dashboard page).
 EMAIL_ADDRESS = 'your@email.addresss'
 KEY = '00000000-0000-0000-0000-000000000000'
@@ -108,4 +111,50 @@
 # # generate a pdf report:
 #pdf = Pdf() # Creating instance of Pdf.
 #pdf.set_create(True) # Setting the create pdf to True to generate PDF report.
-#scan_properties.set_pdf(pdf) # Will generate PDF report.
\ No newline at end of file
+#scan_properties.set_pdf(pdf) # Will generate PDF report.
+
+
+# This example is going to use the AI detector client to detect ai in text
+sample_text = "Lions are social animals, living in groups called prides, typically consisting of several females, their offspring, and a few males. Female lions are the primary hunters, working together to catch prey. Lions are known for their strength, teamwork, and complex social structures."
+natural_language_submission = NaturalLanguageDocument(sample_text)
+natural_language_submission.set_sandbox(True)
+response = Copyleaks.AiDetectionClient.submit_natural_language(auth_token, scan_id, natural_language_submission)
+print(response)
+
+
+# This example is going to use the AI detector client to detect ai in source code
+sample_code = (
+    "def add(a, b):\n"
+    "    return a + b\n"
+    "\n"
+    "def multiply(a, b):\n"
+    "    return a * b\n"
+    "\n"
+    "def main():\n"
+    "    x = 5\n"
+    "    y = 10\n"
+    "    sum_result = add(x, y)\n"
+    "    product_result = multiply(x, y)\n"
+    "    print(f'Sum: {sum_result}')\n"
+    "    print(f'Product: {product_result}')\n"
+    "\n"
+    "if __name__ == '__main__':\n"
+    "    main()"
+)
+source_code_submission = SourceCodeDocument(sample_text, "example.py")
+source_code_submission.set_sandbox(True)
+response = Copyleaks.AiDetectionClient.submit_natural_language(auth_token, scan_id, source_code_submission)
+print(response)
+
+
+# This example is going to use the WritingAssistant client to get feedback on text
+score_weight = ScoreWeights()
+score_weight.set_grammar_score_weight(0.2)
+score_weight.set_mechanics_score_weight(0.3)
+score_weight.set_sentence_structure_score_weight(0.5)
+score_weight.set_word_choice_score_weight(0.4)
+submission = WritingAssistantDocument(sample_text)
+submission.set_score(score_weight)
+submission.set_sandbox(True)
+response = Copyleaks.WritingAssistantClient.submit_text(auth_token, scan_id, submission)
+print(response)