예제 #1
0
    def __init__(self, config=None):

        # Setup Logging
        self.logger = logging.getLogger(__name__)
        formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        fh = logging.handlers.RotatingFileHandler(f"log_pymkm.log",
                                                  maxBytes=500000,
                                                  backupCount=2)
        fh.setLevel(logging.WARNING)
        fh.setFormatter(formatter)
        self.logger.addHandler(fh)
        sh = logging.StreamHandler()
        sh.setLevel(logging.ERROR)  # This gets outputted to stdout
        sh.setFormatter(formatter)
        self.logger.addHandler(sh)

        self.logger.debug(">> Loading config file")
        try:
            with open("config.json", "r") as config_file:
                self.config = json.load(config_file)
        except FileNotFoundError:
            self.logger.error(
                "You must copy config_template.json to config.json and populate the fields."
            )
            sys.exit(0)

        fh.setLevel(self.config["log_level"])
        self.logger.setLevel(self.config["log_level"])
        self.api = PyMkmApi(config=self.config)
        print("Fetching Cardmarket account data...")
        self.account = self.get_account_data()
        self.wantlists = self.api.get_wantslists()
예제 #2
0
파일: tests.py 프로젝트: jbspeakr/pymkm
    def test_file_not_found2(self):
        open_name = '%s.open' % __name__
        with patch("builtins.open", mock_open(read_data="data")) as mocked_open:
            mocked_open.side_effect = FileNotFoundError

            # Assert that an error is logged
            with self.assertRaises(SystemExit):
                with self.assertLogs(level='ERROR') as cm:
                    PyMkmApi()
                    log_record_level = cm.records[0].levelname
                    self.assertEqual(log_record_level, 'ERROR')
예제 #3
0
    def __init__(self, config=None):
        if (config == None):
            logging.debug(">> Loading config file")
            try:
                self.config = json.load(open('config.json'))
            except FileNotFoundError:
                logging.error(
                    "You must copy config_template.json to config.json and populate the fields.")
                sys.exit(0)
        else:
            self.config = config

        self.api = PyMkmApi(config=self.config)
예제 #4
0
    def setUp(self):
        super(TestPyMkmApiCalls, self).setUp()

        self.api = PyMkmApi(self.config)
예제 #5
0
class TestPyMkmApiCalls(TestCommon):

    api = None

    def setUp(self):
        super(TestPyMkmApiCalls, self).setUp()

        self.api = PyMkmApi(self.config)

    def test_file_not_found2(self):
        open_name = '%s.open' % __name__
        with patch("builtins.open",
                   mock_open(read_data="data")) as mocked_open:
            mocked_open.side_effect = FileNotFoundError

            # Assert that an error is logged
            with self.assertRaises(SystemExit):
                with self.assertLogs(level='ERROR') as cm:
                    PyMkmApi()
                    log_record_level = cm.records[0].levelname
                    self.assertEqual(log_record_level, 'ERROR')

    def test_get_account(self):
        mock_oauth = Mock(spec=OAuth1Session)

        mock_oauth.get = MagicMock(
            return_value=self.MockResponse("test", 200, 'testing ok'))
        self.assertEqual(self.api.get_account(mock_oauth), "test")
        mock_oauth.get.assert_called()

        mock_oauth.get = MagicMock(
            return_value=self.MockResponse("", 401, 'Unauthorized'))
        with self.assertLogs(level='ERROR') as cm:
            self.api.get_account(mock_oauth)
            self.assertGreater(len(cm.records), 0)

    def test_get_stock(self):
        articles_response = "{{'article': {}}}".format(
            TestCommon.fake_articles_result).replace("'", '"')
        articles_response_json = json.loads(articles_response)
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(return_value=self.MockResponse(
            articles_response_json, 200, 'testing ok'))
        self.assertEqual(
            self.api.get_stock(None, mock_oauth)[0]['comments'], "x")

    def test_get_games(self):
        test_json = json.loads('{"test": "test"}')
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(
            return_value=self.MockResponse(test_json, 200, 'testing ok'))
        self.assertEqual(self.api.get_games(mock_oauth), test_json)

    def test_get_expansions(self):
        test_json = json.loads('{"test": "test"}')
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(
            return_value=self.MockResponse(test_json, 200, 'testing ok'))
        game_id = 1
        self.assertEqual(self.api.get_expansions(game_id, mock_oauth),
                         test_json)

    def test_get_cards_in_expansion(self):
        test_json = json.loads('{"test": "test"}')
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(
            return_value=self.MockResponse(test_json, 200, 'testing ok'))
        expansion_id = 1
        self.assertEqual(
            self.api.get_cards_in_expansion(expansion_id, mock_oauth),
            test_json)

    def test_get_product(self):
        test_json = json.loads('{"test": "test"}')
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(
            return_value=self.MockResponse(test_json, 200, 'testing ok'))
        product_id = 1
        self.assertEqual(self.api.get_product(product_id, mock_oauth),
                         test_json)

    def test_find_product(self):
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(return_value=self.MockResponse(
            TestCommon.fake_product, 200, 'testing ok'))
        search_string = 'test'
        result = self.api.find_product(search_string, mock_oauth)
        self.assertEqual(result, TestCommon.fake_product)

    def test_find_stock_article(self):
        articles_response = "{{'article': {}}}".format(
            TestCommon.fake_articles_result).replace("'", '"')
        articles_response_json = json.loads(articles_response)
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(return_value=self.MockResponse(
            articles_response_json, 200, 'testing ok'))
        name = 'test'
        game_id = 1
        result = self.api.find_stock_article(name, game_id, mock_oauth)
        self.assertEqual(result[0]['comments'], "x")

    def test_get_articles_in_shoppingcarts(self):
        test_json = json.loads('{"test": "test"}')
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(
            return_value=self.MockResponse(test_json, 200, 'testing ok'))

        self.assertEqual(self.api.get_articles_in_shoppingcarts(mock_oauth),
                         test_json)

    def test_get_articles(self):
        articles_response = "{{'article': {}}}".format(
            TestCommon.fake_articles_result).replace("'", '"')
        articles_response_json = json.loads(articles_response)

        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(return_value=self.MockResponse(
            articles_response_json, 200, 'testing ok'))
        product_id = 1

        result = self.api.get_articles(product_id, 0, mock_oauth)
        self.assertEqual(result[0]['comments'], "x")

        mock_oauth.get = MagicMock(return_value=self.MockResponse(
            articles_response_json, 206, 'partial content'))
        product_id = 1

        result = self.api.get_articles(product_id, 0, mock_oauth)
        self.assertEqual(result[0]['comments'], "x")

    def test_find_user_articles(self):
        articles_response = "{{'article': {}}}".format(
            TestCommon.fake_articles_result).replace("'", '"')
        articles_response_json = json.loads(articles_response)

        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.get = MagicMock(return_value=self.MockResponse(
            articles_response_json, 200, 'testing ok'))
        user_id = 1
        game_id = 1

        result = self.api.find_user_articles(user_id, game_id, 0, mock_oauth)
        self.assertEqual(result[0]['comments'], "x")

        mock_oauth.get = MagicMock(return_value=self.MockResponse(
            articles_response_json, 206, 'partial content'))

        result = self.api.find_user_articles(user_id, game_id, 0, mock_oauth)
        self.assertEqual(result[0]['comments'], "x")

    def test_set_vacation_status(self):
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.put = MagicMock(return_value=self.MockResponse(
            TestCommon.fake_account_data, 200, 'testing ok'))
        vacation_status = True

        result = self.api.set_vacation_status(vacation_status, mock_oauth)
        self.assertEqual(result['message'],
                         'Successfully set the account on vacation.')
        self.assertEqual(result['account']['onVacation'],
                         str(vacation_status).lower())

    def test_set_display_language(self):
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.put = MagicMock(return_value=self.MockResponse(
            TestCommon.fake_account_data, 200, 'testing ok'))
        display_language = 1

        result = self.api.set_display_language(display_language, mock_oauth)
        self.assertEqual(result['account']['idDisplayLanguage'],
                         str(display_language).lower())

    def test_add_stock(self):
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.post = MagicMock(return_value=self.MockResponse(
            TestCommon.fake_stock, 200, 'testing ok'))

        result = self.api.add_stock(TestCommon.fake_stock, mock_oauth)
        self.assertEqual(len(result), 3)

    def test_set_stock(self):
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.put = MagicMock(return_value=self.MockResponse(
            TestCommon.fake_stock, 200, 'testing ok'))

        result = self.api.set_stock(TestCommon.fake_stock, mock_oauth)
        self.assertEqual(len(result), 3)

    def test_delete_stock(self):
        mock_oauth = Mock(spec=OAuth1Session)
        mock_oauth.delete = MagicMock(return_value=self.MockResponse(
            TestCommon.fake_stock, 200, 'testing ok'))

        result = self.api.delete_stock(TestCommon.fake_stock, mock_oauth)
        self.assertEqual(len(result), 3)
예제 #6
0
class BuywizardApp:
    logger = None

    def __init__(self, config=None):

        # Setup Logging
        self.logger = logging.getLogger(__name__)
        formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        fh = logging.handlers.RotatingFileHandler(f"log_pymkm.log",
                                                  maxBytes=500000,
                                                  backupCount=2)
        fh.setLevel(logging.WARNING)
        fh.setFormatter(formatter)
        self.logger.addHandler(fh)
        sh = logging.StreamHandler()
        sh.setLevel(logging.ERROR)  # This gets outputted to stdout
        sh.setFormatter(formatter)
        self.logger.addHandler(sh)

        self.logger.debug(">> Loading config file")
        try:
            with open("config.json", "r") as config_file:
                self.config = json.load(config_file)
        except FileNotFoundError:
            self.logger.error(
                "You must copy config_template.json to config.json and populate the fields."
            )
            sys.exit(0)

        fh.setLevel(self.config["log_level"])
        self.logger.setLevel(self.config["log_level"])
        self.api = PyMkmApi(config=self.config)
        print("Fetching Cardmarket account data...")
        self.account = self.get_account_data()
        self.wantlists = self.api.get_wantslists()

    def start(self, args=None):

        print(
            f"\nLogged in as: {self.account['name']['firstName']} {self.account['name']['lastName']} ({self.account['username']})"
        )

        # print("\nWhich wantlist would you like to optimize?\n")
        # for i, list in enumerate(self.wantlists):
        #     print(f"\t[{i}]: {list['name']} ({list['itemCount']} cards)")
        # choice = int(input("\nEnter your choice: "))
        # os.system("clear")
        #
        # self.optimize_wantlist(choice)

        self.optimize_wantlist(0)

    def get_account_data(self):
        return self.api.get_account()["account"]

    def async_get_retry(self, item_type, item_id_list, **kwargs):
        print(f"Async fetching: {item_type}")

        ret_list = [None] * len(item_id_list)
        to_find = item_id_list.copy()

        round = 1
        while len([x for x in ret_list if x is not None]) < len(item_id_list):
            print(f"Fetch round {round}: {len(to_find)} items left")
            round += 1
            results = self.api.get_items_async(item_type=item_type,
                                               item_id_list=to_find,
                                               **kwargs)

            for ind in range(len(ret_list)):
                if (ret_list[ind] is None) and (len(results) > 0):
                    ret_list[ind] = results.pop(0)
                    if ret_list[ind] is not None:
                        to_find.pop(0)

        return ret_list

    def get_wantlist_data(self, wantlist_id):
        want_items = self.api.get_wantslist_items(
            self.wantlists[wantlist_id]['idWantsList']).get('item')

        products = [x for x in want_items if x['type'] == 'product']
        metaprod_wants = [x for x in want_items if x['type'] == 'metaproduct']

        metaproducts = self.async_get_retry(
            "metaproducts", [x['idMetaproduct'] for x in metaprod_wants])

        product_ids = [prod['idProduct'] for prod in products]

        for metaprod in metaproducts:
            for prod in metaprod['product']:
                product_ids.append(prod['idProduct'])

        articles = self.async_get_retry("articles", product_ids,
                                        **self.config['search_filters'])

        # Filter down to countries
        for i in range(len(articles)):
            for j, item in reversed(list(enumerate(articles[i]['article']))):
                if item['seller']['address']['country'] not in self.config[
                        'search_filters']['countries']:
                    del articles[i]['article'][j]

        # Output formatting
        prod_to_metaprod = {}
        for metaprod in metaproducts:
            for prod in metaprod['product']:
                prod_to_metaprod[prod['idProduct']] = prod['idMetaproduct']

        lod = []
        for ind, prod_id in enumerate(product_ids):
            seller_prices = {
                art['seller']['idUser']: art['price']
                for art in articles[ind]['article']
            }
            lod.append({"prod_id": prod_id, **seller_prices})
            if prod_id in prod_to_metaprod.keys():
                lod[-1]['metaprod_id'] = prod_to_metaprod[prod_id]

        # TODO: Create article_id dataframe (for translation back to article_id list)
        price_df = pd.DataFrame(lod).set_index(['metaprod_id',
                                                'prod_id']).fillna(np.inf)

        zero_rows, *_ = np.where((price_df < np.inf).sum(axis=1) == 0)
        if len(zero_rows) > 0:
            print(
                f"There were {len(zero_rows)} cards with 0 sellers matching your search preferences."
                f"We are removing:")
        price_df = price_df[~((price_df < np.inf).sum(axis=1) == 0)]

        return price_df

    def optimize_wantlist(self, wantlist_id):

        # TODO Filter items out using wantlist preferences
        price_df = self.get_wantlist_data(wantlist_id)

        pass
예제 #7
0
파일: pymkm_app.py 프로젝트: jbspeakr/pymkm
 def __init__(self, config=None):
     self.api = PyMkmApi(config=config)