예제 #1
0
    def test_parameter_processing(self, session, Account):
        account = Account(balance=(Currency('USD'), 15))

        session.add(account)
        session.commit()

        account = session.query(Account).first()
        assert account.balance.currency == Currency('USD')
        assert account.balance.amount == 15
예제 #2
0
    def test_parameter_processing(self, session, type_, Account):
        account = Account(balances=[
            type_.type_cls(Currency('USD'), 15),
            type_.type_cls(Currency('AUD'), 20)
        ])

        session.add(account)
        session.commit()

        account = session.query(Account).first()
        assert account.balances[0].currency == Currency('USD')
        assert account.balances[0].amount == 15
        assert account.balances[1].currency == Currency('AUD')
        assert account.balances[1].amount == 20
예제 #3
0
    def test_parameter_processing(self, session, User, set_get_locale):
        user = User(currency=Currency('USD'))

        session.add(user)
        session.commit()

        user = session.query(User).first()
        assert user.currency.name == u'US Dollar'
예제 #4
0
def valid_currency(form, field):
    from sqlalchemy_utils import Currency
    try:
        Currency(field.data)
    except (TypeError, ValueError):
        raise ValidationError(
            field.gettext(
                u'Not a valid ISO currency code (e.g. USD, EUR, CNY).'))
예제 #5
0
    def test_dict_input(self, session, type_, Account):
        account = Account(balances=[{
            'currency': Currency('USD'),
            'amount': 15
        }, {
            'currency': Currency('AUD'),
            'amount': 20
        }])

        session.add(account)
        session.commit()

        account = session.query(Account).first()
        assert account.balances[0].currency == Currency('USD')
        assert account.balances[0].amount == 15
        assert account.balances[1].currency == Currency('AUD')
        assert account.balances[1].amount == 20
예제 #6
0
    def test_dict_input(self, session, Account):
        account = Account(balance={'currency': Currency('USD'), 'amount': 15})

        session.add(account)
        session.commit()

        account = session.query(Account).first()
        assert account.balance.currency == 'USD'
        assert account.balance.amount == 15
예제 #7
0
    def test_result_set_processing(self):
        account = self.Account(balance=('USD', 15))

        self.session.add(account)
        self.session.commit()

        account = self.session.query(self.Account).first()
        assert account.balance.currency == Currency('USD')
        assert account.balance.amount == 15
예제 #8
0
    def test_parameter_processing(self):
        user = self.User(
            currency=Currency('USD')
        )

        self.session.add(user)
        self.session.commit()

        user = self.session.query(self.User).first()
        assert user.currency.name == u'US Dollar'
예제 #9
0
 def test_symbol_property(self, code, symbol):
     assert Currency(code).symbol == symbol
예제 #10
0
 def test_name_property(self, code, name):
     assert Currency(code).name == name
예제 #11
0
 def test_invalid_currency_code_type(self):
     with raises(TypeError):
         Currency(None)
예제 #12
0
 def test_invalid_currency_code(self):
     with raises(ValueError):
         Currency('Unknown code')
예제 #13
0
    def __parse_2021_auction_soup(self, soup, auction_id):
        def get_embedded_image_urls():
            imgs = soup.find_all('img', attrs= \
                {'class' : re.compile('Thumbnail__StyledThumbnailImage')})
            urls = []
            for i in imgs:
                urllist = i['src'].split('.')
                urllist[-1] = 'jpg'
                urls.append('.'.join(urllist))
            return urls

        json = self.__extract_data_json(soup)

        item = json['item']['byId'][str(auction_id)]
        item_detail = json['itemDetail']['byId'][str(auction_id)]
        bidding_info = json['biddingInfo']['byId'][str(auction_id)]
        catalog = json['catalog']['byId'][str(item['catalogId'])]

        # Extract additional auctioneer info
        seller_id = item['sellerId']
        seller = json['seller']['byId'][str(seller_id)]
        auctioneer = seller['name']
        location = self.__address_from_seller(seller)

        image_urls = ' '.join(get_embedded_image_urls())

        # Construct the auction object
        auction = LiveAuctioneersAuction(id=str(auction_id))
        try:
            auction.title = item['title']
        except KeyError:
            pass
        except ValueError:
            print('auction {} received title {} of invalid type {}' \
                .format(auction_id, item['title'], \
                    type(item['title'])))

        try:
            auction.description = self._normalise_text(
                item_detail['description'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received description {} of invalid type {}' \
                .format(auction_id, item_detail['description'], \
                    type(item_detail['description'])))

        try:
            isostring = item['publishDate']
            # datetime's ISO 8601 parser doesn't understand 'Z' at the end for UTC,
            # so rewrite it into an easier variant
            if isostring[-1] == 'Z':
                auction.start_time = datetime.fromisoformat(isostring[:-1] +
                                                            '+00:00')
            else:
                raise KeyError
        except KeyError:
            pass
        except TypeError:
            print('auction {} received start_time {} of invalid type {}' \
                .format(auction_id, isostring, \
                    type(isostring)))

        try:
            auction.end_time = datetime.utcfromtimestamp(
                catalog['saleStartTs'])
        except KeyError:
            pass
        except TypeError:
            print('auction {} received end_time {} of invalid type {}' \
                .format(auction_id, catalog['saleStartTs'], \
                    type(catalog['saleStartTs'])))

        try:
            auction.n_bids = int(bidding_info['bidCount'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received n_bids {} of invalid type {}' \
                .format(auction_id, bidding_info['bidCount'], \
                    type(bidding_info['bidCount'])))

        auction.currency = Currency('USD')
        try:
            auction.latest_price = float(bidding_info['salePrice'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received latest_price {} of invalid type {}' \
                .format(auction_id, bidding_info['salePrice'], \
                    type(bidding_info['salePrice'])))

        try:
            auction.starting_price = float(item['startPrice'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received starting_price {} of invalid type {}' \
                .format(auction_id, item['startPrice'], \
                    type(item['startPrice'])))

        auction.location = location

        try:
            auction.lot_number = int(re.sub('[^0-9]', '', item['lotNumber']))
        except KeyError:
            pass
        except ValueError:
            print('auction {} received lotNumber {} of invalid type {}' \
                .format(auction_id, item['lotNumber'], \
                    type(item['lotNumber'])))

        auction.image_urls = image_urls
        try:
            auction.condition = item_detail['conditionReport']
        except KeyError:
            pass
        except ValueError:
            print('auction {} received condition {} of invalid type {}' \
                .format(auction_id, item_detail['conditionReport'], \
                    type(item_detail['conditionReport'])))

        try:
            auction.high_bid_estimate = float(item['highBidEstimate'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received high_bid_estimate {} of invalid type {}' \
                .format(auction_id, item['highBidEstimate'], \
                    type(item['highBidEstimate'])))

        try:
            auction.low_bid_estimate = float(item['lowBidEstimate'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received low_bid_estimate {} of invalid type {}' \
                .format(auction_id, item['lowBidEstimate'], \
                    type(item['lowBidEstimate'])))

        try:
            auction.seller_id = str(seller_id)
        except KeyError:
            pass

        return auction
예제 #14
0
 def test_representation(self):
     currency = Currency('USD')
     assert repr(currency) == "Currency('USD')"
예제 #15
0
 def test_unicode(self):
     currency = Currency('USD')
     assert six.text_type(currency) == u'USD'
예제 #16
0
 def test_equality_operator(self):
     assert Currency('USD') == 'USD'
     assert 'USD' == Currency('USD')
     assert Currency('USD') == Currency('USD')
예제 #17
0
 def test_non_equality_operator(self):
     assert Currency('USD') != 'EUR'
     assert not (Currency('USD') != 'USD')
예제 #18
0
 def test_init(self):
     assert Currency('USD') == Currency(Currency('USD'))
예제 #19
0
 def test_str(self):
     currency = Currency('USD')
     assert str(currency) == 'USD'
예제 #20
0
 def test_hashability(self):
     assert len(set([Currency('USD'), Currency('USD')])) == 1
예제 #21
0
    def __parse_2020_auction_soup(self, soup, duplicates):
        def get_embedded_json():
            # Strip c from s, without exception
            def strip(s, c):
                if isinstance(s, str):
                    return s.strip(c)
                return s

            div = soup.find('div', id='JSDF')
            scripts = div.find_all('script', src=None)

            # Look for $rwidgets
            script_texts = []
            for script in scripts:
                for s in script.contents:
                    if '$rwidgets' in s:
                        script_texts.append(s)

            # Bodge until we get rid of slimit
            with silence_output():
                parser = Parser()

            raw_values = {}
            for script_text in script_texts:
                tree = parser.parse(script_text)
                # Parsing js
                for node in nodevisitor.visit(tree):
                    if isinstance(node, ast.FunctionCall):
                        if isinstance(node.identifier, ast.Identifier):
                            if node.identifier.value == '$rwidgets':
                                # Deal with here
                                fields = {}
                                for n in nodevisitor.visit(node):
                                    if isinstance(n, ast.Assign):
                                        k = getattr(n.left, 'value',
                                                    '').strip('"')
                                        v = strip(
                                            getattr(n.right, 'value', ''), '"')
                                        if k in duplicates:
                                            try:
                                                fields[k].append(v)
                                            except KeyError:
                                                fields[k] = [v]
                                        else:
                                            fields[k] = v

                                # Merge fields and raw_values, resolving duplicates
                                for (k, v) in fields.items():
                                    if k in duplicates:
                                        try:
                                            raw_values[k] += v
                                        except KeyError:
                                            raw_values[k] = v
                                    elif v != 'null':
                                        raw_values[k] = v
            return raw_values

        def get_image_urls(raw_values):
            # TODO: sometimes only displayImgUrl is given, when the s-l600 image exists
            # Example: https://www.ebay.com/itm/Chubby-Blob-Seal-Plush-Toy-Animal-Cute-Ocean-Pillow-Pet-Stuffed-Doll-Kids-Gift/362995774962
            # Example: https://i.ebayimg.com/images/g/6NkAAOSwkEFd50Kb/s-l600.jpg
            raw_image_urls = []
            if 'maxImageUrl' in raw_values.keys():
                if 'displayImgUrl' in raw_values.keys():
                    for max_image, disp_image in zip( \
                            self.__get_dict_value(raw_values, 'maxImageUrl'), \
                            self.__get_dict_value(raw_values, 'displayImgUrl')):
                        if max_image == 'null':
                            if disp_image != 'null':
                                raw_image_urls.append(disp_image)
                        else:
                            raw_image_urls.append(max_image)
                else:
                    raw_image_urls = self.__get_dict_value(
                        raw_values, 'maxImageUrl')
            else:
                if 'displayImgUrl' in raw_values.keys():
                    raw_image_urls = self.__get_dict_value(
                        raw_values, 'displayImgUrl')

            def f(url):
                return json.loads('"{}"'.format(url))

            return list(map(f, raw_image_urls))

        # Get raw values, validating API assumptions
        raw_values = get_embedded_json()
        #pdb.set_trace()
        try:
            raw_values['it']
        except KeyError:
            try:
                raw_values['kw']
            except KeyError:
                # No title field available in API.  Obtain it from the page instead
                for c in soup.find('h1', id='itemTitle').contents:
                    if isinstance(c, str):
                        title_key = c
                        break
            else:
                title_key = 'kw'
        else:
            title_key = 'it'

        try:
            if raw_values['entityId'] != raw_values['entityName']:
                print(
                    f'notify author: entityid==entityname assumption incorrect for domain {url}'
                )
        except KeyError:
            print(
                'notify author: entityid or entityname does not exist for auction {}, for domain {}.'
                .format(raw_values['itemId'], url))

        # Extract additional info
        image_urls = get_image_urls(raw_values)
        desc_div = soup.find('div', attrs={'id': 'desc_div'})
        if desc_div is not None:
            iframe = desc_div.find('iframe')
        else:
            iframe = soup.find('div', attrs={'class': 'vi_descsnpt_holder'})
        desc = iframe.text

        # Construct the auction object
        auction = EbayAuction(id=int(raw_values['itemId']))

        try:
            auction.title = unicodedata.normalize("NFKD",
                                                  raw_values[title_key])
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received title {} of invalid type {}' \
                .format(auction_id, raw_values[title_key], \
                    type(raw_values[title_key])))

        try:
            auction.description = self._normalise_text(desc)
        except ValueError:
            print('auction {} received description {} of invalid type {}' \
                .format(auction_id, desc, \
                    type(desc)))

        try:
            auction.seller_id = str(raw_values['entityName'])
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received seller_id {} of invalid type {}' \
                .format(auction_id, raw_values['entityName'], \
                    type(raw_values['entityName'])))

        try:
            auction.start_time = datetime.utcfromtimestamp( \
                int(raw_values['startTime'])/1000)
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received start_time {} of invalid type {}' \
                .format(auction_id, raw_values['startTime'], \
                    type(raw_values['startTime'])))

        try:
            auction.end_time = datetime.utcfromtimestamp( \
                int(raw_values['endTime'])/1000)
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received end_time {} of invalid type {}' \
                .format(auction_id, raw_values['endTime'], \
                    type(raw_values['endTime'])))

        try:
            auction.n_bids = int(raw_values['bids'])
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received n_bids {} of invalid type {}' \
                .format(auction_id, raw_values['bids'], \
                    type(raw_values['bids'])))

        try:
            auction.currency = Currency(raw_values['ccode'])
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received currency {} of invalid type {}' \
                .format(auction_id, raw_values['ccode'], \
                    type(raw_values['ccode'])))

        try:
            auction.latest_price = str(float(raw_values['bidPriceDouble']))
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received latest_price {} of invalid type {}' \
                .format(auction_id, raw_values['bidPriceDouble'], \
                    type(raw_values['bidPriceDouble'])))

        try:
            auction.buy_now_price = str(float(raw_values['binPriceDouble']))
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received buy_now_price {} of invalid type {}' \
                .format(auction_id, raw_values['binPriceDouble'], \
                    type(raw_values['binPriceDouble'])))

        # TODO: add starting price, winner, location
        auction.image_urls = ' '.join(image_urls)

        try:
            auction.locale = str(raw_values['locale'])
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received locale {} of invalid type {}' \
                .format(auction_id, raw_values['locale'], \
                    type(raw_values['locale'])))

        try:
            auction.quantity = int(raw_values['totalQty'])
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received quantity {} of invalid type {}' \
                .format(auction_id, raw_values['quantity'], \
                    type(raw_values['quantity'])))

        try:
            auction.video_url = str(raw_values['videoUrl'])
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received video_url {} of invalid type {}' \
                .format(auction_id, raw_values['videoUrl'], \
                    type(raw_values['videoUrl'])))

        try:
            if str(raw_values['vatIncluded']) == 'true':
                auction.vat_included = True
            elif str(raw_values['vatIncluded']) == 'false':
                auction.vat_included = False
            else:
                print('auction {} received vat_included {} of invalid type {}' \
                    .format(auction_id, raw_values['vatIncluded'], \
                        type(raw_values['vatIncluded'])))
        except (KeyError, TypeError):
            pass

        try:
            auction.domain = raw_values['currentDomain']
        except (KeyError, TypeError):
            pass
        except ValueError:
            print('auction {} received domain {} of invalid type {}' \
                .format(auction_id, raw_values['currentDomain'], \
                    type(raw_values['currentDomain'])))

        return auction
예제 #22
0
    def __parse_2020_auction_soup(self, soup, auction_id):
        def get_embedded_json():
            jsonsect = self.__searcher(soup, \
                '<script data-reactroot="">', '</script>')

            # Bodge until we get rid of slimit
            with silence_output():
                parser = Parser()

            tree = parser.parse(jsonsect)
            j = 0
            element = {}
            for node in nodevisitor.visit(tree):
                try:
                    if isinstance(node, ast.Assign):
                        if node.left.value == '"' + str(auction_id) + '"':
                            for i in node.right.children():
                                leftp = i.left.value[1:-1]
                                rightp = i.right.value
                                element[leftp] = self.__quote_cleaner(rightp)
                except:
                    pass

            return element

        def get_embedded_image_urls():
            divs = soup.find_all('div', attrs= \
                {'class' : re.compile('thumbnail-container')})
            urls = []
            for i in divs:
                urllist = i.find('img')['src'].split('.')
                urllist[-1] = 'jpg'
                urls.append('.'.join(urllist))
            return urls

        element = get_embedded_json()

        # Extract additional auctioneer info
        div = soup.find('div', attrs={'class': re.compile('auctioneerInfo')})
        auctioneer = self.__quote_cleaner( \
            div.find('h3', attrs= {'class' : re.compile('sellerName')}).text)
        location = self.__quote_cleaner( \
            div.find('div', attrs={'class' : re.compile('address')}).text)
        image_urls = ' '.join(get_embedded_image_urls())

        # Construct the auction object
        auction = LiveAuctioneersAuction(id=str(auction_id))
        try:
            auction.title = element['title']
        except KeyError:
            pass
        except ValueError:
            print('auction {} received title {} of invalid type {}' \
                .format(auction_id, element['title'], \
                    type(element['title'])))

        try:
            auction.description = self._normalise_text(element['description'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received description {} of invalid type {}' \
                .format(auction_id, element['description'], \
                    type(element['description'])))

        try:
            auction.start_time = datetime.utcfromtimestamp( \
                element['availableTs'])
        except KeyError:
            pass
        except TypeError:
            print('auction {} received start_time {} of invalid type {}' \
                .format(auction_id, element['availableTs'], \
                    type(element['availableTs'])))

        try:
            auction.end_time = datetime.utcfromtimestamp( \
                element['saleStartTs'])
        except KeyError:
            pass
        except TypeError:
            print('auction {} received end_time {} of invalid type {}' \
                .format(auction_id, element['saleStartTs'], \
                    type(element['saleStartTs'])))

        try:
            auction.n_bids = int(element['bidCount'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received n_bids {} of invalid type {}' \
                .format(auction_id, element['bidCount'], \
                    type(element['bidCount'])))

        auction.currency = Currency('USD')
        try:
            auction.latest_price = float(element['salePrice'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received latest_price {} of invalid type {}' \
                .format(auction_id, element['salePrice'], \
                    type(element['salePrice'])))

        try:
            auction.starting_price = float(element['startPrice'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received starting_price {} of invalid type {}' \
                .format(auction_id, element['startPrice'], \
                    type(element['startPrice'])))

        auction.location = location

        try:
            auction.lot_number = int(re.sub('[^0-9]', '',
                                            element['lotNumber']))
        except KeyError:
            pass
        except ValueError:
            print('auction {} received lotNumber {} of invalid type {}' \
                .format(auction_id, element['lotNumber'], \
                    type(element['lotNumber'])))

        auction.image_urls = image_urls
        try:
            auction.condition = str(element['conditionReport'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received condition {} of invalid type {}' \
                .format(auction_id, element['conditionReport'], \
                    type(element['conditionReport'])))

        try:
            auction.high_bid_estimate = float(element['highBidEstimate'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received high_bid_estimate {} of invalid type {}' \
                .format(auction_id, element['highBidEstimate'], \
                    type(element['highBidEstimate'])))

        try:
            auction.low_bid_estimate = float(element['lowBidEstimate'])
        except KeyError:
            pass
        except ValueError:
            print('auction {} received low_bid_estimate {} of invalid type {}' \
                .format(auction_id, element['lowBidEstimate'], \
                    type(element['lowBidEstimate'])))

        try:
            auction.seller_id = str(element['sellerId'])
        except KeyError:
            pass

        return auction