diff --git a/RELEASE.md b/RELEASE.md index 3d885c7..e5af59c 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -5,20 +5,20 @@ The full process for cutting a release is as follows: 0. Checkout a new branch: - `git checkout -b 0.9.9-beta.4` # 1.0.0-release + `git checkout -b 0.9.9-beta.5` # 1.0.0-release 1. Python / Pip Bumpversion `pip3 install bumpversion` - `bumpversion --current-version 0.9.9-beta.4 minor setup.py xumm/__init__.py` + `bumpversion --current-version 0.9.9-beta.5 minor setup.py xumm/__init__.py` 2. Change the version in the setup.py file: - `VERSION = "v0.9.9-beta.4"` + `VERSION = "0.9.9-beta.5"` 3. Add, and commit the changes, push up the branch, and open a PR: `git add .` - `git commit -m 'RELEASE 0.9.9-beta.4'` + `git commit -m 'RELEASE 0.9.9-beta.5'` `git push --set-upstream origin HEAD` 4. Open PR request @@ -29,13 +29,13 @@ The full process for cutting a release is as follows: `git checkout main` 5. Delete `main` branch (Optional): - `git branch -d 0.9.9-beta.4` + `git branch -d 0.9.9-beta.5` 5. Make a new Git tag that matches the new version (make sure it is associated with the right commit SHA): FIXUP - `git tag -a 0.9.9-beta.4 -m "cut 0.9.9-beta.4"` + `git tag -a 0.9.9-beta.5 -m "cut 0.9.9-beta.5"` 7. Push up the tag from `main`: - `git push origin 0.9.9-beta.4` + `git push origin 0.9.9-beta.5` ## Packaging & Releasing @@ -50,8 +50,8 @@ Build Repo ``` dist/ - xumm-sdk-py-dangell-0.9.9-beta.4-py3-none-any.whl - xumm-sdk-py-dangell-0.9.9-beta.4.tar.gz + xumm-sdk-py-dangell-0.9.9-beta.5-py3-none-any.whl + xumm-sdk-py-dangell-0.9.9-beta.5.tar.gz ``` Install Twine diff --git a/pyproject.toml b/pyproject.toml index 6d86d2f..fed6824 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,9 +2,5 @@ requires=[ "setuptools>=42", "wheel", - "requests >= 2.27.1", - "websocket-client >= 1.2.3", - "six >= 1.16.0", - "python-dotenv >= 0.19.2" ] build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/setup.py b/setup.py index 5d24b1f..b81acdf 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from codecs import open NAME = "xumm-sdk-py-dangell7" -VERSION = "v0.9.9-beta.4" +VERSION = "0.9.9-beta.5" # To install the library, run the following # # python setup.py install @@ -25,17 +25,16 @@ long_description=long_description, long_description_content_type='text/markdown', license='MIT', - author='xrpl-labs', + author='XRPL-Labs', author_email='support@xrpl-labs.com', - url='https://github.com/CASL-AE/xumm-sdk-py', - packages=[ - 'xumm', - 'xumm.resource', - 'xumm.resource.types', - 'xumm.resource.types.xumm_api', - 'xumm.resource.types.meta', - 'xumm.resource.types.payload', - 'xumm.resource.types.storage' + url='https://github.com/XRPL-Labs/xumm-sdk-py', + packages=['xumm'], + include_package_data=True, + install_requires=[ + "requests >= 2.27.1", + "websocket-client >= 1.2.3", + "six >= 1.16.0", + "python-dotenv >= 0.19.2" ], test_suite='pytest', tests_require=['pytest'], diff --git a/tests/fixtures/xumm_api.py b/tests/fixtures/xumm_api.py index 248d027..f2c2d6f 100644 --- a/tests/fixtures/xumm_api.py +++ b/tests/fixtures/xumm_api.py @@ -8,7 +8,6 @@ def to_match_object(model_object: Any) -> bool: try: return model_object.model_check() except Exception as e: - print(e) return False diff --git a/tests/test_common.py b/tests/test_common.py index e065cdf..efb4c5d 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -52,7 +52,7 @@ def test_xumm_ping(cls, mock_get): mock_get.return_value = Mock(status_code=200) mock_get.return_value.json.return_value = cls.json_fixtures['ping']['pong'] - cls.assertEqual(sdk.ping().to_dict(), cls.json_fixtures['ping']['pong']) + cls.assertEqual(sdk.ping().to_dict(), cls.json_fixtures['ping']['pong']['auth']) @patch('xumm.client.requests.get') def test_invalid_credentials(cls, mock_get): diff --git a/tests/types/meta/test_application_details.py b/tests/types/meta/test_application_details.py index ae0c2e9..68c3a49 100644 --- a/tests/types/meta/test_application_details.py +++ b/tests/types/meta/test_application_details.py @@ -33,4 +33,4 @@ def test_application_details_fail(cls): ApplicationDetails(**dict) cls.fail("ApplicationDetails: raised Exception unexpectedly!") except Exception as e: - cls.assertEqual(str(e), "Invalid value for `uuidv4`, must be a ``") \ No newline at end of file + cls.assertEqual(str(e), "Invalid value: 1 for `uuidv4`, must be a `` found: ") \ No newline at end of file diff --git a/tests/types/meta/test_curated_asset_response.py b/tests/types/meta/test_curated_asset_response.py index 1a697ca..9411ae8 100644 --- a/tests/types/meta/test_curated_asset_response.py +++ b/tests/types/meta/test_curated_asset_response.py @@ -80,4 +80,4 @@ def test_curated_asset_response_fail(cls): CuratedAssetsResponse(**dict) cls.fail("CuratedAssetsResponse: raised Exception unexpectedly!") except Exception as e: - cls.assertEqual(str(e), "Invalid value for `name`, must be a ``") \ No newline at end of file + cls.assertEqual(str(e), "Invalid value: 1 for `name`, must be a `` found: ") \ No newline at end of file diff --git a/tests/types/meta/test_kyc_info_response.py b/tests/types/meta/test_kyc_info_response.py index 1e83de6..1bede86 100644 --- a/tests/types/meta/test_kyc_info_response.py +++ b/tests/types/meta/test_kyc_info_response.py @@ -25,4 +25,4 @@ def test_kyc_info_response_fail(cls): KycInfoResponse(**dict) cls.fail("KycInfoResponse: raised Exception unexpectedly!") except Exception as e: - cls.assertEqual(str(e), "Invalid value for `account`, must be a ``") \ No newline at end of file + cls.assertEqual(str(e), "Invalid value: 1 for `account`, must be a `` found: ") \ No newline at end of file diff --git a/tests/types/meta/test_pong_response.py b/tests/types/meta/test_pong_response.py index 80f7385..54044d7 100644 --- a/tests/types/meta/test_pong_response.py +++ b/tests/types/meta/test_pong_response.py @@ -36,4 +36,4 @@ def test_pong_response_fail(cls): PongResponse(**dict) cls.fail("PongResponse: raised Exception unexpectedly!") except Exception as e: - cls.assertEqual(str(e), "Invalid value for `pong`, must be a ``") \ No newline at end of file + cls.assertEqual(str(e), "Invalid value: true for `pong`, must be a `` found: ") \ No newline at end of file diff --git a/tests/types/meta/test_xrpl_transaction.py b/tests/types/meta/test_xrpl_transaction.py index 11a23a6..ce7003d 100644 --- a/tests/types/meta/test_xrpl_transaction.py +++ b/tests/types/meta/test_xrpl_transaction.py @@ -55,6 +55,6 @@ def test_xrpl_tx_response_fail(cls): } try: XrplTransaction(**dict) - cls.fail("PongResponse: raised Exception unexpectedly!") + cls.fail("XrplTransaction: raised Exception unexpectedly!") except Exception as e: - cls.assertEqual(str(e), "Invalid value for `txid`, must be a ``") \ No newline at end of file + cls.assertEqual(str(e), "Invalid value: 1 for `txid`, must be a `` found: ") \ No newline at end of file diff --git a/xumm/__init__.py b/xumm/__init__.py index 7b9447a..a287ad6 100644 --- a/xumm/__init__.py +++ b/xumm/__init__.py @@ -1,8 +1,5 @@ import os -from dotenv import load_dotenv -load_dotenv() - api_base = 'https://xumm.app/api/v1/' api_key = os.environ.get('XUMM_APIKEY', None) api_secret = os.environ.get('XUMM_APISECRET', None) diff --git a/xumm/resource/__init__.py b/xumm/resource/__init__.py index cc0971a..cb3515f 100644 --- a/xumm/resource/__init__.py +++ b/xumm/resource/__init__.py @@ -9,6 +9,9 @@ from xumm import client +# import logging +# logging.basicConfig(level=logging.ERROR) + class BaseResource(object): @@ -60,8 +63,13 @@ def sanity_check(cls, kwargs) -> None: # Error if value is not instance of attribute type if not isinstance(value, is_type): raise ValueError( - "Invalid value for `{}`, " - "must be a `{}`".format(attr, is_type) + "Invalid value: {} for `{}`, " + "must be a `{}` found: {}".format( + value, + attr, + is_type, + type(value) + ) ) # Error if attribute is required and value is @@ -85,7 +93,6 @@ def sanity_check(cls, kwargs) -> None: def to_dict(cls) -> Dict[str, object]: """Returns the model properties as a dict""" result = {} - print(cls.__class__) for attr, _ in six.iteritems(cls.attribute_map): value = getattr(cls, attr) @@ -105,6 +112,7 @@ def to_dict(cls) -> Dict[str, object]: )) else: result[attr] = value + if issubclass(cls.__class__, dict): for key, value in cls.items(): result[key] = value @@ -127,7 +135,7 @@ def to_str(self) -> str: :rtype: str """ - return pprint.pformat(self.to_dict()) + return pprint.pformat(self.__class__) def __repr__(self) -> str: """For `print` and `pprint`""" @@ -135,6 +143,13 @@ def __repr__(self) -> str: def __eq__(self, other) -> bool: """Returns true if both objects are equal""" + + if type(other) != type(self): + return False + + if isinstance(self, list): + return self == other + return self.__dict__ == other.__dict__ def __ne__(self, other) -> bool: diff --git a/xumm/resource/base.py b/xumm/resource/base.py index 9b534de..c40a2b7 100644 --- a/xumm/resource/base.py +++ b/xumm/resource/base.py @@ -72,7 +72,7 @@ def ping(cls) -> PongResponse: """ res = client.get(PingResource.get_url()) - return PongResponse(**res) + return PongResponse(**res).auth def get_kyc_status( cls, diff --git a/xumm/resource/payload.py b/xumm/resource/payload.py index bce191a..0864b44 100644 --- a/xumm/resource/payload.py +++ b/xumm/resource/payload.py @@ -58,6 +58,7 @@ async def _resolved(cls): continue if cls.error: + # return {'data': str(cls.error)} return None return cls.data @@ -176,14 +177,17 @@ def create( :return: The XummPostPayloadResponse of this XummPostPayloadResponse. # noqa: E501 :rtype: XummPostPayloadResponse """ + direct_tx = 'TransactionType' in payload and 'txjson' not in payload + clone_payload = {'txjson': payload} if direct_tx else payload + if not return_errors: try: - res = client.post(cls.post_url(), payload) + res = client.post(cls.post_url(), clone_payload) return XummPostPayloadResponse(**res) except: # noqa: E722 return None - res = client.post(cls.post_url(), payload) + res = client.post(cls.post_url(), clone_payload) return XummPostPayloadResponse(**res) @classmethod @@ -242,51 +246,54 @@ async def subscribe( callback_promise = CallbackPromise() payload_details = cls.resolve_payload(payload) - def on_message(json_data): - if json_data and cls._callback and 'devapp_fetched' not in json_data: # noqa: E501 - try: - callback_result = cls._callback({ - 'uuid': payload_details.meta.uuid, - 'data': json_data, - 'resolve': callback_promise._resolve, - 'payload': payload_details - }) - - if callback_result: - callback_promise._resolve(callback_result) - - except Exception as e: - logger.debug( - 'Payload {}: Callback exception: {}' - .format(payload_details.meta.uuid, e) - ) - - def on_error(error): - logger.debug( - 'Payload {}: Subscription error: {}' - .format(payload_details.meta.uuid, error) - ) - cls._conn.disconnect() - callback_promise._reject(error) - # raise ValueError(error) - - # def on_close(ws, close_status_code, close_msg): - def on_close(): - logger.debug( - 'Payload {}: Subscription ended (WebSocket closed)' - .format(payload_details.meta.uuid) - ) - - def on_open(connection): - logger.debug( - 'Payload {}: Subscription active (WebSocket opened)' - .format(payload_details.meta.uuid) - ) + # callback_promise.promise.then(() => { + # cls._conn.disconnect() + # }) if payload_details: + + def on_open(connection): + logger.debug( + 'Payload {}: Subscription active (WebSocket opened)' + .format(payload_details.meta.uuid) + ) + + def on_message(json_data): + if json_data and cls._callback and 'devapp_fetched' not in json_data: # noqa: E501 + try: + callback_result = cls._callback({ + 'uuid': payload_details.meta.uuid, + 'data': json_data, + 'resolve': callback_promise._resolve, + 'payload': payload_details + }) + + if callback_result: + callback_promise._resolve(callback_result) + + except Exception as e: + logger.debug( + 'Payload {}: Callback error: {}' + .format(payload_details.meta.uuid, e) + ) + + def on_error(error): + logger.debug( + 'Payload {}: Subscription error: {}' + .format(payload_details.meta.uuid, error) + ) + cls._conn.disconnect() + callback_promise._reject(error) + + def on_close(): + logger.debug( + 'Payload {}: Subscription ended (WebSocket closed)' + .format(payload_details.meta.uuid) + ) + cls._callback = callback cls._conn = WSClient( - log_level=logging.ERROR if env == 'sandbox' else logging.ERROR, + log_level=logging.DEBUG if env == 'sandbox' else logging.ERROR, server='ws://localhost:8765' if env == 'sandbox' else 'wss://xumm.app/sign/{}'.format(payload_details.meta.uuid), # noqa: E501 on_response=on_message, on_error=on_error, @@ -314,12 +321,15 @@ async def create_and_subscribe( """Create payload and subscribe to a channel :returns: PayloadAndSubscription """ - created_payload = await cls.create(payload) + created_payload = cls.create(payload) if created_payload: subscription = await cls.subscribe(created_payload, callback) resp = { - 'created': created_payload, - **subscription + 'created': created_payload.to_dict(), + 'payload': subscription.payload.to_dict(), + 'resolve': subscription.resolve, + 'resolved': subscription.resolved, + 'websocket': subscription.websocket } return PayloadAndSubscription(**resp) raise ValueError('Error creating payload or subscribing to created payload') # noqa: E501 diff --git a/xumm/resource/types/meta/application_details.py b/xumm/resource/types/meta/application_details.py index 856d770..45c584b 100644 --- a/xumm/resource/types/meta/application_details.py +++ b/xumm/resource/types/meta/application_details.py @@ -246,6 +246,10 @@ class Quota(XummResource): attribute_map (dict): The key is attribute name and the value is json key in definition. """ + nullable = {} + + required = {} + model_types = { 'ratelimit': str } @@ -285,8 +289,8 @@ def ratelimit(cls, ratelimit: str): :param ratelimit: The ratelimit of this Quota. :type ratelimit: str """ - if ratelimit is None: - raise ValueError("Invalid value for `ratelimit`, must not be `None`") # noqa: E501 + # if ratelimit is None: + # raise ValueError("Invalid value for `ratelimit`, must not be `None`") # noqa: E501 cls._ratelimit = ratelimit