Page MenuHomePhabricator

TestWikibaseMakeClaim.test_Coordinate_edit() of wikibase_edit_tests fails with missing required field "precision"
Open, HighPublic

Description

__________________ TestWikibaseMakeClaim.test_Coordinate_edit __________________

func = <function WikibasePage.addClaim at 0x7f04aa9ab9e0>
self = ItemPage('Q68')
args = (Claim.fromJSON(DataSite("test", "wikidata"), {'mainsnak': {'snaktype': 'value', 'property': 'P20480', 'datatype': 'gl...type': 'globecoordinate'}}, 'type': 'statement', 'id': 'Q68$d8450805-71d2-4cbf-9421-22da1b43656a', 'rank': 'normal'}),)
kwargs = {}, do_async = False, callback = None
err = APIError("modification-failed", "Missing required field "precision"", {'param': 'action=wbsetclaim&claim=%7B%22mainsna...postorius/lists/mediawiki-api-announce.lists.wikimedia.org/&gt; for notice of API deprecations and breaking changes.'})
link = '[[wikidata:test:Q68]]'

    def handle(func, self, *args, **kwargs):
        do_async = kwargs.pop('asynchronous', False)
        callback = kwargs.pop('callback', None)
        err = None
        try:
>           func(self, *args, **kwargs)

pywikibot/page/_decorators.py:32: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pywikibot/page/_wikibase.py:905: in addClaim
    self.repo.addClaim(self, claim, bot=bot, **kwargs)
pywikibot/site/_decorators.py:93: in callee
    return fn(self, *args, **kwargs)
pywikibot/site/_datasite.py:353: in addClaim
    data = req.submit()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = pywikibot.data.api._requests.Request<wikidata:test->'/w/api.php?action=wbsetclaim&claim={"mainsnak":+{"snaktype":+"val...k":+"normal"}&baserevid=671327&bot=&assert=user&maxlag=5&format=json&token=4ff9ea4506dfdd5ae729db08bcadaa1e66693ab1+\'>

    def submit(self) -> dict:
        """Submit a query and parse the response.
    
        .. versionchanged:: 8.0.4
           in addition to *readapidenied* also try to login when API
           response is *notloggedin*.
        .. versionchanged:: 9.0
           Raise :exc:`exceptions.APIError` if the same error comes
           twice in a row within the loop.
    
        :return: a dict containing data retrieved from api.php
        """
        self._add_defaults()
        use_get = self._use_get()
        retries = 0
        self.last_error = dict.fromkeys(['code', 'info'])
        while True:
            paramstring = self._http_param_string()
    
            simulate = self._simulate(self.action)
            if simulate:
                return simulate
    
            if self.throttle:
                self.site.throttle(write=self.write)
            else:
                pywikibot.log(
                    f"Submitting unthrottled action '{self.action}'.")
    
            use_get, uri, body, headers = self._get_request_params(use_get,
                                                                   paramstring)
            response, use_get = self._http_request(use_get, uri, body, headers,
                                                   paramstring)
            if response is None:
                continue
    
            result = self._json_loads(response)
            if result is None:
                continue
    
            if self._userinfo_query(result):
                continue
    
            if self._handle_warnings(result):
                continue
    
            if 'error' not in result:
                return result
    
            error = result['error']
            for key in result:
                if key in ('error', 'warnings'):
                    continue
                assert key not in error
                error[key] = result[key]
    
            if '*' in error:
                # help text returned
                error['help'] = error.pop('*')
            code = error.setdefault('code', 'Unknown')
            info = error.setdefault('info', None)
    
            if (code == self.last_error['code']
                    and info == self.last_error['info']):
                raise pywikibot.exceptions.APIError(**self.last_error)
            self.last_error = error
    
            if not self._logged_in(code):
                continue
    
            if code == 'maxlag':
                retries += 1
                if retries > max(5, pywikibot.config.max_retries):
                    break
                pywikibot.log('Pausing due to database lag: ' + info)
    
                try:
                    lag = error['lag']
                except KeyError:
                    lag = lagpattern.search(info)
                    lag = float(lag['lag']) if lag else 0.0
    
                self.site.throttle.lag(lag * retries)
                # reset last error
                self.last_error = dict.fromkeys(['code', 'info'])
                continue
    
            if code == 'help' and self.action == 'help':
                # The help module returns an error result with the complete
                # API information. As this data was requested, return the
                # data instead of raising an exception.
                return {'help': {'mime': 'text/plain',
                                 'help': error['help']}}
    
            pywikibot.warning(f'API error {code}: {info}')
            pywikibot.log(f'           headers=\n{response.headers}')
    
            if self._internal_api_error(code, error.copy(), result):
                continue
    
            # Phab. tickets T48535, T64126, T68494, T68619
            if code == 'failed-save' \
               and self._is_wikibase_error_retryable(error):
                self.wait()
                continue
    
            if code == 'ratelimited':
                self._ratelimited()
                continue
    
            # If notloggedin or readapidenied is returned try to login
            if code in ('notloggedin', 'readapidenied') \
               and self.site._loginstatus in (LoginStatus.NOT_ATTEMPTED,
                                              LoginStatus.NOT_LOGGED_IN):
                self.site.login()
                continue
    
            if self._bad_token(code):
                continue
    
            if 'mwoauth-invalid-authorization' in code:
                msg = f'OAuth authentication for {self.site}: {info}'
                if 'Nonce already used' in info:
                    pywikibot.error(f'Retrying failed {msg}')
                    continue
                raise NoUsernameError(f'Failed {msg}')
    
            if code == 'cirrussearch-too-busy-error':  # T170647
                self.wait()
                continue
    
            if code in ('search-title-disabled', 'search-text-disabled'):
                prefix = 'gsr' if 'gsrsearch' in self._params else 'sr'
                del self._params[prefix + 'what']
                # use intitle: search instead
                if code == 'search-title-disabled' \
                   and self.site.has_extension('CirrusSearch'):
                    key = prefix + 'search'
                    self._params[key] = ['intitle:' + search
                                         for search in self._params[key]]
                continue
    
            if code == 'urlshortener-blocked':  # T244062
                # add additional informations to error dict
                error['current site'] = self.site
                if self.site.user():
                    error['current user'] = self.site.user()
                else:  # not logged in; show the IP
                    uinfo = self.site.userinfo
                    error['current user'] = uinfo['name']
    
            # raise error
            try:
                param_repr = str(self._params)
                pywikibot.log(
                    f'API Error: query=\n{pprint.pformat(param_repr)}')
                pywikibot.log(f'           response=\n{result}')
    
                args = {'param': body} if body else {}
                args.update(error)
>               raise pywikibot.exceptions.APIError(**args)
E               pywikibot.exceptions.APIError: modification-failed: Missing required field "precision"
E               [param: action=wbsetclaim&claim=%7B%22mainsnak%22%3A+%7B%22snaktype%22%3A+%22value%22%2C+%22property%22%3A+%22P20480%22%2C+%22datatype%22%3A+%22globe-coordinate%22%2C+%22datavalue%22%3A+%7B%22value%22%3A+%7B%22latitude%22%3A+12.0%2C+%22longitude%22%3A+13.0%2C+%22altitude%22%3A+null%2C+%22globe%22%3A+%22http%3A%2F%2Ftest.wikidata.org%2Fentity%2FQ68%22%2C+%22precision%22%3A+null%7D%2C+%22type%22%3A+%22globecoordinate%22%7D%7D%2C+%22type%22%3A+%22statement%22%2C+%22id%22%3A+%22Q68%24d8450805-71d2-4cbf-9421-22da1b43656a%22%2C+%22rank%22%3A+%22normal%22%7D&baserevid=671327&bot=&assert=user&maxlag=5&format=json&token=4ff9ea4506dfdd5ae729db08bcadaa1e66693ab1%2B%5C;
E                messages: [{'name': 'wikibase-validator-missing-field', 'parameters': ['precision'], 'html': {'*': 'Missing required field "precision"'}}];
E                servedby: mw-api-ext.eqiad.main-778c97d8cb-cj5pw;
E                help: See https://test.wikidata.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at &lt;https://lists.wikimedia.org/postorius/lists/mediawiki-api-announce.lists.wikimedia.org/&gt; for notice of API deprecations and breaking changes.]

pywikibot/data/api/_requests.py:1122: APIError

During handling of the above exception, another exception occurred:

self = <tests.wikibase_edit_tests.TestWikibaseMakeClaim testMethod=test_Coordinate_edit>

    def test_Coordinate_edit(self):
        """Attempt adding a Coordinate with globe set via item."""
        testsite = self.get_repo()
        item = self._clean_item(testsite, 'P20480')
    
        # Make sure the wiki supports wikibase-conceptbaseuri
        if testsite.mw_version < '1.29.0-wmf.2':
            self.skipTest('Wiki version must be 1.29.0-wmf.2 or newer to '
                          'support unbound uncertainties.')
    
        # set new claim
        claim = pywikibot.page.Claim(testsite, 'P20480',
                                     datatype='globe-coordinate')
        target = pywikibot.Coordinate(site=testsite, lat=12.0, lon=13.0,
                                      globe_item=item)
        claim.setTarget(target)
>       item.addClaim(claim)

tests/wikibase_edit_tests.py:310: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pywikibot/page/_decorators.py:52: in wrapper
    handle(func, self, *args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

func = <function WikibasePage.addClaim at 0x7f04aa9ab9e0>
self = ItemPage('Q68')
args = (Claim.fromJSON(DataSite("test", "wikidata"), {'mainsnak': {'snaktype': 'value', 'property': 'P20480', 'datatype': 'gl...type': 'globecoordinate'}}, 'type': 'statement', 'id': 'Q68$d8450805-71d2-4cbf-9421-22da1b43656a', 'rank': 'normal'}),)
kwargs = {}, do_async = False, callback = None
err = APIError("modification-failed", "Missing required field "precision"", {'param': 'action=wbsetclaim&claim=%7B%22mainsna...postorius/lists/mediawiki-api-announce.lists.wikimedia.org/&gt; for notice of API deprecations and breaking changes.'})
link = '[[wikidata:test:Q68]]'

    def handle(func, self, *args, **kwargs):
        do_async = kwargs.pop('asynchronous', False)
        callback = kwargs.pop('callback', None)
        err = None
        try:
            func(self, *args, **kwargs)
        # TODO: other "expected" error types to catch?
        except Error as edit_err:
            err = edit_err  # edit_err will be deleted in the end of the scope
            link = self.title(as_link=True)
            if do_async:
                pywikibot.error(f'page {link} not saved due to {err}\n')
            pywikibot.log(f'Error saving page {link} ({err})\n',
                          exc_info=True)
            if not callback and not do_async:
                if isinstance(err, PageSaveRelatedError):
                    raise err
>               raise OtherPageSaveError(self, err)
E               pywikibot.exceptions.OtherPageSaveError: Edit to page [[wikidata:test:Q68]] failed:
E               modification-failed: Missing required field "precision"
E               [param: action=wbsetclaim&claim=%7B%22mainsnak%22%3A+%7B%22snaktype%22%3A+%22value%22%2C+%22property%22%3A+%22P20480%22%2C+%22datatype%22%3A+%22globe-coordinate%22%2C+%22datavalue%22%3A+%7B%22value%22%3A+%7B%22latitude%22%3A+12.0%2C+%22longitude%22%3A+13.0%2C+%22altitude%22%3A+null%2C+%22globe%22%3A+%22http%3A%2F%2Ftest.wikidata.org%2Fentity%2FQ68%22%2C+%22precision%22%3A+null%7D%2C+%22type%22%3A+%22globecoordinate%22%7D%7D%2C+%22type%22%3A+%22statement%22%2C+%22id%22%3A+%22Q68%24d8450805-71d2-4cbf-9421-22da1b43656a%22%2C+%22rank%22%3A+%22normal%22%7D&baserevid=671327&bot=&assert=user&maxlag=5&format=json&token=4ff9ea4506dfdd5ae729db08bcadaa1e66693ab1%2B%5C;
E                messages: [{'name': 'wikibase-validator-missing-field', 'parameters': ['precision'], 'html': {'*': 'Missing required field "precision"'}}];
E                servedby: mw-api-ext.eqiad.main-778c97d8cb-cj5pw;
E                help: See https://test.wikidata.org/w/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at &lt;https://lists.wikimedia.org/postorius/lists/mediawiki-api-announce.lists.wikimedia.org/&gt; for notice of API deprecations and breaking changes.]

pywikibot/page/_decorators.py:44: OtherPageSaveError