From 2ea6523a69bb1d6a84b7a386922b492bf8515337 Mon Sep 17 00:00:00 2001 From: DolphDev Date: Sun, 19 Sep 2021 22:56:33 -0400 Subject: [PATCH 1/6] 3.1.4 Code Commit --- docs/conf.py | 4 +- docs/pages/nationstates.rst | 2 + docs/pages/ratelimit.rst | 2 +- nationstates/exceptions.py | 13 ++- nationstates/info.py | 2 + nationstates/main.py | 7 +- nationstates/nsapiwrapper/exceptions.py | 8 +- nationstates/objects.py | 104 ++++++++++++++++-------- setup.py | 2 +- tests/test_call.py | 6 ++ 10 files changed, 103 insertions(+), 47 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index d7c9a29..91e0a18 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -57,9 +57,9 @@ # built documents. # # The short X.Y version. -version = '3.0.3' +version = '3.1' # The full version, including alpha/beta/rc tags. -release = '3.0.3.9' +release = '3.1.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/pages/nationstates.rst b/docs/pages/nationstates.rst index 3ec129e..5811cbe 100644 --- a/docs/pages/nationstates.rst +++ b/docs/pages/nationstates.rst @@ -84,6 +84,8 @@ You can view what each endpoint currently supports in it's magic methods by view >>> nationstates.get_shard {'get_customreligion', 'get_rcensus', 'get_banners', 'get_govtpriority', 'get_banner', 'get_census', 'get_gavote', 'get_wcensus', 'get_firstlogin', 'get_notable', 'get_admirable', 'get_foundedtime', 'get_category', 'get_customleader', 'get_flag', 'get_currency', 'get_endorsements', 'get_lastlogin', 'get_region', 'get_religion', 'get_capital', 'get_name', 'get_type', 'get_happenings', 'get_crime', 'get_govtdesc', 'get_majorindustry', 'get_influence', 'get_customcapital', 'get_tax', 'get_tgcanrecruit', 'get_demonym2', 'get_legislation', 'get_poorest', 'get_wa', 'get_sectors', 'get_deaths', 'get_dbid', 'get_policies', 'get_scvote', 'get_lastactivity', 'get_demonym', 'get_freedom', 'get_animal', 'get_factbooklist', 'get_industrydesc', 'get_income', 'get_population', 'get_founded', 'get_richest', 'get_demonym2plural', 'get_gdp', 'get_dispatches', 'get_publicsector', 'get_fullname', 'get_motto', 'get_tgcancampaign', 'get_govt', 'get_sensibilities', 'get_dispatchlist', 'get_wabadges', 'get_factbooks', 'get_animaltrait', 'get_leader'} + + Is pynationstates thread safe? ============================== diff --git a/docs/pages/ratelimit.rst b/docs/pages/ratelimit.rst index 98f2ee3..6b056c5 100644 --- a/docs/pages/ratelimit.rst +++ b/docs/pages/ratelimit.rst @@ -8,7 +8,7 @@ The Nationstates package constains an automatic ratelimiter. It's a simple imple How to use the Rate Limiter --------------------------- -The Rate Limit system is completely automatic, and will simply ``time.sleep()`` your thread if it thinks your getting close to the api limit. Each thread keeps tracks of its own requests, so it can leave this period as soon as possible. Due to the possibility of multiple threads, this library slightly lowers the amount of requests per 30 second block to prevent accidental breaches of the ratelimit. +The Rate Limit system is completely automatic, and will simply ``time.sleep()`` your thread if it thinks your getting close to the api limit. Each process keeps tracks of its own requests, so it can leave this period as soon as possible. Due to the possibility of multiple processes, this library slightly lowers the amount of requests per 30 second block to prevent accidental breaches of the ratelimit. Disabling the Rate Limiter -------------------------- diff --git a/nationstates/exceptions.py b/nationstates/exceptions.py index ff1271e..a344cb0 100644 --- a/nationstates/exceptions.py +++ b/nationstates/exceptions.py @@ -8,14 +8,21 @@ NotFound, APIRateLimitBan, APIUsageError, - DispatchTooRecent, + ActionTooRecent, InternalServerError, CloudflareServerError, BadRequest, ServerError, - BadResponse + BadResponse, + BetaDisabled ) class NotAuthenticated(Exception): """If an action requires Authentication but the object isn't Authenticated""" - pass \ No newline at end of file + pass + +class BetaDisabled(Exception): + """Beta Disabled""" + message = 'This Feature is marked as Beta. Pass True to Nationstates() object to enable this functionality' + +DispatchTooRecent = ActionTooRecent \ No newline at end of file diff --git a/nationstates/info.py b/nationstates/info.py index a4dd24d..7eb69e4 100644 --- a/nationstates/info.py +++ b/nationstates/info.py @@ -149,5 +149,7 @@ ) dispatch_to_soon = 'Your nation is attempting to issue many announcements in a short period of time. Please wait for the international press to catch their breath, then try again.' +rmb_to_soon = 'To prevent spam, you cannot post a message so soon after your previous one. Please try again in a few moments.' + diff --git a/nationstates/main.py b/nationstates/main.py index 78d632a..ad9f873 100644 --- a/nationstates/main.py +++ b/nationstates/main.py @@ -6,8 +6,8 @@ class Nationstates: def __init__(self, user_agent, version="11", ratelimit_sleep=True, ratelimit_limit=40, ratelimit_timeframe=30, ratelimit_sleep_time=4, ratelimit_maxsleeps=10, ratelimit_enabled=True, do_retry=True, - retry_sleep=5, max_retries=5, use_nsdict=True, use_session=True, threading_mode=False, - max_ongoing_requests=20): + retry_sleep=5, max_retries=5, use_nsdict=True, use_session=True, threading_mode=True, + max_ongoing_requests=20, enable_beta=False): self.api = nsapiwrapper.Api(user_agent, version=version, ratelimit_sleep=ratelimit_sleep, ratelimit_sleep_time=ratelimit_sleep_time, @@ -15,11 +15,12 @@ def __init__(self, user_agent, version="11", ratelimit_sleep=True, ratelimit_within=ratelimit_timeframe, ratelimit_maxsleeps=ratelimit_maxsleeps, ratelimit_enabled=ratelimit_enabled, - use_session=use_session and threading_mode) + use_session=use_session and not threading_mode) self.do_retry = do_retry self.retry_sleep = retry_sleep self.max_retries = max_retries self.use_nsdict = use_nsdict + self.enable_beta = enable_beta def nation(self, nation_name, password=None, autologin=None): """Setup access to the Nation API with the Nation object diff --git a/nationstates/nsapiwrapper/exceptions.py b/nationstates/nsapiwrapper/exceptions.py index 2367220..997bc04 100644 --- a/nationstates/nsapiwrapper/exceptions.py +++ b/nationstates/nsapiwrapper/exceptions.py @@ -36,7 +36,8 @@ class APIRateLimitBan(APIError): class APIUsageError(APIError): pass -class DispatchTooRecent(APIUsageError): + +class ActionTooRecent(APIUsageError): pass class ServerError(APIError): @@ -46,6 +47,7 @@ class ServerError(APIError): class ConflictError(ServerError): """ConflictError from Server""" pass + class InternalServerError(ServerError): pass @@ -56,6 +58,8 @@ class BadResponse(ServerError): # When NS returns an odd response we can't otherwise classify pass - class BadRequest(APIError): + pass + +class BetaDisabled(NSBaseError): pass \ No newline at end of file diff --git a/nationstates/objects.py b/nationstates/objects.py index 5f946a2..c3f2b41 100644 --- a/nationstates/objects.py +++ b/nationstates/objects.py @@ -6,9 +6,9 @@ from time import sleep from functools import wraps -from .exceptions import ConflictError, InternalServerError, CloudflareServerError, APIUsageError, NotAuthenticated, BadResponse, DispatchTooRecent +from .exceptions import ConflictError, InternalServerError, CloudflareServerError, APIUsageError, NotAuthenticated, BadResponse, DispatchTooRecent, BetaDisabled, ActionTooRecent, NotFound from requests.exceptions import ConnectionError -from .info import nation_shards, region_shards, world_shards, wa_shards, individual_cards_shards, dispatch_to_soon +from .info import nation_shards, region_shards, world_shards, wa_shards, individual_cards_shards, dispatch_to_soon, rmb_to_soon import html @@ -44,17 +44,30 @@ def dispatch_token(resp, use_exception): return False return data['success'] -def dispatch_error_check(resp, use_exception): +def dispatch_error_check(resp, use_exception, custom_message='PlaceHolder'): + if custom_message: + checks = {dispatch_to_soon, rmb_to_soon, custom_message} + else: + checks = {dispatch_to_soon, rmb_to_soon} + data = resp['data'][Nation.api_name] if data.get('error'): if use_exception: - if data['error'] == dispatch_to_soon: - raise DispatchTooRecent(data['error']) + if data['error'] in checks: + raise ActionTooRecent(data['error']) raise APIUsageError(data['error']) else: return False return True +def action_full_response(api, final_resp, full_response): + if final_resp is False: + return False + elif full_response: + return final_resp + else: + return final_resp['data'][api.api_name] + class NSDict(dict): """Specialized Dict""" @@ -219,6 +232,10 @@ def __get_shards__(self, *args, full_response=False, use_post=False): resp = self.request(shards=args, full_response=full_response, use_post=False) return resp + def _check_beta(self): + if not self.api_mother.enable_beta: + raise BetaDisabled('Beta Endpoints are not enabled. Pass enable_beta = True to nationstates.Nationstates to supress') + def get_shards(self, *args, full_response=False): """Get Shards""" return self.__get_shards__(*args, full_response=full_response, use_post=False) @@ -268,6 +285,13 @@ def _check_auth(self): if not self.is_auth: raise NotAuthenticated("Action requires authentication") + def exists(self): + try: + self.get_shards('name') + return True + except NotFound: + return False + def authenticate(self, password=None, autologin=None): self._set_apiwrapper(self._determine_api(self.nation_name, password, autologin)) return self @@ -287,33 +311,40 @@ def pick_issue(self, issue_id, option, full_response=False, raise_exception_if_f else: return resp["data"][self.api_name] - def _dispatch_request(self, dispatch, use_exception=True, **kwargs): - self._check_auth() - token_resp = self.command('dispatch', dispatch=dispatch, mode='prepare', nation=self.nation_name, full_response=True, use_post=True, **kwargs) + + def _prepare_execute_request(self, name, bad_message, use_exception=True, **kwargs): + token_resp = self.command(name, mode='prepare', nation=self.nation_name, full_response=True, use_post=True, **kwargs) token = dispatch_token(token_resp, use_exception) if use_exception is False and token is False: return False - final_resp = self.command('dispatch', dispatch=dispatch, mode='execute', token=token, nation=self.nation_name, full_response=True, use_post=True, **kwargs) - check = dispatch_error_check(final_resp, use_exception) - # Check was False - we need to return False down the line + final_resp = self.command(name, mode='execute', nation=self.nation_name, token=token, full_response=True, use_post=True, **kwargs) + check = dispatch_error_check(final_resp, use_exception, bad_message) if not check: return check else: return final_resp - def _dispatch(self, dispatch, use_exception=True, **kwargs): - limit = 10 - sleep_time = 5 + def execute_command(self, name, use_exception=True, limit=10, sleep_time=5, too_soon_message=None, **kwargs): + """ Executes a command that follows the prepare and execute paradigm """ last_exc = None while limit > 0: try: - return self._dispatch_request(dispatch, use_exception=use_exception, **kwargs) - except DispatchTooRecent as Exc: + return self._prepare_execute_request(name, too_soon_message, use_exception=use_exception, **kwargs) + except ActionTooRecent as Exc: limit = limit - 1 - sleep_thread(sleep_time) last_exc = Exc + sleep_thread(sleep_time) raise last_exc + def _dispatch(self, dispatch, use_exception=True, **kwargs): + if not self.api_mother.enable_beta: + print('Warning: Beta Features are not enabled, but due to backwards compatiblity this method is not disabled. Enable Beta Flag to supress this message') + self._check_auth() + + + kwargs['dispatch'] = dispatch + + return self.execute_command('dispatch', use_exception=use_exception, **kwargs) def create_dispatch(self, title=None, text=None, category=None, subcategory=None, full_response=False, use_exception=True): cant_be_none(title=title, text=text, category=category, subcategory=subcategory) @@ -321,12 +352,7 @@ def create_dispatch(self, title=None, text=None, category=None, subcategory=None final_resp = self._dispatch('add', title=title, text=text, category=category, subcategory=subcategory, use_exception=use_exception) - if final_resp is False: - return False - elif full_response: - return final_resp - else: - return final_resp['data'][self.api_name] + return action_full_response(self, final_resp, full_response) def edit_dispatch(self, dispatch_id=None, title=None, text=None, category=None, subcategory=None, full_response=False, use_exception=True): cant_be_none(dispatch_id=dispatch_id, title=title, text=text, category=category, subcategory=subcategory) @@ -334,24 +360,16 @@ def edit_dispatch(self, dispatch_id=None, title=None, text=None, category=None, final_resp = self._dispatch('edit', dispatchid=dispatch_id, title=title, text=text, category=category, subcategory=subcategory, use_exception=use_exception) - if final_resp is False: - return False - elif full_response: - return final_resp - else: - return final_resp['data'][self.api_name] + return action_full_response(self, final_resp, full_response) + def remove_dispatch(self, dispatch_id=None, full_response=False, use_exception=True): cant_be_none(dispatch_id=dispatch_id) final_resp = self._dispatch('remove', dispatchid=dispatch_id, use_exception=use_exception) - if final_resp is False: - return False - elif full_response: - return final_resp - else: - return final_resp['data'][self.api_name] + return action_full_response(self, final_resp, full_response) + def send_telegram(self, telegram=None, client_key=None, tgid=None, key=None): """Sends Telegram. Can either provide a telegram directly, or provide the api details and created internally @@ -367,6 +385,15 @@ def send_telegram(self, telegram=None, client_key=None, tgid=None, key=None): telegram = self.api_mother.telegram(client_key, tgid, key) telegram.send_telegram(self.nation_name) + def send_rmb(self, region=None, text=None, full_response=False): + self._check_beta() + self._check_auth() + cant_be_none(region=region, text=text) + if isinstance(region, Region): + region = region.region_name + final_resp = self.execute_command('rmbpost', nation_name=self.nation_name, region=region, text=text) + return action_full_response(self, final_resp, full_response) + def verify(self, checksum=None, token=None): """Wraps around the verify API""" cant_be_none(checksum=checksum, token=token) @@ -401,6 +428,13 @@ def __repr__(self): value=self.region_name, hexloc=hex(id(self)).upper().replace("X", "x")) + def exists(self): + try: + self.get_shards('name') + return True + except NotFound: + return False + @property def nations(self): resp = self._auto_shard("nations") diff --git a/setup.py b/setup.py index 8d42d3e..bbceae1 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ """ -version = '3.0.3.9' +version = '3.1.4' from setuptools import setup setup(name='nationstates', diff --git a/tests/test_call.py b/tests/test_call.py index 81d3371..4e43825 100644 --- a/tests/test_call.py +++ b/tests/test_call.py @@ -16,6 +16,7 @@ sep_api = ns.Nationstates(USERAGENT) joint_api = ns.Nationstates(USERAGENT) +joint_api_use_session = ns.Nationstates(USERAGENT, threading_mode=False) test_nation_nonauth = joint_api.nation(test_nation) test_auth_nation = joint_api.nation(test_nation, password=PASSWORD) test_nation_r = joint_api.nation(test_nation_r) @@ -24,6 +25,7 @@ issue_nation_3 = joint_api.nation('Pynationstates Issue Farm 3', password=PASSWORD) issue_nation_zero = joint_api.nation('pynationstates_0_issues_test_nation', password=PASSWORD) api_threads = ns.Nationstates(USERAGENT, threading_mode=True) +fake_nation = joint_api.nation('FAKE NATION 1 FAKE NATION 1 FAKE NATION 1 FAKE NATION 1') def grab_id(newfactbookresponse_text): @@ -230,6 +232,10 @@ def test_private_nation(self): except Exception as Err: self.fail(Err) + def test_exists(self): + assert fake_nation.exists() is False + assert test_nation.exists() + def test_create_dispatch(self): from datetime import datetime From 356cb28152ab41ac4f78752526a7d86df72377c8 Mon Sep 17 00:00:00 2001 From: DolphDev Date: Sun, 19 Sep 2021 23:30:17 -0400 Subject: [PATCH 2/6] Testing Update --- tests/test_call.py | 53 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/tests/test_call.py b/tests/test_call.py index 4e43825..aaf1a34 100644 --- a/tests/test_call.py +++ b/tests/test_call.py @@ -16,9 +16,12 @@ sep_api = ns.Nationstates(USERAGENT) joint_api = ns.Nationstates(USERAGENT) +joint_api_enable_beta = ns.Nationstates(USERAGENT, enable_beta=True) joint_api_use_session = ns.Nationstates(USERAGENT, threading_mode=False) test_nation_nonauth = joint_api.nation(test_nation) test_auth_nation = joint_api.nation(test_nation, password=PASSWORD) +test_auth_nation_BETA = joint_api_enable_beta.nation(test_nation, password=PASSWORD) + test_nation_r = joint_api.nation(test_nation_r) issue_nation_1 = joint_api.nation('Pynationstates Issue Farm 1', password=PASSWORD) issue_nation_2 = joint_api.nation('Pynationstates Issue Farm 2', password=PASSWORD) @@ -27,7 +30,6 @@ api_threads = ns.Nationstates(USERAGENT, threading_mode=True) fake_nation = joint_api.nation('FAKE NATION 1 FAKE NATION 1 FAKE NATION 1 FAKE NATION 1') - def grab_id(newfactbookresponse_text): part1 = newfactbookresponse_text.split('id=') return part1[1].split('">')[0] @@ -234,20 +236,36 @@ def test_private_nation(self): def test_exists(self): assert fake_nation.exists() is False - assert test_nation.exists() + assert test_auth_nation.exists() + + def test_create_dispatch(self): + from datetime import datetime + now = datetime.now + try: + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH TEST', text=str(now()), category=1, subcategory=105, full_response=True) + dispatch_id = grab_id(resp['data']['nation']['success']) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id, full_response=True) + + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH TEST', text=str(now()), category=1, subcategory=105, full_response=False) + dispatch_id = grab_id(resp.success) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id, full_response=True) + + + except Exception as Err: + self.fail(Err) def test_create_dispatch(self): from datetime import datetime now = datetime.now try: - resp = test_auth_nation.create_dispatch(title='AUTOMATED ADD DISPATCH TEST', text=str(now()), category=1, subcategory=105, full_response=True) + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH TEST', text=str(now()), category=1, subcategory=105, full_response=True) dispatch_id = grab_id(resp['data']['nation']['success']) - resp = test_auth_nation.remove_dispatch(dispatch_id=dispatch_id, full_response=True) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id, full_response=True) - resp = test_auth_nation.create_dispatch(title='AUTOMATED ADD DISPATCH TEST', text=str(now()), category=1, subcategory=105, full_response=False) + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH TEST', text=str(now()), category=1, subcategory=105, full_response=False) dispatch_id = grab_id(resp.success) - resp = test_auth_nation.remove_dispatch(dispatch_id=dispatch_id, full_response=True) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id, full_response=True) except Exception as Err: @@ -257,14 +275,14 @@ def test_edit_dispatch(self): from datetime import datetime now = datetime.now try: - resp = test_auth_nation.create_dispatch(title='AUTOMATED ADD DISPATCH EDIT TEST', text=str(now()), category=1, subcategory=105, full_response=False) + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH EDIT TEST', text=str(now()), category=1, subcategory=105, full_response=False) dispatch_id = grab_id(resp.success) - resp = test_auth_nation.edit_dispatch(dispatch_id=dispatch_id, title='EDIT TEST', text="THIS POST WAS LAST EDITED AT:" + str(now()), category=1, subcategory=111, full_response=False) - resp = test_auth_nation.remove_dispatch(dispatch_id=dispatch_id, full_response=True) - resp = test_auth_nation.create_dispatch(title='AUTOMATED ADD DISPATCH EDIT TEST', text=str(now()), category=1, subcategory=105, full_response=False) + resp = test_auth_nation_BETA.edit_dispatch(dispatch_id=dispatch_id, title='EDIT TEST', text="THIS POST WAS LAST EDITED AT:" + str(now()), category=1, subcategory=111, full_response=False) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id, full_response=True) + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH EDIT TEST', text=str(now()), category=1, subcategory=105, full_response=False) dispatch_id = grab_id(resp.success) - resp = test_auth_nation.edit_dispatch(dispatch_id=dispatch_id, title='EDIT TEST', text="THIS POST WAS LAST EDITED AT:" + str(now()), category=1, subcategory=111, full_response=True) - resp = test_auth_nation.remove_dispatch(dispatch_id=dispatch_id, full_response=True) + resp = test_auth_nation_BETA.edit_dispatch(dispatch_id=dispatch_id, title='EDIT TEST', text="THIS POST WAS LAST EDITED AT:" + str(now()), category=1, subcategory=111, full_response=True) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id, full_response=True) except Exception as Err: self.fail(Err) @@ -283,6 +301,17 @@ def test_remove_dispatch(self): self.fail(Err) + def test_send_rmb(self): + from datetime import datetime + now = datetime.now + try: + test_auth_nation.send_rmb(test_auth_nation.region, 'Circle CI: Automated Test') + + except Exception as Err: + self.fail(Err) + + + def test_telegram_send(self): from datetime import datetime import time From c3b3920d74ed9805b2f6d9173243a8763bfc1359 Mon Sep 17 00:00:00 2001 From: DolphDev Date: Sun, 19 Sep 2021 23:38:47 -0400 Subject: [PATCH 3/6] More Test Fixes --- nationstates/objects.py | 2 +- tests/test_call.py | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/nationstates/objects.py b/nationstates/objects.py index c3f2b41..d772632 100644 --- a/nationstates/objects.py +++ b/nationstates/objects.py @@ -234,7 +234,7 @@ def __get_shards__(self, *args, full_response=False, use_post=False): def _check_beta(self): if not self.api_mother.enable_beta: - raise BetaDisabled('Beta Endpoints are not enabled. Pass enable_beta = True to nationstates.Nationstates to supress') + raise BetaDisabled('Beta Endpoints are not enabled. Pass enable_beta = True to nationstates.Nationstates to suppress') def get_shards(self, *args, full_response=False): """Get Shards""" diff --git a/tests/test_call.py b/tests/test_call.py index aaf1a34..d0e34e9 100644 --- a/tests/test_call.py +++ b/tests/test_call.py @@ -43,6 +43,8 @@ def test_create_ns(self): except Exception as Err: self.fail(Err) + + class SeperateCallTest(unittest.TestCase): def test_nation_call(self): @@ -55,6 +57,22 @@ def test_nation_call(self): except Exception as Err: self.fail(Err) + def test_beta(self): + from datetime import datetime + now = datetime.now + try: + test_auth_nation_BETA._check_beta() + + except Exception as Err: + self.fail(Err) + + try: + test_auth_nation._check_beta() + self.fail(Err) + + except Exception as Err: + pass + def test_region_call(self): try: api = sep_api @@ -291,12 +309,12 @@ def test_remove_dispatch(self): from datetime import datetime now = datetime.now try: - resp = test_auth_nation.create_dispatch(title='AUTOMATED ADD DISPATCH REMOVE TEST', text=str(now()), category=1, subcategory=105, full_response=False) + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH REMOVE TEST', text=str(now()), category=1, subcategory=105, full_response=False) dispatch_id = grab_id(resp.success) - resp = test_auth_nation.remove_dispatch(dispatch_id=dispatch_id) - resp = test_auth_nation.create_dispatch(title='AUTOMATED ADD DISPATCH REMOVE TEST', text=str(now()), category=1, subcategory=105, full_response=False) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id) + resp = test_auth_nation_BETA.create_dispatch(title='AUTOMATED ADD DISPATCH REMOVE TEST', text=str(now()), category=1, subcategory=105, full_response=False) dispatch_id = grab_id(resp.success) - resp = test_auth_nation.remove_dispatch(dispatch_id=dispatch_id, full_response=True) + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=dispatch_id, full_response=True) except Exception as Err: self.fail(Err) @@ -305,7 +323,7 @@ def test_send_rmb(self): from datetime import datetime now = datetime.now try: - test_auth_nation.send_rmb(test_auth_nation.region, 'Circle CI: Automated Test') + test_auth_nation_BETA.send_rmb(test_auth_nation.region, 'Circle CI: Automated Test') except Exception as Err: self.fail(Err) From 5d16598f2e65351423381bb1996a1003a0802de1 Mon Sep 17 00:00:00 2001 From: Josh W <5985422+DolphDev@users.noreply.github.com> Date: Tue, 21 Sep 2021 12:24:37 -0400 Subject: [PATCH 4/6] Update nationstates.rst --- docs/pages/nationstates.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/nationstates.rst b/docs/pages/nationstates.rst index 5811cbe..c56abca 100644 --- a/docs/pages/nationstates.rst +++ b/docs/pages/nationstates.rst @@ -89,4 +89,4 @@ You can view what each endpoint currently supports in it's magic methods by view Is pynationstates thread safe? ============================== -pynationstates does have locks in place that should make it safe to use across threads. However, the author recommends you have independent `nationstates.Nationstates` instances for earch thread. This guarntees everything will work. +Pynationstates is now fully thread safe and will work as is across threads. From dfd65453c389745bdcc7395c69699520956fe982 Mon Sep 17 00:00:00 2001 From: DolphDev Date: Wed, 22 Sep 2021 11:21:20 -0400 Subject: [PATCH 5/6] More Test Additions --- tests/test_call.py | 62 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/tests/test_call.py b/tests/test_call.py index d0e34e9..9260ee0 100644 --- a/tests/test_call.py +++ b/tests/test_call.py @@ -29,7 +29,7 @@ issue_nation_zero = joint_api.nation('pynationstates_0_issues_test_nation', password=PASSWORD) api_threads = ns.Nationstates(USERAGENT, threading_mode=True) fake_nation = joint_api.nation('FAKE NATION 1 FAKE NATION 1 FAKE NATION 1 FAKE NATION 1') - +fake_region = joint_api.region('FAKE REGION 1 FAKE REGION 1 FAKE REGION 1 FAKE REGION 1') def grab_id(newfactbookresponse_text): part1 = newfactbookresponse_text.split('id=') return part1[1].split('">')[0] @@ -57,6 +57,20 @@ def test_nation_call(self): except Exception as Err: self.fail(Err) + def test_nation_region_calls(self): + try: + api = sep_api + mycall = api.nation("testlandia") + myr = mycall.region + myr.nations + api.world().nations + api.world().regions + api.wa('0').nations + api.wa('0').regions + + except Exception as Err: + self.fail(Err) + def test_beta(self): from datetime import datetime now = datetime.now @@ -68,7 +82,7 @@ def test_beta(self): try: test_auth_nation._check_beta() - self.fail(Err) + self.fail('beta flag false') except Exception as Err: pass @@ -136,6 +150,36 @@ def test_cards_decks_call(self): except Exception as Err: self.fail(Err) + def test_cards_decks_call_null(self): + try: + api = sep_api + + mycall = api.cards() + mycall.decks() + + self.fail(Err) + + # mycall.get_shards(choice(mycall.auto_shards)) + # mycall.get_shards(choice(mycall.auto_shards), full_response=True) + except Exception as Err: + pass + + def test_cards_decks_call_both(self): + try: + api = sep_api + + mycall = api.cards() + mycall.decks(nation_name='testlandia', nation_id=1) + + self.fail('fail') + + # mycall.get_shards(choice(mycall.auto_shards)) + # mycall.get_shards(choice(mycall.auto_shards), full_response=True) + except Exception as Err: + pass + + + def test_cards_decksinfo_call(self): try: api = sep_api @@ -179,6 +223,7 @@ def test_cards_collections_call(self): self.fail(Err) + def test_cards_auctions_call(self): try: api = sep_api @@ -254,7 +299,10 @@ def test_private_nation(self): def test_exists(self): assert fake_nation.exists() is False + assert fake_region.exists is False assert test_auth_nation.exists() + assert fake_nation.exists() is False + assert test_auth_nation.region.exists() def test_create_dispatch(self): from datetime import datetime @@ -318,6 +366,16 @@ def test_remove_dispatch(self): except Exception as Err: self.fail(Err) + def test_remove_dispatch(self): + from datetime import datetime + now = datetime.now + try: + resp = test_auth_nation_BETA.remove_dispatch(dispatch_id=None, full_response=True) + self.fail('should of failed') + + except Exception as Err: + pass + def test_send_rmb(self): from datetime import datetime From 60cde94782c5629647224f4323c64b2df1e1e102 Mon Sep 17 00:00:00 2001 From: DolphDev Date: Wed, 22 Sep 2021 11:49:49 -0400 Subject: [PATCH 6/6] testing fixes --- nationstates/objects.py | 9 ++------- tests/test_call.py | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/nationstates/objects.py b/nationstates/objects.py index d772632..952142e 100644 --- a/nationstates/objects.py +++ b/nationstates/objects.py @@ -484,13 +484,8 @@ def _determine_api(self, chamber): @property def nations(self): - resp = self._auto_shard("nations") - return tuple(self.api_mother.nation(x) for x in resp.split(":")) - - @property - def regions(self): - resp = self._auto_shard("regions") - return tuple(self.api_mother.region(x) for x in resp.split(":")) + resp = self._auto_shard("members") + return tuple(self.api_mother.nation(x) for x in resp.split(",")) class Telegram(API_WRAPPER): api_name = TelegramAPI.api_name diff --git a/tests/test_call.py b/tests/test_call.py index 9260ee0..f3371bd 100644 --- a/tests/test_call.py +++ b/tests/test_call.py @@ -66,7 +66,6 @@ def test_nation_region_calls(self): api.world().nations api.world().regions api.wa('0').nations - api.wa('0').regions except Exception as Err: self.fail(Err) @@ -299,7 +298,7 @@ def test_private_nation(self): def test_exists(self): assert fake_nation.exists() is False - assert fake_region.exists is False + assert fake_region.exists() is False assert test_auth_nation.exists() assert fake_nation.exists() is False assert test_auth_nation.region.exists()